Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f814bc8b5 | ||
|
|
885fa3b19e | ||
|
|
82ba88a2c9 | ||
|
|
1a4d175e3d | ||
|
|
6a39aa127b | ||
|
|
5c0d5f50fe | ||
|
|
27501acfd2 | ||
|
|
69157ea008 | ||
|
|
db00765f7b | ||
|
|
49854367b1 | ||
|
|
cab497f573 | ||
|
|
2c5c205566 | ||
|
|
447ee3b329 | ||
|
|
e049508ab6 | ||
|
|
9bfb7c4108 | ||
|
|
ea3a88ecb4 | ||
|
|
b502cf4025 | ||
|
|
942e63654e | ||
|
|
baf8c3f794 | ||
|
|
2abfcdc050 | ||
|
|
d22203e7b4 | ||
|
|
8f116c954f | ||
|
|
a8b1ff4588 | ||
|
|
5d036ddeee | ||
|
|
b2843dbf13 | ||
|
|
672fa2e536 | ||
|
|
a7a0a8b0e0 | ||
|
|
e9252bbfcd | ||
|
|
e3e5b757e4 | ||
|
|
6b18d63fb0 | ||
|
|
948db203bd | ||
|
|
f0b3a311d7 | ||
|
|
289620922d | ||
|
|
20ad79f08b | ||
|
|
db3cb2fa29 | ||
|
|
f822c0b32d | ||
|
|
632576de94 | ||
|
|
0b8dc2ef60 | ||
|
|
047f9eaf3a | ||
|
|
792d337e45 | ||
|
|
de89aa5159 | ||
|
|
5c8f2d5e57 | ||
|
|
7391752247 | ||
|
|
27a2e93efc | ||
|
|
5bf2521938 | ||
|
|
41ee27c74e | ||
|
|
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 | ||
|
|
e4057d96ea | ||
|
|
d3b24d52c9 | ||
|
|
711d35360f | ||
|
|
f0428d0bae | ||
|
|
59a686cace | ||
|
|
b628df5ae9 | ||
|
|
b22d23f663 |
4
.github/workflows/build.yml
vendored
@@ -43,11 +43,11 @@ jobs:
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 22.0.0
|
||||
node-version: 22.3.0
|
||||
- name: setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 9.1.0
|
||||
version: 9.6.0
|
||||
- name: remove lockfile
|
||||
run: rm pnpm-lock.yaml
|
||||
- name: Install frontend dependencies
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
||||
pnpm lint-staged
|
||||
|
||||
@@ -15,3 +15,4 @@ qodana.yaml
|
||||
*.svg
|
||||
# data
|
||||
!src/data/**/*.json
|
||||
src-tauri/gen/*.json
|
||||
|
||||
234
CHANGELOG.md
@@ -1,200 +1,58 @@
|
||||
---
|
||||
Author: 目棃
|
||||
Description: CHANGELOG
|
||||
Date: 2024-01-15
|
||||
Update: 2024-06-04
|
||||
Date: 2024-07-09
|
||||
Update: 2024-08-11
|
||||
---
|
||||
|
||||
> 本文档 [`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-04 20:07:53`
|
||||
> 更新于 `2024-08-11 15:43:34`
|
||||
|
||||
## [0.4.8](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.8) (2024-06-04)
|
||||
## [0.5.2](https://github.com/BTMuli/TeyvatGuide/releases/v0.5.2) (2024-08-11)
|
||||
|
||||
- 🐛 修复名片解析异常 [`#110`](https://github.com/BTMuli/TeyvatGuide/issues/110)
|
||||
- 💄 调整链接组件样式
|
||||
- 💄 调整首页生日组件样式
|
||||
- 🐛 修复版本搜索失效,未完成成就优先
|
||||
- 🍱 更新 4.7 版本资源 [`#112`](https://github.com/BTMuli/TeyvatGuide/issues/112)
|
||||
- 🐛 修复日志目录异常
|
||||
- ♻️ 重构窗体/缩放调整逻辑
|
||||
- 🐛 修复公告时间获取异常&内容渲染异常
|
||||
- 🔥 移除扫码登录模块
|
||||
👽️ 调整更新日志链接
|
||||
- 🍱 更新4.8下半数据
|
||||
|
||||
## [0.4.7](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.7) (2024-05-10)
|
||||
## [0.5.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.5.1) (2024-07-30)
|
||||
|
||||
- 🐛 修复 mention 类型渲染异常
|
||||
- ⚡️ 对签到链接跳转进行处理,优化部分网页活动打开
|
||||
- ♻️ 重构用户祈愿数据库相关处理
|
||||
- 🔥 隐藏网页登录模块 [`#108`](https://github.com/BTMuli/TeyvatGuide/issues/108)
|
||||
- ✨ 采用 ajv 验证 UIGF [`#109`](https://github.com/BTMuli/TeyvatGuide/issues/109)
|
||||
- 💄 完善公告`table`&`p`部分的渲染
|
||||
- 💄 调整帖子文本部分的样式
|
||||
- ♻️ UIAF重构,支持祈愿备份/恢复
|
||||
- ⚡️ 完善公告正则
|
||||
- ♻️ 名片组件抽离,wiki添加名片信息
|
||||
- ⚡️ 不允许低于 UIGF v2.3 版本的数据导入
|
||||
- 🐛 修复网页小工具数据获取异常
|
||||
- ⚡️ 咨讯页刷新时记忆 tab 状态,顶部按钮进行调整
|
||||
- ⚡️ 调整收藏页面分类删除逻辑,优化卡片样式
|
||||
- ⚡️ 设置页数据目录添加按钮显式表示相关操作
|
||||
- ⚡️ 优化帖子搜索逻辑,不会自动弹出浮窗
|
||||
- 💄 帖子页面调整刷新数量,20→12
|
||||
- 💄 角色/武器图鉴材料支持左右切换
|
||||
- ✨ 支持短信验证码登录 [`#118`](https://github.com/BTMuli/TeyvatGuide/issues/118)
|
||||
- 💄 调整首页日历组件不同状态下的背景色、边缘、文本色
|
||||
- ♻️ 重构米游社相关链接解析处理
|
||||
- 💄 分享色背景设为透明
|
||||
- 🐛 修复特定情况下的米游社子窗口分享功能异常
|
||||
- 💄 设置页显示设备信息,支持复制cookie
|
||||
- 💄 帖子顶部添加分区图标
|
||||
- 🐛 修复祈愿页面导出按钮逻辑异常
|
||||
- 🐛 修复公告页部分公告时间解析异常
|
||||
- 🐛 调整祈愿页面抽数计算规则
|
||||
- 💄 根据屏幕缩放调整应用缩放
|
||||
|
||||
## [0.4.6](https://github.com/BTMuli/TeyvatGuide/releases/v0.4.6) (2024-04-24)
|
||||
## [0.5.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.5.0) (2024-07-17)
|
||||
|
||||
### 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 页面草创
|
||||
|
||||
11
README.md
@@ -2,16 +2,16 @@
|
||||
Author: 目棃
|
||||
Description: 说明文档
|
||||
Date: 2023-03-05
|
||||
Update: 2024-04-05
|
||||
Update: 2024-07-31
|
||||
---
|
||||
|
||||
> 本文档 [`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-31 18:21:43`
|
||||
|
||||
 
|
||||
|
||||
  
|
||||
   
|
||||
|
||||
<div style="width: 100%; text-align: center; margin: 0 auto;">
|
||||
<img alt="icon" src="https://s2.loli.net/2023/10/19/Y5DpBQRy3usLHEb.png" />
|
||||
@@ -33,7 +33,7 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
|
||||
|
||||
> macOS 用户可以通过 Github Release 下载
|
||||
|
||||
[](https://github.com/BTMuli/TeyvatGuide/releases/latest)
|
||||
[](https://github.com/BTMuli/TeyvatGuide/releases/latest)
|
||||
|
||||
## 仓库概况 / Repo Stats
|
||||
|
||||
@@ -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,UIGF v4.0)
|
||||
- [x] 留影叙佳期画片查看
|
||||
- [x] 帖子收藏
|
||||
|
||||
@@ -66,6 +66,7 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
|
||||
- [x] 武器图鉴
|
||||
- [x] 名片图鉴
|
||||
- [x] 卡牌图鉴
|
||||
- [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,10 +1,11 @@
|
||||
<!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" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>TeyvatGuide</title>
|
||||
<script src="https://static.geetest.com/v4/gt4.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
91
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "TeyvatGuide",
|
||||
"version": "0.4.8",
|
||||
"version": "0.5.2",
|
||||
"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,68 +66,77 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdi/font": "7.4.47",
|
||||
"@tauri-apps/api": "^1.5.5",
|
||||
"ajv": "^8.13.0",
|
||||
"artplayer": "^5.1.1",
|
||||
"@tauri-apps/api": "2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-deep-link": "2.0.0-beta.10",
|
||||
"@tauri-apps/plugin-dialog": "2.0.0-beta.8",
|
||||
"@tauri-apps/plugin-fs": "2.0.0-beta.8",
|
||||
"@tauri-apps/plugin-http": "2.0.0-beta.9",
|
||||
"@tauri-apps/plugin-log": "2.0.0-beta.9",
|
||||
"@tauri-apps/plugin-os": "2.0.0-beta.8",
|
||||
"@tauri-apps/plugin-process": "2.0.0-beta.8",
|
||||
"@tauri-apps/plugin-shell": "2.0.0-beta.9",
|
||||
"@tauri-apps/plugin-sql": "2.0.0-beta.7",
|
||||
"ajv": "^8.17.1",
|
||||
"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",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"pinia": "^2.2.0",
|
||||
"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": "^9.0.1",
|
||||
"vue": "^3.4.27",
|
||||
"vue-echarts": "^6.7.2",
|
||||
"uuid": "^10.0.0",
|
||||
"vue": "^3.4.35",
|
||||
"vue-echarts": "^6.7.3",
|
||||
"vue-json-viewer": "^3.0.4",
|
||||
"vue-router": "^4.3.2",
|
||||
"vuetify": "^3.6.6",
|
||||
"vue-router": "^4.4.2",
|
||||
"vuetify": "^3.6.14",
|
||||
"wcag-color": "^1.1.1",
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.0.2",
|
||||
"@eslint/js": "^9.2.0",
|
||||
"@tauri-apps/cli": "^1.5.14",
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "^9.8.0",
|
||||
"@tauri-apps/cli": "2.0.0-beta.21",
|
||||
"@types/color-convert": "^2.0.3",
|
||||
"@types/js-md5": "^0.7.2",
|
||||
"@types/node": "^20.12.12",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@typescript-eslint/parser": "^7.9.0",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@types/node": "^22.1.0",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/parser": "^8.0.0",
|
||||
"@vitejs/plugin-vue": "^5.1.2",
|
||||
"concurrently": "^8.2.2",
|
||||
"eslint": "^9.2.0",
|
||||
"eslint-config-love": "^47.0.0",
|
||||
"eslint": "^9.8.0",
|
||||
"eslint-config-love": "^62.0.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsonc": "^2.15.1",
|
||||
"eslint-plugin-n": "^17.7.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-vue": "^9.26.0",
|
||||
"eslint-plugin-jsonc": "^2.16.0",
|
||||
"eslint-plugin-n": "^17.10.1",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-promise": "^7.0.0",
|
||||
"eslint-plugin-vue": "^9.27.0",
|
||||
"eslint-plugin-yml": "^1.14.0",
|
||||
"globals": "^15.2.0",
|
||||
"husky": "^9.0.11",
|
||||
"globals": "^15.9.0",
|
||||
"husky": "^9.1.4",
|
||||
"jsonc-eslint-parser": "^2.4.0",
|
||||
"lint-staged": "^15.2.2",
|
||||
"oxlint": "^0.3.4",
|
||||
"prettier": "3.2.5",
|
||||
"stylelint": "^16.5.0",
|
||||
"lint-staged": "^15.2.7",
|
||||
"oxlint": "^0.6.1",
|
||||
"prettier": "3.3.3",
|
||||
"stylelint": "^16.8.1",
|
||||
"stylelint-config-idiomatic-order": "^10.0.0",
|
||||
"stylelint-config-standard-vue": "^1.0.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "^2.8.0",
|
||||
"stylelint-high-performance-animation": "^1.10.0",
|
||||
"stylelint-order": "^6.0.4",
|
||||
"stylelint-prettier": "^5.0.0",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-eslint": "^7.9.0",
|
||||
"vite": "^5.2.11",
|
||||
"vite-plugin-vue-devtools": "^7.1.3",
|
||||
"stylelint-prettier": "^5.0.2",
|
||||
"typescript": "^5.5.4",
|
||||
"typescript-eslint": "^8.0.0",
|
||||
"vite": "^5.3.5",
|
||||
"vite-plugin-node-polyfills": "^0.22.0",
|
||||
"vite-plugin-vue-devtools": "^7.3.7",
|
||||
"vite-plugin-vuetify": "^2.0.3",
|
||||
"vue-eslint-parser": "^9.4.2",
|
||||
"yaml-eslint-parser": "^1.2.2"
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"yaml-eslint-parser": "^1.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
2763
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: 42 KiB |
BIN
public/WIKI/GCG/normal/机关·算力增幅器·芒.webp
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
public/WIKI/GCG/normal/机关·算力增幅器·荒.webp
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
public/WIKI/GCG/normal/歼灭特化型机关.webp
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
public/WIKI/GCG/normal/歼灭特化型机关·芒.webp
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
public/WIKI/GCG/normal/歼灭特化型机关·荒.webp
Normal file
|
After Width: | Height: | Size: 60 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 |
3194
src-tauri/Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "TeyvatGuide"
|
||||
version = "0.4.8"
|
||||
version = "0.5.2"
|
||||
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.4", features = [] }
|
||||
tauri-build = { version = "2.0.0-beta.19", features = [] }
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.38"
|
||||
log = "0.4.21"
|
||||
serde = { version = "1.0.201", features = ["derive"] }
|
||||
serde_json = "1.0.117"
|
||||
tauri = { version = "1.6.7", 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.0"
|
||||
log = "0.4.22"
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
serde_json = "1.0.122"
|
||||
tauri = { version = "2.0.0-rc.0", features = [] }
|
||||
tauri-utils = "2.0.0-rc.0"
|
||||
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
|
||||
|
||||
42
src-tauri/capabilities/DevJson.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "DevJson",
|
||||
"description": "Capability for the dev json window",
|
||||
"windows": ["Dev_JSON"],
|
||||
"permissions": [
|
||||
"core:app:allow-version",
|
||||
"core:app:default",
|
||||
"core:event:allow-listen",
|
||||
"core:event:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"core:path:allow-resolve-directory",
|
||||
"core:path:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:webview:default",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-destroy",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-title",
|
||||
"core:window:allow-set-fullscreen",
|
||||
"core:window:allow-show",
|
||||
"core:window:default",
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://*.miyoushe.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.mihoyo.com/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
}
|
||||
89
src-tauri/capabilities/Mys.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "Mys",
|
||||
"description": "Capability for the mys client window",
|
||||
"windows": ["mhy_client"],
|
||||
"permissions": [
|
||||
"dialog:allow-message",
|
||||
"dialog:default",
|
||||
"core:event:allow-emit",
|
||||
"http:allow-fetch",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:webview:default",
|
||||
"core:window:allow-center",
|
||||
"core:window:default",
|
||||
"core:path:allow-resolve-directory",
|
||||
"core: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": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://*.miyoushe.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.mihoyo.com/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"remote": {
|
||||
"urls": ["https://*.mihoyo.com/*", "https://*.miyoushe.com/*"]
|
||||
},
|
||||
"platforms": ["windows", "macOS"]
|
||||
}
|
||||
75
src-tauri/capabilities/SubWindow.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "SubWindow",
|
||||
"description": "Capability for the sub window",
|
||||
"windows": ["Sub_window"],
|
||||
"permissions": [
|
||||
"core:app:allow-version",
|
||||
"core:app:default",
|
||||
"dialog:allow-save",
|
||||
"dialog:default",
|
||||
"core:event:allow-listen",
|
||||
"core:event:default",
|
||||
"fs:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"core:path:allow-resolve-directory",
|
||||
"core:path:default",
|
||||
"shell:allow-open",
|
||||
"shell:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:webview:default",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-destroy",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-title",
|
||||
"core:window:allow-set-fullscreen",
|
||||
"core:window:allow-show",
|
||||
"core:window: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": "**" }]
|
||||
},
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://*.miyoushe.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.mihoyo.com/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
}
|
||||
99
src-tauri/capabilities/TeyvatGuide.json
Normal file
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "TeyvatGuide",
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["TeyvatGuide"],
|
||||
"permissions": [
|
||||
"core:app:allow-version",
|
||||
"core:app:default",
|
||||
"dialog:allow-save",
|
||||
"dialog:default",
|
||||
"core:event:allow-listen",
|
||||
"core:event:default",
|
||||
"fs:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"core:path:allow-resolve-directory",
|
||||
"core:path:default",
|
||||
"process:allow-exit",
|
||||
"process:default",
|
||||
"shell:allow-execute",
|
||||
"shell:allow-open",
|
||||
"shell:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"core:webview:allow-create-webview-window",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:webview:default",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-destroy",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:default",
|
||||
"core:window:allow-is-minimized",
|
||||
"core:window:allow-set-title",
|
||||
"core:window:allow-set-focus",
|
||||
"core:window:allow-show",
|
||||
"core: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"]
|
||||
}
|
||||
3644
src-tauri/gen/schemas/acl-manifests.json
Normal file
179
src-tauri/gen/schemas/capabilities.json
Normal file
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"DevJson": {
|
||||
"identifier": "DevJson",
|
||||
"description": "Capability for the dev json window",
|
||||
"local": true,
|
||||
"windows": ["Dev_JSON"],
|
||||
"permissions": [
|
||||
"core:app:allow-version",
|
||||
"core:app:default",
|
||||
"core:event:allow-listen",
|
||||
"core:event:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"core:path:allow-resolve-directory",
|
||||
"core:path:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:webview:default",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-destroy",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-title",
|
||||
"core:window:allow-set-fullscreen",
|
||||
"core:window:allow-show",
|
||||
"core:window:default",
|
||||
{
|
||||
"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",
|
||||
"core:event:allow-emit",
|
||||
"http:allow-fetch",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:webview:default",
|
||||
"core:window:allow-center",
|
||||
"core:window:default",
|
||||
"core:path:allow-resolve-directory",
|
||||
"core: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": "**" }] },
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [{ "url": "https://*.miyoushe.com/*" }, { "url": "https://*.mihoyo.com/*" }]
|
||||
}
|
||||
],
|
||||
"platforms": ["windows", "macOS"]
|
||||
},
|
||||
"SubWindow": {
|
||||
"identifier": "SubWindow",
|
||||
"description": "Capability for the sub window",
|
||||
"local": true,
|
||||
"windows": ["Sub_window"],
|
||||
"permissions": [
|
||||
"core:app:allow-version",
|
||||
"core:app:default",
|
||||
"dialog:allow-save",
|
||||
"dialog:default",
|
||||
"core:event:allow-listen",
|
||||
"core:event:default",
|
||||
"fs:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"core:path:allow-resolve-directory",
|
||||
"core:path:default",
|
||||
"shell:allow-open",
|
||||
"shell:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:webview:default",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-destroy",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-title",
|
||||
"core:window:allow-set-fullscreen",
|
||||
"core:window:allow-show",
|
||||
"core:window: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": "**" }] },
|
||||
{
|
||||
"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": [
|
||||
"core:app:allow-version",
|
||||
"core:app:default",
|
||||
"dialog:allow-save",
|
||||
"dialog:default",
|
||||
"core:event:allow-listen",
|
||||
"core:event:default",
|
||||
"fs:default",
|
||||
"http:allow-fetch",
|
||||
"log:allow-log",
|
||||
"log:default",
|
||||
"core:path:allow-resolve-directory",
|
||||
"core:path:default",
|
||||
"process:allow-exit",
|
||||
"process:default",
|
||||
"shell:allow-execute",
|
||||
"shell:allow-open",
|
||||
"shell:default",
|
||||
"sql:allow-load",
|
||||
"sql:allow-execute",
|
||||
"sql:default",
|
||||
"core:webview:allow-create-webview-window",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:webview:default",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-destroy",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:default",
|
||||
"core:window:allow-is-minimized",
|
||||
"core:window:allow-set-title",
|
||||
"core:window:allow-set-focus",
|
||||
"core:window:allow-show",
|
||||
"core: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"]
|
||||
}
|
||||
}
|
||||
5150
src-tauri/gen/schemas/desktop-schema.json
Normal file
5150
src-tauri/gen/schemas/windows-schema.json
Normal file
@@ -1,11 +1,14 @@
|
||||
//! @file src/client/menu.rs
|
||||
//! @desc 客户端菜单模块,负责操作米游社客户端菜单
|
||||
//! @since Beta v0.4.5
|
||||
//! @since Beta v0.5.2
|
||||
|
||||
use tauri::{AppHandle, CustomMenuItem, LogicalSize, Manager, Menu, Size, Submenu, WindowUrl};
|
||||
use crate::client::utils;
|
||||
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 +16,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);
|
||||
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");
|
||||
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());
|
||||
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 +129,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 +144,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 +159,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,39 +174,26 @@ 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;
|
||||
}
|
||||
let window = window_get.unwrap();
|
||||
// 获取窗口宽高比
|
||||
let cur_size = window.inner_size().ok().unwrap();
|
||||
let monitor = window.primary_monitor().ok().unwrap().unwrap();
|
||||
if cur_size.width > cur_size.height {
|
||||
window.set_size(Size::Logical(LogicalSize { width: 400.0, height: 800.0 })).unwrap();
|
||||
let trans_size = utils::get_window_size2(monitor, 400.0, 800.0);
|
||||
window
|
||||
.set_size(Size::Logical(LogicalSize { width: trans_size.0, height: trans_size.1 }))
|
||||
.unwrap();
|
||||
} else {
|
||||
window.set_size(Size::Logical(LogicalSize { width: 1280.0, height: 720.0 })).unwrap();
|
||||
let trans_size = utils::get_window_size2(monitor, 1280.0, 720.0);
|
||||
window
|
||||
.set_size(Size::Logical(LogicalSize { width: trans_size.0, height: trans_size.1 }))
|
||||
.unwrap();
|
||||
}
|
||||
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,44 @@
|
||||
//! @file src/client/mod.rs
|
||||
//! @desc 客户端模块,负责操作米游社客户端
|
||||
//! @since Beta v0.4.5
|
||||
//! @since Beta v0.5.2
|
||||
|
||||
mod menu;
|
||||
use tauri::async_runtime::block_on;
|
||||
use tauri::{AppHandle, Manager, WindowBuilder, WindowEvent, WindowUrl};
|
||||
mod utils;
|
||||
|
||||
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))
|
||||
let trans_size = utils::get_window_size(handle.clone(), win_width, win_height);
|
||||
WebviewWindowBuilder::new(&handle, "mhy_client", url_parse)
|
||||
.inner_size(trans_size.0, trans_size.1)
|
||||
.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();
|
||||
}
|
||||
|
||||
22
src-tauri/src/client/utils.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
//! @file src/client/utils.rs
|
||||
//! @desc 结合屏幕分辨率获取窗口大小
|
||||
//! @since Beta v0.5.2
|
||||
|
||||
use tauri::{AppHandle, Manager, Monitor};
|
||||
|
||||
pub fn get_window_size(app: AppHandle, width: f64, height: f64) -> (f64, f64) {
|
||||
let mhy_window = app.get_webview_window("TeyvatGuide").unwrap();
|
||||
let monitor = mhy_window.primary_monitor().unwrap().expect("failed to get primary monitor");
|
||||
get_window_size2(monitor, width, height)
|
||||
}
|
||||
|
||||
pub fn get_window_size2(monitor: Monitor, width: f64, height: f64) -> (f64, f64) {
|
||||
let monitor_size = monitor.size();
|
||||
let monitor_width = monitor_size.width as f64;
|
||||
let monitor_height = monitor_size.height as f64;
|
||||
let width_scale = monitor_width / 1920.0;
|
||||
let height_scale = monitor_height / 1080.0;
|
||||
let get_width = (width * width_scale).round();
|
||||
let get_height = (height * height_scale).round();
|
||||
(get_width, get_height)
|
||||
}
|
||||
@@ -1,74 +1,57 @@
|
||||
//! @file src/commands.rs
|
||||
//! @desc 命令模块,负责处理命令
|
||||
//! @since Beta v0.4.3
|
||||
//! @since Beta v0.5.1
|
||||
|
||||
use tauri::{Manager, WindowBuilder};
|
||||
use tauri_utils::config::WindowConfig;
|
||||
use tauri::{AppHandle, Emitter, 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,46 +1,54 @@
|
||||
//! @file src/main.rs
|
||||
//! @desc 主模块,用于启动应用
|
||||
//! @since Beta v0.4.3
|
||||
//! @since Beta v0.5.2
|
||||
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
use tauri::Manager;
|
||||
use tauri::{Emitter, Manager};
|
||||
mod client;
|
||||
mod commands;
|
||||
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))
|
||||
.plugin(plugins::build_sql_plugin())
|
||||
.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(tauri_plugin_sql::Builder::default().build())
|
||||
.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,32 +1,28 @@
|
||||
//! @file src/plugins.rs
|
||||
//! @desc 插件模块,用于注册插件
|
||||
//! @since Beta v0.4.4
|
||||
//! @since Beta v0.5.2
|
||||
|
||||
use super::utils;
|
||||
use log::LevelFilter;
|
||||
use tauri::plugin::TauriPlugin;
|
||||
use tauri::Runtime;
|
||||
use tauri_plugin_log::{LogTarget, TimezoneStrategy};
|
||||
use tauri_plugin_sql::PluginConfig;
|
||||
|
||||
// sqlite 插件
|
||||
pub fn build_sql_plugin<R: Runtime>() -> TauriPlugin<R, Option<PluginConfig>> {
|
||||
tauri_plugin_sql::Builder::default().build()
|
||||
}
|
||||
use tauri_plugin_log::{Target, TargetKind, TimezoneStrategy};
|
||||
|
||||
// 日志插件
|
||||
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.2",
|
||||
"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.8"
|
||||
},
|
||||
"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": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
169
src/App.vue
@@ -11,22 +11,24 @@
|
||||
</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, window as TauriWindow } from "@tauri-apps/api";
|
||||
import { PhysicalSize } from "@tauri-apps/api/dpi";
|
||||
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 +43,55 @@ let themeListener: UnlistenFn;
|
||||
let urlListener: UnlistenFn;
|
||||
|
||||
onBeforeMount(async () => {
|
||||
const win = TauriWindow.getCurrent();
|
||||
const win = webviewWindow.getCurrentWebviewWindow();
|
||||
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 checkResize();
|
||||
await win.show();
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
async function checkResize(): Promise<void> {
|
||||
const screen = await TauriWindow.currentMonitor();
|
||||
if (screen === null) {
|
||||
showSnackbar({
|
||||
text: "获取屏幕信息失败!",
|
||||
color: "error",
|
||||
timeout: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const windowCur = await webviewWindow.getCurrentWebviewWindow();
|
||||
if (await windowCur.isMaximized()) return;
|
||||
const designSize = getSize(windowCur.label);
|
||||
const widthScale = screen.size.width / 1920;
|
||||
const heightScale = screen.size.height / 1080;
|
||||
await windowCur.setSize(
|
||||
new PhysicalSize(
|
||||
Math.round(designSize.width * widthScale),
|
||||
Math.round(designSize.height * heightScale),
|
||||
),
|
||||
);
|
||||
await windowCur.setZoom((1 / screen.scaleFactor) * Math.min(widthScale, heightScale));
|
||||
await windowCur.center();
|
||||
return;
|
||||
}
|
||||
|
||||
function getSize(label: string): PhysicalSize {
|
||||
if (label === "TeyvatGuide") return new PhysicalSize(1600, 900);
|
||||
if (label === "Sub_Window" || label === "Dev_JSON") return new PhysicalSize(960, 720);
|
||||
return new PhysicalSize(1280, 720);
|
||||
}
|
||||
|
||||
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 +100,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 +114,6 @@ async function listenOnInit(): Promise<void> {
|
||||
}
|
||||
await checkUpdate();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
async function checkAppLoad(): Promise<void> {
|
||||
@@ -108,15 +143,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 +176,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 +196,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.getCurrentWebviewWindow().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>();
|
||||
@@ -52,7 +52,7 @@ function toStore() {
|
||||
}
|
||||
|
||||
function toSite() {
|
||||
window.open("https://app.btmuli.ink/docs/Changelogs.html");
|
||||
window.open("https://app.btmuli.ink/docs/TeyvatGuide/changelogs.html");
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
|
||||
@@ -2,63 +2,103 @@
|
||||
<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>
|
||||
<v-list-item title="用户数据目录" :subtitle="appStore.userDir">
|
||||
<template #prepend>
|
||||
<div class="config-icon">
|
||||
<v-icon>mdi-folder-key</v-icon>
|
||||
</div>
|
||||
</template>
|
||||
<v-list-item-title style="cursor: pointer" @click="confirmCUD"
|
||||
>用户数据目录
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle @click="openPath('user')">{{ appStore.userDir }}</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-icon @click="copyPath('user')">mdi-content-copy</v-icon>
|
||||
<v-icon @click="confirmCUD()" style="cursor: pointer" title="修改用户数据目录"
|
||||
>mdi-pencil
|
||||
</v-icon>
|
||||
 
|
||||
<v-icon @click="openPath('user')" style="cursor: pointer" title="打开用户数据目录"
|
||||
>mdi-folder-open
|
||||
</v-icon>
|
||||
 
|
||||
<v-icon @click="copyPath('user')" style="cursor: pointer" title="复制用户数据目录路径"
|
||||
>mdi-content-copy
|
||||
</v-icon>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item title="应用数据库路径">
|
||||
<v-list-item title="应用数据库路径" :subtitle="appStore.dbPath">
|
||||
<template #prepend>
|
||||
<div class="config-icon">
|
||||
<v-icon>mdi-folder-account</v-icon>
|
||||
</div>
|
||||
</template>
|
||||
<v-list-item-subtitle @click="openPath('db')">{{ appStore.dbPath }}</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-icon @click="copyPath('db')">mdi-content-copy</v-icon>
|
||||
<v-icon @click="openPath('db')" style="cursor: pointer" title="打开数据库目录"
|
||||
>mdi-folder-open
|
||||
</v-icon>
|
||||
 
|
||||
<v-icon @click="copyPath('db')" style="cursor: pointer" title="复制数据库目录路径"
|
||||
>mdi-content-copy
|
||||
</v-icon>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-list-item title="日志目录" :subtitle="appStore.logDir">
|
||||
<template #prepend>
|
||||
<div class="config-icon">
|
||||
<v-icon>mdi-folder-multiple</v-icon>
|
||||
</div>
|
||||
</template>
|
||||
<v-list-item-title style="cursor: pointer" @click="confirmCLD">日志目录</v-list-item-title>
|
||||
<v-list-item-subtitle @click="openPath('log')">{{ appStore.logDir }}</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-icon @click="copyPath('log')">mdi-content-copy</v-icon>
|
||||
<v-icon @click="confirmCLD()" style="cursor: pointer" title="清理日志文件"
|
||||
>mdi-delete
|
||||
</v-icon>
|
||||
 
|
||||
<v-icon @click="openPath('log')" style="cursor: pointer" title="打开日志目录"
|
||||
>mdi-folder-open
|
||||
</v-icon>
|
||||
 
|
||||
<v-icon @click="copyPath('log')" style="cursor: pointer" title="复制日志目录路径"
|
||||
>mdi-content-copy
|
||||
</v-icon>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</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 { onMounted } from "vue";
|
||||
|
||||
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();
|
||||
|
||||
onMounted(async () => {
|
||||
const logDir = await path.appLogDir();
|
||||
const dbPath = `${await path.appConfigDir()}${path.sep()}TeyvatGuide.db`;
|
||||
let message = "";
|
||||
if (appStore.dbPath !== dbPath) {
|
||||
appStore.dbPath = dbPath;
|
||||
await TGSqlite.saveAppData("dbPath", dbPath);
|
||||
message += "数据库路径 ";
|
||||
}
|
||||
if (appStore.logDir !== logDir) {
|
||||
appStore.logDir = logDir;
|
||||
message += "日志路径 ";
|
||||
}
|
||||
if (message !== "") {
|
||||
showSnackbar({
|
||||
text: `${message}已更新!`,
|
||||
color: "success",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function confirmCUD(): Promise<void> {
|
||||
const oriDir = appStore.userDir;
|
||||
const check = await showConfirm({
|
||||
title: "确认修改用户数据路径吗?",
|
||||
text: "祈愿数据需修改后重新手动备份!",
|
||||
});
|
||||
const check = await showConfirm({ title: "确认修改用户数据路径吗?" });
|
||||
if (!check) {
|
||||
showSnackbar({
|
||||
color: "cancel",
|
||||
@@ -66,7 +106,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 +118,6 @@ async function confirmCUD(): Promise<void> {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (typeof dir !== "string") {
|
||||
showSnackbar({
|
||||
color: "error",
|
||||
text: "路径错误!",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (dir === oriDir) {
|
||||
showSnackbar({
|
||||
color: "warn",
|
||||
@@ -95,11 +128,21 @@ async function confirmCUD(): Promise<void> {
|
||||
appStore.userDir = dir;
|
||||
await TGSqlite.saveAppData("userDir", dir);
|
||||
await backUpUserData(dir);
|
||||
await fs.removeDir(oriDir, { recursive: true });
|
||||
showSnackbar({
|
||||
text: "已重新备份数据!即将刷新页面!",
|
||||
timeout: 3000,
|
||||
text: "已重新备份数据!",
|
||||
color: "success",
|
||||
});
|
||||
const confirm = await showConfirm({
|
||||
title: "是否删除原用户数据目录?",
|
||||
text: "删除后不可恢复!",
|
||||
});
|
||||
if (confirm) {
|
||||
await remove(oriDir, { recursive: true });
|
||||
showSnackbar({
|
||||
text: "已删除原用户数据目录!",
|
||||
color: "success",
|
||||
});
|
||||
}
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 4000);
|
||||
@@ -126,11 +169,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 +186,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) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<template>
|
||||
<ToGameLogin v-model="scan" @success="refreshUser" />
|
||||
<v-card class="tcu-box">
|
||||
<template #prepend>
|
||||
<v-avatar :image="userInfo.avatar" />
|
||||
@@ -9,28 +8,38 @@
|
||||
<template #text>{{ userInfo.desc }}</template>
|
||||
<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" />
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
@click="tryCaptchaLogin()"
|
||||
icon="mdi-cellphone"
|
||||
title="验证码登录"
|
||||
/>
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
@click="confirmRefreshUser"
|
||||
icon="mdi-refresh"
|
||||
:loading="loading"
|
||||
title="刷新用户信息"
|
||||
/>
|
||||
<v-btn variant="outlined" @click="confirmCopyCookie" icon="mdi-cookie" title="复制Cookie" />
|
||||
</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 { 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 ToGameLogin from "../overlay/to-gameLogin.vue";
|
||||
import Mys from "../../plugins/Mys/index.js";
|
||||
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 showGeetest from "../func/geetest.js";
|
||||
import showSnackbar from "../func/snackbar.js";
|
||||
|
||||
interface TcUserBadgeEmits {
|
||||
(e: "loadOuter", v: TGApp.Component.Loading.EmitParams): void;
|
||||
@@ -42,7 +51,6 @@ const appStore = useAppStore();
|
||||
const userStore = storeToRefs(useUserStore());
|
||||
|
||||
const loading = ref<boolean>(false);
|
||||
const scan = ref<boolean>(false);
|
||||
const userInfo = ref<TGApp.App.Account.BriefInfo>({
|
||||
nickname: "未登录",
|
||||
uid: "-1",
|
||||
@@ -64,175 +72,63 @@ watch(userStore.briefInfo, (v) => {
|
||||
}
|
||||
});
|
||||
|
||||
async function toWebLogin(): Promise<void> {
|
||||
const confirm = await showConfirm({
|
||||
title: "请在子窗口中完成登录操作",
|
||||
text: "请操作完成后点击子窗口的“用户登录”菜单",
|
||||
async function tryCaptchaLogin(): Promise<void> {
|
||||
const phone = await showConfirm({
|
||||
mode: "input",
|
||||
title: "请输入手机号",
|
||||
text: "+86",
|
||||
});
|
||||
if (!confirm) {
|
||||
if (!phone) {
|
||||
showSnackbar({
|
||||
color: "cancel",
|
||||
text: "已取消登录",
|
||||
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 });
|
||||
const phoneReg = /^1[3-9]\d{9}$/;
|
||||
if (!phoneReg.test(phone)) {
|
||||
showSnackbar({
|
||||
text: "未检测到 login_ticket, 请确认是否登录成功!",
|
||||
color: "error",
|
||||
text: "请输入正确的手机号",
|
||||
});
|
||||
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: "",
|
||||
const actionType = await tryGetCaptcha(phone);
|
||||
if (!actionType) return;
|
||||
showSnackbar({
|
||||
text: `已发送验证码到 ${phone}`,
|
||||
});
|
||||
const captcha = await showConfirm({
|
||||
mode: "input",
|
||||
title: "请输入验证码",
|
||||
text: "验证码:",
|
||||
otcancel: false,
|
||||
});
|
||||
if (!captcha) {
|
||||
showSnackbar({
|
||||
color: "error",
|
||||
text: "输入验证码为空",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const loginResp = await tryLoginByCaptcha(phone, captcha, actionType);
|
||||
if (!loginResp) return;
|
||||
userStore.cookie.value = {
|
||||
account_id: loginResp.user_info.aid,
|
||||
ltuid: loginResp.user_info.aid,
|
||||
stuid: loginResp.user_info.aid,
|
||||
mid: loginResp.user_info.mid,
|
||||
cookie_token: "",
|
||||
stoken: "",
|
||||
stoken: loginResp.token.token,
|
||||
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);
|
||||
showSnackbar({
|
||||
text: "登录成功,即将刷新用户信息",
|
||||
color: "success",
|
||||
});
|
||||
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 });
|
||||
setTimeout(() => {
|
||||
refreshUser();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
async function refreshUser() {
|
||||
@@ -241,7 +137,7 @@ async function refreshUser() {
|
||||
await TGLogger.Error("[tc-userBadge][refreshUser] cookie 不存在");
|
||||
showSnackbar({
|
||||
color: "error",
|
||||
text: "扫码登录后才能刷新用户信息!",
|
||||
text: "登录后才能刷新用户信息!",
|
||||
});
|
||||
appStore.isLogin = false;
|
||||
return;
|
||||
@@ -321,8 +217,8 @@ async function refreshUser() {
|
||||
emits("loadOuter", { show: false });
|
||||
}
|
||||
|
||||
async function refreshUserInfo(cnt: number = 0): Promise<number> {
|
||||
let failCount = cnt;
|
||||
async function refreshUserInfo(): Promise<number> {
|
||||
let failCount = 0;
|
||||
const ck = userStore.cookie.value;
|
||||
if (ck === undefined) {
|
||||
showSnackbar({
|
||||
@@ -392,6 +288,74 @@ async function confirmRefreshUser(): Promise<void> {
|
||||
await refreshUser();
|
||||
}
|
||||
|
||||
async function confirmCopyCookie(): Promise<void> {
|
||||
const res = await showConfirm({
|
||||
title: "确认复制 Cookie 吗?",
|
||||
text: "将会复制当前登录的 Cookie",
|
||||
});
|
||||
if (!res) {
|
||||
showSnackbar({
|
||||
color: "cancel",
|
||||
text: "已取消复制",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!userStore.cookie) {
|
||||
showSnackbar({
|
||||
color: "error",
|
||||
text: "请先登录",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const ckText = useUserStore().getAllCookie();
|
||||
await navigator.clipboard.writeText(ckText);
|
||||
showSnackbar({
|
||||
text: "已复制 Cookie!",
|
||||
color: "success",
|
||||
});
|
||||
}
|
||||
|
||||
async function tryGetCaptcha(phone: string, aigis?: string): Promise<string | false> {
|
||||
const captchaResp = await Mys.User.getCaptcha(phone, aigis);
|
||||
if ("retcode" in captchaResp) {
|
||||
if (!captchaResp.data || captchaResp.data === "") {
|
||||
showSnackbar({
|
||||
text: `[${captchaResp.retcode}] ${captchaResp.message}`,
|
||||
color: "error",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
const aigisResp: TGApp.Plugins.Mys.CaptchaLogin.CaptchaAigis = JSON.parse(captchaResp.data);
|
||||
const resp = await showGeetest(JSON.parse(aigisResp.data));
|
||||
const aigisStr = `${aigisResp.session_id};${btoa(JSON.stringify(resp))}`;
|
||||
return await tryGetCaptcha(phone, aigisStr);
|
||||
}
|
||||
return captchaResp.action_type;
|
||||
}
|
||||
|
||||
async function tryLoginByCaptcha(
|
||||
phone: string,
|
||||
captcha: string,
|
||||
actionType: string,
|
||||
aigis?: string,
|
||||
): Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | false> {
|
||||
const loginResp = await Mys.User.login(phone, captcha, actionType, aigis);
|
||||
if ("retcode" in loginResp) {
|
||||
if (!loginResp.data || loginResp.data === "") {
|
||||
showSnackbar({
|
||||
text: `[${loginResp.retcode}] ${loginResp.message}`,
|
||||
color: "error",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
const aigisResp: TGApp.Plugins.Mys.CaptchaLogin.CaptchaAigis = JSON.parse(loginResp.data);
|
||||
const resp = await showGeetest(JSON.parse(aigisResp.data));
|
||||
const aigisStr = `${aigisResp.session_id};${btoa(JSON.stringify(resp))}`;
|
||||
return await tryLoginByCaptcha(phone, captcha, actionType, aigisStr);
|
||||
}
|
||||
return loginResp;
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (signListener) signListener();
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
59
src/components/func/geetest.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file component/func/geetest.ts
|
||||
* @description 封装自定义 geetest 组件,通过函数调用的方式,简化 geetest 的使用
|
||||
* @since Beta v0.5.1
|
||||
*/
|
||||
|
||||
import { h, render } from "vue";
|
||||
import type { ComponentInternalInstance, VNode } from "vue";
|
||||
|
||||
import geetest from "./geetest.vue";
|
||||
|
||||
const geetestId = "tg-func-geetest";
|
||||
|
||||
/**
|
||||
* @description 自定义 geetest 组件
|
||||
* @since Beta v0.5.1
|
||||
* @extends ComponentInternalInstance
|
||||
* @property {Function} exposeProxy.displayBox 弹出 geetest 验证
|
||||
* @return GeetestInstance
|
||||
*/
|
||||
interface GeetestInstance extends ComponentInternalInstance {
|
||||
exposeProxy: {
|
||||
displayBox: (
|
||||
props: TGApp.Plugins.Mys.Geetest.reqResp,
|
||||
) => Promise<TGApp.Plugins.Mys.Geetest.validateResp | false>;
|
||||
};
|
||||
}
|
||||
|
||||
const renderBox = (props: TGApp.Plugins.Mys.Geetest.reqResp): VNode => {
|
||||
const container = document.createElement("div");
|
||||
container.id = geetestId;
|
||||
const boxVNode: VNode = h(geetest, props);
|
||||
render(boxVNode, container);
|
||||
document.body.appendChild(container);
|
||||
return boxVNode;
|
||||
};
|
||||
|
||||
let geetestInstance: VNode;
|
||||
|
||||
/**
|
||||
* @function showGeetest
|
||||
* @since Beta v0.5.1
|
||||
* @description 弹出 geetest 验证
|
||||
* @param {TGApp.Plugins.Mys.Geetest.reqResp} props geetest 验证的参数
|
||||
* @return {Promise<TGApp.Plugins.Mys.Geetest.validateResp>} 验证成功返回验证数据
|
||||
*/
|
||||
async function showGeetest(
|
||||
props: TGApp.Plugins.Mys.Geetest.reqResp,
|
||||
): Promise<TGApp.Plugins.Mys.Geetest.validateResp | false> {
|
||||
if (geetestInstance !== undefined) {
|
||||
const boxVue = <GeetestInstance>geetestInstance.component;
|
||||
return boxVue.exposeProxy.displayBox(props);
|
||||
} else {
|
||||
geetestInstance = renderBox(props);
|
||||
return await showGeetest(props);
|
||||
}
|
||||
}
|
||||
|
||||
export default showGeetest;
|
||||
165
src/components/func/geetest.vue
Normal file
@@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<transition name="func-geetest-outer">
|
||||
<div v-show="show || showOuter" class="geetest-overlay" @click.self.prevent>
|
||||
<transition name="func-geetest-inner">
|
||||
<div v-show="showInner" class="geetest-box">
|
||||
<div class="geetest-top">
|
||||
<div class="geetest-title">请完成如下极验测试</div>
|
||||
</div>
|
||||
<div id="verify" class="geetest-mid">
|
||||
<div id="geetest" ref="geetestRef"></div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
|
||||
const show = ref<boolean>(false);
|
||||
const showOuter = ref<boolean>(false);
|
||||
const showInner = ref<boolean>(false);
|
||||
|
||||
const geetestRef = ref<HTMLElement>(<HTMLElement>document.getElementById("geetest"));
|
||||
|
||||
watch(show, () => {
|
||||
if (show.value) {
|
||||
showOuter.value = true;
|
||||
setTimeout(() => {
|
||||
showInner.value = true;
|
||||
}, 100);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
showInner.value = false;
|
||||
}, 100);
|
||||
setTimeout(() => {
|
||||
showOuter.value = false;
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
|
||||
async function displayBox(
|
||||
props: TGApp.Plugins.Mys.Geetest.reqResp,
|
||||
): Promise<TGApp.Plugins.Mys.Geetest.validateResp | false> {
|
||||
return await new Promise<TGApp.Plugins.Mys.Geetest.validateResp>((resolve) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
initGeetest(
|
||||
{
|
||||
gt: props.gt,
|
||||
challenge: props.challenge,
|
||||
offline: false,
|
||||
new_captcha: true,
|
||||
product: "custom",
|
||||
area: "#verify",
|
||||
width: "250px",
|
||||
},
|
||||
(captchaObj: TGApp.Plugins.Mys.Geetest.GeetestCaptcha) => {
|
||||
geetestRef.value.innerHTML = "";
|
||||
captchaObj.appendTo("#geetest");
|
||||
captchaObj.onReady(() => {
|
||||
show.value = true;
|
||||
});
|
||||
captchaObj.onSuccess(async () => {
|
||||
const validate = captchaObj.getValidate();
|
||||
resolve(validate);
|
||||
});
|
||||
captchaObj.onClose(() => {
|
||||
show.value = false;
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
displayBox,
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.func-geetest-outer-enter-active,
|
||||
.func-geetest-outer-leave-active,
|
||||
.func-geetest-inner-enter-active {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.func-geetest-inner-leave-active {
|
||||
transition: all 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.func-geetest-inner-enter-from {
|
||||
opacity: 0;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
|
||||
.func-geetest-inner-enter-to,
|
||||
.func-geetest-inner-leave-from {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.func-geetest-outer-enter-to,
|
||||
.func-geetest-outer-leave-from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.func-geetest-outer-enter-from,
|
||||
.func-geetest-outer-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.func-geetest-inner-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.geetest-overlay {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
backdrop-filter: blur(20px);
|
||||
background: rgb(0 0 0 / 50%);
|
||||
}
|
||||
|
||||
.geetest-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: var(--box-bg-1);
|
||||
color: var(--app-page-content);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.geetest-top {
|
||||
border-bottom: 1px solid var(--common-shadow-4);
|
||||
font-family: var(--font-title);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.geetest-title {
|
||||
color: var(--common-text-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.geetest-mid {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-2);
|
||||
}
|
||||
|
||||
#verify {
|
||||
width: 256px;
|
||||
height: 320px;
|
||||
}
|
||||
</style>
|
||||
@@ -123,17 +123,17 @@ function loadData(): void {
|
||||
star4List.value.push({
|
||||
...item,
|
||||
gachaCount: reset4count.value,
|
||||
icon: getIcon(item.itemId, item.type),
|
||||
icon: getIcon(item.itemId),
|
||||
});
|
||||
reset4count.value = 0;
|
||||
reset4count.value = 1;
|
||||
} else if (item.rank === "5") {
|
||||
reset4count.value++;
|
||||
star5List.value.push({
|
||||
...item,
|
||||
gachaCount: reset5count.value,
|
||||
icon: getIcon(item.itemId, item.type),
|
||||
icon: getIcon(item.itemId),
|
||||
});
|
||||
reset5count.value = 0;
|
||||
reset5count.value = 1;
|
||||
}
|
||||
});
|
||||
star5avg.value = getStar5Avg();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -16,9 +16,19 @@
|
||||
:key="text.week"
|
||||
rounded
|
||||
:style="{
|
||||
border: text.week === weekNow ? '1px solid var(--common-shadow-4)' : 'none',
|
||||
backgroundColor: text.week === btnNow ? 'var(--tgc-yellow-1)' : 'var(--tgc-btn-1)',
|
||||
color: text.week === btnNow ? 'var(--box-text-4)' : 'var(--btn-text)',
|
||||
border: text.week === weekNow ? '1px solid var(--tgc-yellow-1)' : 'none',
|
||||
backgroundColor:
|
||||
text.week === btnNow
|
||||
? 'var(--tgc-yellow-1)'
|
||||
: text.week === weekNow
|
||||
? 'transparent'
|
||||
: 'var(--tgc-btn-1)',
|
||||
color:
|
||||
text.week === btnNow
|
||||
? 'var(--box-text-4)'
|
||||
: text.week === weekNow
|
||||
? 'var(--tgc-yellow-1)'
|
||||
: 'var(--btn-text)',
|
||||
}"
|
||||
@click="getContents(text.week)"
|
||||
>{{ text.text }}
|
||||
@@ -45,7 +55,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 {
|
||||
|
||||