Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3041185128 | ||
|
|
ecbf8209bd | ||
|
|
9f40e28eca | ||
|
|
462335b20b | ||
|
|
cc46e727d1 | ||
|
|
b566d32eb8 | ||
|
|
1fbbcf29b9 | ||
|
|
34a4aa4449 | ||
|
|
008b0f4b75 | ||
|
|
e23473862b | ||
|
|
704efbb52f | ||
|
|
d646c20b21 | ||
|
|
46627f4a54 | ||
|
|
59e4012ced | ||
|
|
cf66a7e128 | ||
|
|
5d054c309a | ||
|
|
3347482164 | ||
|
|
ea5e568525 | ||
|
|
cee7d192ae | ||
|
|
3f93be29b6 | ||
|
|
012be32ffe | ||
|
|
26f8aabcc3 | ||
|
|
bd124e46df | ||
|
|
5e32cce930 | ||
|
|
7baa8050d7 | ||
|
|
d0ed35b2bb | ||
|
|
c365cb4906 | ||
|
|
ba3885b637 | ||
|
|
5816f5c825 | ||
|
|
d9ab24cb14 | ||
|
|
2ba4596f50 | ||
|
|
efcf16fe93 | ||
|
|
012efb03ea | ||
|
|
f4de7552e1 | ||
|
|
8a2c7d13c6 | ||
|
|
367307029b | ||
|
|
1214501691 | ||
|
|
ac63baed2c | ||
|
|
834a8da696 | ||
|
|
3c6c3cffaf | ||
|
|
bdd5e99f95 | ||
|
|
d48e39e580 | ||
|
|
0061dfa988 | ||
|
|
f2e4186042 | ||
|
|
8a4edd29f5 | ||
|
|
7ea47b4606 | ||
|
|
b87de84a0d |
2
.github/workflows/build.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
- name: setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 9.1.0
|
||||
version: 9.5.0
|
||||
- name: remove lockfile
|
||||
run: rm pnpm-lock.yaml
|
||||
- name: Install frontend dependencies
|
||||
|
||||
@@ -15,3 +15,4 @@ qodana.yaml
|
||||
*.svg
|
||||
# data
|
||||
!src/data/**/*.json
|
||||
src-tauri/gen/*.json
|
||||
|
||||
219
CHANGELOG.md
@@ -1,208 +1,27 @@
|
||||
---
|
||||
Author: 目棃
|
||||
Description: CHANGELOG
|
||||
Date: 2024-01-15
|
||||
Update: 2024-06-14
|
||||
Date: 2024-07-09
|
||||
Update: 2024-07-16
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2024-01-15 17:29:15`
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2024-07-09 14:16:16`
|
||||
>
|
||||
> 更新于 `2024-06-14 22:52:08`
|
||||
> 更新于 `2024-07-16 22:03:11`
|
||||
|
||||
## [0.4.9](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.9) (2024-06-14)
|
||||
## [0.5.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.5.0) (2024-07-09)
|
||||
|
||||
- 💄 调整帖子 `tag` 样式
|
||||
- 🐛 修复成就导入异常
|
||||
- ✏️ 修正角色图鉴部分描述
|
||||
- 🍱 更新卡牌资料
|
||||
- ⚡️ 成就查询输入为空时重置结果
|
||||
|
||||
## [0.4.8](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.8) (2024-06-04)
|
||||
|
||||
- 🐛 修复名片解析异常 [`#110`](https://github.com/BTMuli/TeyvatGuide/issues/110)
|
||||
- 💄 调整链接组件样式
|
||||
- 💄 调整首页生日组件样式
|
||||
- 🐛 修复版本搜索失效,未完成成就优先
|
||||
- 🍱 更新 4.7 版本资源 [`#112`](https://github.com/BTMuli/TeyvatGuide/issues/112)
|
||||
|
||||
## [0.4.7](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.7) (2024-05-10)
|
||||
|
||||
- 🐛 修复 mention 类型渲染异常
|
||||
- ⚡️ 对签到链接跳转进行处理,优化部分网页活动打开
|
||||
- ♻️ 重构用户祈愿数据库相关处理
|
||||
- 🔥 隐藏网页登录模块 [`#108`](https://github.com/BTMuli/TeyvatGuide/issues/108)
|
||||
- ✨ 采用 ajv 验证 UIGF [`#109`](https://github.com/BTMuli/TeyvatGuide/issues/109)
|
||||
- 💄 完善公告`table`&`p`部分的渲染
|
||||
- 💄 调整帖子文本部分的样式
|
||||
- ♻️ UIAF重构,支持祈愿备份/恢复
|
||||
- ⚡️ 完善公告正则
|
||||
- ♻️ 名片组件抽离,wiki添加名片信息
|
||||
|
||||
## [0.4.6](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.6) (2024-04-24)
|
||||
|
||||
### Feat
|
||||
|
||||
- 帖子:重构文本解析,现在更加贴近应用内的渲染效果
|
||||
- 应用:侧边栏点击咨讯时的参数也支持记忆了
|
||||
- 应用:更新 4.6 版本的游戏资源
|
||||
|
||||
### Fix
|
||||
|
||||
- 留影叙佳期:修复侧边栏点击时初始画片数异常
|
||||
- 首页:修复特定情况下日历组件左侧切换日期按钮点击无效
|
||||
- 帖子:修复 `align:right` 不生效的问题
|
||||
- 首页:修复特定情况下首页卡池渲染异常
|
||||
|
||||
### Change
|
||||
|
||||
- 应用:数据库更新后弹出更新日志
|
||||
|
||||
## [0.4.5](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.5) (2024-04-05)
|
||||
|
||||
### Feat
|
||||
|
||||
- 添加收藏页面,支持导入用户收藏 [`#100`](https://github.com/BTMuli/TeyvatGuide/issues/100)
|
||||
- 设置页添加更新日志跳转
|
||||
- 首页:组件样式迭代
|
||||
- 帖子:替换默认封面
|
||||
- 帖子:支持关键词搜索 [`#103`](https://github.com/BTMuli/TeyvatGuide/issues/103)
|
||||
|
||||
### Fix
|
||||
|
||||
- 成就:修正部分成就版本信息 [`3501590f`](https://github.com/BTMuli/TeyvatGuide/commit/3501590f)
|
||||
- 帖子:链接卡片添加间距
|
||||
- 图鉴:修复埃洛伊背景渲染异常
|
||||
- 留影叙佳期:补充遗漏数据,支持特定日期查看
|
||||
|
||||
### Change
|
||||
|
||||
- 帖子:微调解析逻辑
|
||||
- 重构:通用帖子卡片抽离作为组件,添加 `select` 状态
|
||||
- 帖子:抽奖详情改为 `overlay`
|
||||
- 应用:调整默认颜色
|
||||
|
||||
## [0.4.4](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.4) (2024-03-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- 咨讯:优化咨讯版块切换&页面跳转体验
|
||||
- 公告:在可能的情况下根据公告内容获取对应时间 [`#94`](https://github.com/BTMuli/TeyvatGuide/issues/94)
|
||||
- 帖子:添加转载声明,支持图片浮窗
|
||||
- 祈愿:添加 `祈愿历史` 页面,支持查看历史祈愿记录及对应信息
|
||||
- 祈愿:添加集录祈愿支持,更新 UIGF 版本至 3.0 [`#96`](https://github.com/BTMuli/TeyvatGuide/issues/96)
|
||||
- 应用:版本更新弹窗确认后将直接更新数据库
|
||||
- 应用:添加 `留影叙佳期` 页面,汇聚三年间的相关信息
|
||||
- 应用:再次支持米游社扫码登录,网页登录自动检测数据并刷新 [`#99`](https://github.com/BTMuli/TeyvatGuide/issues/99)
|
||||
- 应用:添加 4.5 版本的游戏资源 [`#95`](https://github.com/BTMuli/TeyvatGuide/issues/95)
|
||||
- 祈愿:支持增量更新祈愿数据
|
||||
|
||||
### Fix
|
||||
|
||||
- 图鉴:修复武器图鉴左侧列表高度异常
|
||||
- 日志:修正过期日志判断逻辑
|
||||
- 帖子:修复动图渲染异常
|
||||
- 深渊:当期不存在9层及以上的数据时进行提示
|
||||
- JSBridge: 修复特定页面的分享图渲染错误
|
||||
- 帖子:完善文本样式解析,修复特定情况下文本异常渲染为图片
|
||||
- 应用:修复侧边栏及设置页面用户信息响应式异常
|
||||
|
||||
### Change
|
||||
|
||||
- 公告:调整样式,顶部添加相关信息
|
||||
- 设置:数据路径采用系统命令而非文件选择器打开
|
||||
- 日志:调试模式下不将日志写入文件
|
||||
- 帖子:移除大别野组件
|
||||
- 首页:素材日历移除留影叙佳期入口及生日提醒
|
||||
- 深渊:胡桃数据库角色持有页面重构
|
||||
- 首页:卡池组件样式重构
|
||||
|
||||
## [0.4.3](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.3) (2024-02-09)
|
||||
|
||||
### Feat
|
||||
|
||||
- 公告:支持服务器&语言的切换 [`#81`](https://github.com/BTMuli/TeyvatGuide/issues/81)
|
||||
- 战绩:世界探索部分数据结构调整,合并同类数据(如沉玉谷)[`#91`](https://github.com/BTMuli/TeyvatGuide/issues/91)
|
||||
- 图鉴:角色/武器图鉴支持条件筛选(武器类型、星级等) [`#87`](https://github.com/BTMuli/TeyvatGuide/issues/87)
|
||||
|
||||
### Fix
|
||||
|
||||
- 应用:完善 UID 与服务器的对应关系 [`#90`](https://github.com/BTMuli/TeyvatGuide/issues/81)
|
||||
- 应用:修正扫码登录,增加网页登录 [`#89`](https://github.com/BTMuli/TeyvatGuide/issues/89)
|
||||
- 祈愿:修复 `authkey` 获取失败后无限加载的问题
|
||||
- 图鉴:修复部分文本错误,增加遗漏数据
|
||||
- 应用:修复外部唤起失效,**不保证*应用商店版本*的唤起可用性**
|
||||
- 日志:修复过时日志检测逻辑错误
|
||||
|
||||
### Change
|
||||
|
||||
- 设置:平台图标跟随平台变更,调整图标样式 [`#88`](https://github.com/BTMuli/TeyvatGuide/issues/88)
|
||||
- 深渊:调整深渊样式,完善上传错误处理
|
||||
- 应用:后端代码重构,修复窗口创建时的 `error` 问题
|
||||
|
||||
## [0.4.2](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.2) (2024-01-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- 应用:支持日志记录 [`#83`](https://github.com/BTMuli/TeyvatGuide/issues/83)
|
||||
- 图鉴:角色/武器图鉴支持查看材料详细信息
|
||||
- 资源:游戏资源更新至 4.4 版本 [`#86`](https://github.com/BTMuli/TeyvatGuide/issues/86)
|
||||
- 成就:支持查看成就详细信息,数据来源于 [`amos-data`](https://github.com/yuehaiteam/amos-data)
|
||||
- 首页:祈愿卡池 Up 角色支持直接跳转到对应图鉴界面
|
||||
|
||||
### Fix
|
||||
|
||||
- 应用:完善用户账号数据返回,修复部分用户数据获取失败
|
||||
- 应用:修复深渊页面分享图生成错误,完善分享&上传判断
|
||||
- 首页:采用 `emit` 替代 `interval`,提升性能
|
||||
- JSBridge:修复特定情况下的 `panic`
|
||||
|
||||
### Change
|
||||
|
||||
- 应用:设置页面重构
|
||||
- 应用:首页组件配置移至首页
|
||||
- 帖子:调整别野卡片、合集 overlay 样式
|
||||
|
||||
## [0.4.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.1) (2024-01-19)
|
||||
|
||||
### Feat
|
||||
|
||||
- 组件:首页素材日历添加 wiki 页面跳转
|
||||
- 应用:完善 fp 获取,添加强制更新入口
|
||||
- 图鉴:名片图鉴搜索支持搜索来源
|
||||
- 应用:支持修改数据目录 [`#78`](https://github.com/BTMuli/TeyvatGuide/issues/78)
|
||||
|
||||
### Fix
|
||||
|
||||
- 应用:修复首页启动卡数据加载 [`#79`](https://github.com/BTMuli/TeyvatGuide/issues/79)
|
||||
- 应用:修复 macOS 启动崩溃 [`#82`](https://github.com/BTMuli/TeyvatGuide/issues/82)
|
||||
- 图鉴:完善切换时的底部 hint
|
||||
|
||||
### Change
|
||||
|
||||
- 图鉴:卡牌图鉴样式重构
|
||||
- 组件:统一底部弹窗样式
|
||||
- 应用:调整部分点击跳转逻辑
|
||||
|
||||
## [0.4.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.0) (2024-01-15)
|
||||
|
||||
### Feat
|
||||
|
||||
- 应用:实装角色、武器、名片图鉴
|
||||
- JSBridge:添加窗口旋转子菜单
|
||||
- 应用:更新米社 salt 版本
|
||||
- 帖子:完成 `video` 类型数据的渲染 [`#77`](https://github.com/BTMuli/TeyvatGuide/issues/77)
|
||||
|
||||
### Fix
|
||||
|
||||
- wiki:修复流浪者数据错误
|
||||
- 应用:添加夏沃蕾、究极霸王超级魔剑的数据
|
||||
- 帖子:修复部分格式图片渲染失败
|
||||
- 公告:优化公告详情在深色模式下的表现
|
||||
- JSBridge:修复登录态错误
|
||||
- 应用:类型重构 [`#51`](https://github.com/BTMuli/TeyvatGuide/issues/51)
|
||||
- 应用:完善数据库完整性检测
|
||||
|
||||
### Change
|
||||
|
||||
- 应用:调整 `snackbar` 样式
|
||||
- 应用:取消 `transparent` 配置
|
||||
- ⬆️ 底层架构更新,升级至 `Tauri v2` [`#92`](https://github.com/BTMuli/TeyvatGuide/issues/92)
|
||||
- 🐛 修复数据恢复异常
|
||||
- ⬆️ 更新绝区零版块列表
|
||||
- ⬆️ 适配米游社返回数据
|
||||
- ⚡️ 链接解析调整
|
||||
- ✨ 幻想真境剧诗适配 [`#113`](https://github.com/BTMuli/TeyvatGuide/issues/113)
|
||||
- ♻️ 帖子顶部小工具添加到首页
|
||||
- ⚡️ 公告链接样式调整
|
||||
- ⚡️ 角色分享图添加水印
|
||||
- ✨ 视频支持封面下载
|
||||
- ⚡️ 咨讯页调整绝区零版块排序
|
||||
- ✨ 祈愿添加 UIGF v4 支持
|
||||
- 🍱 更新 4.8 版本资源 [`#115`](https://github.com/BTMuli/TeyvatGuide/issues/115)
|
||||
- ✨ 材料 wiki 页面草创
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
Author: 目棃
|
||||
Description: 说明文档
|
||||
Date: 2023-03-05
|
||||
Update: 2024-04-05
|
||||
Update: 2024-07-14
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-03-05 14:41:55`
|
||||
>
|
||||
> 更新于 `2024-04-05 14:25:24`
|
||||
> 更新于 `2024-07-14 08:50:43`
|
||||
|
||||
 
|
||||
|
||||
  
|
||||
   
|
||||
|
||||
<div style="width: 100%; text-align: center; margin: 0 auto;">
|
||||
<img alt="icon" src="https://s2.loli.net/2023/10/19/Y5DpBQRy3usLHEb.png" />
|
||||
@@ -48,7 +48,7 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
|
||||
- [x] 米游社官方帖获取(支持通过 ID 获取)
|
||||
- [x] 米游社各分区帖子获取(支持通过 ID 获取)
|
||||
- [x] 成就管理(UIAF v1.1),支持 [`YaeAchievement`](https://github.com/HolographicHat/YaeAchievement) 导入
|
||||
- [x] 祈愿管理(UIGF v3.0)
|
||||
- [x] 祈愿管理(UIGF v3.0,0.5.0 起支持 UIGF v4.0)
|
||||
- [x] 留影叙佳期画片查看
|
||||
- [x] 帖子收藏
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
Author: 目棃
|
||||
Date: 2023-06-18
|
||||
Description: CHANGELOG
|
||||
Description: CHANGELOG v0.2.x
|
||||
Update: 2023-08-31
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
Author: 目棃
|
||||
Description: CHANGELOG
|
||||
Description: CHANGELOG v0.3.x
|
||||
Date: 2023-09-08
|
||||
Update: 2024-01-15
|
||||
---
|
||||
|
||||
208
docs/CHANGELOG-v0.4.x.md
Normal file
@@ -0,0 +1,208 @@
|
||||
---
|
||||
Author: 目棃
|
||||
Description: CHANGELOG v0.4.x
|
||||
Date: 2024-01-15
|
||||
Update: 2024-07-09
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2024-01-15 17:29:15`
|
||||
>
|
||||
> 更新于 `2024-07-09 14:17:46`
|
||||
|
||||
## [0.4.9](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.9) (2024-06-14)
|
||||
|
||||
- 💄 调整帖子 `tag` 样式
|
||||
- 🐛 修复成就导入异常
|
||||
- ✏️ 修正角色图鉴部分描述
|
||||
- 🍱 更新卡牌资料
|
||||
- ⚡️ 成就查询输入为空时重置结果
|
||||
|
||||
## [0.4.8](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.8) (2024-06-04)
|
||||
|
||||
- 🐛 修复名片解析异常 [`#110`](https://github.com/BTMuli/TeyvatGuide/issues/110)
|
||||
- 💄 调整链接组件样式
|
||||
- 💄 调整首页生日组件样式
|
||||
- 🐛 修复版本搜索失效,未完成成就优先
|
||||
- 🍱 更新 4.7 版本资源 [`#112`](https://github.com/BTMuli/TeyvatGuide/issues/112)
|
||||
|
||||
## [0.4.7](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.7) (2024-05-10)
|
||||
|
||||
- 🐛 修复 mention 类型渲染异常
|
||||
- ⚡️ 对签到链接跳转进行处理,优化部分网页活动打开
|
||||
- ♻️ 重构用户祈愿数据库相关处理
|
||||
- 🔥 隐藏网页登录模块 [`#108`](https://github.com/BTMuli/TeyvatGuide/issues/108)
|
||||
- ✨ 采用 ajv 验证 UIGF [`#109`](https://github.com/BTMuli/TeyvatGuide/issues/109)
|
||||
- 💄 完善公告`table`&`p`部分的渲染
|
||||
- 💄 调整帖子文本部分的样式
|
||||
- ♻️ UIAF重构,支持祈愿备份/恢复
|
||||
- ⚡️ 完善公告正则
|
||||
- ♻️ 名片组件抽离,wiki添加名片信息
|
||||
|
||||
## [0.4.6](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.6) (2024-04-24)
|
||||
|
||||
### Feat
|
||||
|
||||
- 帖子:重构文本解析,现在更加贴近应用内的渲染效果
|
||||
- 应用:侧边栏点击咨讯时的参数也支持记忆了
|
||||
- 应用:更新 4.6 版本的游戏资源
|
||||
|
||||
### Fix
|
||||
|
||||
- 留影叙佳期:修复侧边栏点击时初始画片数异常
|
||||
- 首页:修复特定情况下日历组件左侧切换日期按钮点击无效
|
||||
- 帖子:修复 `align:right` 不生效的问题
|
||||
- 首页:修复特定情况下首页卡池渲染异常
|
||||
|
||||
### Change
|
||||
|
||||
- 应用:数据库更新后弹出更新日志
|
||||
|
||||
## [0.4.5](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.5) (2024-04-05)
|
||||
|
||||
### Feat
|
||||
|
||||
- 添加收藏页面,支持导入用户收藏 [`#100`](https://github.com/BTMuli/TeyvatGuide/issues/100)
|
||||
- 设置页添加更新日志跳转
|
||||
- 首页:组件样式迭代
|
||||
- 帖子:替换默认封面
|
||||
- 帖子:支持关键词搜索 [`#103`](https://github.com/BTMuli/TeyvatGuide/issues/103)
|
||||
|
||||
### Fix
|
||||
|
||||
- 成就:修正部分成就版本信息 [`3501590f`](https://github.com/BTMuli/TeyvatGuide/commit/3501590f)
|
||||
- 帖子:链接卡片添加间距
|
||||
- 图鉴:修复埃洛伊背景渲染异常
|
||||
- 留影叙佳期:补充遗漏数据,支持特定日期查看
|
||||
|
||||
### Change
|
||||
|
||||
- 帖子:微调解析逻辑
|
||||
- 重构:通用帖子卡片抽离作为组件,添加 `select` 状态
|
||||
- 帖子:抽奖详情改为 `overlay`
|
||||
- 应用:调整默认颜色
|
||||
|
||||
## [0.4.4](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.4) (2024-03-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- 咨讯:优化咨讯版块切换&页面跳转体验
|
||||
- 公告:在可能的情况下根据公告内容获取对应时间 [`#94`](https://github.com/BTMuli/TeyvatGuide/issues/94)
|
||||
- 帖子:添加转载声明,支持图片浮窗
|
||||
- 祈愿:添加 `祈愿历史` 页面,支持查看历史祈愿记录及对应信息
|
||||
- 祈愿:添加集录祈愿支持,更新 UIGF 版本至 3.0 [`#96`](https://github.com/BTMuli/TeyvatGuide/issues/96)
|
||||
- 应用:版本更新弹窗确认后将直接更新数据库
|
||||
- 应用:添加 `留影叙佳期` 页面,汇聚三年间的相关信息
|
||||
- 应用:再次支持米游社扫码登录,网页登录自动检测数据并刷新 [`#99`](https://github.com/BTMuli/TeyvatGuide/issues/99)
|
||||
- 应用:添加 4.5 版本的游戏资源 [`#95`](https://github.com/BTMuli/TeyvatGuide/issues/95)
|
||||
- 祈愿:支持增量更新祈愿数据
|
||||
|
||||
### Fix
|
||||
|
||||
- 图鉴:修复武器图鉴左侧列表高度异常
|
||||
- 日志:修正过期日志判断逻辑
|
||||
- 帖子:修复动图渲染异常
|
||||
- 深渊:当期不存在9层及以上的数据时进行提示
|
||||
- JSBridge: 修复特定页面的分享图渲染错误
|
||||
- 帖子:完善文本样式解析,修复特定情况下文本异常渲染为图片
|
||||
- 应用:修复侧边栏及设置页面用户信息响应式异常
|
||||
|
||||
### Change
|
||||
|
||||
- 公告:调整样式,顶部添加相关信息
|
||||
- 设置:数据路径采用系统命令而非文件选择器打开
|
||||
- 日志:调试模式下不将日志写入文件
|
||||
- 帖子:移除大别野组件
|
||||
- 首页:素材日历移除留影叙佳期入口及生日提醒
|
||||
- 深渊:胡桃数据库角色持有页面重构
|
||||
- 首页:卡池组件样式重构
|
||||
|
||||
## [0.4.3](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.3) (2024-02-09)
|
||||
|
||||
### Feat
|
||||
|
||||
- 公告:支持服务器&语言的切换 [`#81`](https://github.com/BTMuli/TeyvatGuide/issues/81)
|
||||
- 战绩:世界探索部分数据结构调整,合并同类数据(如沉玉谷)[`#91`](https://github.com/BTMuli/TeyvatGuide/issues/91)
|
||||
- 图鉴:角色/武器图鉴支持条件筛选(武器类型、星级等) [`#87`](https://github.com/BTMuli/TeyvatGuide/issues/87)
|
||||
|
||||
### Fix
|
||||
|
||||
- 应用:完善 UID 与服务器的对应关系 [`#90`](https://github.com/BTMuli/TeyvatGuide/issues/81)
|
||||
- 应用:修正扫码登录,增加网页登录 [`#89`](https://github.com/BTMuli/TeyvatGuide/issues/89)
|
||||
- 祈愿:修复 `authkey` 获取失败后无限加载的问题
|
||||
- 图鉴:修复部分文本错误,增加遗漏数据
|
||||
- 应用:修复外部唤起失效,**不保证*应用商店版本*的唤起可用性**
|
||||
- 日志:修复过时日志检测逻辑错误
|
||||
|
||||
### Change
|
||||
|
||||
- 设置:平台图标跟随平台变更,调整图标样式 [`#88`](https://github.com/BTMuli/TeyvatGuide/issues/88)
|
||||
- 深渊:调整深渊样式,完善上传错误处理
|
||||
- 应用:后端代码重构,修复窗口创建时的 `error` 问题
|
||||
|
||||
## [0.4.2](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.2) (2024-01-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- 应用:支持日志记录 [`#83`](https://github.com/BTMuli/TeyvatGuide/issues/83)
|
||||
- 图鉴:角色/武器图鉴支持查看材料详细信息
|
||||
- 资源:游戏资源更新至 4.4 版本 [`#86`](https://github.com/BTMuli/TeyvatGuide/issues/86)
|
||||
- 成就:支持查看成就详细信息,数据来源于 [`amos-data`](https://github.com/yuehaiteam/amos-data)
|
||||
- 首页:祈愿卡池 Up 角色支持直接跳转到对应图鉴界面
|
||||
|
||||
### Fix
|
||||
|
||||
- 应用:完善用户账号数据返回,修复部分用户数据获取失败
|
||||
- 应用:修复深渊页面分享图生成错误,完善分享&上传判断
|
||||
- 首页:采用 `emit` 替代 `interval`,提升性能
|
||||
- JSBridge:修复特定情况下的 `panic`
|
||||
|
||||
### Change
|
||||
|
||||
- 应用:设置页面重构
|
||||
- 应用:首页组件配置移至首页
|
||||
- 帖子:调整别野卡片、合集 overlay 样式
|
||||
|
||||
## [0.4.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.1) (2024-01-19)
|
||||
|
||||
### Feat
|
||||
|
||||
- 组件:首页素材日历添加 wiki 页面跳转
|
||||
- 应用:完善 fp 获取,添加强制更新入口
|
||||
- 图鉴:名片图鉴搜索支持搜索来源
|
||||
- 应用:支持修改数据目录 [`#78`](https://github.com/BTMuli/TeyvatGuide/issues/78)
|
||||
|
||||
### Fix
|
||||
|
||||
- 应用:修复首页启动卡数据加载 [`#79`](https://github.com/BTMuli/TeyvatGuide/issues/79)
|
||||
- 应用:修复 macOS 启动崩溃 [`#82`](https://github.com/BTMuli/TeyvatGuide/issues/82)
|
||||
- 图鉴:完善切换时的底部 hint
|
||||
|
||||
### Change
|
||||
|
||||
- 图鉴:卡牌图鉴样式重构
|
||||
- 组件:统一底部弹窗样式
|
||||
- 应用:调整部分点击跳转逻辑
|
||||
|
||||
## [0.4.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.0) (2024-01-15)
|
||||
|
||||
### Feat
|
||||
|
||||
- 应用:实装角色、武器、名片图鉴
|
||||
- JSBridge:添加窗口旋转子菜单
|
||||
- 应用:更新米社 salt 版本
|
||||
- 帖子:完成 `video` 类型数据的渲染 [`#77`](https://github.com/BTMuli/TeyvatGuide/issues/77)
|
||||
|
||||
### Fix
|
||||
|
||||
- wiki:修复流浪者数据错误
|
||||
- 应用:添加夏沃蕾、究极霸王超级魔剑的数据
|
||||
- 帖子:修复部分格式图片渲染失败
|
||||
- 公告:优化公告详情在深色模式下的表现
|
||||
- JSBridge:修复登录态错误
|
||||
- 应用:类型重构 [`#51`](https://github.com/BTMuli/TeyvatGuide/issues/51)
|
||||
- 应用:完善数据库完整性检测
|
||||
|
||||
### Change
|
||||
|
||||
- 应用:调整 `snackbar` 样式
|
||||
- 应用:取消 `transparent` 配置
|
||||
@@ -13,6 +13,7 @@ export default [
|
||||
"pnpm-lock.yaml",
|
||||
"src/data/**/*.json",
|
||||
"src-tauri/tauri.conf.json",
|
||||
"src-tauri/gen/*.json",
|
||||
"qodana.yaml",
|
||||
".github",
|
||||
".vscode",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<html lang="en" style="background: #1e1e1e">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
|
||||
|
||||
61
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "TeyvatGuide",
|
||||
"version": "0.4.9",
|
||||
"version": "0.5.0",
|
||||
"description": "Game Tool for Genshin Impact player",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -20,7 +20,7 @@
|
||||
"tauri:icon": "tauri icon ./public/icon.png",
|
||||
"vite:dev": "vite dev",
|
||||
"vite:build": "vite build",
|
||||
"prepare": "husky install"
|
||||
"prepare": "husky"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.ts": [
|
||||
@@ -66,54 +66,61 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdi/font": "7.4.47",
|
||||
"@tauri-apps/api": "^1.5.6",
|
||||
"@tauri-apps/api": "2.0.0-beta.14",
|
||||
"@tauri-apps/plugin-deep-link": "2.0.0-beta.8",
|
||||
"@tauri-apps/plugin-dialog": "2.0.0-beta.6",
|
||||
"@tauri-apps/plugin-fs": "2.0.0-beta.6",
|
||||
"@tauri-apps/plugin-http": "2.0.0-beta.7",
|
||||
"@tauri-apps/plugin-log": "2.0.0-beta.7",
|
||||
"@tauri-apps/plugin-os": "2.0.0-beta.6",
|
||||
"@tauri-apps/plugin-process": "2.0.0-beta.6",
|
||||
"@tauri-apps/plugin-shell": "2.0.0-beta.7",
|
||||
"@tauri-apps/plugin-sql": "2.0.0-beta.6",
|
||||
"ajv": "^8.16.0",
|
||||
"artplayer": "^5.1.5",
|
||||
"artplayer": "^5.1.6",
|
||||
"clipboard": "^2.0.11",
|
||||
"color-convert": "^2.0.1",
|
||||
"echarts": "^5.5.0",
|
||||
"echarts": "^5.5.1",
|
||||
"html2canvas": "^1.4.1",
|
||||
"js-md5": "^0.8.3",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"qrcode.vue": "^3.4.1",
|
||||
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v1",
|
||||
"tauri-plugin-sql-api": "github:tauri-apps/tauri-plugin-sql#v1",
|
||||
"uuid": "^10.0.0",
|
||||
"vue": "^3.4.27",
|
||||
"vue": "^3.4.31",
|
||||
"vue-echarts": "^6.7.3",
|
||||
"vue-json-viewer": "^3.0.4",
|
||||
"vue-router": "^4.3.3",
|
||||
"vuetify": "^3.6.9",
|
||||
"vue-router": "^4.4.0",
|
||||
"vuetify": "^3.6.11",
|
||||
"wcag-color": "^1.1.1",
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "^9.4.0",
|
||||
"@tauri-apps/cli": "^1.5.14",
|
||||
"@eslint/js": "^9.6.0",
|
||||
"@tauri-apps/cli": "2.0.0-beta.21",
|
||||
"@types/color-convert": "^2.0.3",
|
||||
"@types/js-md5": "^0.7.2",
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@typescript-eslint/parser": "^7.13.0",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/parser": "^7.15.0",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"concurrently": "^8.2.2",
|
||||
"eslint": "^9.4.0",
|
||||
"eslint-config-love": "^52.0.0",
|
||||
"eslint": "^9.6.0",
|
||||
"eslint-config-love": "^53.0.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsonc": "^2.16.0",
|
||||
"eslint-plugin-n": "^17.8.1",
|
||||
"eslint-plugin-n": "^17.9.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-promise": "^6.2.0",
|
||||
"eslint-plugin-vue": "^9.26.0",
|
||||
"eslint-plugin-promise": "^6.4.0",
|
||||
"eslint-plugin-vue": "^9.27.0",
|
||||
"eslint-plugin-yml": "^1.14.0",
|
||||
"globals": "^15.4.0",
|
||||
"globals": "^15.8.0",
|
||||
"husky": "^9.0.11",
|
||||
"jsonc-eslint-parser": "^2.4.0",
|
||||
"lint-staged": "^15.2.6",
|
||||
"oxlint": "^0.4.3",
|
||||
"lint-staged": "^15.2.7",
|
||||
"oxlint": "^0.5.2",
|
||||
"prettier": "3.3.2",
|
||||
"stylelint": "^16.6.1",
|
||||
"stylelint-config-idiomatic-order": "^10.0.0",
|
||||
@@ -122,10 +129,10 @@
|
||||
"stylelint-high-performance-animation": "^1.10.0",
|
||||
"stylelint-order": "^6.0.4",
|
||||
"stylelint-prettier": "^5.0.0",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-eslint": "^7.13.0",
|
||||
"vite": "^5.2.13",
|
||||
"vite-plugin-vue-devtools": "^7.2.1",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript-eslint": "^7.15.0",
|
||||
"vite": "^5.3.3",
|
||||
"vite-plugin-vue-devtools": "^7.3.5",
|
||||
"vite-plugin-vuetify": "^2.0.3",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"yaml-eslint-parser": "^1.2.3"
|
||||
|
||||
1418
pnpm-lock.yaml
generated
BIN
public/WIKI/GCG/normal/「看到那小子挣钱…」.webp
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
public/WIKI/GCG/normal/「究极霸王超级魔剑」.webp
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
public/WIKI/GCG/normal/不明流通渠道.webp
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
public/WIKI/GCG/normal/冰雅刺剑.webp
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
public/WIKI/GCG/normal/勘探钻机.webp
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
public/WIKI/GCG/normal/噔噔!.webp
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
public/WIKI/GCG/normal/夏沃蕾.webp
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
public/WIKI/GCG/normal/娜维娅.webp
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
public/WIKI/GCG/normal/尖兵协同战法.webp
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
public/WIKI/GCG/normal/愚人众·霜役人.webp
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
public/WIKI/GCG/normal/瑟琳.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/WIKI/GCG/normal/角斗士的凯旋.webp
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
public/WIKI/character/10000099.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/WIKI/weapon/13513.webp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/icon/constellations/UI_Talent_S_Emilie_01.webp
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
public/icon/constellations/UI_Talent_S_Emilie_02.webp
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
public/icon/constellations/UI_Talent_S_Emilie_03.webp
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/icon/constellations/UI_Talent_S_Emilie_04.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/icon/constellations/UI_Talent_U_Emilie_01.webp
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/icon/constellations/UI_Talent_U_Emilie_02.webp
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
public/icon/material/140014.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/icon/talents/Skill_E_Emilie_01.webp
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/icon/talents/Skill_S_Emilie_01.webp
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/icon/talents/UI_Talent_S_Emilie_05.webp
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
public/icon/talents/UI_Talent_S_Emilie_06.webp
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
public/icon/talents/UI_Talent_S_Emilie_07.webp
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
public/source/nameCard/bg/塞索斯·跋灵.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/source/nameCard/bg/庆典·盛宴·其二.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/source/nameCard/bg/纪行·拟像.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/source/nameCard/bg/艾梅莉埃·后调.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/source/nameCard/icon/塞索斯·跋灵.webp
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
public/source/nameCard/icon/庆典·盛宴·其二.webp
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
public/source/nameCard/icon/纪行·拟像.webp
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
public/source/nameCard/icon/艾梅莉埃·后调.webp
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
public/source/nameCard/profile/塞索斯·跋灵.webp
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
public/source/nameCard/profile/庆典·盛宴·其二.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/source/nameCard/profile/纪行·拟像.webp
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
public/source/nameCard/profile/艾梅莉埃·后调.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
2907
src-tauri/Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "TeyvatGuide"
|
||||
version = "0.4.9"
|
||||
version = "0.5.0"
|
||||
description = "Game Tool for Genshin Impact player"
|
||||
authors = ["BTMuli <bt-muli@outlook.com>"]
|
||||
license = "MIT"
|
||||
@@ -10,39 +10,69 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.5.2", features = [] }
|
||||
tauri-build = { version = "2.0.0-beta.18", features = [] }
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.38"
|
||||
log = "0.4.21"
|
||||
serde = { version = "1.0.203", features = ["derive"] }
|
||||
serde_json = "1.0.117"
|
||||
tauri = { version = "1.6.8", features = [ "shell-execute", "shell-open", "window-set-always-on-top", "window-set-fullscreen", "dialog-message", "process-exit", "fs-read-dir", "window-hide", "os-all", "clipboard-all", "dialog-open", "dialog-save", "fs-create-dir", "fs-remove-dir", "fs-write-file", "fs-remove-file", "fs-read-file", "path-all", "fs-exists", "window-close", "window-set-title", "window-unminimize", "window-show", "window-set-focus", "http-request"] }
|
||||
tauri-utils = "1.5.4"
|
||||
url = "2.5.1"
|
||||
log = "0.4.22"
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
serde_json = "1.0.120"
|
||||
tauri = { version = "2.0.0-beta.23", features = [] }
|
||||
tauri-utils = "2.0.0-beta.18"
|
||||
url = "2.5.2"
|
||||
walkdir = "2.5.0"
|
||||
|
||||
# sqlite 插件
|
||||
[dependencies.tauri-plugin-sql]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v1"
|
||||
features = ["sqlite"]
|
||||
|
||||
# deep link 插件
|
||||
[dependencies.tauri-plugin-deep-link]
|
||||
version = "0.1.2"
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v2"
|
||||
|
||||
# dialog 插件
|
||||
[dependencies.tauri-plugin-dialog]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v2"
|
||||
|
||||
# fs 插件
|
||||
[dependencies.tauri-plugin-fs]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v2"
|
||||
|
||||
# http 插件
|
||||
[dependencies.tauri-plugin-http]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v2"
|
||||
features = ["unsafe-headers"]
|
||||
|
||||
# log 插件
|
||||
[dependencies.tauri-plugin-log]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v1"
|
||||
branch = "v2"
|
||||
|
||||
# 用于打包
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = "s"
|
||||
panic = "abort"
|
||||
# os 插件
|
||||
[dependencies.tauri-plugin-os]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v2"
|
||||
|
||||
# process 插件
|
||||
[dependencies.tauri-plugin-process]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v2"
|
||||
|
||||
# shell 插件
|
||||
[dependencies.tauri-plugin-shell]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v2"
|
||||
|
||||
# single-instance 插件
|
||||
[dependencies.tauri-plugin-single-instance]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v2"
|
||||
|
||||
# sqlite 插件
|
||||
[dependencies.tauri-plugin-sql]
|
||||
git = "https://github.com/tauri-apps/plugins-workspace"
|
||||
branch = "v2"
|
||||
features = ["sqlite"]
|
||||
|
||||
[features]
|
||||
# this feature is used for production builds or when `devPath` points to the filesystem
|
||||
|
||||
37
src-tauri/capabilities/DevJson.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "DevJson",
|
||||
"description": "Capability for the dev json window",
|
||||
"windows": ["Dev_JSON"],
|
||||
"permissions": [
|
||||
"app:allow-version",
|
||||
"app:default",
|
||||
"event:allow-listen",
|
||||
"event:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"path:allow-resolve-directory",
|
||||
"path:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"window:allow-close",
|
||||
"window:allow-destroy",
|
||||
"window:allow-set-title",
|
||||
"window:allow-set-fullscreen",
|
||||
"window:allow-show",
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://*.miyoushe.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.mihoyo.com/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
}
|
||||
45
src-tauri/capabilities/Mys.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "Mys",
|
||||
"description": "Capability for the mys client window",
|
||||
"windows": ["mhy_client"],
|
||||
"permissions": [
|
||||
"dialog:allow-message",
|
||||
"dialog:default",
|
||||
"event:allow-emit",
|
||||
"path:allow-resolve-directory",
|
||||
"path:default",
|
||||
{
|
||||
"identifier": "fs:allow-exists",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-mkdir",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-dir",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-text-file",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-remove",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-file",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-text-file",
|
||||
"allow": [{ "path": "**" }]
|
||||
}
|
||||
],
|
||||
"remote": {
|
||||
"urls": ["https://*.mihoyo.com/*", "https://*.miyoushe.com/*"]
|
||||
},
|
||||
"platforms": ["windows", "macOS"]
|
||||
}
|
||||
70
src-tauri/capabilities/SubWindow.json
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "SubWindow",
|
||||
"description": "Capability for the sub window",
|
||||
"windows": ["Sub_window"],
|
||||
"permissions": [
|
||||
"app:allow-version",
|
||||
"app:default",
|
||||
"dialog:allow-save",
|
||||
"dialog:default",
|
||||
"event:allow-listen",
|
||||
"event:default",
|
||||
"fs:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"path:allow-resolve-directory",
|
||||
"path:default",
|
||||
"shell:allow-open",
|
||||
"shell:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"window:allow-close",
|
||||
"window:allow-destroy",
|
||||
"window:allow-set-title",
|
||||
"window:allow-set-fullscreen",
|
||||
"window:allow-show",
|
||||
{
|
||||
"identifier": "fs:allow-exists",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-mkdir",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-dir",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-text-file",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-remove",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-file",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-text-file",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://*.miyoushe.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.mihoyo.com/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
}
|
||||
96
src-tauri/capabilities/TeyvatGuide.json
Normal file
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "TeyvatGuide",
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["TeyvatGuide"],
|
||||
"permissions": [
|
||||
"app:allow-version",
|
||||
"app:default",
|
||||
"dialog:allow-save",
|
||||
"dialog:default",
|
||||
"event:allow-listen",
|
||||
"event:default",
|
||||
"fs:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"path:allow-resolve-directory",
|
||||
"path:default",
|
||||
"process:allow-exit",
|
||||
"process:default",
|
||||
"shell:allow-execute",
|
||||
"shell:allow-open",
|
||||
"shell:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"webview:allow-create-webview-window",
|
||||
"webview:default",
|
||||
"window:allow-close",
|
||||
"window:allow-destroy",
|
||||
"window:default",
|
||||
"window:allow-is-minimized",
|
||||
"window:allow-set-title",
|
||||
"window:allow-set-focus",
|
||||
"window:allow-show",
|
||||
"window:allow-unminimize",
|
||||
{
|
||||
"identifier": "fs:allow-exists",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-mkdir",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-dir",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-text-file",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-remove",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-file",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-text-file",
|
||||
"allow": [{ "path": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://*.miyoushe.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.mihoyo.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://homa.snapgenshin.com/*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "shell:allow-execute",
|
||||
"allow": [
|
||||
{
|
||||
"name": "win_open",
|
||||
"cmd": "explorer",
|
||||
"args": true
|
||||
},
|
||||
{
|
||||
"name": "mac_open",
|
||||
"cmd": "open",
|
||||
"args": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
}
|
||||
3624
src-tauri/gen/schemas/acl-manifests.json
Normal file
157
src-tauri/gen/schemas/capabilities.json
Normal file
@@ -0,0 +1,157 @@
|
||||
{
|
||||
"DevJson": {
|
||||
"identifier": "DevJson",
|
||||
"description": "Capability for the dev json window",
|
||||
"local": true,
|
||||
"windows": ["Dev_JSON"],
|
||||
"permissions": [
|
||||
"app:allow-version",
|
||||
"app:default",
|
||||
"event:allow-listen",
|
||||
"event:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"path:allow-resolve-directory",
|
||||
"path:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"window:allow-close",
|
||||
"window:allow-destroy",
|
||||
"window:allow-set-title",
|
||||
"window:allow-set-fullscreen",
|
||||
"window:allow-show",
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [{ "url": "https://*.miyoushe.com/*" }, { "url": "https://*.mihoyo.com/*" }]
|
||||
}
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
},
|
||||
"Mys": {
|
||||
"identifier": "Mys",
|
||||
"description": "Capability for the mys client window",
|
||||
"remote": { "urls": ["https://*.mihoyo.com/*", "https://*.miyoushe.com/*"] },
|
||||
"local": true,
|
||||
"windows": ["mhy_client"],
|
||||
"permissions": [
|
||||
"dialog:allow-message",
|
||||
"dialog:default",
|
||||
"event:allow-emit",
|
||||
"path:allow-resolve-directory",
|
||||
"path:default",
|
||||
{ "identifier": "fs:allow-exists", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-mkdir", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-read-dir", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-read-text-file", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-remove", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-write-file", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-write-text-file", "allow": [{ "path": "**" }] }
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
},
|
||||
"SubWindow": {
|
||||
"identifier": "SubWindow",
|
||||
"description": "Capability for the sub window",
|
||||
"local": true,
|
||||
"windows": ["Sub_window"],
|
||||
"permissions": [
|
||||
"app:allow-version",
|
||||
"app:default",
|
||||
"dialog:allow-save",
|
||||
"dialog:default",
|
||||
"event:allow-listen",
|
||||
"event:default",
|
||||
"fs:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"path:allow-resolve-directory",
|
||||
"path:default",
|
||||
"shell:allow-open",
|
||||
"shell:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"window:allow-close",
|
||||
"window:allow-destroy",
|
||||
"window:allow-set-title",
|
||||
"window:allow-set-fullscreen",
|
||||
"window:allow-show",
|
||||
{ "identifier": "fs:allow-exists", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-mkdir", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-read-dir", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-read-text-file", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-remove", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-write-file", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-write-text-file", "allow": [{ "path": "**" }] },
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [{ "url": "https://*.miyoushe.com/*" }, { "url": "https://*.mihoyo.com/*" }]
|
||||
}
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
},
|
||||
"TeyvatGuide": {
|
||||
"identifier": "TeyvatGuide",
|
||||
"description": "Capability for the main window",
|
||||
"local": true,
|
||||
"windows": ["TeyvatGuide"],
|
||||
"permissions": [
|
||||
"app:allow-version",
|
||||
"app:default",
|
||||
"dialog:allow-save",
|
||||
"dialog:default",
|
||||
"event:allow-listen",
|
||||
"event:default",
|
||||
"fs:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"path:allow-resolve-directory",
|
||||
"path:default",
|
||||
"process:allow-exit",
|
||||
"process:default",
|
||||
"shell:allow-execute",
|
||||
"shell:allow-open",
|
||||
"shell:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"webview:allow-create-webview-window",
|
||||
"webview:default",
|
||||
"window:allow-close",
|
||||
"window:allow-destroy",
|
||||
"window:default",
|
||||
"window:allow-is-minimized",
|
||||
"window:allow-set-title",
|
||||
"window:allow-set-focus",
|
||||
"window:allow-show",
|
||||
"window:allow-unminimize",
|
||||
{ "identifier": "fs:allow-exists", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-mkdir", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-read-dir", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-read-text-file", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-remove", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-write-file", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-write-text-file", "allow": [{ "path": "**" }] },
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{ "url": "https://*.miyoushe.com/*" },
|
||||
{ "url": "https://*.mihoyo.com/*" },
|
||||
{ "url": "https://homa.snapgenshin.com/*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "shell:allow-execute",
|
||||
"allow": [
|
||||
{ "args": true, "cmd": "explorer", "name": "win_open" },
|
||||
{ "args": true, "cmd": "open", "name": "mac_open" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
}
|
||||
}
|
||||
5130
src-tauri/gen/schemas/desktop-schema.json
Normal file
5130
src-tauri/gen/schemas/windows-schema.json
Normal file
@@ -1,11 +1,13 @@
|
||||
//! @file src/client/menu.rs
|
||||
//! @desc 客户端菜单模块,负责操作米游社客户端菜单
|
||||
//! @since Beta v0.4.5
|
||||
//! @since Beta v0.5.0
|
||||
|
||||
use tauri::{AppHandle, CustomMenuItem, LogicalSize, Manager, Menu, Size, Submenu, WindowUrl};
|
||||
use tauri::menu::{Menu, MenuBuilder, MenuEvent, MenuItemBuilder, Submenu, SubmenuBuilder};
|
||||
use tauri::{AppHandle, LogicalSize, Manager, Size, Window, Wry};
|
||||
use tauri_utils::config::WebviewUrl;
|
||||
use url::Url;
|
||||
|
||||
pub fn get_mhy_client_url(func: String) -> WindowUrl {
|
||||
pub fn get_mhy_client_url(func: String) -> WebviewUrl {
|
||||
let mut url_res: Url = "https://bbs.mihoyo.com/ys/".parse().unwrap();
|
||||
if func == "sign_in" {
|
||||
url_res = "https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?act_id=e202009291139501"
|
||||
@@ -13,105 +15,81 @@ pub fn get_mhy_client_url(func: String) -> WindowUrl {
|
||||
.unwrap();
|
||||
} else if func == "game_record" {
|
||||
url_res =
|
||||
"https://webstatic.mihoyo.com/app/community-game-records/index.html?bbs_presentation_style=fullscreen".parse().unwrap();
|
||||
"https://webstatic.mihoyo.com/app/community-game-records/index.html?bbs_presentation_style=fullscreen".parse().unwrap();
|
||||
} else if func == "birthday" {
|
||||
url_res = "https://webstatic.mihoyo.com/ys/event/e20220303-birthday/index.html?activity_id=20220301153521"
|
||||
.parse()
|
||||
.unwrap();
|
||||
.parse()
|
||||
.unwrap();
|
||||
}
|
||||
return WindowUrl::External(url_res);
|
||||
return WebviewUrl::External(url_res);
|
||||
}
|
||||
|
||||
// 创建子菜单-工具
|
||||
fn create_utils_menu() -> Menu {
|
||||
let retry_bridge = CustomMenuItem::new("retry".to_string(), "重试桥接");
|
||||
let mock_touch = CustomMenuItem::new("mock_touch".to_string(), "模拟触摸");
|
||||
let remove_overlay = CustomMenuItem::new("remove_overlay".to_string(), "移除遮罩");
|
||||
let rotate_window = CustomMenuItem::new("rotate_window".to_string(), "旋转窗口");
|
||||
let switch_ua = CustomMenuItem::new("switch_ua".to_string(), "切换 UA");
|
||||
return Menu::new()
|
||||
.add_item(retry_bridge)
|
||||
.add_item(mock_touch)
|
||||
.add_item(remove_overlay)
|
||||
.add_item(rotate_window);
|
||||
fn create_utils_menu(app: AppHandle) -> Submenu<Wry> {
|
||||
let retry_bridge_submenu = MenuItemBuilder::with_id("retry", "重试桥接").build(&app).unwrap();
|
||||
let mock_touch_submenu = MenuItemBuilder::with_id("mock_touch", "模拟触摸").build(&app).unwrap();
|
||||
let remove_overlay_submenu =
|
||||
MenuItemBuilder::with_id("remove_overlay", "移除遮罩").build(&app).unwrap();
|
||||
let rotate_window_submenu =
|
||||
MenuItemBuilder::with_id("rotate_window", "旋转窗口").build(&app).unwrap();
|
||||
let utils_menu = SubmenuBuilder::new(&app, "工具")
|
||||
.item(&retry_bridge_submenu)
|
||||
.item(&mock_touch_submenu)
|
||||
.item(&remove_overlay_submenu)
|
||||
.item(&rotate_window_submenu)
|
||||
.build()
|
||||
.expect("failed to create utils_menu");
|
||||
return utils_menu;
|
||||
}
|
||||
|
||||
// 创建米游社客户端菜单
|
||||
pub fn create_mhy_menu(func: String) -> Menu {
|
||||
let top = CustomMenuItem::new("top".to_string(), "置顶");
|
||||
let cancel_top = CustomMenuItem::new("cancel_top".to_string(), "取消置顶");
|
||||
let sign_in = CustomMenuItem::new("sign_in".to_string(), "用户登录");
|
||||
let open_post = CustomMenuItem::new("open_post".to_string(), "打开帖子");
|
||||
let utils_menu = Submenu::new("工具".to_string(), create_utils_menu());
|
||||
// 如果是登录
|
||||
if func == "config_sign_in" {
|
||||
return Menu::new().add_item(sign_in);
|
||||
}
|
||||
return Menu::new()
|
||||
.add_item(top)
|
||||
.add_item(cancel_top)
|
||||
.add_item(open_post)
|
||||
.add_submenu(utils_menu);
|
||||
pub fn create_mhy_menu(app: AppHandle) -> Menu<Wry> {
|
||||
let top_menu = MenuItemBuilder::with_id("top", "置顶").build(&app).unwrap();
|
||||
let cancel_top_menu = MenuItemBuilder::with_id("cancel_top", "取消置顶").build(&app).unwrap();
|
||||
let open_post_menu = MenuItemBuilder::with_id("open_post", "打开帖子").build(&app).unwrap();
|
||||
let utils_menu = create_utils_menu(app.clone());
|
||||
return MenuBuilder::new(&app)
|
||||
.item(&top_menu)
|
||||
.item(&cancel_top_menu)
|
||||
.item(&open_post_menu)
|
||||
.item(&utils_menu)
|
||||
.build()
|
||||
.expect("failed to create mhy_menu");
|
||||
}
|
||||
|
||||
// 菜单栏事件处理
|
||||
pub fn handle_menu_event(app_handle: AppHandle, event: tauri::MenuEvent) {
|
||||
match event.menu_item_id() {
|
||||
"top" => handle_menu_top(app_handle),
|
||||
"cancel_top" => handle_menu_cancel_top(app_handle),
|
||||
"sign_in" => handle_menu_sign_in(app_handle),
|
||||
"open_post" => handle_menu_open_post(app_handle),
|
||||
"retry" => handle_menu_retry(app_handle),
|
||||
"mock_touch" => handle_menu_mock_touch(app_handle),
|
||||
"remove_overlay" => handle_menu_remove_overlay(app_handle),
|
||||
"rotate_window" => handle_menu_rotate_window(app_handle),
|
||||
"switch_ua" => handle_menu_switch_ua(app_handle),
|
||||
pub fn handle_menu_event(window: &Window, event: MenuEvent) {
|
||||
match event.id.as_ref() {
|
||||
"top" => handle_menu_top(window),
|
||||
"cancel_top" => handle_menu_cancel_top(window),
|
||||
"open_post" => handle_menu_open_post(window),
|
||||
"retry" => handle_menu_retry(window),
|
||||
"mock_touch" => handle_menu_mock_touch(window),
|
||||
"remove_overlay" => handle_menu_remove_overlay(window),
|
||||
"rotate_window" => handle_menu_rotate_window(window),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理置顶菜单
|
||||
fn handle_menu_top(app_handle: AppHandle) {
|
||||
let window = app_handle.get_window("mhy_client");
|
||||
fn handle_menu_top(app_handle: &Window) {
|
||||
let window = app_handle.get_webview_window("mhy_client");
|
||||
if window.is_some() {
|
||||
window.unwrap().set_always_on_top(true).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// 处理取消置顶菜单
|
||||
fn handle_menu_cancel_top(app_handle: AppHandle) {
|
||||
let window = app_handle.get_window("mhy_client");
|
||||
fn handle_menu_cancel_top(app_handle: &Window) {
|
||||
let window = app_handle.get_webview_window("mhy_client");
|
||||
if window.is_some() {
|
||||
window.unwrap().set_always_on_top(false).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// 处理用户登录菜单
|
||||
fn handle_menu_sign_in(app_handle: AppHandle) {
|
||||
let window = app_handle.get_window("mhy_client");
|
||||
let execute_js = r#"
|
||||
javascript:(async function(){
|
||||
// 首先检测是不是 user.mihoyo.com
|
||||
const url = new URL(window.location.href);
|
||||
if(url.hostname !== "user.mihoyo.com"){
|
||||
alert("当前页面不是米游社登录页面");
|
||||
return;
|
||||
}
|
||||
const ck = document.cookie;
|
||||
const arg = {
|
||||
method: 'teyvat_sign_in',
|
||||
payload: ck,
|
||||
}
|
||||
await window.__TAURI__.event.emit('post_mhy_client',JSON.stringify(arg));
|
||||
})()"#;
|
||||
if window.is_some() {
|
||||
window.unwrap().eval(&execute_js).ok().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// 处理打开帖子菜单
|
||||
fn handle_menu_open_post(app_handle: AppHandle) {
|
||||
let window = app_handle.get_window("mhy_client");
|
||||
fn handle_menu_open_post(app_handle: &Window) {
|
||||
let window = app_handle.get_webview_window("mhy_client");
|
||||
let execute_js = r#"
|
||||
javascript:(async function(){
|
||||
let url = new URL(window.location.href);
|
||||
@@ -150,8 +128,8 @@ fn handle_menu_open_post(app_handle: AppHandle) {
|
||||
}
|
||||
|
||||
// 处理重试桥接菜单
|
||||
fn handle_menu_retry(app_handle: AppHandle) {
|
||||
let window = app_handle.get_window("mhy_client");
|
||||
fn handle_menu_retry(app_handle: &Window) {
|
||||
let window = app_handle.get_webview_window("mhy_client");
|
||||
let execute_js = r#"
|
||||
javascript:(async function(){
|
||||
const arg = {
|
||||
@@ -165,8 +143,8 @@ fn handle_menu_retry(app_handle: AppHandle) {
|
||||
}
|
||||
|
||||
// 处理模拟触摸菜单
|
||||
fn handle_menu_mock_touch(app_handle: AppHandle) {
|
||||
let window = app_handle.get_window("mhy_client");
|
||||
fn handle_menu_mock_touch(app_handle: &Window) {
|
||||
let window = app_handle.get_webview_window("mhy_client");
|
||||
let execute_js = r#"
|
||||
javascript:(async function(){
|
||||
const arg = {
|
||||
@@ -180,8 +158,8 @@ fn handle_menu_mock_touch(app_handle: AppHandle) {
|
||||
}
|
||||
|
||||
// 处理移除遮罩菜单
|
||||
fn handle_menu_remove_overlay(app_handle: AppHandle) {
|
||||
let window = app_handle.get_window("mhy_client");
|
||||
fn handle_menu_remove_overlay(app_handle: &Window) {
|
||||
let window = app_handle.get_webview_window("mhy_client");
|
||||
let execute_js = r#"
|
||||
javascript:(async function(){
|
||||
const arg = {
|
||||
@@ -195,8 +173,8 @@ fn handle_menu_remove_overlay(app_handle: AppHandle) {
|
||||
}
|
||||
|
||||
// 处理旋转窗口菜单
|
||||
fn handle_menu_rotate_window(app_handle: AppHandle) {
|
||||
let window_get = app_handle.get_window("mhy_client");
|
||||
fn handle_menu_rotate_window(app_handle: &Window) {
|
||||
let window_get = app_handle.get_webview_window("mhy_client");
|
||||
if window_get == None {
|
||||
return;
|
||||
}
|
||||
@@ -211,23 +189,3 @@ fn handle_menu_rotate_window(app_handle: AppHandle) {
|
||||
window.center().unwrap();
|
||||
window.set_focus().unwrap();
|
||||
}
|
||||
|
||||
// 处理切换 UA 菜单
|
||||
fn handle_menu_switch_ua(app_handle: AppHandle) {
|
||||
let window = app_handle.get_window("mhy_client");
|
||||
let execute_js = r#"
|
||||
javascript:(async function(){
|
||||
const isPc = navigator.userAgent.includes("Windows NT");
|
||||
const arg = {
|
||||
method: 'teyvat_switch_ua',
|
||||
payload: {
|
||||
url: window.location.href,
|
||||
isPc,
|
||||
}
|
||||
}
|
||||
await window.__TAURI__.event.emit('post_mhy_client',JSON.stringify(arg));
|
||||
})()"#;
|
||||
if window.is_some() {
|
||||
window.unwrap().eval(&execute_js).ok().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,41 @@
|
||||
//! @file src/client/mod.rs
|
||||
//! @desc 客户端模块,负责操作米游社客户端
|
||||
//! @since Beta v0.4.5
|
||||
//! @since Beta v0.5.0
|
||||
|
||||
mod menu;
|
||||
use tauri::async_runtime::block_on;
|
||||
use tauri::{AppHandle, Manager, WindowBuilder, WindowEvent, WindowUrl};
|
||||
use tauri::{AppHandle, Manager, WebviewWindowBuilder};
|
||||
use tauri_utils::config::WebviewUrl;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn create_mhy_client(handle: AppHandle, func: String, url: String) {
|
||||
let mut mhy_window_config = handle.config().tauri.windows.get(1).unwrap().clone();
|
||||
mhy_window_config.visible = true;
|
||||
let mut win_width = 400.0;
|
||||
let mut win_height = 800.0;
|
||||
let win_ua = "Mozilla/5.0 (Linux; Android 12) Mobile miHoYoBBS/2.72.2";
|
||||
let url_parse;
|
||||
if url != "" {
|
||||
mhy_window_config.url = WindowUrl::External(url.parse().unwrap());
|
||||
url_parse = WebviewUrl::External(url.parse().unwrap());
|
||||
} else {
|
||||
mhy_window_config.url = menu::get_mhy_client_url(func.clone());
|
||||
url_parse = menu::get_mhy_client_url(func.clone());
|
||||
}
|
||||
// if pc {
|
||||
// let user_agent = mhy_window_config.user_agent.as_ref().unwrap();
|
||||
// let version = user_agent.split("/").last().unwrap();
|
||||
// mhy_window_config.user_agent = Some(format!("Mozilla/5.0 (Windows NT 10.0; Win64; x64) miHoYoBBS/{}", version));
|
||||
// }
|
||||
if func == "birthday"
|
||||
|| func == "web_act"
|
||||
|| url.starts_with("https://webstatic.mihoyo.com/ys/event/e20220303-birthday/index.html")
|
||||
{
|
||||
mhy_window_config.width = 1280.0;
|
||||
mhy_window_config.height = 720.0;
|
||||
win_width = 1280.0;
|
||||
win_height = 720.0;
|
||||
}
|
||||
let window_get = handle.get_window("mhy_client");
|
||||
if window_get.is_some() {
|
||||
let mhy_client = window_get.unwrap();
|
||||
mhy_client.on_window_event(move |e| {
|
||||
if let WindowEvent::Destroyed = e {
|
||||
let future = create_mhy_client(handle.clone(), func.clone(), url.clone());
|
||||
block_on(future);
|
||||
}
|
||||
});
|
||||
mhy_client.close().unwrap();
|
||||
let window_find = handle.get_webview_window("mhy_client");
|
||||
if window_find.is_some() {
|
||||
window_find.unwrap().destroy().unwrap();
|
||||
return;
|
||||
}
|
||||
WindowBuilder::from_config(&handle, mhy_window_config)
|
||||
.menu(menu::create_mhy_menu(func))
|
||||
WebviewWindowBuilder::new(&handle, "mhy_client", url_parse)
|
||||
.inner_size(win_width, win_height)
|
||||
.title("米游社")
|
||||
.center()
|
||||
.user_agent(win_ua)
|
||||
.menu(menu::create_mhy_menu(handle.clone()))
|
||||
.on_menu_event(move |app, event| menu::handle_menu_event(app, event))
|
||||
.build()
|
||||
.expect("failed to create mhy_client")
|
||||
.on_menu_event(move |event| menu::handle_menu_event(handle.clone(), event));
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -1,74 +1,57 @@
|
||||
//! @file src/commands.rs
|
||||
//! @desc 命令模块,负责处理命令
|
||||
//! @since Beta v0.4.3
|
||||
//! @since Beta v0.5.0
|
||||
|
||||
use tauri::{Manager, WindowBuilder};
|
||||
use tauri_utils::config::WindowConfig;
|
||||
use tauri::{AppHandle, Manager, WebviewWindowBuilder};
|
||||
use tauri_utils::config::{WebviewUrl, WindowConfig};
|
||||
|
||||
// 放一个常数,用来判断应用是否初始化
|
||||
static mut APP_INITIALIZED: bool = false;
|
||||
static mut DEEP_LINK_REGISTERED: bool = false;
|
||||
|
||||
// 初始化应用
|
||||
#[tauri::command]
|
||||
pub async fn init_app(app_handle: tauri::AppHandle) {
|
||||
pub async fn init_app(app_handle: AppHandle) {
|
||||
unsafe {
|
||||
if APP_INITIALIZED == true && DEEP_LINK_REGISTERED == true {
|
||||
if APP_INITIALIZED == true {
|
||||
return;
|
||||
}
|
||||
}
|
||||
dbg!("init_app");
|
||||
let _mhy = app_handle.get_window("mhy_client");
|
||||
if _mhy.is_some() {
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
_mhy.unwrap().close().unwrap();
|
||||
}
|
||||
app_handle.emit_all("initApp", ()).unwrap();
|
||||
app_handle.emit("initApp", ()).unwrap();
|
||||
unsafe {
|
||||
APP_INITIALIZED = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 注册deep link
|
||||
#[tauri::command]
|
||||
pub async fn register_deep_link(app_handle: tauri::AppHandle) {
|
||||
unsafe {
|
||||
if DEEP_LINK_REGISTERED == true {
|
||||
return;
|
||||
}
|
||||
}
|
||||
dbg!("register_deep_link");
|
||||
tauri_plugin_deep_link::register("teyvatguide", move |request| {
|
||||
dbg!(&request);
|
||||
app_handle.emit_all("active_deep_link", request).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
unsafe {
|
||||
DEEP_LINK_REGISTERED = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建窗口
|
||||
#[tauri::command]
|
||||
pub async fn create_window(app_handle: tauri::AppHandle, label: String, mut option: WindowConfig) {
|
||||
let window_old = app_handle.get_window(&label);
|
||||
option.label = label.clone();
|
||||
if window_old.is_some() {
|
||||
dbg!("window exists");
|
||||
window_old.unwrap().close().unwrap();
|
||||
pub async fn create_window(
|
||||
app_handle: AppHandle,
|
||||
label: String,
|
||||
url: String,
|
||||
option: WindowConfig,
|
||||
) {
|
||||
let window_find = app_handle.get_webview_window(&label);
|
||||
if window_find.is_some() {
|
||||
window_find.unwrap().destroy().unwrap();
|
||||
return;
|
||||
}
|
||||
let window_new =
|
||||
Some(WindowBuilder::from_config(&app_handle, option).build().expect("failed to create window"));
|
||||
window_new.unwrap();
|
||||
let url_parse = WebviewUrl::App(url.parse().unwrap());
|
||||
WebviewWindowBuilder::new(&app_handle, &label, url_parse)
|
||||
.inner_size(option.width, option.height)
|
||||
.resizable(option.resizable)
|
||||
.visible(option.visible)
|
||||
.title(option.title)
|
||||
.center()
|
||||
.build()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// 执行 js
|
||||
#[tauri::command]
|
||||
pub async fn execute_js(app_handle: tauri::AppHandle, label: String, js: String) {
|
||||
let window = app_handle.get_window(&label);
|
||||
pub async fn execute_js(app_handle: AppHandle, label: String, js: String) {
|
||||
let window = app_handle.get_webview_window(&label);
|
||||
if window.is_some() {
|
||||
window.unwrap().eval(&js).ok().unwrap();
|
||||
window.unwrap().eval(&js).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! @file src/main.rs
|
||||
//! @desc 主模块,用于启动应用
|
||||
//! @since Beta v0.4.3
|
||||
//! @since Beta v0.5.0
|
||||
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
@@ -12,35 +12,43 @@ mod plugins;
|
||||
mod utils;
|
||||
|
||||
// 窗口事件处理
|
||||
fn window_event_handler(event: tauri::GlobalWindowEvent) -> () {
|
||||
match event.event() {
|
||||
fn window_event_handler(app: &tauri::Window, event: &tauri::WindowEvent) {
|
||||
match event {
|
||||
tauri::WindowEvent::CloseRequested { api, .. } => {
|
||||
api.prevent_close();
|
||||
let window = event.window().clone();
|
||||
if window.label() == "TeyvatGuide" {
|
||||
if app.label() == "TeyvatGuide" {
|
||||
// 子窗口 label 的数组
|
||||
const SUB_WINDOW_LABELS: [&str; 3] = ["Sub_window", "Dev_JSON", "mhy_client"];
|
||||
for label in SUB_WINDOW_LABELS.iter() {
|
||||
let sub = window.get_window(label);
|
||||
let sub = app.get_webview_window(label);
|
||||
if sub.is_some() {
|
||||
sub.unwrap().close().unwrap();
|
||||
sub.unwrap().destroy().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
window.close().unwrap();
|
||||
app.destroy().unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri_plugin_deep_link::prepare("teyvatguide");
|
||||
tauri::Builder::default()
|
||||
.on_window_event(|event| window_event_handler(event))
|
||||
.on_window_event(move |app, event| window_event_handler(app, event))
|
||||
.plugin(tauri_plugin_single_instance::init(|app, argv, _cwd| {
|
||||
app.emit("active_deep_link", argv).unwrap();
|
||||
}))
|
||||
.plugin(tauri_plugin_deep_link::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_http::init())
|
||||
.plugin(tauri_plugin_os::init())
|
||||
.plugin(tauri_plugin_process::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(plugins::build_sql_plugin())
|
||||
.plugin(plugins::build_log_plugin())
|
||||
.setup(|_app| {
|
||||
let _window = _app.get_window("TeyvatGuide");
|
||||
let _window = _app.get_webview_window("TeyvatGuide");
|
||||
#[cfg(debug_assertions)]
|
||||
if _window.is_some() {
|
||||
_window.unwrap().open_devtools();
|
||||
@@ -49,7 +57,6 @@ fn main() {
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::init_app,
|
||||
commands::register_deep_link,
|
||||
commands::create_window,
|
||||
commands::execute_js,
|
||||
commands::get_dir_size,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//! @file src/plugins.rs
|
||||
//! @desc 插件模块,用于注册插件
|
||||
//! @since Beta v0.4.4
|
||||
//! @since Beta v0.5.0
|
||||
|
||||
use super::utils;
|
||||
use log::LevelFilter;
|
||||
use tauri::plugin::TauriPlugin;
|
||||
use tauri::Runtime;
|
||||
use tauri_plugin_log::{LogTarget, TimezoneStrategy};
|
||||
use tauri_plugin_log::{Target, TargetKind, TimezoneStrategy};
|
||||
use tauri_plugin_sql::PluginConfig;
|
||||
|
||||
// sqlite 插件
|
||||
@@ -18,15 +18,17 @@ pub fn build_sql_plugin<R: Runtime>() -> TauriPlugin<R, Option<PluginConfig>> {
|
||||
pub fn build_log_plugin<R: Runtime>() -> TauriPlugin<R> {
|
||||
if cfg!(debug_assertions) {
|
||||
return tauri_plugin_log::Builder::default()
|
||||
.targets([LogTarget::Stdout])
|
||||
.targets([Target::new(TargetKind::Webview)])
|
||||
.timezone_strategy(TimezoneStrategy::UseLocal)
|
||||
.level(LevelFilter::Debug)
|
||||
.build();
|
||||
}
|
||||
return tauri_plugin_log::Builder::default()
|
||||
.targets([LogTarget::LogDir, LogTarget::Stdout])
|
||||
.targets([
|
||||
Target::new(TargetKind::Webview),
|
||||
Target::new(TargetKind::LogDir { file_name: utils::get_current_date().into() }),
|
||||
])
|
||||
.timezone_strategy(TimezoneStrategy::UseLocal)
|
||||
.level(LevelFilter::Info)
|
||||
.log_name(utils::get_current_date())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -1,159 +1,42 @@
|
||||
{
|
||||
"productName": "TeyvatGuide",
|
||||
"identifier": "TeyvatGuide",
|
||||
"version": "0.5.0",
|
||||
"build": {
|
||||
"beforeDevCommand": "pnpm vite:dev",
|
||||
"beforeBuildCommand": "pnpm vite:build",
|
||||
"devPath": "http://localhost:4000",
|
||||
"distDir": "../dist",
|
||||
"withGlobalTauri": true
|
||||
"devUrl": "http://localhost:4000",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"package": {
|
||||
"productName": "TeyvatGuide",
|
||||
"version": "0.4.9"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": false,
|
||||
"fs": {
|
||||
"all": false,
|
||||
"exists": true,
|
||||
"readFile": true,
|
||||
"readDir": true,
|
||||
"writeFile": true,
|
||||
"createDir": true,
|
||||
"removeDir": true,
|
||||
"removeFile": true,
|
||||
"scope": ["**", "**/*"]
|
||||
},
|
||||
"http": {
|
||||
"all": false,
|
||||
"request": true,
|
||||
"scope": ["http://**", "https://**"]
|
||||
},
|
||||
"dialog": {
|
||||
"all": false,
|
||||
"open": true,
|
||||
"save": true,
|
||||
"message": true
|
||||
},
|
||||
"clipboard": {
|
||||
"all": true
|
||||
},
|
||||
"path": {
|
||||
"all": true
|
||||
},
|
||||
"window": {
|
||||
"all": false,
|
||||
"close": true,
|
||||
"hide": true,
|
||||
"setAlwaysOnTop": true,
|
||||
"setFocus": true,
|
||||
"setFullscreen": true,
|
||||
"setTitle": true,
|
||||
"show": true,
|
||||
"unminimize": true
|
||||
},
|
||||
"os": {
|
||||
"all": true
|
||||
},
|
||||
"process": {
|
||||
"all": false,
|
||||
"exit": true
|
||||
},
|
||||
"shell": {
|
||||
"all": false,
|
||||
"open": true,
|
||||
"execute": true,
|
||||
"scope": [
|
||||
{
|
||||
"name": "win_open",
|
||||
"cmd": "explorer",
|
||||
"args": true
|
||||
},
|
||||
{
|
||||
"name": "mac_open",
|
||||
"cmd": "open",
|
||||
"args": true
|
||||
}
|
||||
]
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"icon": [
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/32x32.png",
|
||||
"icons/Square107x107Logo.png",
|
||||
"icons/Square142x142Logo.png",
|
||||
"icons/Square150x150Logo.png",
|
||||
"icons/Square284x284Logo.png",
|
||||
"icons/Square30x30Logo.png",
|
||||
"icons/Square310x310Logo.png",
|
||||
"icons/Square44x44Logo.png",
|
||||
"icons/Square71x71Logo.png",
|
||||
"icons/Square89x89Logo.png",
|
||||
"icons/StoreLogo.png",
|
||||
"icons/icon.ico",
|
||||
"icons/icon.png"
|
||||
],
|
||||
"targets": ["msi", "app", "dmg"],
|
||||
"windows": {
|
||||
"wix": {
|
||||
"language": "zh-CN"
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"icon": [
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/32x32.png",
|
||||
"icons/Square107x107Logo.png",
|
||||
"icons/Square142x142Logo.png",
|
||||
"icons/Square150x150Logo.png",
|
||||
"icons/Square284x284Logo.png",
|
||||
"icons/Square30x30Logo.png",
|
||||
"icons/Square310x310Logo.png",
|
||||
"icons/Square44x44Logo.png",
|
||||
"icons/Square71x71Logo.png",
|
||||
"icons/Square89x89Logo.png",
|
||||
"icons/StoreLogo.png",
|
||||
"icons/icon.ico",
|
||||
"icons/icon.png"
|
||||
],
|
||||
"identifier": "TeyvatGuide",
|
||||
"targets": ["msi", "app", "dmg"],
|
||||
"windows": {
|
||||
"wix": {
|
||||
"language": "zh-CN"
|
||||
}
|
||||
},
|
||||
"macOS": {}
|
||||
},
|
||||
"security": {
|
||||
"dangerousRemoteDomainIpcAccess": [
|
||||
{
|
||||
"domain": "act.mihoyo.com",
|
||||
"windows": ["mhy_client"],
|
||||
"enableTauriAPI": true
|
||||
},
|
||||
{
|
||||
"domain": "m.miyoushe.com",
|
||||
"windows": ["mhy_client"],
|
||||
"enableTauriAPI": true
|
||||
},
|
||||
{
|
||||
"domain": "qaa.miyoushe.com",
|
||||
"windows": ["mhy_client"],
|
||||
"enableTauriAPI": true
|
||||
},
|
||||
{
|
||||
"domain": "user.mihoyo.com",
|
||||
"windows": ["mhy_client"],
|
||||
"enableTauriAPI": true
|
||||
},
|
||||
{
|
||||
"domain": "webstatic.mihoyo.com",
|
||||
"windows": ["mhy_client"],
|
||||
"enableTauriAPI": true
|
||||
},
|
||||
{
|
||||
"domain": "bbs.mihoyo.com",
|
||||
"windows": ["mhy_client"],
|
||||
"enableTauriAPI": true
|
||||
},
|
||||
{
|
||||
"domain": "api-takumi-record.mihoyo.com",
|
||||
"windows": ["mhy_client"],
|
||||
"enableTauriAPI": true
|
||||
}
|
||||
],
|
||||
"csp": null
|
||||
},
|
||||
"updater": {
|
||||
"active": false,
|
||||
"dialog": true,
|
||||
"endpoints": [
|
||||
"https://raw.fastgit.org/BTMuli/TeyvatGuide/master/latest.json",
|
||||
"https://raw.kgithub.com/BTMuli/TeyvatGuide/master/latest.json"
|
||||
],
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDg2MkVGRjMxQzJDQzFBNTkKUldSWkdzekNNZjh1aHJGRXBEOGtwbUxLaU1wdWNVeUJaeGhoV2ZlZ3VlYmQ0b2tYZWQwODdnTHkK"
|
||||
},
|
||||
"macOS": {}
|
||||
},
|
||||
"app": {
|
||||
"withGlobalTauri": true,
|
||||
"windows": [
|
||||
{
|
||||
"fullscreen": false,
|
||||
@@ -162,22 +45,20 @@
|
||||
"label": "TeyvatGuide",
|
||||
"width": 1600,
|
||||
"height": 900,
|
||||
"center": true
|
||||
},
|
||||
{
|
||||
"fullscreen": false,
|
||||
"resizable": false,
|
||||
"title": "米游社",
|
||||
"label": "mhy_client",
|
||||
"url": "",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 12) Mobile miHoYoBBS/2.70.1",
|
||||
"visible": false,
|
||||
"width": 400,
|
||||
"height": 800,
|
||||
"center": true,
|
||||
"decorations": true,
|
||||
"closable": true
|
||||
"visible": false
|
||||
}
|
||||
]
|
||||
],
|
||||
"security": {
|
||||
"capabilities": ["TeyvatGuide", "Mys", "SubWindow", "DevJson"]
|
||||
}
|
||||
},
|
||||
"plugins": {
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": ["teyvatguide"]
|
||||
},
|
||||
"mobile": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
135
src/App.vue
@@ -11,22 +11,23 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { app, event, fs, tauri, window as TauriWindow } from "@tauri-apps/api";
|
||||
import { UnlistenFn } from "@tauri-apps/api/helpers/event";
|
||||
import { app, event, core, webviewWindow } from "@tauri-apps/api";
|
||||
import { UnlistenFn, Event } from "@tauri-apps/api/event";
|
||||
import { mkdir } from "@tauri-apps/plugin-fs";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onBeforeMount, onMounted, onUnmounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import TBackTop from "./components/app/t-backTop.vue";
|
||||
import TSidebar from "./components/app/t-sidebar.vue";
|
||||
import showConfirm from "./components/func/confirm";
|
||||
import showSnackbar from "./components/func/snackbar";
|
||||
import TGSqlite from "./plugins/Sqlite";
|
||||
import { useAppStore } from "./store/modules/app";
|
||||
import { useUserStore } from "./store/modules/user";
|
||||
import { getBuildTime } from "./utils/TGBuild";
|
||||
import TGLogger from "./utils/TGLogger";
|
||||
import TGRequest from "./web/request/TGRequest";
|
||||
import showConfirm from "./components/func/confirm.js";
|
||||
import showSnackbar from "./components/func/snackbar.js";
|
||||
import TGSqlite from "./plugins/Sqlite/index.js";
|
||||
import { useAppStore } from "./store/modules/app.js";
|
||||
import { useUserStore } from "./store/modules/user.js";
|
||||
import { getBuildTime } from "./utils/TGBuild.js";
|
||||
import TGLogger from "./utils/TGLogger.js";
|
||||
import TGRequest from "./web/request/TGRequest.js";
|
||||
|
||||
const appStore = useAppStore();
|
||||
const userStore = storeToRefs(useUserStore());
|
||||
@@ -41,21 +42,22 @@ let themeListener: UnlistenFn;
|
||||
let urlListener: UnlistenFn;
|
||||
|
||||
onBeforeMount(async () => {
|
||||
const win = TauriWindow.getCurrent();
|
||||
const win = webviewWindow.getCurrent();
|
||||
isMain.value = win.label === "TeyvatGuide";
|
||||
if (isMain.value) {
|
||||
const title = "Teyvat Guide v" + (await app.getVersion()) + " Beta";
|
||||
await win.setTitle(title);
|
||||
await listenOnInit();
|
||||
await tauri.invoke("init_app");
|
||||
listenOnInit();
|
||||
await core.invoke("init_app");
|
||||
urlListener = await getDeepLink();
|
||||
}
|
||||
await win.show();
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
onMounted(() => {
|
||||
document.documentElement.className = theme.value;
|
||||
themeListener = await event.listen("readTheme", async (e) => {
|
||||
const themeGet = <string>e.payload;
|
||||
themeListener = event.listen("readTheme", async (e: Event<string>) => {
|
||||
const themeGet = e.payload;
|
||||
if (theme.value !== themeGet) {
|
||||
theme.value = themeGet;
|
||||
document.documentElement.className = theme.value;
|
||||
@@ -64,9 +66,9 @@ onMounted(async () => {
|
||||
});
|
||||
|
||||
// 启动后只执行一次的监听
|
||||
async function listenOnInit(): Promise<void> {
|
||||
await event.listen("initApp", async () => {
|
||||
await tauri.invoke("register_deep_link");
|
||||
function listenOnInit(): void {
|
||||
console.info("[App][listenOnInit] 监听初始化事件!");
|
||||
event.listen("initApp", async () => {
|
||||
await checkAppLoad();
|
||||
await checkDeviceFp();
|
||||
try {
|
||||
@@ -78,7 +80,6 @@ async function listenOnInit(): Promise<void> {
|
||||
}
|
||||
await checkUpdate();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
async function checkAppLoad(): Promise<void> {
|
||||
@@ -108,15 +109,18 @@ async function resetDB(): Promise<void> {
|
||||
// 检测 deviceFp
|
||||
async function checkDeviceFp(): Promise<void> {
|
||||
const appData = await TGSqlite.getAppData();
|
||||
const deviceInfo = appData.find((item) => item.key === "deviceInfo")?.value;
|
||||
const deviceLocal = appStore.deviceInfo;
|
||||
if (deviceInfo === undefined) {
|
||||
if (deviceLocal.device_fp === "0000000000000")
|
||||
const deviceFind = appData.find((item) => item.key === "deviceInfo");
|
||||
if (typeof deviceFind === "undefined") {
|
||||
if (deviceLocal.device_fp === "0000000000000") {
|
||||
appStore.deviceInfo = await TGRequest.Device.getFp(appStore.deviceInfo);
|
||||
}
|
||||
await TGSqlite.saveAppData("deviceInfo", JSON.stringify(deviceLocal));
|
||||
return;
|
||||
}
|
||||
if (JSON.parse(deviceInfo) !== deviceLocal) appStore.deviceInfo = JSON.parse(deviceInfo);
|
||||
if (JSON.parse(deviceFind.value) !== deviceLocal) {
|
||||
appStore.deviceInfo = JSON.parse(deviceFind.value);
|
||||
}
|
||||
}
|
||||
|
||||
// 检测 ck,info 数据
|
||||
@@ -138,9 +142,9 @@ async function checkUserLoad(): Promise<void> {
|
||||
const infoLocal = userStore.briefInfo.value;
|
||||
const appData = await TGSqlite.getAppData();
|
||||
const infoDB = appData.find((item) => item.key === "userInfo")?.value;
|
||||
if (infoDB === undefined && JSON.stringify(infoLocal) !== "{}") {
|
||||
if (typeof infoDB === "undefined" && JSON.stringify(infoLocal) !== "{}") {
|
||||
await TGSqlite.saveAppData("userInfo", JSON.stringify(infoLocal));
|
||||
} else if (infoDB !== undefined && infoLocal !== JSON.parse(infoDB)) {
|
||||
} else if (typeof infoDB !== "undefined" && infoLocal !== JSON.parse(infoDB)) {
|
||||
userStore.briefInfo.value = JSON.parse(infoDB);
|
||||
console.info("briefInfo 数据已更新!");
|
||||
}
|
||||
@@ -158,64 +162,77 @@ async function checkUserLoad(): Promise<void> {
|
||||
}
|
||||
if (accountDB !== accountLocal) userStore.account.value = accountDB;
|
||||
const userDir = appData.find((item) => item.key === "userDir")?.value;
|
||||
if (userDir === undefined) {
|
||||
if (typeof userDir === "undefined") {
|
||||
await TGSqlite.saveAppData("userDir", appStore.userDir);
|
||||
return;
|
||||
}
|
||||
if (userDir !== appStore.userDir) appStore.userDir = userDir;
|
||||
await fs.createDir(appStore.userDir, { recursive: true });
|
||||
await mkdir(appStore.userDir, { recursive: true });
|
||||
}
|
||||
|
||||
async function getDeepLink(): Promise<UnlistenFn> {
|
||||
return await event.listen("active_deep_link", async (e) => {
|
||||
const windowGet = new TauriWindow.WebviewWindow("TeyvatGuide");
|
||||
return await event.listen("active_deep_link", async (e: Event<string>) => {
|
||||
const windowGet = new webviewWindow.WebviewWindow("TeyvatGuide");
|
||||
if (await windowGet.isMinimized()) {
|
||||
await windowGet.unminimize();
|
||||
}
|
||||
await windowGet.setFocus();
|
||||
if (typeof e.payload !== "string") {
|
||||
const payload = parseDeepLink(e.payload);
|
||||
if (payload === false) {
|
||||
showSnackbar({
|
||||
text: "无效的 deep link!",
|
||||
color: "error",
|
||||
timeout: 3000,
|
||||
});
|
||||
await TGLogger.Error(`[App][getDeepLink] 无效的 deep link! ${JSON.stringify(e)}`);
|
||||
await TGLogger.Error(`[App][getDeepLink] 无效的 deep link! ${JSON.stringify(e.payload)}`);
|
||||
return;
|
||||
}
|
||||
await TGLogger.Info(`[App][getDeepLink] ${e.payload}`);
|
||||
if (e.payload === "") return;
|
||||
if (
|
||||
e.payload.startsWith("teyvatguide://import_uigf") ||
|
||||
e.payload.startsWith("teyvatguide://import_uiaf")
|
||||
) {
|
||||
await toUIAF(e.payload);
|
||||
return;
|
||||
}
|
||||
if (e.payload.startsWith("router?path=")) {
|
||||
const routerPath = e.payload.replace("router?path=", "");
|
||||
if (router.currentRoute.value.path === routerPath) {
|
||||
showSnackbar({
|
||||
text: "已在当前页面!",
|
||||
color: "warn",
|
||||
timeout: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
await router.push(routerPath);
|
||||
return;
|
||||
}
|
||||
showSnackbar({
|
||||
text: "无效的 deep link!",
|
||||
color: "error",
|
||||
timeout: 3000,
|
||||
});
|
||||
await handleDeepLink(payload);
|
||||
});
|
||||
}
|
||||
|
||||
function parseDeepLink(payload: string | string[]): string | false {
|
||||
try {
|
||||
if (typeof payload === "string") return payload;
|
||||
if (payload.length < 2) return "teyvatguide://";
|
||||
return payload[1];
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
TGLogger.Error(`[App][parseDeepLink] ${e.name}: ${e.message}`);
|
||||
} else console.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDeepLink(payload: string): Promise<void> {
|
||||
if (payload === "" || payload === "teyvatguide://") return;
|
||||
if (
|
||||
payload.startsWith("teyvatguide://import_uigf") ||
|
||||
payload.startsWith("teyvatguide://import_uiaf")
|
||||
) {
|
||||
await toUIAF(payload);
|
||||
return;
|
||||
}
|
||||
if (payload.startsWith("router?path=")) {
|
||||
const routerPath = payload.replace("router?path=", "");
|
||||
if (router.currentRoute.value.path === routerPath) {
|
||||
showSnackbar({
|
||||
text: "已在当前页面!",
|
||||
color: "warn",
|
||||
timeout: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
await router.push(routerPath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
async function toUIAF(link: string) {
|
||||
const url = new URL(link);
|
||||
const app = url.searchParams.get("app");
|
||||
if (app === null || app === "") {
|
||||
if (app == null || app === "") {
|
||||
await router.push("/achievements");
|
||||
} else {
|
||||
await router.push("/achievements/?app=" + app);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @file assets/css/post-parser.css
|
||||
* @description 游戏公告解析 css
|
||||
* @since Beta v0.4.5
|
||||
* @since Beta v0.5.0
|
||||
*/
|
||||
|
||||
.anno-body {
|
||||
@@ -37,15 +37,12 @@
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.anno-link-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
color: #00c3ff;
|
||||
}
|
||||
|
||||
.anno-content :deep(a) {
|
||||
color: #00c3ff;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
text-decoration: underline solid #00c3ff;
|
||||
text-underline-position: under;
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
.anno-content :deep(p) {
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
</transition>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
// vue
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
|
||||
const scrollTop = ref(0); // 滚动条距离顶部的距离
|
||||
const canTop = ref(false); // 默认不显示
|
||||
@@ -45,6 +44,11 @@ function handleScrollTop(): void {
|
||||
onMounted(() => {
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
});
|
||||
|
||||
// 销毁监听
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -160,7 +160,6 @@
|
||||
value="wiki-material"
|
||||
:link="true"
|
||||
href="/wiki/material"
|
||||
v-if="isDevEnv"
|
||||
>
|
||||
<template #prepend>
|
||||
<img src="/source/UI/wikiGCG.webp" alt="gcgIcon" class="side-icon-menu" />
|
||||
@@ -242,16 +241,16 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { event, window as TauriWindow } from "@tauri-apps/api";
|
||||
import { UnlistenFn } from "@tauri-apps/api/helpers/event";
|
||||
import { event, webviewWindow } from "@tauri-apps/api";
|
||||
import { UnlistenFn, Event } from "@tauri-apps/api/event";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
|
||||
|
||||
import { useAppStore } from "../../store/modules/app";
|
||||
import { useUserStore } from "../../store/modules/user";
|
||||
import mhyClient from "../../utils/TGClient";
|
||||
import TGLogger from "../../utils/TGLogger";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
import { useUserStore } from "../../store/modules/user.js";
|
||||
import mhyClient from "../../utils/TGClient.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
|
||||
const appStore = useAppStore();
|
||||
const userStore = storeToRefs(useUserStore());
|
||||
@@ -298,11 +297,11 @@ function collapse(): void {
|
||||
let themeListener: UnlistenFn;
|
||||
|
||||
onMounted(async () => {
|
||||
themeListener = await event.listen("readTheme", (e) => {
|
||||
const theme = <string>e.payload;
|
||||
themeListener = await event.listen("readTheme", (e: Event<string>) => {
|
||||
const theme = e.payload;
|
||||
themeGet.value = theme === "default" ? "default" : "dark";
|
||||
});
|
||||
if (TauriWindow.getCurrent().label === "TeyvatGuide") {
|
||||
if (webviewWindow.getCurrent().label === "TeyvatGuide") {
|
||||
await mhyClient.run();
|
||||
}
|
||||
if (userStore.briefInfo.value && userStore.briefInfo.value.nickname) {
|
||||
@@ -329,9 +328,7 @@ function login(): void {
|
||||
});
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
themeListener();
|
||||
});
|
||||
onUnmounted(() => themeListener());
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { event } from "@tauri-apps/api";
|
||||
import { UnlistenFn } from "@tauri-apps/api/helpers/event";
|
||||
import { UnlistenFn, Event } from "@tauri-apps/api/event";
|
||||
import { computed, onMounted, onUnmounted } from "vue";
|
||||
|
||||
import { useAppStore } from "../../store/modules/app";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
|
||||
const appStore = useAppStore();
|
||||
const themeGet = computed({
|
||||
@@ -25,8 +25,8 @@ const themeGet = computed({
|
||||
});
|
||||
let themeListener: UnlistenFn;
|
||||
|
||||
onMounted(async () => {
|
||||
themeListener = await listenOnTheme();
|
||||
onMounted(() => {
|
||||
themeListener = listenOnTheme();
|
||||
});
|
||||
|
||||
async function switchTheme(): Promise<void> {
|
||||
@@ -34,18 +34,14 @@ async function switchTheme(): Promise<void> {
|
||||
await event.emit("readTheme", themeGet.value);
|
||||
}
|
||||
|
||||
async function listenOnTheme(): Promise<UnlistenFn> {
|
||||
return await event.listen<string>("readTheme", (e) => {
|
||||
function listenOnTheme(): UnlistenFn {
|
||||
return event.listen("readTheme", (e: Event<string>) => {
|
||||
const theme = e.payload;
|
||||
themeGet.value = theme === "default" ? "default" : "dark";
|
||||
});
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (themeListener) {
|
||||
themeListener();
|
||||
}
|
||||
});
|
||||
onUnmounted(() => themeListener());
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.switch-box {
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
import { app } from "@tauri-apps/api";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
|
||||
import { useAppStore } from "../../store/modules/app";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
|
||||
const appStore = useAppStore();
|
||||
const versionApp = ref<string>();
|
||||
|
||||
@@ -42,14 +42,16 @@
|
||||
</v-list>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { dialog, fs, path } from "@tauri-apps/api";
|
||||
import { path } from "@tauri-apps/api";
|
||||
import { open } from "@tauri-apps/plugin-dialog";
|
||||
import { readDir, remove } from "@tauri-apps/plugin-fs";
|
||||
|
||||
import TGSqlite from "../../plugins/Sqlite";
|
||||
import { useAppStore } from "../../store/modules/app";
|
||||
import { backUpUserData } from "../../utils/dataBS";
|
||||
import TGShell from "../../utils/TGShell";
|
||||
import showConfirm from "../func/confirm";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
import { backUpUserData } from "../../utils/dataBS.js";
|
||||
import TGShell from "../../utils/TGShell.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
@@ -66,7 +68,7 @@ async function confirmCUD(): Promise<void> {
|
||||
});
|
||||
return;
|
||||
}
|
||||
const dir = await dialog.open({
|
||||
const dir: string | null = await open({
|
||||
directory: true,
|
||||
defaultPath: oriDir,
|
||||
multiple: false,
|
||||
@@ -78,13 +80,6 @@ async function confirmCUD(): Promise<void> {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (typeof dir !== "string") {
|
||||
showSnackbar({
|
||||
color: "error",
|
||||
text: "路径错误!",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (dir === oriDir) {
|
||||
showSnackbar({
|
||||
color: "warn",
|
||||
@@ -95,7 +90,7 @@ async function confirmCUD(): Promise<void> {
|
||||
appStore.userDir = dir;
|
||||
await TGSqlite.saveAppData("userDir", dir);
|
||||
await backUpUserData(dir);
|
||||
await fs.removeDir(oriDir, { recursive: true });
|
||||
await remove(oriDir, { recursive: true });
|
||||
showSnackbar({
|
||||
text: "已重新备份数据!即将刷新页面!",
|
||||
timeout: 3000,
|
||||
@@ -126,11 +121,11 @@ async function confirmCLD(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
const logDir = appStore.logDir;
|
||||
const files = await fs.readDir(logDir);
|
||||
const files = await readDir(logDir);
|
||||
const delFiles = files.filter((file) => {
|
||||
// yyyy-mm-dd.log
|
||||
const reg = /(\d{4}-\d{2}-\d{2}\.log)/;
|
||||
const match = file.path.match(reg);
|
||||
const match = file.name.match(reg);
|
||||
if (!Array.isArray(match) || match.length < 1) return false;
|
||||
const date = match[1].replace(".log", "");
|
||||
return isOverWeek(date);
|
||||
@@ -143,7 +138,8 @@ async function confirmCLD(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
for (const file of delFiles) {
|
||||
await fs.removeFile(file.path);
|
||||
const filePath = `${logDir}/${file.name}`;
|
||||
await remove(filePath);
|
||||
}
|
||||
showSnackbar({
|
||||
text: `已清理 ${delFiles.length} 个日志文件!`,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<v-list class="config-list">
|
||||
<v-list-subheader :inset="true" class="config-header" title="相关信息" />
|
||||
<v-divider :inset="true" class="border-opacity-75" />
|
||||
<v-list-item title="Tauri 版本" @click="toOuter('https://next--tauri.netlify.app/')">
|
||||
<v-list-item title="Tauri 版本" @click="toOuter('https://v2.tauri.app/')">
|
||||
<template #prepend>
|
||||
<v-img class="config-icon" src="/platforms/tauri.webp" alt="Tauri" />
|
||||
</template>
|
||||
@@ -73,12 +73,13 @@
|
||||
</v-list>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { app, os } from "@tauri-apps/api";
|
||||
import { app } from "@tauri-apps/api";
|
||||
import { platform, version } from "@tauri-apps/plugin-os";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
import TGSqlite from "../../plugins/Sqlite";
|
||||
import { useAchievementsStore } from "../../store/modules/achievements";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import { useAchievementsStore } from "../../store/modules/achievements.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
|
||||
const achievementsStore = useAchievementsStore();
|
||||
|
||||
@@ -92,25 +93,25 @@ const dbInfo = ref<Array<TGApp.Sqlite.AppData.Item>>([]);
|
||||
onMounted(async () => {
|
||||
versionApp.value = await app.getVersion();
|
||||
versionTauri.value = await app.getTauriVersion();
|
||||
osPlatform.value = `${await os.platform()}`;
|
||||
osPlatform.value = platform();
|
||||
switch (osPlatform.value) {
|
||||
case "linux":
|
||||
iconPlatform.value = "mdi-linux";
|
||||
break;
|
||||
case "darwin":
|
||||
case "macos":
|
||||
iconPlatform.value = "mdi-apple";
|
||||
break;
|
||||
case "ios":
|
||||
iconPlatform.value = "mdi-apple-ios";
|
||||
break;
|
||||
case "win32":
|
||||
case "windows":
|
||||
iconPlatform.value = "mdi-microsoft-windows";
|
||||
break;
|
||||
default:
|
||||
iconPlatform.value = "mdi-desktop-classic";
|
||||
break;
|
||||
}
|
||||
osVersion.value = await os.version();
|
||||
osVersion.value = version();
|
||||
try {
|
||||
dbInfo.value = await TGSqlite.getAppData();
|
||||
} catch (e) {
|
||||
|
||||
@@ -10,26 +10,23 @@
|
||||
<template #actions>
|
||||
<v-spacer />
|
||||
<v-btn variant="outlined" @click="scan = true" icon="mdi-qrcode-scan" />
|
||||
<v-btn v-if="false" variant="outlined" @click="toWebLogin" icon="mdi-web" />
|
||||
<v-btn variant="outlined" @click="confirmRefreshUser" icon="mdi-refresh" :loading="loading" />
|
||||
</template>
|
||||
</v-card>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { event, window as windowTauri } from "@tauri-apps/api";
|
||||
import type { UnlistenFn } from "@tauri-apps/api/helpers/event";
|
||||
import type { UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
||||
|
||||
import TGSqlite from "../../plugins/Sqlite";
|
||||
import { useAppStore } from "../../store/modules/app";
|
||||
import { useUserStore } from "../../store/modules/user";
|
||||
import TGClient from "../../utils/TGClient";
|
||||
import TGLogger from "../../utils/TGLogger";
|
||||
import { getDeviceFp } from "../../web/request/getDeviceFp";
|
||||
import TGRequest from "../../web/request/TGRequest";
|
||||
import showConfirm from "../func/confirm";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
import { useUserStore } from "../../store/modules/user.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import { getDeviceFp } from "../../web/request/getDeviceFp.js";
|
||||
import TGRequest from "../../web/request/TGRequest.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import ToGameLogin from "../overlay/to-gameLogin.vue";
|
||||
|
||||
interface TcUserBadgeEmits {
|
||||
@@ -64,177 +61,6 @@ watch(userStore.briefInfo, (v) => {
|
||||
}
|
||||
});
|
||||
|
||||
async function toWebLogin(): Promise<void> {
|
||||
const confirm = await showConfirm({
|
||||
title: "请在子窗口中完成登录操作",
|
||||
text: "请操作完成后点击子窗口的“用户登录”菜单",
|
||||
});
|
||||
if (!confirm) {
|
||||
showSnackbar({
|
||||
color: "cancel",
|
||||
text: "已取消登录",
|
||||
});
|
||||
return;
|
||||
}
|
||||
await TGClient.open("config_sign_in", "https://user.mihoyo.com");
|
||||
signListener = await event.listen("config_user_sign", async (e) => {
|
||||
if (typeof e.payload !== "string") {
|
||||
showSnackbar({
|
||||
color: "error",
|
||||
text: "登录失败!",
|
||||
});
|
||||
return;
|
||||
}
|
||||
await getTokenWeb(e.payload);
|
||||
});
|
||||
}
|
||||
|
||||
async function getTokenWeb(cookie: string): Promise<void> {
|
||||
await windowTauri.appWindow.setFocus();
|
||||
emits("loadOuter", { show: true, title: "正在解析 cookie" });
|
||||
const ck = cookie.split(";").reduce(
|
||||
(prev, curr) => {
|
||||
const [key, value] = curr.split("=");
|
||||
prev[key.trim()] = value.trim();
|
||||
return prev;
|
||||
},
|
||||
<Record<string, string>>{},
|
||||
);
|
||||
if (!("login_ticket" in ck) || !("login_uid" in ck)) {
|
||||
emits("loadOuter", { show: false });
|
||||
showSnackbar({
|
||||
text: "未检测到 login_ticket, 请确认是否登录成功!",
|
||||
color: "error",
|
||||
});
|
||||
try {
|
||||
setTimeout(() => {
|
||||
windowTauri.WebviewWindow.getByLabel("mhy_client")?.setFocus();
|
||||
}, 2000);
|
||||
} catch (e) {
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 无法获取子窗口");
|
||||
await TGClient.open("config_sign_in", "https://user.mihoyo.com/");
|
||||
}
|
||||
return;
|
||||
}
|
||||
emits("loadOuter", { show: true, title: "正在获取 token" });
|
||||
let cookieUser: TGApp.User.Account.Cookie = {
|
||||
account_id: "",
|
||||
ltuid: "",
|
||||
stuid: "",
|
||||
mid: "",
|
||||
cookie_token: "",
|
||||
stoken: "",
|
||||
ltoken: "",
|
||||
};
|
||||
cookieUser.account_id = ck["login_uid"];
|
||||
cookieUser.ltuid = ck["login_uid"];
|
||||
cookieUser.stuid = ck["login_uid"];
|
||||
const tokenRes = await TGRequest.User.byLoginTicket.getTokens(
|
||||
ck["login_ticket"],
|
||||
ck["login_uid"],
|
||||
);
|
||||
if ("retcode" in tokenRes) {
|
||||
emits("loadOuter", { show: false });
|
||||
showSnackbar({
|
||||
text: "获取 token 失败!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 获取 token 失败");
|
||||
await TGLogger.Error(`[tc-userBadge][getTokenWeb] ${tokenRes.retcode}: ${tokenRes.message}`);
|
||||
return;
|
||||
}
|
||||
tokenRes.map((i) => {
|
||||
if (i.name === "ltoken") return (cookieUser.ltoken = i.token);
|
||||
if (i.name === "stoken") return (cookieUser.stoken = i.token);
|
||||
});
|
||||
if (cookieUser.ltoken === "" || cookieUser.stoken === "") {
|
||||
emits("loadOuter", { show: false });
|
||||
showSnackbar({
|
||||
text: "获取 ltoken 或者 stoken 失败!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 获取 ltoken 或者 stoken 失败");
|
||||
return;
|
||||
}
|
||||
const ltokenRes = await TGRequest.User.byLToken.verify(cookieUser.ltoken, cookieUser.ltuid);
|
||||
if (typeof ltokenRes !== "string") {
|
||||
showSnackbar({
|
||||
text: "ltoken 验证失败!",
|
||||
color: "error",
|
||||
});
|
||||
} else {
|
||||
cookieUser.mid = ltokenRes;
|
||||
}
|
||||
if (!cookieUser.stoken.startsWith("v2")) {
|
||||
const stokenRes = await TGRequest.User.bySToken.update(cookieUser.stoken, cookieUser.stuid);
|
||||
if ("retcode" in stokenRes) {
|
||||
showSnackbar({
|
||||
text: "stoken 更新失败!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] stoken 更新失败");
|
||||
await TGLogger.Error(
|
||||
`[tc-userBadge][getTokenWeb] ${stokenRes.retcode}: ${stokenRes.message}`,
|
||||
);
|
||||
} else {
|
||||
cookieUser.stoken = stokenRes.token.token;
|
||||
if (cookieUser.mid === "" && stokenRes.user_info.mid !== "")
|
||||
cookieUser.mid = stokenRes.user_info.mid;
|
||||
}
|
||||
}
|
||||
const cookieTokenRes = await TGRequest.User.bySToken.getCookieToken(
|
||||
cookieUser.mid,
|
||||
cookieUser.stoken,
|
||||
);
|
||||
if (typeof cookieTokenRes !== "string") {
|
||||
showSnackbar({
|
||||
text: "cookie_token 获取失败!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] cookie_token 获取失败");
|
||||
await TGLogger.Error(
|
||||
`[tc-userBadge][getTokenWeb] ${cookieTokenRes.retcode}: ${cookieTokenRes.message}`,
|
||||
);
|
||||
} else {
|
||||
cookieUser.cookie_token = cookieTokenRes;
|
||||
}
|
||||
userStore.cookie.value = cookieUser;
|
||||
try {
|
||||
await windowTauri.WebviewWindow.getByLabel("mhy_client")?.close();
|
||||
} catch (e) {
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 无法获取子窗口");
|
||||
showSnackbar({
|
||||
text: "请手动关闭子窗口!",
|
||||
color: "error",
|
||||
});
|
||||
}
|
||||
signListener();
|
||||
if (Object.values(cookieUser).some((i) => i === "")) {
|
||||
showSnackbar({
|
||||
text: "获取 cookie 失败!部分项为空!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 获取 cookie 失败");
|
||||
return;
|
||||
}
|
||||
await TGSqlite.saveAppData("cookie", JSON.stringify(cookieUser));
|
||||
const failCount = await refreshUserInfo();
|
||||
if (failCount > 0) {
|
||||
showSnackbar({
|
||||
color: "error",
|
||||
text: "获取用户信息失败!",
|
||||
});
|
||||
} else {
|
||||
showSnackbar({
|
||||
text: "登录成功!",
|
||||
color: "success",
|
||||
});
|
||||
appStore.isLogin = true;
|
||||
}
|
||||
loading.value = false;
|
||||
emits("loadOuter", { show: false });
|
||||
}
|
||||
|
||||
async function refreshUser() {
|
||||
const ck = userStore.cookie.value;
|
||||
if (ck === undefined || JSON.stringify(ck) === "{}") {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUpdated, ref } from "vue";
|
||||
|
||||
import { saveImgLocal } from "../../utils/TGShare";
|
||||
import { saveImgLocal } from "../../utils/TGShare.js";
|
||||
|
||||
interface DucDetailOlbProps {
|
||||
modelValue: TGApp.Sqlite.Character.RoleConstellation[];
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUpdated, ref } from "vue";
|
||||
|
||||
import { saveImgLocal } from "../../utils/TGShare";
|
||||
import { saveImgLocal } from "../../utils/TGShare.js";
|
||||
|
||||
interface DucDetailOrtProps {
|
||||
modelValue: TGApp.Sqlite.Character.RoleTalent[];
|
||||
|
||||
@@ -13,17 +13,18 @@
|
||||
<div class="duc-doc-lt">
|
||||
<DucDetailOlt :data="props.dataVal" mode="avatar" />
|
||||
<DucDetailOlt :data="JSON.parse(props.dataVal.weapon)" mode="weapon" />
|
||||
<v-btn
|
||||
class="duc-doc-btn"
|
||||
@click="share"
|
||||
variant="outlined"
|
||||
:loading="loading"
|
||||
data-html2canvas-ignore
|
||||
>
|
||||
<v-icon>mdi-share-variant</v-icon>
|
||||
<span>分享</span>
|
||||
</v-btn>
|
||||
<DucDetailRelics :data="props.dataVal.reliquary" />
|
||||
</div>
|
||||
<v-btn
|
||||
class="duc-doc-btn"
|
||||
@click="share"
|
||||
variant="outlined"
|
||||
:loading="loading"
|
||||
data-html2canvas-ignore
|
||||
>
|
||||
<v-icon>mdi-share-variant</v-icon>
|
||||
<span>分享</span>
|
||||
</v-btn>
|
||||
<!-- 右侧天赋 -->
|
||||
<div class="duc-doc-rt">
|
||||
<DucDetailOrt :model-value="JSON.parse(props.dataVal.talent)" />
|
||||
@@ -32,6 +33,11 @@
|
||||
<div class="duc-doc-lb">
|
||||
<DucDetailOlb :model-value="JSON.parse(props.dataVal.constellation)" />
|
||||
</div>
|
||||
<!-- 底部水印信息 -->
|
||||
<div class="duc-doc-bt">
|
||||
UID: {{ props.dataVal.uid }} Updated: {{ props.dataVal.updated }} | Rendered by
|
||||
TeyvatGuide v{{ version }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧箭头 -->
|
||||
<div class="duc-arrow-right" @click="handleClick('right')">
|
||||
@@ -41,15 +47,17 @@
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { app } from "@tauri-apps/api";
|
||||
import { computed, onMounted, onUpdated, ref } from "vue";
|
||||
|
||||
import TGSqlite from "../../plugins/Sqlite";
|
||||
import { generateShareImg } from "../../utils/TGShare";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import { generateShareImg } from "../../utils/TGShare.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
import DucDetailOlb from "./duc-detail-olb.vue";
|
||||
import DucDetailOlt from "./duc-detail-olt.vue";
|
||||
import DucDetailOrt from "./duc-detail-ort.vue";
|
||||
import DucDetailRelics from "./duc-detail-relics.vue";
|
||||
|
||||
interface DucDetailOverlayProps {
|
||||
modelValue: boolean;
|
||||
@@ -64,6 +72,7 @@ type DucDetailOverlayEmits = {
|
||||
|
||||
const props = defineProps<DucDetailOverlayProps>();
|
||||
const emits = defineEmits<DucDetailOverlayEmits>();
|
||||
const version = await app.getVersion();
|
||||
const visible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => {
|
||||
@@ -90,6 +99,8 @@ onMounted(async () => {
|
||||
});
|
||||
onUpdated(async () => {
|
||||
await loadData();
|
||||
console.log("updated, loadData");
|
||||
console.log(props.dataVal);
|
||||
});
|
||||
|
||||
async function loadData(): Promise<void> {
|
||||
@@ -183,6 +194,9 @@ async function share(): Promise<void> {
|
||||
}
|
||||
|
||||
.duc-doc-btn {
|
||||
position: absolute;
|
||||
bottom: 90px;
|
||||
left: 370px;
|
||||
color: var(--tgc-white-1);
|
||||
}
|
||||
|
||||
@@ -199,4 +213,13 @@ async function share(): Promise<void> {
|
||||
left: 10px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.duc-doc-bt {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: -1px;
|
||||
color: var(--tgc-white-1);
|
||||
font-size: 12px;
|
||||
text-shadow: 0 0 2px var(--tgc-dark-2);
|
||||
}
|
||||
</style>
|
||||
|
||||
82
src/components/devCharacter/duc-detail-relic.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<div class="duc-dr-box">
|
||||
<div class="duc-dr-bg">
|
||||
<img :src="`/icon/relic/${props.pos}.webp`" alt="relic" />
|
||||
</div>
|
||||
<div v-if="props.modelValue" class="duc-dr-bg">
|
||||
<img :src="`/icon/bg/${props.modelValue.star}-Star.webp`" alt="bg" />
|
||||
</div>
|
||||
<div v-if="props.modelValue" class="duc-dr-icon">
|
||||
<img :src="props.modelValue.icon" alt="relic" />
|
||||
</div>
|
||||
<div v-if="props.modelValue !== false" class="duc-dr-level">
|
||||
{{ props.modelValue.level }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
interface ducDetailRelicProps {
|
||||
modelValue: TGApp.Sqlite.Character.RoleReliquary | false;
|
||||
pos: number;
|
||||
}
|
||||
|
||||
const props = defineProps<ducDetailRelicProps>();
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.duc-dr-box {
|
||||
position: relative;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background: rgb(50 56 68/50%);
|
||||
}
|
||||
|
||||
.duc-dr-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.duc-dr-bg:nth-child(1) {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.duc-dr-bg img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.duc-dr-icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.duc-dr-icon img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.duc-dr-level {
|
||||
position: absolute;
|
||||
right: -4px;
|
||||
bottom: -4px;
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: var(--tgc-yellow-3);
|
||||
color: var(--tgc-white-1);
|
||||
font-family: var(--font-title);
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
}
|
||||
</style>
|
||||
45
src/components/devCharacter/duc-detail-relics.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div class="ddr-box">
|
||||
<DucDetailRelic
|
||||
v-for="(relic, index) in transData"
|
||||
:key="index"
|
||||
:model-value="relic"
|
||||
:pos="index + 1"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
import DucDetailRelic from "./duc-detail-relic.vue";
|
||||
|
||||
interface DucDetailRelicsProps {
|
||||
data: string;
|
||||
}
|
||||
|
||||
const props = defineProps<DucDetailRelicsProps>();
|
||||
const transData = computed<Array<TGApp.Sqlite.Character.RoleReliquary | false>>(() => {
|
||||
if (!props.data || props.data === "") return [false, false, false, false, false];
|
||||
try {
|
||||
const parsedData: TGApp.Sqlite.Character.RoleReliquary[] = JSON.parse(props.data);
|
||||
let relics: Array<TGApp.Sqlite.Character.RoleReliquary | false> = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const relic = parsedData.find((relic) => relic.pos === i + 1);
|
||||
if (relic) relics.push(relic);
|
||||
else relics.push(false);
|
||||
}
|
||||
return relics;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return [false, false, false, false, false];
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.ddr-box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -123,7 +123,7 @@ function loadData(): void {
|
||||
star4List.value.push({
|
||||
...item,
|
||||
gachaCount: reset4count.value,
|
||||
icon: getIcon(item.itemId, item.type),
|
||||
icon: getIcon(item.itemId),
|
||||
});
|
||||
reset4count.value = 0;
|
||||
} else if (item.rank === "5") {
|
||||
@@ -131,7 +131,7 @@ function loadData(): void {
|
||||
star5List.value.push({
|
||||
...item,
|
||||
gachaCount: reset5count.value,
|
||||
icon: getIcon(item.itemId, item.type),
|
||||
icon: getIcon(item.itemId),
|
||||
});
|
||||
reset5count.value = 0;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<v-chart :option="getPoolData()" autoresize />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
// todo 解决引用问题
|
||||
import type { EChartsOption } from "echarts";
|
||||
import { PieChart } from "echarts/charts";
|
||||
import {
|
||||
@@ -16,7 +17,7 @@ import { CanvasRenderer } from "echarts/renderers";
|
||||
import { onMounted, provide } from "vue";
|
||||
import VChart, { THEME_KEY } from "vue-echarts";
|
||||
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
// echarts
|
||||
|
||||
use([
|
||||
|
||||
@@ -54,11 +54,11 @@
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import { AppGachaData, AppCharacterData, AppWeaponData } from "../../data";
|
||||
import { createPost } from "../../utils/TGWindow";
|
||||
import { timestampToDate } from "../../utils/toolFunc";
|
||||
import showConfirm from "../func/confirm";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import { AppGachaData, AppCharacterData, AppWeaponData } from "../../data/index.js";
|
||||
import { createPost } from "../../utils/TGWindow.js";
|
||||
import { timestampToDate } from "../../utils/toolFunc.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TItembox, { TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
interface GroHistoryMap {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
import { onBeforeMount, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import TSAvatarBirth from "../../plugins/Sqlite/modules/avatarBirth";
|
||||
import TSAvatarBirth from "../../plugins/Sqlite/modules/avatarBirth.js";
|
||||
|
||||
const isBirthday = ref<boolean>(false);
|
||||
const router = useRouter();
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
|
||||
import { AppCalendarData } from "../../data";
|
||||
import { AppCalendarData } from "../../data/index.js";
|
||||
import TibCalendarItem from "../itembox/tib-calendar-item.vue";
|
||||
import ToCalendar from "../overlay/to-calendar.vue";
|
||||
|
||||
|
||||
@@ -56,11 +56,11 @@
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import Mys from "../../plugins/Mys";
|
||||
import { useHomeStore } from "../../store/modules/home";
|
||||
import { createPost, createTGWindow } from "../../utils/TGWindow";
|
||||
import { stamp2LastTime } from "../../utils/toolFunc";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import Mys from "../../plugins/Mys/index.js";
|
||||
import { useHomeStore } from "../../store/modules/home.js";
|
||||
import { createPost, createTGWindow } from "../../utils/TGWindow.js";
|
||||
import { stamp2LastTime } from "../../utils/toolFunc.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TItembox, { TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
import THomeCard from "./t-homecard.vue";
|
||||
@@ -193,7 +193,7 @@ async function toOuter(
|
||||
});
|
||||
return;
|
||||
}
|
||||
createTGWindow(url, "Sub_window", `Pool_${title}`, 1200, 800, true, true);
|
||||
await createTGWindow(url, "Sub_window", `Pool_${title}`, 1200, 800, true, true);
|
||||
}
|
||||
|
||||
function getCBox(info: TGApp.App.Character.WikiBriefInfo): TItemBoxData {
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
|
||||
import Mys from "../../plugins/Mys";
|
||||
import { createPost } from "../../utils/TGWindow";
|
||||
import { stamp2LastTime } from "../../utils/toolFunc";
|
||||
import Mys from "../../plugins/Mys/index.js";
|
||||
import { createPost } from "../../utils/TGWindow.js";
|
||||
import { stamp2LastTime } from "../../utils/toolFunc.js";
|
||||
|
||||
import THomeCard from "./t-homecard.vue";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
import TGSqlite from "../../plugins/Sqlite";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import TItemBox from "../main/t-itembox.vue";
|
||||
import type { TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
import TGSqlite from "../../plugins/Sqlite";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import TItemBox from "../main/t-itembox.vue";
|
||||
import type { TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
|
||||
import TGSqlite from "../../plugins/Sqlite";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import TItemBox, { type TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
interface TibWikiAbyssProps {
|
||||
modelValue: string;
|
||||
modelValue: string | number;
|
||||
}
|
||||
|
||||
const props = defineProps<TibWikiAbyssProps>();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
|
||||
import TGSqlite from "../../plugins/Sqlite";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import TItemBox, { type TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
interface TibWikiAbyssProps {
|
||||
|
||||
145
src/components/main/t-gamenav.vue
Normal file
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div class="tgn-container">
|
||||
<div v-for="navItem in nav" :key="navItem.id" class="tgn-nav" @click="toNav(navItem)">
|
||||
<img alt="navIcon" :src="navItem.icon" />
|
||||
<span>{{ navItem.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
|
||||
import Mys from "../../plugins/Mys/index.js";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
import TGClient from "../../utils/TGClient.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import { createPost } from "../../utils/TGWindow.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
|
||||
interface TGameNavProps {
|
||||
modelValue: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<TGameNavProps>(), {
|
||||
modelValue: 2,
|
||||
});
|
||||
|
||||
const appStore = useAppStore();
|
||||
const nav = ref<TGApp.BBS.Navigator.Navigator[]>([]);
|
||||
|
||||
onMounted(async () => await loadNav());
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async () => await loadNav(),
|
||||
);
|
||||
|
||||
async function loadNav(): Promise<void> {
|
||||
nav.value = await Mys.Posts.nav(props.modelValue);
|
||||
}
|
||||
|
||||
async function toNav(item: TGApp.BBS.Navigator.Navigator): Promise<void> {
|
||||
if (!appStore.isLogin) {
|
||||
showSnackbar({
|
||||
text: "请先登录",
|
||||
color: "warn",
|
||||
});
|
||||
return;
|
||||
}
|
||||
await TGLogger.Info(`[TGameNav][toNav] 打开网页活动 ${item.name}`);
|
||||
await TGLogger.Info(`[TGameNav}][toNav] ${item.app_path}`);
|
||||
const link = new URL(item.app_path);
|
||||
const mysList = [
|
||||
"https://act.mihoyo.com",
|
||||
"https://webstatic.mihoyo.com",
|
||||
"https://bbs.mihoyo.com",
|
||||
"https://qaa.miyoushe.com",
|
||||
"https://mhyurl.cn",
|
||||
];
|
||||
if (link.protocol != "https:") {
|
||||
await toBBS(link);
|
||||
return;
|
||||
}
|
||||
// 如果不在上面的域名里面,就直接打开
|
||||
if (!mysList.includes(link.origin)) {
|
||||
window.open(item.app_path);
|
||||
return;
|
||||
}
|
||||
if (item.name === "签到福利") {
|
||||
await TGClient.open("web_act_thin", item.app_path);
|
||||
return;
|
||||
}
|
||||
const modeConfirm = await showConfirm({
|
||||
title: "是否采用宽屏模式打开?",
|
||||
text: "取消则采用竖屏模式打开",
|
||||
});
|
||||
if (modeConfirm === undefined) {
|
||||
showSnackbar({
|
||||
text: "已取消打开",
|
||||
color: "cancel",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (modeConfirm) await TGClient.open("web_act", item.app_path);
|
||||
else await TGClient.open("web_act_thin", item.app_path);
|
||||
}
|
||||
|
||||
// 处理 protocol
|
||||
async function toBBS(link: URL): Promise<void> {
|
||||
if (link.protocol == "mihoyobbs:") {
|
||||
if (link.pathname.startsWith("//article")) {
|
||||
const postId = link.pathname.split("/").pop();
|
||||
await createPost(<string>postId);
|
||||
return;
|
||||
}
|
||||
if (link.pathname.startsWith("//forum")) {
|
||||
const forumId = link.pathname.split("/").pop();
|
||||
const url = `https://www.miyoushe.com/ys/home/${forumId}`;
|
||||
window.open(url);
|
||||
return;
|
||||
}
|
||||
}
|
||||
showSnackbar({
|
||||
text: `不支持的链接:${link.href}`,
|
||||
color: "warn",
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tgn-container {
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
gap: 10px 10px;
|
||||
}
|
||||
|
||||
.tgn-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(20px);
|
||||
background: var(--common-shadow-t-4);
|
||||
box-shadow: 0 0 5px var(--common-shadow-4);
|
||||
color: var(--tgc-white-1);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tgn-nav img {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
.tgn-nav span {
|
||||
display: none;
|
||||
color: var(--common-text-title);
|
||||
font-family: var(--font-title);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tgn-nav:hover span {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@@ -14,8 +14,8 @@
|
||||
</div>
|
||||
<div class="tpc-content">
|
||||
<div class="tpc-title" :title="card.title">{{ card.title }}</div>
|
||||
<TpAvatar :data="card.user" position="left" />
|
||||
<div class="tpc-data">
|
||||
<TpAvatar v-if="card.user" :data="card.user" position="left" />
|
||||
<div class="tpc-data" v-if="card.data">
|
||||
<div class="tpc-info-item" :title="`浏览数:${card.data.view}`">
|
||||
<v-icon>mdi-eye</v-icon>
|
||||
<span>{{ card.data.view }}</span>
|
||||
@@ -38,7 +38,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tpc-forum" v-if="card.forum.icon !== ''" :title="`频道: ${card.forum.name}`">
|
||||
<div class="tpc-forum" v-if="card.forum" :title="`频道: ${card.forum.name}`">
|
||||
<img :src="card.forum.icon" :alt="card.forum.name" />
|
||||
<span>{{ card.forum.name }}</span>
|
||||
</div>
|
||||
@@ -50,7 +50,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onBeforeMount, ref } from "vue";
|
||||
|
||||
import { createPost } from "../../utils/TGWindow";
|
||||
import { createPost } from "../../utils/TGWindow.js";
|
||||
import TpAvatar from "../post/tp-avatar.vue";
|
||||
|
||||
interface TPostCardProps {
|
||||
@@ -157,23 +157,31 @@ function getPostCover(item: TGApp.Plugins.Mys.Post.FullData): string {
|
||||
* @returns {TGApp.Plugins.Mys.News.RenderCard} 渲染用咨讯列表项
|
||||
*/
|
||||
function getCommonCard(item: TGApp.Plugins.Mys.Post.FullData): TGApp.Plugins.Mys.News.RenderCard {
|
||||
let forum = null;
|
||||
let data = null;
|
||||
if (item.forum !== null) {
|
||||
forum = {
|
||||
name: item.forum.name,
|
||||
icon: item.forum.icon,
|
||||
};
|
||||
}
|
||||
if (item.stat !== null) {
|
||||
data = {
|
||||
mark: item.stat.bookmark_num,
|
||||
forward: item.stat.forward_num,
|
||||
like: item.stat.like_num,
|
||||
reply: item.stat.reply_num,
|
||||
view: item.stat.view_num,
|
||||
};
|
||||
}
|
||||
return {
|
||||
title: item.post.subject,
|
||||
cover: getPostCover(item),
|
||||
postId: Number(item.post.post_id),
|
||||
subtitle: item.post.post_id,
|
||||
user: item.user,
|
||||
forum: {
|
||||
name: item.forum.name,
|
||||
icon: item.forum.icon,
|
||||
},
|
||||
data: {
|
||||
mark: item.stat.bookmark_num,
|
||||
forward: item.stat.forward_num,
|
||||
like: item.stat.like_num,
|
||||
reply: item.stat.reply_num,
|
||||
view: item.stat.view_num,
|
||||
},
|
||||
forum: forum,
|
||||
data: data,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
// utils
|
||||
import TGLogger from "../../utils/TGLogger";
|
||||
import { generateShareImg } from "../../utils/TGShare";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import { generateShareImg } from "../../utils/TGShare.js";
|
||||
|
||||
interface TShareBtnProps {
|
||||
modelValue: HTMLElement;
|
||||
|
||||
@@ -56,8 +56,8 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
|
||||
import { AppAchievementsData, AppAchievementSeriesData } from "../../data";
|
||||
import TGLogger from "../../utils/TGLogger";
|
||||
import { AppAchievementsData, AppAchievementSeriesData } from "../../data/index.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
import ToPostSearch from "../post/to-postSearch.vue";
|
||||
|
||||
|
||||
@@ -28,14 +28,13 @@
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { http } from "@tauri-apps/api";
|
||||
import { ResponseType } from "@tauri-apps/api/http";
|
||||
import { fetch } from "@tauri-apps/plugin-http";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { xml2json } from "xml-js";
|
||||
|
||||
import { copyToClipboard, getImageBuffer, saveCanvasImg } from "../../utils/TGShare";
|
||||
import { bytesToSize } from "../../utils/toolFunc";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import { copyToClipboard, getImageBuffer, saveCanvasImg } from "../../utils/TGShare.js";
|
||||
import { bytesToSize } from "../../utils/toolFunc.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
interface ToArcBirthProps {
|
||||
@@ -166,11 +165,10 @@ async function loadText(): Promise<void> {
|
||||
|
||||
async function parseXml(link: string) {
|
||||
try {
|
||||
const res = await http.fetch<string>(link, {
|
||||
method: "GET",
|
||||
responseType: ResponseType.Text,
|
||||
});
|
||||
return JSON.parse(xml2json(res.data));
|
||||
const response = await fetch(link, { method: "GET" });
|
||||
const data = await response.arrayBuffer();
|
||||
const xml = new TextDecoder("utf-8").decode(data);
|
||||
return JSON.parse(xml2json(xml));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return false;
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
import { computed } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import { useAppStore } from "../../store/modules/app";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
interface ToChannelProps {
|
||||
@@ -72,6 +72,11 @@ const channelList: ToChannelItem[] = [
|
||||
icon: "/platforms/mhy/sr.webp",
|
||||
gid: "6",
|
||||
},
|
||||
{
|
||||
title: "绝区零",
|
||||
icon: "/platforms/mhy/zzz.webp",
|
||||
gid: "8",
|
||||
},
|
||||
{
|
||||
title: "崩坏3",
|
||||
icon: "/platforms/mhy/bh3.webp",
|
||||
@@ -87,11 +92,6 @@ const channelList: ToChannelItem[] = [
|
||||
icon: "/platforms/mhy/wd.webp",
|
||||
gid: "4",
|
||||
},
|
||||
{
|
||||
title: "绝区零",
|
||||
icon: "/platforms/mhy/zzz.webp",
|
||||
gid: "8",
|
||||
},
|
||||
{
|
||||
title: "大别野",
|
||||
icon: "/platforms/mhy/dby.webp",
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
||||
import TSUserCollection from "../../plugins/Sqlite/modules/userCollect";
|
||||
import showConfirm from "../func/confirm";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import TSUserCollection from "../../plugins/Sqlite/modules/userCollect.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
interface ToPostCollectProps {
|
||||
|
||||
@@ -22,11 +22,11 @@ import { storeToRefs } from "pinia";
|
||||
import QrcodeVue from "qrcode.vue";
|
||||
import { computed, onUnmounted, reactive, ref, watch } from "vue";
|
||||
|
||||
import Mys from "../../plugins/Mys";
|
||||
import { useUserStore } from "../../store/modules/user";
|
||||
import TGLogger from "../../utils/TGLogger";
|
||||
import TGRequest from "../../web/request/TGRequest";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import Mys from "../../plugins/Mys/index.js";
|
||||
import { useUserStore } from "../../store/modules/user.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import TGRequest from "../../web/request/TGRequest.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
interface ToWebLoginProps {
|
||||
@@ -80,6 +80,10 @@ function onCancel(): void {
|
||||
text: "已取消登录",
|
||||
color: "cancel",
|
||||
});
|
||||
if (cycleTimer !== null) {
|
||||
clearInterval(cycleTimer);
|
||||
cycleTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function freshQr(): Promise<void> {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
import { generateShareImg } from "../../utils/TGShare";
|
||||
import { generateShareImg } from "../../utils/TGShare.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
interface ToNamecardProps {
|
||||
|
||||
@@ -36,9 +36,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
||||
import TSUserCollection from "../../plugins/Sqlite/modules/userCollect";
|
||||
import showConfirm from "../func/confirm";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import TSUserCollection from "../../plugins/Sqlite/modules/userCollect.js";
|
||||
import showConfirm from "../func/confirm.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
interface ToPostCollectProps {
|
||||
@@ -100,7 +100,8 @@ async function deleteCollect(item: TGApp.Sqlite.UserCollection.UFCollection): Pr
|
||||
});
|
||||
return;
|
||||
}
|
||||
const resD = await TSUserCollection.deleteCollect(item.title);
|
||||
// todo,这边暂时将默认force设为false,后续需要根据需求修改
|
||||
const resD = await TSUserCollection.deleteCollect(item.title, false);
|
||||
if (resD) {
|
||||
showSnackbar({
|
||||
text: "删除成功",
|
||||
|
||||