Compare commits

..

130 Commits

Author SHA1 Message Date
目棃
da17f8cd03 🚀 v0.7.3 2025-04-11 22:22:05 +08:00
目棃
4b77c031c2 🚸 更新系列参数处理逻辑 2025-04-11 22:18:15 +08:00
目棃
3f3e941b68 🍱 更新卡池信息 2025-04-11 20:19:18 +08:00
目棃
2502c27ee5 💄 兑换码浮窗样式迭代 2025-04-11 20:06:09 +08:00
目棃
41fb2a43f7 ⬆️ 更新依赖 2025-04-09 15:47:36 +08:00
目棃
b7c49ce09b 🎨 改进代码结构 2025-04-09 15:45:29 +08:00
目棃
43f9e432cc 🚸 重构日期切换逻辑 2025-04-05 19:30:53 +08:00
目棃
74217e679e ⬆️ 更新依赖 2025-04-05 19:30:17 +08:00
目棃
06a57c9bcf 💄 添加图片数数据 2025-04-01 15:08:16 +08:00
目棃
1ce8c1fddf 💄 优化成就信息展示和样式 2025-04-01 14:54:29 +08:00
目棃
a1cd7ff840 💄 背景色同步 2025-04-01 14:29:51 +08:00
目棃
fce56dcf55 🔧 更新权限配置 2025-04-01 14:20:54 +08:00
目棃
7cf4516865 💄 更新配置文件和优化图片下载逻辑 2025-04-01 14:08:50 +08:00
目棃
01009b36eb ⬆️ 更新依赖 2025-04-01 13:40:55 +08:00
目棃
79067d6f77 🐛 修复显示异常 2025-04-01 13:39:03 +08:00
目棃
978c9c7778 💄 优化角色与武器信息展示 2025-04-01 10:07:30 +08:00
目棃
29542a737e 💄 优化角色信息展示与样式 2025-03-31 16:14:05 +08:00
目棃
0016ec1fc1 🚸 更新Yae链接 2025-03-31 15:55:02 +08:00
目棃
61a89348d1 🎨 优化逻辑 2025-03-31 15:52:09 +08:00
目棃
1c16bfc29a 💄 添加滤镜过渡效果 2025-03-31 15:48:15 +08:00
目棃
454b94f401 🚸 调整满好感区分 2025-03-31 15:37:00 +08:00
目棃
da6a29c5ac 🚸 提供Yae入口 2025-03-31 15:33:15 +08:00
目棃
40d46f41c3 🚸 成就系列未完成/完成区分 2025-03-31 15:24:02 +08:00
目棃
d79de499cf 🚸 显式成就隐藏 2025-03-31 14:52:39 +08:00
目棃
d11d4fe803 💄 调整触发dom 2025-03-31 14:47:04 +08:00
目棃
121e29ad4f 💄 pendant 禁止裁切 2025-03-31 11:51:53 +08:00
目棃
215f0c6500 ♻️ 重构传递数据 2025-03-31 11:49:44 +08:00
目棃
fd34b66148 🚸 select-mode下阻止所有点击 2025-03-31 11:28:26 +08:00
目棃
c154381c3a 🚸 调整层级 2025-03-28 20:03:52 +08:00
目棃
960a3442ff 🚸 调整hint 2025-03-28 14:45:22 +08:00
目棃
ff66dfca30 💄 调整层级 2025-03-28 14:36:35 +08:00
目棃
ef9469643e 💄 use v-icon instead of v-btn to disable active shadow 2025-03-28 14:20:01 +08:00
目棃
b61d235221 💄 调整回复浮窗样式 2025-03-28 14:15:44 +08:00
目棃
400a501f30 💄 调整通用backupText组件样式 2025-03-28 13:50:20 +08:00
目棃
a63edd81bd 🚸 支持其他分区兑换码获取 2025-03-28 13:35:12 +08:00
目棃
3bd1853008 存储分区信息 2025-03-28 12:02:28 +08:00
目棃
1d8e7ec35d 🧪 测试获取合集信息失败 2025-03-28 11:10:15 +08:00
目棃
211f689426 ⬆️ 更新依赖 2025-03-28 10:23:19 +08:00
目棃
89a79dc968 🚀 v0.7.2 2025-03-27 20:47:38 +08:00
目棃
e1653bdfb0 🍱 更新卡池数据 2025-03-27 20:45:27 +08:00
目棃
8af5136a9c 🚸 调整保存hint 2025-03-27 18:00:47 +08:00
目棃
a8694104a9 🚸 查询时重置选中成就系列 2025-03-27 15:53:01 +08:00
目棃
570cbb5fed 🍱 补充遗漏数据 2025-03-27 15:44:45 +08:00
目棃
dd339285cb 🎨 代码格式化 2025-03-27 14:53:58 +08:00
目棃
31311510ef 🍱 更新5.5成就资源
close #147
2025-03-27 14:43:30 +08:00
目棃
f367e797a9 🍱 更新5.5角色&武器&素材日历
#147
2025-03-27 14:30:08 +08:00
目棃
082fe9dfab ♻️ 更新5.5名片资源,重构名片数据结构
#147
2025-03-27 11:06:16 +08:00
目棃
3769859611 🍱 更新5.5材料资源
#147
2025-03-27 09:57:24 +08:00
目棃
928c71ead8 🍱 更新5.5部分资源,适配新版本返回数据
#147
2025-03-27 09:53:39 +08:00
目棃
39f2a7dc31 💄 调整mention组件样式 2025-03-26 17:50:05 +08:00
目棃
1d637705b7 获取用户关注动态 2025-03-26 17:31:10 +08:00
目棃
9e2eb80a21 🌱 获取用户关注动态 2025-03-26 16:58:33 +08:00
目棃
927d4545a1 🚸 更新图片下载提示信息 2025-03-26 16:40:45 +08:00
目棃
45217d423a ⬆️ 更新依赖 2025-03-26 09:21:53 +08:00
目棃
d430cd4672 🚸 优化自定义表情处理 2025-03-25 14:08:33 +08:00
目棃
d15d78b73f 🚸 调整触发dom 2025-03-25 11:25:48 +08:00
目棃
00fdcc79d6 ️ use sass-embedded 2025-03-25 10:26:04 +08:00
目棃
20438106a4 💄 调整UI 2025-03-24 09:14:19 +08:00
目棃
f92684c7b3 ⬆️ 更新依赖 2025-03-21 10:45:35 +08:00
目棃
3228b6a305 💄 调整UI 2025-03-21 10:28:20 +08:00
目棃
a47afbf2e0 💄 调整UI 2025-03-20 16:52:41 +08:00
目棃
f4a0165e81 💄 调整UI 2025-03-20 10:32:31 +08:00
目棃
31874e07c4 💄 调整UI 2025-03-19 17:52:06 +08:00
目棃
c696d3b51d 💄 调整UI 2025-03-19 17:06:43 +08:00
目棃
8a2a3f5279 💄 调整角色页面UI 2025-03-19 16:50:09 +08:00
目棃
a2f68b92c7 💄 调整战绩页面UI 2025-03-19 16:20:40 +08:00
目棃
96dfec969c 💄 调整成就页面UI 2025-03-19 14:59:24 +08:00
目棃
1b5ddf9b3f 💄 调整select 2025-03-19 10:45:49 +08:00
目棃
4dc273662d 🚸 调整hint 2025-03-19 09:16:16 +08:00
目棃
83d52c6f40 ♻️ 迁移数据而非清空 2025-03-19 09:12:39 +08:00
目棃
0aabd2fa80 🚨 fix qodana warn 2025-03-18 15:39:19 +08:00
目棃
01dc6a6ea7 ♻️ use opener instead of window.open/shell 2025-03-18 14:52:00 +08:00
目棃
765c860473 💄 add time info 2025-03-18 14:04:52 +08:00
目棃
b276b04f23 🏷️ typo 2025-03-18 13:42:21 +08:00
目棃
e308e4789c 🐛 fix gt call err 2025-03-18 09:28:33 +08:00
目棃
522add2441 ♻️ erasableSyntaxOnly 2025-03-17 17:58:15 +08:00
目棃
08f74ce6a0 🚸 hide copy on gif overlay 2025-03-17 17:32:59 +08:00
目棃
3be703d329 🚨 fix command warn 2025-03-17 16:14:52 +08:00
目棃
a3e42b63e6 💄 调整样式 2025-03-17 15:07:42 +08:00
目棃
4ef3313eb1 ⬆️ 更新依赖 2025-03-17 09:33:34 +08:00
目棃
a22aac457a 🚸 采用原图 2025-03-14 20:39:53 +08:00
目棃
8a2524d6b1 🙈 ignore gen json schema 2025-03-14 11:32:00 +08:00
目棃
b504f043b4 comboToken 2025-03-12 17:47:04 +08:00
目棃
f842975f21 💄 调整UI 2025-03-12 16:00:10 +08:00
目棃
577f86248e 🚸 首页卡池点击唤起子窗口 2025-03-12 14:45:29 +08:00
目棃
c3246e95ce 加载指定用户帖子 2025-03-12 11:06:12 +08:00
目棃
e3fb88fd44 🎨 仅刷新部分账户 2025-03-11 17:15:20 +08:00
目棃
0f6fe11c75 🔥 移除无用sql 2025-03-11 11:00:04 +08:00
目棃
9d212a5b87 🚸 支持删除无用账户,重构游戏账号表格 2025-03-11 10:54:34 +08:00
目棃
c0d9830670 ♻️ 调整结构 2025-03-11 10:28:17 +08:00
目棃
c577a6f1ea 🚸 调整Hint 2025-03-10 18:00:20 +08:00
目棃
0e6210ee8e 💄 调整偏移 2025-03-10 17:43:26 +08:00
目棃
adfe55054e 🚨 修复devtool警告 2025-03-10 17:31:33 +08:00
目棃
fecad43dec 🚸 投票显示相对进度 2025-03-10 17:14:13 +08:00
目棃
4c93bb0d42 🐛 修正判断逻辑 2025-03-10 16:52:08 +08:00
目棃
667aa6fb94 🐛 修复扫码登录异常 2025-03-10 15:12:05 +08:00
目棃
a1a5271603 💄 替换icon 2025-03-10 14:57:38 +08:00
目棃
4a646c2c4e 🎨 优化链接识别 2025-03-10 14:54:40 +08:00
目棃
48b976ac84 🚸 识别ys.mihoyo.com 2025-03-10 14:26:31 +08:00
目棃
d7250ce13c 🌱 游戏签到 2025-03-10 14:18:23 +08:00
目棃
1cad9891dc 🚸 一些优化 2025-03-10 13:39:50 +08:00
目棃
6302f171e9 🎨 记录所有账号但只显示原神 2025-03-09 22:12:28 +08:00
目棃
bb67da034b 🚸 优化逻辑 2025-03-09 21:54:48 +08:00
目棃
804b735e95 ✏️ TakumiApi → takumiReq 2025-03-09 21:48:39 +08:00
目棃
e6904e14b5 🚸 切换账户时清空数据 2025-03-09 21:32:11 +08:00
目棃
b4954bd74c 💄 显示连续执行天数 2025-03-08 23:12:11 +08:00
目棃
8f9006b9f4 👔 调整判断逻辑 2025-03-08 22:51:25 +08:00
目棃
fba7a6c088 🚸 移除每次路由变化引起的居中 2025-03-08 19:19:31 +08:00
目棃
0fdbea55eb 💄 调整标题占据空间 2025-03-08 19:04:46 +08:00
dependabot[bot]
b93ae791f2 Bump ring from 0.17.11 to 0.17.13 in /src-tauri (#146)
Bumps [ring](https://github.com/briansmith/ring) from 0.17.11 to 0.17.13.
- [Changelog](https://github.com/briansmith/ring/blob/main/RELEASES.md)
- [Commits](https://github.com/briansmith/ring/commits)

---
updated-dependencies:
- dependency-name: ring
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-08 17:50:15 +08:00
目棃
b6b0b90ae8 👔 调整判断逻辑 2025-03-08 17:48:47 +08:00
目棃
7e7fb318ea 💄 调整抽奖UI 2025-03-08 17:37:20 +08:00
目棃
3a102f31be 🚸 一些调整 2025-03-08 17:01:25 +08:00
目棃
9dba531bb2 💄 调整深色模式下帖子卡片样式 2025-03-08 16:48:43 +08:00
目棃
6b5959ff76 🎨 调整帖子卡片点击处理 2025-03-08 16:41:54 +08:00
目棃
d8267cbf7b 💄 调整整体滚动条样式 2025-03-08 16:30:33 +08:00
目棃
ac4d2a319f 🚸 即时响应页面适配 2025-03-08 16:06:06 +08:00
目棃
214dec29d8 ♻️ 卡池&活动组件重构 2025-03-08 15:39:27 +08:00
目棃
fcb16c9299 💄 调整UI 2025-03-08 11:36:24 +08:00
目棃
37ea45f0c1 💄 组件复用 2025-03-08 11:31:27 +08:00
目棃
dafa153b62 🌱 获取合集信息 2025-03-08 11:18:09 +08:00
目棃
9b152eb59f 💄 渲染推荐理由 2025-03-08 10:28:52 +08:00
目棃
d5aaecbf72 ♻️ 类型迁移&重构 2025-03-08 09:53:25 +08:00
目棃
ce5a88954a ♻️ 请求重构 2025-03-07 17:53:35 +08:00
目棃
fee1872b46 🚸 处理下线villaCard渲染 2025-03-07 15:54:57 +08:00
目棃
dd3ce101a6 🎨 重构滚动高度计算 2025-03-07 15:13:20 +08:00
目棃
d32d7b69f1 👽️ 接口适配
https://github.com/Womsxd/MihoyoBBSTools/issues/237
2025-03-07 11:13:12 +08:00
目棃
11a6157af0 ⬆️ 更新依赖 2025-03-06 16:23:27 +08:00
目棃
1a40f88027 🐛 修复参数调用异常 2025-03-06 15:59:09 +08:00
目棃
81fc5f9dca 🔧 参考最新项目修改配置 2025-03-06 15:56:08 +08:00
263 changed files with 11452 additions and 28421 deletions

View File

@@ -55,7 +55,7 @@ jobs:
- name: setup pnpm
uses: pnpm/action-setup@v2
with:
version: 10.2.0
version: 10.7.0
- name: Install frontend dependencies
run: pnpm install

View File

@@ -16,7 +16,7 @@ jobs:
- name: setup pnpm
uses: pnpm/action-setup@v2
with:
version: 9.15.0
version: 10.7.0
- name: Install dependencies
run: pnpm install --no-frozen-lockfile
- name: "Qodana Scan"

View File

@@ -2,12 +2,52 @@
Author: 目棃
Description: CHANGELOG
Date: 2024-10-09
Update: 2025-03-06
Update: 2025-04-11
---
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2024-10-09 15:51:43`
>
> 更新于 `2025-03-06 10:01:22`
> 更新于 `2025-04-11 22:18:50`
## [0.7.3](https://github.com/BTMuli/TeyvatGuide/releases/v0.7.3) (2025-04-11)
- 🍱 更新下半卡池信息
- 💄 兑换码浮窗样式迭代
- 💄 帖子卡片添加图片数数据
- 💄 优化成就信息展示和样式
- 💄 帖子图片浮窗背景色同步
- 💄 调整通用backupText组件样式
- 💄 调整回复浮窗样式
- 💄 角色详情调整满好感区分
- 💄 优化角色武器Wiki样式
- 🚸 重构素材日历日期切换逻辑
- 🚸 优化图片下载路径&提示
- 🚸 支持其他分区兑换码获取
- 🚸 收藏页select-mode下阻止所有点击
## [0.7.2](https://github.com/BTMuli/TeyvatGuide/releases/v0.7.2) (2025-03-27)
- 🍱 更新5.5资源 [`#147`](https://github.com/BTMuli/TeyvatGuide/issues/147)
- ✨ 新增游戏签到脚本
- ✨ 扫码登录新增游戏登录方式
- ✨ 获取登录用户关注帖子
- 🐛 修复获取深渊数据概览异常
- 🐛 修复扫码登录异常
- ♻️ 首页卡池&活动组件重构
- ♻️ 重构游戏账号数据库
- ♻️ 调用浏览器而非webview2打开外部链接
- 💄 帖子卡片UI调整增加时间&推荐理由数据
- 💄 调整整体滚动条样式
- 💄 调整抽奖UI
- 💄 米游币脚本显示连续执行天数
- 💄 帖子投票组件进度条显示相对进度(以最高数为基准)
- 💄 调整多页面UI
- 🎨 重构合集浮窗滚动高度计算
- 🎨 调整帖子卡片点击处理
- 🚸 处理下线villaCard渲染
- 🚸 即时响应页面适配
- 🚸 完善部分请求防抖处理
- 🚸 链接识别`ys.mihoyo.com`
## [0.7.1](https://github.com/BTMuli/TeyvatGuide/releases/v0.7.1) (2025-03-06)

View File

@@ -2,12 +2,12 @@
Author: 目棃
Description: 说明文档
Date: 2023-03-05
Update: 2025-02-28
Update: 2025-03-31
---
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-03-05 14:41:55`
>
> 更新于 `2025-02-28 10:54:28`
> 更新于 `2025-03-31 15:53:10`
![](https://img.shields.io/github/last-commit/BTMuli/TeyvatGuide?style=for-the-badge) ![](https://img.shields.io/github/commits-since/BTMuli/TeyvatGuide/latest?include_prereleases&style=for-the-badge)
@@ -50,7 +50,7 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
- [x] 米游社官方帖获取(支持通过 ID 获取)
- [x] 米游社各分区帖子获取(支持通过 ID 获取)
- [x] 米游社话题帖子获取(通过话题点击跳转)
- [x] 成就管理UIAF v1.1),支持 [`YaeAchievement`](https://github.com/HolographicHat/YaeAchievement) 导入
- [x] 成就管理UIAF v1.1),支持 [`Yae`](https://github.com/HolographicHat/Yae) 导入
- [x] 祈愿管理UIGF v3.0UIGF v4.0
- [x] 留影叙佳期画片查看
- [x] 帖子收藏
@@ -66,7 +66,9 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
- [x] 真境剧诗数据获取
- [x] 祈愿数据获取(近一年)
- [x] 用户收藏帖子获取
- [x] 一键完成米游币每日任务 **需要验证码登录**
- [x] 用户关注帖子获取
- [x] 一键完成米游币每日任务
- [x] 一键完成游戏签到
- Wiki 功能:
@@ -77,6 +79,7 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
- [x] 材料图鉴
- 应用功能:
- [x] 浅色/深色主题切换
- [x] 米游社 JSBridge

View File

@@ -5,7 +5,6 @@
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TeyvatGuide</title>
<script src="https://static.geetest.com/v4/gt4.js"></script>
</head>
<body>

View File

@@ -1,18 +1,19 @@
{
"name": "teyvatguide",
"version": "0.7.1",
"version": "0.7.3",
"description": "Game Tool for GenshinImpact player",
"private": true,
"packageManager": "pnpm@10.5.2",
"packageManager": "pnpm@10.8.0",
"type": "module",
"scripts": {
"build": "tauri build",
"debug": "tauri build --debug",
"dev": "tauri dev --exit-on-panic",
"eslint:pre": "pnpx @eslint/config-inspector@latest",
"oxlint": "oxlint",
"lint": "concurrently \"pnpm:lint:*(!fix)\"",
"lint:fix": "concurrently \"pnpm:lint:*:fix\"",
"lint:vue": "vue-tsc --noEmit",
"lint-vue": "vue-tsc --noEmit",
"lint:code": "eslint .",
"lint:code:fix": "eslint . --fix",
"lint:style": "stylelint \"src/**/*.{vue,css,scss}\" -f verbose",
@@ -69,15 +70,16 @@
},
"dependencies": {
"@mdi/font": "7.4.47",
"@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.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/api": "^2.4.1",
"@tauri-apps/plugin-deep-link": "^2.2.1",
"@tauri-apps/plugin-dialog": "^2.2.1",
"@tauri-apps/plugin-fs": "^2.2.1",
"@tauri-apps/plugin-http": "^2.4.3",
"@tauri-apps/plugin-log": "^2.3.1",
"@tauri-apps/plugin-opener": "^2.2.6",
"@tauri-apps/plugin-os": "^2.2.1",
"@tauri-apps/plugin-process": "^2.2.1",
"@tauri-apps/plugin-shell": "^2.2.1",
"@tauri-apps/plugin-sql": "^2.2.0",
"ajv": "^8.17.1",
"artplayer": "^5.2.2",
@@ -90,43 +92,42 @@
"pinia": "^3.0.1",
"pinia-plugin-persistedstate": "^4.2.0",
"qrcode.vue": "^3.6.0",
"sass": "^1.85.1",
"sass-loader": "^16.0.5",
"sass-embedded": "^1.86.3",
"uuid": "^11.1.0",
"vue": "^3.5.13",
"vue-echarts": "^7.0.3",
"vue-json-pretty": "^2.4.0",
"vue-router": "^4.5.0",
"vuetify": "^3.7.14",
"vuetify": "^3.8.1",
"wcag-color": "^1.1.1",
"xml-js": "^1.6.11"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.0",
"@eslint/js": "^9.21.0",
"@tauri-apps/cli": "2.3.1",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.24.0",
"@tauri-apps/cli": "2.4.1",
"@types/color-convert": "^2.0.4",
"@types/fs-extra": "^11.0.4",
"@types/js-md5": "^0.7.2",
"@types/node": "^22.13.7",
"@types/node": "^22.14.0",
"@types/uuid": "^10.0.0",
"@typescript-eslint/parser": "^8.25.0",
"@vitejs/plugin-vue": "^5.2.1",
"@typescript-eslint/parser": "^8.29.1",
"@vitejs/plugin-vue": "^5.2.3",
"concurrently": "^9.1.2",
"eslint": "^9.21.0",
"eslint": "^9.24.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsonc": "^2.19.1",
"eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-vue": "^9.32.0",
"eslint-plugin-jsonc": "^2.20.0",
"eslint-plugin-prettier": "^5.2.6",
"eslint-plugin-vue": "^10.0.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.4.3",
"oxlint": "^0.15.12",
"prettier": "3.5.2",
"stylelint": "^16.15.0",
"lint-staged": "^15.5.0",
"oxlint": "^0.16.5",
"prettier": "3.5.3",
"stylelint": "^16.18.0",
"stylelint-config-idiomatic-order": "^10.0.0",
"stylelint-config-standard-vue": "^1.0.0",
"stylelint-declaration-block-no-ignored-properties": "^2.8.0",
@@ -135,13 +136,13 @@
"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",
"typescript": "^5.8.3",
"typescript-eslint": "^8.29.1",
"vite": "^6.2.5",
"vite-plugin-vue-devtools": "^7.7.2",
"vite-plugin-vuetify": "^2.1.0",
"vue-eslint-parser": "^9.4.3",
"vue-tsc": "^2.2.4",
"vite-plugin-vuetify": "^2.1.1",
"vue-eslint-parser": "^10.1.3",
"vue-tsc": "^2.2.8",
"yaml-eslint-parser": "^1.3.0"
}
}

3047
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -2,3 +2,6 @@
# will have compiled files and executables
/target/
# Generated by Tauri
# will have schema files for capabilities auto-completion
/gen/schemas

1188
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package]
name = "TeyvatGuide"
version = "0.7.1"
version = "0.7.3"
description = "Game Tool for Genshin Impact player"
authors = ["BTMuli <bt-muli@outlook.com>"]
license = "MIT"
@@ -9,16 +9,23 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
# The `_lib` suffix may seem redundant, but it is necessary
# to make the lib name unique and wouldn't conflict with the bin name.
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
name = "teyvat_guide_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2.0.6", features = [] }
tauri-build = { version = "2.1.1", features = [] }
[dependencies]
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"
log = "0.4.27"
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
tauri = { version = "2.4.1", features = [] }
tauri-utils = "2.3.1"
url = "2.5.4"
walkdir = "2.5.0"
@@ -48,6 +55,11 @@ features = ["unsafe-headers"]
git = "ssh://git@github.com/tauri-apps/plugins-workspace.git"
branch = "v2"
# opener 插件
[dependencies.tauri-plugin-opener]
git = "ssh://git@github.com/tauri-apps/plugins-workspace.git"
branch = "v2"
# os 插件
[dependencies.tauri-plugin-os]
git = "ssh://git@github.com/tauri-apps/plugins-workspace.git"
@@ -73,8 +85,3 @@ branch = "v2"
git = "ssh://git@github.com/tauri-apps/plugins-workspace.git"
branch = "v2"
features = ["sqlite"]
[features]
# this feature is used for production builds or when `devPath` points to the filesystem
# DO NOT REMOVE!!
custom-protocol = ["tauri/custom-protocol"]

View File

@@ -21,6 +21,7 @@
"core:window:allow-center",
"core:window:allow-close",
"core:window:allow-destroy",
"core:window:allow-set-always-on-top",
"core:window:allow-set-size",
"core:window:allow-set-title",
"core:window:allow-set-fullscreen",

View File

@@ -14,6 +14,7 @@
"core:window:default",
"core:path:allow-resolve-directory",
"core:path:default",
"opener:default",
{ "identifier": "fs:allow-exists", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-mkdir", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-read-dir", "allow": [{ "path": "**" }] },

View File

@@ -4,35 +4,36 @@
"description": "Capability for the sub window",
"windows": ["Sub_window"],
"permissions": [
"core:app:allow-version",
"core:app:default",
"dialog:allow-save",
"core:app:allow-version",
"dialog:default",
"core:event:allow-listen",
"dialog:allow-save",
"core:event:default",
"fs:default",
"http:allow-fetch",
"log:allow-log",
"log:default",
"core:path:allow-resolve-directory",
"core:event:allow-listen",
"core:path:default",
"shell:allow-open",
"shell:default",
"sql:allow-load",
"sql:allow-execute",
"sql:default",
"core:webview:allow-set-webview-zoom",
"core:path:allow-resolve-directory",
"core:webview:default",
"core:webview:allow-set-webview-zoom",
"core:window:default",
"core:window:allow-center",
"core:window:allow-close",
"core:window:allow-destroy",
"core:window:allow-set-size",
"core:window:allow-set-title",
"core:window:allow-set-always-on-top",
"core:window:allow-set-focus",
"core:window:allow-set-fullscreen",
"core:window:allow-set-size",
"core:window:allow-set-title",
"core:window:allow-show",
"core:window:allow-set-always-on-top",
"core:window:default",
"fs:default",
"http:allow-fetch",
"log:default",
"log:allow-log",
"opener:default",
"shell:default",
"shell:allow-open",
"sql:default",
"sql:allow-execute",
"sql:allow-load",
{ "identifier": "fs:allow-exists", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-mkdir", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-read-dir", "allow": [{ "path": "**" }] },
@@ -40,6 +41,7 @@
{ "identifier": "fs:allow-remove", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-write-file", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-write-text-file", "allow": [{ "path": "**" }] },
{ "identifier": "opener:allow-open-path", "allow": [{ "path": "**" }] },
{
"identifier": "http:default",
"allow": [

View File

@@ -4,39 +4,40 @@
"description": "Capability for the main window",
"windows": ["TeyvatGuide"],
"permissions": [
"core:app:allow-version",
"core:app:default",
"dialog:allow-save",
"dialog:default",
"core:event:allow-listen",
"core:app:allow-version",
"core:event:default",
"fs:default",
"http:allow-fetch",
"log:allow-log",
"log:default",
"core:path:allow-resolve-directory",
"core:event:allow-listen",
"core:path:default",
"process:allow-exit",
"process:default",
"shell:allow-execute",
"shell:allow-open",
"shell:default",
"sql:allow-load",
"sql:allow-execute",
"sql:default",
"core:path:allow-resolve-directory",
"core:webview:default",
"core:webview:allow-create-webview-window",
"core:webview:allow-set-webview-zoom",
"core:webview:default",
"core:window:default",
"core:window:allow-center",
"core:window:allow-close",
"core:window:allow-destroy",
"core:window:allow-set-size",
"core:window:default",
"core:window:allow-is-minimized",
"core:window:allow-set-title",
"core:window:allow-set-focus",
"core:window:allow-set-size",
"core:window:allow-set-title",
"core:window:allow-show",
"core:window:allow-unminimize",
"dialog:default",
"dialog:allow-save",
"fs:default",
"http:allow-fetch",
"log:default",
"log:allow-log",
"opener:default",
"process:default",
"process:allow-exit",
"shell:default",
"shell:allow-open",
"shell:allow-execute",
"sql:default",
"sql:allow-load",
"sql:allow-execute",
{ "identifier": "fs:allow-exists", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-mkdir", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-read-dir", "allow": [{ "path": "**" }] },
@@ -44,6 +45,7 @@
{ "identifier": "fs:allow-remove", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-write-file", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-write-text-file", "allow": [{ "path": "**" }] },
{ "identifier": "opener:allow-open-path", "allow": [{ "path": "**" }] },
{
"identifier": "http:default",
"allow": [
@@ -55,11 +57,7 @@
},
{
"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 }
]
"allow": [{ "name": "exec-sh", "cmd": "powershell", "args": true }]
}
],
"platforms": ["windows", "macOS"]

File diff suppressed because it is too large Load Diff

View File

@@ -1,201 +0,0 @@
{
"DevJson": {
"identifier": "DevJson",
"description": "Capability for the dev json window",
"local": true,
"windows": ["Dev_JSON"],
"permissions": [
"core:app:allow-version",
"core:app:default",
"core:event:allow-listen",
"core:event:default",
"http:allow-fetch",
"log:allow-log",
"log:default",
"core:path:allow-resolve-directory",
"core:path:default",
"sql:allow-load",
"sql:allow-execute",
"sql:default",
"core:webview:allow-set-webview-zoom",
"core:webview:default",
"core:window:allow-center",
"core:window:allow-close",
"core:window:allow-destroy",
"core:window:allow-set-size",
"core:window:allow-set-title",
"core:window:allow-set-fullscreen",
"core:window:allow-show",
"core:window:default",
{
"identifier": "http:default",
"allow": [
{ "url": "https://*.miyoushe.com/*" },
{ "url": "https://*.mihoyo.com/*" },
{ "url": "https://*.hoyoverse.com/*" }
]
}
],
"platforms": ["windows", "macOS"]
},
"Mys": {
"identifier": "Mys",
"description": "Capability for the mys client window",
"remote": {
"urls": ["https://*.mihoyo.com/*", "https://*.miyoushe.com/*", "https://*.genshinnet.com/*"]
},
"local": true,
"windows": ["mhy_client"],
"permissions": [
"dialog:allow-message",
"dialog:default",
"core:event:allow-emit",
"http:allow-fetch",
"core:webview:allow-set-webview-zoom",
"core:webview:default",
"core:window:allow-center",
"core:window:default",
"core:path:allow-resolve-directory",
"core:path:default",
{ "identifier": "fs:allow-exists", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-mkdir", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-read-dir", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-read-text-file", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-remove", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-write-file", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-write-text-file", "allow": [{ "path": "**" }] },
{
"identifier": "http:default",
"allow": [
{ "url": "https://*.miyoushe.com/*" },
{ "url": "https://*.mihoyo.com/*" },
{ "url": "https://*.genshinnet.com/*" }
]
}
],
"platforms": ["windows", "macOS"]
},
"SubWindow": {
"identifier": "SubWindow",
"description": "Capability for the sub window",
"local": true,
"windows": ["Sub_window"],
"permissions": [
"core:app:allow-version",
"core:app:default",
"dialog:allow-save",
"dialog:default",
"core:event:allow-listen",
"core:event:default",
"fs:default",
"http:allow-fetch",
"log:allow-log",
"log:default",
"core:path:allow-resolve-directory",
"core:path:default",
"shell:allow-open",
"shell:default",
"sql:allow-load",
"sql:allow-execute",
"sql:default",
"core:webview:allow-set-webview-zoom",
"core:webview:default",
"core:window:allow-center",
"core:window:allow-close",
"core:window:allow-destroy",
"core:window:allow-set-size",
"core:window:allow-set-title",
"core:window:allow-set-focus",
"core:window:allow-set-fullscreen",
"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": "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/*" }
]
}
],
"platforms": ["windows", "macOS"]
},
"TeyvatGuide": {
"identifier": "TeyvatGuide",
"description": "Capability for the main window",
"local": true,
"windows": ["TeyvatGuide"],
"permissions": [
"core:app:allow-version",
"core:app:default",
"dialog:allow-save",
"dialog:default",
"core:event:allow-listen",
"core:event:default",
"fs:default",
"http:allow-fetch",
"log:allow-log",
"log:default",
"core:path:allow-resolve-directory",
"core:path:default",
"process:allow-exit",
"process:default",
"shell:allow-execute",
"shell:allow-open",
"shell:default",
"sql:allow-load",
"sql:allow-execute",
"sql:default",
"core:webview:allow-create-webview-window",
"core:webview:allow-set-webview-zoom",
"core:webview:default",
"core:window:allow-center",
"core:window:allow-close",
"core:window:allow-destroy",
"core:window:allow-set-size",
"core:window:default",
"core:window:allow-is-minimized",
"core:window:allow-set-title",
"core:window:allow-set-focus",
"core:window:allow-show",
"core:window:allow-unminimize",
{ "identifier": "fs:allow-exists", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-mkdir", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-read-dir", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-read-text-file", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-remove", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-write-file", "allow": [{ "path": "**" }] },
{ "identifier": "fs:allow-write-text-file", "allow": [{ "path": "**" }] },
{
"identifier": "http:default",
"allow": [
{ "url": "https://*.miyoushe.com/*" },
{ "url": "https://*.mihoyo.com/*" },
{ "url": "https://homa.snapgenshin.com/*" },
{ "url": "https://*.hoyoverse.com/*" }
]
},
{
"identifier": "shell:allow-execute",
"allow": [
{ "args": true, "cmd": "explorer", "name": "win_open" },
{ "args": true, "cmd": "open", "name": "mac_open" },
{ "args": true, "cmd": "powershell", "name": "exec-sh" }
]
}
],
"platforms": ["windows", "macOS"]
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
//! @file src/client/mod.rs
//! @desc 客户端模块,负责操作米游社客户端
//! @since Beta v0.7.0
//! @since Beta v0.7.3
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.82.0";
static BBS_VERSION: &'static str = "2.85.1";
#[tauri::command]
pub async fn create_mhy_client(handle: AppHandle, func: String, url: String) {
@@ -39,6 +39,7 @@ pub async fn create_mhy_client(handle: AppHandle, func: String, url: String) {
.title("米游社")
.center()
.user_agent(&win_ua)
.additional_browser_args("--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection --autoplay-policy=no-user-gesture-required")
// todo mac环境下没看到menu
.menu(menu::create_mhy_menu(handle.clone()))
.on_menu_event(move |app, event| menu::handle_menu_event(app, event))

View File

@@ -1,6 +1,6 @@
//! @file src/commands.rs
//! @desc 命令模块,负责处理命令
//! @since Beta v0.5.1
//! @since Beta v0.7.2
use tauri::{AppHandle, Emitter, Manager, WebviewWindowBuilder};
use tauri_utils::config::{WebviewUrl, WindowConfig};
@@ -42,6 +42,7 @@ pub async fn create_window(
.visible(option.visible)
.title(option.title)
.center()
.additional_browser_args("--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection --autoplay-policy=no-user-gesture-required")
.build()
.unwrap();
}

68
src-tauri/src/lib.rs Normal file
View File

@@ -0,0 +1,68 @@
//! @file src/lib.rs
//! @desc 主模块,用于启动应用
//! @since Beta v0.7.2
mod client;
mod commands;
mod plugins;
mod utils;
use crate::client::create_mhy_client;
use crate::commands::{create_window, execute_js, get_dir_size, init_app};
use crate::plugins::{build_log_plugin, build_si_plugin};
use tauri::{generate_context, generate_handler, Builder, Manager, Window, WindowEvent};
// 窗口事件处理
fn window_event_handler(app: &Window, event: &WindowEvent) {
match event {
WindowEvent::CloseRequested { api, .. } => {
api.prevent_close();
if app.label() == "TeyvatGuide" {
// 子窗口 label 的数组
const SUB_WINDOW_LABELS: [&str; 3] = ["Sub_window", "Dev_JSON", "mhy_client"];
for label in SUB_WINDOW_LABELS.iter() {
let sub = app.get_webview_window(label);
if sub.is_some() {
sub.unwrap().destroy().unwrap();
}
}
}
app.destroy().unwrap();
}
_ => {}
}
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
Builder::default()
.on_window_event(move |app, event| window_event_handler(app, event))
.plugin(build_si_plugin())
.plugin(tauri_plugin_deep_link::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_http::init())
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_sql::Builder::default().build())
.plugin(build_log_plugin())
.setup(|_app| {
let _window = _app.get_webview_window("TeyvatGuide");
#[cfg(debug_assertions)]
if _window.is_some() {
_window.unwrap().open_devtools();
}
Ok(())
})
.invoke_handler(generate_handler![
init_app,
create_window,
execute_js,
get_dir_size,
create_mhy_client
])
.run(generate_context!())
.expect("error while running tauri application");
}

View File

@@ -1,69 +1,10 @@
//! @file src/main.rs
//! @desc 主模块,用于启动应用
//! @since Beta v0.6.2
//! @since Beta v0.7.2
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
mod client;
mod commands;
mod plugins;
mod utils;
use crate::client::create_mhy_client;
use crate::commands::{create_window, execute_js, get_dir_size, init_app};
use crate::plugins::{build_log_plugin, build_si_plugin};
use tauri::{generate_context, generate_handler, Builder, Manager, Window, WindowEvent};
// 窗口事件处理
fn window_event_handler(app: &Window, event: &WindowEvent) {
match event {
WindowEvent::CloseRequested { api, .. } => {
api.prevent_close();
if app.label() == "TeyvatGuide" {
// 子窗口 label 的数组
const SUB_WINDOW_LABELS: [&str; 3] = ["Sub_window", "Dev_JSON", "mhy_client"];
for label in SUB_WINDOW_LABELS.iter() {
let sub = app.get_webview_window(label);
if sub.is_some() {
sub.unwrap().destroy().unwrap();
}
}
}
app.destroy().unwrap();
}
_ => {}
}
}
fn main() {
Builder::default()
.on_window_event(move |app, event| window_event_handler(app, event))
.plugin(build_si_plugin())
.plugin(tauri_plugin_deep_link::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_http::init())
.plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_sql::Builder::default().build())
.plugin(build_log_plugin())
.setup(|_app| {
let _window = _app.get_webview_window("TeyvatGuide");
#[cfg(debug_assertions)]
if _window.is_some() {
_window.unwrap().open_devtools();
}
Ok(())
})
.invoke_handler(generate_handler![
init_app,
create_window,
execute_js,
get_dir_size,
create_mhy_client
])
.run(generate_context!())
.expect("error while running tauri application");
teyvat_guide_lib::run()
}

View File

@@ -1,7 +1,8 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "TeyvatGuide",
"identifier": "TeyvatGuide",
"version": "0.7.1",
"version": "0.7.3",
"build": {
"beforeDevCommand": "pnpm vite:dev",
"beforeBuildCommand": "pnpm vite:build",
@@ -39,6 +40,7 @@
"resizable": true,
"title": "Teyvat Guide",
"label": "TeyvatGuide",
"additionalBrowserArgs": "--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection --autoplay-policy=no-user-gesture-required",
"width": 1600,
"height": 900,
"center": true,

View File

@@ -18,10 +18,10 @@ import showSnackbar from "@comp/func/snackbar.js";
import TGSqlite from "@Sqlite/index.js";
import TSUserAccount from "@Sqlite/modules/userAccount.js";
import { app, core, event, webviewWindow } from "@tauri-apps/api";
import { PhysicalSize } from "@tauri-apps/api/dpi";
import type { Event, UnlistenFn } from "@tauri-apps/api/event";
import { currentMonitor, getCurrentWindow } from "@tauri-apps/api/window";
import { getCurrentWindow, LogicalSize } from "@tauri-apps/api/window";
import { mkdir } from "@tauri-apps/plugin-fs";
import { openUrl } from "@tauri-apps/plugin-opener";
import { storeToRefs } from "pinia";
import { computed, onMounted, onUnmounted, ref } from "vue";
import { useRouter } from "vue-router";
@@ -30,6 +30,7 @@ import { useAppStore } from "@/store/modules/app.js";
import { useUserStore } from "@/store/modules/user.js";
import { getBuildTime } from "@/utils/TGBuild.js";
import TGLogger from "@/utils/TGLogger.js";
import { getWindowSize, resizeWindow } from "@/utils/TGWindow.js";
import OtherApi from "@/web/request/otherReq.js";
const router = useRouter();
@@ -40,6 +41,7 @@ const vuetifyTheme = computed<string>(() => (theme.value === "dark" ? "dark" : "
let themeListener: UnlistenFn | null = null;
let urlListener: UnlistenFn | null = null;
let resizeListener: UnlistenFn | null = null;
onMounted(async () => {
const win = getCurrentWindow();
@@ -51,43 +53,27 @@ onMounted(async () => {
await core.invoke("init_app");
urlListener = await getDeepLink();
}
if (needResize.value !== "false") await checkResize();
if (needResize.value !== "false") await resizeWindow();
document.documentElement.className = theme.value;
themeListener = await event.listen<string>("readTheme", (e: Event<string>) => {
theme.value = e.payload;
document.documentElement.className = theme.value;
});
resizeListener = await event.listen<string>("needResize", async (e: Event<string>) => {
console.log(needResize);
const windowCur = webviewWindow.getCurrentWebviewWindow();
if (e.payload !== "false") {
await resizeWindow();
} else {
const size = getWindowSize(windowCur.label);
await windowCur.setSize(new LogicalSize(size.width, size.height));
await windowCur.setZoom(1);
}
await windowCur.center();
});
await getCurrentWindow().show();
});
async function checkResize(): Promise<void> {
const screen = await currentMonitor();
if (screen === null) {
showSnackbar.error("获取屏幕信息失败!", 3000);
return;
}
const windowCur = webviewWindow.getCurrentWebviewWindow();
if (await windowCur.isMaximized()) return;
const designSize = getSize(windowCur.label);
const widthScale = screen.size.width / 1920;
const heightScale = screen.size.height / 1080;
await windowCur.setSize(
new PhysicalSize(
Math.round(designSize.width * widthScale),
Math.round(designSize.height * heightScale),
),
);
await windowCur.setZoom((1 / screen.scaleFactor) * Math.min(widthScale, heightScale));
await windowCur.setFocus();
return;
}
function getSize(label: string): PhysicalSize {
if (label === "TeyvatGuide") return new PhysicalSize(1600, 900);
if (label === "Sub_window" || label === "Dev_JSON") return new PhysicalSize(960, 720);
return new PhysicalSize(1280, 720);
}
// 启动后只执行一次的监听
async function listenOnInit(): Promise<void> {
console.info("[App][listenOnInit] 监听初始化事件!");
@@ -248,7 +234,7 @@ async function checkUpdate(): Promise<void> {
buildTime.value = getBuildTime();
await TGSqlite.update();
showSnackbar.success("数据库已更新!", 3000);
window.open("https://app.btmuli.ink/docs/TeyvatGuide/changelogs.html");
await openUrl("https://app.btmuli.ink/docs/TeyvatGuide/changelogs.html");
}
}
@@ -261,6 +247,10 @@ onUnmounted(() => {
urlListener();
urlListener = null;
}
if (resizeListener !== null) {
resizeListener();
resizeListener = null;
}
});
</script>
<style lang="css" scoped>

View File

@@ -1,12 +1,12 @@
/*
* @file assets/index.css
* @description 全局样式文件
* @since Beta v0.5.5
* @since Beta v0.7.2
*/
@import "fonts/index.css";
@import url("themes/default.css");
@import url("themes/dark.css");
@import "themes/default.css";
@import "themes/dark.css";
:root {
/* font */
@@ -62,26 +62,27 @@ html {
/*
* @description 侧边滚动条样式
* @since Beta v0.5.5
* @since Beta v0.7.2
*/
::-webkit-scrollbar {
width: 8px;
height: 8px;
border-radius: 5px;
width: 4px;
height: 4px;
border-radius: 4px;
}
::-webkit-scrollbar-track {
border-radius: 5px;
border-radius: 4px;
background: var(--common-shadow-2);
}
::-webkit-scrollbar-corner {
border-radius: 5px;
border-radius: 4px;
background: var(--common-shadow-2);
}
::-webkit-scrollbar-thumb {
border-radius: 5px;
min-height: 48px;
border-radius: 4px;
background: var(--tgc-od-white);
}

View File

@@ -0,0 +1,49 @@
/**
* @file styles/github.styles.scss
* @description GitHub styles
* @since Beta v0.7.2
*/
/* Card传入theme参数 */
@mixin github-card($theme: "default") {
@include github-card-shadow($theme);
@if $theme == "default" {
border: 1px solid #d1d9e0;
background: #ffffff;
} @else {
border: 1px solid #3d444d;
background: #0d1117;
}
}
/* CardShadow传入theme参数 */
@mixin github-card-shadow($theme: "default") {
@if $theme == "default" {
box-shadow:
rgba(31, 35, 40, 0.06) 0 1px 1px 0,
rgba(31, 35, 40, 0.06) 0 1px 3px 0;
} @else {
box-shadow:
rgba(1, 4, 9, 0.6) 0 1px 1px 0,
rgba(1, 4, 9, 0.6) 0 1px 3px 0;
}
}
/* Btn传入theme参数 */
@mixin github-btn($theme: "default") {
@if $theme == "default" {
border: 1px solid #d1d9e0;
background: #f6f8fa;
} @else {
border: 1px solid #3d444d;
background: #212830;
}
}
/* tags深色主题 */
@mixin github-tag-dark-gen($color: #548af7) {
border: 1px solid rgba($color, 0.3);
background: rgba($color, 0.18);
color: $color;
}

View File

@@ -1,7 +1,7 @@
/**
* @file assets/themes/dark.css
* @description 主题样式文件-深色主题
* @since Beta v0.4.5
* @since Beta v0.7.2
*/
/* dark mode */
@@ -33,8 +33,6 @@ html.dark {
/* button */
--btn-text: var(--tgc-yellow-1);
--btn-bg-1: var(--tgc-dark-5);
--btn-text-1: var(--tgc-yellow-1);
/* box-shadow */
--common-shadow-1: rgb(255 255 255 / 10%);

View File

@@ -1,7 +1,7 @@
/**
* @file assets/themes/default.css
* @description 主题样式文件-默认(浅色)主题
* @since Beta v0.4.5
* @since Beta v0.7.2
*/
/* default(light) theme */
@@ -33,8 +33,6 @@ html.default {
/* button */
--btn-text: var(--tgc-yellow-2); /* with tgc-btn-1 */
--btn-bg-1: var(--tgc-yellow-1);
--btn-text-1: var(--tgc-blue-1);
/* box-shadow */
--common-shadow-1: rgb(0 0 0 / 10%);

View File

@@ -42,6 +42,7 @@ onUnmounted(() => window.removeEventListener("scroll", handleScroll));
<style lang="css" scoped>
.back-top {
position: fixed;
z-index: 1;
right: 10px;
bottom: 10px;
width: 40px;

View File

@@ -4,8 +4,8 @@
<TMiImg alt="navIcon" :src="navItem.icon" :ori="true" />
<span>{{ navItem.name }}</span>
</div>
<div v-if="props.modelValue === 2 && hasNav" class="tgn-nav">
<v-btn size="25" @click="tryGetCode" title="查看兑换码" icon="mdi-code-tags-check"></v-btn>
<div v-if="hasNav" class="tgn-nav">
<v-icon size="25" @click="tryGetCode" title="查看兑换码">mdi-code-tags-check</v-icon>
</div>
<ToLivecode v-model="showOverlay" :data="codeData" v-model:actId="actId" />
</div>
@@ -15,6 +15,7 @@ import TMiImg from "@comp/app/t-mi-img.vue";
import showDialog from "@comp/func/dialog.js";
import showSnackbar from "@comp/func/snackbar.js";
import { emit } from "@tauri-apps/api/event";
import { openUrl } from "@tauri-apps/plugin-opener";
import { storeToRefs } from "pinia";
import { computed, onMounted, ref, shallowRef, watch } from "vue";
@@ -37,8 +38,8 @@ const showOverlay = ref<boolean>(false);
const actId = ref<string>();
const hasNav = computed<TGApp.BBS.Navigator.Navigator | undefined>(() => {
if (props.modelValue !== 2) return undefined;
return nav.value.find((item) => item.name === "前瞻直播" || item.name === "直播兑换码");
const liveNames = ["前瞻直播", "前瞻节目", "直播兑换码"];
return nav.value.find((item) => liveNames.includes(item.name));
});
onMounted(async () => await loadNav());
@@ -53,7 +54,6 @@ async function loadNav(): Promise<void> {
}
async function tryGetCode(): Promise<void> {
if (props.modelValue !== 2) return;
if (!hasNav.value) return;
const actIdFind = new URL(hasNav.value.app_path).searchParams.get("act_id");
if (!actIdFind) {
@@ -81,6 +81,7 @@ async function toNav(item: TGApp.BBS.Navigator.Navigator): Promise<void> {
await TGLogger.Info(`[TGameNav][toNav] ${item.app_path}`);
const link = new URL(item.app_path);
const mysList = [
"https://ys.mihoyo.com",
"https://act.mihoyo.com",
"https://webstatic.mihoyo.com",
"https://bbs.mihoyo.com",
@@ -93,10 +94,10 @@ async function toNav(item: TGApp.BBS.Navigator.Navigator): Promise<void> {
}
// 如果不在上面的域名里面,就直接打开
if (!mysList.includes(link.origin)) {
window.open(item.app_path);
await openUrl(item.app_path);
return;
}
if (item.name === "签到福利") {
if (item.name === "签到福利" || item.name === "每日签到") {
await TGClient.open("web_act_thin", item.app_path);
return;
}
@@ -112,78 +113,49 @@ async function toNav(item: TGApp.BBS.Navigator.Navigator): Promise<void> {
// 处理 protocol
async function toBBS(link: URL): Promise<void> {
if (link.protocol == "mihoyobbs:") {
if (link.pathname.startsWith("//article")) {
if (link.hostname === "article") {
const postId = link.pathname.split("/").pop();
await createPost(<string>postId);
return;
}
if (link.pathname.startsWith("//forum")) {
if (link.hostname === "forum") {
const forumId = link.pathname.split("/").pop();
const localPath = getLocalPath(forumId);
if (localPath === "") {
showSnackbar.warn(`不支持的链接:${link.href}`);
return;
}
const localPath = `/posts/forum/${props.modelValue}/${forumId}`;
await emit("active_deep_link", `router?path=${localPath}`);
return;
}
}
showSnackbar.warn(`不支持的链接:${link.href}`);
}
// todo 动态获取版块列表
function getLocalPath(forum?: string): string {
if (!forum) return "";
const forumLocalMap: Record<string, string> = {
"31": "/news/3", // 崩坏2 官方
"6": "/news/1", // 崩坏3 官方
"28": "/news/2", // 原神官方
"33": "/news/4", // 未定官方
"58": "/news/8", // 绝区零官方
"36": "/news/5", // 大别野公告
};
if (forumLocalMap[forum]) return forumLocalMap[forum];
const ysForums = ["26", "43", "29", "49", "50"];
const srForums = ["52", "61", "56", "62"];
const bh3Forums = ["1", "14", "4", "41"];
const bh2Forums = ["30", "51", "40"];
const wdForums = ["37", "60", "42", "38"];
const zzzForums = ["57", "59", "64", "65"];
const dbyForums = ["54", "35", "34", "39", "47", "48", "55", "36"];
if (ysForums.includes(forum)) return `/posts/forum/2/${forum}`;
if (srForums.includes(forum)) return `/posts/forum/6/${forum}`;
if (bh3Forums.includes(forum)) return `/posts/forum/1/${forum}`;
if (bh2Forums.includes(forum)) return `/posts/forum/3/${forum}`;
if (wdForums.includes(forum)) return `/posts/forum/4/${forum}`;
if (zzzForums.includes(forum)) return `/posts/forum/8/${forum}`;
if (dbyForums.includes(forum)) return `/posts/forum/5/${forum}`;
return "";
}
</script>
<style lang="css" scoped>
<style lang="scss" scoped>
@use "@styles/github.styles.scss" as github-styles;
.tgn-container {
position: relative;
display: flex;
padding: 5px;
gap: 10px;
padding: 8px;
gap: 8px;
}
.tgn-nav {
@include github-styles.github-card();
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
border-radius: 5px;
-webkit-backdrop-filter: blur(20px);
backdrop-filter: blur(20px);
background: var(--common-shadow-t-4);
box-shadow: 0 0 5px var(--common-shadow-4);
padding: 4px;
border-radius: 4px;
color: var(--tgc-white-1);
cursor: pointer;
}
.dark .tgn-nav {
@include github-styles.github-card("dark");
}
.tgn-nav img {
width: 25px;
height: 25px;
width: 28px;
height: 28px;
}
.tgn-nav span {

View File

@@ -68,8 +68,8 @@ const props = defineProps<TItemBoxProps>();
left: 0;
overflow: hidden;
width: v-bind("props.modelValue.size");
border-radius: 5px;
aspect-ratio: 1;
height: v-bind("props.modelValue.height");
border-radius: 4px;
}
.tib-bg img {
@@ -82,8 +82,8 @@ const props = defineProps<TItemBoxProps>();
position: relative;
overflow: hidden;
width: v-bind("props.modelValue.size");
border-radius: 5px;
aspect-ratio: 1;
height: v-bind("props.modelValue.height");
border-radius: 4px;
}
.tib-icon img {
@@ -98,11 +98,11 @@ const props = defineProps<TItemBoxProps>();
left: 0;
display: flex;
width: v-bind("props.modelValue.size");
height: v-bind("props.modelValue.height");
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 5px;
aspect-ratio: 1;
border-radius: 4px;
}
.tib-lt {
@@ -111,9 +111,9 @@ const props = defineProps<TItemBoxProps>();
left: 3%;
display: flex;
width: v-bind("props.modelValue.ltSize");
height: v-bind("props.modelValue.ltSize");
align-items: center;
justify-content: center;
aspect-ratio: 1;
}
.tib-lt img {
@@ -128,12 +128,12 @@ const props = defineProps<TItemBoxProps>();
right: 0;
display: flex;
width: v-bind("props.modelValue.rtSize");
height: v-bind("props.modelValue.rtSize");
align-items: center;
justify-content: center;
aspect-ratio: 1;
background: rgb(0 0 0 / 40%);
border-bottom-left-radius: 5px;
border-top-right-radius: 5px;
border-bottom-left-radius: 4px;
border-top-right-radius: 4px;
color: var(--tgc-white-1);
font-family: var(--font-title);
}
@@ -145,13 +145,15 @@ const props = defineProps<TItemBoxProps>();
display: flex;
width: 100%;
height: v-bind("props.modelValue.innerHeight ?? 0") px;
flex-grow: 1;
flex-shrink: 0;
align-items: center;
justify-content: center;
-webkit-backdrop-filter: blur(v-bind("props.modelValue.innerBlur ?? 0"));
backdrop-filter: blur(v-bind("props.modelValue.innerBlur ?? 0"));
background: rgb(20 20 20 / 40%);
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
color: var(--tgc-white-1);
font-family: var(--font-title);
font-size: v-bind("((props.modelValue.innerHeight ?? 0) / 2).toString() + 'px'");
@@ -159,8 +161,8 @@ const props = defineProps<TItemBoxProps>();
.tib-inner img {
width: v-bind("(props.modelValue.innerHeight ?? 0).toString() + 'px'");
height: v-bind("(props.modelValue.innerHeight ?? 0).toString() + 'px'");
padding: 1px;
aspect-ratio: 1;
}
.tib-inner span {

View File

@@ -14,11 +14,7 @@ import { onMounted, ref } from "vue";
const isPined = ref<boolean>(false);
onMounted(async () => {
// 因为无法获取窗口是否置顶,这边手动取消置顶
// 详见https://github.com/tauri-apps/tauri/issues/11078
await getCurrentWindow().setAlwaysOnTop(false);
});
onMounted(async () => (isPined.value = await getCurrentWindow().isAlwaysOnTop()));
async function switchPin(): Promise<void> {
isPined.value = !isPined.value;

View File

@@ -1,7 +1,13 @@
<template>
<div v-if="card" :id="`post-card-${card.postId}`" class="tpc-card">
<div
v-if="card"
:id="`post-card-${card.postId}`"
class="tpc-card"
:class="{ 'select-mode': props.selectMode }"
@click="trySelect()"
>
<div class="tpc-top">
<div class="tpc-cover" @click="createPost(card)">
<div class="tpc-cover" @click="toPost()">
<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">
@@ -11,41 +17,72 @@
<span>{{ card.subtitle }}</span>
</div>
</div>
<div
v-else-if="props.modelValue.post.images.length > 1"
class="tpc-image-cnt"
:title="`图片数:${props.modelValue.post.images.length}`"
>
<v-icon size="10">mdi-folder-multiple-image</v-icon>
<span>{{ props.modelValue.post.images.length }}</span>
</div>
</div>
<div class="tpc-title" :title="card.title" @click="shareCard">{{ card.title }}</div>
<div class="tpc-title" :title="card.title" @click="shareCard()">{{ card.title }}</div>
</div>
<div class="tpc-mid" v-if="card.user !== null">
<TpAvatar :data="card.user" position="left" />
<TpAvatar
:data="card.user"
position="left"
:style="{ cursor: props.userClick ? 'pointer' : 'default' }"
@click="onUserClick()"
/>
</div>
<div class="tpc-bottom" v-if="card.data !== null">
<div class="tpc-bottom">
<div class="tpc-tags">
<div v-for="(reason, idx) in card.reasons" :key="idx" class="tpc-reason" title="推荐理由">
<v-icon size="12">mdi-lightbulb-on</v-icon>
<span>{{ reason.text }}</span>
</div>
<div v-for="topic in card.topics" :key="topic.id" class="tpc-tag" @click="toTopic(topic)">
<v-icon size="10">mdi-tag</v-icon>
<v-icon size="12">mdi-tag</v-icon>
<span>{{ topic.name }}</span>
</div>
</div>
<div class="tpc-data">
<div class="tpc-data" v-if="card.data !== null">
<div class="tpc-info-item" :title="`浏览数:${card.data.view}`">
<v-icon>mdi-eye</v-icon>
<v-icon size="12">mdi-eye</v-icon>
<span>{{ card.data.view }}</span>
</div>
<div class="tpc-info-item" :title="`收藏数:${card.data.mark}`">
<v-icon>mdi-star</v-icon>
<v-icon size="12">mdi-star</v-icon>
<span>{{ card.data.mark }}</span>
</div>
<div class="tpc-info-item" :title="`回复数:${card.data.reply}`">
<v-icon>mdi-comment</v-icon>
<v-icon size="12">mdi-comment</v-icon>
<span>{{ card.data.reply }}</span>
</div>
<div class="tpc-info-item" :title="`点赞数:${card.data.like}`">
<v-icon>mdi-thumb-up</v-icon>
<v-icon size="12">mdi-thumb-up</v-icon>
<span>{{ card.data.like }}</span>
</div>
<div class="tpc-info-item" :title="`转发数:${card.data.forward}`">
<v-icon>mdi-share-variant</v-icon>
<v-icon size="12">mdi-share-variant</v-icon>
<span>{{ card.data.forward }}</span>
</div>
</div>
<div class="tpc-data">
<div class="tpc-info-item" :title="`创建时间: ${card.meta.create_time}`">
<v-icon size="12">mdi-calendar-clock</v-icon>
<span>{{ card.meta.create_time }}</span>
</div>
<div
v-if="card.meta.update_time"
class="tpc-info-item"
:title="`更新时间: ${card.meta.update_time}`"
>
<v-icon size="12">mdi-calendar-edit</v-icon>
<span>{{ card.meta.update_time }}</span>
</div>
</div>
</div>
<div
class="tpc-forum"
@@ -53,13 +90,14 @@
:title="`频道: ${card.forum.name}`"
@click="toForum(card.forum)"
>
<img :src="card.forum.icon" :alt="card.forum.name" />
<img v-if="card.forum.icon !== ''" :src="card.forum.icon" :alt="card.forum.name" />
<span>{{ card.forum.name }}</span>
</div>
<v-checkbox-btn
v-model="isSelected"
v-if="props.selectMode"
class="tpc-select"
@click="emits('onSelected', props.modelValue.post.post_id)"
@click.stop="trySelect()"
data-html2canvas-ignore
/>
<div class="tpc-info-id" v-else>{{ props.modelValue.post.post_id }}</div>
@@ -70,43 +108,50 @@ 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, shallowRef, watch } from "vue";
import { computed, onMounted, ref, shallowRef, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { generateShareImg } from "@/utils/TGShare.js";
import { createPost } from "@/utils/TGWindow.js";
import { timestampToDate } from "@/utils/toolFunc.js";
type TPostCardProps = { modelValue: TGApp.Plugins.Mys.Post.FullData; selectMode?: boolean };
type TPostCardEmits = (e: "onSelected", v: string) => void;
type TPostStatus = RenderStatus & { stat: ActStat };
type TPostCardProps = {
modelValue: TGApp.BBS.Post.FullData;
selectMode?: boolean;
userClick?: boolean;
};
type TPostCardEmits = {
(e: "onSelected", v: string): void;
(e: "onUserClick", u: TGApp.BBS.Post.User, g: number): void;
};
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 };
type RenderMeta = { create_time: string; update_time?: string };
export type RenderCard = {
title: string;
cover: string;
postId: number;
subtitle: string;
user: TGApp.Plugins.Mys.User.Post | null;
user: TGApp.BBS.Post.User | null;
forum: RenderForum | null;
data: RenderData | null;
meta: RenderMeta;
status?: RenderStatus;
topics: Array<TGApp.BBS.Topic.Info>;
topics: Array<TGApp.BBS.Post.Topic>;
reasons: Array<TGApp.BBS.Post.RecommendTags>;
};
enum ActStat {
UNKNOWN,
STARTED,
FINISHED,
SELECTION,
}
const stats: Readonly<Array<TPostStatus>> = [
{ stat: ActStat.UNKNOWN, label: "未知", color: "var(--tgc-od-red)" },
{ stat: ActStat.STARTED, label: "进行中", color: "var(--tgc-od-green)" },
{ stat: ActStat.FINISHED, label: "已结束", color: "var(--tgc-od-white)" },
{ stat: ActStat.SELECTION, label: "评选中", color: "var(--tgc-od-orange)" },
const stats: Readonly<Array<RenderStatus>> = [
{ stat: 0, label: "未知", color: "var(--tgc-od-red)" },
{ stat: 1, label: "进行中", color: "var(--tgc-od-green)" },
{ stat: 2, label: "已结束", color: "var(--tgc-od-white)" },
{ stat: 3, label: "评选中", color: "var(--tgc-od-orange)" },
];
const route = useRoute();
const router = useRouter();
const props = withDefaults(defineProps<TPostCardProps>(), { selectMode: false });
const isSelected = ref<boolean>(false);
const emits = defineEmits<TPostCardEmits>();
const card = shallowRef<RenderCard>();
@@ -122,25 +167,42 @@ watch(
async () => (card.value = getPostCard(props.modelValue)),
);
function getActivityStatus(status: number): RenderStatus {
if (status satisfies ActStat) {
const stat: ActStat = status;
return stats[stat];
}
return stats[ActStat.UNKNOWN];
function trySelect(): void {
if (props.selectMode) emits("onSelected", props.modelValue.post.post_id);
isSelected.value = !isSelected.value;
}
function getPostCover(item: TGApp.Plugins.Mys.Post.FullData): string {
async function toPost(): Promise<void> {
if (props.selectMode) return;
if (!card.value) return;
if (route.name !== "帖子详情") {
await createPost(card.value);
return;
}
if (route.params.post_id.toString() === card.value.postId.toString()) {
showSnackbar.warn("当前已在该帖子详情页", 3000);
return;
}
await router.push({ name: "帖子详情", params: { post_id: card.value.postId.toString() } });
}
function getActivityStatus(status: number): RenderStatus {
let idx = stats.findIndex((v) => v.stat === status);
if (idx === -1) idx = 0;
return stats[idx];
}
function getPostCover(item: TGApp.BBS.Post.FullData): string {
let cover;
if (item.cover) cover = item.cover.url;
else if (item.post.cover) cover = item.post.cover;
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/resize,m_fill,w_360,h_130,limit_0/format,png`;
return `${cover}?x-oss-process=image/resize,m_fill,w_690,h_320,limit_0/format,png`;
}
function getCommonCard(item: TGApp.Plugins.Mys.Post.FullData): RenderCard {
function getCommonCard(item: TGApp.BBS.Post.FullData): RenderCard {
let forumData: RenderForum | null = null;
let statData: RenderData | null = null;
if (item.forum !== null) {
@@ -155,6 +217,11 @@ function getCommonCard(item: TGApp.Plugins.Mys.Post.FullData): RenderCard {
view: item.stat.view_num,
};
}
const metaData: RenderMeta = {
create_time: timestampToDate(Number(item.post.created_at) * 1000),
update_time:
item.post.updated_at === 0 ? undefined : timestampToDate(Number(item.post.updated_at) * 1000),
};
return {
title: item.post.subject,
cover: getPostCover(item),
@@ -163,11 +230,13 @@ function getCommonCard(item: TGApp.Plugins.Mys.Post.FullData): RenderCard {
user: item.user,
forum: forumData,
data: statData,
meta: metaData,
topics: item.topics,
reasons: item.recommend_reason?.tags ?? [],
};
}
function getPostCard(item: TGApp.Plugins.Mys.Post.FullData): RenderCard {
function getPostCard(item: TGApp.BBS.Post.FullData): RenderCard {
const commonCard = getCommonCard(item);
if (
item.news_meta !== undefined &&
@@ -184,6 +253,7 @@ function getPostCard(item: TGApp.Plugins.Mys.Post.FullData): RenderCard {
}
async function shareCard(): Promise<void> {
if (props.selectMode) return;
if (!card.value) return;
const shareDom = document.querySelector<HTMLDivElement>(`#post-card-${card.value.postId}`);
if (shareDom === null) {
@@ -194,18 +264,29 @@ async function shareCard(): Promise<void> {
await generateShareImg(fileName, shareDom, 2.5);
}
async function toTopic(topic: TGApp.BBS.Topic.Info): Promise<void> {
async function toTopic(topic: TGApp.BBS.Post.Topic): Promise<void> {
if (props.selectMode) return;
const gid = props.modelValue.post.game_id;
await emit("active_deep_link", `router?path=/posts/topic/${gid}/${topic.id}`);
}
async function toForum(forum: RenderForum): Promise<void> {
if (props.selectMode) return;
const gid = props.modelValue.post.game_id;
await emit("active_deep_link", `router?path=/posts/forum/${gid}/${forum.id}`);
}
function onUserClick(): void {
if (props.selectMode) return;
if (!card.value || card.value.user === null) return;
emits("onUserClick", card.value.user, props.modelValue.post.game_id);
}
</script>
<style lang="css" scoped>
<style lang="scss" scoped>
@use "@styles/github.styles.scss" as github-styles;
.tpc-card {
@include github-styles.github-card();
position: relative;
display: flex;
overflow: hidden;
@@ -214,11 +295,16 @@ async function toForum(forum: RenderForum): Promise<void> {
flex-direction: column;
align-items: center;
justify-content: space-between;
border: 1px solid var(--common-shadow-1);
border-radius: 5px;
background: var(--box-bg-1);
box-shadow: 2px 2px 5px var(--common-shadow-2);
row-gap: 10px;
border-radius: 4px;
row-gap: 8px;
&.select-mode {
cursor: pointer;
}
}
.dark .tpc-card {
@include github-styles.github-card("dark");
}
.tpc-top {
@@ -227,7 +313,7 @@ async function toForum(forum: RenderForum): Promise<void> {
flex-direction: column;
align-items: center;
justify-content: center;
row-gap: 5px;
row-gap: 4px;
}
.tpc-cover {
@@ -237,13 +323,14 @@ async function toForum(forum: RenderForum): Promise<void> {
width: 100%;
align-items: center;
justify-content: center;
aspect-ratio: 36 / 13;
aspect-ratio: 69 / 32;
background: var(--common-shadow-2);
cursor: pointer;
}
.tpc-cover img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
transition: all 0.3s linear;
@@ -251,8 +338,11 @@ async function toForum(forum: RenderForum): Promise<void> {
.tpc-mid {
position: relative;
width: 100%;
width: fit-content;
max-width: 100%;
box-sizing: border-box;
padding: 0 10px;
margin-right: auto;
}
.tpc-bottom {
@@ -260,45 +350,55 @@ async function toForum(forum: RenderForum): Promise<void> {
display: flex;
width: 100%;
flex-direction: column;
padding: 5px 10px;
row-gap: 5px;
padding: 4px 8px;
}
.tpc-title {
overflow: hidden;
width: 100%;
padding: 5px 10px;
position: relative;
width: fit-content;
max-width: 100%;
padding: 4px 8px;
margin-right: auto;
cursor: pointer;
font-family: var(--font-title);
font-size: 18px;
text-overflow: ellipsis;
white-space: nowrap;
}
.tpc-tags {
display: flex;
width: fit-content;
max-width: 100%;
flex-wrap: wrap;
align-items: flex-start;
justify-content: flex-start;
color: var(--box-text-5);
font-size: 12px;
gap: 5px;
:hover {
color: var(--box-text-3);
}
gap: 4px;
}
.tpc-tag {
@include github-styles.github-tag-dark-gen(#e06c63);
display: flex;
align-items: center;
justify-content: center;
padding: 0 3px;
border: 1px solid var(--common-shadow-1);
border-radius: 5px;
background: var(--box-bg-2);
padding: 0 4px;
border-radius: 4px;
cursor: pointer;
gap: 3px;
gap: 4px;
&:hover {
@include github-styles.github-tag-dark-gen(#00aeec);
}
}
.tpc-reason {
@include github-styles.github-tag-dark-gen(#d19a66);
display: flex;
align-items: center;
justify-content: center;
padding: 0 4px;
border-radius: 4px;
gap: 4px;
}
.tpc-forum {
@@ -308,15 +408,15 @@ async function toForum(forum: RenderForum): Promise<void> {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 5px;
padding: 4px;
background: var(--tgc-od-white);
border-bottom-left-radius: 5px;
border-top-right-radius: 5px;
border-bottom-left-radius: 4px;
border-top-right-radius: 4px;
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);
text-shadow: 0 0 4px var(--tgc-dark-1);
}
.tpc-select {
@@ -349,12 +449,13 @@ async function toForum(forum: RenderForum): Promise<void> {
.tpc-data {
display: flex;
width: 100%;
width: fit-content;
max-width: 100%;
height: 20px;
align-items: center;
justify-content: flex-end;
padding: 5px;
column-gap: 10px;
justify-content: center;
margin-left: auto;
column-gap: 8px;
}
.tpc-info-item {
@@ -363,7 +464,8 @@ async function toForum(forum: RenderForum): Promise<void> {
justify-content: flex-start;
color: var(--box-text-7);
font-size: 12px;
gap: 5px;
gap: 2px;
white-space: nowrap;
opacity: 0.6;
}
@@ -381,12 +483,29 @@ async function toForum(forum: RenderForum): Promise<void> {
font-size: 12px;
}
.tpc-image-cnt {
position: absolute;
bottom: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 0 8px;
border-top-left-radius: 12px;
column-gap: 2px;
font-size: 12px;
color: var(--tgc-white-1);
background: var(--tgc-od-blue);
opacity: 0.8;
box-shadow: -2px -2px 8px var(--tgc-dark-1);
}
.tpc-status {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
padding: 5px 30px 5px 5px;
padding: 4px 30px 4px 4px;
background-color: v-bind(cardBg);
clip-path: polygon(0 0, calc(100% - 15px) 0, 100% 50%, calc(100% - 15px) 100%, 0 100%);
color: var(--tgc-white-1);
@@ -413,9 +532,9 @@ async function toForum(forum: RenderForum): Promise<void> {
display: flex;
align-items: center;
justify-content: flex-start;
margin: 5px;
margin: 4px;
color: var(--tgc-white-1);
gap: 5px;
gap: 4px;
opacity: 0.8;
}
@@ -426,16 +545,16 @@ async function toForum(forum: RenderForum): Promise<void> {
display: flex;
align-items: center;
justify-content: center;
padding: 0 5px;
padding: 0 4px;
-webkit-backdrop-filter: blur(20px);
backdrop-filter: blur(20px);
background: var(--tgc-od-orange);
border-bottom-right-radius: 5px;
border-top-left-radius: 5px;
box-shadow: 2px 2px 5px var(--tgc-dark-1);
border-bottom-right-radius: 4px;
border-top-left-radius: 4px;
box-shadow: 2px 2px 4px var(--tgc-dark-1);
color: var(--tgc-white-1);
font-size: 12px;
opacity: 0.8;
text-shadow: 0 0 5px var(--tgc-dark-1);
text-shadow: 0 0 4px var(--tgc-dark-1);
}
</style>

View File

@@ -79,7 +79,7 @@
<template #title>测试页面</template>
</v-list-item>
<v-divider v-show="isDevEnv" />
<v-menu :open-on-click="true" location="end">
<v-menu :open-on-click="true" location="end" :offset="[8, 0]">
<template #activator="{ props }">
<v-list-item :title.attr="'图鉴'" v-bind="props">
<template #title>图鉴</template>
@@ -88,7 +88,7 @@
</template>
</v-list-item>
</template>
<v-list class="side-list-menu wiki" density="compact" :nav="true">
<v-list class="side-list-menu sub" density="compact" :nav="true">
<v-list-item class="side-item-menu" title="深渊数据库" :link="true" href="/wiki/abyss">
<template #prepend>
<img src="/source/UI/wikiAbyss.webp" alt="abyssIcon" class="side-icon-menu" />
@@ -133,7 +133,7 @@
</template>
</v-list-item>
</template>
<v-list class="side-list-menu" density="compact" :nav="true">
<v-list class="side-list-menu sub" density="compact" :nav="true">
<v-list-item class="side-item-menu" title="签到" @click="openClient('sign_in')">
<template #prepend>
<img src="/source/UI/userGacha.webp" class="side-icon-menu" alt="sing_in" />
@@ -154,6 +154,11 @@
<img src="/source/UI/posts.webp" alt="collect" class="side-icon-menu" />
</template>
</v-list-item>
<v-list-item class="side-item-menu" title="关注" @click="showFollow = true">
<template #prepend>
<img src="/platforms/mhy/mys.webp" alt="follow" class="side-icon-menu" />
</template>
</v-list-item>
</v-list>
</v-menu>
<v-list-item
@@ -172,13 +177,15 @@
</div>
</v-list>
</v-navigation-drawer>
<vp-overlay-follow v-model="showFollow" />
</template>
<script lang="ts" setup>
import showSnackbar from "@comp/func/snackbar.js";
import VpOverlayFollow from "@comp/viewPost/vp-overlay-follow.vue";
import { event, webviewWindow } from "@tauri-apps/api";
import type { Event, UnlistenFn } from "@tauri-apps/api/event";
import { storeToRefs } from "pinia";
import { computed, onMounted, onUnmounted } from "vue";
import { computed, onMounted, onUnmounted, ref } from "vue";
import { useAppStore } from "@/store/modules/app.js";
import { useUserStore } from "@/store/modules/user.js";
@@ -189,6 +196,7 @@ const { briefInfo } = storeToRefs(useUserStore());
let themeListener: UnlistenFn | null = null;
// @ts-expect-error The import.meta meta-property is not allowed in files which will build into CommonJS output.
const isDevEnv = import.meta.env.MODE === "development";
const showFollow = ref<boolean>();
const rail = computed<boolean>({
get: () => sidebar.value.collapse,
set: (v) => (sidebar.value.collapse = v),
@@ -197,7 +205,7 @@ const userInfo = computed<TGApp.App.Account.BriefInfo>(() => {
if (briefInfo.value && briefInfo.value.nickname) return briefInfo.value;
return { nickname: "未登录", uid: "-1", desc: "请扫码登录", avatar: "/source/UI/lumine.webp" };
});
const themeTitle = computed<string>(() => (theme.value === "default" ? "夜间模式" : "日间模式"));
const themeTitle = computed<string>(() => (theme.value === "default" ? "深色模式" : "浅色模式"));
onMounted(async () => {
themeListener = await event.listen<string>("readTheme", (e: Event<string>) => {
@@ -260,8 +268,8 @@ onUnmounted(() => {
font-family: var(--font-title);
}
.side-list-menu.wiki {
margin-left: 10px;
.side-list-menu.sub {
box-shadow: -2px 0 4px var(--common-shadow-2) !important;
}
.side-item-menu {

View File

@@ -8,26 +8,20 @@
.tsl-box {
display: flex;
align-items: center;
padding: 5px;
border-radius: 5px;
margin: 5px 0;
background: var(--box-bg-3);
color: var(--box-text-4);
padding: 4px;
border-radius: 4px;
background: var(--box-bg-1);
color: var(--box-text-1);
font-family: var(--font-title);
gap: 5px;
gap: 4px;
}
.tsl-box :first-child {
width: 20px;
height: 20px;
width: 24px;
height: 24px;
box-sizing: border-box;
padding: 2px;
border-radius: 5px;
filter: invert(22%) sepia(7%) saturate(1241%) hue-rotate(182deg) brightness(95%) contrast(99%);
}
.dark .tsl-box {
background: #2c313a;
color: #faf7e8;
filter: invert(0.75);
}
.dark .tsl-box :first-child {

View File

@@ -13,39 +13,34 @@
/>
</div>
<div class="tolc-info">ActID:{{ props.actId }}</div>
<v-list-item v-for="(item, index) in props.data" :key="index">
<template #title>
{{ item.code === "" ? "暂无兑换码" : item.code }}
</template>
<template #subtitle>
<div v-html="item.title"></div>
<div v-for="(item, index) in props.data" :key="index" class="tolc-list-box">
<div class="tolc-list-icon">
<img v-if="item.img === ''" src="/source/UI/empty.webp" alt="empty" />
<TMiImg :src="item.img" :ori="true" v-else alt="award" />
</div>
<div class="tolc-list-info">
<span>{{ item.code === "" ? "暂无兑换码" : item.code }}</span>
<span v-html="item.title" />
<span title="开放时间">{{ timestampToDate(Number(item.to_get_time) * 1000) }}</span>
</template>
<template #prepend>
<img
:src="item.img === '' ? '/source/UI/empty.webp' : item.img"
alt="icon"
class="tolc-icon"
/>
</template>
<template #append>
</div>
<div class="tolc-list-btn">
<v-btn
size="small"
:disabled="item.code === ''"
@click="copy(item.code)"
icon="mdi-content-copy"
variant="outlined"
class="tolc-btn"
data-html2canvas-ignore
/>
</template>
</v-list-item>
</div>
</div>
</div>
</TOverlay>
</template>
<script setup lang="ts">
import showSnackbar from "@comp/func/snackbar.js";
import TMiImg from "./t-mi-img.vue";
import TOverlay from "./t-overlay.vue";
import { generateShareImg } from "@/utils/TGShare.js";
@@ -78,11 +73,16 @@ async function shareImg(): Promise<void> {
.tolc-box {
position: relative;
display: flex;
width: 340px;
padding: 10px;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 10px 10px 20px;
border: 1px solid var(--common-shadow-2);
border-radius: 5px;
background: var(--app-page-bg);
row-gap: 12px;
}
.tolc-title {
@@ -104,13 +104,54 @@ async function shareImg(): Promise<void> {
font-size: 10px;
}
.tolc-icon {
width: 40px;
margin-right: 10px;
aspect-ratio: 1;
.tolc-list-box {
position: relative;
display: flex;
width: 100%;
box-sizing: border-box;
align-items: flex-start;
justify-content: flex-start;
padding: 8px;
border: 1px solid var(--common-shadow-1);
border-radius: 4px;
background: var(--box-bg-1);
color: var(--box-text-1);
column-gap: 12px;
}
.tolc-btn {
margin-left: 10px;
.tolc-list-icon {
position: relative;
display: flex;
width: 40px;
height: 40px;
flex-shrink: 0;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.tolc-list-info {
position: relative;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
:first-child {
font-family: var(--font-title);
}
:last-child {
font-size: 12px;
}
}
.tolc-list-btn {
margin-left: auto;
}
</style>

View File

@@ -14,7 +14,7 @@
<span>{{ parseNameCard(props.data.desc) }}</span>
<span>获取途径{{ props.data.source }}</span>
</div>
<div class="ton-type">{{ getType }}</div>
<div class="ton-type">{{ props.data.type }}</div>
<v-btn
class="ton-share"
@click="shareNameCard"
@@ -32,41 +32,17 @@
</template>
<script setup lang="ts">
import showSnackbar from "@comp/func/snackbar.js";
import { computed, ref } from "vue";
import { ref } from "vue";
import TOverlay from "./t-overlay.vue";
import { generateShareImg } from "@/utils/TGShare.js";
enum ToNameCardTypeEnum {
other,
achievement,
role,
record,
activity,
unknown,
}
type ToNameCardTypeMap = { [key in ToNameCardTypeEnum]: string };
type ToNameCardProps = { data?: TGApp.App.NameCard.Item };
const props = defineProps<ToNameCardProps>();
const visible = defineModel<boolean>();
const typeMap: ToNameCardTypeMap = {
0: "其他",
1: "成就",
2: "角色",
3: "纪行",
4: "活动",
5: "未知",
};
const loading = ref<boolean>(false);
const getType = computed<string>(() => {
if (!props.data) return typeMap[ToNameCardTypeEnum.unknown];
if (!(props.data.type satisfies ToNameCardTypeEnum)) return typeMap[5];
const type: ToNameCardTypeEnum = props.data.type;
return typeMap[type];
});
function parseNameCard(desc: string): string {
let array = [];
@@ -100,7 +76,7 @@ function parseNameCard(desc: string): string {
function parseDesc(desc: string, inQuote: boolean = false): string[] {
let res = desc.replace(/。/g, "。\n");
res = res.replace(//g, "\n");
if (props?.data?.index !== 187) {
if (props?.data?.id !== 210187) {
res = res.replace(//g, "\n");
res = res.replace(//g, "\n");
} else {
@@ -129,7 +105,7 @@ async function shareNameCard(): Promise<void> {
showSnackbar.error("未找到名片内容");
return;
}
const fileName = `${getType.value}名片】-${props.data?.name}`;
const fileName = `${props.data?.type}名片】-${props.data?.name}`;
loading.value = true;
await generateShareImg(fileName, nameCardBox);
loading.value = false;
@@ -149,23 +125,23 @@ async function shareNameCard(): Promise<void> {
overflow: hidden;
width: 800px;
height: 400px;
border-radius: 10px;
border-radius: 4px;
}
.ton-bg {
position: absolute;
width: 100%;
height: 100%;
border-radius: 10px;
border-radius: 4px;
}
.ton-type {
position: absolute;
top: 10px;
left: 10px;
padding: 0 5px;
padding: 0 4px;
border: 1px solid var(--tgc-white-1);
border-radius: 5px;
border-radius: 4px;
color: var(--tgc-white-1);
}
@@ -180,8 +156,8 @@ async function shareNameCard(): Promise<void> {
flex-direction: column;
align-items: flex-start;
justify-content: flex-end;
padding: 10px;
border-radius: 10px;
padding: 8px;
border-radius: 4px;
backdrop-filter: blur(5px);
background: rgb(0 0 0 / 25%);
color: var(--tgc-white-1);
@@ -213,7 +189,7 @@ async function shareNameCard(): Promise<void> {
right: 10px;
bottom: 10px;
border: 1px solid var(--tgc-white-1);
border-radius: 5px;
border-radius: 4px;
color: var(--tgc-white-1);
}
</style>

View File

@@ -1,5 +1,10 @@
<template>
<v-list class="top-nc-box" @click="emit('selected', props.data)">
<v-list
class="top-nc-box"
@click="emit('selected', props.data)"
:class="{ grey: !props.finish }"
:title.attr="props.data.name"
>
<v-list-item :title="props.data.name">
<template #subtitle>
<span class="desc" :title="props.data.desc">{{ props.data.desc }}</span>
@@ -7,7 +12,7 @@
<template #prepend>
<v-img
width="80px"
style="margin-right: 10px"
style="margin-right: 8px"
:src="`/WIKI/nameCard/icon/${props.data.name}.webp`"
/>
</template>
@@ -17,10 +22,12 @@
<script lang="ts" setup>
import { computed } from "vue";
type TopNameCardProps = { data: TGApp.App.NameCard.Item };
type TopNameCardProps = { data: TGApp.App.NameCard.Item; finish?: boolean };
type TopNameCardEmits = (e: "selected", v: TGApp.App.NameCard.Item) => void;
const props = defineProps<TopNameCardProps>();
const props = withDefaults(defineProps<TopNameCardProps>(), {
finish: true,
});
const emit = defineEmits<TopNameCardEmits>();
const bgImage = computed<string>(() => {
@@ -28,22 +35,39 @@ const bgImage = computed<string>(() => {
return `url("/WIKI/nameCard/bg/${props.data.name}.webp")`;
});
</script>
<style lang="css" scoped>
<style lang="scss" scoped>
@use "@styles/github.styles.scss" as github-styles;
.top-nc-box {
@include github-styles.github-card-shadow();
width: 100%;
height: 80px;
border: 1px solid var(--common-shadow-2);
border-radius: 10px 50px 50px 10px;
margin-bottom: 10px;
border: 1px solid var(--common-shadow-1);
border-radius: 4px 50px 50px 4px;
margin-bottom: 8px;
background-color: var(--box-bg-1);
background-image: v-bind(bgImage);
background-position: right;
background-repeat: no-repeat;
cursor: pointer;
font-family: var(--font-title);
transition: filter 0.5s ease-in-out;
&.grey {
filter: grayscale(1);
}
&.grey:hover {
filter: grayscale(0);
}
}
.dark .top-nc-box {
@include github-styles.github-card-shadow("dark");
}
.desc {
text-shadow: 1px 1px 1px #222;
text-shadow: 0 0 2px var(--common-shadow-t-8);
}
</style>

View File

@@ -252,7 +252,7 @@ defineExpose({ displayInputBox, displayCheckBox });
font-size: 20px;
text-align: center;
text-overflow: ellipsis;
white-space: normal;
white-space: pre-wrap;
word-break: break-all;
}

View File

@@ -15,6 +15,7 @@
</transition>
</template>
<script setup lang="ts">
import "https://static.geetest.com/static/js/gt.0.4.9.js";
import { ref, useTemplateRef, watch } from "vue";
const show = ref<boolean>(false);

View File

@@ -90,7 +90,7 @@ defineExpose({ displayBox });
.func-snackbar-container {
position: fixed;
z-index: 999;
z-index: 9999;
bottom: 0;
left: 0;
display: flex;

View File

@@ -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">
<div :title="props.modelValue.title" class="anno-cover" @click="createAnno">
<TMiImg
v-if="props.modelValue.banner !== ''"
:ori="true"
:src="props.modelValue.banner"
alt="cover"
:ori="true"
v-if="props.modelValue.banner !== ''"
/>
<img alt="cover" src="/source/UI/defaultCover.webp" v-else />
<img v-else alt="cover" src="/source/UI/defaultCover.webp" />
<div class="anno-info">
<div class="anno-time">
<v-icon>mdi-clock-time-four-outline</v-icon>
@@ -15,10 +15,10 @@
</div>
</div>
</div>
<div class="anno-title" :title="props.modelValue.title" @click="shareAnno">
<div :title="props.modelValue.title" class="anno-title" @click="shareAnno">
{{ parseTitle(props.modelValue.subtitle) }}
</div>
<div class="anno-label" :title="`标签:${props.modelValue.tagLabel}`">
<div :title="`标签:${props.modelValue.tagLabel}`" class="anno-label">
<img :src="props.modelValue.tagIcon" alt="tag" />
<span>{{ props.modelValue.tagLabel }}</span>
</div>
@@ -29,11 +29,12 @@
import TMiImg from "@comp/app/t-mi-img.vue";
import showSnackbar from "@comp/func/snackbar.js";
import type { AnnoCard } from "@/pages/common/PageAnno.vue";
import TGLogger from "@/utils/TGLogger.js";
import { generateShareImg } from "@/utils/TGShare.js";
import { createTGWindow } from "@/utils/TGWindow.js";
type TAnnoCardProps = { region: string; modelValue: TGApp.App.Announcement.ListCard; lang: string };
type TAnnoCardProps = { region: string; modelValue: AnnoCard; lang: string };
const props = defineProps<TAnnoCardProps>();
function parseTitle(title: string): string {
@@ -58,14 +59,20 @@ async function shareAnno(): Promise<void> {
await generateShareImg(fileName, element, 2.5);
}
</script>
<style lang="css" scoped>
<style lang="scss" scoped>
@use "@styles/github.styles.scss" as github-styles;
.anno-card {
@include github-styles.github-card();
position: relative;
overflow: hidden;
width: 100%;
border: 1px solid var(--common-shadow-1);
border-radius: 5px;
box-shadow: 2px 2px 5px var(--common-shadow-2);
border-radius: 6px;
box-sizing: border-box;
}
.dark .anno-card {
@include github-styles.github-card("dark");
}
.anno-cover {
@@ -89,13 +96,15 @@ async function shareAnno(): Promise<void> {
.anno-title {
position: relative;
overflow: hidden;
width: 100%;
padding: 5px;
max-width: 100%;
width: fit-content;
padding: 4px;
cursor: pointer;
font-size: 18px;
text-align: right;
margin-left: auto;
text-overflow: ellipsis;
white-space: nowrap;
box-sizing: border-box;
}
.anno-info {
@@ -116,9 +125,9 @@ async function shareAnno(): Promise<void> {
display: flex;
align-items: center;
justify-content: flex-start;
margin: 5px;
margin: 4px;
color: var(--tgc-white-1);
gap: 5px;
gap: 4px;
}
.anno-label {
@@ -128,19 +137,19 @@ async function shareAnno(): Promise<void> {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 5px;
padding: 4px;
background-color: var(--tgc-od-white);
border-bottom-left-radius: 5px;
border-bottom-left-radius: 6px;
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);
text-shadow: 0 0 4px var(--tgc-dark-1);
}
.anno-label img {
width: 20px;
height: 20px;
margin-right: 5px;
margin-right: 4px;
}
.anno-cover img:hover {
@@ -155,14 +164,14 @@ async function shareAnno(): Promise<void> {
display: flex;
align-items: center;
justify-content: center;
padding: 0 5px;
padding: 0 4px;
background: var(--tgc-od-orange);
border-bottom-right-radius: 5px;
border-top-left-radius: 5px;
box-shadow: 0 0 10px var(--tgc-dark-1);
border-bottom-right-radius: 6px;
border-top-left-radius: 6px;
box-shadow: 0 0 8px var(--tgc-dark-1);
color: var(--tgc-white-1);
font-size: 12px;
opacity: 0.8;
text-shadow: 0 0 5px var(--tgc-dark-1);
text-shadow: 0 0 4px var(--tgc-dark-1);
}
</style>

View File

@@ -21,7 +21,7 @@ import parseAnnoContent from "@/web/utils/annoParser.js";
type TaParserProps = { data: TGApp.BBS.Announcement.ContentItem };
const props = defineProps<TaParserProps>();
function getTaName(ta: TGApp.Plugins.Mys.SctPost.Base): Component {
function getTaName(ta: TGApp.BBS.SctPost.Base): Component {
if (ta.children) return TpTexts;
if (typeof ta.insert === "string") return TpText;
if ("image" in ta.insert) return TpImage;

View File

@@ -133,8 +133,8 @@ async function freshData(): Promise<void> {
}
.tocp-btn {
background: var(--btn-bg-1);
color: var(--btn-text-1);
background: var(--tgc-btn-1);
color: var(--btn-text);
font-family: var(--font-title);
}

View File

@@ -23,6 +23,7 @@
</template>
<script lang="ts" setup>
import { app } from "@tauri-apps/api";
import { openUrl } from "@tauri-apps/plugin-opener";
import { storeToRefs } from "pinia";
import { onMounted, ref } from "vue";
@@ -33,24 +34,24 @@ const versionApp = ref<string>();
onMounted(async () => (versionApp.value = await app.getVersion()));
function toRelease(): void {
window.open("https://github.com/BTMuli/TeyvatGuide/releases/latest");
async function toRelease(): Promise<void> {
await openUrl("https://github.com/BTMuli/TeyvatGuide/releases/latest");
}
function toGroup(): void {
window.open("https://h5.qun.qq.com/s/3cgX0hJ4GA");
async function toGroup(): Promise<void> {
await openUrl("https://h5.qun.qq.com/s/3cgX0hJ4GA");
}
function toGithub(): void {
window.open("https://github.com/BTMuli/TeyvatGuide");
async function toGithub(): Promise<void> {
await openUrl("https://github.com/BTMuli/TeyvatGuide");
}
function toStore(): void {
window.open("https://www.microsoft.com/store/productId/9NLBNNNBNSJN");
async function toStore(): Promise<void> {
await openUrl("https://www.microsoft.com/store/productId/9NLBNNNBNSJN");
}
function toSite(): void {
window.open("https://app.btmuli.ink/docs/TeyvatGuide/changelogs.html");
async function toSite(): Promise<void> {
await openUrl("https://app.btmuli.ink/docs/TeyvatGuide/changelogs.html");
}
</script>
<style lang="css" scoped>

View File

@@ -11,7 +11,7 @@
<template #append>
<div class="config-opers">
<v-icon @click="confirmCUD()" title="修改用户数据目录"> mdi-pencil</v-icon>
<v-icon @click="openPath('user')" title="打开用户数据目录"> mdi-folder-open</v-icon>
<v-icon @click="openDataPath('user')" title="打开用户数据目录"> mdi-folder-open</v-icon>
<v-icon @click="copyPath('user')" title="复制用户数据目录路径"> mdi-content-copy</v-icon>
</div>
</template>
@@ -24,7 +24,7 @@
</template>
<template #append>
<div class="config-opers">
<v-icon @click="openPath('db')" title="打开数据库目录"> mdi-folder-open</v-icon>
<v-icon @click="openDataPath('db')" title="打开数据库目录"> mdi-folder-open</v-icon>
<v-icon @click="copyPath('db')" title="复制数据库目录路径"> mdi-content-copy</v-icon>
</div>
</template>
@@ -38,7 +38,7 @@
<template #append>
<div class="config-opers">
<v-icon @click="confirmCGD()" title="修改游戏安装目录"> mdi-pencil</v-icon>
<v-icon @click="openPath('game')" title="打开游戏安装目录"> mdi-folder-open</v-icon>
<v-icon @click="openDataPath('game')" title="打开游戏安装目录"> mdi-folder-open</v-icon>
<v-icon @click="copyPath('game')" title="复制游戏安装目录"> mdi-content-copy</v-icon>
</div>
</template>
@@ -52,7 +52,7 @@
<template #append>
<div class="config-opers">
<v-icon @click="confirmCLD()" title="清理日志文件"> mdi-delete</v-icon>
<v-icon @click="openPath('log')" title="打开日志目录"> mdi-folder-open</v-icon>
<v-icon @click="openDataPath('log')" title="打开日志目录"> mdi-folder-open</v-icon>
<v-icon @click="copyPath('log')" title="复制日志目录路径"> mdi-content-copy</v-icon>
</div>
</template>
@@ -68,13 +68,13 @@ import { path } from "@tauri-apps/api";
import { sep } from "@tauri-apps/api/path";
import { open } from "@tauri-apps/plugin-dialog";
import { exists, readDir, remove } from "@tauri-apps/plugin-fs";
import { openPath } from "@tauri-apps/plugin-opener";
import { platform } from "@tauri-apps/plugin-os";
import { storeToRefs } from "pinia";
import { onMounted } from "vue";
import { useAppStore } from "@/store/modules/app.js";
import { backUpUserData } from "@/utils/dataBS.js";
import TGShell from "@/utils/TGShell.js";
const { dbPath, logDir, userDir, gameDir } = storeToRefs(useAppStore());
@@ -225,7 +225,7 @@ function copyPath(type: "db" | "user" | "log" | "game"): void {
showSnackbar.success(`${targetName}路径已复制!`);
}
async function openPath(type: "db" | "user" | "log" | "game"): Promise<void> {
async function openDataPath(type: "db" | "user" | "log" | "game"): Promise<void> {
let targetPath: string;
switch (type) {
case "db":
@@ -245,7 +245,7 @@ async function openPath(type: "db" | "user" | "log" | "game"): Promise<void> {
targetPath = gameDir.value;
break;
}
await TGShell.openPath(targetPath);
await openPath(targetPath);
}
</script>
<style lang="css" scoped>

View File

@@ -2,7 +2,7 @@
<v-list class="config-list">
<v-list-subheader :inset="true" class="config-header" title="相关信息" />
<v-divider :inset="true" class="border-opacity-75" />
<v-list-item title="Tauri 版本" @click="toOuter('https://v2.tauri.app/')">
<v-list-item title="Tauri 版本" @click="openUrl('https://v2.tauri.app/')">
<template #prepend>
<v-img class="config-icon" src="/platforms/tauri.webp" alt="Tauri" />
</template>
@@ -77,6 +77,7 @@ import showSnackbar from "@comp/func/snackbar.js";
import TGSqlite from "@Sqlite/index.js";
import TSUserAchi from "@Sqlite/modules/userAchi.js";
import { app } from "@tauri-apps/api";
import { openUrl } from "@tauri-apps/plugin-opener";
import { platform, version } from "@tauri-apps/plugin-os";
import { onMounted, ref, shallowRef } from "vue";
@@ -123,10 +124,6 @@ onMounted(async () => {
await TGLogger.Error(`加载数据库错误: ${e}`);
}
});
function toOuter(url: string): void {
window.open(url);
}
</script>
<style lang="css" scoped>
.config-header {

View File

@@ -107,9 +107,12 @@
<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 @click="tryCodeLogin(false)">
<v-list-item-title>扫码登录(游戏)</v-list-item-title>
<v-list-item-subtitle>使用米游社扫码登录</v-list-item-subtitle>
<template #append>
<img src="/platforms/mhy/mys.webp" alt="launcher" class="menu-icon" />
</template>
</v-list-item>
</v-list>
</v-menu>
@@ -122,7 +125,6 @@ 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, ref, shallowRef } from "vue";
@@ -132,7 +134,8 @@ import { useUserStore } from "@/store/modules/user.js";
import TGLogger from "@/utils/TGLogger.js";
import BBSApi from "@/web/request/bbsReq.js";
import PassportApi from "@/web/request/passportReq.js";
import TakumiApi from "@/web/request/takumiReq.js";
import passportReq from "@/web/request/passportReq.js";
import takumiReq from "@/web/request/takumiReq.js";
const { isLogin } = storeToRefs(useAppStore());
const { uid, briefInfo, cookie, account } = storeToRefs(useUserStore());
@@ -201,7 +204,7 @@ async function tryGetTokens(ck: TGApp.App.Account.Cookie): Promise<void> {
cookie.value = ck;
isLogin.value = true;
await showLoading.update("正在获取游戏账号");
const gameRes = await TakumiApi.bind.gameRoles(cookie.value);
const gameRes = await takumiReq.bind.gameRoles(cookie.value);
if (!Array.isArray(gameRes)) {
await showLoading.end();
showSnackbar.error(`[${gameRes.retcode}]${gameRes.message}`);
@@ -328,7 +331,7 @@ async function refreshUser(uid: string) {
}
await TSUserAccount.account.saveAccount(account);
await showLoading.update("正在获取账号信息");
const accountRes = await TakumiApi.bind.gameRoles(ck);
const accountRes = await takumiReq.bind.gameRoles(ck);
if (Array.isArray(accountRes)) {
await showLoading.update("获取账号信息成功");
await TGLogger.Info("[tc-userBadge][refreshUserInfo] 获取账号信息成功");
@@ -398,13 +401,13 @@ async function confirmCopyCookie(): Promise<void> {
}
async function tryGetCaptcha(phone: string, aigis?: string): Promise<string | false> {
const captchaResp = await Mys.User.getCaptcha(phone, aigis);
const captchaResp = await passportReq.captcha.create(phone, aigis);
if ("retcode" in captchaResp) {
if (!captchaResp.data || captchaResp.data === "") {
showSnackbar.error(`[${captchaResp.retcode}] ${captchaResp.message}`);
return false;
}
const aigisResp: TGApp.Plugins.Mys.CaptchaLogin.CaptchaAigis = JSON.parse(captchaResp.data);
const aigisResp: TGApp.BBS.CaptchaLogin.CaptchaAigis = JSON.parse(captchaResp.data);
const resp = await showGeetest(JSON.parse(aigisResp.data));
const aigisStr = `${aigisResp.session_id};${btoa(JSON.stringify(resp))}`;
return await tryGetCaptcha(phone, aigisStr);
@@ -417,14 +420,14 @@ async function tryLoginByCaptcha(
captcha: string,
actionType: string,
aigis?: string,
): Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | false> {
const loginResp = await Mys.User.login(phone, captcha, actionType, aigis);
): Promise<TGApp.BBS.CaptchaLogin.LoginRes | false> {
const loginResp = await passportReq.captcha.login(phone, captcha, actionType, aigis);
if ("retcode" in loginResp) {
if (!loginResp.data || loginResp.data === "") {
showSnackbar.error(`[${loginResp.retcode}] ${loginResp.message}`);
return false;
}
const aigisResp: TGApp.Plugins.Mys.CaptchaLogin.CaptchaAigis = JSON.parse(loginResp.data);
const aigisResp: TGApp.BBS.CaptchaLogin.CaptchaAigis = JSON.parse(loginResp.data);
const resp = await showGeetest(JSON.parse(aigisResp.data));
const aigisStr = `${aigisResp.session_id};${btoa(JSON.stringify(resp))}`;
return await tryLoginByCaptcha(phone, captcha, actionType, aigisStr);
@@ -441,7 +444,8 @@ async function showAccounts(): Promise<void> {
showSnackbar.warn("未登录!");
return;
}
gameAccounts.value = await TSUserAccount.game.getAccount(uid.value);
const accountsGet = await TSUserAccount.game.getAccount(uid.value);
gameAccounts.value = accountsGet.filter((a) => a.gameBiz === "hk4e_cn");
if (gameAccounts.value.length === 0) {
showSnackbar.warn("未找到账户的游戏数据,请尝试刷新!");
return;
@@ -522,7 +526,7 @@ async function addByCookie(): Promise<void> {
updated: "",
});
await showLoading.update("正在获取游戏账号");
const gameRes = await TakumiApi.bind.gameRoles(ck);
const gameRes = await takumiReq.bind.gameRoles(ck);
if (!Array.isArray(gameRes)) {
await showLoading.end();
showSnackbar.error(`[${gameRes.retcode}]${gameRes.message}`);
@@ -570,5 +574,6 @@ async function clearUser(user: TGApp.App.Account.User): Promise<void> {
.menu-icon {
width: 24px;
height: 24px;
border-radius: 4px;
}
</style>

Some files were not shown because too many files have changed in this diff Show More