lionwebsite-frontend-desktop/llm_readme.md
chuzhongzai e25afb7445 重构 store 并修复多个 bug
- state.collectGallery.slice(0) → splice(0),修复收藏列表数据残留 bug
   - action 中 state 引用改为 context.state,遵循 Vuex 规范
   - 修复 _searchLocalByLink 中 gid 判空条件(null → undefined)
   - 修复 deleteTask splice 后索引跳过下一个元素
   - 简化 getShortname 用正则替代繁琐的手动遍历
   - 移除 loadWeekUsedAmount 冗余的成功提示弹窗
   - 添加 Axios 全局错误拦截器,统一处理网络请求失败
   - websocket 初始值 {} → null,修正类型
   - resetUndone 硬编码授权码改为从 state 获取
   - computed 移除副作用,改用 watch 实现
   - HentaiSearch 加载指示器 DOM 操作改为响应式 v-show
   - 提取重复的 validateLink 到共享工具函数
   - OnlineReader 全量 watch(store.state) → 精准监听 isReading
2026-06-07 16:18:44 +08:00

201 lines
9.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LionWebsite 项目分析
## 项目概述
LionWebsite 是一个基于 Vue 3 + Vite 构建的漫画/Gallery 下载与管理前端应用。用户通过授权码连接后端服务,可以搜索、下载、在线预览来自 exhentai/e-hentai 的漫画 gallery并管理下载任务。
后端基址: `https://downloader.lionwebsite.xyz/`
## 技术栈
| 技术 | 用途 |
|------|------|
| **Vue 3** (Composition API, `<script setup>`) | 前端框架 |
| **Vite 5** | 构建工具 |
| **Element Plus 2.2** | UI 组件库 |
| **Vuex 4** | 状态管理 |
| **Axios** | HTTP 请求 |
| **qs** | URL 序列化 |
## 项目结构
```
D:\WorkSpace\code\Vue\LionWebsite\
├── index.html # 入口 HTML
├── package.json # 依赖声明
├── vite.config.js # Vite 配置(仅 vue 插件 + 0.0.0.0 host)
├── public/ # 静态资源(空)
├── dist/ # 构建产物
└── src/
├── main.js # 应用入口: mount Element Plus + 全局 CSS
├── reset.css # CSS reset
├── App.vue # 根组件: el-container 布局
├── store/
│ └── index.js # Vuex store (所有状态与业务逻辑)
└── components/
├── DashBoard.vue # 仪表盘: 授权、查询、配置、搜索结果弹窗
├── Side.vue # 主列表: Gallery 表格、翻页、分类/排序
├── HentaiSearch.vue# 在线搜索弹窗: 远程搜索 exhentai gallery
└── OnlineReader.vue# 在线预览弹窗: 阅读下载完成的 gallery
```
## 组件详解
### App.vue (根组件)
- 使用 `el-container` 布局
- 左侧 `el-aside` (750px) 放置 `Side` 组件
- 右侧 `el-main` 放置 `DashBoard` 组件
### DashBoard.vue — 仪表盘
**功能**: 授权登录、查询任务、修改授权码、在线搜索入口、节点重连、配置管理
- **授权模块**: 输入授权码 → 调用 `store.dispatch("validate")` → 记住密码(localStorage)
- **查询模块**: 支持按链接远程查询或按链接/关键字本地查询
- **操作按钮**: 修改授权码、删除本地授权码、夜间模式切换、在线搜索入口、重连节点
- **配置弹窗**: 夜间模式(跟随系统)、在线预览分页数、默认分类/排序/显示类型 → 持久化到 localStorage
- **查询结果弹窗**: 显示 gallery 详细信息,可选择分辨率提交下载任务
- **缩略图预览**: 鼠标悬停 gallery 时在仪表盘显示封面缩略图
- **初始化**: `onMounted` 时从 localStorage 恢复授权码与配置
### Side.vue — 主列表
**功能**: 展示 gallery 表格、分页、分类/排序切换
- **表格**: 使用 Element Plus `el-table`,列含展开行(详细信息)、名字、操作(下载/收藏/在线看)、进度
- **操作列**:
- 下载: 仅当 status==="下载完成" 时可用,直接 `window.open` 下载链接
- 收藏/取消收藏: 调用 `collectGallery` / `disCollectGallery`
- 在线看: 调用 `readOnlineGallery`
- **分类切换**: 我的下载 / 我的收藏 / 全部
- **排序**: 名字 / 简洁名字 / 任务创建时间
- **显示类型**: 完整名字 / 简洁名字
- **翻页**: 首页/上一页/下一页/尾页 + 直接输入页码
- **缩略图悬停**: 500ms 防抖后触发缩略图更新
- **空状态提示**: 根据分类显示"您未下载过"或"您未收藏过"
### HentaiSearch.vue — 在线搜索
**功能**: 远程搜索 exhentai 上的 gallery
- 输入关键字 → 调用 `https://downloader.lionwebsite.xyz/query?keyword=xxx`
- 支持分页导航(首页/上一页/下一页/尾页),后端返回分页链接
- 每个搜索结果展示: 封面缩略图、名字、上传时间、页数、类型、链接
- 操作: "在线看"直接阅读、"查看详情"查询到本地并打开详情弹窗
- 加载状态: CSS 旋转动画 loading 指示器
### OnlineReader.vue — 在线预览
**功能**: 在弹窗中阅读 gallery 图片
- 分页阅读: 每页显示 `lengthPerPage` 张图片(默认30),支持翻页
- 图片懒加载: 每加载完成一张自动触发加载下一张(`loadImage`)
- 支持大图预览: 点击图片使用 Element Plus `el-image``preview-src-list`
- 连续阅读: 翻页滚动体验优化(监听 `switch` 事件)
- 页数 < 9 时显示全部页码按钮>= 9 时只显示输入跳转
## Vuex Store 分析 (store/index.js)
Store 是应用的核心,管理所有状态与后端通信。
### State 关键字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `totalGalleryTask` | Array | 所有 gallery 任务 |
| `chosenGallery` | Object/false | 当前选中的 gallery(待下载) |
| `collectGallery` | Array | 收藏的 gallery |
| `downloadGallery` | Array | 分配给当前用户的 gallery |
| `searchTask` | Array | 本地搜索结果 |
| `currentTasks` | Array | 当前显示的 tasks(根据分类筛选) |
| `readingGallery` | Object | 正在阅读的 gallery |
| `isReading` | Boolean | 是否正在阅读 |
| `isAuth` | Boolean | 是否已验证 |
| `AuthCode` | String | 授权码 |
| `userId` | Number | 用户 ID |
| `username` | String | 用户名 |
| `category` | String | 分类: myDownload / myCollect / total |
| `sortType` | String | 排序: shortName / name / createTime |
| `galleryNameType` | String | 显示名: shortName / name |
| `page` | Number | 当前页码 |
| `length` | Number | 每页条目数 |
| `websocket` | WebSocket | WebSocket 连接 |
### Actions (后端交互)
| Action | 方法 | 端点 | 说明 |
|--------|------|------|------|
| `validate` | POST | `/validate` | 验证授权码,初始化数据 |
| `updateGalleryTasks` | GET | `/GalleryManage` | 获取所有 gallery 任务 |
| `postGalleryTask` | POST | `/GalleryManage` | 提交下载任务 |
| `queryGalleryTask` | GET | `/GalleryManage` | 按链接查询 gallery |
| `loadWeekUsedAmount` | GET | `/GalleryManage/weekUsedAmount` | 查询本周用量 |
| `collectGallery` | POST | `/GalleryManage/collect` | 收藏 gallery |
| `disCollectGallery` | POST | `/GalleryManage/disCollect` | 取消收藏 |
| `deleteGallery` | DELETE | `/GalleryManage` | 删除 gallery |
| `readOnlineGallery` | POST | `/GalleryManage/cache` | 缓存并开始在线预览 |
| `alterAuthCode` | PUT | `/AuthCode` | 修改授权码 |
| `reconnect` | POST | `/GalleryManage/reconnect` | 重连下载节点 |
| `resetUndone` | POST | `/GalleryManage/reset` | 重置未完成任务 |
### WebSocket 通信
- 端点: `wss://downloader.lionwebsite.xyz/ws/`
- 连接后发送: `"DownloaderWebsocket"`
- 消息类型:
- `updateTasks`: 增量更新任务进度
- `fullUpdate`: 触发全量刷新
### Getters
| Getter | 说明 |
|--------|------|
| `currentTasks` | 返回当前页的 tasks(支持搜索态) |
| `min` | 最小页码(1) |
| `max` | 最大页码 |
### 辅助函数
- `getShortname(name)`: 从 gallery 名中去除中括号/括号内的标签信息
- `confirmCurrentTask(state)`: 根据 category 切换 currentTasks
- `sortTasks(state)`: 根据 sortType 排序
- `deleteTask(tasks, key, value)`: 从多个数组中删除匹配的任务
## API 端点汇总
所有请求均需携带 `AuthCode` 参数:
| 端点 | 用途 |
|------|------|
| `POST /validate` | 授权码验证 |
| `GET/POST/DELETE /GalleryManage` | 任务 CRUD |
| `GET /GalleryManage/weekUsedAmount` | 每周用量查询 |
| `POST /GalleryManage/collect` | 收藏 |
| `POST /GalleryManage/disCollect` | 取消收藏 |
| `POST /GalleryManage/cache` | 缓存 gallery 用于在线预览 |
| `POST /GalleryManage/reconnect` | 重连下载节点 |
| `POST /GalleryManage/reset` | 重置未完成任务 |
| `GET /GalleryManage/ehThumbnail` | 获取缩略图 |
| `GET /GalleryManage/file/{name}.zip` | 下载文件 |
| `GET /GalleryManage/onlineImage/{i}` | 在线预览图片 |
| `PUT /AuthCode` | 修改授权码 |
| `GET /query` | 远程搜索 exhentai |
| `WS /ws/` | WebSocket 实时推送 |
## 特色与关键实现
1. **简洁名字处理**: `getShortname()` 使用启发式逻辑从 gallery 完整名中剥离标签
2. **防抖缩略图**: Side 组件 mouseenter 时 500ms 防抖才更新缩略图
3. **夜间模式**: 通过 Element Plus 的 `dark` CSS class 切换,支持跟随系统偏好
4. **权限分级**: userId===3 的用户(Lion)有额外操作权限(重置任务、查看 downloader)
5. **本地持久化**: 授权码、分页配置、分类/排序/显示偏好均存 localStorage
6. **WebSocket 实时更新**: 任务进度变化时服务端通过 WebSocket 推送增量更新
7. **图片懒加载**: 按页加载图片,每加载完成一张自动触发下一张加载
## 构建与运行
```bash
npm run dev # 开发服务器 (0.0.0.0)
npm run build # 生产构建
npm run preview # 预览构建产物
```
## 潜在问题/改进点
1. `store/index.js``updateGalleryTasks` 的 action 引用了未在函数签名中声明的 `state` — 使用了外部模块级变量而非 context.state这在严格模式下可能引起问题
2. `state.websocket` 在 Vuex 中初始化为 `{}` 而非 `null`,检查方式不够严谨
3. `getShortname` 函数逻辑复杂且有多处副作用,可读性较低
4. 部分错误处理较简略(如 `queryGalleries` 中无网络错误处理)
5. `store/index.js` 中 action 使用全局 `state` 变量(而非 `context.state`),可能导致作用域混淆