├── .cursorrules ├── .gitignore ├── LICENSE ├── README-zh.md ├── README.md ├── admin ├── .editorconfig ├── .env ├── .gitattributes ├── .gitignore ├── .prettierrc.json ├── README.md ├── env.d.ts ├── eslint.config.ts ├── index.html ├── package-lock.json ├── package.json ├── public │ └── favicon.ico ├── src │ ├── App.vue │ ├── assets │ │ ├── base.css │ │ ├── logo.svg │ │ └── main.css │ ├── components │ │ ├── HelloWorld.vue │ │ ├── SideBar.vue │ │ ├── TheWelcome.vue │ │ ├── WelcomeItem.vue │ │ └── icons │ │ │ ├── IconCommunity.vue │ │ │ ├── IconDocumentation.vue │ │ │ ├── IconEcosystem.vue │ │ │ ├── IconSupport.vue │ │ │ └── IconTooling.vue │ ├── composables │ │ └── useCharts.ts │ ├── layouts │ │ └── AdminLayout.vue │ ├── main.ts │ ├── router │ │ └── index.ts │ ├── services │ │ └── api.ts │ ├── stores │ │ └── counter.ts │ ├── types │ │ └── index.ts │ ├── utils │ │ └── date.ts │ └── views │ │ ├── AboutView.vue │ │ ├── DashboardView.vue │ │ ├── FeedbackView.vue │ │ ├── HomeView.vue │ │ └── StatsView.vue ├── ssl │ ├── cert.pem │ └── key.pem ├── start.sh ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── certs ├── cert.pem └── key.pem ├── client ├── .gitignore ├── README.md ├── copy-pdf-worker.js ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── ai-logo.svg │ ├── error-placeholder.svg │ ├── pdf │ │ ├── cmaps │ │ │ ├── 78-EUC-H.bcmap │ │ │ ├── 78-EUC-V.bcmap │ │ │ ├── 78-H.bcmap │ │ │ ├── 78-RKSJ-H.bcmap │ │ │ ├── 78-RKSJ-V.bcmap │ │ │ ├── 78-V.bcmap │ │ │ ├── 78ms-RKSJ-H.bcmap │ │ │ ├── 78ms-RKSJ-V.bcmap │ │ │ ├── 83pv-RKSJ-H.bcmap │ │ │ ├── 90ms-RKSJ-H.bcmap │ │ │ ├── 90ms-RKSJ-V.bcmap │ │ │ ├── 90msp-RKSJ-H.bcmap │ │ │ ├── 90msp-RKSJ-V.bcmap │ │ │ ├── 90pv-RKSJ-H.bcmap │ │ │ ├── 90pv-RKSJ-V.bcmap │ │ │ ├── Add-H.bcmap │ │ │ ├── Add-RKSJ-H.bcmap │ │ │ ├── Add-RKSJ-V.bcmap │ │ │ ├── Add-V.bcmap │ │ │ ├── Adobe-CNS1-0.bcmap │ │ │ ├── Adobe-CNS1-1.bcmap │ │ │ ├── Adobe-CNS1-2.bcmap │ │ │ ├── Adobe-CNS1-3.bcmap │ │ │ ├── Adobe-CNS1-4.bcmap │ │ │ ├── Adobe-CNS1-5.bcmap │ │ │ ├── Adobe-CNS1-6.bcmap │ │ │ ├── Adobe-CNS1-UCS2.bcmap │ │ │ ├── Adobe-GB1-0.bcmap │ │ │ ├── Adobe-GB1-1.bcmap │ │ │ ├── Adobe-GB1-2.bcmap │ │ │ ├── Adobe-GB1-3.bcmap │ │ │ ├── Adobe-GB1-4.bcmap │ │ │ ├── Adobe-GB1-5.bcmap │ │ │ ├── Adobe-GB1-UCS2.bcmap │ │ │ ├── Adobe-Japan1-0.bcmap │ │ │ ├── Adobe-Japan1-1.bcmap │ │ │ ├── Adobe-Japan1-2.bcmap │ │ │ ├── Adobe-Japan1-3.bcmap │ │ │ ├── Adobe-Japan1-4.bcmap │ │ │ ├── Adobe-Japan1-5.bcmap │ │ │ ├── Adobe-Japan1-6.bcmap │ │ │ ├── Adobe-Japan1-UCS2.bcmap │ │ │ ├── Adobe-Korea1-0.bcmap │ │ │ ├── Adobe-Korea1-1.bcmap │ │ │ ├── Adobe-Korea1-2.bcmap │ │ │ ├── Adobe-Korea1-UCS2.bcmap │ │ │ ├── B5-H.bcmap │ │ │ ├── B5-V.bcmap │ │ │ ├── B5pc-H.bcmap │ │ │ ├── B5pc-V.bcmap │ │ │ ├── CNS-EUC-H.bcmap │ │ │ ├── CNS-EUC-V.bcmap │ │ │ ├── CNS1-H.bcmap │ │ │ ├── CNS1-V.bcmap │ │ │ ├── CNS2-H.bcmap │ │ │ ├── CNS2-V.bcmap │ │ │ ├── ETHK-B5-H.bcmap │ │ │ ├── ETHK-B5-V.bcmap │ │ │ ├── ETen-B5-H.bcmap │ │ │ ├── ETen-B5-V.bcmap │ │ │ ├── ETenms-B5-H.bcmap │ │ │ ├── ETenms-B5-V.bcmap │ │ │ ├── EUC-H.bcmap │ │ │ ├── EUC-V.bcmap │ │ │ ├── Ext-H.bcmap │ │ │ ├── Ext-RKSJ-H.bcmap │ │ │ ├── Ext-RKSJ-V.bcmap │ │ │ ├── Ext-V.bcmap │ │ │ ├── GB-EUC-H.bcmap │ │ │ ├── GB-EUC-V.bcmap │ │ │ ├── GB-H.bcmap │ │ │ ├── GB-V.bcmap │ │ │ ├── GBK-EUC-H.bcmap │ │ │ ├── GBK-EUC-V.bcmap │ │ │ ├── GBK2K-H.bcmap │ │ │ ├── GBK2K-V.bcmap │ │ │ ├── GBKp-EUC-H.bcmap │ │ │ ├── GBKp-EUC-V.bcmap │ │ │ ├── GBT-EUC-H.bcmap │ │ │ ├── GBT-EUC-V.bcmap │ │ │ ├── GBT-H.bcmap │ │ │ ├── GBT-V.bcmap │ │ │ ├── GBTpc-EUC-H.bcmap │ │ │ ├── GBTpc-EUC-V.bcmap │ │ │ ├── GBpc-EUC-H.bcmap │ │ │ ├── GBpc-EUC-V.bcmap │ │ │ ├── H.bcmap │ │ │ ├── HKdla-B5-H.bcmap │ │ │ ├── HKdla-B5-V.bcmap │ │ │ ├── HKdlb-B5-H.bcmap │ │ │ ├── HKdlb-B5-V.bcmap │ │ │ ├── HKgccs-B5-H.bcmap │ │ │ ├── HKgccs-B5-V.bcmap │ │ │ ├── HKm314-B5-H.bcmap │ │ │ ├── HKm314-B5-V.bcmap │ │ │ ├── HKm471-B5-H.bcmap │ │ │ ├── HKm471-B5-V.bcmap │ │ │ ├── HKscs-B5-H.bcmap │ │ │ ├── HKscs-B5-V.bcmap │ │ │ ├── Hankaku.bcmap │ │ │ ├── Hiragana.bcmap │ │ │ ├── KSC-EUC-H.bcmap │ │ │ ├── KSC-EUC-V.bcmap │ │ │ ├── KSC-H.bcmap │ │ │ ├── KSC-Johab-H.bcmap │ │ │ ├── KSC-Johab-V.bcmap │ │ │ ├── KSC-V.bcmap │ │ │ ├── KSCms-UHC-H.bcmap │ │ │ ├── KSCms-UHC-HW-H.bcmap │ │ │ ├── KSCms-UHC-HW-V.bcmap │ │ │ ├── KSCms-UHC-V.bcmap │ │ │ ├── KSCpc-EUC-H.bcmap │ │ │ ├── KSCpc-EUC-V.bcmap │ │ │ ├── Katakana.bcmap │ │ │ ├── LICENSE │ │ │ ├── NWP-H.bcmap │ │ │ ├── NWP-V.bcmap │ │ │ ├── RKSJ-H.bcmap │ │ │ ├── RKSJ-V.bcmap │ │ │ ├── Roman.bcmap │ │ │ ├── UniCNS-UCS2-H.bcmap │ │ │ ├── UniCNS-UCS2-V.bcmap │ │ │ ├── UniCNS-UTF16-H.bcmap │ │ │ ├── UniCNS-UTF16-V.bcmap │ │ │ ├── UniCNS-UTF32-H.bcmap │ │ │ ├── UniCNS-UTF32-V.bcmap │ │ │ ├── UniCNS-UTF8-H.bcmap │ │ │ ├── UniCNS-UTF8-V.bcmap │ │ │ ├── UniGB-UCS2-H.bcmap │ │ │ ├── UniGB-UCS2-V.bcmap │ │ │ ├── UniGB-UTF16-H.bcmap │ │ │ ├── UniGB-UTF16-V.bcmap │ │ │ ├── UniGB-UTF32-H.bcmap │ │ │ ├── UniGB-UTF32-V.bcmap │ │ │ ├── UniGB-UTF8-H.bcmap │ │ │ ├── UniGB-UTF8-V.bcmap │ │ │ ├── UniJIS-UCS2-H.bcmap │ │ │ ├── UniJIS-UCS2-HW-H.bcmap │ │ │ ├── UniJIS-UCS2-HW-V.bcmap │ │ │ ├── UniJIS-UCS2-V.bcmap │ │ │ ├── UniJIS-UTF16-H.bcmap │ │ │ ├── UniJIS-UTF16-V.bcmap │ │ │ ├── UniJIS-UTF32-H.bcmap │ │ │ ├── UniJIS-UTF32-V.bcmap │ │ │ ├── UniJIS-UTF8-H.bcmap │ │ │ ├── UniJIS-UTF8-V.bcmap │ │ │ ├── UniJIS2004-UTF16-H.bcmap │ │ │ ├── UniJIS2004-UTF16-V.bcmap │ │ │ ├── UniJIS2004-UTF32-H.bcmap │ │ │ ├── UniJIS2004-UTF32-V.bcmap │ │ │ ├── UniJIS2004-UTF8-H.bcmap │ │ │ ├── UniJIS2004-UTF8-V.bcmap │ │ │ ├── UniJISPro-UCS2-HW-V.bcmap │ │ │ ├── UniJISPro-UCS2-V.bcmap │ │ │ ├── UniJISPro-UTF8-V.bcmap │ │ │ ├── UniJISX0213-UTF32-H.bcmap │ │ │ ├── UniJISX0213-UTF32-V.bcmap │ │ │ ├── UniJISX02132004-UTF32-H.bcmap │ │ │ ├── UniJISX02132004-UTF32-V.bcmap │ │ │ ├── UniKS-UCS2-H.bcmap │ │ │ ├── UniKS-UCS2-V.bcmap │ │ │ ├── UniKS-UTF16-H.bcmap │ │ │ ├── UniKS-UTF16-V.bcmap │ │ │ ├── UniKS-UTF32-H.bcmap │ │ │ ├── UniKS-UTF32-V.bcmap │ │ │ ├── UniKS-UTF8-H.bcmap │ │ │ ├── UniKS-UTF8-V.bcmap │ │ │ ├── V.bcmap │ │ │ └── WP-Symbol.bcmap │ │ ├── pdf.worker.min.js │ │ └── pdf.worker.min.mjs │ ├── pdfium │ │ ├── pdfium.js │ │ └── pdfium.wasm │ └── vite.svg ├── src │ ├── App.vue │ ├── assets │ │ ├── ai-logo.svg │ │ └── vue.svg │ ├── components │ │ ├── DocTree.vue │ │ ├── DocView.vue │ │ ├── HelloWorld.vue │ │ ├── ImmersiveReader.vue │ │ ├── MarkdownViewer.vue │ │ ├── MobileNav.vue │ │ ├── NavBar.vue │ │ ├── PDFViewer.vue │ │ ├── ReadingControls.vue │ │ ├── RecentDocs.vue │ │ ├── SearchBar.vue │ │ ├── TreeNode.vue │ │ ├── announcement │ │ │ ├── AnnouncementBoard.vue │ │ │ ├── AnnouncementButton.vue │ │ │ ├── FeedbackForm.vue │ │ │ ├── RecommendationsPanel.vue │ │ │ └── UpdatesPanel.vue │ │ └── icons │ │ │ └── index.js │ ├── composables │ │ └── useDebounce.ts │ ├── main.ts │ ├── router │ │ └── index.ts │ ├── services │ │ └── api.ts │ ├── stores │ │ ├── announcement.ts │ │ ├── doc.ts │ │ ├── reading.ts │ │ ├── search.ts │ │ └── theme.ts │ ├── style.css │ ├── styles │ │ ├── immersive.css │ │ └── immersive.scss │ ├── utils │ │ └── markdown.ts │ ├── views │ │ ├── AdminDashboard.vue │ │ ├── DocView.vue │ │ ├── HomeView.vue │ │ └── SearchView.vue │ └── vite-env.d.ts ├── ssl │ ├── cert.pem │ └── key.pem ├── stats.html ├── tailwind.config.js ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json ├── vite.config.ts ├── yarn.lock └── 图书网站UI.html ├── dark-mode.png ├── deploy.sh ├── docker-compose.yml ├── env.md ├── home.png ├── install_meilisearch_windows.md ├── meilisearch.md ├── mode.png ├── requirements.txt ├── responsive.png ├── search.png ├── server ├── app │ ├── __init__.py │ ├── main.py │ ├── routers │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── announcements.py │ │ ├── docs.py │ │ ├── feedback.py │ │ └── search.py │ └── services │ │ ├── __init__.py │ │ ├── announcement_service.py │ │ ├── doc_service.py │ │ ├── meilisearch_service.py │ │ ├── search_service.py │ │ └── stats_service.py ├── build_index.py ├── cert.pem ├── data │ ├── feedback.json │ ├── popular_docs.json │ ├── recommendations.json │ ├── stats.json │ ├── updates.json │ └── visits.json ├── key.pem ├── logs.txt ├── package-lock.json ├── requirements.txt ├── run_h2.py ├── ssl │ ├── cert.pem │ └── key.pem ├── start_with_meilisearch.sh ├── static │ └── stats │ │ ├── popular_docs.json │ │ ├── stats.json │ │ └── visits.json ├── test_meili.py └── 软链.md ├── start_services.ps1 └── tools ├── categorize_articles.py ├── clean_empty_courses.py ├── detect_duplicates.py ├── fix_image_paths.py ├── llm_api.py ├── search_engine.py ├── smart_categorize.py ├── split_articles.py └── web_scraper.py /.gitignore: -------------------------------------------------------------------------------- 1 | # 输出目录 2 | downloaded_content/ 3 | 4 | # 日志文件 5 | *.log 6 | 7 | # 爬虫文件 8 | scraper.py 9 | 10 | # Python 相关 11 | __pycache__/ 12 | *.py[cod] 13 | *$py.class 14 | *.so 15 | .Python 16 | env/ 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | .eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | wheels/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | 33 | # 虚拟环境 34 | venv/ 35 | py310/ 36 | ENV/ 37 | 38 | # IDE 相关 39 | .idea/ 40 | .vscode/ 41 | *.swp 42 | *.swo 43 | .DS_Store 44 | 45 | # 临时文件 46 | *.tmp 47 | *.bak 48 | *.swp 49 | *~ 50 | 51 | # 系统文件 52 | .DS_Store 53 | Thumbs.db 54 | 55 | # Docs 相关 56 | docs/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 AI Library 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README-zh.md: -------------------------------------------------------------------------------- 1 | # AI Library 2 | 3 | [![English](https://img.shields.io/badge/English-Click-blue)](README.md) 4 | [![中文文档](https://img.shields.io/badge/中文文档-当前-orange)](README-zh.md) 5 | 6 | AI Library 是一个由ai开发的现代化的文档管理系统,专注于提供优雅的阅读体验和高效的知识管理。 7 | 8 | ## ✨ 功能展示 9 | 10 | 11 | ### 📱 响应式布局 12 | ![响应式布局](responsive.png) 13 | 完美适配桌面端和移动端,提供一致的阅读体验。 14 | 15 | ### 🌓 深色模式 16 | ![深色模式](dark-mode.png) 17 | 自动跟随系统切换,保护你的眼睛。支持浅色、深色和护眼模式。 18 | 19 | ### 沉浸护眼模式 20 | ![深色模式](dmode.png) 21 | 进入深度阅读模式,排除一切干扰,自动隐藏设置栏,护眼模式低饱和暖色 22 | 23 | ### 🔍 实时搜索 24 | ![实时搜索](search.png) 25 | 快速定位文档,支持标题和内容搜索。 26 | 27 | ## 功能特点 28 | 29 | ### 阅读体验 30 | - 沉浸式阅读模式 31 | - 智能隐藏非必要UI元素 32 | - 自动调整内容宽度和留白 33 | - 支持键盘快捷操作 34 | - 阅读进度实时显示 35 | - 章节导航保持显示 36 | - 支持自动滚动 37 | - 多主题支持 38 | - 浅色主题 39 | - 深色主题 40 | - 护眼模式 41 | - 阅读设置 42 | - 字体大小调节 43 | - 行高调整 44 | - 段落间距设置 45 | - 页面宽度控制 46 | - 大屏优化 47 | - 支持24-40寸显示器自适应 48 | - 智能分栏布局 49 | - 图片优化显示 50 | 51 | ### 文档管理 52 | - 支持多种文档格式 53 | - Markdown 文档 54 | - PDF 文件 55 | - 树形目录结构 56 | - 文档实时搜索 57 | - 最近访问记录 58 | - 阅读位置记忆 59 | - 阅读时长统计 60 | 61 | ### 用户体验 62 | - 响应式设计 63 | - 多主题支持 64 | - 优雅的动画过渡 65 | - 手势操作支持 66 | - 快捷键支持 67 | 68 | ### 特性 69 | - HTTP/2 支持 70 | - 高性能后端 API 71 | - 实时搜索引擎 72 | - 缓存优化 73 | 74 | ## 技术栈 75 | 76 | ### 前端 77 | - Vue 3 (Composition API) 78 | - TypeScript 79 | - Tailwind CSS 80 | - Vite 81 | - Pinia 状态管理 82 | - Vue Router 83 | 84 | ### 后端 85 | - FastAPI 86 | - Uvicorn (HTTP/2 支持) 87 | - Python 3.10+ 88 | 89 | ### 部署 90 | - HTTPS/HTTP2 91 | - Docker 支持 92 | - Cloudflare Tunnel 93 | 94 | ## 环境要求 95 | 96 | ### 开发环境 97 | - Node.js 16+ 98 | - Python 3.10+ 99 | - pip 100 | - yarn/npm 101 | - Git 102 | 103 | ### 生产环境 104 | - Linux/macOS/Windows 105 | - Docker (可选) 106 | 107 | ## 安装指南 108 | 109 | ### 1. 克隆项目 110 | ```bash 111 | git clone https://github.com/yourusername/ai-library.git 112 | cd ai-library 113 | ``` 114 | 115 | ### 2. 后端设置 116 | ```bash 117 | # 创建 Python 虚拟环境 118 | python -m venv py310 119 | source py310/bin/activate # Linux/macOS 120 | # 或 121 | .\py310\Scripts\activate # Windows 122 | 123 | # 安装依赖 124 | pip install -r requirements.txt 125 | 126 | # 生成 SSL 证书(用于开发环境) 127 | openssl req -x509 -newkey rsa:4096 -keyout server/key.pem -out server/cert.pem -days 365 -nodes 128 | ``` 129 | 130 | ### 3. 前端设置 131 | ```bash 132 | cd client 133 | yarn install # 或 npm install 134 | 135 | # 开发环境配置 136 | cp .env.example .env.local 137 | ``` 138 | 139 | ## 开发指南 140 | 141 | ### 启动开发服务器 142 | 143 | 1. 后端服务器 144 | ```bash 145 | cd server 146 | PYTHONPATH=/path/to/project/server python run.py 147 | ``` 148 | 149 | 2. 前端服务器 150 | ```bash 151 | cd client 152 | yarn dev # 或 npm run dev 153 | ``` 154 | 155 | ### 开发模式 156 | - 后端服务器运行在 https://localhost:8000 157 | - 前端服务器运行在 https://localhost:5173 158 | - API 文档访问地址:https://localhost:8000/docs 159 | 160 | ## API接口 161 | 162 | ### 文档接口 163 | - `GET /api/docs/tree` - 获取文档目录树 164 | - `GET /api/docs/content/{path}` - 获取文档内容 165 | - `GET /api/docs/metadata/{path}` - 获取文档元数据 166 | - `GET /api/docs/recent` - 获取最近访问的文档 167 | - `GET /api/docs/breadcrumb/{path}` - 获取文档面包屑导航 168 | 169 | ### 搜索接口 170 | - `GET /api/search?q={query}` - 搜索文档 171 | - `POST /api/search/rebuild-index` - 重建搜索索引 172 | 173 | ## 项目结构 174 | ``` 175 | . 176 | ├── client/ # 前端代码 177 | │ ├── src/ 178 | │ │ ├── components/ # Vue 组件 179 | │ │ ├── stores/ # Pinia 状态管理 180 | │ │ ├── services/ # API 服务 181 | │ │ └── styles/ # 全局样式 182 | │ └── public/ # 静态资源 183 | ├── server/ # 后端代码 184 | │ ├── app/ # FastAPI 应用 185 | │ │ ├── routers/ # API 路由 186 | │ │ ├── services/ # 业务逻辑 187 | │ │ └── models/ # 数据模型 188 | │ ├── static/ # 静态文件 189 | │ │ └── docs/ # 文档存储 190 | │ └── tests/ # 测试用例 191 | └── docs/ # 文档目录 192 | ``` 193 | 194 | ## 贡献指南 195 | 196 | 1. Fork 项目 197 | 2. 创建功能分支 (`git checkout -b feature/AmazingFeature`) 198 | 3. 提交更改 (`git commit -m 'Add some AmazingFeature'`) 199 | 4. 推送到分支 (`git push origin feature/AmazingFeature`) 200 | 5. 提交 Pull Request 201 | 202 | ## 许可证 203 | 204 | [MIT License](LICENSE) 205 | 206 | ## 联系方式 207 | 208 | - 项目维护者:[LY-GGBOY](li1980303503@gmail.com) 209 | - 项目主页:[GitHub](https://github.com/Ly-GGboy/ai-library) -------------------------------------------------------------------------------- /admin/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}] 2 | charset = utf-8 3 | indent_size = 2 4 | indent_style = space 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | 8 | end_of_line = lf 9 | max_line_length = 100 10 | -------------------------------------------------------------------------------- /admin/.env: -------------------------------------------------------------------------------- 1 | VITE_API_BASE_URL=https://localhost:8000 -------------------------------------------------------------------------------- /admin/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /admin/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | 30 | *.tsbuildinfo 31 | -------------------------------------------------------------------------------- /admin/.prettierrc.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "$schema": "https://json.schemastore.org/prettierrc", 4 | "semi": false, 5 | "singleQuote": true, 6 | "printWidth": 100 7 | } 8 | -------------------------------------------------------------------------------- /admin/README.md: -------------------------------------------------------------------------------- 1 | # AI Library 管理后台 2 | 3 | AI Library 管理后台是一个独立的管理界面,用于管理AI Library的内容、监控用户访问和查看用户反馈。 4 | 5 | ## 功能特性 6 | 7 | - **仪表盘**: 总览网站访问数据、热门文档和用户反馈 8 | - **访问统计**: 查看详细的访问统计和趋势分析 9 | - **用户反馈**: 管理用户提交的反馈和建议 10 | 11 | ## 技术栈 12 | 13 | - **前端框架**: Vue.js 3 + TypeScript 14 | - **UI组件**: 纯CSS自定义组件 15 | - **状态管理**: Vue Composition API 16 | - **HTTP客户端**: Axios 17 | - **构建工具**: Vite 18 | 19 | ## 开发指南 20 | 21 | ### 环境准备 22 | 23 | 确保已安装以下工具: 24 | 25 | - Node.js (v14+) 26 | - npm 或 yarn 27 | 28 | ### 安装依赖 29 | 30 | ```bash 31 | npm install 32 | # 或 33 | yarn 34 | ``` 35 | 36 | ### 启动开发服务器 37 | 38 | ```bash 39 | npm run dev 40 | # 或 41 | yarn dev 42 | ``` 43 | 44 | 或者使用提供的启动脚本: 45 | 46 | ```bash 47 | chmod +x start.sh 48 | ./start.sh 49 | ``` 50 | 51 | ### 构建生产版本 52 | 53 | ```bash 54 | npm run build 55 | # 或 56 | yarn build 57 | ``` 58 | 59 | ## API接口 60 | 61 | 管理后台通过以下API与后端通信: 62 | 63 | - `GET /api/admin/dashboard` - 获取仪表盘数据 64 | - `GET /api/admin/stats` - 获取访问统计数据 65 | - `GET /api/admin/popular-documents` - 获取热门文档 66 | - `GET /api/admin/feedback` - 获取用户反馈 67 | 68 | ## 项目结构 69 | 70 | ``` 71 | admin/ 72 | ├── public/ # 静态资源 73 | ├── src/ 74 | │ ├── assets/ # 项目资源文件 75 | │ ├── components/ # 共享组件 76 | │ ├── router/ # 路由配置 77 | │ ├── services/ # API服务 78 | │ ├── views/ # 页面组件 79 | │ ├── App.vue # 根组件 80 | │ └── main.ts # 入口文件 81 | ├── .env # 环境变量 82 | ├── index.html # HTML模板 83 | ├── package.json # 项目依赖 84 | ├── tsconfig.json # TypeScript配置 85 | ├── vite.config.ts # Vite配置 86 | └── README.md # 项目文档 87 | ``` 88 | 89 | ## 部署指南 90 | 91 | 1. 构建生产版本: 92 | ```bash 93 | npm run build 94 | ``` 95 | 96 | 2. 将 `dist` 目录部署到Web服务器的适当位置 97 | 98 | 3. 确保API服务器正在运行并配置了正确的API基础URL 99 | 100 | ## 许可证 101 | 102 | [MIT License](LICENSE) 103 | -------------------------------------------------------------------------------- /admin/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /admin/eslint.config.ts: -------------------------------------------------------------------------------- 1 | import pluginVue from 'eslint-plugin-vue' 2 | import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript' 3 | import skipFormatting from '@vue/eslint-config-prettier/skip-formatting' 4 | 5 | // To allow more languages other than `ts` in `.vue` files, uncomment the following lines: 6 | // import { configureVueProject } from '@vue/eslint-config-typescript' 7 | // configureVueProject({ scriptLangs: ['ts', 'tsx'] }) 8 | // More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup 9 | 10 | export default defineConfigWithVueTs( 11 | { 12 | name: 'app/files-to-lint', 13 | files: ['**/*.{ts,mts,tsx,vue}'], 14 | }, 15 | 16 | { 17 | name: 'app/files-to-ignore', 18 | ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'], 19 | }, 20 | 21 | pluginVue.configs['flat/essential'], 22 | vueTsConfigs.recommended, 23 | skipFormatting, 24 | ) 25 | -------------------------------------------------------------------------------- /admin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /admin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "admin", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "run-p type-check \"build-only {@}\" --", 9 | "preview": "vite preview", 10 | "build-only": "vite build", 11 | "type-check": "vue-tsc --build", 12 | "lint": "eslint . --fix", 13 | "format": "prettier --write src/" 14 | }, 15 | "dependencies": { 16 | "@headlessui/vue": "^1.7.23", 17 | "@vicons/fluent": "^0.13.0", 18 | "@vicons/ionicons5": "^0.13.0", 19 | "axios": "^1.8.1", 20 | "chart.js": "^4.4.8", 21 | "echarts": "^5.6.0", 22 | "naive-ui": "^2.41.0", 23 | "pinia": "^3.0.1", 24 | "vue": "^3.5.13", 25 | "vue-chartjs": "^5.3.2", 26 | "vue-router": "^4.5.0" 27 | }, 28 | "devDependencies": { 29 | "@tsconfig/node22": "^22.0.0", 30 | "@types/node": "^22.13.4", 31 | "@vitejs/plugin-vue": "^5.2.1", 32 | "@vue/eslint-config-prettier": "^10.2.0", 33 | "@vue/eslint-config-typescript": "^14.4.0", 34 | "@vue/tsconfig": "^0.7.0", 35 | "eslint": "^9.20.1", 36 | "eslint-plugin-vue": "^9.32.0", 37 | "jiti": "^2.4.2", 38 | "npm-run-all2": "^7.0.2", 39 | "prettier": "^3.5.1", 40 | "typescript": "~5.7.3", 41 | "vite": "^6.1.0", 42 | "vite-plugin-vue-devtools": "^7.7.2", 43 | "vue-tsc": "^2.2.2" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /admin/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/admin/public/favicon.ico -------------------------------------------------------------------------------- /admin/src/App.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 15 | 16 | 23 | -------------------------------------------------------------------------------- /admin/src/assets/base.css: -------------------------------------------------------------------------------- 1 | /* color palette from */ 2 | :root { 3 | --vt-c-white: #ffffff; 4 | --vt-c-white-soft: #f8f8f8; 5 | --vt-c-white-mute: #f2f2f2; 6 | 7 | --vt-c-black: #181818; 8 | --vt-c-black-soft: #222222; 9 | --vt-c-black-mute: #282828; 10 | 11 | --vt-c-indigo: #2c3e50; 12 | 13 | --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); 14 | --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); 15 | --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); 16 | --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); 17 | 18 | --vt-c-text-light-1: var(--vt-c-indigo); 19 | --vt-c-text-light-2: rgba(60, 60, 60, 0.66); 20 | --vt-c-text-dark-1: var(--vt-c-white); 21 | --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); 22 | } 23 | 24 | /* semantic color variables for this project */ 25 | :root { 26 | --color-background: var(--vt-c-white); 27 | --color-background-soft: var(--vt-c-white-soft); 28 | --color-background-mute: var(--vt-c-white-mute); 29 | 30 | --color-border: var(--vt-c-divider-light-2); 31 | --color-border-hover: var(--vt-c-divider-light-1); 32 | 33 | --color-heading: var(--vt-c-text-light-1); 34 | --color-text: var(--vt-c-text-light-1); 35 | 36 | --section-gap: 160px; 37 | } 38 | 39 | @media (prefers-color-scheme: dark) { 40 | :root { 41 | --color-background: var(--vt-c-black); 42 | --color-background-soft: var(--vt-c-black-soft); 43 | --color-background-mute: var(--vt-c-black-mute); 44 | 45 | --color-border: var(--vt-c-divider-dark-2); 46 | --color-border-hover: var(--vt-c-divider-dark-1); 47 | 48 | --color-heading: var(--vt-c-text-dark-1); 49 | --color-text: var(--vt-c-text-dark-2); 50 | } 51 | } 52 | 53 | *, 54 | *::before, 55 | *::after { 56 | box-sizing: border-box; 57 | margin: 0; 58 | font-weight: normal; 59 | } 60 | 61 | body { 62 | min-height: 100vh; 63 | color: var(--color-text); 64 | background: var(--color-background); 65 | transition: 66 | color 0.5s, 67 | background-color 0.5s; 68 | line-height: 1.6; 69 | font-family: 70 | Inter, 71 | -apple-system, 72 | BlinkMacSystemFont, 73 | 'Segoe UI', 74 | Roboto, 75 | Oxygen, 76 | Ubuntu, 77 | Cantarell, 78 | 'Fira Sans', 79 | 'Droid Sans', 80 | 'Helvetica Neue', 81 | sans-serif; 82 | font-size: 15px; 83 | text-rendering: optimizeLegibility; 84 | -webkit-font-smoothing: antialiased; 85 | -moz-osx-font-smoothing: grayscale; 86 | } 87 | -------------------------------------------------------------------------------- /admin/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /admin/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | /* 重置默认样式 */ 4 | * { 5 | margin: 0; 6 | padding: 0; 7 | box-sizing: border-box; 8 | } 9 | 10 | #app { 11 | width: 100%; 12 | height: 100vh; 13 | } 14 | 15 | /* 主题变量 */ 16 | :root { 17 | /* 主题色 */ 18 | --primary-color: #18a058; 19 | --info-color: #2080f0; 20 | --success-color: #18a058; 21 | --warning-color: #f0a020; 22 | --error-color: #d03050; 23 | 24 | /* 文字颜色 */ 25 | --text-color-base: #333639; 26 | --text-color-secondary: #666; 27 | --text-color-disabled: #999; 28 | 29 | /* 背景色 */ 30 | --background-color: #f5f7fa; 31 | --background-color-light: #fff; 32 | 33 | /* 边框颜色 */ 34 | --border-color: #eee; 35 | --border-radius: 8px; 36 | 37 | /* 阴影 */ 38 | --box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); 39 | --box-shadow-light: 0 2px 8px 0 rgba(0, 0, 0, 0.06); 40 | } 41 | 42 | /* 全局样式 */ 43 | html, body { 44 | margin: 0; 45 | padding: 0; 46 | width: 100%; 47 | height: 100%; 48 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 49 | 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 50 | 'Noto Color Emoji'; 51 | -webkit-font-smoothing: antialiased; 52 | -moz-osx-font-smoothing: grayscale; 53 | background-color: var(--background-color); 54 | color: var(--text-color-base); 55 | } 56 | 57 | /* 滚动条样式 */ 58 | ::-webkit-scrollbar { 59 | width: 6px; 60 | height: 6px; 61 | } 62 | 63 | ::-webkit-scrollbar-track { 64 | background: transparent; 65 | } 66 | 67 | ::-webkit-scrollbar-thumb { 68 | background: rgba(0, 0, 0, 0.2); 69 | border-radius: 3px; 70 | } 71 | 72 | ::-webkit-scrollbar-thumb:hover { 73 | background: rgba(0, 0, 0, 0.3); 74 | } 75 | 76 | /* 过渡动画 */ 77 | .fade-enter-active, 78 | .fade-leave-active { 79 | transition: opacity 0.3s ease; 80 | } 81 | 82 | .fade-enter-from, 83 | .fade-leave-to { 84 | opacity: 0; 85 | } 86 | 87 | /* 通用布局类 */ 88 | .flex-center { 89 | display: flex; 90 | align-items: center; 91 | justify-content: center; 92 | } 93 | 94 | .flex-between { 95 | display: flex; 96 | align-items: center; 97 | justify-content: space-between; 98 | } 99 | 100 | .flex-column { 101 | display: flex; 102 | flex-direction: column; 103 | } 104 | 105 | /* 间距类 */ 106 | .mt-1 { margin-top: 4px; } 107 | .mt-2 { margin-top: 8px; } 108 | .mt-3 { margin-top: 12px; } 109 | .mt-4 { margin-top: 16px; } 110 | .mt-5 { margin-top: 20px; } 111 | 112 | .mb-1 { margin-bottom: 4px; } 113 | .mb-2 { margin-bottom: 8px; } 114 | .mb-3 { margin-bottom: 12px; } 115 | .mb-4 { margin-bottom: 16px; } 116 | .mb-5 { margin-bottom: 20px; } 117 | 118 | .mr-1 { margin-right: 4px; } 119 | .mr-2 { margin-right: 8px; } 120 | .mr-3 { margin-right: 12px; } 121 | .mr-4 { margin-right: 16px; } 122 | .mr-5 { margin-right: 20px; } 123 | 124 | .ml-1 { margin-left: 4px; } 125 | .ml-2 { margin-left: 8px; } 126 | .ml-3 { margin-left: 12px; } 127 | .ml-4 { margin-left: 16px; } 128 | .ml-5 { margin-left: 20px; } 129 | -------------------------------------------------------------------------------- /admin/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 42 | -------------------------------------------------------------------------------- /admin/src/components/TheWelcome.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 95 | -------------------------------------------------------------------------------- /admin/src/components/WelcomeItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 88 | -------------------------------------------------------------------------------- /admin/src/components/icons/IconCommunity.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /admin/src/components/icons/IconDocumentation.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /admin/src/components/icons/IconEcosystem.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /admin/src/components/icons/IconSupport.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /admin/src/components/icons/IconTooling.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | -------------------------------------------------------------------------------- /admin/src/composables/useCharts.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts' 2 | import type { ChartData } from '@/types' 3 | 4 | let chart: echarts.ECharts | null = null 5 | 6 | export function useCharts() { 7 | const initChart = (elementId: string) => { 8 | const chartElement = document.getElementById(elementId) 9 | if (!chartElement) return 10 | 11 | chart = echarts.init(chartElement) 12 | 13 | // 监听窗口大小变化 14 | window.addEventListener('resize', () => { 15 | chart?.resize() 16 | }) 17 | } 18 | 19 | const updateChart = (data: ChartData) => { 20 | if (!chart) return 21 | 22 | chart.setOption({ 23 | tooltip: { 24 | trigger: 'axis', 25 | axisPointer: { 26 | type: 'shadow' 27 | } 28 | }, 29 | legend: { 30 | data: ['访问量', '独立访客'] 31 | }, 32 | grid: { 33 | left: '3%', 34 | right: '4%', 35 | bottom: '3%', 36 | containLabel: true 37 | }, 38 | xAxis: { 39 | type: 'category', 40 | data: data.dates, 41 | axisLabel: { 42 | rotate: 45 43 | } 44 | }, 45 | yAxis: { 46 | type: 'value' 47 | }, 48 | series: [ 49 | { 50 | name: '访问量', 51 | type: 'line', 52 | smooth: true, 53 | data: data.visits, 54 | itemStyle: { 55 | color: '#18a058' 56 | }, 57 | areaStyle: { 58 | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ 59 | { 60 | offset: 0, 61 | color: 'rgba(24, 160, 88, 0.4)' 62 | }, 63 | { 64 | offset: 1, 65 | color: 'rgba(24, 160, 88, 0.1)' 66 | } 67 | ]) 68 | } 69 | }, 70 | { 71 | name: '独立访客', 72 | type: 'line', 73 | smooth: true, 74 | data: data.visitors, 75 | itemStyle: { 76 | color: '#2080f0' 77 | }, 78 | areaStyle: { 79 | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ 80 | { 81 | offset: 0, 82 | color: 'rgba(32, 128, 240, 0.4)' 83 | }, 84 | { 85 | offset: 1, 86 | color: 'rgba(32, 128, 240, 0.1)' 87 | } 88 | ]) 89 | } 90 | } 91 | ] 92 | }) 93 | } 94 | 95 | const destroyChart = () => { 96 | if (chart) { 97 | chart.dispose() 98 | chart = null 99 | } 100 | window.removeEventListener('resize', () => { 101 | chart?.resize() 102 | }) 103 | } 104 | 105 | return { 106 | initChart, 107 | updateChart, 108 | destroyChart 109 | } 110 | } -------------------------------------------------------------------------------- /admin/src/main.ts: -------------------------------------------------------------------------------- 1 | import './assets/main.css' 2 | 3 | import { createApp } from 'vue' 4 | import { createPinia } from 'pinia' 5 | import { 6 | create, 7 | NButton, 8 | NCard, 9 | NSpace, 10 | NLayout, 11 | NLayoutSider, 12 | NLayoutHeader, 13 | NLayoutContent, 14 | NMenu, 15 | NIcon, 16 | NBreadcrumb, 17 | NBreadcrumbItem, 18 | NAvatar, 19 | NGrid, 20 | NGridItem, 21 | NStatistic, 22 | NSelect, 23 | NDatePicker, 24 | NRadioGroup, 25 | NRadioButton, 26 | NDataTable, 27 | NTag, 28 | NH2, 29 | NText 30 | } from 'naive-ui' 31 | 32 | import App from './App.vue' 33 | import router from './router' 34 | 35 | const naive = create({ 36 | components: [ 37 | NButton, 38 | NCard, 39 | NSpace, 40 | NLayout, 41 | NLayoutSider, 42 | NLayoutHeader, 43 | NLayoutContent, 44 | NMenu, 45 | NIcon, 46 | NBreadcrumb, 47 | NBreadcrumbItem, 48 | NAvatar, 49 | NGrid, 50 | NGridItem, 51 | NStatistic, 52 | NSelect, 53 | NDatePicker, 54 | NRadioGroup, 55 | NRadioButton, 56 | NDataTable, 57 | NTag, 58 | NH2, 59 | NText 60 | ] 61 | }) 62 | 63 | const app = createApp(App) 64 | 65 | app.use(createPinia()) 66 | app.use(router) 67 | app.use(naive) 68 | 69 | app.mount('#app') 70 | -------------------------------------------------------------------------------- /admin/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import AdminLayout from '@/layouts/AdminLayout.vue' 3 | 4 | const router = createRouter({ 5 | history: createWebHistory(import.meta.env.BASE_URL), 6 | routes: [ 7 | { 8 | path: '/admin', 9 | component: AdminLayout, 10 | children: [ 11 | { 12 | path: '', 13 | name: 'dashboard', 14 | component: () => import('@/views/DashboardView.vue') 15 | }, 16 | { 17 | path: 'stats', 18 | name: 'stats', 19 | component: () => import('@/views/StatsView.vue') 20 | }, 21 | { 22 | path: 'feedback', 23 | name: 'feedback', 24 | component: () => import('@/views/FeedbackView.vue') 25 | } 26 | ] 27 | } 28 | ] 29 | }) 30 | 31 | // 路由守卫,用于设置页面标题 32 | router.beforeEach((to, from, next) => { 33 | // 设置页面标题 34 | document.title = to.meta.title as string || 'AI Library 管理后台' 35 | next() 36 | }) 37 | 38 | export default router 39 | -------------------------------------------------------------------------------- /admin/src/services/api.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | // 创建API基础配置 4 | const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'https://localhost:8000' 5 | 6 | // 创建Axios实例 7 | const apiClient = axios.create({ 8 | baseURL: API_BASE_URL, 9 | headers: { 10 | 'Content-Type': 'application/json', 11 | 'Accept': 'application/json' 12 | }, 13 | timeout: 10000, 14 | withCredentials: true // 添加这个配置以支持跨域请求携带cookie 15 | }) 16 | 17 | // 请求拦截器 18 | apiClient.interceptors.request.use( 19 | config => { 20 | // 可以在这里添加身份验证令牌等 21 | return config 22 | }, 23 | error => { 24 | return Promise.reject(error) 25 | } 26 | ) 27 | 28 | // 响应拦截器 29 | apiClient.interceptors.response.use( 30 | response => { 31 | return response 32 | }, 33 | error => { 34 | console.error('API请求错误:', error.response?.data || error.message) 35 | return Promise.reject(error) 36 | } 37 | ) 38 | 39 | // 管理后台API服务 40 | export const adminAPI = { 41 | // 获取仪表盘统计数据 42 | getDashboardData: async () => { 43 | try { 44 | const response = await apiClient.get('/api/admin/dashboard') 45 | return response.data 46 | } catch (error) { 47 | console.error('获取仪表盘数据失败:', error) 48 | throw error 49 | } 50 | }, 51 | 52 | // 获取访问统计数据 53 | getStats: async (timeRange = '7d') => { 54 | try { 55 | const response = await apiClient.get('/api/admin/stats', { 56 | params: { range: timeRange } 57 | }) 58 | return response.data 59 | } catch (error) { 60 | console.error('获取访问统计数据失败:', error) 61 | throw error 62 | } 63 | }, 64 | 65 | // 获取热门文档 66 | getPopularDocuments: async (limit = 10) => { 67 | try { 68 | const response = await apiClient.get('/api/admin/popular-docs', { 69 | params: { limit } 70 | }) 71 | return response.data 72 | } catch (error) { 73 | console.error('获取热门文档失败:', error) 74 | throw error 75 | } 76 | }, 77 | 78 | // 获取用户反馈 79 | getFeedback: async (params = {}) => { 80 | try { 81 | const response = await apiClient.get('/api/admin/feedback', { params }) 82 | return response.data 83 | } catch (error) { 84 | console.error('获取用户反馈失败:', error) 85 | throw error 86 | } 87 | }, 88 | 89 | // 回复用户反馈 90 | replyToFeedback: async (feedbackId: string, replyText: string) => { 91 | try { 92 | const response = await apiClient.post(`/api/admin/feedback/${feedbackId}/reply`, { 93 | reply_text: replyText 94 | }) 95 | return response.data 96 | } catch (error) { 97 | console.error('回复反馈失败:', error) 98 | throw error 99 | } 100 | } 101 | } 102 | 103 | export default apiClient -------------------------------------------------------------------------------- /admin/src/stores/counter.ts: -------------------------------------------------------------------------------- 1 | import { ref, computed } from 'vue' 2 | import { defineStore } from 'pinia' 3 | 4 | export const useCounterStore = defineStore('counter', () => { 5 | const count = ref(0) 6 | const doubleCount = computed(() => count.value * 2) 7 | function increment() { 8 | count.value++ 9 | } 10 | 11 | return { count, doubleCount, increment } 12 | }) 13 | -------------------------------------------------------------------------------- /admin/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export interface DailyStats { 2 | date: string 3 | total_visits: number 4 | unique_visitors: number 5 | avg_duration: number 6 | bounce_rate: number 7 | } 8 | 9 | export interface VisitStats { 10 | total_visits: number 11 | unique_visitors: number 12 | avg_daily_visits: number 13 | bounce_rate: number 14 | daily_data: DailyStats[] 15 | } 16 | 17 | export interface ChartData { 18 | dates: string[] 19 | visits: number[] 20 | visitors: number[] 21 | } -------------------------------------------------------------------------------- /admin/src/utils/date.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 格式化日期字符串为本地时间格式 3 | * @param dateString ISO格式的日期字符串 4 | * @returns 格式化后的日期字符串 5 | */ 6 | export function formatDate(dateString: string): string { 7 | if (!dateString) return '未知时间' 8 | const date = new Date(dateString) 9 | return date.toLocaleString('zh-CN', { 10 | year: 'numeric', 11 | month: '2-digit', 12 | day: '2-digit', 13 | hour: '2-digit', 14 | minute: '2-digit' 15 | }) 16 | } -------------------------------------------------------------------------------- /admin/src/views/AboutView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /admin/src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /admin/ssl/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFCTCCAvGgAwIBAgIUDobUkiV/hI+pVjFaI6kL4P74YtUwDQYJKoZIhvcNAQEL 3 | BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDIyNjE1NDMwMloXDTI2MDIy 4 | NjE1NDMwMlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF 5 | AAOCAg8AMIICCgKCAgEAtdmBYOviegREW7QRnxckKirSW3XykM8JCnlW6DuMWJVQ 6 | OtEnlE35g/C/ElYxV81WV+zpUiH/B5DMTqvM2Qipk+cPUK+kY2jWofbC6GCa2fk6 7 | jTICTxGmFV5seEAUEwRm/yZ1Eb6aoCv/Z8ah/7IAjoDeZU5qKZTF/AqoVpLOjmbn 8 | jRK/ZtrIqR9l8SkrVeK4NhdYnuoU63TdcBI1UNbRKi/Bz+iFVFb6c5JdVhHNntZz 9 | lcnEeezjWalEU2qp8B9x8SeKyDuDRXSRuMwXMpu583MObq97tWez/UBGpUEM5M8o 10 | 5UBX7q+jRjZVdfGQg+WeOfM/IDeT09zNs8a/ZyvN4SVwlToYpy1ca1SR3SGrGwr3 11 | 8MGudtNa5gYh4wwh1XJTg/hZNJgy+f9oJQ34+V0anMmscYG5IavxJjxYfXcFMpy2 12 | 1GwIHml8C5xn0dbn4nX0J1c9BUE5FkFlWvoy0RvT35oM5CilafhAIZRcz+e0cIad 13 | NnU9u10U+HfZgaoNsgnPoQRoXsrcVpOsVoEb2hICz+bUIX3+bICPoaA7gRGxC+2q 14 | 8JhN+hxalojdfdJfOUD6sKH498kGzVOeTstZrQKJxDmOIF/VXBa/yPJEErLJhjhQ 15 | h6RyIERSm3feJU2qO/2Hzl4H+l1iDhVvELYmX7ULmKnN/WntTzu8PkpR6nFDv+cC 16 | AwEAAaNTMFEwHQYDVR0OBBYEFCQISLSS8QIFcTWN3L5/PcRvFR0sMB8GA1UdIwQY 17 | MBaAFCQISLSS8QIFcTWN3L5/PcRvFR0sMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI 18 | hvcNAQELBQADggIBADc1h66VvZ0LVTVxLwhNHNvhdOhpWmNctFhTuvKdWzQgJWOn 19 | 8gUWO4lxbk3kavfIGAM7gCOial0UV46cuDTKwEHBBMBczaBWLH89HUcbtuVldOZO 20 | 1xV4tYKzguUwHs7RqOvPmTykcciymdOjae7ZlVd478qQcgRPaZfzhf+VKptpAQSN 21 | uj4DGl6+BK0SJ3GAP7sieVVz/LfDq7n5E6EK+aN8Bj5a2PJzaVAp25m/hXyqpmFH 22 | UqsN0bk8cfLE/WU50fqiUfbrDpnlhRh79UKCURlBoOcqLSNj5Rw1KW1SGMRzQ9ou 23 | 1KCszTIo7nVmcPMed1YO5eGJw1xLP/cZlM78Jo8KuReyKgjDRDUnD6OoGkPJhE+b 24 | 7cW+q1e4rSvII+Zz6lRGy5htTfITe2jsh74ORKl0secSko6h9xkfBHRQPQa1dhVo 25 | Drd+3ZSaTFkRitMcZn10sRxpFKpD6UyhE0iHT3wJKl0g4+CLvfBp8IKuMA3dEM89 26 | Rm/C3l8hDtuItnWQqo+WX9VaoC52yMCzO2v6UDED88CNbdTFlaLdzEuZsrZMb8AG 27 | C9oF2dMrhMKcP5bueUKyF+Dp9Uy/u3Y0gg5wvddB2SA5y591GHY5ZGwtyaKmqEB/ 28 | rFEUcFP8er7bozX0+CJMgLIaTIPrrI9M/IAK9+yD0rnxXPYYRDmrwXZMiP2J 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /admin/ssl/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | BsENT9oIAn7MfkgmhGB6PbgAJNnm 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /admin/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # AI Library 管理后台启动脚本 3 | 4 | echo "===== 启动 AI Library 管理后台 =====" 5 | echo "确保已安装Node.js和npm..." 6 | 7 | # 检查是否已安装依赖 8 | if [ ! -d "node_modules" ]; then 9 | echo "正在安装依赖..." 10 | npm install 11 | fi 12 | 13 | # 启动开发服务器 14 | echo "启动管理后台开发服务器..." 15 | npm run dev 16 | 17 | # 如果需要构建生产版本 18 | # echo "构建管理后台生产版本..." 19 | # npm run build -------------------------------------------------------------------------------- /admin/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 7 | 8 | "paths": { 9 | "@/*": ["./src/*"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /admin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /admin/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node22/tsconfig.json", 3 | "include": [ 4 | "vite.config.*", 5 | "vitest.config.*", 6 | "cypress.config.*", 7 | "nightwatch.conf.*", 8 | "playwright.config.*", 9 | "eslint.config.*" 10 | ], 11 | "compilerOptions": { 12 | "noEmit": true, 13 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 14 | 15 | "module": "ESNext", 16 | "moduleResolution": "Bundler", 17 | "types": ["node"] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /admin/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | import fs from 'node:fs' 3 | import path from 'node:path' 4 | 5 | import { defineConfig } from 'vite' 6 | import vue from '@vitejs/plugin-vue' 7 | import vueDevTools from 'vite-plugin-vue-devtools' 8 | 9 | // https://vite.dev/config/ 10 | export default defineConfig({ 11 | plugins: [ 12 | vue(), 13 | vueDevTools(), 14 | ], 15 | resolve: { 16 | alias: { 17 | '@': fileURLToPath(new URL('./src', import.meta.url)) 18 | }, 19 | }, 20 | server: { 21 | https: { 22 | key: fs.readFileSync(path.resolve(__dirname, 'ssl/key.pem')), 23 | cert: fs.readFileSync(path.resolve(__dirname, 'ssl/cert.pem')), 24 | }, 25 | port: 5175, 26 | host: '0.0.0.0', 27 | }, 28 | }) 29 | -------------------------------------------------------------------------------- /certs/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /certs/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | B5fnscVWigrrN73w2K1Oh/1eKT0t9Q== 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + TypeScript + Vite 2 | 3 | This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` 67 | 68 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "node copy-pdf-worker.js && vite", 8 | "build": "node copy-pdf-worker.js && vite build", 9 | "build:type-check": "vue-tsc -b && vite build", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@fortawesome/fontawesome-free": "^6.7.2", 14 | "@headlessui/vue": "^1.7.23", 15 | "@heroicons/vue": "^2.2.0", 16 | "@types/lodash-es": "^4.17.12", 17 | "@vueuse/core": "^12.3.0", 18 | "axios": "^1.6.2", 19 | "gsap": "^3.12.7", 20 | "highlight.js": "^11.11.1", 21 | "lodash": "^4.17.21", 22 | "lodash-es": "^4.17.21", 23 | "marked": "^11.0.0", 24 | "pdfium-wasm": "^0.0.2", 25 | "pdfjs-dist": "^3.11.174", 26 | "pinia": "^2.3.0", 27 | "prismjs": "^1.29.0", 28 | "vue": "^3.5.13", 29 | "vue-router": "^4.5.0" 30 | }, 31 | "devDependencies": { 32 | "@tailwindcss/typography": "^0.5.15", 33 | "@types/gsap": "^1.20.2", 34 | "@types/lodash": "^4.17.14", 35 | "@types/markdown-it": "^14.1.2", 36 | "@types/node": "^22.13.10", 37 | "@types/prismjs": "^1.26.5", 38 | "@vitejs/plugin-vue": "^5.2.1", 39 | "@vue/tsconfig": "^0.7.0", 40 | "autoprefixer": "^10.4.20", 41 | "postcss": "^8.4.49", 42 | "rollup-plugin-visualizer": "^5.14.0", 43 | "tailwindcss": "^3.4.17", 44 | "terser": "^5.39.0", 45 | "typescript": "~5.6.2", 46 | "vite": "^6.0.5", 47 | "vite-plugin-compression": "^0.5.1", 48 | "vue-tsc": "^2.2.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /client/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /client/public/ai-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /client/public/error-placeholder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 图片加载失败 6 | 7 | -------------------------------------------------------------------------------- /client/public/pdf/cmaps/78-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/78-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/78-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/78-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/78-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/78-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/78-RKSJ-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/78-RKSJ-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/78-RKSJ-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/78-RKSJ-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/78-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/78-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/78ms-RKSJ-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/78ms-RKSJ-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/78ms-RKSJ-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/78ms-RKSJ-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/83pv-RKSJ-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/83pv-RKSJ-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/90ms-RKSJ-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/90ms-RKSJ-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/90ms-RKSJ-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/90ms-RKSJ-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/90msp-RKSJ-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/90msp-RKSJ-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/90msp-RKSJ-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/90msp-RKSJ-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/90pv-RKSJ-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/90pv-RKSJ-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/90pv-RKSJ-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/90pv-RKSJ-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Add-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Add-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Add-RKSJ-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Add-RKSJ-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Add-RKSJ-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Add-RKSJ-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Add-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Add-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-CNS1-0.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-CNS1-0.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-CNS1-1.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-CNS1-1.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-CNS1-2.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-CNS1-2.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-CNS1-3.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-CNS1-3.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-CNS1-4.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-CNS1-4.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-CNS1-5.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-CNS1-5.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-CNS1-6.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-CNS1-6.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-CNS1-UCS2.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-CNS1-UCS2.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-GB1-0.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-GB1-0.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-GB1-1.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-GB1-1.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-GB1-2.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-GB1-2.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-GB1-3.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-GB1-3.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-GB1-4.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-GB1-4.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-GB1-5.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-GB1-5.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-GB1-UCS2.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-GB1-UCS2.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Japan1-0.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Japan1-0.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Japan1-1.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Japan1-1.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Japan1-2.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Japan1-2.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Japan1-3.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Japan1-3.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Japan1-4.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Japan1-4.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Japan1-5.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Japan1-5.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Japan1-6.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Japan1-6.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Japan1-UCS2.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Japan1-UCS2.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Korea1-0.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Korea1-0.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Korea1-1.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Korea1-1.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Korea1-2.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Korea1-2.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Adobe-Korea1-UCS2.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Adobe-Korea1-UCS2.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/B5pc-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/B5pc-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/B5pc-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/B5pc-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/CNS-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/CNS-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/CNS-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/CNS-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/CNS1-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/CNS1-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/CNS1-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/CNS1-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/CNS2-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/CNS2-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/CNS2-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/CNS2-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/ETHK-B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/ETHK-B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/ETHK-B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/ETHK-B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/ETen-B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/ETen-B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/ETen-B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/ETen-B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/ETenms-B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/ETenms-B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/ETenms-B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/ETenms-B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Ext-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Ext-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Ext-RKSJ-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Ext-RKSJ-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Ext-RKSJ-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Ext-RKSJ-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Ext-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Ext-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GB-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GB-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GB-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GB-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GB-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GB-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GB-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GB-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBK-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBK-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBK-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBK-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBK2K-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBK2K-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBK2K-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBK2K-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBKp-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBKp-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBKp-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBKp-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBT-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBT-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBT-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBT-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBT-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBT-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBT-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBT-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBTpc-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBTpc-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBTpc-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBTpc-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBpc-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBpc-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/GBpc-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/GBpc-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKdla-B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKdla-B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKdla-B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKdla-B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKdlb-B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKdlb-B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKdlb-B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKdlb-B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKgccs-B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKgccs-B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKgccs-B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKgccs-B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKm314-B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKm314-B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKm314-B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKm314-B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKm471-B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKm471-B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKm471-B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKm471-B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKscs-B5-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKscs-B5-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/HKscs-B5-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/HKscs-B5-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Hankaku.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Hankaku.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Hiragana.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Hiragana.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSC-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSC-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSC-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSC-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSC-Johab-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSC-Johab-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSC-Johab-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSC-Johab-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSCms-UHC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSCms-UHC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSCms-UHC-HW-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSCms-UHC-HW-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSCms-UHC-HW-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSCms-UHC-HW-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSCms-UHC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSCms-UHC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSCpc-EUC-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSCpc-EUC-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/KSCpc-EUC-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/KSCpc-EUC-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Katakana.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Katakana.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/LICENSE: -------------------------------------------------------------------------------- 1 | %%Copyright: ----------------------------------------------------------- 2 | %%Copyright: Copyright 1990-2009 Adobe Systems Incorporated. 3 | %%Copyright: All rights reserved. 4 | %%Copyright: 5 | %%Copyright: Redistribution and use in source and binary forms, with or 6 | %%Copyright: without modification, are permitted provided that the 7 | %%Copyright: following conditions are met: 8 | %%Copyright: 9 | %%Copyright: Redistributions of source code must retain the above 10 | %%Copyright: copyright notice, this list of conditions and the following 11 | %%Copyright: disclaimer. 12 | %%Copyright: 13 | %%Copyright: Redistributions in binary form must reproduce the above 14 | %%Copyright: copyright notice, this list of conditions and the following 15 | %%Copyright: disclaimer in the documentation and/or other materials 16 | %%Copyright: provided with the distribution. 17 | %%Copyright: 18 | %%Copyright: Neither the name of Adobe Systems Incorporated nor the names 19 | %%Copyright: of its contributors may be used to endorse or promote 20 | %%Copyright: products derived from this software without specific prior 21 | %%Copyright: written permission. 22 | %%Copyright: 23 | %%Copyright: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 24 | %%Copyright: CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 25 | %%Copyright: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 | %%Copyright: MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | %%Copyright: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 28 | %%Copyright: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | %%Copyright: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 | %%Copyright: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | %%Copyright: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | %%Copyright: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 | %%Copyright: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 34 | %%Copyright: OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35 | %%Copyright: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | %%Copyright: ----------------------------------------------------------- 37 | -------------------------------------------------------------------------------- /client/public/pdf/cmaps/NWP-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/NWP-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/NWP-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/NWP-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/RKSJ-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/RKSJ-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/RKSJ-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/RKSJ-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/Roman.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/Roman.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniCNS-UCS2-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniCNS-UCS2-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniCNS-UCS2-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniCNS-UCS2-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniCNS-UTF16-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniCNS-UTF16-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniCNS-UTF16-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniCNS-UTF16-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniCNS-UTF32-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniCNS-UTF32-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniCNS-UTF32-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniCNS-UTF32-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniCNS-UTF8-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniCNS-UTF8-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniCNS-UTF8-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniCNS-UTF8-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniGB-UCS2-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniGB-UCS2-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniGB-UCS2-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniGB-UCS2-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniGB-UTF16-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniGB-UTF16-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniGB-UTF16-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniGB-UTF16-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniGB-UTF32-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniGB-UTF32-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniGB-UTF32-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniGB-UTF32-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniGB-UTF8-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniGB-UTF8-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniGB-UTF8-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniGB-UTF8-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UCS2-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UCS2-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UCS2-HW-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UCS2-HW-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UCS2-HW-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UCS2-HW-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UCS2-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UCS2-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UTF16-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UTF16-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UTF16-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UTF16-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UTF32-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UTF32-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UTF32-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UTF32-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UTF8-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UTF8-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS-UTF8-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS-UTF8-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS2004-UTF16-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS2004-UTF16-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS2004-UTF16-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS2004-UTF16-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS2004-UTF32-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS2004-UTF32-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS2004-UTF32-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS2004-UTF32-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS2004-UTF8-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS2004-UTF8-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJIS2004-UTF8-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJIS2004-UTF8-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJISPro-UCS2-HW-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJISPro-UCS2-HW-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJISPro-UCS2-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJISPro-UCS2-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJISPro-UTF8-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJISPro-UTF8-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJISX0213-UTF32-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJISX0213-UTF32-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJISX0213-UTF32-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJISX0213-UTF32-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJISX02132004-UTF32-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJISX02132004-UTF32-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniJISX02132004-UTF32-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniJISX02132004-UTF32-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniKS-UCS2-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniKS-UCS2-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniKS-UCS2-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniKS-UCS2-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniKS-UTF16-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniKS-UTF16-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniKS-UTF16-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniKS-UTF16-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniKS-UTF32-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniKS-UTF32-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniKS-UTF32-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniKS-UTF32-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniKS-UTF8-H.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniKS-UTF8-H.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/UniKS-UTF8-V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/UniKS-UTF8-V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/V.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/V.bcmap -------------------------------------------------------------------------------- /client/public/pdf/cmaps/WP-Symbol.bcmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdf/cmaps/WP-Symbol.bcmap -------------------------------------------------------------------------------- /client/public/pdfium/pdfium.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/client/public/pdfium/pdfium.wasm -------------------------------------------------------------------------------- /client/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/assets/ai-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /client/src/assets/vue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 36 | 37 | 42 | -------------------------------------------------------------------------------- /client/src/components/MobileNav.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 25 | 26 | -------------------------------------------------------------------------------- /client/src/components/RecentDocs.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 96 | 97 | -------------------------------------------------------------------------------- /client/src/components/SearchBar.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 69 | 70 | -------------------------------------------------------------------------------- /client/src/components/announcement/AnnouncementButton.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 36 | 37 | -------------------------------------------------------------------------------- /client/src/components/announcement/RecommendationsPanel.vue: -------------------------------------------------------------------------------- 1 | 53 | 54 | 81 | 82 | -------------------------------------------------------------------------------- /client/src/components/icons/index.js: -------------------------------------------------------------------------------- 1 | // 自定义图标组件导出 2 | import { h } from 'vue'; 3 | 4 | export const GithubIcon = { 5 | name: 'GithubIcon', 6 | props: { 7 | width: { 8 | type: Number, 9 | default: 20 10 | }, 11 | height: { 12 | type: Number, 13 | default: 20 14 | } 15 | }, 16 | render() { 17 | return h('svg', { 18 | xmlns: 'http://www.w3.org/2000/svg', 19 | viewBox: '0 0 24 24', 20 | width: this.width, 21 | height: this.height, 22 | fill: 'none', 23 | stroke: 'currentColor', 24 | 'stroke-width': '2', 25 | 'stroke-linecap': 'round', 26 | 'stroke-linejoin': 'round' 27 | }, [ 28 | h('path', { 29 | d: 'M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22' 30 | }) 31 | ]); 32 | } 33 | }; -------------------------------------------------------------------------------- /client/src/composables/useDebounce.ts: -------------------------------------------------------------------------------- 1 | export const useDebounce = () => { 2 | const debounce = any>( 3 | fn: T, 4 | delay: number 5 | ): ((...args: Parameters) => void) => { 6 | let timeoutId: ReturnType 7 | 8 | return (...args: Parameters) => { 9 | clearTimeout(timeoutId) 10 | timeoutId = setTimeout(() => fn(...args), delay) 11 | } 12 | } 13 | 14 | return { 15 | debounce 16 | } 17 | } -------------------------------------------------------------------------------- /client/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import { createPinia } from 'pinia' 3 | import App from './App.vue' 4 | import router from './router' 5 | import './style.css' 6 | import '@fortawesome/fontawesome-free/css/all.css' 7 | 8 | // 初始化主题 9 | const theme = localStorage.getItem('theme') 10 | if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) { 11 | document.documentElement.classList.add('dark') 12 | localStorage.setItem('theme', 'dark') 13 | } else { 14 | document.documentElement.classList.remove('dark') 15 | localStorage.setItem('theme', 'light') 16 | } 17 | 18 | const app = createApp(App) 19 | 20 | app.use(createPinia()) 21 | app.use(router) 22 | 23 | app.mount('#app') 24 | -------------------------------------------------------------------------------- /client/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | 3 | // 使用动态导入实现路由懒加载 4 | const HomeView = () => import('../views/HomeView.vue') 5 | const DocView = () => import('../views/DocView.vue') 6 | const SearchView = () => import('../views/SearchView.vue') 7 | const AdminDashboard = () => import('../views/AdminDashboard.vue') 8 | 9 | const router = createRouter({ 10 | history: createWebHistory(import.meta.env.BASE_URL), 11 | routes: [ 12 | { 13 | path: '/', 14 | name: 'home', 15 | component: HomeView, 16 | meta: { 17 | title: 'AI Library - 首页' 18 | } 19 | }, 20 | { 21 | path: '/doc/:path(.*)', 22 | name: 'doc', 23 | component: DocView, 24 | meta: { 25 | title: 'AI Library - 文档阅读' 26 | } 27 | }, 28 | { 29 | path: '/search', 30 | name: 'search', 31 | component: SearchView, 32 | meta: { 33 | title: 'AI Library - 搜索结果' 34 | } 35 | }, 36 | { 37 | path: '/admin', 38 | name: 'Admin', 39 | component: AdminDashboard, 40 | meta: { 41 | title: '管理后台 - AI Library' 42 | } 43 | } 44 | ], 45 | scrollBehavior(to, from, savedPosition) { 46 | if (savedPosition) { 47 | return savedPosition 48 | } else if (to.hash) { 49 | return { 50 | el: to.hash, 51 | behavior: 'smooth' 52 | } 53 | } else { 54 | return { top: 0 } 55 | } 56 | } 57 | }) 58 | 59 | // 动态设置页面标题 60 | router.beforeEach((to, from, next) => { 61 | document.title = to.meta.title as string || 'AI Library' 62 | next() 63 | }) 64 | 65 | export default router -------------------------------------------------------------------------------- /client/src/stores/doc.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref } from 'vue' 3 | import { docApi, type DocTree, type DocContent, type Breadcrumb } from '../services/api' 4 | 5 | export const useDocStore = defineStore('doc', { 6 | state: () => ({ 7 | docTree: null as DocTree | null, 8 | currentDoc: null as DocContent | null, 9 | recentDocs: [] as DocContent[], 10 | loading: false, 11 | subTreeLoading: {} as Record, 12 | error: null as string | null 13 | }), 14 | 15 | actions: { 16 | async loadDocTree() { 17 | this.loading = true 18 | this.error = null 19 | try { 20 | const result = await docApi.getDocTree() 21 | this.docTree = result 22 | } catch (err) { 23 | console.error('Error loading doc tree:', err) 24 | this.error = err instanceof Error ? err.message : '加载文档树失败' 25 | } finally { 26 | this.loading = false 27 | } 28 | }, 29 | 30 | async loadDocSubtree(path: string) { 31 | // 设置特定路径的加载状态 32 | this.subTreeLoading[path] = true 33 | console.log(`开始加载子树: ${path}`); 34 | 35 | try { 36 | const subtree = await docApi.getDocSubtree(path) 37 | console.log(`子树加载成功: ${path}, 子节点数: ${subtree?.children?.length || 0}`); 38 | 39 | // 递归函数查找目标节点 40 | const updateNode = (node: DocTree, targetPath: string, newChildren: DocTree["children"]) => { 41 | if (node.path === targetPath) { 42 | // 找到目标节点,更新其子节点 43 | console.log(`找到目标节点: ${targetPath}, 更新子节点数: ${newChildren?.length || 0}`); 44 | node.children = newChildren 45 | // 移除加载标记 46 | delete node.has_children 47 | return true 48 | } 49 | 50 | // 递归查找 51 | if (node.children) { 52 | for (const child of node.children) { 53 | if (updateNode(child, targetPath, newChildren)) { 54 | return true 55 | } 56 | } 57 | } 58 | 59 | return false 60 | } 61 | 62 | // 更新文档树 63 | if (this.docTree) { 64 | const updated = updateNode(this.docTree, path, subtree.children) 65 | if (!updated) { 66 | console.warn(`未找到目标节点 ${path} 来更新子树`); 67 | } 68 | } else { 69 | console.warn(`文档树为空,无法更新子树 ${path}`); 70 | } 71 | 72 | } catch (err) { 73 | console.error(`Error loading subtree for path ${path}:`, err) 74 | } finally { 75 | // 更新加载状态 76 | this.subTreeLoading[path] = false 77 | } 78 | }, 79 | 80 | async loadDocContent(path: string) { 81 | this.loading = true 82 | this.error = null 83 | try { 84 | const doc = await docApi.getDocContent(path) 85 | this.currentDoc = doc 86 | } catch (err) { 87 | console.error('Error loading doc content:', err) 88 | this.error = err instanceof Error ? err.message : '加载文档内容失败' 89 | } finally { 90 | this.loading = false 91 | } 92 | }, 93 | 94 | async loadRecentDocs() { 95 | this.loading = true 96 | this.error = null 97 | try { 98 | const result = await docApi.getRecentDocs() 99 | this.recentDocs = result 100 | } catch (err) { 101 | console.error('Error loading recent docs:', err) 102 | this.error = err instanceof Error ? err.message : '加载最近文档失败' 103 | } finally { 104 | this.loading = false 105 | } 106 | } 107 | } 108 | }) -------------------------------------------------------------------------------- /client/src/stores/reading.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | 3 | interface ReadingSettings { 4 | contentWidth: number 5 | fontSize: number 6 | autoHideControls: boolean 7 | enableAutoScroll: boolean 8 | theme: 'light' | 'dark' | 'sepia' 9 | lineHeight: number 10 | paragraphSpacing: number 11 | marginSize: number 12 | } 13 | 14 | interface ReadingState { 15 | isImmersive: boolean 16 | settings: ReadingSettings 17 | lastPosition: { 18 | path: string 19 | scroll: number 20 | } | null 21 | readingTime: { 22 | [key: string]: number // 文档路径: 阅读时间(秒) 23 | } 24 | } 25 | 26 | export const useReadingStore = defineStore('reading', { 27 | state: (): ReadingState => ({ 28 | isImmersive: false, 29 | settings: { 30 | contentWidth: 70, 31 | fontSize: 16, 32 | autoHideControls: true, 33 | enableAutoScroll: false, 34 | theme: 'light', 35 | lineHeight: 1.6, 36 | paragraphSpacing: 1.2, 37 | marginSize: 2 38 | }, 39 | lastPosition: null, 40 | readingTime: {} 41 | }), 42 | 43 | actions: { 44 | setImmersiveMode(value: boolean) { 45 | this.isImmersive = value 46 | // 保存到本地存储 47 | localStorage.setItem('reading-immersive', String(value)) 48 | }, 49 | 50 | updateSettings(settings: Partial) { 51 | this.settings = { ...this.settings, ...settings } 52 | // 保存到本地存储 53 | localStorage.setItem('reading-settings', JSON.stringify(this.settings)) 54 | }, 55 | 56 | savePosition(path: string, scroll: number) { 57 | this.lastPosition = { path, scroll } 58 | // 保存到本地存储 59 | localStorage.setItem('reading-position', JSON.stringify(this.lastPosition)) 60 | }, 61 | 62 | updateReadingTime(path: string, seconds: number) { 63 | if (!this.readingTime[path]) { 64 | this.readingTime[path] = 0 65 | } 66 | this.readingTime[path] += seconds 67 | // 保存到本地存储 68 | localStorage.setItem('reading-time', JSON.stringify(this.readingTime)) 69 | }, 70 | 71 | // 从本地存储恢复状态 72 | restoreState() { 73 | // 恢复沉浸式模式状态 74 | const immersive = localStorage.getItem('reading-immersive') 75 | if (immersive) { 76 | this.isImmersive = immersive === 'true' 77 | } 78 | 79 | // 恢复设置 80 | const settings = localStorage.getItem('reading-settings') 81 | if (settings) { 82 | this.settings = { ...this.settings, ...JSON.parse(settings) } 83 | } 84 | 85 | // 恢复上次阅读位置 86 | const position = localStorage.getItem('reading-position') 87 | if (position) { 88 | this.lastPosition = JSON.parse(position) 89 | } 90 | 91 | // 恢复阅读时间统计 92 | const readingTime = localStorage.getItem('reading-time') 93 | if (readingTime) { 94 | this.readingTime = JSON.parse(readingTime) 95 | } 96 | } 97 | }, 98 | 99 | getters: { 100 | // 获取特定文档的阅读时间(格式化后的) 101 | getFormattedReadingTime: (state) => (path: string) => { 102 | const seconds = state.readingTime[path] || 0 103 | if (seconds < 60) { 104 | return `${seconds}秒` 105 | } 106 | const minutes = Math.floor(seconds / 60) 107 | if (minutes < 60) { 108 | return `${minutes}分钟` 109 | } 110 | const hours = Math.floor(minutes / 60) 111 | const remainingMinutes = minutes % 60 112 | return `${hours}小时${remainingMinutes}分钟` 113 | }, 114 | 115 | // 获取所有文档的总阅读时间 116 | totalReadingTime: (state) => { 117 | return Object.values(state.readingTime).reduce((total, time) => total + time, 0) 118 | } 119 | } 120 | }) -------------------------------------------------------------------------------- /client/src/stores/search.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref } from 'vue' 3 | import { searchDocs } from '../services/api' 4 | 5 | interface SearchResult { 6 | path: string 7 | name: string 8 | matches: Array<{ 9 | type: string 10 | text: string 11 | line: number 12 | }> 13 | relevance_score: number 14 | } 15 | 16 | interface SearchMeta { 17 | total: number 18 | total_matches: number 19 | page: number 20 | per_page: number 21 | total_pages: number 22 | } 23 | 24 | interface SearchParams { 25 | q: string 26 | page?: number 27 | per_page?: number 28 | sort_by?: string 29 | sort_order?: string 30 | doc_type?: string 31 | } 32 | 33 | export const useSearchStore = defineStore('search', () => { 34 | const searchResults = ref([]) 35 | const searchMeta = ref({ 36 | total: 0, 37 | total_matches: 0, 38 | page: 1, 39 | per_page: 10, 40 | total_pages: 0 41 | }) 42 | const loading = ref(false) 43 | const error = ref(null) 44 | 45 | const search = async (params: SearchParams) => { 46 | loading.value = true 47 | error.value = null 48 | try { 49 | const response = await searchDocs(params) 50 | searchResults.value = response.results 51 | searchMeta.value = { 52 | total: response.total, 53 | total_matches: response.total_matches, 54 | page: response.page, 55 | per_page: response.per_page, 56 | total_pages: response.total_pages 57 | } 58 | } catch (e) { 59 | error.value = e instanceof Error ? e.message : '搜索失败' 60 | searchResults.value = [] 61 | searchMeta.value = { 62 | total: 0, 63 | total_matches: 0, 64 | page: 1, 65 | per_page: 10, 66 | total_pages: 0 67 | } 68 | } finally { 69 | loading.value = false 70 | } 71 | } 72 | 73 | return { 74 | searchResults, 75 | searchMeta, 76 | loading, 77 | error, 78 | search 79 | } 80 | }) -------------------------------------------------------------------------------- /client/src/stores/theme.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref, watch } from 'vue' 3 | 4 | export const useThemeStore = defineStore('theme', () => { 5 | const isDark = ref(document.documentElement.classList.contains('dark')) 6 | 7 | // 监听主题变化 8 | watch(isDark, (newValue) => { 9 | if (newValue) { 10 | document.documentElement.classList.add('dark') 11 | localStorage.setItem('theme', 'dark') 12 | } else { 13 | document.documentElement.classList.remove('dark') 14 | localStorage.setItem('theme', 'light') 15 | } 16 | }) 17 | 18 | // 切换主题 19 | const toggleTheme = () => { 20 | isDark.value = !isDark.value 21 | } 22 | 23 | // 设置主题 24 | const setTheme = (dark: boolean) => { 25 | isDark.value = dark 26 | } 27 | 28 | return { 29 | isDark, 30 | toggleTheme, 31 | setTheme 32 | } 33 | }) -------------------------------------------------------------------------------- /client/src/style.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | html { 7 | @apply antialiased; 8 | } 9 | 10 | body { 11 | @apply bg-gray-50 text-gray-900; 12 | } 13 | } 14 | 15 | @layer components { 16 | .markdown-body { 17 | @apply prose prose-slate max-w-none; 18 | } 19 | 20 | .markdown-body pre { 21 | @apply bg-gray-800 text-white p-4 rounded-lg overflow-x-auto; 22 | } 23 | 24 | .markdown-body code { 25 | @apply font-mono text-sm; 26 | } 27 | 28 | .markdown-body img { 29 | @apply max-w-full h-auto rounded-lg shadow-lg; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /client/src/styles/immersive.scss: -------------------------------------------------------------------------------- 1 | /* 沉浸式阅读模式样式 */ 2 | :root { 3 | --reading-content-width: 70%; 4 | --reading-font-size: 16px; 5 | --reading-line-height: 1.6; 6 | --reading-paragraph-spacing: 1.2rem; 7 | --reading-margin-size: 2rem; 8 | } 9 | 10 | /* 沉浸式阅读模式的全局样式 */ 11 | .immersive-reading { 12 | /* 隐藏非必要UI元素 */ 13 | .doc-tree, 14 | .header, 15 | .footer { 16 | opacity: 0; 17 | pointer-events: none; 18 | transition: opacity 0.3s ease; 19 | } 20 | 21 | /* 内容区域样式 */ 22 | .markdown-viewer, 23 | .pdf-viewer { 24 | max-width: var(--reading-content-width); 25 | margin: 0 auto; 26 | padding: var(--reading-margin-size); 27 | font-size: var(--reading-font-size); 28 | line-height: var(--reading-line-height); 29 | 30 | /* 段落间距 */ 31 | p { 32 | margin-bottom: var(--reading-paragraph-spacing); 33 | } 34 | 35 | /* 优化大屏显示 */ 36 | @media (min-width: 1920px) { 37 | /* 24-27寸屏幕 */ 38 | max-width: min(var(--reading-content-width), 1200px); 39 | font-size: calc(var(--reading-font-size) * 1.1); 40 | } 41 | 42 | @media (min-width: 2560px) { 43 | /* 32寸及以上屏幕 */ 44 | max-width: min(var(--reading-content-width), 1400px); 45 | font-size: calc(var(--reading-font-size) * 1.2); 46 | } 47 | 48 | @media (min-width: 3440px) { 49 | /* 40寸及以上超宽屏 */ 50 | max-width: min(var(--reading-content-width), 1600px); 51 | font-size: calc(var(--reading-font-size) * 1.3); 52 | } 53 | } 54 | 55 | /* 图片优化 */ 56 | img { 57 | max-width: 100%; 58 | height: auto; 59 | margin: 2rem auto; 60 | border-radius: 8px; 61 | box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); 62 | } 63 | 64 | /* 代码块优化 */ 65 | pre { 66 | margin: 2rem 0; 67 | padding: 1.5rem; 68 | border-radius: 8px; 69 | font-size: 0.95em; 70 | line-height: 1.5; 71 | } 72 | 73 | /* 标题优化 */ 74 | h1, h2, h3, h4, h5, h6 { 75 | margin-top: 2em; 76 | margin-bottom: 1em; 77 | line-height: 1.3; 78 | } 79 | 80 | /* 列表优化 */ 81 | ul, ol { 82 | padding-left: 2em; 83 | margin: 1em 0; 84 | } 85 | 86 | /* 引用块优化 */ 87 | blockquote { 88 | margin: 2rem 0; 89 | padding: 1rem 2rem; 90 | border-left: 4px solid; 91 | background: rgba(0, 0, 0, 0.03); 92 | } 93 | 94 | /* 表格优化 */ 95 | table { 96 | margin: 2rem 0; 97 | width: 100%; 98 | border-collapse: collapse; 99 | 100 | th, td { 101 | padding: 0.75rem 1rem; 102 | border: 1px solid rgba(0, 0, 0, 0.1); 103 | } 104 | } 105 | } 106 | 107 | /* 深色模式适配 */ 108 | .dark .immersive-reading { 109 | img { 110 | box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3); 111 | } 112 | 113 | blockquote { 114 | background: rgba(255, 255, 255, 0.03); 115 | } 116 | 117 | table { 118 | th, td { 119 | border-color: rgba(255, 255, 255, 0.1); 120 | } 121 | } 122 | } 123 | 124 | /* 护眼模式 */ 125 | .sepia .immersive-reading { 126 | background: #f4f1ea; 127 | color: #5c4b37; 128 | 129 | img { 130 | filter: sepia(20%); 131 | } 132 | } -------------------------------------------------------------------------------- /client/src/utils/markdown.ts: -------------------------------------------------------------------------------- 1 | import MarkdownIt from 'markdown-it' 2 | import type { Options } from 'markdown-it' 3 | import Token from 'markdown-it/lib/token' 4 | 5 | // 创建 markdown-it 实例 6 | const md = new MarkdownIt({ 7 | html: true, 8 | linkify: true, 9 | typographer: true 10 | } as Options) 11 | 12 | // 重写图片渲染规则 13 | md.renderer.rules.image = (tokens: Token[], idx: number, options: Options, env: any, self: any): string => { 14 | const token = tokens[idx] 15 | const srcIndex = token.attrIndex('src') 16 | const src = token.attrs?.[srcIndex]?.[1] || '' 17 | const alt = token.content || '' 18 | 19 | // 构建图片标签,不包含文件名显示 20 | return `${alt}` 21 | } 22 | 23 | // 移除图片后的文件名段落 24 | const defaultParagraphRule = md.renderer.rules.paragraph_open || ((tokens: Token[], idx: number, options: Options, env: any, self: any) => self.renderToken(tokens, idx, options)) 25 | 26 | md.renderer.rules.paragraph_open = (tokens: Token[], idx: number, options: Options, env: any, self: any): string => { 27 | const nextToken = tokens[idx + 1] 28 | 29 | // 如果这个段落只包含一个图片文件名,就跳过渲染 30 | if (nextToken && 31 | nextToken.type === 'inline' && 32 | nextToken.children && 33 | nextToken.children.length === 1 && 34 | nextToken.children[0].type === 'text' && 35 | (nextToken.children[0].content.endsWith('.png') || 36 | nextToken.children[0].content.endsWith('.jpg') || 37 | nextToken.children[0].content.endsWith('.jpeg') || 38 | nextToken.children[0].content.endsWith('.gif') || 39 | nextToken.children[0].content.endsWith('.webp'))) { 40 | return '' 41 | } 42 | 43 | return defaultParagraphRule(tokens, idx, options, env, self) 44 | } 45 | 46 | export default md -------------------------------------------------------------------------------- /client/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // 声明模块 4 | declare module 'gsap' { 5 | export const gsap: any; 6 | export function to(target: any, vars: any): any; 7 | export function from(target: any, vars: any): any; 8 | export function fromTo(target: any, fromVars: any, toVars: any): any; 9 | export default { 10 | to, 11 | from, 12 | fromTo 13 | }; 14 | } 15 | 16 | declare module '*.vue' { 17 | import type { DefineComponent } from 'vue' 18 | const component: DefineComponent<{}, {}, any> 19 | export default component 20 | } 21 | 22 | // 声明AnnouncementStore的类型 23 | declare interface UpdateItem { 24 | id: string; 25 | title: string; 26 | description: string; 27 | date: string; 28 | changes?: string[]; 29 | important?: boolean; 30 | } 31 | 32 | declare interface RecommendationItem { 33 | id: string; 34 | title: string; 35 | description: string; 36 | category: string; 37 | tags: string[]; 38 | path?: string; 39 | url?: string; 40 | } 41 | 42 | declare interface FeedbackItem { 43 | name: string; 44 | type: string; 45 | content: string; 46 | contact: string; 47 | timestamp: string; 48 | } 49 | -------------------------------------------------------------------------------- /client/ssl/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFCTCCAvGgAwIBAgIUaDZaBIpvaLbYndshVnvSr6+3kXgwDQYJKoZIhvcNAQEL 3 | BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDMxMzAzMzY1N1oXDTI2MDMx 4 | MzAzMzY1N1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF 5 | AAOCAg8AMIICCgKCAgEAss4wWX6Xu5ZD9zUXzhX0wSyQL3eL7Ixu9zFOeQy+4tMe 6 | YPQLrMZdrQH1oT9a2V9MiD7AVnI+wCIOkRHy8ho0XaH+asL2ntINB10W9WAk1MGa 7 | 23V2AAFaaONfK7CXSEzpxX8gVIcdEsQyNJ/GskcX0McdgWp7HX1qSqylp1n9BRDX 8 | wzNmge+H1YhGSLzRvwQfXoQpVc1wp7dM/1Ce0GDi/jkvUNdCRyzvwaSzahBuCZoC 9 | Clo8q9jNELYQ3YEtefS/hvh8JOzpX+azzXkyaVvgNGymFpb6tzGG61GEZ3QxHtQd 10 | I1zfhN8MSFeKbIBb7G6JbBEYOFCxzconAVu3E1FS9bQb+oN7ZeSWB4lzTyobvVBF 11 | h862DjscRnx1B/QicJf3WS6QRGRI5co4iq2VpwzfuaqT6ZeEI1us+7arrXIYhgx1 12 | CjanyWeKFWwgMGSEQ1s9kgxqWiAKA5wg+VIV4NfwyI/U5I+aOlVJvKfZ8p/8hVGT 13 | bz5QSjo4EVx7mV5Z8KT9+joMYVBwFr8+EhjHodcBz27JCLuX3yXnMC3R4HLfqBku 14 | qy6zSQKjXrhNRc0ehE6uB/Ox5QrJtX9pQymJ0RJu9BTZ5mcV8HaZ04ZCZgHB+Pnz 15 | u48/EcGIhiU4souqjzE4JWq7nGBMNjXi8dfELApH7WQ5v9OFxMlP+F4DVFgOp1MC 16 | AwEAAaNTMFEwHQYDVR0OBBYEFODeMJVDz6ihbIqqdyExsy180N/iMB8GA1UdIwQY 17 | MBaAFODeMJVDz6ihbIqqdyExsy180N/iMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI 18 | hvcNAQELBQADggIBAEv7NnKNA6Ums3BBxbJ5iX3Loldp/VMPWhlwQS6UPlV2dBPI 19 | Odefc+a0rnljMbiwORk9COKla0mtHH8dWJCRc1wHV75tj+f72v2G7rSkjLRNAzSE 20 | pZI1/ZRzl2i076By20wGnCJPtUOJ/Zm5TASdIq7GOTgmh7bEgpNuyCDHWtdyX6hP 21 | 9QFnUUNLHf35hT3k8KmMLK6Nbgl6pRVReezmlux3qHIKrvx7oV28t9kyafRzENFH 22 | MBwN/hpr3hihDvf4Bxb/qOy1jdGmdovR4qQH7JiPkLKwGYL+6vXL547nkjfFRk5Z 23 | E9y2ogpExNK7IC9ex0yjSgpQ5qX8hNO9Y9wLGi76qK8VMaSkOLw2o/w5KfvVtyjz 24 | vXJwTBYce6WY30RIjENv/dvbV5ea66p9eRNQ7syebXA4eCtJExULFODuzs5iVjen 25 | HKXo+W15vF39KFIG70MOZV/UMZUEH0bTunGTFMKT/ObwyUwKBTZWCs03diQZ3d2+ 26 | njc34AN5K7rlbocSCjFuKrptA32t+F1DLRJ5meZccQ+pdwOCoL1Sbp9xVZb8fy/H 27 | YqQjwn+aaM78GAi4V67H0wkJb+1/pJEnKVXRlgMfThyMQQ9gGbkDwrZZRIMe3QYk 28 | Lx79k1s77a9NGbJszX1Slw2wFDOVAmJM7/H5HHS0+cTPbg5CZ/JF8JWeSdxl 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /client/ssl/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | 81tv7dRrojdJIEqdRS2tkOsnrow3XZk= 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /client/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{vue,js,ts,jsx,tsx}", 6 | ], 7 | darkMode: 'class', 8 | theme: { 9 | extend: { 10 | colors: { 11 | primary: { 12 | 50: '#f0f9ff', 13 | 100: '#e0f2fe', 14 | 200: '#bae6fd', 15 | 300: '#7dd3fc', 16 | 400: '#38bdf8', 17 | 500: '#0ea5e9', 18 | 600: '#0284c7', 19 | 700: '#0369a1', 20 | 800: '#075985', 21 | 900: '#0c4a6e', 22 | 950: '#082f49', 23 | }, 24 | }, 25 | }, 26 | }, 27 | plugins: [ 28 | require('@tailwindcss/typography'), 29 | ], 30 | } 31 | 32 | -------------------------------------------------------------------------------- /client/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "compilerOptions": { 4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 5 | 6 | /* Linting */ 7 | "strict": true, 8 | "noUnusedLocals": true, 9 | "noUnusedParameters": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "noUncheckedSideEffectImports": true 12 | }, 13 | "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] 14 | } 15 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /client/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2022", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "isolatedModules": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true, 21 | "noUncheckedSideEffectImports": true 22 | }, 23 | "include": ["vite.config.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /client/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | import { fileURLToPath } from 'node:url' 4 | import { visualizer } from 'rollup-plugin-visualizer' 5 | import viteCompression from 'vite-plugin-compression' 6 | import fs from 'node:fs' 7 | import path from 'node:path' 8 | 9 | // https://vitejs.dev/config/ 10 | export default defineConfig({ 11 | plugins: [ 12 | vue(), 13 | // 生成gzip压缩文件 14 | viteCompression({ 15 | verbose: true, 16 | disable: false, 17 | threshold: 10240, 18 | algorithm: 'gzip', 19 | ext: '.gz', 20 | }), 21 | // 生成构建分析报告 22 | visualizer({ 23 | open: false, 24 | gzipSize: true, 25 | brotliSize: true, 26 | }), 27 | ], 28 | resolve: { 29 | alias: { 30 | '@': fileURLToPath(new URL('./src', import.meta.url)), 31 | } 32 | }, 33 | build: { 34 | // 启用多页面构建 35 | rollupOptions: { 36 | output: { 37 | manualChunks: { 38 | 'pdf.worker': ['pdfjs-dist/build/pdf.worker.min'], 39 | 'vue-vendor': ['vue', 'vue-router', 'pinia'], 40 | 'ui-vendor': ['@heroicons/vue'], 41 | 'markdown': ['marked', 'highlight.js'], 42 | 'utils': ['axios', 'lodash-es'] 43 | }, 44 | // 自定义chunk文件名 45 | chunkFileNames: 'assets/js/[name]-[hash].js', 46 | entryFileNames: 'assets/js/[name]-[hash].js', 47 | assetFileNames: 'assets/[ext]/[name]-[hash].[ext]', 48 | } 49 | }, 50 | // 启用CSS代码分割 51 | cssCodeSplit: true, 52 | // 禁用源码映射以减小构建体积 53 | sourcemap: false, 54 | // 减小chunk大小警告阈值 55 | chunkSizeWarningLimit: 1000, 56 | // 启用minify 57 | minify: 'terser', 58 | // terser配置 59 | terserOptions: { 60 | compress: { 61 | drop_console: true, 62 | drop_debugger: true, 63 | }, 64 | }, 65 | // 启用CSS压缩 66 | cssMinify: true, 67 | // 启用预加载 68 | assetsInlineLimit: 4096, 69 | }, 70 | server: { 71 | https: { 72 | key: fs.readFileSync(path.resolve(process.cwd(), '../certs/key.pem')), 73 | cert: fs.readFileSync(path.resolve(process.cwd(), '../certs/cert.pem')), 74 | }, 75 | proxy: { 76 | '/api': { 77 | target: 'https://frp6.mmszxc.xin:18926/', 78 | changeOrigin: true, 79 | ws: true, 80 | secure: false 81 | } 82 | } 83 | }, 84 | // 优化预构建 85 | optimizeDeps: { 86 | include: [ 87 | 'vue', 88 | 'vue-router', 89 | 'pinia', 90 | 'axios', 91 | 'marked', 92 | 'prismjs', 93 | '@heroicons/vue/24/outline' 94 | ], 95 | exclude: ['pdfjs-dist/build/pdf.worker.min'] 96 | } 97 | }) 98 | -------------------------------------------------------------------------------- /dark-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/dark-mode.png -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 更新系统包 4 | sudo yum update -y 5 | 6 | # 安装 EPEL 源 7 | sudo yum install epel-release -y 8 | 9 | # 安装 Nginx 10 | sudo yum install nginx -y 11 | 12 | # 创建网站目录 13 | sudo mkdir -p /var/www/ailibrary 14 | 15 | # 确保目录权限正确 16 | sudo chown -R nginx:nginx /var/www/ailibrary 17 | sudo chmod -R 755 /var/www/ailibrary 18 | 19 | # 配置 Nginx 20 | sudo mkdir -p /etc/nginx/conf.d 21 | sudo tee /etc/nginx/conf.d/ailibrary.conf << EOF 22 | server { 23 | listen 80; 24 | server_name _; # 暂时匹配所有域名 25 | 26 | root /var/www/ailibrary; 27 | index index.html; 28 | 29 | # 启用 gzip 压缩 30 | gzip on; 31 | gzip_vary on; 32 | gzip_min_length 10240; 33 | gzip_proxied expired no-cache no-store private auth; 34 | gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml; 35 | gzip_disable "MSIE [1-6]\."; 36 | 37 | location / { 38 | try_files \$uri \$uri/ /index.html; # 支持 Vue Router 的 history 模式 39 | } 40 | 41 | # 缓存静态资源 42 | location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { 43 | expires 30d; 44 | add_header Cache-Control "public, no-transform"; 45 | } 46 | } 47 | EOF 48 | 49 | # 创建日志目录(如果不存在) 50 | sudo mkdir -p /var/log/nginx 51 | sudo chown -R nginx:nginx /var/log/nginx 52 | 53 | # 配置 SELinux(如果启用) 54 | if command -v sestatus >/dev/null 2>&1; then 55 | if sestatus | grep "SELinux status" | grep -q "enabled"; then 56 | sudo setsebool -P httpd_can_network_connect 1 57 | sudo chcon -Rt httpd_sys_content_t /var/www/ailibrary 58 | fi 59 | fi 60 | 61 | # 启动 Nginx 并设置开机自启 62 | sudo systemctl enable nginx 63 | sudo systemctl start nginx 64 | 65 | # 配置防火墙 66 | if command -v firewall-cmd >/dev/null 2>&1; then 67 | sudo firewall-cmd --permanent --zone=public --add-service=http 68 | sudo firewall-cmd --permanent --zone=public --add-service=https 69 | sudo firewall-cmd --reload 70 | fi 71 | 72 | echo "部署脚本执行完成!" 73 | echo "现在你可以将构建好的 dist 目录内容上传到 /var/www/ailibrary/ 目录" -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | meilisearch: 5 | image: getmeili/meilisearch:v1.5 6 | container_name: ai-library-meilisearch 7 | ports: 8 | - "7700:7700" 9 | environment: 10 | - MEILI_MASTER_KEY=masterKey 11 | - MEILI_NO_ANALYTICS=true 12 | - MEILI_ENV=development 13 | volumes: 14 | - meilisearch_data:/meili_data 15 | restart: unless-stopped 16 | healthcheck: 17 | test: ["CMD", "wget", "--no-verbose", "--spider", "http://localhost:7700/health"] 18 | interval: 10s 19 | timeout: 5s 20 | retries: 5 21 | 22 | volumes: 23 | meilisearch_data: -------------------------------------------------------------------------------- /env.md: -------------------------------------------------------------------------------- 1 | ip:206.233.249.233 2 | root 3 | XL93jP18zkU0fF 4 | -------------------------------------------------------------------------------- /home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/home.png -------------------------------------------------------------------------------- /install_meilisearch_windows.md: -------------------------------------------------------------------------------- 1 | # 在Windows上安装MeiliSearch 2 | 3 | 本指南提供两种在Windows系统上安装MeiliSearch的方法:直接使用Windows二进制文件和通过WSL(Windows Subsystem for Linux)。 4 | 5 | ## 方法一:直接下载Windows二进制文件 6 | 7 | 1. 访问MeiliSearch的GitHub发布页面:https://github.com/meilisearch/meilisearch/releases 8 | 9 | 2. 找到最新版本(当前为v1.13.2),在Assets中下载Windows版本: 10 | - `meilisearch-windows-amd64.exe`(适用于64位Windows系统) 11 | 12 | 3. 下载完成后,将文件重命名为`meilisearch.exe`(可选) 13 | 14 | 4. 创建一个用于存储MeiliSearch数据的文件夹,例如:`C:\meilisearch-data` 15 | 16 | 5. 打开命令提示符(CMD)或PowerShell,切换到存放meilisearch.exe的目录 17 | 18 | 6. 运行MeiliSearch: 19 | ``` 20 | .\meilisearch.exe --db-path=C:\meilisearch-data\data.ms --master-key=你的密钥 21 | ``` 22 | 23 | 参数说明: 24 | - `--db-path`:指定数据存储位置 25 | - `--master-key`:设置API密钥(强烈建议设置,用于安全保护) 26 | 27 | 7. 服务启动后,可以在浏览器访问:http://localhost:7700 28 | 29 | ## 方法二:通过WSL(Windows Subsystem for Linux) 30 | 31 | 如果您熟悉Linux环境,可以通过WSL来安装和运行MeiliSearch: 32 | 33 | 1. 安装WSL(如果尚未安装) 34 | - 以管理员身份打开PowerShell并运行: 35 | ``` 36 | wsl --install 37 | ``` 38 | - 重启电脑完成安装 39 | 40 | 2. 打开WSL终端(通常是Ubuntu) 41 | 42 | 3. 安装MeiliSearch: 43 | ```bash 44 | curl -L https://install.meilisearch.com | sh 45 | ``` 46 | 47 | 4. 给MeiliSearch可执行权限: 48 | ```bash 49 | chmod +x meilisearch 50 | ``` 51 | 52 | 5. 运行MeiliSearch: 53 | ```bash 54 | ./meilisearch --master-key=你的密钥 55 | ``` 56 | 57 | 6. 服务启动后,同样可以在Windows系统的浏览器访问:http://localhost:7700 58 | 59 | ## 配置和使用 60 | 61 | 无论使用哪种安装方法,MeiliSearch都将在端口7700上运行。您可以使用以下参数自定义配置: 62 | 63 | - `--http-addr`:指定监听地址(默认为`127.0.0.1:7700`) 64 | - `--env`:设置环境(development或production) 65 | - `--no-analytics`:禁用匿名分析收集 66 | 67 | 更多配置选项,请参考[官方文档](https://www.meilisearch.com/docs/learn/configuration/instance_options)。 68 | 69 | ## 将MeiliSearch设置为Windows服务 70 | 71 | 要将MeiliSearch作为Windows服务运行,可以使用NSSM(Non-Sucking Service Manager): 72 | 73 | 1. 下载NSSM:https://nssm.cc/download 74 | 75 | 2. 解压后,在命令提示符中运行: 76 | ``` 77 | nssm.exe install MeiliSearch 78 | ``` 79 | 80 | 3. 在打开的GUI中配置: 81 | - Path:MeiliSearch可执行文件的完整路径 82 | - Startup directory:MeiliSearch可执行文件所在目录 83 | - Arguments:`--db-path=C:\meilisearch-data\data.ms --master-key=你的密钥` 84 | 85 | 4. 点击"Install service"完成安装 86 | 87 | 5. 服务将随Windows启动而自动运行 88 | 89 | ## 测试MeiliSearch安装 90 | 91 | 安装完成后,可以使用以下命令测试MeiliSearch是否正常工作: 92 | 93 | ```bash 94 | # 使用curl测试API是否响应 95 | curl http://localhost:7700/health 96 | 97 | # 应返回类似内容 98 | # {"status":"available"} 99 | ``` 100 | 101 | ## 连接到AI-Library 102 | 103 | 在AI-Library的配置中,设置以下环境变量: 104 | 105 | ``` 106 | MEILISEARCH_HOST=http://localhost:7700 107 | MEILISEARCH_API_KEY=你设置的master-key 108 | ``` 109 | 110 | 这样AI-Library就可以使用MeiliSearch提供的搜索功能。 -------------------------------------------------------------------------------- /meilisearch.md: -------------------------------------------------------------------------------- 1 | # MeiliSearch 搜索集成 2 | 3 | AI Library 现在支持使用 MeiliSearch 进行全文搜索,这极大提高了搜索性能和用户体验。 4 | 5 | ## 什么是 MeiliSearch? 6 | 7 | MeiliSearch 是一个开源、快速、强大的全文搜索引擎。与文件系统搜索相比,它提供: 8 | 9 | - 毫秒级搜索响应时间 10 | - 拼写容错(模糊搜索) 11 | - 智能排名与相关性评分 12 | - 过滤器和分面搜索 13 | - 支持中文和其他多语言搜索 14 | 15 | ## 安装与设置 16 | 17 | ### 使用 Docker(推荐) 18 | 19 | 最简单的方法是使用 Docker 和 Docker Compose: 20 | 21 | 1. 确保已安装 Docker 和 Docker Compose 22 | 2. 运行 `docker-compose up -d meilisearch` 启动 MeiliSearch 服务 23 | 3. MeiliSearch 将在端口 7700 上运行 24 | 25 | 或者直接使用提供的脚本: 26 | 27 | ```bash 28 | # 给脚本执行权限 29 | chmod +x start_with_meilisearch.sh 30 | 31 | # 启动 MeiliSearch 和应用服务器 32 | ./start_with_meilisearch.sh 33 | ``` 34 | 35 | ### 手动安装 36 | 37 | 如果您不想使用 Docker,可以按照 [MeiliSearch 官方文档](https://docs.meilisearch.com/learn/getting_started/installation.html) 进行安装。 38 | 39 | ## 配置 40 | 41 | 默认配置应该能够正常工作,但您可以通过环境变量自定义: 42 | 43 | - `MEILISEARCH_HOST`: MeiliSearch 服务器地址,默认为 `http://localhost:7700` 44 | - `MEILISEARCH_API_KEY`: MeiliSearch 主密钥,默认为 `masterKey` 45 | 46 | 示例: 47 | 48 | ```bash 49 | # 设置环境变量 50 | export MEILISEARCH_HOST="http://meilisearch.example.com" 51 | export MEILISEARCH_API_KEY="your-secret-key" 52 | 53 | # 然后启动应用 54 | python server/run_h2.py 55 | ``` 56 | 57 | ## 构建索引 58 | 59 | 首次使用需要构建搜索索引: 60 | 61 | 1. 启动应用服务器 62 | 2. 访问 `/api/search/rebuild-index` API 端点 (POST 请求) 63 | 3. 等待索引构建完成 64 | 65 | 例如: 66 | 67 | ```bash 68 | curl -X POST http://localhost:8000/api/search/rebuild-index 69 | ``` 70 | 71 | ## 故障排除 72 | 73 | 如果 MeiliSearch 无法正常工作,系统会自动回退到文件系统搜索。您可以通过访问 `/api/search/status` 端点检查搜索服务状态。 74 | 75 | 常见问题: 76 | 77 | 1. MeiliSearch 服务未运行 - 确保 Docker 容器正在运行 78 | 2. 连接失败 - 检查 `MEILISEARCH_HOST` 环境变量 79 | 3. 索引为空 - 重新构建索引 80 | 81 | ## 性能比较 82 | 83 | 与文件系统搜索相比,MeiliSearch 提供了显著的性能改进: 84 | 85 | - 搜索速度提高约 20-50 倍 86 | - 更好的搜索相关性和排序 87 | - 支持更复杂的查询和过滤 88 | 89 | ## 局限性 90 | 91 | 当前实现有一些限制: 92 | 93 | 1. PDF 文件仅索引标题,不索引内容 94 | 2. 未使用 MeiliSearch 的高级分面功能 95 | 3. 首次索引构建可能较慢 96 | 97 | 这些问题将在未来版本中改进。 -------------------------------------------------------------------------------- /mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/mode.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.104.1 2 | uvicorn[standard]==0.24.0 3 | hypercorn[h2]==0.15.0 4 | python-multipart==0.0.6 5 | python-jose[cryptography]==3.3.0 6 | passlib[bcrypt]==1.7.4 7 | sqlalchemy==2.0.23 8 | aiofiles==23.2.1 9 | httpx==0.25.1 10 | python-dotenv==1.0.0 11 | pydantic==2.5.1 12 | pydantic-settings==2.1.0 13 | markdown2==2.4.10 14 | Jinja2==3.1.2 15 | websockets==12.0 16 | h2==4.1.0 17 | uvloop>=0.17.0 18 | httptools>=0.6.0 19 | watchdog==3.0.0 20 | PyPDF2==3.0.1 21 | python-magic==0.4.27 -------------------------------------------------------------------------------- /responsive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/responsive.png -------------------------------------------------------------------------------- /search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/search.png -------------------------------------------------------------------------------- /server/app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/server/app/__init__.py -------------------------------------------------------------------------------- /server/app/routers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/server/app/routers/__init__.py -------------------------------------------------------------------------------- /server/app/routers/announcements.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Depends, HTTPException, status, Body 2 | from typing import List, Optional 3 | import os 4 | import json 5 | from datetime import datetime 6 | from pydantic import BaseModel 7 | import logging 8 | 9 | from ..services.announcement_service import AnnouncementService 10 | 11 | router = APIRouter(prefix="", tags=["announcements"]) 12 | logger = logging.getLogger(__name__) 13 | 14 | # 数据模型 15 | class UpdateItem(BaseModel): 16 | id: str 17 | title: str 18 | description: str 19 | date: str 20 | changes: Optional[List[str]] = None 21 | important: Optional[bool] = None 22 | 23 | class RecommendationItem(BaseModel): 24 | id: str 25 | title: str 26 | description: str 27 | category: str 28 | tags: List[str] 29 | path: Optional[str] = None 30 | url: Optional[str] = None 31 | 32 | class FeedbackItem(BaseModel): 33 | name: Optional[str] = "" 34 | type: str 35 | content: str 36 | contact: Optional[str] = "" 37 | timestamp: str 38 | 39 | # 获取服务实例 40 | def get_announcement_service(): 41 | return AnnouncementService() 42 | 43 | # 路由 44 | @router.get("/updates", response_model=List[UpdateItem]) 45 | async def get_updates( 46 | announcement_service: AnnouncementService = Depends(get_announcement_service) 47 | ): 48 | """获取更新信息列表""" 49 | try: 50 | updates = announcement_service.get_updates() 51 | return updates 52 | except Exception as e: 53 | logger.error(f"Error getting updates: {str(e)}") 54 | raise HTTPException( 55 | status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, 56 | detail=f"Error getting updates: {str(e)}" 57 | ) 58 | 59 | @router.get("/recommendations", response_model=List[RecommendationItem]) 60 | async def get_recommendations( 61 | announcement_service: AnnouncementService = Depends(get_announcement_service) 62 | ): 63 | """获取推荐内容列表""" 64 | try: 65 | recommendations = announcement_service.get_recommendations() 66 | return recommendations 67 | except Exception as e: 68 | logger.error(f"Error getting recommendations: {str(e)}") 69 | raise HTTPException( 70 | status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, 71 | detail=f"Error getting recommendations: {str(e)}" 72 | ) 73 | 74 | @router.post("/feedback", status_code=status.HTTP_201_CREATED) 75 | async def submit_feedback( 76 | feedback: FeedbackItem, 77 | announcement_service: AnnouncementService = Depends(get_announcement_service) 78 | ): 79 | """提交用户反馈""" 80 | try: 81 | announcement_service.save_feedback(feedback) 82 | return {"message": "Feedback submitted successfully"} 83 | except Exception as e: 84 | logger.error(f"Error submitting feedback: {str(e)}") 85 | raise HTTPException( 86 | status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, 87 | detail=f"Error submitting feedback: {str(e)}" 88 | ) -------------------------------------------------------------------------------- /server/app/routers/feedback.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Depends, HTTPException, status, Body 2 | from typing import List, Optional 3 | import logging 4 | from pydantic import BaseModel 5 | 6 | from ..services.announcement_service import AnnouncementService 7 | 8 | router = APIRouter(prefix="", tags=["feedback"]) 9 | logger = logging.getLogger(__name__) 10 | 11 | class FeedbackItem(BaseModel): 12 | name: Optional[str] = "" 13 | type: str 14 | content: str 15 | contact: Optional[str] = "" 16 | timestamp: str 17 | 18 | # 获取服务实例 19 | def get_announcement_service(): 20 | return AnnouncementService() 21 | 22 | @router.post("", status_code=status.HTTP_201_CREATED) 23 | async def submit_feedback( 24 | feedback: FeedbackItem, 25 | announcement_service: AnnouncementService = Depends(get_announcement_service) 26 | ): 27 | """提交用户反馈""" 28 | try: 29 | announcement_service.save_feedback(feedback) 30 | return {"message": "Feedback submitted successfully"} 31 | except Exception as e: 32 | logger.error(f"Error submitting feedback: {str(e)}") 33 | raise HTTPException( 34 | status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, 35 | detail=f"Error submitting feedback: {str(e)}" 36 | ) -------------------------------------------------------------------------------- /server/app/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ly-GGboy/AI-Library/2fc1a855fc66b2c1743fe7a154b8a13a03210aff/server/app/services/__init__.py -------------------------------------------------------------------------------- /server/build_index.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import asyncio 3 | from app.services.meilisearch_service import MeiliSearchService 4 | 5 | async def main(): 6 | service = MeiliSearchService() 7 | print("[INFO] 开始构建索引...") 8 | result = await service.build_index() 9 | print(f"[INFO] 索引构建结果: {result}") 10 | 11 | if __name__ == "__main__": 12 | asyncio.run(main()) -------------------------------------------------------------------------------- /server/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFCTCCAvGgAwIBAgIUCwfAcNEEzNV7h6HjR+kXnO17QoswDQYJKoZIhvcNAQEL 3 | BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDEwNDE2MTEzNFoXDTI2MDEw 4 | NDE2MTEzNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF 5 | AAOCAg8AMIICCgKCAgEA/XKaswV/FtXpPTXeCe0xIX/z55OAXPwZAOdyyLkHm12U 6 | w6DeDx8+WPPanZDCCx3vDoWEHrBQJ24UJtRg4UR25nU1S/O4uLzEGneTvUc8y9g0 7 | hhgpN1SHIM9t6/CRdxYSAkTHR4uE5cge53ZHe/EjLQ+qWBPa75e8WcjFM1l5HcQr 8 | KUYQXCcqOi996O8FuKErONp8HF+qjO0DexgbB3SvyTXpPPW1UMqySkdCOOEbIHKQ 9 | TTV+w/k5DXgOeEE+HdNcLpIg2xf7wBn3SZXkfCKYCBWGpp0pxiYGamlN/1N7RVSr 10 | C1S9iVpidzOh4GKwO4g1JJeVyJ7IxSIneDpekrVLeM/lAsponZpLsd/acJwWdE6Q 11 | cFZ5wfvXMUO7esRHeK/3UrDJ8YyMDcf9hIMS9iq9pGRT9tg9ksK8D0b28bRfHFiq 12 | pNj1Y21uw2javZh3+aFf4Wfgk3b/8vie4pizPrpSIsqzDii1pUxQU2Ll5eteU9p1 13 | Z+ghJrfCKMHaAVFH6M7RZdsJPp+XYyXVKSDK6Lg7L/vNpkz2QxWeh4mFCf6Msh3Z 14 | 4Bu0e2/nj/ADkfwTR1djSXTNaUPrIf37/Es+jhvrE9gbd22gN6GcPZl9E51sSP/J 15 | rgax2FV5JLIhIchBQGZrhvjgNpPQ6hp/lEdRVT/0UtrsSa0PXzRxxhknNst+6n8C 16 | AwEAAaNTMFEwHQYDVR0OBBYEFEozWRxI+XoWBGBRH2M9xOZOSkyzMB8GA1UdIwQY 17 | MBaAFEozWRxI+XoWBGBRH2M9xOZOSkyzMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI 18 | hvcNAQELBQADggIBAEf6XMHfseXc9n71pC5AVadS8daNA6UYkOuSz9Z4QtxATXgu 19 | YxxRJPJVUJuRJSXrIzAgN+aqk3R5h9fLXcMoSFHWXAPkYmt8gXphLL9ucdL290qK 20 | MNGBY7EOtjsG1Pk0ibNNBRW7bzOEg+P3TA6vGkq3BHbnVIMa+b9TLd3ib6Z2WKH+ 21 | zBjWsoYuwyOpqk8c/yPGgyEcqsJugh3IDdBYDsRhl25la3ah05QHZ+SVMMKV0ZMp 22 | FCmcCZpZczbwVNvpBdtst4XK14SG8nJCWXiyyuwvTzGFP0HJhFuLjlHVLniEsuuF 23 | FXu5X8Q35Nbdx9zq9g14KyuhaZwnIxKbhDNu4x/PHOjHK08mJmQzyyHyKfVr9Evh 24 | ER+6Zno/S2IJqIbZt271nDdXtuaARLyjtKXNVPR6ld5iBe+IhmD8LhYo5QZiGIbC 25 | eVkBq+tAdikdIsZ7X1WCC5FGKhrcLchslM3sEuRYzaAUMZrb5Kwe3UqSsEyaUlkA 26 | y6GqE2h8HTs3YVHTE+kNk0YSntzPSoPGdj7DxPXH3ZUsI6G1JY1QGK3vOS/tViA3 27 | r6CkgSMA8oD08YxQsZKZ7VHLdBEuW2qcuET3ZXwO2us4LFYTTu+OgJfEBh2FdloN 28 | bcAuqV6+vwzprubRD+fkyOdwm26SnkJZtEvobuzwOK6MSKfMBlUsAlWRQ8WV 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /server/data/feedback.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "测试用户", 4 | "type": "suggestion", 5 | "content": "测试反馈内容", 6 | "contact": "test@example.com", 7 | "timestamp": "2023-08-15T10:00:00Z" 8 | }, 9 | { 10 | "name": "路由", 11 | "type": "content", 12 | "content": "23455", 13 | "contact": "", 14 | "timestamp": "2025-02-26T12:31:01.658Z" 15 | }, 16 | { 17 | "name": "", 18 | "type": "suggestion", 19 | "content": "23445", 20 | "contact": "", 21 | "timestamp": "2025-02-26T12:31:32.123Z" 22 | }, 23 | { 24 | "name": "测试用户", 25 | "type": "suggestion", 26 | "content": "测试反馈内容", 27 | "contact": "test@example.com", 28 | "timestamp": "2023-08-15T10:00:00Z" 29 | }, 30 | { 31 | "name": "", 32 | "type": "suggestion", 33 | "content": "123124124", 34 | "contact": "", 35 | "timestamp": "2025-02-26T12:39:09.640Z" 36 | }, 37 | { 38 | "name": "", 39 | "type": "suggestion", 40 | "content": "12312312", 41 | "contact": "", 42 | "timestamp": "2025-02-26T12:39:13.221Z" 43 | }, 44 | { 45 | "name": "反馈1", 46 | "type": "suggestion", 47 | "content": "测试反馈信息", 48 | "contact": "li1980303503@gmail.com", 49 | "timestamp": "2025-03-24T07:49:37.205Z", 50 | "id": "6c7419fd-9ebe-47f5-ae79-143c179b39cc" 51 | } 52 | ] -------------------------------------------------------------------------------- /server/data/popular_docs.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": [ 3 | { 4 | "path": "/docs/doc1", 5 | "title": "示例文档 1", 6 | "visits": 126, 7 | "rating": 4.2 8 | }, 9 | { 10 | "path": "/docs/doc2", 11 | "title": "示例文档 2", 12 | "visits": 87, 13 | "rating": 4.7 14 | }, 15 | { 16 | "path": "/docs/doc3", 17 | "title": "示例文档 3", 18 | "visits": 77, 19 | "rating": 4.3 20 | }, 21 | { 22 | "path": "/docs/doc4", 23 | "title": "示例文档 4", 24 | "visits": 115, 25 | "rating": 4.6 26 | }, 27 | { 28 | "path": "/docs/doc5", 29 | "title": "示例文档 5", 30 | "visits": 186, 31 | "rating": 4.7 32 | }, 33 | { 34 | "path": "/docs/doc6", 35 | "title": "示例文档 6", 36 | "visits": 56, 37 | "rating": 4.5 38 | }, 39 | { 40 | "path": "/docs/doc7", 41 | "title": "示例文档 7", 42 | "visits": 66, 43 | "rating": 4.5 44 | }, 45 | { 46 | "path": "/docs/doc8", 47 | "title": "示例文档 8", 48 | "visits": 172, 49 | "rating": 4.5 50 | }, 51 | { 52 | "path": "/docs/doc9", 53 | "title": "示例文档 9", 54 | "visits": 76, 55 | "rating": 4.4 56 | }, 57 | { 58 | "path": "/docs/doc10", 59 | "title": "示例文档 10", 60 | "visits": 164, 61 | "rating": 4.9 62 | } 63 | ] 64 | } -------------------------------------------------------------------------------- /server/data/recommendations.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "1", 4 | "title": "AI基础知识入门", 5 | "description": "了解人工智能的基本概念和应用场景,适合完全没有AI基础的初学者。", 6 | "category": "入门系列", 7 | "tags": ["AI入门", "基础知识"], 8 | "path": "ai-basics" 9 | }, 10 | { 11 | "id": "2", 12 | "title": "Python编程基础", 13 | "description": "学习Python编程的基础知识,为深入学习AI打下基础。", 14 | "category": "编程基础", 15 | "tags": ["Python", "编程基础"], 16 | "path": "python-basics" 17 | }, 18 | { 19 | "id": "3", 20 | "title": "深度学习入门指南", 21 | "description": "深度学习基础概念详解,帮助你理解神经网络的工作原理。", 22 | "category": "进阶知识", 23 | "tags": ["深度学习", "神经网络"], 24 | "path": "deep-learning-intro" 25 | }, 26 | { 27 | "id": "4", 28 | "title": "机器学习模型评估方法", 29 | "description": "学习如何正确评估机器学习模型的性能,避免常见的评估陷阱。", 30 | "category": "实用技巧", 31 | "tags": ["模型评估", "机器学习"], 32 | "path": "model-evaluation" 33 | } 34 | ] -------------------------------------------------------------------------------- /server/data/stats.json: -------------------------------------------------------------------------------- 1 | { 2 | "total_visits": 805, 3 | "unique_visitors": 245, 4 | "avg_daily_visits": 115, 5 | "period_days": 7, 6 | "daily_data": [ 7 | { 8 | "date": "2025-02-20", 9 | "total_visits": 165, 10 | "unique_visitors": 87 11 | }, 12 | { 13 | "date": "2025-02-21", 14 | "total_visits": 62, 15 | "unique_visitors": 88 16 | }, 17 | { 18 | "date": "2025-02-22", 19 | "total_visits": 96, 20 | "unique_visitors": 48 21 | }, 22 | { 23 | "date": "2025-02-23", 24 | "total_visits": 106, 25 | "unique_visitors": 93 26 | }, 27 | { 28 | "date": "2025-02-24", 29 | "total_visits": 112, 30 | "unique_visitors": 37 31 | }, 32 | { 33 | "date": "2025-02-25", 34 | "total_visits": 125, 35 | "unique_visitors": 70 36 | }, 37 | { 38 | "date": "2025-02-26", 39 | "total_visits": 139, 40 | "unique_visitors": 67 41 | } 42 | ], 43 | "last_updated": "2025-02-26T21:17:35.910446" 44 | } -------------------------------------------------------------------------------- /server/data/updates.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "5", 4 | "title": "系统全面优化与心理书籍资源上线", 5 | "description": "我们对AI Library进行了全面的性能优化,并新增了300本心理学书籍资源,进一步丰富了平台内容。", 6 | "date": "2025-04-15T10:00:00.000Z", 7 | "changes": [ 8 | "优化Markdown渲染性能,使用增量代码高亮和缓存策略", 9 | "改进图片处理,实现图片懒加载和移除图片名称显示", 10 | "优化文档内容读取与缓存机制,提升加载速度", 11 | "添加HTTP压缩优化,减少网络传输量", 12 | "修复移动端文档显示问题,优化沉浸模式下的阅读体验", 13 | "改进进度条功能,提供更平滑的滚动体验", 14 | "修复搜索服务连接与错误处理问题", 15 | "新增300本心理学经典书籍,涵盖认知心理学、发展心理学和临床心理学等领域", 16 | "提升系统整体稳定性和响应速度" 17 | ], 18 | "important": true 19 | }, 20 | { 21 | "id": "1", 22 | "title": "AI Library 1.0 发布", 23 | "description": "我们很高兴地宣布 AI Library 1.0 正式发布!", 24 | "date": "2025-01-26T10:00:00.000Z", 25 | "changes": [ 26 | "支持Markdown文档阅读", 27 | "树形目录结构浏览", 28 | "支持深色模式", 29 | "响应式设计,支持手机和平板浏览" 30 | ], 31 | "important": true 32 | }, 33 | { 34 | "id": "2", 35 | "title": "新增公告板功能", 36 | "description": "现在您可以通过公告板了解最新的更新和推荐内容,并向我们提供反馈。", 37 | "date": "2025-02-27T10:00:00.000Z", 38 | "changes": [ 39 | "添加项目更新通知", 40 | "内容推荐功能", 41 | "用户反馈收集" 42 | ], 43 | "important": true 44 | }, 45 | { 46 | "id": "3", 47 | "title": "UI 界面全面升级与功能优化", 48 | "description": "我们对 AI Library 进行了全面的界面升级和功能优化,提供更加现代化的用户体验。", 49 | "date": "2025-03-12T10:00:00.000Z", 50 | "changes": [ 51 | "全新 Apple 风格 UI 设计,包括毛玻璃效果和圆角卡片", 52 | "搜索功能优化,移除建议功能,直接显示搜索结果", 53 | "统一暗色模式样式,提升视觉一致性", 54 | "改进表单元素和输入框样式,优化交互体验", 55 | "搜索结果页面重新设计,提供更清晰的结果展示", 56 | "文档阅读体验优化,支持 PDF 文件查看", 57 | "阅读控制面板增强,支持自定义字体大小和行高" 58 | ], 59 | "important": true 60 | }, 61 | { 62 | "id": "4", 63 | "title": "搜索引擎升级与海量内容更新", 64 | "description": "我们为 AI Library 引入了基于 Rust 的 Meilisearch 搜索引擎,并更新了大量高质量 AI 学习资源和面试资料。", 65 | "date": "2025-03-24T10:00:00.000Z", 66 | "changes": [ 67 | "引入 Meilisearch 搜索引擎,提供更快、更准确的检索体验", 68 | "新增在线人数实时展示功能,了解平台活跃度", 69 | "更新知识星球付费文章 400 篇,涵盖商业、经济、财产等", 70 | "新增大模型相关面试题 300 篇,包含面试技巧、RAG、Agent 实操、微调预训练等内容", 71 | "提供面试资料和实践指南源文件下载功能", 72 | "导航支持分层加载,优化性能,提升用户体验" 73 | ], 74 | "important": true 75 | } 76 | ] -------------------------------------------------------------------------------- /server/data/visits.json: -------------------------------------------------------------------------------- 1 | { 2 | "daily_visits": {}, 3 | "daily_visitors": {}, 4 | "doc_visits": {} 5 | } -------------------------------------------------------------------------------- /server/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | mgTohLYQnje6sR6RWoPzqly920f5UQ== 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": {} 6 | } 7 | -------------------------------------------------------------------------------- /server/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.104.1 2 | uvicorn[standard]==0.24.0 3 | h11==0.14.0 4 | h2==4.1.0 5 | httptools==0.6.1 6 | python-multipart==0.0.6 7 | pydantic==2.5.2 8 | aiofiles==23.2.1 9 | python-jose[cryptography]==3.3.0 10 | passlib[bcrypt]==1.7.4 11 | watchdog==3.0.0 12 | psutil==5.9.6 13 | PyPDF2==3.0.1 14 | python-magic==0.4.27 15 | hypercorn==0.15.0 16 | PyMuPDF==1.23.5 17 | meilisearch-python-async==1.8.1 -------------------------------------------------------------------------------- /server/run_h2.py: -------------------------------------------------------------------------------- 1 | import os 2 | import asyncio 3 | from hypercorn.config import Config 4 | from hypercorn.asyncio import serve 5 | import logging 6 | 7 | # 配置日志 8 | logging.basicConfig(level=logging.DEBUG) 9 | logger = logging.getLogger('hypercorn.error') 10 | 11 | config = Config() 12 | config.bind = ["0.0.0.0:8000"] 13 | config.worker_class = "uvloop" # 使用 uvloop 14 | config.use_reloader = True # 启用热重载 15 | config.accesslog = "-" # 输出访问日志到 stdout 16 | config.errorlog = logger # 使用自定义的错误日志处理器 17 | 18 | # 配置SSL/HTTPS 19 | cert_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "certs") 20 | config.certfile = os.path.join(cert_dir, "cert.pem") 21 | config.keyfile = os.path.join(cert_dir, "key.pem") 22 | 23 | # 如果证书文件不存在,则输出警告 24 | if not os.path.exists(config.certfile) or not os.path.exists(config.keyfile): 25 | logger.warning(f"SSL证书文件不存在: {config.certfile} 或 {config.keyfile}") 26 | logger.warning("使用以下命令生成自签名证书:") 27 | logger.warning("mkdir -p certs && openssl req -x509 -newkey rsa:4096 " 28 | f"-keyout {config.keyfile} -out {config.certfile} -days 365 -nodes") 29 | raise FileNotFoundError("SSL证书文件不存在") 30 | 31 | # 启用HTTPS 32 | config.scheme = "https" 33 | logger.info(f"服务器将使用HTTPS启动,监听端口 {config.bind[0]}") 34 | 35 | # 错误处理装饰器 36 | def handle_errors(func): 37 | async def wrapper(*args, **kwargs): 38 | try: 39 | return await func(*args, **kwargs) 40 | except Exception as e: 41 | if isinstance(e, KeyError) and str(e) == '1': 42 | # 忽略 stream 1 的错误(通常是客户端断开连接) 43 | logger.debug("Client disconnected, stream 1 not found") 44 | else: 45 | logger.exception("Unexpected error occurred") 46 | return None 47 | return wrapper 48 | 49 | # 启动服务器 50 | if __name__ == "__main__": 51 | from app.main import app 52 | # 包装应用以处理错误 53 | @handle_errors 54 | async def wrapped_app(*args, **kwargs): 55 | return await app(*args, **kwargs) 56 | 57 | asyncio.run(serve(wrapped_app, config)) -------------------------------------------------------------------------------- /server/ssl/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFCTCCAvGgAwIBAgIUSTAqQgY84CsmZh5Gkun1/M6ILRkwDQYJKoZIhvcNAQEL 3 | BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDMxMzAzMzUyNVoXDTI2MDMx 4 | MzAzMzUyNVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF 5 | AAOCAg8AMIICCgKCAgEAvT9mmpVl1UHNV9CTKaXbaQsJgoIP5MlB4SidiKjhlotR 6 | Oks5FUtCtAiiPnbYQ3FatE5EukVudUx9eEwkqIZeVxPiwaQEArRthqzfJd/RgEaF 7 | j5XJapD1Eih7jimMtF9ekoA7njs949OO4J8BpjZ6APh5VF8qFOeaI0xZMTX5E0jB 8 | v+WaNhn8btM77A2CDqfzwremjq6IMBEiy3Zp+BeW5XPC6Rd1uPbyQWW4xXRgsra7 9 | 5j3gHfC6TKD1IBQfQOwI4Mid5WFgVA2i2Rtcve8PIhI+ZF6o1QW8jysKXxB0F7h0 10 | W0PCsLBqsvXCx/5VYGCi3LVagCe7bkx2Fpwi+4jd1+1XYQar6YFYo1Lw15GR5y7B 11 | C0WPJiWQ/FMN5vgwTjmnYp08j6RrGHlp2SmdecCZ5VuVgoQzOsIxIYGutHPyOyzs 12 | wguZSPHkiw/GAJfpNCQOvhWsxUQS+v8hxVJwHaL98OrHqchg0eKgiUpwAXarUa6w 13 | 1ou0pmSoSPzyQIL659n4pSsRCs16OgrlolpOoFYyuZuDUIrqTAXBymObWcChYi75 14 | n4ncg4zwuHsxLKFabhWKVSMxUJQtpTwXO70jdK1okBL3lIWOiJjZTIv23g5+CB1V 15 | 2D4A+olN9VHV28Kyc/cp++HHE9xROVvfU1605P35sfcV+Qi1kZqZKCXxJad7g28C 16 | AwEAAaNTMFEwHQYDVR0OBBYEFAzN1UcGfHDe/CujrR4ou/jlHU0OMB8GA1UdIwQY 17 | MBaAFAzN1UcGfHDe/CujrR4ou/jlHU0OMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI 18 | hvcNAQELBQADggIBAJUAFmKuLJ8TFORdCCP7Ku6yG11IbKgdt7i42a0aJvbdj+9y 19 | VA8V6FtcvUlq12SZxPr9hfP1nD0V+wzpyqLHR+ggzQpInJyNRN4Py7iTJUYmfpWr 20 | OmIh5Uww/uwG4WB9JoYKCKp611Jql0AxwM8lFtRCbmI9u7lqnUD0Va35+58UwbuS 21 | qqnmYw5SZna60CExTsOo/mS4yv/pajdydIRqt+tb4n3GD+/sNay6FyUb0uWuM1IR 22 | dY2yVuohdBsJKmtaw31vH/NXO2Gzo4jzZt7NiyBm/XQlOIcXYGQNGdcEZzMr3tNR 23 | 84fDtq3H6I/ywbjSt5Db/T2ZoMXaijFbe+hzv1jgFzMJgkLtFYtq9J++aLjurz51 24 | kLciA5olePM3XHSc5xqB6RvXE8CrYJsLWCB9FF177WWtFL67bNXO4f/b5up+w92f 25 | Yt8LAW2C5GQ/LH7lO8CeYhQee1r7So+NaZ9T4fZcAW10oVxIbNUzA8U55YO5qj/o 26 | /44Fi9Or4Ir3ja3XQZwdlJNkOcLJPgYmmNRi4QzYeWIfZqJG1sFGdf9dY6YelDFv 27 | 7LxIAKafNfe7TDQR0f3rnf5yYbCPL1G/maVILeD/St5pCUOKciysqezMDRKjloye 28 | OvAcUG4/kGkiDmmK4Txe3DWUScLPcUTd8qYGaRZ78mWHhNdDL8vx5mbm7deA 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /server/ssl/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | /K2wVBOqTIcTzE/q8U/C2kNc5sjkNw== 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /server/start_with_meilisearch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 输出带颜色的文字 4 | GREEN='\033[0;32m' 5 | YELLOW='\033[1;33m' 6 | NC='\033[0m' # No Color 7 | 8 | echo -e "${GREEN}启动 MeiliSearch 服务...${NC}" 9 | docker-compose up -d meilisearch 10 | 11 | # 等待 MeiliSearch 启动 12 | echo -e "${YELLOW}等待 MeiliSearch 启动 (10秒)...${NC}" 13 | sleep 10 14 | 15 | # 设置环境变量 16 | export MEILISEARCH_HOST="http://localhost:7700" 17 | export MEILISEARCH_API_KEY="masterKey" 18 | 19 | # 进入服务器目录 20 | cd server 21 | 22 | # 启动后端服务器 23 | echo -e "${GREEN}启动后端服务器...${NC}" 24 | python run_h2.py -------------------------------------------------------------------------------- /server/static/stats/popular_docs.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": [ 3 | { 4 | "path": "/docs/doc1", 5 | "title": "示例文档 1", 6 | "visits": 82, 7 | "rating": 4.8 8 | }, 9 | { 10 | "path": "/docs/doc2", 11 | "title": "示例文档 2", 12 | "visits": 107, 13 | "rating": 5.0 14 | }, 15 | { 16 | "path": "/docs/doc3", 17 | "title": "示例文档 3", 18 | "visits": 144, 19 | "rating": 4.3 20 | }, 21 | { 22 | "path": "/docs/doc4", 23 | "title": "示例文档 4", 24 | "visits": 98, 25 | "rating": 4.8 26 | }, 27 | { 28 | "path": "/docs/doc5", 29 | "title": "示例文档 5", 30 | "visits": 122, 31 | "rating": 4.6 32 | }, 33 | { 34 | "path": "/docs/doc6", 35 | "title": "示例文档 6", 36 | "visits": 139, 37 | "rating": 4.2 38 | }, 39 | { 40 | "path": "/docs/doc7", 41 | "title": "示例文档 7", 42 | "visits": 193, 43 | "rating": 4.2 44 | }, 45 | { 46 | "path": "/docs/doc8", 47 | "title": "示例文档 8", 48 | "visits": 56, 49 | "rating": 4.8 50 | }, 51 | { 52 | "path": "/docs/doc9", 53 | "title": "示例文档 9", 54 | "visits": 94, 55 | "rating": 5.0 56 | }, 57 | { 58 | "path": "/docs/doc10", 59 | "title": "示例文档 10", 60 | "visits": 79, 61 | "rating": 4.2 62 | } 63 | ] 64 | } -------------------------------------------------------------------------------- /server/static/stats/stats.json: -------------------------------------------------------------------------------- 1 | { 2 | "total_visits": 1994, 3 | "unique_visitors": 792, 4 | "avg_daily_visits": 285, 5 | "bounce_rate": 32.3, 6 | "daily_data": [ 7 | { 8 | "date": "2025-03-21", 9 | "total_visits": 135, 10 | "unique_visitors": 81, 11 | "avg_duration": 213, 12 | "bounce_rate": 37.9 13 | }, 14 | { 15 | "date": "2025-03-20", 16 | "total_visits": 200, 17 | "unique_visitors": 150, 18 | "avg_duration": 169, 19 | "bounce_rate": 33.5 20 | }, 21 | { 22 | "date": "2025-03-19", 23 | "total_visits": 334, 24 | "unique_visitors": 59, 25 | "avg_duration": 62, 26 | "bounce_rate": 28.2 27 | }, 28 | { 29 | "date": "2025-03-18", 30 | "total_visits": 232, 31 | "unique_visitors": 65, 32 | "avg_duration": 213, 33 | "bounce_rate": 31.6 34 | }, 35 | { 36 | "date": "2025-03-17", 37 | "total_visits": 381, 38 | "unique_visitors": 159, 39 | "avg_duration": 165, 40 | "bounce_rate": 37.8 41 | }, 42 | { 43 | "date": "2025-03-16", 44 | "total_visits": 377, 45 | "unique_visitors": 81, 46 | "avg_duration": 181, 47 | "bounce_rate": 33.6 48 | }, 49 | { 50 | "date": "2025-03-15", 51 | "total_visits": 335, 52 | "unique_visitors": 197, 53 | "avg_duration": 256, 54 | "bounce_rate": 23.7 55 | } 56 | ] 57 | } -------------------------------------------------------------------------------- /server/static/stats/visits.json: -------------------------------------------------------------------------------- 1 | { 2 | "visits": [] 3 | } -------------------------------------------------------------------------------- /server/test_meili.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from meilisearch_python_sdk import AsyncClient 3 | import asyncio 4 | 5 | async def test(): 6 | async with AsyncClient('http://localhost:7700', 'masterKey') as client: 7 | # 测试健康状态 8 | print("\n=== 测试健康状态 ===") 9 | health = await client.health() 10 | print(f'Health Status: {health.status}') 11 | 12 | # 测试索引操作 13 | print("\n=== 测试索引操作 ===") 14 | index_name = "documents" 15 | try: 16 | # 获取或创建索引 17 | indexes = await client.get_indexes() 18 | print(f"获取到的索引列表: {indexes}") 19 | 20 | # 检查索引是否存在 21 | index_exists = False 22 | if indexes: 23 | index_exists = any(index.uid == index_name for index in indexes) 24 | 25 | if not index_exists: 26 | print(f"创建索引: {index_name}") 27 | await client.create_index(index_name) 28 | 29 | index = await client.get_index(index_name) 30 | print(f"获取到索引: {index_name}") 31 | 32 | # 设置可过滤属性 33 | print("\n设置可过滤属性...") 34 | await index.update_filterable_attributes(['type']) 35 | 36 | # 设置可排序属性 37 | print("\n设置可排序属性...") 38 | await index.update_sortable_attributes(['name']) 39 | 40 | # 添加测试文档 41 | test_docs = [ 42 | { 43 | "id": "test1", 44 | "name": "测试文档1.md", 45 | "content": "这是一个测试文档的内容", 46 | "type": "md" 47 | }, 48 | { 49 | "id": "test2", 50 | "name": "测试文档2.md", 51 | "content": "这是另一个测试文档", 52 | "type": "md" 53 | } 54 | ] 55 | 56 | print("\n添加测试文档...") 57 | task = await index.add_documents(test_docs) 58 | print("等待索引更新...") 59 | await client.wait_for_task(task.task_uid) # 使用内置的 wait_for_task 60 | 61 | # 测试基本搜索 62 | print("\n=== 测试基本搜索 ===") 63 | query = "测试" 64 | print(f"\n1. 使用字符串查询: search('{query}')") 65 | # 将查询字符串作为第一个位置参数传递 66 | results = await index.search(query) 67 | print(f"结果内容: {results}") 68 | 69 | # 测试带选项的搜索 70 | print("\n2. 使用查询和选项") 71 | print(f"搜索参数: limit=5, offset=0, attributes_to_retrieve=['id', 'name', 'content', 'type']") 72 | results = await index.search( 73 | query, # 查询字符串作为第一个位置参数 74 | limit=5, 75 | offset=0, 76 | attributes_to_retrieve=["id", "name", "content", "type"] 77 | ) 78 | print(f"结果内容: {results}") 79 | 80 | # 测试不同的搜索选项组合 81 | print("\n3. 测试不同的搜索选项组合") 82 | 83 | # 测试带过滤的搜索 84 | print("\n3.1 带过滤的搜索: filter='type = md'") 85 | results = await index.search( 86 | query, # 查询字符串作为第一个位置参数 87 | filter="type = md", 88 | limit=5, 89 | attributes_to_retrieve=["id", "name", "content", "type"] 90 | ) 91 | print(f"过滤搜索结果: {results}") 92 | 93 | # 测试带排序的搜索 94 | print("\n3.2 带排序的搜索: sort=['name:asc']") 95 | results = await index.search( 96 | query, # 查询字符串作为第一个位置参数 97 | sort=["name:asc"], 98 | limit=5, 99 | attributes_to_retrieve=["id", "name", "content", "type"] 100 | ) 101 | print(f"排序搜索结果: {results}") 102 | 103 | # 清理测试数据 104 | print("\n=== 清理测试数据 ===") 105 | task = await index.delete_documents(['test1', 'test2']) 106 | await client.wait_for_task(task.task_uid) 107 | print("测试文档已删除") 108 | 109 | except Exception as e: 110 | print(f"测试过程中出错: {str(e)}") 111 | import traceback 112 | traceback.print_exc() 113 | 114 | if __name__ == "__main__": 115 | asyncio.run(test()) -------------------------------------------------------------------------------- /server/软链.md: -------------------------------------------------------------------------------- 1 | # ln -s /Users/mod/PycharmProjects/downloaded_content server/static/docs -------------------------------------------------------------------------------- /start_services.ps1: -------------------------------------------------------------------------------- 1 | # 激活Python虚拟环境 2 | .\py310\Scripts\Activate.ps1 3 | 4 | # 设置环境变量 5 | $env:PYTHONPATH = "D:\work\AI-Library-main\server" 6 | 7 | Write-Host "Starting backend service..." 8 | # 启动后端服务 9 | Start-Process -FilePath "python" -ArgumentList "server\run.py" -NoNewWindow 10 | 11 | Write-Host "Starting frontend service..." 12 | # 启动前端服务 13 | Push-Location -Path "client" 14 | Start-Process -FilePath "npm" -ArgumentList "run preview" -NoNewWindow 15 | Pop-Location 16 | 17 | Write-Host "Starting Cloudflare tunnel..." 18 | # 启动Cloudflare隧道 19 | Start-Service -Name Cloudflared 20 | 21 | Write-Host "All services started!" 22 | Write-Host "Frontend: https://localhost:4173" 23 | Write-Host "Backend: https://localhost:8000" -------------------------------------------------------------------------------- /tools/fix_image_paths.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | from pathlib import Path 4 | 5 | def fix_image_paths(docs_dir): 6 | """Fix image paths in markdown files to use relative paths correctly.""" 7 | docs_path = Path(docs_dir) 8 | 9 | # Regular expression to match markdown image syntax 10 | img_pattern = re.compile(r'!\[([^\]]*)\]\(images/([^)]+)\)') 11 | 12 | # Walk through all directories 13 | for root, _, files in os.walk(docs_path): 14 | root_path = Path(root) 15 | 16 | # Only process markdown files 17 | for file in files: 18 | if not file.endswith('.md'): 19 | continue 20 | 21 | file_path = root_path / file 22 | 23 | # Calculate relative path to images directory 24 | relative_to_root = os.path.relpath(docs_path, root_path) 25 | new_image_path = os.path.join(relative_to_root, 'images') 26 | 27 | # Read the file content 28 | try: 29 | with open(file_path, 'r', encoding='utf-8') as f: 30 | content = f.read() 31 | 32 | # Replace image paths 33 | new_content = img_pattern.sub( 34 | rf'![\1]({new_image_path}/\2)', 35 | content 36 | ) 37 | 38 | # Only write if content changed 39 | if new_content != content: 40 | print(f'Fixing image paths in {file_path}') 41 | with open(file_path, 'w', encoding='utf-8') as f: 42 | f.write(new_content) 43 | 44 | except Exception as e: 45 | print(f'Error processing {file_path}: {e}') 46 | 47 | if __name__ == '__main__': 48 | docs_dir = 'server/static/docs/极客时间' 49 | fix_image_paths(docs_dir) -------------------------------------------------------------------------------- /tools/llm_api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env /workspace/tmp_windsurf/py310/bin/python3 2 | 3 | from openai import OpenAI 4 | import argparse 5 | 6 | def create_llm_client(): 7 | client = OpenAI( 8 | base_url="https://api.deepseek.com", 9 | api_key="sk-1f7931b1fce2474bbd36807ebeb48f3f" 10 | ) 11 | return client 12 | 13 | def query_llm(prompt, client=None, model="deepseek-chat"): 14 | if client is None: 15 | client = create_llm_client() 16 | 17 | try: 18 | response = client.chat.completions.create( 19 | model=model, 20 | messages=[ 21 | {"role": "user", "content": prompt} 22 | ], 23 | temperature=0.7, 24 | ) 25 | return response.choices[0].message.content 26 | except Exception as e: 27 | print(f"Error querying LLM: {e}") 28 | return None 29 | 30 | def main(): 31 | parser = argparse.ArgumentParser(description='Query an LLM with a prompt') 32 | parser.add_argument('--prompt', type=str, help='The prompt to send to the LLM', required=True) 33 | parser.add_argument('--model', type=str, default="deepseek-chat", 34 | help='The model to use (default: deepseek-chat)') 35 | args = parser.parse_args() 36 | 37 | client = create_llm_client() 38 | response = query_llm(args.prompt, client, model=args.model) 39 | if response: 40 | print(response) 41 | else: 42 | print("Failed to get response from LLM") 43 | 44 | if __name__ == "__main__": 45 | main() 46 | -------------------------------------------------------------------------------- /tools/search_engine.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import sys 5 | import traceback 6 | from duckduckgo_search import DDGS 7 | 8 | def search(query, max_results=10): 9 | """ 10 | Search using DuckDuckGo and return results with URLs and text snippets. 11 | Uses the HTML backend which has proven to be more reliable. 12 | 13 | Args: 14 | query (str): Search query 15 | max_results (int): Maximum number of results to return 16 | """ 17 | try: 18 | print(f"DEBUG: Searching for query: {query}", file=sys.stderr) 19 | 20 | with DDGS() as ddgs: 21 | results = list(ddgs.text( 22 | query, 23 | max_results=max_results, 24 | backend='html' # Use only the HTML backend 25 | )) 26 | 27 | if not results: 28 | print("DEBUG: No results found", file=sys.stderr) 29 | return 30 | 31 | print(f"DEBUG: Found {len(results)} results", file=sys.stderr) 32 | 33 | for i, r in enumerate(results, 1): 34 | print(f"\n=== Result {i} ===") 35 | print(f"URL: {r.get('link', r.get('href', 'N/A'))}") 36 | print(f"Title: {r.get('title', 'N/A')}") 37 | print(f"Snippet: {r.get('snippet', r.get('body', 'N/A'))}") 38 | 39 | except Exception as e: 40 | print(f"ERROR: Search failed: {str(e)}", file=sys.stderr) 41 | print(f"ERROR type: {type(e)}", file=sys.stderr) 42 | traceback.print_exc(file=sys.stderr) 43 | sys.exit(1) 44 | 45 | def main(): 46 | parser = argparse.ArgumentParser(description="Search using DuckDuckGo API") 47 | parser.add_argument("query", help="Search query") 48 | parser.add_argument("--max-results", type=int, default=10, 49 | help="Maximum number of results (default: 10)") 50 | 51 | args = parser.parse_args() 52 | search(args.query, args.max_results) 53 | 54 | if __name__ == "__main__": 55 | main() -------------------------------------------------------------------------------- /tools/split_articles.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import re 4 | from pathlib import Path 5 | 6 | def ensure_dir(directory): 7 | """确保目录存在,如果不存在则创建""" 8 | Path(directory).mkdir(parents=True, exist_ok=True) 9 | 10 | def sanitize_filename(filename): 11 | """清理文件名,移除不合法字符""" 12 | # 替换Windows和Unix系统都不支持的文件名字符 13 | filename = re.sub(r'[<>:"/\\|?*]', '', filename) 14 | # 移除前后空格 15 | filename = filename.strip() 16 | # 确保文件名不为空 17 | return filename if filename else 'untitled' 18 | 19 | def split_markdown(input_file): 20 | """将markdown文件按章节拆分""" 21 | try: 22 | with open(input_file, 'r', encoding='utf-8') as f: 23 | content = f.read() 24 | except Exception as e: 25 | print(f"Error reading file {input_file}: {e}") 26 | return 27 | 28 | # 获取文件夹名(使用原文件名,不包含扩展名) 29 | folder_name = os.path.splitext(os.path.basename(input_file))[0] 30 | base_dir = os.path.dirname(input_file) 31 | output_dir = os.path.join(base_dir, folder_name) 32 | 33 | # 创建输出目录 34 | ensure_dir(output_dir) 35 | 36 | # 使用正则表达式匹配标题 37 | # 匹配 # 开头的标题(一级标题) 38 | chapters = re.split(r'\n(?=# (?![#]))', content) 39 | 40 | # 处理每个章节 41 | for chapter in chapters: 42 | if not chapter.strip(): 43 | continue 44 | 45 | # 提取章节标题 46 | title_match = re.match(r'# (.*?)(?:\n|$)', chapter) 47 | if title_match: 48 | title = title_match.group(1).strip() 49 | # 清理文件名 50 | filename = sanitize_filename(title) 51 | 52 | # 计算到 images 目录的相对路径 53 | relative_to_root = os.path.relpath(base_dir, output_dir) 54 | images_path = os.path.join(relative_to_root, 'images') 55 | 56 | # 替换图片路径 57 | chapter = re.sub( 58 | r'!\[([^\]]*)\]\(images/([^)]+)\)', 59 | rf'![\1]({images_path}/\2)', 60 | chapter 61 | ) 62 | 63 | # 创建文件 64 | output_file = os.path.join(output_dir, f"{filename}.md") 65 | try: 66 | with open(output_file, 'w', encoding='utf-8') as f: 67 | f.write(chapter.strip() + '\n') 68 | print(f"Created: {output_file}") 69 | except Exception as e: 70 | print(f"Error writing file {output_file}: {e}") 71 | 72 | def process_directory(directory): 73 | """处理指定目录下的所有markdown文件""" 74 | for root, _, files in os.walk(directory): 75 | for file in files: 76 | if file.endswith('.md'): 77 | input_file = os.path.join(root, file) 78 | print(f"\nProcessing: {input_file}") 79 | split_markdown(input_file) 80 | 81 | if __name__ == '__main__': 82 | # 处理 server/static/docs/极客时间 目录下的所有markdown文件 83 | docs_dir = 'server/static/docs/极客时间' 84 | process_directory(docs_dir) --------------------------------------------------------------------------------