Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da17f8cd03 | ||
|
|
4b77c031c2 | ||
|
|
3f3e941b68 | ||
|
|
2502c27ee5 | ||
|
|
41fb2a43f7 | ||
|
|
b7c49ce09b | ||
|
|
43f9e432cc | ||
|
|
74217e679e | ||
|
|
06a57c9bcf | ||
|
|
1ce8c1fddf | ||
|
|
a1cd7ff840 | ||
|
|
fce56dcf55 | ||
|
|
7cf4516865 | ||
|
|
01009b36eb | ||
|
|
79067d6f77 | ||
|
|
978c9c7778 | ||
|
|
29542a737e | ||
|
|
0016ec1fc1 | ||
|
|
61a89348d1 | ||
|
|
1c16bfc29a | ||
|
|
454b94f401 | ||
|
|
da6a29c5ac | ||
|
|
40d46f41c3 | ||
|
|
d79de499cf | ||
|
|
d11d4fe803 | ||
|
|
121e29ad4f | ||
|
|
215f0c6500 | ||
|
|
fd34b66148 | ||
|
|
c154381c3a | ||
|
|
960a3442ff | ||
|
|
ff66dfca30 | ||
|
|
ef9469643e | ||
|
|
b61d235221 | ||
|
|
400a501f30 | ||
|
|
a63edd81bd | ||
|
|
3bd1853008 | ||
|
|
1d8e7ec35d | ||
|
|
211f689426 | ||
|
|
89a79dc968 | ||
|
|
e1653bdfb0 | ||
|
|
8af5136a9c | ||
|
|
a8694104a9 | ||
|
|
570cbb5fed | ||
|
|
dd339285cb | ||
|
|
31311510ef | ||
|
|
f367e797a9 | ||
|
|
082fe9dfab | ||
|
|
3769859611 | ||
|
|
928c71ead8 | ||
|
|
39f2a7dc31 | ||
|
|
1d637705b7 | ||
|
|
9e2eb80a21 | ||
|
|
927d4545a1 | ||
|
|
45217d423a | ||
|
|
d430cd4672 | ||
|
|
d15d78b73f | ||
|
|
00fdcc79d6 | ||
|
|
20438106a4 | ||
|
|
f92684c7b3 | ||
|
|
3228b6a305 | ||
|
|
a47afbf2e0 | ||
|
|
f4a0165e81 | ||
|
|
31874e07c4 | ||
|
|
c696d3b51d | ||
|
|
8a2a3f5279 | ||
|
|
a2f68b92c7 | ||
|
|
96dfec969c | ||
|
|
1b5ddf9b3f | ||
|
|
4dc273662d | ||
|
|
83d52c6f40 | ||
|
|
0aabd2fa80 | ||
|
|
01dc6a6ea7 | ||
|
|
765c860473 | ||
|
|
b276b04f23 | ||
|
|
e308e4789c | ||
|
|
522add2441 | ||
|
|
08f74ce6a0 | ||
|
|
3be703d329 | ||
|
|
a3e42b63e6 | ||
|
|
4ef3313eb1 | ||
|
|
a22aac457a | ||
|
|
8a2524d6b1 | ||
|
|
b504f043b4 | ||
|
|
f842975f21 | ||
|
|
577f86248e | ||
|
|
c3246e95ce | ||
|
|
e3fb88fd44 | ||
|
|
0f6fe11c75 | ||
|
|
9d212a5b87 | ||
|
|
c0d9830670 | ||
|
|
c577a6f1ea | ||
|
|
0e6210ee8e | ||
|
|
adfe55054e | ||
|
|
fecad43dec | ||
|
|
4c93bb0d42 | ||
|
|
667aa6fb94 | ||
|
|
a1a5271603 | ||
|
|
4a646c2c4e | ||
|
|
48b976ac84 | ||
|
|
d7250ce13c | ||
|
|
1cad9891dc | ||
|
|
6302f171e9 | ||
|
|
bb67da034b | ||
|
|
804b735e95 | ||
|
|
e6904e14b5 | ||
|
|
b4954bd74c | ||
|
|
8f9006b9f4 | ||
|
|
fba7a6c088 | ||
|
|
0fdbea55eb | ||
|
|
b93ae791f2 | ||
|
|
b6b0b90ae8 | ||
|
|
7e7fb318ea | ||
|
|
3a102f31be | ||
|
|
9dba531bb2 | ||
|
|
6b5959ff76 | ||
|
|
d8267cbf7b | ||
|
|
ac4d2a319f | ||
|
|
214dec29d8 | ||
|
|
fcb16c9299 | ||
|
|
37ea45f0c1 | ||
|
|
dafa153b62 | ||
|
|
9b152eb59f | ||
|
|
d5aaecbf72 | ||
|
|
ce5a88954a | ||
|
|
fee1872b46 | ||
|
|
dd3ce101a6 | ||
|
|
d32d7b69f1 | ||
|
|
11a6157af0 | ||
|
|
1a40f88027 | ||
|
|
81fc5f9dca |
2
.github/workflows/build.yml
vendored
@@ -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
|
||||
|
||||
|
||||
2
.github/workflows/qodana_code_quality.yml
vendored
@@ -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"
|
||||
|
||||
44
CHANGELOG.md
@@ -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)
|
||||
|
||||
|
||||
11
README.md
@@ -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`
|
||||
|
||||
 
|
||||
|
||||
@@ -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.0,UIGF 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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
71
package.json
@@ -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
BIN
public/WIKI/character/10000110.webp
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/WIKI/character/10000111.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/WIKI/nameCard/bg/伊安珊·不懈.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/WIKI/nameCard/bg/成就·寂宁.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/WIKI/nameCard/bg/瓦雷莎·力源.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/WIKI/nameCard/bg/纪行·荣花.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/WIKI/nameCard/bg/纳塔·眬瞳.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/WIKI/nameCard/icon/伊安珊·不懈.webp
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
public/WIKI/nameCard/icon/成就·寂宁.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
public/WIKI/nameCard/icon/瓦雷莎·力源.webp
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
public/WIKI/nameCard/icon/纪行·荣花.webp
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
public/WIKI/nameCard/icon/纳塔·眬瞳.webp
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
public/WIKI/nameCard/profile/伊安珊·不懈.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/WIKI/nameCard/profile/成就·寂宁.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/WIKI/nameCard/profile/瓦雷莎·力源.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/WIKI/nameCard/profile/纪行·荣花.webp
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
public/WIKI/nameCard/profile/纳塔·眬瞳.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
public/WIKI/weapon/14519.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/icon/achievement/UI_AchievementIcon_A021.webp
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
public/icon/achievement/UI_AchievementIcon_B007_Part3.webp
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
public/icon/constellations/UI_Talent_S_Iansan_01.webp
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/icon/constellations/UI_Talent_S_Iansan_02.webp
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
public/icon/constellations/UI_Talent_S_Iansan_03.webp
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/icon/constellations/UI_Talent_S_Iansan_04.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/icon/constellations/UI_Talent_S_Varesa_01.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/icon/constellations/UI_Talent_S_Varesa_02.webp
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
public/icon/constellations/UI_Talent_S_Varesa_03.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/icon/constellations/UI_Talent_S_Varesa_04.webp
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/icon/constellations/UI_Talent_U_Iansan_01.webp
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/icon/constellations/UI_Talent_U_Iansan_02.webp
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
public/icon/constellations/UI_Talent_U_Varesa_01.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/icon/constellations/UI_Talent_U_Varesa_02.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/icon/material/101254.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/icon/material/101255.webp
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
public/icon/material/101256.webp
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
public/icon/material/112119.webp
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
public/icon/material/112120.webp
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
public/icon/material/112121.webp
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/icon/material/113072.webp
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
public/icon/talents/Skill_E_Iansan_01.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/icon/talents/Skill_E_Varesa_01.webp
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/icon/talents/Skill_S_Iansan_01.webp
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/icon/talents/Skill_S_Varesa_01.webp
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
public/icon/talents/UI_Talent_S_Iansan_05.webp
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
public/icon/talents/UI_Talent_S_Iansan_06.webp
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
public/icon/talents/UI_Talent_S_Iansan_08.webp
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
public/icon/talents/UI_Talent_S_Varesa_05.webp
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
public/icon/talents/UI_Talent_S_Varesa_06.webp
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/icon/talents/UI_Talent_S_Varesa_07.webp
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/icon/talents/UI_Talent_S_Varesa_08.webp
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/platforms/mhy/observer.webp
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
3
src-tauri/.gitignore
vendored
@@ -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
@@ -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"]
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "**" }] },
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
|
||||
@@ -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
@@ -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");
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
54
src/App.vue
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
49
src/assets/styles/github.styles.scss
Normal 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;
|
||||
}
|
||||
@@ -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%);
|
||||
|
||||
@@ -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%);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -90,7 +90,7 @@ defineExpose({ displayBox });
|
||||
|
||||
.func-snackbar-container {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
z-index: 9999;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||