# JMcomic-copy **Repository Path**: zfz2005/jmcomic-copy ## Basic Information - **Project Name**: JMcomic-copy - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-23 - **Last Updated**: 2026-08-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # JM-Web1.5.0 JM-Web 是一个本地运行的漫画浏览与阅读项目,仓库包含浏览器版和 Windows Electron 桌面版两套源码。项目通过第三方上游服务获取漫画、章节、图片和账号收藏数据;本地收藏、历史、书架、下载和缓存保存在用户自己的设备上。 > 本项目为个人学习和研究用途。第三方服务、漫画内容、图片 CDN、账号登录和 API线路均不由本项目保证稳定性。使用者必须自行遵守所在地法律法规、第三方服务条款和年龄限制。 ## 目录 - [功能概览](#功能概览) - [仓库结构](#仓库结构) - [环境要求](#环境要求) - [Web 浏览器版](#web-浏览器版) - [Desktop Windows版](#desktop-windows-版) - [数据目录和文件位置](#数据目录和文件位置) - [本地备份格式](#本地备份格式) - [API 接口](#api-接口) - [实现方法和安全边界](#实现方法和安全边界) - [测试与构建](#测试与构建) - [源码仓库上传边界](#源码仓库上传边界) - [免责声明](#免责声明) # 功能概览 ## 内容浏览与阅读 - 首页推荐、关键词搜索、JM车号直达、分类和周榜浏览。 - 漫画详情、章节列表、作者/标签/关联作品和评论展示。 - 连续纵向阅读、横向 LTR 阅读、横向 RTL 阅读和画廊阅读。 - 上一章、下一章、章节选择和返回来源页。 - 阅读历史记录当前漫画、章节 ID、章节标题和阅读时间。 - 详情页和收藏页高亮上次阅读章节。 - 图片使用当前 CDN 和漫画 ID 动态重建,避免长期保存失效的旧封面地址。 ## 本地数据 - 本地收藏夹、收藏夹内漫画、浏览历史和本地书架。 - 书架支持章节和图片离线保存,普通下载与 ZIP 主动导出分开存放。 - 收藏列表和书架支持关键词模糊查询与标签分类筛选。 - 收藏和历史可以导出为一个 JSON 文件,也可以导入到新设备。 - 导入时根据漫画 ID重新请求标题、作者、标签和当前封面;不存在的收藏夹会自动创建。 - 本地漫画元数据使用内存缓存和磁盘缓存,缓存可以刷新、统计或完全清除。 - 清除缓存不会删除收藏、历史、书架、下载、设置、会话或账号凭据。 ## 云端账号功能 - 登录、退出、登录状态恢复、云端收藏、收藏夹、点赞、评论和签到。 - 云端收藏可以选择多个自定义收藏夹,不会隐式加入默认收藏夹。 - 未登录状态下右上角仍保留用户菜单:API线路、本地收藏、本地书架、本地缓存和登录入口可用。 - 未登录时“收藏”默认进入本地收藏,云端收藏按钮不可用,也不会因为浏览云端收藏自动弹出登录窗口。 - 只有用户主动点击菜单中的“登录”按钮才会打开登录界面。 ## API线路和加载体验 - 当前内置4 条 API线路: - `www.cdnhjk.net` - `www.cdngwc.cc` - `www.cdngwc.net` - `www.cdngwc.club` - 头像菜单可以刷新线路、查看线路健康状态并手动选择线路。 - API 请求失败时区分线路故障和登录失效,网络故障不会被误报为“请先登录”。 - 云端收藏分页使用最多6 个并发 Worker,单页故障会被记录为失败页而不是直接中断全部结果。 - 自动登录恢复使用 single-flight,同一时间只执行一次恢复请求。 - 页面路由使用 AbortController 和渲染代次保护,快速切换页面时丢弃旧请求结果。 - 首页横向内容使用横向滚动,进度条支持点击、触摸和 Pointer Events 拖动。 - 阅读器进度条根据纵向、横向、RTL 和画廊模式实时计算并刷新。 # 仓库结构 ```text jmcomic-copy/ ├── README.md # 项目使用、数据目录、API 和构建说明 ├── PROJECT-SUMMARY.md # 当前项目实现总结和文件索引 ├── .gitignore #运行数据、依赖和构建产物排除规则 ├── web/ # 浏览器版源码 │ ├── package.json # Node版本和 Web 脚本 │ ├── package-lock.json # Web依赖锁定文件 │ ├── server.js # 本地 HTTP 服务、远程 API 和图片代理 │ ├── data-paths.js # Web 数据目录定义 │ ├── data-lock.js # Web 并发写入锁 │ ├── file-store.js # 本地 JSON/图片分类存储 │ ├── data-cleanup.js # 缓存和更新临时文件清理 │ ├── data-cleanup-cli.js # npm run clear-cache入口 │ ├── public/index.html # 页面壳和资源加载顺序 │ ├── public/css/style.css # 页面、菜单、滚动条和阅读器样式 │ ├── public/js/app.js # SPA 路由、视图、登录、收藏、阅读器和 AI │ ├── public/js/db.js # 本地数据 API适配器 │ ├── public/js/zipper.js # 用户主动导出章节/漫画 ZIP │ └── docs/ # Web API、前端和打包说明 └── desktop/ # Windows Electron版源码 ├── package.json # Electron 和构建脚本 ├── package-lock.json # Desktop依赖锁定文件 ├── src/main/index.js # 主进程、IPC、下载和生命周期 ├── src/main/window.js # BrowserWindow 安全选项 ├── src/main/protocol.js # jm-app://app 自定义协议 ├── src/main/storage.js # 安装版、Portable 和开发版数据根目录 ├── src/main/menu.js # 应用菜单和缓存操作 ├── src/main/tray.js # 系统托盘操作 ├── src/main/updater.js # 更新清单和 SHA-256 校验 ├── src/main/logger.js # 脱敏日志 ├── src/preload/index.js # contextIsolation 白名单桥接 ├── src/service/api-router.js # Desktop API 请求路由和限制 ├── src/service/app-service.js # Desktop业务服务和本地 API ├── src/service/upstream-client.js # 上游鉴权、解密、线路轮转和 CDN ├── src/service/data-store.js # 收藏、历史、书架和本地元数据 ├── src/service/data-paths.js # Desktop 分类数据路径 ├── src/service/data-cleanup.js # 缓存和更新临时文件清理 ├── src/service/session-store.js # safeStorage/Windows DPAPI 会话存储 ├── src/service/image-proxy.js # HTTPS 图片 CDN 白名单代理 ├── src/service/static-assets.js # 静态资源和路径安全检查 ├── resources/public/ # Desktop 内置的前端资源副本 ├── build/ # 图标、检查、构建和哈希脚本 ├── tests/ # 核心路由、存储和缓存测试 └── docs/ # Desktop API、安全和打包说明 ``` `web/public/` 和 `desktop/resources/public/` 是两套独立的前端资源。修改 Web 前端后必须同步 Desktop 副本,并分别执行语法检查。 # 环境要求 | 工程 | 要求 | |---|---| | Web | Node.js `>=18.14`,Chrome/Edge 等现代浏览器 | | Desktop | Windows x64、Node.js `>=18.14`、Electron `38.8.6`、electron-builder `26.15.3` | | Android | 当前未创建 Android 工程,仅保留未来规划,不提供 APK | Web 和 Desktop 分别管理依赖,仓库根目录没有必须执行的 npm 命令。 # Web 浏览器版 ## 安装和启动 ```bash cd web npm install npm start ``` 默认访问地址: ```text http://127.0.0.1:3000 ``` 如果端口被占用,服务会继续尝试后续端口,最高到 `3010`。也可以显式指定端口: ```bash PORT=3100 npm start ``` Windows PowerShell: ```powershell cd web $env:PORT = "3100" npm start ``` 启动后使用 Chrome、Edge 或其他现代浏览器打开终端显示的地址。服务默认只绑定本机回环地址,不作为公网服务器使用。 ## Web 命令 ```bash cd web npm start # 启动本地 Web 服务 npm run check # 检查 server.js语法 npm run clear-cache # 清理 Web 缓存和更新临时文件 ``` 停止服务时在终端按 `Ctrl+C`。如果需要确认端口占用,可以在 Windows PowerShell 中执行: ```powershell Get-NetTCPConnection -LocalPort 3000,3001,3010 -ErrorAction SilentlyContinue ``` # Desktop Windows版 ## 开发启动 ```bash cd desktop npm install npm test npm run check npm start ``` Desktop 使用 Electron 自定义协议: ```text jm-app://app/index.html ``` 生产版不调用 `web/server.js`,不启动本地 HTTP/TCP 服务,也不监听 Web版的 `3000`—`3010`端口。 ## Desktop 构建 `desktop/package.json` 配置了 `electronDist: ".electron-dist"`。由于 Electron runtime 不上传源码仓库,首次构建前需要准备本地 Electron 分发目录: Git Bash: ```bash cd desktop npm install rm -rf .electron-dist cp -a node_modules/electron/dist .electron-dist ``` Windows PowerShell: ```powershell cd desktop npm install Remove-Item -Recurse -Force .electron-dist -ErrorAction SilentlyContinue Copy-Item -Recurse node_modules/electron/dist .electron-dist ``` 构建命令: ```bash npm run build:icon #生成 build/icon.ico npm run check # 构建前安全检查 npm run dist:portable #生成绿色版 npm run dist:setup #生成 NSIS 安装版 npm run dist #依次生成两种版本 npm run hash #生成 SHA256SUMS.txt ``` 默认构建目录为: ```text desktop/dist/ ``` 项目发布整理时将最终文件复制到仓库根目录的: ```text exe/ ``` 但 `exe/`、`desktop/dist/`、`.electron-dist/` 和解包目录均为本地构建产物,不上传 Gitee。 ## 安装位置 NSIS per-user 安装版默认程序目录: ```text %LOCALAPPDATA%\Programs\JM-Web\ ``` 安装向导可以选择其他程序目录。程序目录只存放应用文件、`resources/app.asar`、卸载程序和快捷方式,不存放用户收藏、书架、Cookie、会话或 AI Key。 # 数据目录和文件位置 ## Web 数据 Web 默认数据根目录: ```text <仓库根目录>/web/data/ ``` 可以使用环境变量改到其他位置: ```bash JM_WEB_DATA_DIR=/path/to/private-data npm start ``` Windows PowerShell: ```powershell $env:JM_WEB_DATA_DIR = "D:\JM-Web-Data" npm start ``` 分类结构: ```text / ├── manifest.json # 数据格式和版本 ├── .data.lock # 并发写入锁 ├── favorites/ │ ├── folders/.json # 本地收藏夹 │ ├── items/.json # 本地收藏记录 │ └── tags/.json # 标签索引 ├── history/items/.json # 阅读历史 ├── shelf/ │ ├── comics/.json #书架漫画元数据 │ ├── chapters/.json #章节元数据 │ └── images/// # 离线图片 ├── downloads/ │ ├── files/ # 普通下载文件 │ ├── metadata/ # 下载元数据 │ └── zip/ # 用户主动导出的 ZIP ├── settings/.json # 普通设置 ├── session/session.json # Cookie、uid、username,敏感 ├── logs/ #运行日志和错误日志 ├── cache/http/ # 可重新获取的 HTTP 缓存 ├── cache/images/ # 可重新获取的图片缓存 ├── cache/local-meta/.json # 漫画元数据缓存 └── updates/ # 更新临时文件 ``` ## Desktop 数据 开发模式默认使用: ```text desktop/.runtime/ ``` 安装版使用: ```text %APPDATA%\JM-Web\ ``` 通常对应: ```text C:\Users\<用户名>\AppData\Roaming\JM-Web\ ``` Portable版使用 Portable EXE 同级目录下的: ```text \data\ ``` Desktop 数据结构与 Web 分类基本一致,并额外包含: ```text / ├── browser-profile/ # Electron Chromium profile ├── server/secure-credentials.bin # safeStorage/DPAPI 加密账号凭据 ├── server/secure-aiSettings.bin # safeStorage/DPAPI 加密 AI 设置 ├── session/session.enc.json # 加密登录会话 ├── migration/ #旧数据迁移清单和备份 └── window-state.json # 窗口位置、大小和最大化状态 ``` 删除会话或凭据通常只需要重新登录;删除整个数据根目录会删除收藏、历史、书架、下载、设置和缓存,操作前应先导出备份。 ## 缓存清理边界 缓存刷新和清除只处理可重新获取的数据,例如: ```text cache/http/ cache/images/ cache/local-meta/ updates/ ``` 不会删除: ```text favorites/ history/ shelf/ downloads/ settings/ session/ ``` 日志可以在程序停止后按需清理,但日志不应上传到仓库,因为可能包含错误上下文、路径或登录失败信息。 # 本地备份格式 收藏和历史导出为一个 JSON 文件,格式标识为: ```json { "schema": "jm-web.local-records", "version":2, "exportedAt": "2026-01-01T00:00:00.000Z", "cover": { "strategy": "album-id", "version":1 }, "favorites": { "folders": [], "items": { "123456": { "folderId": "2", "savedAt":1700000000000 } } }, "history": { "123456": { "lastEpId": "789012", "lastEpTitle": "第1 話", "lastReadAt":1700000000000 } } } ``` 导出边界: - 收藏对象键是漫画 ID,只保存 `folderId` 和 `savedAt`。 - 历史对象键是漫画 ID,只保存 `lastEpId`、`lastEpTitle` 和 `lastReadAt`。 - 收藏夹名称和 ID 映射会随备份保存,用于新设备自动创建收藏夹。 - 不保存完整漫画元数据、旧封面 URL、章节文件、书架图片、ZIP、Cookie、会话、账号密码或 AI Key。 - 导入后根据漫画 ID重新获取标题、作者、标签和当前 CDN 封面。 - Desktop 导出使用原生保存对话框,用户必须选择保存位置;Web 浏览器版使用浏览器下载机制。 # API 接口 Web 和 Desktop 对外提供相同的主要业务 API。Web 请求由 `web/server.js`处理;Desktop 请求由 `desktop/src/service/api-router.js` 转发到 `desktop/src/service/app-service.js`。 所有成功响应使用统一信封: ```json { "ok": true, "data": {} } ``` 失败响应包含 `error`,登录过期时可能包含 `loginExpired: true`。实际请求参数和响应字段以对应源码为准。 ## 状态、登录和线路 | 方法 | 路径 | 用途 | |---|---|---| | GET | `/api/status` | 当前登录状态、当前线路、线路列表、健康统计和图片 CDN | | POST | `/api/login` | 登录并保存会话 | | POST | `/api/logout` | 清除登录状态和会话 | | POST | `/api/refresh-domains` | 刷新并验证 API线路列表 | | POST | `/api/select-domain` | 从已发布线路中手动选择一条,不接受任意 URL | ## 内容和阅读 | 方法 | 路径 | 用途 | |---|---|---| | GET | `/api/explore` | 首页推荐内容 | | GET | `/api/search` |关键词或 JM车号搜索 | | GET | `/api/categories` | 分类筛选和排序 | | GET | `/api/week` | 周榜分类 | | GET | `/api/weekfilter` | 周榜内容 | | GET | `/api/album` | 漫画详情、章节和关联作品 | | GET | `/api/chapter` |章节图片地址和分段参数 | | GET | `/api/comments` | 评论列表 | | POST | `/api/comment` | 发布评论 | | POST | `/api/like` | 点赞或取消点赞 | | POST | `/api/checkin` | 每日签到 | | POST | `/api/ai/chat` | 使用用户自行配置的 AI 服务转发请求 | ## 云端收藏 | 方法 | 路径 | 用途 | |---|---|---| | GET | `/api/favorite-folders` | 查询云端收藏夹 | | POST | `/api/favorite-folder` | 新建、移动或删除收藏夹内容 | | GET | `/api/favorites` | 收藏列表、关键词、标签、分页和排序 | | POST | `/api/favorite` | 加入或切换云端收藏 | 云端收藏搜索会限制分页并发,部分线路错误通过 `failedPages` 返回;401、`Unauthorized` 和上游登录失效响应会标记为登录过期,网络失败和非 JSON 响应只记为线路故障。 ## 本地数据 `/api/local/*` | 方法 | 路径 | 用途 | |---|---|---| | GET | `/api/local/health` | 本地存储健康和 manifest | | GET/POST/DELETE | `/api/local/favorites/folders` | 查询、新建和删除本地收藏夹 | | GET | `/api/local/favorites/tags` | 获取收藏或书架标签 | | GET/POST | `/api/local/backup` | 导出或导入本地收藏/历史备份 | | GET | `/api/local/downloads` | 查询下载记录 | | POST | `/api/local/resolve` | 根据漫画 ID 获取本地元数据 | | GET | `/api/local/cache/stats` | 查询缓存统计 | | POST | `/api/local/cache/refresh` | 根据当前记录刷新缓存 | | POST | `/api/local/cache/clear` | 完全清除可重建缓存 | | GET/POST/DELETE | `/api/local/favorites/items` | 查询、保存和删除本地收藏 | | GET/POST/DELETE | `/api/local/history` | 查询、保存、删除和清空历史 | | GET/POST/DELETE | `/api/local/shelf/comics` | 查询、保存和删除书架漫画 | | GET/POST/DELETE | `/api/local/shelf/chapters` | 查询、保存和删除章节 | | GET/POST/DELETE | `/api/local/shelf/images` | 查询、保存和删除离线图片 | | GET/POST | `/api/local/settings` | 查询和保存普通设置 | | POST | `/api/local/cleanup` | 执行本地缓存清理 | # 实现方法和安全边界 ## 路由和并发 - 前端是原生 HTML/CSS/JavaScript SPA,没有 React、Vue 或 Vite运行时依赖。 - `routeRenderId` 和 `renderIsCurrent()` 防止旧路由结果写入新页面。 - 路由切换时使用 `AbortController`取消上一代请求。 - 进行中的登录恢复和线路刷新使用 single-flight Promise,避免重复请求。 - 云端收藏分页使用固定 Worker 队列,防止一次搜索并发创建几十到上百个请求。 ## 本地存储和备份 - Web 使用分类 JSON 文件、原子写入和数据锁;Desktop 使用同等分类存储实现。 - 收藏、历史、书架和下载是持久数据;HTTP、图片、元数据和更新目录是可重建缓存。 - 备份只保存轻量关系数据,展示信息由漫画 ID重新匹配。 - 收藏夹导入使用 ID/名称映射,保证新设备可以创建缺失收藏夹。 ## 图片和网络边界 - 图片代理只接受 HTTPS 且经过 CDN/线路白名单校验的地址。 - 封面优先根据当前图片 CDN 和漫画 ID生成,不信任导入文件中的旧 URL。 - API线路只能从后端发布的线路列表中选择,`/api/select-domain` 不允许任意域名或 URL。 - AI 接口要求 HTTPS,禁止 URL 中携带账号密码,并阻止本机和内网地址。 ## Desktop 安全 - 主进程和渲染进程通过 preload 白名单通信,启用 context isolation。 - 登录会话、账号凭据和 AI 设置使用 Electron safeStorage/Windows DPAPI 能力保存。 - Desktop 不在本地启动 Web HTTP/TCP监听服务。 - 本地文件路径、静态资源路径、下载文件名和请求体大小均经过限制。 - 普通下载和 ZIP 下载使用不同的数据目录;本地记录 JSON 导出使用固定 `backup:save` IPC,不暴露任意路径写文件接口。 # 测试与构建 ### 语法和项目检查 ```bash node --check web/public/js/app.js node --check web/server.js node --check desktop/resources/public/js/app.js node --check desktop/src/main/index.js node --check desktop/src/preload/index.js node --check desktop/src/service/upstream-client.js node --check desktop/src/service/app-service.js cd desktop npm test npm run check ``` ## 当前测试覆盖 - 静态资源路径遍历拒绝。 - API 路由请求体大小和响应信封。 - 加密会话不落明文。 - 缓存清理不会删除本地持久记录。 - 当前 CDN 下的封面重建。 - 分类文件存储、级联删除和并发写入。 - V2备份导入、收藏夹映射、记录合并和本地数据过滤。 - 本地元数据缓存统计、过期、刷新和清理。 ## 发布前检查 ```bash git diff --check git status --short git ls-files | grep -E '\.(exe|blockmap)$' # 应无输出 ``` 构建产物生成后: ```bash sha256sum exe/JM-Web-Portable.exe \ exe/JM-Web-Setup.exe \ exe/JM-Web-Setup.exe.blockmap \ > exe/SHA256SUMS.txt sha256sum -c exe/SHA256SUMS.txt ``` # 源码仓库上传边界 本仓库只上传: - Web 和 Desktop 源代码; - 测试文件; - 构建、检查和图标脚本; - API、实现、安全和打包说明; - `package.json`、`package-lock.json` 等依赖描述文件; - 本 README 和项目总结文档。 不上传: - `exe/` 下的 Portable、NSIS、blockmap 和 SHA 文件; - `desktop/dist/`、`desktop/.electron-dist/`、解包目录和构建缓存; - `node_modules/`、Electron runtime 和 npm 缓存; - `web/data/`、`desktop/.runtime/`、Portable `data/`; - Cookie、账号密码、加密会话、AI Key、浏览器 profile、日志、下载、收藏、历史和书架图片。 Gitee 仓库地址: ## 免责声明 项目不保证第三方服务、API线路、账号登录、图片 CDN、更新地址或漫画内容持续可用。使用者应自行确认访问、下载、缓存、保存和分享行为符合所在地法律法规及第三方服务条款,并自行备份重要数据。