mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-12 09:18:14 +08:00
✨ 扫码登录
This commit is contained in:
23
package.json
23
package.json
@@ -3,7 +3,7 @@
|
||||
"version": "0.6.7",
|
||||
"description": "Game Tool for GenshinImpact player",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.15.2",
|
||||
"packageManager": "pnpm@10.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tauri build",
|
||||
@@ -67,7 +67,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdi/font": "7.4.47",
|
||||
"@tauri-apps/api": "^2.1.1",
|
||||
"@tauri-apps/api": "^2.2.0",
|
||||
"@tauri-apps/plugin-deep-link": "^2.2.0",
|
||||
"@tauri-apps/plugin-dialog": "^2.2.0",
|
||||
"@tauri-apps/plugin-fs": "^2.2.0",
|
||||
@@ -87,9 +87,10 @@
|
||||
"jsencrypt": "^3.3.2",
|
||||
"pinia": "^2.3.0",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"sass": "^1.83.0",
|
||||
"qrcode.vue": "^3.6.0",
|
||||
"sass": "^1.83.1",
|
||||
"sass-loader": "^16.0.4",
|
||||
"uuid": "^11.0.3",
|
||||
"uuid": "^11.0.4",
|
||||
"vue": "^3.5.13",
|
||||
"vue-echarts": "^7.0.3",
|
||||
"vue-json-viewer": "^3.0.4",
|
||||
@@ -101,12 +102,12 @@
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.17.0",
|
||||
"@tauri-apps/cli": "2.1.0",
|
||||
"@tauri-apps/cli": "2.2.2",
|
||||
"@types/color-convert": "^2.0.4",
|
||||
"@types/js-md5": "^0.7.2",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/node": "^22.10.5",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/parser": "^8.19.0",
|
||||
"@typescript-eslint/parser": "^8.19.1",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"concurrently": "^9.1.2",
|
||||
"eslint": "^9.17.0",
|
||||
@@ -119,7 +120,7 @@
|
||||
"husky": "^9.1.7",
|
||||
"jsonc-eslint-parser": "^2.4.0",
|
||||
"lint-staged": "^15.3.0",
|
||||
"oxlint": "^0.15.4",
|
||||
"oxlint": "^0.15.5",
|
||||
"prettier": "3.4.2",
|
||||
"stylelint": "^16.12.0",
|
||||
"stylelint-config-idiomatic-order": "^10.0.0",
|
||||
@@ -130,9 +131,9 @@
|
||||
"stylelint-prettier": "^5.0.2",
|
||||
"stylelint-scss": "^6.10.0",
|
||||
"typescript": "^5.7.2",
|
||||
"typescript-eslint": "^8.19.0",
|
||||
"vite": "^6.0.6",
|
||||
"vite-plugin-vue-devtools": "^7.6.8",
|
||||
"typescript-eslint": "^8.19.1",
|
||||
"vite": "^6.0.7",
|
||||
"vite-plugin-vue-devtools": "^7.7.0",
|
||||
"vite-plugin-vuetify": "^2.0.4",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"yaml-eslint-parser": "^1.2.3"
|
||||
|
||||
874
pnpm-lock.yaml
generated
874
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
486
src-tauri/Cargo.lock
generated
486
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -10,15 +10,15 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.3", features = [] }
|
||||
tauri-build = { version = "2.0.4", features = [] }
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.39"
|
||||
log = "0.4.22"
|
||||
serde = { version = "1.0.217", features = ["derive"] }
|
||||
serde_json = "1.0.134"
|
||||
tauri = { version = "2.1.1", features = [] }
|
||||
tauri-utils = "2.1.0"
|
||||
serde_json = "1.0.135"
|
||||
tauri = { version = "2.2.0", features = [] }
|
||||
tauri-utils = "2.1.1"
|
||||
url = "2.5.4"
|
||||
walkdir = "2.5.0"
|
||||
|
||||
|
||||
@@ -37,97 +37,28 @@
|
||||
"core:window:allow-set-focus",
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-unminimize",
|
||||
{
|
||||
"identifier": "fs:allow-exists",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-mkdir",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-dir",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-text-file",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-remove",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-file",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-text-file",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{ "identifier": "fs:allow-exists", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-mkdir", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-read-dir", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-read-text-file", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-remove", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-write-file", "allow": [{ "path": "**" }] },
|
||||
{ "identifier": "fs:allow-write-text-file", "allow": [{ "path": "**" }] },
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://*.miyoushe.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.mihoyo.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://homa.snapgenshin.com/*"
|
||||
},
|
||||
{
|
||||
"url": "https://*.hoyoverse.com/*"
|
||||
}
|
||||
{ "url": "https://*.miyoushe.com/*" },
|
||||
{ "url": "https://*.mihoyo.com/*" },
|
||||
{ "url": "https://homa.snapgenshin.com/*" },
|
||||
{ "url": "https://*.hoyoverse.com/*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "shell:allow-execute",
|
||||
"allow": [
|
||||
{
|
||||
"name": "win_open",
|
||||
"cmd": "explorer",
|
||||
"args": true
|
||||
},
|
||||
{
|
||||
"name": "mac_open",
|
||||
"cmd": "open",
|
||||
"args": true
|
||||
},
|
||||
{
|
||||
"name": "exec-sh",
|
||||
"cmd": "powershell",
|
||||
"args": true
|
||||
}
|
||||
{ "name": "win_open", "cmd": "explorer", "args": true },
|
||||
{ "name": "mac_open", "cmd": "open", "args": true },
|
||||
{ "name": "exec-sh", "cmd": "powershell", "args": true }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -773,6 +773,11 @@
|
||||
"description": "Enables the reparent command without any pre-configured scope.",
|
||||
"commands": { "allow": ["reparent"], "deny": [] }
|
||||
},
|
||||
"allow-set-webview-background-color": {
|
||||
"identifier": "allow-set-webview-background-color",
|
||||
"description": "Enables the set_webview_background_color command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_webview_background_color"], "deny": [] }
|
||||
},
|
||||
"allow-set-webview-focus": {
|
||||
"identifier": "allow-set-webview-focus",
|
||||
"description": "Enables the set_webview_focus command without any pre-configured scope.",
|
||||
@@ -853,6 +858,11 @@
|
||||
"description": "Denies the reparent command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["reparent"] }
|
||||
},
|
||||
"deny-set-webview-background-color": {
|
||||
"identifier": "deny-set-webview-background-color",
|
||||
"description": "Denies the set_webview_background_color command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_webview_background_color"] }
|
||||
},
|
||||
"deny-set-webview-focus": {
|
||||
"identifier": "deny-set-webview-focus",
|
||||
"description": "Denies the set_webview_focus command without any pre-configured scope.",
|
||||
@@ -1100,6 +1110,21 @@
|
||||
"description": "Enables the set_always_on_top command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_always_on_top"], "deny": [] }
|
||||
},
|
||||
"allow-set-background-color": {
|
||||
"identifier": "allow-set-background-color",
|
||||
"description": "Enables the set_background_color command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_background_color"], "deny": [] }
|
||||
},
|
||||
"allow-set-badge-count": {
|
||||
"identifier": "allow-set-badge-count",
|
||||
"description": "Enables the set_badge_count command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_badge_count"], "deny": [] }
|
||||
},
|
||||
"allow-set-badge-label": {
|
||||
"identifier": "allow-set-badge-label",
|
||||
"description": "Enables the set_badge_label command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_badge_label"], "deny": [] }
|
||||
},
|
||||
"allow-set-closable": {
|
||||
"identifier": "allow-set-closable",
|
||||
"description": "Enables the set_closable command without any pre-configured scope.",
|
||||
@@ -1185,6 +1210,11 @@
|
||||
"description": "Enables the set_minimizable command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_minimizable"], "deny": [] }
|
||||
},
|
||||
"allow-set-overlay-icon": {
|
||||
"identifier": "allow-set-overlay-icon",
|
||||
"description": "Enables the set_overlay_icon command without any pre-configured scope.",
|
||||
"commands": { "allow": ["set_overlay_icon"], "deny": [] }
|
||||
},
|
||||
"allow-set-position": {
|
||||
"identifier": "allow-set-position",
|
||||
"description": "Enables the set_position command without any pre-configured scope.",
|
||||
@@ -1445,6 +1475,21 @@
|
||||
"description": "Denies the set_always_on_top command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_always_on_top"] }
|
||||
},
|
||||
"deny-set-background-color": {
|
||||
"identifier": "deny-set-background-color",
|
||||
"description": "Denies the set_background_color command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_background_color"] }
|
||||
},
|
||||
"deny-set-badge-count": {
|
||||
"identifier": "deny-set-badge-count",
|
||||
"description": "Denies the set_badge_count command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_badge_count"] }
|
||||
},
|
||||
"deny-set-badge-label": {
|
||||
"identifier": "deny-set-badge-label",
|
||||
"description": "Denies the set_badge_label command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_badge_label"] }
|
||||
},
|
||||
"deny-set-closable": {
|
||||
"identifier": "deny-set-closable",
|
||||
"description": "Denies the set_closable command without any pre-configured scope.",
|
||||
@@ -1530,6 +1575,11 @@
|
||||
"description": "Denies the set_minimizable command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_minimizable"] }
|
||||
},
|
||||
"deny-set-overlay-icon": {
|
||||
"identifier": "deny-set-overlay-icon",
|
||||
"description": "Denies the set_overlay_icon command without any pre-configured scope.",
|
||||
"commands": { "allow": [], "deny": ["set_overlay_icon"] }
|
||||
},
|
||||
"deny-set-position": {
|
||||
"identifier": "deny-set-position",
|
||||
"description": "Denies the set_position command without any pre-configured scope.",
|
||||
|
||||
@@ -2626,6 +2626,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2706,6 +2711,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2921,6 +2931,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3006,6 +3031,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3266,6 +3296,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3351,6 +3396,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
|
||||
@@ -2626,6 +2626,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2706,6 +2711,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2921,6 +2931,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3006,6 +3031,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3266,6 +3296,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3351,6 +3396,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! @file src/client/mod.rs
|
||||
//! @desc 客户端模块,负责操作米游社客户端
|
||||
//! @since Beta v0.6.7
|
||||
//! @since Beta v0.6.8
|
||||
|
||||
mod menu;
|
||||
mod utils;
|
||||
@@ -8,7 +8,7 @@ mod utils;
|
||||
use tauri::{AppHandle, Manager, WebviewWindowBuilder};
|
||||
use tauri_utils::config::WebviewUrl;
|
||||
|
||||
static BBS_VERSION: &'static str = "2.79.1";
|
||||
static BBS_VERSION: &'static str = "2.80.1";
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn create_mhy_client(handle: AppHandle, func: String, url: String) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<template>
|
||||
<ToGameLogin v-model="showLoginQr" @success="tryGetTokens" />
|
||||
<v-card class="tcu-box">
|
||||
<template #prepend>
|
||||
<v-avatar :image="userInfo.avatar" />
|
||||
@@ -36,12 +37,18 @@
|
||||
</template>
|
||||
<template #actions>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
@click="tryCaptchaLogin()"
|
||||
icon="mdi-cellphone"
|
||||
title="验证码登录"
|
||||
/>
|
||||
<!-- <v-btn-->
|
||||
<!-- variant="outlined"-->
|
||||
<!-- @click="showLoginQr = true"-->
|
||||
<!-- icon="mdi-qrcode-scan"-->
|
||||
<!-- title="扫码登录"-->
|
||||
<!-- />-->
|
||||
<!-- <v-btn-->
|
||||
<!-- variant="outlined"-->
|
||||
<!-- @click="tryCaptchaLogin()"-->
|
||||
<!-- icon="mdi-cellphone"-->
|
||||
<!-- title="验证码登录"-->
|
||||
<!-- />-->
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
@click="confirmRefreshUser(uid!)"
|
||||
@@ -62,6 +69,7 @@
|
||||
variant="outlined"
|
||||
icon="mdi-account-switch"
|
||||
title="切换账户"
|
||||
:disabled="accounts.length === 0"
|
||||
@click="showMenu"
|
||||
v-bind="props"
|
||||
/>
|
||||
@@ -90,10 +98,25 @@
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-menu location="start">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn variant="outlined" icon="mdi-login" title="登录" v-bind="props" />
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item @click="addByCookie()" append-icon="mdi-account-plus">
|
||||
<v-list-item-title>手动添加</v-list-item-title>
|
||||
<v-list-item-subtitle>手动输入Cookie</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
<v-list-item @click="tryCaptchaLogin()" append-icon="mdi-cellphone">
|
||||
<v-list-item-title>验证码登录</v-list-item-title>
|
||||
<v-list-item-subtitle>使用手机号登录</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
<v-list-item @click="showLoginQr = true" append-icon="mdi-qrcode-scan">
|
||||
<v-list-item-title>扫码登录</v-list-item-title>
|
||||
<v-list-item-subtitle>使用米游社扫码登录</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
@@ -104,10 +127,11 @@ import showDialog from "@comp/func/dialog.js";
|
||||
import showGeetest from "@comp/func/geetest.js";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import ToGameLogin from "@comp/pageConfig/tco-gameLogin.vue";
|
||||
import Mys from "@Mys/index.js";
|
||||
import TSUserAccount from "@Sqlite/modules/userAccount.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, shallowRef } from "vue";
|
||||
import { computed, ref, shallowRef } from "vue";
|
||||
|
||||
import { useAppStore } from "@/store/modules/app.js";
|
||||
import { useUserStore } from "@/store/modules/user.js";
|
||||
@@ -119,6 +143,7 @@ import TakumiApi from "@/web/request/takumiReq.js";
|
||||
const { isLogin } = storeToRefs(useAppStore());
|
||||
const { uid, briefInfo, cookie, account } = storeToRefs(useUserStore());
|
||||
|
||||
const showLoginQr = ref<boolean>(false);
|
||||
const accounts = shallowRef<Array<TGApp.App.Account.User>>([]);
|
||||
const gameAccounts = shallowRef<Array<TGApp.Sqlite.Account.Game>>([]);
|
||||
const userInfo = computed<TGApp.App.Account.BriefInfo>(() => {
|
||||
@@ -131,37 +156,7 @@ const userInfo = computed<TGApp.App.Account.BriefInfo>(() => {
|
||||
};
|
||||
});
|
||||
|
||||
async function tryCaptchaLogin(): Promise<void> {
|
||||
const phone = await showDialog.input("请输入手机号", "+86");
|
||||
if (!phone) {
|
||||
showSnackbar.cancel("已取消验证码登录");
|
||||
return;
|
||||
}
|
||||
const phoneReg = /^1[3-9]\d{9}$/;
|
||||
if (!phoneReg.test(phone)) {
|
||||
showSnackbar.warn("请输入正确的手机号");
|
||||
return;
|
||||
}
|
||||
const actionType = await tryGetCaptcha(phone);
|
||||
if (!actionType) return;
|
||||
showSnackbar.success(`已发送验证码到 ${phone}`);
|
||||
const captcha = await showDialog.input("请输入验证码", "验证码:", undefined, false);
|
||||
if (!captcha) {
|
||||
showSnackbar.warn("输入验证码为空");
|
||||
return;
|
||||
}
|
||||
const loginResp = await tryLoginByCaptcha(phone, captcha, actionType);
|
||||
if (!loginResp) return;
|
||||
await showLoading.start("正在尝试登录...");
|
||||
const ck: TGApp.App.Account.Cookie = {
|
||||
account_id: loginResp.user_info.aid,
|
||||
ltuid: loginResp.user_info.aid,
|
||||
stuid: loginResp.user_info.aid,
|
||||
mid: loginResp.user_info.mid,
|
||||
cookie_token: "",
|
||||
stoken: loginResp.token.token,
|
||||
ltoken: "",
|
||||
};
|
||||
async function tryGetTokens(ck: TGApp.App.Account.Cookie): Promise<void> {
|
||||
await showLoading.update("正在获取 LToken");
|
||||
const ltokenRes = await PassportApi.lToken.get(ck);
|
||||
if (typeof ltokenRes !== "string") {
|
||||
@@ -231,6 +226,40 @@ async function tryCaptchaLogin(): Promise<void> {
|
||||
showSnackbar.success("成功登录!");
|
||||
}
|
||||
|
||||
async function tryCaptchaLogin(): Promise<void> {
|
||||
const phone = await showDialog.input("请输入手机号", "+86");
|
||||
if (!phone) {
|
||||
showSnackbar.cancel("已取消验证码登录");
|
||||
return;
|
||||
}
|
||||
const phoneReg = /^1[3-9]\d{9}$/;
|
||||
if (!phoneReg.test(phone)) {
|
||||
showSnackbar.warn("请输入正确的手机号");
|
||||
return;
|
||||
}
|
||||
const actionType = await tryGetCaptcha(phone);
|
||||
if (!actionType) return;
|
||||
showSnackbar.success(`已发送验证码到 ${phone}`);
|
||||
const captcha = await showDialog.input("请输入验证码", "验证码:", undefined, false);
|
||||
if (!captcha) {
|
||||
showSnackbar.warn("输入验证码为空");
|
||||
return;
|
||||
}
|
||||
const loginResp = await tryLoginByCaptcha(phone, captcha, actionType);
|
||||
if (!loginResp) return;
|
||||
await showLoading.start("正在尝试登录...");
|
||||
const ck: TGApp.App.Account.Cookie = {
|
||||
account_id: loginResp.user_info.aid,
|
||||
ltuid: loginResp.user_info.aid,
|
||||
stuid: loginResp.user_info.aid,
|
||||
mid: loginResp.user_info.mid,
|
||||
cookie_token: "",
|
||||
stoken: loginResp.token.token,
|
||||
ltoken: "",
|
||||
};
|
||||
await tryGetTokens(ck);
|
||||
}
|
||||
|
||||
async function refreshUser(uid: string) {
|
||||
let account = await TSUserAccount.account.getAccount(uid);
|
||||
if (!account) {
|
||||
@@ -375,6 +404,7 @@ async function tryGetCaptcha(phone: string, aigis?: string): Promise<string | fa
|
||||
showSnackbar.error(`[${captchaResp.retcode}] ${captchaResp.message}`);
|
||||
return false;
|
||||
}
|
||||
// @ts-expect-error type {} is not assignable to type string
|
||||
const aigisResp: TGApp.Plugins.Mys.CaptchaLogin.CaptchaAigis = JSON.parse(captchaResp.data);
|
||||
const resp = await showGeetest(JSON.parse(aigisResp.data));
|
||||
const aigisStr = `${aigisResp.session_id};${btoa(JSON.stringify(resp))}`;
|
||||
|
||||
129
src/components/pageConfig/tco-gameLogin.vue
Normal file
129
src/components/pageConfig/tco-gameLogin.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<TOverlay v-model="model" hide blur-val="20px">
|
||||
<div class="tog-box">
|
||||
<div class="tog-top">
|
||||
<div class="tog-title">请使用米游社进行扫码操作</div>
|
||||
</div>
|
||||
<div class="tog-mid">
|
||||
<qrcode-vue
|
||||
v-if="codeData"
|
||||
class="tog-qr"
|
||||
:value="codeData.url"
|
||||
render-as="svg"
|
||||
:background="'var(--box-bg-1)'"
|
||||
foreground="var(--box-text-1)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import QrcodeVue from "qrcode.vue";
|
||||
import { onUnmounted, shallowRef, watch } from "vue";
|
||||
|
||||
import PassportReq from "@/web/request/passportReq.js";
|
||||
|
||||
type ToGameLoginEmits = (e: "success", data: TGApp.App.Account.Cookie) => void;
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
let cycleTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
const model = defineModel<boolean>({ default: false });
|
||||
const emits = defineEmits<ToGameLoginEmits>();
|
||||
const codeData = shallowRef<TGApp.BBS.GameLogin.GetLoginQrData>();
|
||||
|
||||
watch(model, async (value) => {
|
||||
if (value) {
|
||||
await freshQr();
|
||||
cycleTimer = setInterval(cycleGetData, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
async function freshQr(): Promise<void> {
|
||||
const res = await PassportReq.qrLogin.create();
|
||||
if ("retcode" in res) {
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
return;
|
||||
}
|
||||
codeData.value = res;
|
||||
}
|
||||
|
||||
async function cycleGetData() {
|
||||
if (cycleTimer === null || !codeData.value) return;
|
||||
const res = await PassportReq.qrLogin.query(codeData.value.ticket);
|
||||
console.log(res);
|
||||
if ("retcode" in res) {
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
if (res.retcode === -106) {
|
||||
await freshQr();
|
||||
} else {
|
||||
clearInterval(cycleTimer);
|
||||
cycleTimer = null;
|
||||
model.value = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (res.status === "Created" || res.status === "Scanned") return;
|
||||
if (res.status === "Confirmed") {
|
||||
clearInterval(cycleTimer);
|
||||
cycleTimer = null;
|
||||
const ck: TGApp.App.Account.Cookie = {
|
||||
mid: res.user_info.mid,
|
||||
stoken: res.tokens[0].token,
|
||||
stuid: res.user_info.aid,
|
||||
account_id: res.user_info.aid,
|
||||
cookie_token: "",
|
||||
ltoken: "",
|
||||
ltuid: "",
|
||||
};
|
||||
emits("success", ck);
|
||||
model.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (cycleTimer !== null) clearInterval(cycleTimer);
|
||||
cycleTimer = null;
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tog-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: var(--box-bg-1);
|
||||
color: var(--app-page-content);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tog-top {
|
||||
border-bottom: 1px solid var(--common-shadow-4);
|
||||
font-family: var(--font-title);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tog-title {
|
||||
color: var(--common-text-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.tog-mid {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
border-radius: 5px;
|
||||
aspect-ratio: 1;
|
||||
background: var(--box-bg-2);
|
||||
}
|
||||
|
||||
.tog-qr {
|
||||
width: 256px;
|
||||
height: 256px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,11 @@
|
||||
/**
|
||||
* @file plugins/Mys/index.ts
|
||||
* @description Mys plugin index
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.6.8
|
||||
*/
|
||||
|
||||
import * as ApiHub from "./request/apiHubReq.js";
|
||||
import { doCaptchaLogin, getCaptcha } from "./request/doCaptchaLogin.js";
|
||||
import { getLoginQr, getLoginStatus } from "./request/doGameLogin.js";
|
||||
import { getGachaData, getPositionData } from "./request/obcReq.js";
|
||||
import * as Painter from "./request/painterReq.js";
|
||||
import * as Post from "./request/postReq.js";
|
||||
@@ -21,7 +20,7 @@ const Mys = {
|
||||
Gacha: { get: getGachaData, card: getGachaCard },
|
||||
Position: { get: getPositionData, card: getPositionCard },
|
||||
Lottery: { get: Painter.lotteryUserShow, card: getLotteryCard },
|
||||
User: { getQr: getLoginQr, getData: getLoginStatus, getCaptcha, login: doCaptchaLogin },
|
||||
User: { getCaptcha, login: doCaptchaLogin },
|
||||
};
|
||||
|
||||
export default Mys;
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/request/doGameLogin
|
||||
* @description 获取 gameToken,曲线获取 stoken
|
||||
* @since Beta v0.5.0
|
||||
*/
|
||||
|
||||
import TGHttp from "@/utils/TGHttp.js";
|
||||
import { getDeviceInfo } from "@/utils/toolFunc.js";
|
||||
import { getRequestHeader } from "@/web/utils/getRequestHeader.js";
|
||||
|
||||
const APP_ID = 8;
|
||||
|
||||
/**
|
||||
* @description 获取登录二维码
|
||||
* @since Beta v0.5.0
|
||||
* @returns {Promise<TGApp.Plugins.Mys.GameLogin.GetLoginQrData|TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
export async function getLoginQr(): Promise<
|
||||
TGApp.Plugins.Mys.GameLogin.GetLoginQrData | TGApp.BBS.Response.Base
|
||||
> {
|
||||
const data: Record<string, string | number> = {
|
||||
app_id: APP_ID,
|
||||
device: getDeviceInfo("device_id"),
|
||||
};
|
||||
const resp = await TGHttp<
|
||||
TGApp.Plugins.Mys.GameLogin.GetLoginQrResponse | TGApp.BBS.Response.Base
|
||||
>("https://hk4e-sdk.mihoyo.com/hk4e_cn/combo/panda/qrcode/fetch", {
|
||||
method: "POST",
|
||||
headers: getRequestHeader({}, "POST", data),
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录状态
|
||||
* @since Beta v0.5.0
|
||||
* @param {string} ticket 二维码 ticket
|
||||
* @returns {Promise<TGApp.Plugins.Mys.GameLogin.GetLoginStatusData | TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
export async function getLoginStatus(
|
||||
ticket: string,
|
||||
): Promise<TGApp.Plugins.Mys.GameLogin.GetLoginStatusData | TGApp.BBS.Response.Base> {
|
||||
const data: Record<string, string | number> = {
|
||||
app_id: APP_ID,
|
||||
device: getDeviceInfo("device_id"),
|
||||
ticket,
|
||||
};
|
||||
const resp = await TGHttp<
|
||||
TGApp.Plugins.Mys.GameLogin.GetLoginStatusResponse | TGApp.BBS.Response.Base
|
||||
>("https://hk4e-sdk.mihoyo.com/hk4e_cn/combo/panda/qrcode/query", {
|
||||
method: "POST",
|
||||
headers: getRequestHeader({}, "POST", data),
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
102
src/plugins/Mys/types/GameLogin.d.ts
vendored
102
src/plugins/Mys/types/GameLogin.d.ts
vendored
@@ -1,102 +0,0 @@
|
||||
/**
|
||||
* @file plugins/Mys/types/GameLogin.d.ts
|
||||
* @description Mys 插件 Game 登录类型定义文件
|
||||
* @since Beta v0.4.4
|
||||
*/
|
||||
|
||||
/**
|
||||
* @description Mys 插件 Game 登录类型
|
||||
* @since Beta v0.4.4
|
||||
* @namespace TGApp.Plugins.Mys.GameLogin
|
||||
* @memberof TGApp.Plugins.Mys
|
||||
*/
|
||||
declare namespace TGApp.Plugins.Mys.GameLogin {
|
||||
/**
|
||||
* @description 获取登录二维码返回数据
|
||||
* @since Beta v0.3.0
|
||||
* @interface GetLoginQrResponse
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {GetLoginQrData} data 数据
|
||||
* @return GetLoginQrResponse
|
||||
*/
|
||||
interface GetLoginQrResponse extends TGApp.BBS.Response.BaseWithData {
|
||||
data: GetLoginQrData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录二维码返回数据
|
||||
* @since Beta v0.3.0
|
||||
* @interface GetLoginQrData
|
||||
* @property {string} url 二维码链接
|
||||
* @return GetLoginQrData
|
||||
*/
|
||||
interface GetLoginQrData {
|
||||
url: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据
|
||||
* @since Beta v0.3.0
|
||||
* @interface GetLoginStatusResponse
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {GetLoginStatusData} data 数据
|
||||
* @return GetLoginStatusResponse
|
||||
*/
|
||||
interface GetLoginStatusResponse extends TGApp.BBS.Response.BaseWithData {
|
||||
data: GetLoginStatusData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据
|
||||
* @since Beta v0.3.0
|
||||
* @interface GetLoginStatusData
|
||||
* @property {string} stat 状态 // Init: 未扫码,Scanned: 已扫码,Confirmed: 已确认
|
||||
* @property {StatusPayload} payload 状态数据
|
||||
* @return GetLoginStatusData
|
||||
*/
|
||||
interface GetLoginStatusData {
|
||||
stat: string;
|
||||
payload: StatusPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据
|
||||
* @since Beta v0.3.0
|
||||
* @interface StatusPayload
|
||||
* @property {string} ext 未知
|
||||
* @property {string} proto 未知
|
||||
* @property {string} raw 序列化数据,反序列化后是 {uid: string, token: string}
|
||||
* @return StatusPayload
|
||||
*/
|
||||
interface StatusPayload {
|
||||
ext: string;
|
||||
proto: string;
|
||||
raw: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 反序列化后的登录状态数据
|
||||
* @since Beta v0.4.4
|
||||
* @interface StatusPayloadRawOpen
|
||||
* @property {string} uid 用户 UID
|
||||
* @property {string} token 用户 token
|
||||
* @return StatusPayloadRawOpen
|
||||
*/
|
||||
interface StatusPayloadRawOpen {
|
||||
open_id: string;
|
||||
open_token: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 反序列化后的登录状态数据
|
||||
* @since Beta v0.4.4
|
||||
* @interface StatusPayloadRawAccount
|
||||
* @property {string} uid 用户 UID
|
||||
* @property {string} token 用户 token
|
||||
* @return StatusPayloadRawOpen
|
||||
*/
|
||||
interface StatusPayloadRawAccount {
|
||||
uid: string;
|
||||
token: string;
|
||||
}
|
||||
}
|
||||
152
src/types/BBS/GameLogin.d.ts
vendored
Normal file
152
src/types/BBS/GameLogin.d.ts
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file types/BBS/GameLogin.d.ts
|
||||
* @description Mys 插件 Game 登录类型定义文件
|
||||
* @since Beta v0.6.8
|
||||
*/
|
||||
|
||||
declare namespace TGApp.BBS.GameLogin {
|
||||
/**
|
||||
* @description 获取登录二维码返回数据
|
||||
* @since Beta v0.3.0
|
||||
* @interface GetLoginQrResponse
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {GetLoginQrData} data 数据
|
||||
* @return GetLoginQrResponse
|
||||
*/
|
||||
type GetLoginQrResponse = TGApp.BBS.Response.BaseWithData & { data: GetLoginQrData };
|
||||
|
||||
/**
|
||||
* @description 获取登录二维码返回数据
|
||||
* @since Beta v0.6.8
|
||||
* @interface GetLoginQrData
|
||||
* @property {string} ticket 二维码 ticket,用于查询登录状态
|
||||
* @property {string} url 二维码链接
|
||||
* @return GetLoginQrData
|
||||
*/
|
||||
type GetLoginQrData = { ticket: string; url: string };
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据
|
||||
* @since Beta v0.3.0
|
||||
* @interface GetLoginStatusResponse
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {GetLoginStatusData} data 数据
|
||||
* @return GetLoginStatusResponse
|
||||
*/
|
||||
type GetLoginStatusResponse = TGApp.BBS.Response.BaseWithData & { data: GetLoginStatusData };
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据-通用
|
||||
* @since Beta v0.6.8
|
||||
* @interface GetLoginStatusDataCommon
|
||||
* @property {string} app_id 应用 ID
|
||||
* @property {number} client_type 客户端类型
|
||||
* @property {string} created_at 创建时间
|
||||
* @property {string} ext 未知
|
||||
* @property {boolean} need_realperson 是否需要真人验证
|
||||
* @property {unknown} realname_info 未知
|
||||
* @property {string} scan_game_biz 未知
|
||||
* @property {string} scanned_at 扫描时间
|
||||
* @return GetLoginStatusDataCommon
|
||||
*/
|
||||
type GetLoginStatusDataCommon = {
|
||||
app_id: string;
|
||||
client_type: number;
|
||||
created_at: string;
|
||||
ext: string;
|
||||
need_realperson: boolean;
|
||||
realname_info: unknown;
|
||||
scan_game_biz: string;
|
||||
scanned_at: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据-未确认
|
||||
* @since Beta v0.6.8
|
||||
* @interface GetLoginStatusDataUnconfirmed
|
||||
* @extends GetLoginStatusDataCommon
|
||||
* @property {"Created" | "Scanned"} status 状态
|
||||
* @return GetLoginStatusDataUnconfirmed
|
||||
*/
|
||||
type GetLoginStatusDataUnconfirmed = GetLoginStatusDataCommon & {
|
||||
status: "Created" | "Scanned";
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据-已确认
|
||||
* @since Beta v0.6.8
|
||||
* @interface GetLoginStatusDataConfirmed
|
||||
* @extends GetLoginStatusDataCommon
|
||||
*/
|
||||
type GetLoginStatusDataConfirmed = GetLoginStatusDataCommon & {
|
||||
status: "Confirmed";
|
||||
tokens: Array<GetLoginStatusDataToken>;
|
||||
user_info: GetLoginStatusDataUserInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据-Token
|
||||
* @since Beta v0.6.8
|
||||
* @interface GetLoginStatusDataToken
|
||||
* @property {string} token token
|
||||
* @property {number} token_type token 类型
|
||||
* @return GetLoginStatusDataToken
|
||||
*/
|
||||
type GetLoginStatusDataToken = { token: string; token_type: number };
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据-用户信息
|
||||
* @since Beta v0.6.8
|
||||
* @interface GetLoginStatusDataUserInfo
|
||||
* @property {string} account_name 账号名称
|
||||
* @property {string} aid 账号 ID
|
||||
* @property {string} area_code 区域代码
|
||||
* @property {string} country 国家
|
||||
* @property {string} email 邮箱
|
||||
* @property {string} identity_code 身份证号
|
||||
* @property {number} is_email_verify 是否验证邮箱
|
||||
* @property {Array<unknown>} links 链接
|
||||
* @property {string} mid mid
|
||||
* @property {string} mobile 手机号
|
||||
* @property {string} password_time 密码时间
|
||||
* @property {string} realname 真实姓名
|
||||
* @property {string} rebind_area_code 重新绑定区域代码
|
||||
* @property {string} rebind_mobile 重新绑定手机号
|
||||
* @property {string} rebind_mobile_time 重新绑定手机号时间
|
||||
* @property {string} safe_area_code 安全区域代码
|
||||
* @property {string} safe_mobile 安全手机号
|
||||
* @property {string} unmasked_email 未屏蔽邮箱
|
||||
* @property {number} unmasked_email_type 未屏蔽邮箱类型
|
||||
* @return GetLoginStatusDataUserInfo
|
||||
*/
|
||||
type GetLoginStatusDataUserInfo = {
|
||||
account_name: string;
|
||||
aid: string;
|
||||
area_code: string;
|
||||
country: string;
|
||||
email: string;
|
||||
identity_code: string;
|
||||
is_email_verify: number;
|
||||
links: Array<unknown>;
|
||||
mid: string;
|
||||
mobile: string;
|
||||
password_time: string;
|
||||
realname: string;
|
||||
rebind_area_code: string;
|
||||
rebind_mobile: string;
|
||||
rebind_mobile_time: string;
|
||||
safe_area_code: string;
|
||||
safe_mobile: string;
|
||||
unmasked_email: string;
|
||||
unmasked_email_type: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 获取登录状态返回数据
|
||||
* @since Beta v0.6.8
|
||||
* @interface GetLoginStatusData
|
||||
* @property {GetLoginStatusDataUnconfirmed | GetLoginStatusDataConfirmed} data 数据
|
||||
* @return GetLoginStatusData
|
||||
*/
|
||||
type GetLoginStatusData = GetLoginStatusDataUnconfirmed | GetLoginStatusDataConfirmed;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
/**
|
||||
* @file web/constant/bbs.ts
|
||||
* @description 常量-应用数据
|
||||
* @since Beta v0.6.7
|
||||
* @since Beta v0.6.8
|
||||
*/
|
||||
|
||||
export const BBS_VERSION: Readonly<string> = "2.79.1";
|
||||
export const BBS_VERSION: Readonly<string> = "2.80.1";
|
||||
export const BBS_UA_MOBILE: Readonly<string> = `Mozilla/5.0 (Linux; Android 12) Mobile miHoYoBBS/${BBS_VERSION}`;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
/**
|
||||
* @file web/request/passportReq.ts
|
||||
* @description Passport 相关请求
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.6.8
|
||||
*/
|
||||
import TGHttp from "@/utils/TGHttp.js";
|
||||
import { getDeviceInfo } from "@/utils/toolFunc.js";
|
||||
import { getRequestHeader } from "@/web/utils/getRequestHeader.js";
|
||||
|
||||
// PassportApiBaseUrl => pAbu
|
||||
const pAbu: Readonly<string> = "https://passport-api.mihoyo.com/";
|
||||
// PassportV4ApiBaseUrl => p4Abu
|
||||
const p4Abu: Readonly<string> = "https://passport-api-v4.mihoyo.com/";
|
||||
// HoyoLauncherVersion
|
||||
const hlv: Readonly<string> = "1.3.3.182";
|
||||
|
||||
/**
|
||||
* @description 获取登录ticket
|
||||
@@ -40,6 +43,30 @@ async function createAuthTicketByGameBiz(
|
||||
return resp.data.ticket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建登录二维码
|
||||
* @since Beta v0.6.8
|
||||
* @returns {Promise<TGApp.BBS.Response.Base|TGApp.BBS.GameLogin.GetLoginQrData>}
|
||||
*/
|
||||
async function createQrLogin(): Promise<
|
||||
TGApp.BBS.Response.Base | TGApp.BBS.GameLogin.GetLoginQrData
|
||||
> {
|
||||
const resp = await TGHttp<TGApp.BBS.GameLogin.GetLoginQrResponse>(
|
||||
`${pAbu}account/ma-cn-passport/app/createQRLogin`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"x-rpc-device_id": getDeviceInfo("device_id"),
|
||||
"user-agent": `HYPContainer/${hlv}`,
|
||||
"x-rpc-app_id": "ddxf5dufpuyo",
|
||||
"x-rpc-client_type": "3",
|
||||
},
|
||||
},
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 根据 stoken 获取 cookie_token
|
||||
* @since Beta v0.6.3
|
||||
@@ -78,6 +105,32 @@ async function getLTokenBySToken(
|
||||
return resp.data.ltoken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录状态
|
||||
* @since Beta v0.6.8
|
||||
* @param {string} ticket - 二维码 ticket
|
||||
* @returns {Promise<TGApp.BBS.Response.Base|TGApp.BBS.GameLogin.GetLoginStatusData>}
|
||||
*/
|
||||
async function queryLoginStatus(
|
||||
ticket: string,
|
||||
): Promise<TGApp.BBS.Response.Base | TGApp.BBS.GameLogin.GetLoginStatusData> {
|
||||
const resp = await TGHttp<TGApp.BBS.GameLogin.GetLoginStatusResponse>(
|
||||
`${pAbu}account/ma-cn-passport/app/queryQRLoginStatus`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"x-rpc-device_id": getDeviceInfo("device_id"),
|
||||
"user-agent": `HYPContainer/${hlv}`,
|
||||
"x-rpc-app_id": "ddxf5dufpuyo",
|
||||
"x-rpc-client_type": "3",
|
||||
},
|
||||
body: JSON.stringify({ ticket }),
|
||||
},
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 验证 ltoken 有效性,返回 mid
|
||||
* @since Beta v0.6.5
|
||||
@@ -102,6 +155,7 @@ const PassportApi = {
|
||||
authTicket: createAuthTicketByGameBiz,
|
||||
cookieToken: getCookieAccountInfoBySToken,
|
||||
lToken: { get: getLTokenBySToken, verify: verifyLToken },
|
||||
qrLogin: { create: createQrLogin, query: queryLoginStatus },
|
||||
};
|
||||
|
||||
export default PassportApi;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file web/utils/getRequestHeader.ts
|
||||
* @description 获取请求头
|
||||
* @since Beta v0.6.7
|
||||
* @since Beta v0.6.8
|
||||
*/
|
||||
|
||||
import Md5 from "js-md5";
|
||||
@@ -24,12 +24,12 @@ const enum SaltType {
|
||||
|
||||
/**
|
||||
* @description salt 值
|
||||
* @version 2.79.1
|
||||
* @version 2.80.1
|
||||
* @since Beta v0.6.7
|
||||
*/
|
||||
const Salt: Readonly<Record<keyof typeof SaltType, string>> = {
|
||||
K2: "eOzxpHXVGBVdFBtkbkTvwyCgRpqRFeBr",
|
||||
LK2: "AbuxbruiFDIgxLXksUNMAMvDyciznofM",
|
||||
K2: "G1rXOpMLQS77VPWEGycOSxekCTZe2Q8M",
|
||||
LK2: "sd1e1gQJuvqBfZxas1oeAACXzbim5cge",
|
||||
X4: "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs",
|
||||
X6: "t0qEgfub6cvueAPgR5m9aQWWVciEer7v",
|
||||
PROD: "t0qEgfub6cvueAPgR5m9aQWWVciEer7v",
|
||||
|
||||
Reference in New Issue
Block a user