Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c9885441b | ||
|
|
6bbef1332b | ||
|
|
cd5e151926 | ||
|
|
41921a2a6a | ||
|
|
3cead7eda6 | ||
|
|
26f670fae3 | ||
|
|
bc9d848633 | ||
|
|
8f2ea6deea | ||
|
|
92603e8599 | ||
|
|
530f45e75c | ||
|
|
d0936a0a60 | ||
|
|
7d0e0f187c | ||
|
|
cad8de6cd7 | ||
|
|
d29ade356a | ||
|
|
b14ad0e687 | ||
|
|
aeca190f2c | ||
|
|
3ac68c1fd9 | ||
|
|
8a09d8e442 | ||
|
|
0f546e8a57 | ||
|
|
26070919c9 | ||
|
|
bfd73c3d73 | ||
|
|
415927cd0f | ||
|
|
aa6c75e59f | ||
|
|
c31c86bd56 | ||
|
|
1ee3c35216 | ||
|
|
6676357296 | ||
|
|
3ba72969d9 | ||
|
|
c9ea10f0ef | ||
|
|
17f1b39414 | ||
|
|
70216734a3 | ||
|
|
c25bde1b7a | ||
|
|
beb457a884 | ||
|
|
1b1abb9b88 | ||
|
|
112bd3b938 | ||
|
|
55adf31613 | ||
|
|
cdddbae520 | ||
|
|
c4bd07069c | ||
|
|
71b45584e8 | ||
|
|
e343d37a01 | ||
|
|
7f5ffab2a7 | ||
|
|
d2e6d112d5 | ||
|
|
5b390d3ad1 | ||
|
|
798c4bd7d5 | ||
|
|
7e133176e5 | ||
|
|
87a345ffa7 | ||
|
|
2bafb6d491 | ||
|
|
0f278ad25e | ||
|
|
1da157abbd | ||
|
|
2fa9f88da2 | ||
|
|
9e2f91b4d4 | ||
|
|
2b15e1a351 | ||
|
|
25f95d9f90 | ||
|
|
03e33872c2 | ||
|
|
5b5f96c2d3 | ||
|
|
0005e4eb74 | ||
|
|
89d1b2c6a7 | ||
|
|
8eb1d19512 | ||
|
|
8e0bde749f | ||
|
|
93cc9d916e | ||
|
|
18bb76a2a3 | ||
|
|
06a4821888 | ||
|
|
0157ae413b | ||
|
|
cb97cddb89 | ||
|
|
90699a547e | ||
|
|
54fa04ff65 | ||
|
|
dfa9251ae9 | ||
|
|
25fdbd8444 | ||
|
|
ade05d8dab | ||
|
|
4cbd5c516a | ||
|
|
dab6faafde | ||
|
|
87ff3a1148 | ||
|
|
44d181b26a | ||
|
|
7a112f4d17 | ||
|
|
c1cf8b4aa4 | ||
|
|
02bb7b9d6b | ||
|
|
b3a7d92887 | ||
|
|
a46f037075 | ||
|
|
d0669d4a32 | ||
|
|
ae88c4b5ab | ||
|
|
e332dcf384 | ||
|
|
054a0839c6 | ||
|
|
18c96102b3 | ||
|
|
d78b794dc6 | ||
|
|
c9f74537b0 | ||
|
|
da78d27239 | ||
|
|
a3c78ce134 | ||
|
|
59b601a620 | ||
|
|
c8db77f32d | ||
|
|
a542174f54 | ||
|
|
adaa7b1080 | ||
|
|
4713cd4119 | ||
|
|
fbd3d0703d | ||
|
|
0d4ce338f3 | ||
|
|
54b98c7efe | ||
|
|
8e68ca36bb | ||
|
|
8ecaed05ea | ||
|
|
e8a79fb409 | ||
|
|
b6ea50a597 | ||
|
|
547cb2cce7 | ||
|
|
5f6f6e0ea6 | ||
|
|
dd7e8e2261 | ||
|
|
9d995994ca | ||
|
|
a7ca51dcc1 | ||
|
|
0fd9e9a934 | ||
|
|
0464c0fff1 | ||
|
|
0e6a15bd8f | ||
|
|
63b7f685c1 | ||
|
|
aba87dfac0 | ||
|
|
08785514ee | ||
|
|
940ad44052 | ||
|
|
2cdd15b726 | ||
|
|
3c0b02d26b | ||
|
|
72a9408d38 | ||
|
|
b867c008ae | ||
|
|
274eb75754 | ||
|
|
e7bd815b08 | ||
|
|
b7f9d083e7 | ||
|
|
6744c875b6 | ||
|
|
73f7247b59 | ||
|
|
8b5aa106ce | ||
|
|
248130312c | ||
|
|
4f718288c3 | ||
|
|
c7b13983bc | ||
|
|
98dea9d912 | ||
|
|
d5f40a5775 | ||
|
|
f801363440 |
2
.github/workflows/build.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
||||
- name: setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 9.15.0
|
||||
version: 10.2.0
|
||||
- name: Install frontend dependencies
|
||||
run: pnpm install
|
||||
|
||||
|
||||
2
.vscode/extensions.json
vendored
@@ -5,6 +5,6 @@
|
||||
"stylelint.vscode-stylelint",
|
||||
"tauri-apps.tauri-vscode",
|
||||
"Vue.vscode-typescript-vue-plugin",
|
||||
"Vue.volar"
|
||||
"Vue.vue-official"
|
||||
]
|
||||
}
|
||||
|
||||
145
CHANGELOG.md
@@ -2,135 +2,32 @@
|
||||
Author: 目棃
|
||||
Description: CHANGELOG
|
||||
Date: 2024-10-09
|
||||
Update: 2024-12-31
|
||||
Update: 2025-03-06
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2024-10-09 15:51:43`
|
||||
>
|
||||
> 更新于 `2024-12-31 13:41:03`
|
||||
> 更新于 `2025-03-06 10:01:22`
|
||||
|
||||
## [0.6.7](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.7) (2024-12-31)
|
||||
## [0.7.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.7.1) (2025-03-06)
|
||||
|
||||
- 🍱 更新5.3版本游戏资源 [`#139`](https://github.com/BTMuli/TeyvatGuide/issues/139)
|
||||
- ✨ 支持嵌入B站视频的分享图渲染
|
||||
- 🐛 修复版块跳转异常
|
||||
- 🐛 修复清理日志异常
|
||||
- 🐛 修复特定帖子`link_card_ids`数据解析异常
|
||||
- 🐛 修复帖子文本居中异常
|
||||
- 🐛 修复侧边栏跳转角色/武器图鉴异常
|
||||
- ✏️ 调整分享图大小计算方式,采用1024进制而非原有的1000进制
|
||||
- 💄 调整用户等级UI,浅色深色下统一为白色文字
|
||||
- 💄 调整回复弹窗位置,上移一段距离以避免底部提示遮挡
|
||||
- 💄 首页素材日历组件只显示日期,移除具体时间
|
||||
- 💄 调整链接卡片提示文字
|
||||
- 💄 调整剧诗角色列表显示UI
|
||||
- 🚸 版块/咨讯页数据获取/刷新显示成功提示
|
||||
- 🚸 首页近期活动卡片Icon补充缺失的点击逻辑
|
||||
- 🚸 调整合集组件改版后的滚动逻辑,更加流畅
|
||||
- 👽️ 由于API变更,调整版块数据获取逻辑
|
||||
- 👽️ 由于返回数据格式变更,调整视频时长的计算逻辑
|
||||
- 👽️ 由于返回数据格式变更,处理帖子内的转义字符
|
||||
- ♻️ loading组件重构,部分页面显示更精准的进度
|
||||
- ♻️ 应用元数据格式重构,剔除冗余数据
|
||||
- 🐛 修复B站视频时长计算异常
|
||||
- 🐛 处理脚本签到1034 [`#145`](https://github.com/BTMuli/TeyvatGuide/issues/145)
|
||||
- 💄 调整搜索浮窗样式&帖子/公告卡片样式
|
||||
- 🥅 捕获分享图生成异常
|
||||
- 🚸 部分页面添加防抖处理
|
||||
- 🍱 调整缓存图片范围
|
||||
|
||||
## [0.6.6](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.6) (2024-12-13)
|
||||
## [0.7.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.7.0) (2025-02-28)
|
||||
|
||||
- 🐛 修复主题切换响应异常
|
||||
- 🐛 修复增量刷新逻辑异常
|
||||
- ⚡️ 显著降低运行内存占用
|
||||
|
||||
## [0.6.5](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.5) (2024-12-11)
|
||||
|
||||
- 🍱 添加下半卡池数据&部分资源
|
||||
- ✨ 帖子内容中涉及的话题链接支持应用内跳转
|
||||
- ♻️ 首页组件加载逻辑重构
|
||||
- ✨ UIGF4导入/导出浮窗,支持自选UID
|
||||
- 💄 调整剧诗部分数据缺失时的显示
|
||||
- 🐛 调整部分UI,修复切换账户后角色详情刷新异常
|
||||
|
||||
## [0.6.4](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.4) (2024-12-03)
|
||||
|
||||
- 🐛 修复子回复渲染异常
|
||||
- ✏️ 祈愿记录将验证非空ID
|
||||
- 🐛 修复战绩分享图渲染异常
|
||||
- 🐛 修复`dialog`组件`input`默认值无效
|
||||
- 🎨 调整帖子查找overlay逻辑
|
||||
- ✨ 分享图生成阈值自定义
|
||||
- 👽️ 全量刷新时清理旧数据,修复由于米哈游数据异常导致的重复数据
|
||||
|
||||
## [0.6.3](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.3) (2024-11-19)
|
||||
|
||||
- 🐛 修复用户战绩角色数据`undefined`
|
||||
- 🐛 修复咨讯页加载更多异常
|
||||
- 🐛 修复验证码登录提示`-100`,数据刷新后若为已登录UID则不会再提示切换
|
||||
- 🐛 修复部分公告渲染异常
|
||||
- 🐛 修复成就页面在存在搜索内容时点击左侧成就系列无响应
|
||||
- ✨ 帖子新增 UID 卡片解析&渲染
|
||||
- ✨ 帖子新增自定义表情解析&渲染
|
||||
- ✨ 真境剧诗适配,新增真境剧诗页面,支持获取&分享&上传(胡桃数据库),可通过深渊页面进入
|
||||
- ✨ 新增话题页面,可通过帖子卡片标签点击或帖子详情顶部标签点击进入
|
||||
- ✨ 更完善的`loading`显示,调整了组件UI
|
||||
- 🍱 更新5.2版本资源 [`#133`](https://github.com/BTMuli/TeyvatGuide/issues/133)
|
||||
- 💄 调整祈愿记录UP四星颜色
|
||||
- 💄 修复帖子页兑换码弹窗高度异常
|
||||
- 💄 调整帖子卡片UI,增加显示帖子话题(如存在),话题&版块支持点击跳转
|
||||
- 💄 调整帖子详情页UI,顶部话题&版块支持点击跳转
|
||||
- 💄 调整帖子显示数量,支持加载更多,默认排序改为`最新回复`,移除`默认排序`,增加`热门`排序
|
||||
- 💄 咨讯、帖子等页面刷新时自动滚动到顶部
|
||||
- 🔥 深渊数据库显示移除第9层统计数据
|
||||
- 👽️ 米游社子窗口增加`genshinnet`域名支持
|
||||
- 🎨 优化帖子详情数据加载的错误处理
|
||||
- ♻️ `snackbar`、`confirm`、`loading`组件重构
|
||||
- ♻️ 请求模块重构
|
||||
|
||||
## [0.6.2](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.2) (2024-10-31)
|
||||
|
||||
- 🐛 修复用户登录状态异常 [`#132`](https://github.com/BTMuli/TeyvatGudie/issues/132)
|
||||
- 💄 帖子子回复取消保持,点击其他隐藏
|
||||
- 💄 调整未登录时的部分内容渲染
|
||||
- 💄 调整保存时图片的hint
|
||||
- 💄 `mac`:修复回顶组件宽度异常
|
||||
- 💄 `mac`:修复视频封面位置异常
|
||||
- 💄 调整角色卡片UI,维持名片比例
|
||||
- ♻️ 深渊数据库重构,概览显示差距
|
||||
- 🍱 更新下半卡池
|
||||
- 👽️ 修正咨讯Api
|
||||
|
||||
## [0.6.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.1) (2024-10-22)
|
||||
|
||||
- 🐛 新用户数据库初始化异常 [`#131`](https://github.com/BTMuli/TeyavtGuide/issues/131)
|
||||
- 🐛 修复角色数据未即时刷新
|
||||
- 🐛 修复`openSystemBrowser`回调执行异常
|
||||
- ♻️ 公告卡片组件抽离,支持分享
|
||||
- 🎨 成就页面&名片图鉴页面采用虚拟列表优化性能
|
||||
- 🎨 调整卡片封面加载逻辑
|
||||
- 💄 处理特定情况下的内容溢出
|
||||
- 💄 适配深渊新字段,显示跳过楼层
|
||||
- 💄深渊分享显示应用信息,圣遗物详情推荐属性高亮
|
||||
- 💄调整帖子子窗口副标题样式
|
||||
- 💄调整留影叙佳期选项样式
|
||||
|
||||
## [0.6.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.0) (2024-10-09)
|
||||
|
||||
- ✨ 应用支持多账号 [`#126`](https://github.com/BTMuli/TeyvatGuide/issues/126)
|
||||
- ✨ 支持手动输入CK&用户删除
|
||||
- ✨ 帖子卡片支持分享
|
||||
- ✨ 支持官服用户直接启动原神 [`#80`](https://github.com/BTMuli/TeyvatGuide/issues/80)
|
||||
- ♻️ 重构成就表格,支持多存档
|
||||
- ♻️ 重构深渊数据加载逻辑,适配多存档
|
||||
- ♻️ 重构用户登录逻辑及切换
|
||||
- ♻️ 重构祈愿、深渊、角色页面逻辑,支持游戏账号切换
|
||||
- ♻️ 战绩页面适配多账户
|
||||
- 💄 帖子/公告子窗口添加窗口置顶按钮
|
||||
- 💄 调整视频分享截图
|
||||
- 💄 回复分享图忽略导出图标
|
||||
- 💄 显示用户等级
|
||||
- 💄 处理特定情况下的回复内容溢出
|
||||
- 💄 兑换码支持分享,调整了兑换码浮窗UI
|
||||
- 💄 公告对列表进行缩进
|
||||
- 💄 材料Wiki样式优化,支持分类筛选&查询
|
||||
- 💄 材料详情浮窗支持分享
|
||||
- ✏️ JSBridge新增`openSystemBrowser`回调处理
|
||||
- ✏️ 修正公告正则
|
||||
- 👽️ 更新国际服公告Api
|
||||
- 📖 添加 macOS 平台门禁属性导致无法打开应用的修复指引 [`#130`](https://github.com/BTMuli/TeyvatGuide/issues/130)
|
||||
- ✨ 新增无痕浏览配置,默认开启
|
||||
- ✨ 登录状态且关闭无痕浏览时,可对帖子进行点赞操作
|
||||
- ✨ 新增实用脚本页面,支持一键完成米游币每日任务 [`#144`](https://github.com/BTMuli/TeyvatGuide/issues/144)
|
||||
- 🐛 修复公告解析异常
|
||||
- 🐛 修复角色卡片视图(详细)浮窗切换时背景图更新异常
|
||||
- 🐛 修复路由跳转不生效
|
||||
- ♻️ 重构首页素材日历组件生日计算,修复生日计算异常
|
||||
- 🚸 设置页登录二维码支持生成分享图,点击底部图标触发
|
||||
- 💄 调整首页素材日历组件可视页码
|
||||
- 💄 调整部分页面UI
|
||||
- 🍱 更新下半卡池数据
|
||||
|
||||
13
README.md
@@ -2,12 +2,12 @@
|
||||
Author: 目棃
|
||||
Description: 说明文档
|
||||
Date: 2023-03-05
|
||||
Update: 2024-12-03
|
||||
Update: 2025-02-28
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-03-05 14:41:55`
|
||||
>
|
||||
> 更新于 `2024-12-03 16:14:14`
|
||||
> 更新于 `2025-02-28 10:54:28`
|
||||
|
||||
 
|
||||
|
||||
@@ -58,12 +58,15 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
|
||||
|
||||
- 登陆功能:
|
||||
|
||||
> 支持 扫码/验证码/Cookie 登陆,支持多账号管理
|
||||
|
||||
- [x] 原神战绩数据获取
|
||||
- [x] 角色详情数据获取
|
||||
- [x] 螺旋深渊数据获取
|
||||
- [x] 真境剧诗数据获取
|
||||
- [x] 祈愿数据获取(近一年)
|
||||
- [x] 用户收藏帖子获取
|
||||
- [x] 一键完成米游币每日任务 **需要验证码登录**
|
||||
|
||||
- Wiki 功能:
|
||||
|
||||
@@ -95,8 +98,8 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
|
||||
|
||||
- Changelog: [CHANGELOG](CHANGELOG.md)
|
||||
- 资源来源:[项目资源说明](docs/项目资源说明.md)
|
||||
- UIAF:[UIAF v1.1](docs/UIAF.md)
|
||||
- UIGF:[UIGF v3.0](docs/UIGF3.md),[UIGF v4.0](docs/UIGF.md)
|
||||
- UIAF:[UIAF v1.1](docs/standards/UIAF.md)
|
||||
- UIGF:[UIGF v3.0](docs/standards/UIGF3.md),[UIGF v4.0](docs/standards/UIGF.md)
|
||||
- [macOS 平台门禁属性导致应用无法打开应用的修复指引](docs/macos-gatekeeper/README.md)
|
||||
|
||||
## 特定项目 / Special Project
|
||||
@@ -139,6 +142,8 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
|
||||
- [paimon-moe](https://github.com/MadeBaruna/paimon-moe)
|
||||
- [Adachi-BOT](https://github.com/Arondight/Adachi-BOT)
|
||||
- [amos-data](https://github.com/yuehaiteam/amos-data)
|
||||
- [MihoyoBBSTools](https://github.com/Womsxd/MihoyoBBSTools)
|
||||
- [nonebot-plugin-mystool](https://github.com/Ljzd-PRO/nonebot-plugin-mystool)
|
||||
|
||||
感谢 JetBrains 提供的开源许可证。
|
||||
|
||||
|
||||
168
docs/changelogs/CHANGELOG-v0.6.x.md
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
Author: 目棃
|
||||
Description: CHANGELOG
|
||||
Date: 2024-10-09
|
||||
Update: 2025-02-11
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2024-10-09 15:51:43`
|
||||
>
|
||||
> 更新于 `2025-02-11 10:57:49`
|
||||
|
||||
## [0.6.9](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.9) (2025-02-11)
|
||||
|
||||
- 🍱 更新5.4资源 [`#141`](https://github.com/BTMuli/TeyvatGuide/issues/141)
|
||||
- 🐛 修复米游社子窗口路径解析异常
|
||||
- 🐛 修复特定条件下真境剧诗角色元素图标渲染异常
|
||||
- 🐛 修复名片图鉴浮窗渲染异常
|
||||
- 🚸 调整兑换码入口显示判断逻辑
|
||||
- 🚸 成就导入不允许点击外部取消,调整刷新逻辑
|
||||
- 🚸 下载封面图时显示封面链接
|
||||
- 💄 调整部分UI
|
||||
|
||||
## [0.6.8](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.8) (2025-01-22)
|
||||
|
||||
- ✨ 扫码登录
|
||||
- ✨ 调整祈愿记录图表样式,新增祈愿日历&祈愿堆叠柱状图
|
||||
- ✨ 支持配置帖子详情图像质量,默认80%
|
||||
- ✨ 支持帖子详情图像查看原图,当质量配置为100%时,该按钮不显示
|
||||
- ✨ 深渊上传支持胡桃账户设置
|
||||
- 🚸 降低祈愿全量刷新耗时
|
||||
- 🚸 加快帖子加载速度,降低内存占用
|
||||
- 💄 调整角色卡片样式
|
||||
- 💄 调整角色名片样式,增加描述清晰度
|
||||
- 💄 调整深渊Wiki队伍搭配窗口高度
|
||||
- 💄 mac下不显示分享设置
|
||||
- 💄 调整战绩页新洞天渲染样式
|
||||
- 🔥 深渊Wiki移除第10层数据
|
||||
- 🐛 修复深渊数据恢复异常
|
||||
- 🐛 修复 loading 组件 empty 状态设置异常
|
||||
- ♻️ 优化帖子加载逻辑,当刷新内容不足20条时,下次刷新数量为20-当前数量,如刷新数量为19条,则下次刷新数量为1条
|
||||
- ♻️ 动态获取分区列表&版块列表
|
||||
- ♻️ 重构部分路由处理,当话题/帖子切换分区/版块时,页面刷新不重置当前分区/版块
|
||||
|
||||
## [0.6.7](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.7) (2024-12-31)
|
||||
|
||||
- 🍱 更新5.3版本游戏资源 [`#139`](https://github.com/BTMuli/TeyvatGuide/issues/139)
|
||||
- ✨ 支持嵌入B站视频的分享图渲染
|
||||
- 🐛 修复版块跳转异常
|
||||
- 🐛 修复清理日志异常
|
||||
- 🐛 修复特定帖子`link_card_ids`数据解析异常
|
||||
- 🐛 修复帖子文本居中异常
|
||||
- 🐛 修复侧边栏跳转角色/武器图鉴异常
|
||||
- ✏️ 调整分享图大小计算方式,采用1024进制而非原有的1000进制
|
||||
- 💄 调整用户等级UI,浅色深色下统一为白色文字
|
||||
- 💄 调整回复弹窗位置,上移一段距离以避免底部提示遮挡
|
||||
- 💄 首页素材日历组件只显示日期,移除具体时间
|
||||
- 💄 调整链接卡片提示文字
|
||||
- 💄 调整剧诗角色列表显示UI
|
||||
- 🚸 版块/咨讯页数据获取/刷新显示成功提示
|
||||
- 🚸 首页近期活动卡片Icon补充缺失的点击逻辑
|
||||
- 🚸 调整合集组件改版后的滚动逻辑,更加流畅
|
||||
- 👽️ 由于API变更,调整版块数据获取逻辑
|
||||
- 👽️ 由于返回数据格式变更,调整视频时长的计算逻辑
|
||||
- 👽️ 由于返回数据格式变更,处理帖子内的转义字符
|
||||
- ♻️ loading组件重构,部分页面显示更精准的进度
|
||||
- ♻️ 应用元数据格式重构,剔除冗余数据
|
||||
|
||||
## [0.6.6](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.6) (2024-12-13)
|
||||
|
||||
- 🐛 修复主题切换响应异常
|
||||
- 🐛 修复增量刷新逻辑异常
|
||||
- ⚡️ 显著降低运行内存占用
|
||||
|
||||
## [0.6.5](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.5) (2024-12-11)
|
||||
|
||||
- 🍱 添加下半卡池数据&部分资源
|
||||
- ✨ 帖子内容中涉及的话题链接支持应用内跳转
|
||||
- ♻️ 首页组件加载逻辑重构
|
||||
- ✨ UIGF4导入/导出浮窗,支持自选UID
|
||||
- 💄 调整剧诗部分数据缺失时的显示
|
||||
- 🐛 调整部分UI,修复切换账户后角色详情刷新异常
|
||||
|
||||
## [0.6.4](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.4) (2024-12-03)
|
||||
|
||||
- 🐛 修复子回复渲染异常
|
||||
- ✏️ 祈愿记录将验证非空ID
|
||||
- 🐛 修复战绩分享图渲染异常
|
||||
- 🐛 修复`dialog`组件`input`默认值无效
|
||||
- 🎨 调整帖子查找overlay逻辑
|
||||
- ✨ 分享图生成阈值自定义
|
||||
- 👽️ 全量刷新时清理旧数据,修复由于米哈游数据异常导致的重复数据
|
||||
|
||||
## [0.6.3](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.3) (2024-11-19)
|
||||
|
||||
- 🐛 修复用户战绩角色数据`undefined`
|
||||
- 🐛 修复咨讯页加载更多异常
|
||||
- 🐛 修复验证码登录提示`-100`,数据刷新后若为已登录UID则不会再提示切换
|
||||
- 🐛 修复部分公告渲染异常
|
||||
- 🐛 修复成就页面在存在搜索内容时点击左侧成就系列无响应
|
||||
- ✨ 帖子新增 UID 卡片解析&渲染
|
||||
- ✨ 帖子新增自定义表情解析&渲染
|
||||
- ✨ 真境剧诗适配,新增真境剧诗页面,支持获取&分享&上传(胡桃数据库),可通过深渊页面进入
|
||||
- ✨ 新增话题页面,可通过帖子卡片标签点击或帖子详情顶部标签点击进入
|
||||
- ✨ 更完善的`loading`显示,调整了组件UI
|
||||
- 🍱 更新5.2版本资源 [`#133`](https://github.com/BTMuli/TeyvatGuide/issues/133)
|
||||
- 💄 调整祈愿记录UP四星颜色
|
||||
- 💄 修复帖子页兑换码弹窗高度异常
|
||||
- 💄 调整帖子卡片UI,增加显示帖子话题(如存在),话题&版块支持点击跳转
|
||||
- 💄 调整帖子详情页UI,顶部话题&版块支持点击跳转
|
||||
- 💄 调整帖子显示数量,支持加载更多,默认排序改为`最新回复`,移除`默认排序`,增加`热门`排序
|
||||
- 💄 咨讯、帖子等页面刷新时自动滚动到顶部
|
||||
- 🔥 深渊数据库显示移除第9层统计数据
|
||||
- 👽️ 米游社子窗口增加`genshinnet`域名支持
|
||||
- 🎨 优化帖子详情数据加载的错误处理
|
||||
- ♻️ `snackbar`、`confirm`、`loading`组件重构
|
||||
- ♻️ 请求模块重构
|
||||
|
||||
## [0.6.2](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.2) (2024-10-31)
|
||||
|
||||
- 🐛 修复用户登录状态异常 [`#132`](https://github.com/BTMuli/TeyvatGudie/issues/132)
|
||||
- 💄 帖子子回复取消保持,点击其他隐藏
|
||||
- 💄 调整未登录时的部分内容渲染
|
||||
- 💄 调整保存时图片的hint
|
||||
- 💄 `mac`:修复回顶组件宽度异常
|
||||
- 💄 `mac`:修复视频封面位置异常
|
||||
- 💄 调整角色卡片UI,维持名片比例
|
||||
- ♻️ 深渊数据库重构,概览显示差距
|
||||
- 🍱 更新下半卡池
|
||||
- 👽️ 修正咨讯Api
|
||||
|
||||
## [0.6.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.1) (2024-10-22)
|
||||
|
||||
- 🐛 新用户数据库初始化异常 [`#131`](https://github.com/BTMuli/TeyavtGuide/issues/131)
|
||||
- 🐛 修复角色数据未即时刷新
|
||||
- 🐛 修复`openSystemBrowser`回调执行异常
|
||||
- ♻️ 公告卡片组件抽离,支持分享
|
||||
- 🎨 成就页面&名片图鉴页面采用虚拟列表优化性能
|
||||
- 🎨 调整卡片封面加载逻辑
|
||||
- 💄 处理特定情况下的内容溢出
|
||||
- 💄 适配深渊新字段,显示跳过楼层
|
||||
- 💄深渊分享显示应用信息,圣遗物详情推荐属性高亮
|
||||
- 💄调整帖子子窗口副标题样式
|
||||
- 💄调整留影叙佳期选项样式
|
||||
|
||||
## [0.6.0](https://github.com/BTMuli/TeyvatGuide/releases/v0.6.0) (2024-10-09)
|
||||
|
||||
- ✨ 应用支持多账号 [`#126`](https://github.com/BTMuli/TeyvatGuide/issues/126)
|
||||
- ✨ 支持手动输入CK&用户删除
|
||||
- ✨ 帖子卡片支持分享
|
||||
- ✨ 支持官服用户直接启动原神 [`#80`](https://github.com/BTMuli/TeyvatGuide/issues/80)
|
||||
- ♻️ 重构成就表格,支持多存档
|
||||
- ♻️ 重构深渊数据加载逻辑,适配多存档
|
||||
- ♻️ 重构用户登录逻辑及切换
|
||||
- ♻️ 重构祈愿、深渊、角色页面逻辑,支持游戏账号切换
|
||||
- ♻️ 战绩页面适配多账户
|
||||
- 💄 帖子/公告子窗口添加窗口置顶按钮
|
||||
- 💄 调整视频分享截图
|
||||
- 💄 回复分享图忽略导出图标
|
||||
- 💄 显示用户等级
|
||||
- 💄 处理特定情况下的回复内容溢出
|
||||
- 💄 兑换码支持分享,调整了兑换码浮窗UI
|
||||
- 💄 公告对列表进行缩进
|
||||
- 💄 材料Wiki样式优化,支持分类筛选&查询
|
||||
- 💄 材料详情浮窗支持分享
|
||||
- ✏️ JSBridge新增`openSystemBrowser`回调处理
|
||||
- ✏️ 修正公告正则
|
||||
- 👽️ 更新国际服公告Api
|
||||
- 📖 添加 macOS 平台门禁属性导致无法打开应用的修复指引 [`#130`](https://github.com/BTMuli/TeyvatGuide/issues/130)
|
||||
@@ -2,12 +2,12 @@
|
||||
Author: 目棃
|
||||
Description: 项目资源说明
|
||||
Date: 2023-03-10
|
||||
Update: 2024-09-19
|
||||
Update: 2025-02-28
|
||||
---
|
||||
|
||||
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-03-10 22:05:44`
|
||||
>
|
||||
> 更新于 `2024-09-19 15:28:16`
|
||||
> 更新于 `2025-02-28 09:40:33`
|
||||
|
||||
## 说明
|
||||
|
||||
@@ -28,6 +28,7 @@ Update: 2024-09-19
|
||||
- 我的角色:Hoyolab
|
||||
- 深渊记录:Hoyolab
|
||||
- 祈愿记录:Hoyolab
|
||||
- 实用脚本:Hoyolab
|
||||
- 图鉴:Hoyolab,其子目录图标同样来源于 Hoyolab
|
||||
- 模式切换:`mdi-weather-night` `mdi-weather-sunny`
|
||||
- 设置:个人绘制 SVG
|
||||
|
||||
85
package.json
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "teyvatguide",
|
||||
"version": "0.6.7",
|
||||
"version": "0.7.1",
|
||||
"description": "Game Tool for GenshinImpact player",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.15.0",
|
||||
"packageManager": "pnpm@10.5.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tauri build",
|
||||
@@ -12,12 +12,14 @@
|
||||
"eslint:pre": "pnpx @eslint/config-inspector@latest",
|
||||
"lint": "concurrently \"pnpm:lint:*(!fix)\"",
|
||||
"lint:fix": "concurrently \"pnpm:lint:*:fix\"",
|
||||
"lint:vue": "vue-tsc --noEmit",
|
||||
"lint:code": "eslint .",
|
||||
"lint:code:fix": "eslint . --fix",
|
||||
"lint:style": "stylelint \"src/**/*.{vue,css,scss}\" -f verbose",
|
||||
"lint:style:fix": "pnpm lint:style --fix",
|
||||
"lint:rust:fix": "cd src-tauri && cargo fmt",
|
||||
"prettier": "prettier . --write",
|
||||
"upv": "tsx scripts/update-version.ts",
|
||||
"tauri": "tauri",
|
||||
"vite:dev": "vite dev",
|
||||
"vite:build": "vite build",
|
||||
@@ -67,74 +69,79 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdi/font": "7.4.47",
|
||||
"@tauri-apps/api": "^2.1.1",
|
||||
"@tauri-apps/api": "^2.3.0",
|
||||
"@tauri-apps/plugin-deep-link": "^2.2.0",
|
||||
"@tauri-apps/plugin-dialog": "^2.2.0",
|
||||
"@tauri-apps/plugin-fs": "^2.2.0",
|
||||
"@tauri-apps/plugin-http": "^2.2.0",
|
||||
"@tauri-apps/plugin-log": "^2.2.0",
|
||||
"@tauri-apps/plugin-http": "^2.3.0",
|
||||
"@tauri-apps/plugin-log": "^2.2.3",
|
||||
"@tauri-apps/plugin-os": "^2.2.0",
|
||||
"@tauri-apps/plugin-process": "^2.2.0",
|
||||
"@tauri-apps/plugin-shell": "^2.2.0",
|
||||
"@tauri-apps/plugin-sql": "^2.2.0",
|
||||
"ajv": "^8.17.1",
|
||||
"artplayer": "^5.2.1",
|
||||
"artplayer": "^5.2.2",
|
||||
"clipboard": "^2.0.11",
|
||||
"color-convert": "^2.0.1",
|
||||
"echarts": "^5.5.1",
|
||||
"color-convert": "^3.0.1",
|
||||
"echarts": "^5.6.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"js-md5": "^0.8.3",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"pinia": "^2.3.0",
|
||||
"pinia-plugin-persistedstate": "^4.1.3",
|
||||
"sass": "^1.83.0",
|
||||
"sass-loader": "^16.0.4",
|
||||
"uuid": "^11.0.3",
|
||||
"pinia": "^3.0.1",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"qrcode.vue": "^3.6.0",
|
||||
"sass": "^1.85.1",
|
||||
"sass-loader": "^16.0.5",
|
||||
"uuid": "^11.1.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-echarts": "^7.0.3",
|
||||
"vue-json-viewer": "^3.0.4",
|
||||
"vue-json-pretty": "^2.4.0",
|
||||
"vue-router": "^4.5.0",
|
||||
"vuetify": "^3.7.5",
|
||||
"vuetify": "^3.7.14",
|
||||
"wcag-color": "^1.1.1",
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.17.0",
|
||||
"@tauri-apps/cli": "2.1.0",
|
||||
"@eslint/eslintrc": "^3.3.0",
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@tauri-apps/cli": "2.3.1",
|
||||
"@types/color-convert": "^2.0.4",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/js-md5": "^0.7.2",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/node": "^22.13.7",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/parser": "^8.18.0",
|
||||
"@typescript-eslint/parser": "^8.25.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"concurrently": "^9.1.0",
|
||||
"eslint": "^9.17.0",
|
||||
"concurrently": "^9.1.2",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-jsonc": "^2.18.2",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-jsonc": "^2.19.1",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"eslint-plugin-vue": "^9.32.0",
|
||||
"eslint-plugin-yml": "^1.16.0",
|
||||
"globals": "^15.13.0",
|
||||
"eslint-plugin-yml": "^1.17.0",
|
||||
"fs-extra": "^11.3.0",
|
||||
"globals": "^16.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"jsonc-eslint-parser": "^2.4.0",
|
||||
"lint-staged": "^15.2.11",
|
||||
"oxlint": "^0.15.2",
|
||||
"prettier": "3.4.2",
|
||||
"stylelint": "^16.11.0",
|
||||
"lint-staged": "^15.4.3",
|
||||
"oxlint": "^0.15.12",
|
||||
"prettier": "3.5.2",
|
||||
"stylelint": "^16.15.0",
|
||||
"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-high-performance-animation": "^1.11.0",
|
||||
"stylelint-order": "^6.0.4",
|
||||
"stylelint-prettier": "^5.0.2",
|
||||
"stylelint-scss": "^6.10.0",
|
||||
"typescript": "^5.7.2",
|
||||
"typescript-eslint": "^8.18.0",
|
||||
"vite": "^6.0.3",
|
||||
"vite-plugin-vue-devtools": "^7.6.8",
|
||||
"vite-plugin-vuetify": "^2.0.4",
|
||||
"stylelint-prettier": "^5.0.3",
|
||||
"stylelint-scss": "^6.11.1",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.8.2",
|
||||
"typescript-eslint": "^8.25.0",
|
||||
"vite": "^6.2.0",
|
||||
"vite-plugin-vue-devtools": "^7.7.2",
|
||||
"vite-plugin-vuetify": "^2.1.0",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"yaml-eslint-parser": "^1.2.3"
|
||||
"vue-tsc": "^2.2.4",
|
||||
"yaml-eslint-parser": "^1.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
3889
pnpm-lock.yaml
generated
BIN
public/WIKI/character/10000109.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/WIKI/nameCard/bg/庆典·炙热.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/WIKI/nameCard/bg/梦见月瑞希·噩喰.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/WIKI/nameCard/bg/纪行·绮梦.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/WIKI/nameCard/icon/庆典·炙热.webp
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
public/WIKI/nameCard/icon/梦见月瑞希·噩喰.webp
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
public/WIKI/nameCard/icon/纪行·绮梦.webp
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
public/WIKI/nameCard/profile/庆典·炙热.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/WIKI/nameCard/profile/梦见月瑞希·噩喰.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/WIKI/nameCard/profile/纪行·绮梦.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/WIKI/weapon/13432.webp
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
public/WIKI/weapon/14518.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/icon.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
public/icon/constellations/UI_Talent_S_Mizuki_01.webp
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/icon/constellations/UI_Talent_S_Mizuki_02.webp
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
public/icon/constellations/UI_Talent_S_Mizuki_03.webp
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
public/icon/constellations/UI_Talent_S_Mizuki_04.webp
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
public/icon/constellations/UI_Talent_U_Mizuki_01.webp
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/icon/constellations/UI_Talent_U_Mizuki_02.webp
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/icon/talents/Skill_E_Mizuki_01.webp
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/icon/talents/Skill_S_Mizuki_01.webp
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/icon/talents/UI_Talent_S_Mizuki_05.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/icon/talents/UI_Talent_S_Mizuki_06.webp
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
public/icon/talents/UI_Talent_S_Mizuki_07.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/platforms/mhy/launcher.webp
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 30 KiB |
BIN
public/source/UI/act_birthday.webp
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
BIN
public/source/UI/posts.webp
Normal file
|
After Width: | Height: | Size: 776 B |
BIN
public/source/UI/toolbox.webp
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
BIN
public/source/UI/video_play_bili.webp
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
32
scripts/update-version.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file scripts/update-version.ts
|
||||
* @description 抬升版本号
|
||||
* @since Beta v0.6.8
|
||||
*/
|
||||
import fs from "fs-extra";
|
||||
import { resolve } from "path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { execSync } from "node:child_process";
|
||||
|
||||
// 获取参数
|
||||
const args = process.argv;
|
||||
const version = args[2];
|
||||
if (!version) {
|
||||
console.error("请输入版本号");
|
||||
process.exit(1);
|
||||
}
|
||||
const __dirname = resolve(fileURLToPath(import.meta.url), "../");
|
||||
// 更新package.json
|
||||
const pkgJson = fs.readJsonSync(resolve(__dirname, "../package.json"));
|
||||
pkgJson.version = version;
|
||||
fs.writeJsonSync(resolve(__dirname, "../package.json"), pkgJson);
|
||||
// 更新src-tauri
|
||||
const tauriDir = resolve(__dirname, "../src-tauri");
|
||||
const tauriToml = fs.readFileSync(resolve(tauriDir, "Cargo.toml"), "utf-8").split("\n");
|
||||
tauriToml[2] = `version = "${version}"`;
|
||||
fs.writeFileSync(resolve(tauriDir, "Cargo.toml"), tauriToml.join("\n"));
|
||||
const tauriJson = fs.readJsonSync(resolve(tauriDir, "tauri.conf.json"));
|
||||
tauriJson.version = version;
|
||||
fs.writeJsonSync(resolve(tauriDir, "tauri.conf.json"), tauriJson);
|
||||
|
||||
execSync("pnpm prettier", { cwd: resolve(__dirname, "..") });
|
||||
1668
src-tauri/Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "TeyvatGuide"
|
||||
version = "0.6.7"
|
||||
version = "0.7.1"
|
||||
description = "Game Tool for Genshin Impact player"
|
||||
authors = ["BTMuli <bt-muli@outlook.com>"]
|
||||
license = "MIT"
|
||||
@@ -10,15 +10,15 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.3", features = [] }
|
||||
tauri-build = { version = "2.0.6", features = [] }
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.39"
|
||||
log = "0.4.22"
|
||||
serde = { version = "1.0.216", features = ["derive"] }
|
||||
serde_json = "1.0.133"
|
||||
tauri = { version = "2.1.1", features = [] }
|
||||
tauri-utils = "2.1.0"
|
||||
chrono = "0.4.40"
|
||||
log = "0.4.26"
|
||||
serde = { version = "1.0.218", features = ["derive"] }
|
||||
serde_json = "1.0.139"
|
||||
tauri = { version = "2.3.1", features = [] }
|
||||
tauri-utils = "2.2.0"
|
||||
url = "2.5.4"
|
||||
walkdir = "2.5.0"
|
||||
|
||||
|
||||
@@ -29,15 +29,9 @@
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://*.miyoushe.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.mihoyo.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.hoyoverse.com/*"
|
||||
}
|
||||
{ "url": "https://*.miyoushe.com/*" },
|
||||
{ "url": "https://*.mihoyo.com/*" },
|
||||
{ "url": "https://*.hoyoverse.com/*" }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -14,74 +14,19 @@
|
||||
"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": "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://*.genshinnet.com/*"
|
||||
}
|
||||
{ "url": "https://*.miyoushe.com/*" },
|
||||
{ "url": "https://*.mihoyo.com/*" },
|
||||
{ "url": "https://*.genshinnet.com/*" }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -33,86 +33,23 @@
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-set-always-on-top",
|
||||
"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": "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://*.mihoyogift.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.bilibili.com/*"
|
||||
},
|
||||
{
|
||||
"url": "http://*.hdslb.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.hoyoverse.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.genshinnet.com/*"
|
||||
}
|
||||
{ "url": "https://*.miyoushe.com/*" },
|
||||
{ "url": "https://*.mihoyo.com/*" },
|
||||
{ "url": "https://*.mihoyogift.com/*" },
|
||||
{ "url": "https://*.bilibili.com/*" },
|
||||
{ "url": "http://*.hdslb.com/*" },
|
||||
{ "url": "https://*.hoyoverse.com/*" },
|
||||
{ "url": "https://*.genshinnet.com/*" }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -37,97 +37,28 @@
|
||||
"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": "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/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.hoyoverse.com/*"
|
||||
}
|
||||
{ "url": "https://*.miyoushe.com/*" },
|
||||
{ "url": "https://*.mihoyo.com/*" },
|
||||
{ "url": "https://homa.snapgenshin.com/*" },
|
||||
{ "url": "https://*.hoyoverse.com/*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "shell:allow-execute",
|
||||
"allow": [
|
||||
{
|
||||
"name": "win_open",
|
||||
"cmd": "explorer",
|
||||
"args": true
|
||||
},
|
||||
{
|
||||
"name": "mac_open",
|
||||
"cmd": "open",
|
||||
"args": true
|
||||
},
|
||||
{
|
||||
"name": "exec-sh",
|
||||
"cmd": "powershell",
|
||||
"args": true
|
||||
}
|
||||
{ "name": "win_open", "cmd": "explorer", "args": true },
|
||||
{ "name": "mac_open", "cmd": "open", "args": true },
|
||||
{ "name": "exec-sh", "cmd": "powershell", "args": true }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -773,6 +773,11 @@
|
||||
"description": "Enables the reparent command without any pre-configured scope.",
|
||||
"commands": { "allow": ["reparent"], "deny": [] }
|
||||
},
|
||||
"allow-set-webview-background-color": {
|
||||
"identifier": "allow-set-webview-background-color",
|
||||
"description": "Enables the set_webview_background_color command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_webview_background_color"], "deny": [] }
|
||||
},
|
||||
"allow-set-webview-focus": {
|
||||
"identifier": "allow-set-webview-focus",
|
||||
"description": "Enables the set_webview_focus command without any pre-configured scope.",
|
||||
@@ -853,6 +858,11 @@
|
||||
"description": "Denies the reparent command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["reparent"] }
|
||||
},
|
||||
"deny-set-webview-background-color": {
|
||||
"identifier": "deny-set-webview-background-color",
|
||||
"description": "Denies the set_webview_background_color command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_webview_background_color"] }
|
||||
},
|
||||
"deny-set-webview-focus": {
|
||||
"identifier": "deny-set-webview-focus",
|
||||
"description": "Denies the set_webview_focus command without any pre-configured scope.",
|
||||
@@ -1100,6 +1110,21 @@
|
||||
"description": "Enables the set_always_on_top command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_always_on_top"], "deny": [] }
|
||||
},
|
||||
"allow-set-background-color": {
|
||||
"identifier": "allow-set-background-color",
|
||||
"description": "Enables the set_background_color command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_background_color"], "deny": [] }
|
||||
},
|
||||
"allow-set-badge-count": {
|
||||
"identifier": "allow-set-badge-count",
|
||||
"description": "Enables the set_badge_count command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_badge_count"], "deny": [] }
|
||||
},
|
||||
"allow-set-badge-label": {
|
||||
"identifier": "allow-set-badge-label",
|
||||
"description": "Enables the set_badge_label command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_badge_label"], "deny": [] }
|
||||
},
|
||||
"allow-set-closable": {
|
||||
"identifier": "allow-set-closable",
|
||||
"description": "Enables the set_closable command without any pre-configured scope.",
|
||||
@@ -1185,6 +1210,11 @@
|
||||
"description": "Enables the set_minimizable command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_minimizable"], "deny": [] }
|
||||
},
|
||||
"allow-set-overlay-icon": {
|
||||
"identifier": "allow-set-overlay-icon",
|
||||
"description": "Enables the set_overlay_icon command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_overlay_icon"], "deny": [] }
|
||||
},
|
||||
"allow-set-position": {
|
||||
"identifier": "allow-set-position",
|
||||
"description": "Enables the set_position command without any pre-configured scope.",
|
||||
@@ -1445,6 +1475,21 @@
|
||||
"description": "Denies the set_always_on_top command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_always_on_top"] }
|
||||
},
|
||||
"deny-set-background-color": {
|
||||
"identifier": "deny-set-background-color",
|
||||
"description": "Denies the set_background_color command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_background_color"] }
|
||||
},
|
||||
"deny-set-badge-count": {
|
||||
"identifier": "deny-set-badge-count",
|
||||
"description": "Denies the set_badge_count command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_badge_count"] }
|
||||
},
|
||||
"deny-set-badge-label": {
|
||||
"identifier": "deny-set-badge-label",
|
||||
"description": "Denies the set_badge_label command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_badge_label"] }
|
||||
},
|
||||
"deny-set-closable": {
|
||||
"identifier": "deny-set-closable",
|
||||
"description": "Denies the set_closable command without any pre-configured scope.",
|
||||
@@ -1530,6 +1575,11 @@
|
||||
"description": "Denies the set_minimizable command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_minimizable"] }
|
||||
},
|
||||
"deny-set-overlay-icon": {
|
||||
"identifier": "deny-set-overlay-icon",
|
||||
"description": "Denies the set_overlay_icon command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_overlay_icon"] }
|
||||
},
|
||||
"deny-set-position": {
|
||||
"identifier": "deny-set-position",
|
||||
"description": "Denies the set_position command without any pre-configured scope.",
|
||||
@@ -3594,7 +3644,7 @@
|
||||
"process": {
|
||||
"default_permission": {
|
||||
"identifier": "default",
|
||||
"description": "This permission set configures which\nprocess feeatures are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"permissions": ["allow-exit", "allow-restart"]
|
||||
},
|
||||
"permissions": {
|
||||
|
||||
@@ -2626,6 +2626,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2706,6 +2711,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2921,6 +2931,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3006,6 +3031,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3266,6 +3296,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3351,6 +3396,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -5132,7 +5182,7 @@
|
||||
"const": "os:deny-version"
|
||||
},
|
||||
{
|
||||
"description": "This permission set configures which\nprocess feeatures are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"type": "string",
|
||||
"const": "process:default"
|
||||
},
|
||||
|
||||
@@ -2626,6 +2626,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2706,6 +2711,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2921,6 +2931,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3006,6 +3031,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3266,6 +3296,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3351,6 +3396,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -5132,7 +5182,7 @@
|
||||
"const": "os:deny-version"
|
||||
},
|
||||
{
|
||||
"description": "This permission set configures which\nprocess feeatures are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"type": "string",
|
||||
"const": "process:default"
|
||||
},
|
||||
|
||||
BIN
src-tauri/icons/icon.icns
Normal file
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 65 KiB |
@@ -1,6 +1,6 @@
|
||||
//! @file src/client/mod.rs
|
||||
//! @desc 客户端模块,负责操作米游社客户端
|
||||
//! @since Beta v0.6.7
|
||||
//! @since Beta v0.7.0
|
||||
|
||||
mod menu;
|
||||
mod utils;
|
||||
@@ -8,7 +8,7 @@ mod utils;
|
||||
use tauri::{AppHandle, Manager, WebviewWindowBuilder};
|
||||
use tauri_utils::config::WebviewUrl;
|
||||
|
||||
static BBS_VERSION: &'static str = "2.79.1";
|
||||
static BBS_VERSION: &'static str = "2.82.0";
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn create_mhy_client(handle: AppHandle, func: String, url: String) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"productName": "TeyvatGuide",
|
||||
"identifier": "TeyvatGuide",
|
||||
"version": "0.6.7",
|
||||
"version": "0.7.1",
|
||||
"build": {
|
||||
"beforeDevCommand": "pnpm vite:dev",
|
||||
"beforeBuildCommand": "pnpm vite:build",
|
||||
@@ -11,28 +11,24 @@
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/32x32.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico",
|
||||
"icons/icon.png",
|
||||
"icons/Square30x30Logo.png",
|
||||
"icons/Square44x44Logo.png",
|
||||
"icons/Square71x71Logo.png",
|
||||
"icons/Square89x89Logo.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"
|
||||
"icons/Square310x310Logo.png"
|
||||
],
|
||||
"targets": ["msi", "app", "dmg"],
|
||||
"windows": {
|
||||
"wix": {
|
||||
"language": "zh-CN"
|
||||
}
|
||||
},
|
||||
"windows": { "wix": { "language": "zh-CN" } },
|
||||
"macOS": {}
|
||||
},
|
||||
"app": {
|
||||
@@ -49,16 +45,7 @@
|
||||
"visible": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"capabilities": ["TeyvatGuide", "Mys", "SubWindow", "DevJson"]
|
||||
}
|
||||
"security": { "capabilities": ["TeyvatGuide", "Mys", "SubWindow", "DevJson"] }
|
||||
},
|
||||
"plugins": {
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": ["teyvatguide"]
|
||||
},
|
||||
"mobile": []
|
||||
}
|
||||
}
|
||||
"plugins": { "deep-link": { "desktop": { "schemes": ["teyvatguide"] }, "mobile": [] } }
|
||||
}
|
||||
|
||||
@@ -212,11 +212,13 @@ async function handleDeepLink(payload: string): Promise<void> {
|
||||
}
|
||||
if (payload.startsWith("router?path=")) {
|
||||
const routerPath = payload.replace("router?path=", "");
|
||||
if (router.currentRoute.value.path === routerPath) {
|
||||
const curPath = router.currentRoute.value.path;
|
||||
if (curPath === routerPath) {
|
||||
showSnackbar.warn("已在当前页面!", 3000);
|
||||
return;
|
||||
}
|
||||
await router.push(routerPath);
|
||||
await router.push({ path: routerPath, query: {} });
|
||||
window.location.pathname = routerPath;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="tgn-container">
|
||||
<div v-for="navItem in nav" :key="navItem.id" class="tgn-nav" @click="toNav(navItem)">
|
||||
<img alt="navIcon" :src="navItem.icon" />
|
||||
<TMiImg alt="navIcon" :src="navItem.icon" :ori="true" />
|
||||
<span>{{ navItem.name }}</span>
|
||||
</div>
|
||||
<div v-if="props.modelValue === 2 && hasNav" class="tgn-nav">
|
||||
@@ -11,9 +11,9 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showDialog from "@comp/func/dialog.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import Mys from "@Mys/index.js";
|
||||
import { emit } from "@tauri-apps/api/event";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
||||
@@ -24,6 +24,7 @@ import { useAppStore } from "@/store/modules/app.js";
|
||||
import TGClient from "@/utils/TGClient.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import { createPost } from "@/utils/TGWindow.js";
|
||||
import ApiHubReq from "@/web/request/apiHubReq.js";
|
||||
import OtherApi from "@/web/request/otherReq.js";
|
||||
|
||||
type TGameNavProps = { modelValue: number };
|
||||
@@ -35,9 +36,9 @@ const codeData = shallowRef<TGApp.BBS.Navigator.CodeData[]>([]);
|
||||
const showOverlay = ref<boolean>(false);
|
||||
const actId = ref<string>();
|
||||
|
||||
const hasNav = computed<boolean>(() => {
|
||||
if (props.modelValue !== 2) return false;
|
||||
return nav.value.find((item) => item.name === "前瞻直播") !== undefined;
|
||||
const hasNav = computed<TGApp.BBS.Navigator.Navigator | undefined>(() => {
|
||||
if (props.modelValue !== 2) return undefined;
|
||||
return nav.value.find((item) => item.name === "前瞻直播" || item.name === "直播兑换码");
|
||||
});
|
||||
|
||||
onMounted(async () => await loadNav());
|
||||
@@ -48,14 +49,13 @@ watch(
|
||||
);
|
||||
|
||||
async function loadNav(): Promise<void> {
|
||||
nav.value = await Mys.ApiHub.homeNew(props.modelValue);
|
||||
nav.value = await ApiHubReq.home(props.modelValue);
|
||||
}
|
||||
|
||||
async function tryGetCode(): Promise<void> {
|
||||
if (props.modelValue !== 2) return;
|
||||
const navFind = nav.value.find((item) => item.name === "前瞻直播");
|
||||
if (!navFind) return;
|
||||
const actIdFind = new URL(navFind.app_path).searchParams.get("act_id");
|
||||
if (!hasNav.value) return;
|
||||
const actIdFind = new URL(hasNav.value.app_path).searchParams.get("act_id");
|
||||
if (!actIdFind) {
|
||||
showSnackbar.warn("未找到活动ID");
|
||||
return;
|
||||
@@ -78,7 +78,7 @@ async function toNav(item: TGApp.BBS.Navigator.Navigator): Promise<void> {
|
||||
return;
|
||||
}
|
||||
await TGLogger.Info(`[TGameNav][toNav] 打开网页活动 ${item.name}`);
|
||||
await TGLogger.Info(`[TGameNav}][toNav] ${item.app_path}`);
|
||||
await TGLogger.Info(`[TGameNav][toNav] ${item.app_path}`);
|
||||
const link = new URL(item.app_path);
|
||||
const mysList = [
|
||||
"https://act.mihoyo.com",
|
||||
@@ -131,6 +131,7 @@ async function toBBS(link: URL): Promise<void> {
|
||||
showSnackbar.warn(`不支持的链接:${link.href}`);
|
||||
}
|
||||
|
||||
// todo 动态获取版块列表
|
||||
function getLocalPath(forum?: string): string {
|
||||
if (!forum) return "";
|
||||
const forumLocalMap: Record<string, string> = {
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
<slot name="icon"><img :src="props.modelValue.icon" alt="icon" /></slot>
|
||||
</div>
|
||||
<div class="tib-cover">
|
||||
<div class="tib-lt"><img :src="props.modelValue.lt" alt="lt" /></div>
|
||||
<div class="tib-lt" v-show="props.modelValue.lt !== ''">
|
||||
<img :src="props.modelValue.lt" alt="lt" />
|
||||
</div>
|
||||
<div v-show="props.modelValue.rt" class="tib-rt">{{ props.modelValue.rt }}</div>
|
||||
<div class="tib-inner">
|
||||
<slot name="inner-icon">
|
||||
|
||||
68
src/components/app/t-mi-img.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<img
|
||||
:src="localUrl"
|
||||
:alt="props.alt"
|
||||
:title="props.title"
|
||||
v-if="localUrl"
|
||||
@click="emits('click')"
|
||||
:class="props.class"
|
||||
/>
|
||||
<div class="progress" v-else>
|
||||
<v-progress-circular indeterminate color="primary" size="25" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
||||
|
||||
import { useAppStore } from "@/store/modules/app.js";
|
||||
import { saveImgLocal } from "@/utils/TGShare.js";
|
||||
|
||||
type TMiImgProps = {
|
||||
src: string;
|
||||
alt: string;
|
||||
title?: string;
|
||||
class?: string;
|
||||
ori?: boolean;
|
||||
};
|
||||
type TMiImgEmits = (e: "click") => void;
|
||||
const props = defineProps<TMiImgProps>();
|
||||
const emits = defineEmits<TMiImgEmits>();
|
||||
|
||||
const appStore = useAppStore();
|
||||
const localUrl = ref<string>();
|
||||
|
||||
onMounted(async () => {
|
||||
if (!props.src) return;
|
||||
if (!props.src.startsWith("http")) {
|
||||
localUrl.value = props.src;
|
||||
return;
|
||||
}
|
||||
const link = props.ori ? props.src : appStore.getImageUrl(props.src);
|
||||
localUrl.value = await saveImgLocal(link);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.src,
|
||||
async () => {
|
||||
if (!props.src) return;
|
||||
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
||||
localUrl.value = undefined;
|
||||
const link = props.ori ? props.src : appStore.getImageUrl(props.src);
|
||||
localUrl.value = await saveImgLocal(link);
|
||||
},
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.progress {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -10,17 +10,16 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from "vue";
|
||||
|
||||
type TolProps = { modelValue: boolean; blurVal?: string };
|
||||
type TolEmits = (e: "update:modelValue", v: boolean) => void;
|
||||
const emit = defineEmits<TolEmits>();
|
||||
const props = withDefaults(defineProps<TolProps>(), { modelValue: false, blurVal: "20px" });
|
||||
type TolProps = { blurVal?: string };
|
||||
withDefaults(defineProps<TolProps>(), { blurVal: "20px" });
|
||||
const model = defineModel<boolean>({ default: false });
|
||||
const showTolo = ref<boolean>(false);
|
||||
const showToli = ref<boolean>(false);
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => model.value,
|
||||
async () => {
|
||||
if (props.modelValue) {
|
||||
if (model.value) {
|
||||
showTolo.value = true;
|
||||
showToli.value = true;
|
||||
return;
|
||||
@@ -33,7 +32,7 @@ watch(
|
||||
);
|
||||
|
||||
function toClick(): void {
|
||||
emit("update:modelValue", false);
|
||||
model.value = false;
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
@@ -83,10 +82,12 @@ function toClick(): void {
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
-webkit-backdrop-filter: blur(v-bind(blurVal));
|
||||
backdrop-filter: blur(v-bind(blurVal));
|
||||
background: rgb(0 0 0 / 50%);
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
<div v-if="card" :id="`post-card-${card.postId}`" class="tpc-card">
|
||||
<div class="tpc-top">
|
||||
<div class="tpc-cover" @click="createPost(card)">
|
||||
<img :src="localCover" alt="cover" v-if="localCover" />
|
||||
<v-progress-circular color="primary" :indeterminate="true" v-else-if="card.cover !== ''" />
|
||||
<TMiImg :src="card.cover" alt="cover" :ori="true" v-if="card.cover !== ''" />
|
||||
<img src="/source/UI/defaultCover.webp" alt="cover" v-else />
|
||||
<div v-if="card.status" class="tpc-act">
|
||||
<div class="tpc-status">{{ card.status?.label }}</div>
|
||||
@@ -67,17 +66,32 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TpAvatar from "@comp/viewPost/tp-avatar.vue";
|
||||
import { emit } from "@tauri-apps/api/event";
|
||||
import { computed, onMounted, onUnmounted, ref, shallowRef, watch } from "vue";
|
||||
import { computed, onMounted, shallowRef, watch } from "vue";
|
||||
|
||||
import { generateShareImg, saveImgLocal } from "@/utils/TGShare.js";
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
import { createPost } from "@/utils/TGWindow.js";
|
||||
|
||||
type TPostCardProps = { modelValue: TGApp.Plugins.Mys.Post.FullData; selectMode?: boolean };
|
||||
type TPostCardEmits = (e: "onSelected", v: string) => void;
|
||||
type TPostStatus = TGApp.Plugins.Mys.News.RenderStatus & { stat: ActStat };
|
||||
type TPostStatus = RenderStatus & { stat: ActStat };
|
||||
type RenderForum = { name: string; icon: string; id: number };
|
||||
type RenderStatus = { stat: number; label: string; color: string };
|
||||
type RenderData = { mark: number; forward: number; like: number; reply: number; view: number };
|
||||
export type RenderCard = {
|
||||
title: string;
|
||||
cover: string;
|
||||
postId: number;
|
||||
subtitle: string;
|
||||
user: TGApp.Plugins.Mys.User.Post | null;
|
||||
forum: RenderForum | null;
|
||||
data: RenderData | null;
|
||||
status?: RenderStatus;
|
||||
topics: Array<TGApp.BBS.Topic.Info>;
|
||||
};
|
||||
|
||||
enum ActStat {
|
||||
UNKNOWN,
|
||||
@@ -94,40 +108,21 @@ const stats: Readonly<Array<TPostStatus>> = [
|
||||
];
|
||||
const props = withDefaults(defineProps<TPostCardProps>(), { selectMode: false });
|
||||
const emits = defineEmits<TPostCardEmits>();
|
||||
const card = shallowRef<TGApp.Plugins.Mys.News.RenderCard>();
|
||||
const localCover = ref<string>();
|
||||
const card = shallowRef<RenderCard>();
|
||||
|
||||
const cardBg = computed<string>(() => {
|
||||
if (card.value && card.value.status) return card.value.status.color;
|
||||
return "none";
|
||||
});
|
||||
|
||||
onMounted(async () => await reload(props.modelValue));
|
||||
onMounted(async () => (card.value = getPostCard(props.modelValue)));
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async () => await reload(props.modelValue),
|
||||
async () => (card.value = getPostCard(props.modelValue)),
|
||||
);
|
||||
|
||||
async function reload(data: TGApp.Plugins.Mys.Post.FullData): Promise<void> {
|
||||
if (localCover.value) {
|
||||
URL.revokeObjectURL(localCover.value);
|
||||
localCover.value = undefined;
|
||||
}
|
||||
card.value = getPostCard(data);
|
||||
if (card.value && card.value.cover !== "") {
|
||||
localCover.value = await saveImgLocal(card.value.cover);
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (localCover.value) {
|
||||
URL.revokeObjectURL(localCover.value);
|
||||
localCover.value = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
function getActivityStatus(status: number): TGApp.Plugins.Mys.News.RenderStatus {
|
||||
function getActivityStatus(status: number): RenderStatus {
|
||||
if (status satisfies ActStat) {
|
||||
const stat: ActStat = status;
|
||||
return stats[stat];
|
||||
@@ -142,18 +137,12 @@ function getPostCover(item: TGApp.Plugins.Mys.Post.FullData): string {
|
||||
else if (item.post.images.length > 0) cover = item.post.images[0];
|
||||
if (cover === undefined) return "";
|
||||
if (cover.endsWith(".gif")) return cover;
|
||||
return `${cover}?x-oss-process=image/format,png`;
|
||||
return `${cover}?x-oss-process=image/resize,m_fill,w_360,h_130,limit_0/format,png`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取公共属性
|
||||
* @since Beta v0.6.1
|
||||
* @param {TGApp.Plugins.Mys.Post.FullData} item 咨讯列表项
|
||||
* @returns {TGApp.Plugins.Mys.News.RenderCard} 渲染用咨讯列表项
|
||||
*/
|
||||
function getCommonCard(item: TGApp.Plugins.Mys.Post.FullData): TGApp.Plugins.Mys.News.RenderCard {
|
||||
let forumData: TGApp.Plugins.Mys.News.RenderForum | null = null;
|
||||
let statData: TGApp.Plugins.Mys.News.RenderData | null = null;
|
||||
function getCommonCard(item: TGApp.Plugins.Mys.Post.FullData): RenderCard {
|
||||
let forumData: RenderForum | null = null;
|
||||
let statData: RenderData | null = null;
|
||||
if (item.forum !== null) {
|
||||
forumData = { name: item.forum.name, icon: item.forum.icon, id: item.forum.id };
|
||||
}
|
||||
@@ -178,7 +167,7 @@ function getCommonCard(item: TGApp.Plugins.Mys.Post.FullData): TGApp.Plugins.Mys
|
||||
};
|
||||
}
|
||||
|
||||
function getPostCard(item: TGApp.Plugins.Mys.Post.FullData): TGApp.Plugins.Mys.News.RenderCard {
|
||||
function getPostCard(item: TGApp.Plugins.Mys.Post.FullData): RenderCard {
|
||||
const commonCard = getCommonCard(item);
|
||||
if (
|
||||
item.news_meta !== undefined &&
|
||||
@@ -205,12 +194,12 @@ async function shareCard(): Promise<void> {
|
||||
await generateShareImg(fileName, shareDom, 2.5);
|
||||
}
|
||||
|
||||
async function toTopic(topic: TGApp.Plugins.Mys.Topic.Info): Promise<void> {
|
||||
async function toTopic(topic: TGApp.BBS.Topic.Info): Promise<void> {
|
||||
const gid = props.modelValue.post.game_id;
|
||||
await emit("active_deep_link", `router?path=/posts/topic/${gid}/${topic.id}`);
|
||||
}
|
||||
|
||||
async function toForum(forum: TGApp.Plugins.Mys.News.RenderForum): Promise<void> {
|
||||
async function toForum(forum: RenderForum): Promise<void> {
|
||||
const gid = props.modelValue.post.game_id;
|
||||
await emit("active_deep_link", `router?path=/posts/forum/${gid}/${forum.id}`);
|
||||
}
|
||||
@@ -292,7 +281,6 @@ async function toForum(forum: TGApp.Plugins.Mys.News.RenderForum): Promise<void>
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
color: var(--box-text-5);
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
gap: 5px;
|
||||
|
||||
@@ -309,6 +297,7 @@ async function toForum(forum: TGApp.Plugins.Mys.News.RenderForum): Promise<void>
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-2);
|
||||
cursor: pointer;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
@@ -320,13 +309,13 @@ async function toForum(forum: TGApp.Plugins.Mys.News.RenderForum): Promise<void>
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 5px;
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(20px);
|
||||
background: var(--common-shadow-2);
|
||||
background: var(--tgc-od-white);
|
||||
border-bottom-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
box-shadow: 0 0 10px var(--tgc-dark-1);
|
||||
color: var(--tgc-white-1);
|
||||
cursor: pointer;
|
||||
opacity: 0.8;
|
||||
text-shadow: 0 0 5px var(--tgc-dark-1);
|
||||
}
|
||||
|
||||
@@ -440,12 +429,13 @@ async function toForum(forum: TGApp.Plugins.Mys.News.RenderForum): Promise<void>
|
||||
padding: 0 5px;
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(20px);
|
||||
background: var(--common-shadow-1);
|
||||
background: var(--tgc-od-orange);
|
||||
border-bottom-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
box-shadow: 2px 2px 5px var(--tgc-dark-1);
|
||||
color: var(--tgc-white-1);
|
||||
font-size: 12px;
|
||||
opacity: 0.8;
|
||||
text-shadow: 0 0 5px var(--tgc-dark-1);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<v-list-item :title.attr="'帖子'" :link="true" href="/posts/forum">
|
||||
<template #title>帖子</template>
|
||||
<template #prepend>
|
||||
<img src="/source/UI/posts.png" alt="posts" class="side-icon" />
|
||||
<img src="/source/UI/posts.webp" alt="posts" class="side-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item :title.attr="'成就'" :link="true" href="/achievements">
|
||||
@@ -62,6 +62,12 @@
|
||||
<img src="/source/UI/userGacha.webp" alt="gacha" class="side-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item :title.attr="'实用脚本'" :link="true" href="/user/scripts">
|
||||
<template #title>实用脚本</template>
|
||||
<template #prepend>
|
||||
<img src="/source/UI/toolbox.webp" alt="scripts" class="side-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-divider />
|
||||
<v-list-item
|
||||
v-show="isDevEnv"
|
||||
@@ -114,7 +120,7 @@
|
||||
<v-list-item :title.attr="'留影叙佳期'" :link="true" href="/archive/birthday">
|
||||
<template #title>留影叙佳期</template>
|
||||
<template #prepend>
|
||||
<img src="/source/UI/act_birthday.png" alt="archive_birthday_icon" class="side-icon" />
|
||||
<img src="/source/UI/act_birthday.webp" alt="archive_birthday_icon" class="side-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<div class="bottom-menu">
|
||||
@@ -145,7 +151,7 @@
|
||||
</v-list-item>
|
||||
<v-list-item class="side-item-menu" title="收藏" :link="true" href="/collection">
|
||||
<template #prepend>
|
||||
<img src="/source/UI/posts.png" alt="collect" class="side-icon-menu" />
|
||||
<img src="/source/UI/posts.webp" alt="collect" class="side-icon-menu" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
@@ -45,26 +45,16 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { computed } from "vue";
|
||||
|
||||
import TOverlay from "./t-overlay.vue";
|
||||
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
import { timestampToDate } from "@/utils/toolFunc.js";
|
||||
|
||||
type ToLiveCodeProps = {
|
||||
data: TGApp.BBS.Navigator.CodeData[];
|
||||
actId: string | undefined;
|
||||
modelValue: boolean;
|
||||
};
|
||||
type ToLiveCodeEmits = (e: "update:modelValue", v: boolean) => void;
|
||||
type ToLiveCodeProps = { data: Array<TGApp.BBS.Navigator.CodeData>; actId: string | undefined };
|
||||
|
||||
const props = withDefaults(defineProps<ToLiveCodeProps>(), { modelValue: false });
|
||||
const emits = defineEmits<ToLiveCodeEmits>();
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
const props = defineProps<ToLiveCodeProps>();
|
||||
const visible = defineModel<boolean>({ default: false });
|
||||
|
||||
function copy(code: string): void {
|
||||
navigator.clipboard.writeText(code);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<TOverlay v-model="visible">
|
||||
<div v-if="props.data" class="ton-container">
|
||||
<TOverlay v-model="visible" v-if="props.data">
|
||||
<div class="ton-container">
|
||||
<slot name="left"></slot>
|
||||
<div class="ton-box">
|
||||
<img
|
||||
@@ -48,10 +48,10 @@ enum ToNameCardTypeEnum {
|
||||
}
|
||||
|
||||
type ToNameCardTypeMap = { [key in ToNameCardTypeEnum]: string };
|
||||
type ToNameCardProps = { modelValue: boolean; data?: TGApp.App.NameCard.Item };
|
||||
type ToNameCardEmits = (e: "update:modelValue", v: boolean) => void;
|
||||
type ToNameCardProps = { data?: TGApp.App.NameCard.Item };
|
||||
|
||||
const props = defineProps<ToNameCardProps>();
|
||||
const emits = defineEmits<ToNameCardEmits>();
|
||||
const visible = defineModel<boolean>();
|
||||
const typeMap: ToNameCardTypeMap = {
|
||||
0: "其他",
|
||||
1: "成就",
|
||||
@@ -61,10 +61,6 @@ const typeMap: ToNameCardTypeMap = {
|
||||
5: "未知",
|
||||
};
|
||||
const loading = ref<boolean>(false);
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
const getType = computed<string>(() => {
|
||||
if (!props.data) return typeMap[ToNameCardTypeEnum.unknown];
|
||||
if (!(props.data.type satisfies ToNameCardTypeEnum)) return typeMap[5];
|
||||
@@ -141,10 +137,11 @@ async function shareNameCard(): Promise<void> {
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.ton-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 10px;
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.ton-box {
|
||||
@@ -159,6 +156,7 @@ async function shareNameCard(): Promise<void> {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.ton-type {
|
||||
@@ -176,12 +174,14 @@ async function shareNameCard(): Promise<void> {
|
||||
right: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-end;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
backdrop-filter: blur(5px);
|
||||
background: rgb(0 0 0 / 25%);
|
||||
color: var(--tgc-white-1);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<v-list class="top-nc-box" @click="emit('selected', props.data)">
|
||||
<v-list-item :title="props.data.name">
|
||||
<template #subtitle>
|
||||
<span :title="props.data.desc">{{ props.data.desc }}</span>
|
||||
<span class="desc" :title="props.data.desc">{{ props.data.desc }}</span>
|
||||
</template>
|
||||
<template #prepend>
|
||||
<v-img
|
||||
@@ -42,4 +42,8 @@ const bgImage = computed<string>(() => {
|
||||
cursor: pointer;
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
|
||||
.desc {
|
||||
text-shadow: 1px 1px 1px #222;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* @file component/func/geetest.ts
|
||||
* @description 封装自定义 geetest 组件,通过函数调用的方式,简化 geetest 的使用
|
||||
* @since Beta v0.6.6
|
||||
* @since Beta v0.7.1
|
||||
*/
|
||||
|
||||
import { h, render } from "vue";
|
||||
import type { ComponentInternalInstance, VNode } from "vue";
|
||||
import { h, render } from "vue";
|
||||
|
||||
import geetest from "./geetest.vue";
|
||||
|
||||
@@ -21,12 +21,12 @@ const geetestId = "tg-func-geetest";
|
||||
interface GeetestInstance extends ComponentInternalInstance {
|
||||
exposeProxy: {
|
||||
displayBox: (
|
||||
props: TGApp.Plugins.Mys.Geetest.reqResp,
|
||||
) => Promise<TGApp.Plugins.Mys.Geetest.validateResp | false>;
|
||||
props: TGApp.BBS.Geetest.CreateRes,
|
||||
) => Promise<TGApp.BBS.Geetest.GeetestVerifyRes | false>;
|
||||
};
|
||||
}
|
||||
|
||||
function renderBox(props: TGApp.Plugins.Mys.Geetest.reqResp): VNode {
|
||||
function renderBox(props: TGApp.BBS.Geetest.CreateRes): VNode {
|
||||
const container = document.createElement("div");
|
||||
container.id = geetestId;
|
||||
const boxVNode: VNode = h(geetest, props);
|
||||
@@ -39,14 +39,14 @@ let geetestInstance: VNode;
|
||||
|
||||
/**
|
||||
* @function showGeetest
|
||||
* @since Beta v0.5.1
|
||||
* @since Beta v0.7.1
|
||||
* @description 弹出 geetest 验证
|
||||
* @param {TGApp.Plugins.Mys.Geetest.reqResp} props geetest 验证的参数
|
||||
* @return {Promise<TGApp.Plugins.Mys.Geetest.validateResp>} 验证成功返回验证数据
|
||||
* @param {TGApp.BBS.Geetest.CreateRes} props geetest 验证的参数
|
||||
* @return {Promise<TGApp.BBS.Geetest.GeetestVerifyRes|false>} 验证成功返回验证数据
|
||||
*/
|
||||
async function showGeetest(
|
||||
props: TGApp.Plugins.Mys.Geetest.reqResp,
|
||||
): Promise<TGApp.Plugins.Mys.Geetest.validateResp | false> {
|
||||
props: TGApp.BBS.Geetest.CreateRes,
|
||||
): Promise<TGApp.BBS.Geetest.GeetestVerifyRes | false> {
|
||||
if (geetestInstance !== undefined) {
|
||||
const boxVue = <GeetestInstance>geetestInstance.component;
|
||||
return boxVue.exposeProxy.displayBox(props);
|
||||
|
||||
@@ -40,14 +40,14 @@ watch(
|
||||
);
|
||||
|
||||
declare function initGeetest(
|
||||
params: TGApp.Plugins.Mys.Geetest.InitGeetestParams,
|
||||
callback: (captchaObj: TGApp.Plugins.Mys.Geetest.GeetestCaptcha) => void,
|
||||
params: TGApp.BBS.Geetest.InitGeetestParams,
|
||||
callback: (captchaObj: TGApp.BBS.Geetest.GeetestCaptcha) => void,
|
||||
): void;
|
||||
|
||||
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) => {
|
||||
props: TGApp.BBS.Geetest.CreateRes,
|
||||
): Promise<TGApp.BBS.Geetest.GeetestVerifyRes | false> {
|
||||
return await new Promise<TGApp.BBS.Geetest.GeetestVerifyRes>((resolve) => {
|
||||
initGeetest(
|
||||
{
|
||||
gt: props.gt,
|
||||
@@ -58,7 +58,7 @@ async function displayBox(
|
||||
area: "#verify",
|
||||
width: "250px",
|
||||
},
|
||||
(captchaObj: TGApp.Plugins.Mys.Geetest.GeetestCaptcha) => {
|
||||
(captchaObj: TGApp.BBS.Geetest.GeetestCaptcha) => {
|
||||
if (geetestEl.value === null) return;
|
||||
geetestEl.value.innerHTML = "";
|
||||
captchaObj.appendTo("#geetest");
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="loading-box">
|
||||
<div class="loading-title">
|
||||
<span>{{ data.title }}</span>
|
||||
<div class="loading-circle" v-show="!empty">
|
||||
<div class="loading-circle" v-show="!data.empty">
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
@@ -15,7 +15,7 @@
|
||||
{{ data.subtitle }}
|
||||
</div>
|
||||
<div class="loading-img">
|
||||
<img v-if="!empty" src="/source/UI/loading.webp" alt="loading" />
|
||||
<img v-if="!data.empty" src="/source/UI/loading.webp" alt="loading" />
|
||||
<img v-else src="/source/UI/empty.webp" alt="empty" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -125,8 +125,9 @@ defineExpose({ displayBox });
|
||||
|
||||
.loading-container {
|
||||
display: flex;
|
||||
min-width: 800px;
|
||||
width: 800px;
|
||||
min-height: 300px;
|
||||
box-sizing: border-box;
|
||||
padding: 15px;
|
||||
border-radius: 15px;
|
||||
background: rgb(255 255 255 / 5%);
|
||||
@@ -136,7 +137,7 @@ defineExpose({ displayBox });
|
||||
.loading-box {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
box-sizing: content-box;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -159,10 +160,15 @@ defineExpose({ displayBox });
|
||||
}
|
||||
|
||||
.loading-subtitle {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 25px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 20px;
|
||||
font-size: 1rem;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.loading-img {
|
||||
|
||||
@@ -103,13 +103,16 @@ defineExpose({ displayBox });
|
||||
.func-snackbar {
|
||||
display: flex;
|
||||
min-width: 200px;
|
||||
height: 40px;
|
||||
max-width: calc(100% - 40px);
|
||||
min-height: 40px;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
background-color: v-bind(bgColor);
|
||||
box-shadow: 0 0 10px rgb(0 0 0 / 20%);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.func-snackbar-text {
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<script lang="ts" setup>
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { computed, ref } from "vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
import HtaOverviewLine from "./hta-overview-line.vue";
|
||||
|
||||
@@ -63,19 +63,11 @@ import type { AbyssDataItem } from "@/pages/WIKI/Abyss.vue";
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
import { timestampToDate } from "@/utils/toolFunc.js";
|
||||
|
||||
type HtaOverlayOverviewProps = {
|
||||
modelValue: boolean;
|
||||
data: AbyssDataItem<TGApp.Plugins.Hutao.Abyss.OverviewData>;
|
||||
};
|
||||
type HtaOverlayOverviewEmits = (e: "update:modelValue", v: boolean) => void;
|
||||
type HtaOverlayOverviewProps = { data: AbyssDataItem<TGApp.Plugins.Hutao.Abyss.OverviewData> };
|
||||
|
||||
const props = defineProps<HtaOverlayOverviewProps>();
|
||||
const emits = defineEmits<HtaOverlayOverviewEmits>();
|
||||
const visible = defineModel<boolean>();
|
||||
const loadShare = ref<boolean>(false);
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
|
||||
async function share(): Promise<void> {
|
||||
loadShare.value = true;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<template>
|
||||
<!-- todo fix typo err -->
|
||||
<v-data-table :headers="headers" fixed-header :items="holdData" height="calc(100vh - 160px)">
|
||||
<template v-slot:item="{ item }">
|
||||
<tr class="hta-th-tr">
|
||||
@@ -53,7 +52,7 @@ type HtaTabHoldData = {
|
||||
const props = defineProps<HtaTabHoldProps>();
|
||||
const holdData = shallowRef<Array<HtaTabHoldData>>([]);
|
||||
|
||||
const headers = [
|
||||
const headers = <const>[
|
||||
{ title: "角色", align: "center", key: "AvatarId" },
|
||||
{ title: "持有", align: "center", key: "HoldingRate.cur" },
|
||||
{ title: "0命", align: "center", key: "Constellations[0].RateCur" },
|
||||
|
||||
@@ -66,7 +66,6 @@ onMounted(async () => {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 130px);
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
@@ -102,7 +101,7 @@ onMounted(async () => {
|
||||
.hta-tuf-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-height: calc(100vh - 200px);
|
||||
max-height: calc(100vh - 160px);
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-1);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="hta-tu-box">
|
||||
<v-tabs v-model="tab" direction="vertical" class="hta-tu-tab">
|
||||
<v-tab :value="10">第10层</v-tab>
|
||||
<v-tab :value="11">第11层</v-tab>
|
||||
<v-tab :value="12">第12层</v-tab>
|
||||
</v-tabs>
|
||||
@@ -29,7 +28,7 @@ type HtaTabUpProps = { data: AbyssDataItem<Array<TGApp.Plugins.Hutao.Abyss.Avata
|
||||
type HtaTabUpData = { Floor: number; Ranks: Array<AbyssDataItem<TGApp.Plugins.Hutao.Base.Rate>> };
|
||||
|
||||
const props = defineProps<HtaTabUpProps>();
|
||||
const tab = ref<number>(10);
|
||||
const tab = ref<number>(11);
|
||||
const select = shallowRef<Array<HtaTabUpData>>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="hta-tus-box">
|
||||
<v-tabs v-model="tab" direction="vertical" class="hta-tus-tab">
|
||||
<v-tab :value="10">第10层</v-tab>
|
||||
<v-tab :value="11">第11层</v-tab>
|
||||
<v-tab :value="12">第12层</v-tab>
|
||||
</v-tabs>
|
||||
@@ -29,7 +28,7 @@ type HtaTabUseProps = { data: AbyssDataItem<Array<TGApp.Plugins.Hutao.Abyss.Avat
|
||||
type HtaTabUseData = { Floor: number; Ranks: Array<AbyssDataItem<{ Item: number; Rate: number }>> };
|
||||
|
||||
const props = defineProps<HtaTabUseProps>();
|
||||
const tab = ref<number>(10);
|
||||
const tab = ref<number>(11);
|
||||
const select = shallowRef<Array<HtaTabUseData>>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div :id="`anno_card_${props.modelValue.id}`" class="anno-card">
|
||||
<div class="anno-cover" :title="props.modelValue.title" @click="createAnno">
|
||||
<img :src="localBanner" alt="cover" v-if="localBanner" />
|
||||
<v-progress-circular
|
||||
color="primary"
|
||||
:indeterminate="true"
|
||||
v-else-if="props.modelValue.banner !== ''"
|
||||
<TMiImg
|
||||
:src="props.modelValue.banner"
|
||||
alt="cover"
|
||||
:ori="true"
|
||||
v-if="props.modelValue.banner !== ''"
|
||||
/>
|
||||
<img src="/source/UI/defaultCover.webp" alt="cover" v-else />
|
||||
<img alt="cover" src="/source/UI/defaultCover.webp" v-else />
|
||||
<div class="anno-info">
|
||||
<div class="anno-time">
|
||||
<v-icon>mdi-clock-time-four-outline</v-icon>
|
||||
@@ -19,55 +19,22 @@
|
||||
{{ parseTitle(props.modelValue.subtitle) }}
|
||||
</div>
|
||||
<div class="anno-label" :title="`标签:${props.modelValue.tagLabel}`">
|
||||
<img :src="localTag" alt="tag" v-if="localTag" />
|
||||
<v-icon v-else>mdi-tag</v-icon>
|
||||
<img :src="props.modelValue.tagIcon" alt="tag" />
|
||||
<span>{{ props.modelValue.tagLabel }}</span>
|
||||
</div>
|
||||
<div class="anno-id">{{ props.modelValue.id }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
||||
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import { generateShareImg, saveImgLocal } from "@/utils/TGShare.js";
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
import { createTGWindow } from "@/utils/TGWindow.js";
|
||||
|
||||
type TAnnoCardProps = { region: string; modelValue: TGApp.App.Announcement.ListCard; lang: string };
|
||||
const props = defineProps<TAnnoCardProps>();
|
||||
const localBanner = ref<string>();
|
||||
const localTag = ref<string>();
|
||||
|
||||
onMounted(async () => {
|
||||
if (props.modelValue.banner !== "") {
|
||||
localBanner.value = await saveImgLocal(props.modelValue.banner);
|
||||
}
|
||||
localTag.value = await saveImgLocal(props.modelValue.tagIcon);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async () => {
|
||||
if (localBanner.value && localBanner.value.startsWith("blob:")) {
|
||||
URL.revokeObjectURL(localBanner.value);
|
||||
localBanner.value = undefined;
|
||||
}
|
||||
if (props.modelValue.banner !== "") {
|
||||
localBanner.value = await saveImgLocal(props.modelValue.banner);
|
||||
}
|
||||
if (localTag.value && localTag.value.startsWith("blob:")) {
|
||||
URL.revokeObjectURL(localTag.value);
|
||||
localTag.value = undefined;
|
||||
}
|
||||
localTag.value = await saveImgLocal(props.modelValue.tagIcon);
|
||||
},
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
if (localBanner.value) URL.revokeObjectURL(localBanner.value);
|
||||
if (localTag.value) URL.revokeObjectURL(localTag.value);
|
||||
});
|
||||
|
||||
function parseTitle(title: string): string {
|
||||
const dom = new DOMParser().parseFromString(title, "text/html");
|
||||
@@ -106,7 +73,7 @@ async function shareAnno(): Promise<void> {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
aspect-ratio: 36 / 13;
|
||||
cursor: pointer;
|
||||
@@ -162,12 +129,11 @@ async function shareAnno(): Promise<void> {
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 5px;
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(20px);
|
||||
background: var(--common-shadow-2);
|
||||
background-color: var(--tgc-od-white);
|
||||
border-bottom-left-radius: 5px;
|
||||
box-shadow: 0 0 10px var(--tgc-dark-1);
|
||||
color: var(--tgc-white-1);
|
||||
opacity: 0.8;
|
||||
text-shadow: 0 0 5px var(--tgc-dark-1);
|
||||
}
|
||||
|
||||
@@ -190,14 +156,13 @@ async function shareAnno(): Promise<void> {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 5px;
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(20px);
|
||||
background: var(--common-shadow-1);
|
||||
background: var(--tgc-od-orange);
|
||||
border-bottom-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
box-shadow: 2px 2px 5px var(--tgc-dark-1);
|
||||
box-shadow: 0 0 10px var(--tgc-dark-1);
|
||||
color: var(--tgc-white-1);
|
||||
font-size: 12px;
|
||||
opacity: 0.8;
|
||||
text-shadow: 0 0 5px var(--tgc-dark-1);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<TOverlay v-model="visible" blur-val="5px">
|
||||
<div class="toab-container" v-if="props.data">
|
||||
<div class="toab-img">
|
||||
<img :src="props.data.take_picture[Number(props.choice)]" alt="顶部图像" />
|
||||
<TMiImg :ori="true" :src="props.data.take_picture[Number(props.choice)]" alt="顶部图像" />
|
||||
<div class="toab-dialog" v-show="showText">
|
||||
<div v-for="(item, index) in textParse" :key="index" class="toab-dialog-item">
|
||||
<div class="toab-dialog-item-icon" v-if="item.icon" :title="item.name">
|
||||
<img :src="item.icon" alt="对白头像" />
|
||||
<TMiImg :src="item.icon" alt="对白头像" :ori="true" />
|
||||
</div>
|
||||
<div v-else-if="item.name !== '未知'" class="toab-dialog-item-name">
|
||||
{{ item.name }}
|
||||
@@ -33,35 +33,28 @@
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { fetch } from "@tauri-apps/plugin-http";
|
||||
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
||||
import { onMounted, ref, shallowRef, watch } from "vue";
|
||||
import { xml2json } from "xml-js";
|
||||
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import { copyToClipboard, getImageBuffer, saveCanvasImg } from "@/utils/TGShare.js";
|
||||
import { bytesToSize } from "@/utils/toolFunc.js";
|
||||
|
||||
type ToArcBirthProps = {
|
||||
modelValue: boolean;
|
||||
data?: TGApp.Archive.Birth.DrawItem;
|
||||
choice: boolean;
|
||||
};
|
||||
type ToArcBirthEmits = (e: "update:modelValue", v: boolean) => void;
|
||||
type ToArcBirthProps = { data?: TGApp.Archive.Birth.DrawItem; choice: boolean };
|
||||
type XmlKeyMap = { id: string; rel: string; group?: string; icon: string };
|
||||
type XmlTextList = { chara: string; img: string; text: string };
|
||||
type XmlTextParse = { name: string; icon?: string; text: string };
|
||||
|
||||
const props = defineProps<ToArcBirthProps>();
|
||||
const emits = defineEmits<ToArcBirthEmits>();
|
||||
const visible = defineModel<boolean>();
|
||||
const showText = ref<boolean>(false);
|
||||
const buffer = shallowRef<Uint8Array | null>(null);
|
||||
const textParse = shallowRef<Array<XmlTextParse>>([]);
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
|
||||
onMounted(() => clearData());
|
||||
watch(() => props.data, clearData);
|
||||
watch(() => props.choice, clearData);
|
||||
|
||||
@@ -26,26 +26,23 @@ import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showDialog from "@comp/func/dialog.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TSUserCollection from "@Sqlite/modules/userCollect.js";
|
||||
import { computed, ref, shallowRef, watch } from "vue";
|
||||
import { ref, shallowRef, watch } from "vue";
|
||||
|
||||
type ToPostCollectProps = { modelValue: boolean; post: Array<string> };
|
||||
type ToPostCollectEmits = {
|
||||
(e: "update:modelValue", v: boolean): void;
|
||||
(e: "submit"): void;
|
||||
};
|
||||
type ToPostCollectProps = { post: Array<string> };
|
||||
type ToPostCollectEmits = (e: "submit") => void;
|
||||
|
||||
const props = defineProps<ToPostCollectProps>();
|
||||
const emits = defineEmits<ToPostCollectEmits>();
|
||||
const visible = defineModel<boolean>();
|
||||
const select = ref<string>();
|
||||
const submit = ref<boolean>(false);
|
||||
const collectList = shallowRef<Array<TGApp.Sqlite.UserCollection.UFCollection>>([]);
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (val) => (val ? await freshData() : null),
|
||||
() => visible.value,
|
||||
async () => {
|
||||
if (visible.value) await freshData();
|
||||
},
|
||||
);
|
||||
|
||||
async function onSubmit(): Promise<void> {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<template>
|
||||
<ToGameLogin v-model="showLoginQr" @success="tryGetTokens" v-model:launcher="isLauncherQr" />
|
||||
<v-card class="tcu-box">
|
||||
<template #prepend>
|
||||
<v-avatar :image="userInfo.avatar" />
|
||||
@@ -36,12 +37,6 @@
|
||||
</template>
|
||||
<template #actions>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
@click="tryCaptchaLogin()"
|
||||
icon="mdi-cellphone"
|
||||
title="验证码登录"
|
||||
/>
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
@click="confirmRefreshUser(uid!)"
|
||||
@@ -90,10 +85,32 @@
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-menu location="start">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn variant="outlined" icon="mdi-account-plus" title="添加账户" v-bind="props" />
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item @click="addByCookie()" append-icon="mdi-account-plus">
|
||||
<v-list-item-title>手动添加</v-list-item-title>
|
||||
<v-list-item-subtitle>手动输入Cookie</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
<v-list-item @click="tryCaptchaLogin()" append-icon="mdi-cellphone">
|
||||
<v-list-item-title>验证码登录</v-list-item-title>
|
||||
<v-list-item-subtitle>使用手机号登录</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
<v-list-item @click="tryCodeLogin(true)">
|
||||
<v-list-item-title>扫码登录(启动器)</v-list-item-title>
|
||||
<v-list-item-subtitle>使用米游社扫码登录</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<img src="/platforms/mhy/launcher.webp" alt="launcher" class="menu-icon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item @click="tryCodeLogin(false)" append-icon="mdi-qrcode-scan" v-if="false">
|
||||
<v-list-item-title>扫码登录(游戏)</v-list-item-title>
|
||||
<v-list-item-subtitle>使用米游社扫码登录</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
@@ -104,10 +121,11 @@ import showDialog from "@comp/func/dialog.js";
|
||||
import showGeetest from "@comp/func/geetest.js";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import ToGameLogin from "@comp/pageConfig/tco-gameLogin.vue";
|
||||
import Mys from "@Mys/index.js";
|
||||
import TSUserAccount from "@Sqlite/modules/userAccount.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, shallowRef } from "vue";
|
||||
import { computed, ref, shallowRef } from "vue";
|
||||
|
||||
import { useAppStore } from "@/store/modules/app.js";
|
||||
import { useUserStore } from "@/store/modules/user.js";
|
||||
@@ -119,6 +137,8 @@ import TakumiApi from "@/web/request/takumiReq.js";
|
||||
const { isLogin } = storeToRefs(useAppStore());
|
||||
const { uid, briefInfo, cookie, account } = storeToRefs(useUserStore());
|
||||
|
||||
const showLoginQr = ref<boolean>(false);
|
||||
const isLauncherQr = ref<boolean>(true);
|
||||
const accounts = shallowRef<Array<TGApp.App.Account.User>>([]);
|
||||
const gameAccounts = shallowRef<Array<TGApp.Sqlite.Account.Game>>([]);
|
||||
const userInfo = computed<TGApp.App.Account.BriefInfo>(() => {
|
||||
@@ -126,42 +146,12 @@ const userInfo = computed<TGApp.App.Account.BriefInfo>(() => {
|
||||
return {
|
||||
nickname: "未登录",
|
||||
uid: "-1",
|
||||
desc: "请使用短信验证码登录",
|
||||
desc: "请登录",
|
||||
avatar: "/source/UI/lumine.webp",
|
||||
};
|
||||
});
|
||||
|
||||
async function tryCaptchaLogin(): Promise<void> {
|
||||
const phone = await showDialog.input("请输入手机号", "+86");
|
||||
if (!phone) {
|
||||
showSnackbar.cancel("已取消验证码登录");
|
||||
return;
|
||||
}
|
||||
const phoneReg = /^1[3-9]\d{9}$/;
|
||||
if (!phoneReg.test(phone)) {
|
||||
showSnackbar.warn("请输入正确的手机号");
|
||||
return;
|
||||
}
|
||||
const actionType = await tryGetCaptcha(phone);
|
||||
if (!actionType) return;
|
||||
showSnackbar.success(`已发送验证码到 ${phone}`);
|
||||
const captcha = await showDialog.input("请输入验证码", "验证码:", undefined, false);
|
||||
if (!captcha) {
|
||||
showSnackbar.warn("输入验证码为空");
|
||||
return;
|
||||
}
|
||||
const loginResp = await tryLoginByCaptcha(phone, captcha, actionType);
|
||||
if (!loginResp) return;
|
||||
await showLoading.start("正在尝试登录...");
|
||||
const ck: TGApp.App.Account.Cookie = {
|
||||
account_id: loginResp.user_info.aid,
|
||||
ltuid: loginResp.user_info.aid,
|
||||
stuid: loginResp.user_info.aid,
|
||||
mid: loginResp.user_info.mid,
|
||||
cookie_token: "",
|
||||
stoken: loginResp.token.token,
|
||||
ltoken: "",
|
||||
};
|
||||
async function tryGetTokens(ck: TGApp.App.Account.Cookie): Promise<void> {
|
||||
await showLoading.update("正在获取 LToken");
|
||||
const ltokenRes = await PassportApi.lToken.get(ck);
|
||||
if (typeof ltokenRes !== "string") {
|
||||
@@ -231,6 +221,45 @@ async function tryCaptchaLogin(): Promise<void> {
|
||||
showSnackbar.success("成功登录!");
|
||||
}
|
||||
|
||||
async function tryCaptchaLogin(): Promise<void> {
|
||||
const phone = await showDialog.input("请输入手机号", "+86");
|
||||
if (!phone) {
|
||||
showSnackbar.cancel("已取消验证码登录");
|
||||
return;
|
||||
}
|
||||
const phoneReg = /^1[3-9]\d{9}$/;
|
||||
if (!phoneReg.test(phone)) {
|
||||
showSnackbar.warn("请输入正确的手机号");
|
||||
return;
|
||||
}
|
||||
const actionType = await tryGetCaptcha(phone);
|
||||
if (!actionType) return;
|
||||
showSnackbar.success(`已发送验证码到 ${phone}`);
|
||||
const captcha = await showDialog.input("请输入验证码", "验证码:", undefined, false);
|
||||
if (!captcha) {
|
||||
showSnackbar.warn("输入验证码为空");
|
||||
return;
|
||||
}
|
||||
const loginResp = await tryLoginByCaptcha(phone, captcha, actionType);
|
||||
if (!loginResp) return;
|
||||
await showLoading.start("正在尝试登录...");
|
||||
const ck: TGApp.App.Account.Cookie = {
|
||||
account_id: loginResp.user_info.aid,
|
||||
ltuid: loginResp.user_info.aid,
|
||||
stuid: loginResp.user_info.aid,
|
||||
mid: loginResp.user_info.mid,
|
||||
cookie_token: "",
|
||||
stoken: loginResp.token.token,
|
||||
ltoken: "",
|
||||
};
|
||||
await tryGetTokens(ck);
|
||||
}
|
||||
|
||||
async function tryCodeLogin(isLauncher: boolean): Promise<void> {
|
||||
isLauncherQr.value = isLauncher;
|
||||
showLoginQr.value = true;
|
||||
}
|
||||
|
||||
async function refreshUser(uid: string) {
|
||||
let account = await TSUserAccount.account.getAccount(uid);
|
||||
if (!account) {
|
||||
@@ -537,4 +566,9 @@ async function clearUser(user: TGApp.App.Account.User): Promise<void> {
|
||||
.tcu-btn {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
220
src/components/pageConfig/tco-gameLogin.vue
Normal file
@@ -0,0 +1,220 @@
|
||||
<template>
|
||||
<TOverlay v-model="model" hide blur-val="20px">
|
||||
<div class="tog-box">
|
||||
<div class="tog-top">
|
||||
<div class="tog-title">请使用米游社进行扫码操作</div>
|
||||
</div>
|
||||
<div class="tog-mid">
|
||||
<qrcode-vue
|
||||
v-if="codeUrl"
|
||||
class="tog-qr"
|
||||
:value="codeUrl"
|
||||
render-as="svg"
|
||||
:background="'var(--box-bg-1)'"
|
||||
foreground="var(--box-text-1)"
|
||||
/>
|
||||
</div>
|
||||
<div class="tog-bottom" @click="share()">
|
||||
<img src="/platforms/mhy/launcher.webp" alt="icon" v-if="isLauncherCode" />
|
||||
<img src="/platforms/mhy/mys.webp" alt="icon" v-else />
|
||||
</div>
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import QrcodeVue from "qrcode.vue";
|
||||
import { computed, onUnmounted, ref, watch } from "vue";
|
||||
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
import hk4eReq from "@/web/request/hk4eReq.js";
|
||||
import PassportReq from "@/web/request/passportReq.js";
|
||||
import takumiReq from "@/web/request/takumiReq.js";
|
||||
|
||||
type ToGameLoginEmits = (e: "success", data: TGApp.App.Account.Cookie) => void;
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
let cycleTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
const model = defineModel<boolean>({ default: false });
|
||||
const isLauncherCode = defineModel<boolean>("launcher", { default: false });
|
||||
const emits = defineEmits<ToGameLoginEmits>();
|
||||
const codeUrl = ref<string>();
|
||||
const codeTicket = computed<string>(() => {
|
||||
if (!codeUrl.value) return "";
|
||||
const url = new URL(codeUrl.value);
|
||||
return url.searchParams.get("ticket") || "";
|
||||
});
|
||||
|
||||
watch(model, async (value) => {
|
||||
if (value) {
|
||||
await freshQr();
|
||||
cycleTimer = setInterval(cycleGetData, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
async function share(): Promise<void> {
|
||||
const shareDom = document.querySelector<HTMLDivElement>(".tog-box");
|
||||
if (shareDom === null) {
|
||||
showSnackbar.error("分享失败");
|
||||
return;
|
||||
}
|
||||
await generateShareImg(`tco-gameLogin`, shareDom);
|
||||
}
|
||||
|
||||
async function freshQr(): Promise<void> {
|
||||
let res;
|
||||
if (isLauncherCode.value) res = await PassportReq.qrLogin.create();
|
||||
else res = await hk4eReq.loginQr.create();
|
||||
console.log(res);
|
||||
if ("retcode" in res) {
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
return;
|
||||
}
|
||||
codeUrl.value = res.url;
|
||||
}
|
||||
|
||||
async function cycleGetData() {
|
||||
if (cycleTimer === null || codeTicket.value === "") return;
|
||||
if (isLauncherCode.value) await cycleGetDataLauncher(cycleTimer);
|
||||
else await cycleGetDataGame(cycleTimer);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
async function cycleGetDataLauncher(timer: NodeJS.Timeout): Promise<void> {
|
||||
const res = await PassportReq.qrLogin.query(codeTicket.value);
|
||||
console.log(res);
|
||||
if ("retcode" in res) {
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
if (res.retcode === -106) {
|
||||
await freshQr();
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
cycleTimer = null;
|
||||
model.value = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (res.status === "Created" || res.status === "Scanned") return;
|
||||
if (res.status === "Confirmed") {
|
||||
clearInterval(timer);
|
||||
cycleTimer = null;
|
||||
const ck: TGApp.App.Account.Cookie = {
|
||||
account_id: res.user_info.aid,
|
||||
ltuid: res.user_info.aid,
|
||||
stuid: res.user_info.aid,
|
||||
mid: res.user_info.mid,
|
||||
cookie_token: "",
|
||||
stoken: res.tokens[0].token,
|
||||
ltoken: "",
|
||||
};
|
||||
emits("success", ck);
|
||||
model.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
async function cycleGetDataGame(timer: NodeJS.Timeout): Promise<void> {
|
||||
const res = await hk4eReq.loginQr.state(codeTicket.value);
|
||||
console.log(res);
|
||||
if ("retcode" in res) {
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
if (res.retcode === -106) {
|
||||
await freshQr();
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
cycleTimer = null;
|
||||
model.value = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (res.stat === "Init" || res.stat === "Scanned") return;
|
||||
if (res.stat === "Confirmed") {
|
||||
clearInterval(timer);
|
||||
cycleTimer = null;
|
||||
if (res.payload.proto === "Raw") {
|
||||
showSnackbar.error(`返回数据异常:${res.payload}`);
|
||||
model.value = false;
|
||||
return;
|
||||
}
|
||||
const statusRaw: TGApp.Game.Login.StatusPayloadRaw = JSON.parse(res.payload.raw);
|
||||
await showLoading.start("正在获取SToken");
|
||||
const stResp = await takumiReq.game.stoken(statusRaw);
|
||||
console.log(stResp);
|
||||
await showLoading.end();
|
||||
if ("retcode" in stResp) {
|
||||
showSnackbar.error(`[${stResp.retcode}] ${stResp.message}`);
|
||||
model.value = false;
|
||||
return;
|
||||
}
|
||||
// const ck: TGApp.App.Account.Cookie = {
|
||||
// account_id: statusRaw.uid,
|
||||
// ltuid: statusRaw.uid,
|
||||
// stuid: statusRaw.uid,
|
||||
// mid: res.user_info.mid,
|
||||
// cookie_token: "",
|
||||
// stoken: res.tokens[0].token,
|
||||
// ltoken: "",
|
||||
// };
|
||||
// emits("success", ck);
|
||||
model.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (cycleTimer !== null) clearInterval(cycleTimer);
|
||||
cycleTimer = null;
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tog-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: var(--box-bg-1);
|
||||
color: var(--app-page-content);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tog-top {
|
||||
border-bottom: 1px solid var(--common-shadow-4);
|
||||
font-family: var(--font-title);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tog-title {
|
||||
color: var(--common-text-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.tog-mid {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
border-radius: 5px;
|
||||
aspect-ratio: 1;
|
||||
background: var(--box-bg-2);
|
||||
}
|
||||
|
||||
.tog-qr {
|
||||
width: 256px;
|
||||
height: 256px;
|
||||
}
|
||||
|
||||
.tog-bottom {
|
||||
margin: 0 auto;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -6,20 +6,30 @@
|
||||
</div>
|
||||
<div class="tcb-top-active" v-else>
|
||||
<span>今天是</span>
|
||||
<img
|
||||
v-for="i in cur"
|
||||
:key="i.role_id"
|
||||
class="tcb-cur"
|
||||
:alt="i.name"
|
||||
:src="i.head_icon"
|
||||
:title="i.name"
|
||||
/>
|
||||
<div v-for="i in cur" :key="i.role_id">
|
||||
<TMiImg
|
||||
:src="i.head_icon"
|
||||
:alt="i.name"
|
||||
:title="i.name"
|
||||
:ori="true"
|
||||
v-if="i.head_icon.startsWith('http')"
|
||||
/>
|
||||
<img @click="toBirth(true)" :src="i.head_icon" alt="empty" class="tcb-cur" v-else />
|
||||
</div>
|
||||
<span>的生日哦~</span>
|
||||
<img @click="toBirth(true)" src="/source/UI/act_birthday.png" alt="empty" class="active" />
|
||||
<img @click="toBirth(true)" src="/source/UI/act_birthday.webp" alt="empty" class="active" />
|
||||
</div>
|
||||
<div>即将到来:{{ next[0].role_birthday }}</div>
|
||||
<div v-for="i in next" :key="i.role_id" class="tcb-item">
|
||||
<img :src="i.head_icon" :alt="i.name" @click="toBirth(i)" :title="i.name" />
|
||||
<TMiImg
|
||||
v-if="i.head_icon.startsWith('http')"
|
||||
:src="i.head_icon"
|
||||
:alt="i.name"
|
||||
@click="toBirth(i)"
|
||||
:title="i.name"
|
||||
:ori="true"
|
||||
/>
|
||||
<img v-else :src="i.head_icon" alt="empty" @click="toBirth(i)" />
|
||||
<div class="tcb-item-info">
|
||||
<span>{{ i.name }} 所属:{{ i.belong === "" ? "未知" : i.belong }}</span>
|
||||
<span>{{ parseDesc(i.introduce) }}</span>
|
||||
@@ -28,6 +38,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import TSAvatarBirth from "@Sqlite/modules/avatarBirth.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onBeforeMount, ref, shallowRef } from "vue";
|
||||
@@ -46,11 +57,13 @@ onBeforeMount(async () => {
|
||||
if (check.length !== 0) {
|
||||
isBirthday.value = true;
|
||||
cur.value = check;
|
||||
console.log(cur.value);
|
||||
}
|
||||
next.value = TSAvatarBirth.getNextAvatarBirth();
|
||||
console.log(next.value);
|
||||
});
|
||||
|
||||
function toBirth(type: TGApp.Archive.Birth.RoleItem | true): void {
|
||||
async function toBirth(type: TGApp.Archive.Birth.RoleItem | true): Promise<void> {
|
||||
let dateStr;
|
||||
if (type === true) {
|
||||
const date = new Date();
|
||||
@@ -61,15 +74,15 @@ function toBirth(type: TGApp.Archive.Birth.RoleItem | true): void {
|
||||
dateStr = type.role_birthday;
|
||||
}
|
||||
if (type !== true) {
|
||||
router.push({ name: "留影叙佳期", params: { date: dateStr } });
|
||||
await router.push({ name: "留影叙佳期", params: { date: dateStr } });
|
||||
return;
|
||||
}
|
||||
if (cur.value.length > 0 && !cur.value[0].is_subscribe) {
|
||||
recentNewsType.value = "news";
|
||||
router.push("/news/2/news");
|
||||
await router.push("/news/2/news");
|
||||
return;
|
||||
}
|
||||
router.push({ name: "留影叙佳期", params: { date: dateStr } });
|
||||
await router.push({ name: "留影叙佳期", params: { date: dateStr } });
|
||||
}
|
||||
|
||||
function parseDesc(intro: string): string {
|
||||
@@ -130,6 +143,7 @@ function parseDesc(intro: string): string {
|
||||
|
||||
.tcb-item img {
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
aspect-ratio: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -36,20 +36,12 @@ import { useRouter } from "vue-router";
|
||||
|
||||
import TibCalendarMaterial from "./ph-calendar-material.vue";
|
||||
|
||||
type ToCalendarProps = {
|
||||
modelValue: boolean;
|
||||
dataType: "weapon" | "character";
|
||||
dataVal: TGApp.App.Calendar.Item;
|
||||
};
|
||||
type ToCalendarEmits = (e: "update:modelValue", v: boolean) => void;
|
||||
type ToCalendarProps = { dataType: "weapon" | "character"; dataVal: TGApp.App.Calendar.Item };
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const props = defineProps<ToCalendarProps>();
|
||||
const emits = defineEmits<ToCalendarEmits>();
|
||||
const router = useRouter();
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
const visible = defineModel<boolean>();
|
||||
const boxData = computed<TItemBoxData>(() => ({
|
||||
bg: `/icon/bg/${props.dataVal.star}-Star.webp`,
|
||||
icon: `/WIKI/${props.dataType}/${props.dataVal.id}.webp`,
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
{{ text.text }}
|
||||
</v-btn>
|
||||
</div>
|
||||
<v-pagination class="tc-page" v-model="page" :total-visible="visible" :length="length" />
|
||||
<v-pagination class="tc-page" v-model="page" :total-visible="9" :length="length" />
|
||||
</div>
|
||||
<div class="tc-content">
|
||||
<TCalendarBirth />
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="pool-grid">
|
||||
<div v-for="pool in poolSelect" :key="pool.postId" class="pool-card">
|
||||
<div class="pool-cover" @click="createPost(pool.postId, pool.title)">
|
||||
<img :src="pool.cover" alt="cover" />
|
||||
<TMiImg :src="pool.cover" alt="cover" :ori="true" />
|
||||
</div>
|
||||
<div class="pool-bottom">
|
||||
<div class="pool-character">
|
||||
@@ -56,6 +56,7 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TItembox, { type TItemBoxData } from "@comp/app/t-itemBox.vue";
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import Mys from "@Mys/index.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="top">
|
||||
<div class="main">
|
||||
<div class="left" @click="openPosition(props.position)">
|
||||
<img :src="props.position.icon" alt="icon" />
|
||||
<TMiImg :ori="true" :src="props.position.icon" alt="icon" />
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="title">{{ props.position.title }}</div>
|
||||
@@ -38,6 +38,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import type { PositionItem } from "@comp/pageHome/ph-comp-position.vue";
|
||||
|
||||
@@ -102,6 +103,7 @@ async function openPosition(card: TGApp.Plugins.Mys.Position.RenderCard): Promis
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 3px;
|
||||
background: var(--box-bg-2);
|
||||
object-fit: contain;
|
||||
|
||||
img {
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
v-for="(item, index) in channelList"
|
||||
:key="index"
|
||||
class="toc-list-item"
|
||||
:class="{ active: props.gid === item.gid }"
|
||||
:class="props.gid === item.gid.toString() ? 'active' : ''"
|
||||
@click="toChannel(item)"
|
||||
>
|
||||
<img :src="item.icon" alt="icon" />
|
||||
<TMiImg :src="item.icon" alt="icon" :ori="true" />
|
||||
<span>{{ item.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -18,30 +18,30 @@
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { onMounted, shallowRef } from "vue";
|
||||
|
||||
import { type NewsType, useAppStore } from "@/store/modules/app.js";
|
||||
import type { ToChannelItem } from "@/web/constant/bbs.js";
|
||||
import TGConstant from "@/web/constant/TGConstant.js";
|
||||
import apiHubReq from "@/web/request/apiHubReq.js";
|
||||
|
||||
type ChannelItem = { icon: string; title: string; gid: number };
|
||||
type ToChannelProps = { gid?: string; curType?: string };
|
||||
|
||||
type ToChannelProps = { gid?: string; curType?: string; modelValue: boolean };
|
||||
type ToChannelEmits = (e: "update:modelValue", v: boolean) => void;
|
||||
const router = useRouter();
|
||||
const props = withDefaults(defineProps<ToChannelProps>(), { modelValue: false });
|
||||
const emits = defineEmits<ToChannelEmits>();
|
||||
const { recentNewsType } = storeToRefs(useAppStore());
|
||||
const channelList = TGConstant.BBS.CHANNELS;
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
const channelList = shallowRef<Array<ChannelItem>>();
|
||||
const props = defineProps<ToChannelProps>();
|
||||
const visible = defineModel<boolean>({ default: false });
|
||||
|
||||
onMounted(async () => {
|
||||
const allGames = await apiHubReq.game();
|
||||
channelList.value = allGames.map((i) => ({ icon: i.app_icon, title: i.name, gid: i.id }));
|
||||
});
|
||||
|
||||
async function toChannel(item: ToChannelItem): Promise<void> {
|
||||
if (props.gid === item.gid) {
|
||||
async function toChannel(item: ChannelItem): Promise<void> {
|
||||
if (props.gid === item.gid.toString()) {
|
||||
showSnackbar.warn("当前已经在该频道");
|
||||
return;
|
||||
}
|
||||
@@ -53,7 +53,7 @@ async function toChannel(item: ToChannelItem): Promise<void> {
|
||||
link = link.replace("{type}", "notice");
|
||||
recentNewsType.value = "notice";
|
||||
}
|
||||
await router.push(link);
|
||||
window.location.href = link;
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
@@ -107,24 +107,4 @@ async function toChannel(item: ToChannelItem): Promise<void> {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.toc-close {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.toc-close-btn {
|
||||
display: flex;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: var(--box-bg-1);
|
||||
color: var(--app-page-content);
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { getVersion } from "@tauri-apps/api/app";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
import TwoConvert from "./two-convert.vue";
|
||||
import TwoSource from "./two-source.vue";
|
||||
@@ -37,15 +37,11 @@ import TwoSource from "./two-source.vue";
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
import { parseHtmlText } from "@/utils/toolFunc.js";
|
||||
|
||||
type TwoMaterialProps = { modelValue: boolean; data: TGApp.App.Material.WikiItem };
|
||||
type TwoMaterialEmits = (e: "update:modelValue", v: boolean) => void;
|
||||
type TwoMaterialProps = { data: TGApp.App.Material.WikiItem };
|
||||
|
||||
const props = defineProps<TwoMaterialProps>();
|
||||
const emits = defineEmits<TwoMaterialEmits>();
|
||||
const visible = defineModel<boolean>();
|
||||
const version = ref<string>();
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
|
||||
onMounted(async () => (version.value = await getVersion()));
|
||||
|
||||
|
||||
@@ -66,7 +66,8 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { ref, toRaw, watch } from "vue";
|
||||
|
||||
export type SelectedCValue = {
|
||||
star: Array<number>;
|
||||
@@ -74,14 +75,8 @@ export type SelectedCValue = {
|
||||
elements: Array<string>;
|
||||
area: Array<string>;
|
||||
};
|
||||
type TwoSelectCProps = { modelValue: boolean; reset: boolean };
|
||||
type TwoSelectCEmits = {
|
||||
(e: "update:modelValue", v: boolean): void;
|
||||
(e: "update:reset", v: boolean): void;
|
||||
(e: "select-c", v: SelectedCValue): void;
|
||||
};
|
||||
type TwoSelectCEmits = (e: "select-c", v: SelectedCValue) => void;
|
||||
|
||||
const props = defineProps<TwoSelectCProps>();
|
||||
const emits = defineEmits<TwoSelectCEmits>();
|
||||
const selectStarList = [4, 5];
|
||||
const selectWeaponList = ["单手剑", "双手剑", "弓", "法器", "长柄武器"];
|
||||
@@ -93,24 +88,29 @@ const selectedStar = ref<Array<number>>(selectStarList);
|
||||
const selectedWeapon = ref<Array<string>>(selectWeaponList);
|
||||
const selectedElements = ref<Array<string>>(selectElementList);
|
||||
const selectedArea = ref<Array<string>>(selectAreaList);
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
const reset = computed<boolean>({
|
||||
get: () => props.reset,
|
||||
set: (v: boolean) => emits("update:reset", v),
|
||||
});
|
||||
const visible = defineModel<boolean>();
|
||||
const resetModel = defineModel<boolean>("reset");
|
||||
|
||||
watch(
|
||||
() => props.reset,
|
||||
(value) => {
|
||||
if (value) {
|
||||
() => resetModel.value,
|
||||
() => {
|
||||
if (resetModel.value) {
|
||||
if (
|
||||
toRaw(selectedStar.value) === selectStarList &&
|
||||
toRaw(selectedWeapon.value) === selectWeaponList &&
|
||||
toRaw(selectedElements.value) === selectElementList &&
|
||||
toRaw(selectedArea.value) === selectAreaList
|
||||
) {
|
||||
showSnackbar.warn("无需重置");
|
||||
resetModel.value = false;
|
||||
return;
|
||||
}
|
||||
selectedStar.value = selectStarList;
|
||||
selectedWeapon.value = selectWeaponList;
|
||||
selectedElements.value = selectElementList;
|
||||
selectedArea.value = selectAreaList;
|
||||
reset.value = false;
|
||||
resetModel.value = false;
|
||||
showSnackbar.success("已重置");
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -36,17 +36,12 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { ref, toRaw, watch } from "vue";
|
||||
|
||||
export type SelectedWValue = { star: Array<number>; weapon: Array<string> };
|
||||
type TwoSelectWProps = { modelValue: boolean; reset: boolean };
|
||||
type TwoSelectWEmits = {
|
||||
(e: "update:modelValue", value: boolean): void;
|
||||
(e: "update:reset", value: boolean): void;
|
||||
(e: "select-w", value: SelectedWValue): void;
|
||||
};
|
||||
export type SelectedWValue = { star: Array<number>; weapon: Array<string>; isReset: boolean };
|
||||
type TwoSelectWEmits = (e: "select-w", value: SelectedWValue) => void;
|
||||
|
||||
const props = defineProps<TwoSelectWProps>();
|
||||
const emits = defineEmits<TwoSelectWEmits>();
|
||||
|
||||
const selectStarList = [4, 5];
|
||||
@@ -54,29 +49,31 @@ const selectWeaponList = ["单手剑", "双手剑", "弓", "法器", "长柄武
|
||||
|
||||
const selectedStar = ref<Array<number>>(selectStarList);
|
||||
const selectedWeapon = ref<Array<string>>(selectWeaponList);
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
const reset = computed<boolean>({
|
||||
get: () => props.reset,
|
||||
set: (v) => emits("update:reset", v),
|
||||
});
|
||||
const visible = defineModel<boolean>();
|
||||
const resetModel = defineModel<boolean>("reset");
|
||||
|
||||
watch(
|
||||
() => props.reset,
|
||||
(value) => {
|
||||
if (value) {
|
||||
() => resetModel.value,
|
||||
() => {
|
||||
if (resetModel.value) {
|
||||
if (
|
||||
toRaw(selectedStar.value) === selectStarList &&
|
||||
toRaw(selectedWeapon.value) === selectWeaponList
|
||||
) {
|
||||
showSnackbar.warn("无需重置");
|
||||
resetModel.value = false;
|
||||
return;
|
||||
}
|
||||
selectedStar.value = selectStarList;
|
||||
selectedWeapon.value = selectWeaponList;
|
||||
reset.value = false;
|
||||
confirmSelect();
|
||||
resetModel.value = false;
|
||||
emits("select-w", { star: selectedStar.value, weapon: selectedWeapon.value, isReset: true });
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function confirmSelect(): void {
|
||||
emits("select-w", { star: selectedStar.value, weapon: selectedWeapon.value });
|
||||
emits("select-w", { star: selectedStar.value, weapon: selectedWeapon.value, isReset: false });
|
||||
visible.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
<slot name="left"></slot>
|
||||
<div class="tua-ao-box">
|
||||
<div class="tua-ao-top">
|
||||
<span class="tua-ao-click" @click="searchDirect(props.data.name)">
|
||||
<span class="tua-ao-click" title="查询" @click="searchDirect(props.data.name)">
|
||||
{{ props.data.name }}
|
||||
</span>
|
||||
<span>{{ props.data.description }}</span>
|
||||
<span class="tua-ao-click" title="分享" @click="share()">
|
||||
{{ props.data.description }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="tua-ao-mid-title">
|
||||
<span>所属系列:</span>
|
||||
@@ -53,32 +55,38 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import VpOverlaySearch from "@comp/viewPost/vp-overlay-search.vue";
|
||||
import { computed, ref } from "vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
import { AppAchievementSeriesData } from "@/data/index.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import { generateShareImg } from "@/utils/TGShare.js";
|
||||
|
||||
type ToAchiInfoProps = { modelValue: boolean; data: TGApp.Sqlite.Achievement.RenderAchi };
|
||||
type ToAchiInfoEmits = {
|
||||
(e: "update:modelValue", v: boolean): void;
|
||||
(e: "select-series", v: number): void;
|
||||
};
|
||||
type ToAchiInfoProps = { data: TGApp.Sqlite.Achievement.RenderAchi };
|
||||
type ToAchiInfoEmits = (e: "select-series", v: number) => void;
|
||||
|
||||
const props = defineProps<ToAchiInfoProps>();
|
||||
const emits = defineEmits<ToAchiInfoEmits>();
|
||||
const visible = defineModel<boolean>();
|
||||
const showSearch = ref<boolean>(false);
|
||||
const search = ref<string>();
|
||||
const visible = computed<boolean>({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emits("update:modelValue", v),
|
||||
});
|
||||
|
||||
async function searchDirect(word: string): Promise<void> {
|
||||
await TGLogger.Info(`[ToAchiInfo][${props.data.id}][Search] 查询 ${word}`);
|
||||
search.value = word;
|
||||
showSearch.value = true;
|
||||
}
|
||||
|
||||
async function share(): Promise<void> {
|
||||
const achiBox = document.querySelector<HTMLElement>(".tua-ao-box");
|
||||
if (achiBox === null) {
|
||||
showSnackbar.error("未找到成就详情");
|
||||
return;
|
||||
}
|
||||
const fileName = `【成就详情】【${props.data.id}】-${props.data.name}`;
|
||||
await generateShareImg(fileName, achiBox);
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tua-ao-container {
|
||||
|
||||
@@ -38,14 +38,11 @@ import { AppAchievementSeriesData } from "@/data/index.js";
|
||||
import { timestampToDate } from "@/utils/toolFunc.js";
|
||||
|
||||
type TuaAchiProps = { modelValue: TGApp.Sqlite.Achievement.RenderAchi };
|
||||
type TuaAchiEmits = {
|
||||
(e: "update:modelValue", data: TGApp.Sqlite.Achievement.RenderAchi): void;
|
||||
(e: "update:update", data: boolean): void;
|
||||
(e: "select-achi", data: TGApp.Sqlite.Achievement.RenderAchi): void;
|
||||
};
|
||||
type TuaAchiEmits = (e: "select-achi", data: TGApp.Sqlite.Achievement.RenderAchi) => void;
|
||||
|
||||
const props = defineProps<TuaAchiProps>();
|
||||
const emits = defineEmits<TuaAchiEmits>();
|
||||
const model = defineModel<TGApp.Sqlite.Achievement.RenderAchi>();
|
||||
const data = ref<TGApp.Sqlite.Achievement.RenderAchi>(toRaw(props.modelValue));
|
||||
|
||||
watch(
|
||||
@@ -69,7 +66,7 @@ async function setAchiStat(stat: boolean): Promise<void> {
|
||||
if (!stat) {
|
||||
data.value.isCompleted = false;
|
||||
await TSUserAchi.updateAchi(data.value);
|
||||
emits("update:modelValue", data.value);
|
||||
model.value = data.value;
|
||||
await event.emit("updateAchi", data.value.series);
|
||||
showSnackbar.success(`已将成就 ${data.value.name}(${data.value.id}) 状态设为未完成`);
|
||||
return;
|
||||
@@ -80,7 +77,7 @@ async function setAchiStat(stat: boolean): Promise<void> {
|
||||
return;
|
||||
}
|
||||
if (progress === undefined) progress = data.value.progress.toString();
|
||||
if (isNaN(Number(progress)) || progress === "0") {
|
||||
if (isNaN(Number(progress))) {
|
||||
showSnackbar.warn("请输入有效数字!");
|
||||
return;
|
||||
}
|
||||
@@ -90,7 +87,7 @@ async function setAchiStat(stat: boolean): Promise<void> {
|
||||
await TSUserAchi.updateAchi(data.value);
|
||||
await event.emit("updateAchi", data.value.series);
|
||||
showSnackbar.success(`已将成就 ${data.value.name}(${data.value.id}) 状态设为已完成`);
|
||||
emits("update:modelValue", data.value);
|
||||
model.value = data.value;
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
class="tua-dcc-item"
|
||||
:title="`${constellation.pos}命-${constellation.name}`"
|
||||
>
|
||||
<img :src="constellation.icon" alt="constellation" class="tua-dcc-icon" />
|
||||
<TMiImg :ori="true" :src="constellation.icon" alt="constellation" class="tua-dcc-icon" />
|
||||
<div v-if="!constellation.is_actived" class="tua-dcc-lock">
|
||||
<v-icon size="10px" color="var(--tgc-od-white)">mdi-lock</v-icon>
|
||||
</div>
|
||||
@@ -14,6 +14,8 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
|
||||
type TuaDcConstellationsProps = { modelValue: Array<TGApp.Game.Avatar.Constellation> };
|
||||
|
||||
const props = defineProps<TuaDcConstellationsProps>();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
v-if="props.modelValue === false"
|
||||
class="empty"
|
||||
/>
|
||||
<img :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
||||
<TMiImg :ori="true" :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
||||
</div>
|
||||
</div>
|
||||
<div class="tua-dcr-right">
|
||||
@@ -35,6 +35,7 @@
|
||||
:src="propMain.icon"
|
||||
alt="propMain"
|
||||
/>
|
||||
<v-icon v-else class="icon" size="14">mdi-adjust</v-icon>
|
||||
<span :style="getPropMainStyle()">
|
||||
{{ propMain !== false ? propMain.name : "未知属性" }}
|
||||
</span>
|
||||
@@ -44,6 +45,7 @@
|
||||
<div v-for="(prop, index) in propSubs" :key="index" class="tua-dcr-prop">
|
||||
<span class="tua-prop-sub">
|
||||
<img v-if="prop !== false && prop.icon !== ''" :src="prop.icon" alt="propSub" />
|
||||
<v-icon v-else class="icon" size="14">mdi-information-outline</v-icon>
|
||||
<span :style="getPropSubStyle(prop, props.recommend.sub_property_list)">
|
||||
{{ prop !== false ? prop.name : "未知属性" }}
|
||||
</span>
|
||||
@@ -57,6 +59,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import { computed } from "vue";
|
||||
|
||||
import { useUserStore } from "@/store/modules/user.js";
|
||||
@@ -142,6 +145,7 @@ function getPropSubStyle(
|
||||
background: rgb(0 0 0 / 20%);
|
||||
color: var(--tgc-white-1);
|
||||
font-size: 12px;
|
||||
row-gap: 5px;
|
||||
text-shadow: 0 0 5px rgb(0 0 0 / 50%);
|
||||
}
|
||||
|
||||
@@ -185,8 +189,11 @@ function getPropSubStyle(
|
||||
|
||||
.tua-dcr-icon {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
@@ -235,6 +242,7 @@ function getPropSubStyle(
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid rgb(255 255 255 / 20%);
|
||||
column-gap: 5px;
|
||||
font-family: var(--font-title);
|
||||
|
||||
@@ -242,6 +250,7 @@ function getPropSubStyle(
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 5px;
|
||||
}
|
||||
|
||||
img {
|
||||
@@ -269,6 +278,10 @@ function getPropSubStyle(
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
.tua-prop-time {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
:title="skill.name"
|
||||
class="tua-dct-item"
|
||||
>
|
||||
<img :src="skill.icon" alt="talent" class="tua-dct-icon" />
|
||||
<TMiImg :ori="true" :src="skill.icon" alt="talent" class="tua-dct-icon" />
|
||||
<div v-if="!skill.is_unlock" class="tua-dct-lock">
|
||||
<v-icon size="10px" color="var(--tgc-od-white)">mdi-lock</v-icon>
|
||||
</div>
|
||||
@@ -17,6 +17,8 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
|
||||
type TuaDcTalentsProps = { modelValue: Array<TGApp.Game.Avatar.Skill> };
|
||||
|
||||
const props = defineProps<TuaDcTalentsProps>();
|
||||
|
||||