Compare commits

...

6 Commits

Author SHA1 Message Date
BTMuli
dc03edd30b 🚀 v0.8.8 2025-12-03 20:30:48 +08:00
BTMuli
d18b6bb898 ♻️ 代码重构提取 2025-12-03 20:30:28 +08:00
BTMuli
0f107abde6 🐛 重构管理员权限重启逻辑 2025-12-03 19:58:03 +08:00
BTMuli
46cf40734f 🐛 修复成就数据读取异常 2025-12-03 18:53:35 +08:00
BTMuli
676ef8e8ee 🚀 v0.8.7 2025-12-03 10:24:27 +08:00
BTMuli
5d8ea639b8 🍱 更新成就&卡池数据 2025-12-03 10:22:07 +08:00
17 changed files with 277 additions and 167 deletions

View File

@@ -2,12 +2,43 @@
Author: 目棃
Description: CHANGELOG
Date: 2025-09-09
Update: 2025-11-19
Update: 2025-12-03
---
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2025-09-09 14:30:56`
>
> 更新于 `2025-11-19 14:08:20`
> 更新于 `2025-12-03 20:02:17`
## [0.8.8](https://github.com/BTMuli/TeyvatGuide/releases/v0.8.8) (2025-12-03)
- 🐛 修复成就数据读取异常
- 🐛 重构管理员权限重启逻辑
## [0.8.7](https://github.com/BTMuli/TeyvatGuide/releases/v0.8.7) (2025-12-03)
- 🍱 更新 6.2 版本资源
- ✨ 帖子搜索支持“最新”“最热”排序
- ✨ 登录支持 Gt4 验证 [`#162`](https://github.com/BTMuli/TeyvatGuide/issues/162)
- ✨ 帖子视图支持窄视图模式,**未完全适配所有组件,可能存在显示异常**
- ✨ 支持通过内置 Yae 自动获取成就数据 [`#142`](https://github.com/BTMuli/TeyvatGuide/issues/142)
- 🐛 修复无法手动关闭极验验证弹窗
- 🐛 修复数据刷新后渲染异常 [`#163`](https://github.com/BTMuli/TeyvatGuide/issues/163)
- 🐛 重构祈愿图表,修复祈愿日历没有下拉条 [`#165`](https://github.com/BTMuli/TeyvatGuide/issues/165)
- 🐛 修复 MacOS 下极验验证浮窗加载异常 [`#164`](https://github.com/BTMuli/TeyvatGuide/issues/164)
- 🐛 重构回复浮窗处理,调整 UI ,修复滚动异常 [`#168`](https://github.com/BTMuli/TeyvatGuide/issues/168)
- 🐛 修复自定义表情格式解析异常,增加文本清晰度
- 🐛 调整回复按钮展示判断,修复特定条件下的数据对应异常
- 🐛 修复角色 Wiki 左侧列表顺序概率异常
- ✏️ 修正通过 Yae 导入成就的文本错误
- ✏️ 修正清除缓存后的提示文本
- 🚸 执行脚本时不允许切换账号
- 🚸 调整外部导入祈愿记录时进度显示逻辑,导入后刷新页面
- 🚸 增加部分 UI 在浅色模式下的可见度
- 🚸 账号相关操作(添加,切换)移至侧栏 [`#170`](https://github.com/BTMuli/TeyvatGuide/issues/170)
- 🚸 侧栏添加启动入口,满足条件时显示
- 🚸 完善角色 Wiki 侧边栏奇偶点击处理
- 👽️ 完善前瞻识别规则,增加空列表处理
- 📝 更新Q群链接
## [0.8.6](https://github.com/BTMuli/TeyvatGuide/releases/v0.8.6) (2025-11-19)

View File

@@ -2,16 +2,20 @@
Author: 目棃
Description: 说明文档
Date: 2023-03-05
Update: 2025-11-19
Update: 2025-12-03
---
> 本文档 [`Frontmatter`](https://github.com/BTMuli/MuCli#Frontmatter) 由 [MuCli](https://github.com/BTMuli/Mucli) 自动生成于 `2023-03-05 14:41:55`
>
> 更新于 `2025-11-19 13:21:38`
> 更新于 `2025-12-03 10:22:51`
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/BTMuli/TeyvatGuide) ![](https://img.shields.io/github/last-commit/BTMuli/TeyvatGuide) ![](https://img.shields.io/github/commits-since/BTMuli/TeyvatGuide/latest?include_prereleases)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/BTMuli/TeyvatGuide)
![](https://img.shields.io/badge/UIAF-v1.1-orange?style=for-the-badge) ![](https://img.shields.io/badge/UIGF-v3.0-red?style=for-the-badge) ![](https://img.shields.io/badge/UIGF-v4.1-red?style=for-the-badge) ![](https://img.shields.io/github/license/BTMuli/TeyvatGuide?style=for-the-badge)
[![](https://img.shields.io/github/last-commit/BTMuli/TeyvatGuide)](https://github.com/BTMuli/TeyvatGuide/commits) [![](https://img.shields.io/github/commits-since/BTMuli/TeyvatGuide/latest?include_prereleases)](https://github.com/BTMuli/TeyvatGuide/commits)
[![](https://img.shields.io/badge/UIAF-v1.1-orange?style=for-the-badge)](./docs/standards/UIAF.md) [![](https://img.shields.io/badge/UIGF-v3.0-red?style=for-the-badge)](./docs/standards/UIGF3.md) [![](https://img.shields.io/badge/UIGF-v4.1-red?style=for-the-badge)](./docs/standards/UIGF.md)
[![](https://img.shields.io/github/license/BTMuli/TeyvatGuide?style=for-the-badge)](./LICENSE)
<div style="width: 100%; text-align: center; margin: 0 auto;">
<img alt="icon" src="https://s2.loli.net/2023/10/19/Y5DpBQRy3usLHEb.png" />
@@ -49,7 +53,7 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
- [x] 米游社官方帖获取(支持通过 ID 获取)
- [x] 米游社各分区帖子获取(支持通过 ID 获取)
- [x] 米游社话题帖子获取(通过话题点击跳转)
- [x] 成就管理UIAF v1.1),支持 [`Yae`](https://github.com/HolographicHat/Yae) 导入
- [x] 成就管理UIAF v1.1),支持 [`Yae`](https://github.com/HolographicHat/Yae) 导入 & 自动导入内置Yae
- [x] 祈愿管理UIGF v3.0UIGF v4.1
- [x] 留影叙佳期画片查看
- [x] 帖子收藏
@@ -102,7 +106,6 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
- UIAF[UIAF v1.1](docs/standards/UIAF.md)
- UIGF[UIGF v3.0](docs/standards/UIGF3.md)[UIGF v4.0](docs/standards/UIGF.md)
- [macOS 平台门禁属性导致应用无法打开应用的修复指引](docs/macos-gatekeeper/README.md)
- [隐私政策](https://app.btmuli.ink/docs/TeyvatGuide/privacy.html)
- [如何导入胡桃数据库](https://app.btmuli.ink/docs/TeyvatGuide/import-hutao-db.html)
## 特定项目 / Special Project
@@ -147,5 +150,6 @@ Game Tool for Genshin Impact player, supports Windows and macOS.
- [amos-data](https://github.com/yuehaiteam/amos-data)
- [MihoyoBBSTools](https://github.com/Womsxd/MihoyoBBSTools)
- [nonebot-plugin-mystool](https://github.com/Ljzd-PRO/nonebot-plugin-mystool)
- [Yae](https://github.com/HolographicHat/Yae)
[![Star History Chart](https://api.star-history.com/svg?repos=BTMuli/TeyvatGuide&type=Timeline)](https://star-history.com/#BTMuli/TeyvatGuide&Timeline)

View File

@@ -1,6 +1,6 @@
{
"name": "teyvatguide",
"version": "0.8.6",
"version": "0.8.8",
"description": "Game Tool for GenshinImpact player",
"private": true,
"packageManager": "pnpm@10.24.0",

28
src-tauri/Cargo.lock generated
View File

@@ -4,7 +4,7 @@ version = 4
[[package]]
name = "TeyvatGuide"
version = "0.8.6"
version = "0.8.8"
dependencies = [
"chrono",
"log",
@@ -2398,9 +2398,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.28"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
dependencies = [
"value-bag",
]
@@ -5011,7 +5011,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-deep-link"
version = "2.4.5"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"dunce",
"plist",
@@ -5031,7 +5031,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-dialog"
version = "2.4.2"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"log",
"raw-window-handle",
@@ -5048,7 +5048,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-fs"
version = "2.4.4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"anyhow",
"dunce",
@@ -5069,7 +5069,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-http"
version = "2.5.4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"bytes",
"cookie_store",
@@ -5092,7 +5092,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-log"
version = "2.7.1"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"android_logger",
"byte-unit",
@@ -5113,7 +5113,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-opener"
version = "2.5.2"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"dunce",
"glob",
@@ -5134,7 +5134,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-os"
version = "2.3.2"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"gethostname",
"log",
@@ -5151,7 +5151,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-process"
version = "2.3.1"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"tauri",
"tauri-plugin",
@@ -5160,7 +5160,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-shell"
version = "2.3.3"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"encoding_rs",
"log",
@@ -5180,7 +5180,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-single-instance"
version = "2.3.6"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"serde",
"serde_json",
@@ -5194,7 +5194,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-sql"
version = "2.3.1"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#1483c63101aef6ee7ac4701ec91f0a2e5c912ad4"
source = "git+ssh://git@github.com/tauri-apps/plugins-workspace.git?branch=v2#d9d51eb8ea2fd6ce3298ec0dc370cc04351a9b98"
dependencies = [
"futures-core",
"indexmap 2.12.1",

View File

@@ -1,6 +1,6 @@
[package]
name = "TeyvatGuide"
version = "0.8.6"
version = "0.8.8"
description = "Game Tool for Genshin Impact player"
authors = ["BTMuli <bt-muli@outlook.com>"]
license = "MIT"
@@ -21,7 +21,7 @@ tauri-build = { version = "2.5.3", features = [] }
[dependencies]
chrono = "0.4.42"
log = "0.4.28"
log = "0.4.29"
prost = "0.14.1"
prost-types = "0.14.1"
serde = { version = "1.0.228", features = ["derive"] }

View File

@@ -1,43 +0,0 @@
syntax = "proto3";
message AchievementProtoFieldInfo {
uint32 id = 1;
uint32 status = 2;
uint32 total_progress = 3;
uint32 current_progress = 4;
uint32 finish_timestamp = 5;
}
message AchievementItem {
uint32 pre = 1;
uint32 group = 2;
string name = 3;
string description = 4;
}
message MethodRvaConfig {
uint32 do_cmd = 1;
uint32 update_normal_prop = 3;
uint32 new_string = 4;
uint32 find_game_object = 5;
uint32 event_system_update = 6;
uint32 simulate_pointer_click = 7;
uint32 to_int32 = 8;
uint32 tcp_state_ptr = 9;
uint32 shared_info_ptr = 10;
uint32 decompress = 11;
}
message NativeLibConfig {
uint32 store_cmd_id = 1;
uint32 achievement_cmd_id = 2;
map<uint32, MethodRvaConfig> method_rva = 10;
}
message AchievementInfo {
string version = 1;
map<uint32, string> group = 2;
map<uint32, AchievementItem> items = 3;
AchievementProtoFieldInfo pb_info = 4;
NativeLibConfig native_config = 5;
}

View File

@@ -1,5 +1,5 @@
//! 命令模块,负责处理命令
//! @since Beta v0.7.8
//! @since Beta v0.8.8
use tauri::{AppHandle, Emitter, Manager, WebviewWindowBuilder};
use tauri_utils::config::{WebviewUrl, WindowConfig};
@@ -127,58 +127,3 @@ pub fn is_in_admin() -> bool {
}
}
}
// 以管理员权限重启应用
#[tauri::command]
pub fn run_with_admin() -> Result<(), String> {
#[cfg(not(target_os = "windows"))]
{
return Err("This function is only supported on Windows.".into());
}
#[cfg(target_os = "windows")]
{
use std::ffi::OsStr;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;
use windows_sys::Win32::Foundation::HWND;
use windows_sys::Win32::UI::Shell::ShellExecuteW;
use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
fn to_wide(s: &OsStr) -> Vec<u16> {
s.encode_wide().chain(once(0)).collect()
}
let exe_path = std::env::current_exe().map_err(|e| e.to_string())?;
if !exe_path.exists() {
return Err(format!("executable not found: {}", exe_path.display()));
}
let elevated_arg = "--elevated-action=post_install";
// /C start "" "<full_path>" --elevated-action=post_install
let params = format!("/C start \"\" \"{}\" {}", exe_path.display(), elevated_arg);
let cmd_w = to_wide(OsStr::new("cmd.exe"));
let verb_w = to_wide(OsStr::new("runas"));
let params_w = to_wide(OsStr::new(&params));
let workdir_w =
exe_path.parent().map(|p| to_wide(p.as_os_str())).unwrap_or_else(|| to_wide(OsStr::new("")));
unsafe {
let result = ShellExecuteW(
0 as HWND,
verb_w.as_ptr(),
cmd_w.as_ptr(),
params_w.as_ptr(),
if workdir_w.len() > 1 { workdir_w.as_ptr() } else { null_mut() },
SW_SHOWNORMAL,
);
if (result as usize) > 32 {
Ok(())
} else {
Err("Failed to restart as administrator via cmd.".into())
}
}
}
}

View File

@@ -1,21 +1,19 @@
//! 主模块,用于启动应用
//! @since Beta v0.7.8
//! @since Beta v0.8.8
mod client;
mod commands;
mod plugins;
mod utils;
#[cfg(target_os = "windows")]
mod watchdog;
#[cfg(target_os = "windows")]
mod yae;
use crate::client::create_mhy_client;
use crate::commands::{
create_window, execute_js, get_dir_size, init_app, is_in_admin, run_with_admin,
};
use crate::commands::{create_window, execute_js, get_dir_size, init_app, is_in_admin};
use crate::plugins::{build_log_plugin, build_si_plugin};
#[cfg(target_os = "windows")]
use crate::yae::call_yae_dll;
use tauri::{generate_context, generate_handler, Builder, Manager, Window, WindowEvent};
use tauri::{generate_context, generate_handler, Manager, Window, WindowEvent};
// 窗口事件处理
fn window_event_handler(app: &Window, event: &WindowEvent) {
@@ -40,9 +38,35 @@ fn window_event_handler(app: &Window, event: &WindowEvent) {
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
Builder::default()
#[cfg(target_os = "windows")]
{
let args: Vec<String> = std::env::args().collect();
let is_watchdog = args.iter().any(|a| a == "--watchdog");
// 看门狗模式:不初始化 Tauri不加载单例纯等待 + 提权启动
if is_watchdog {
// 解析父进程 PID
let mut ppid: u32 = 0;
for a in &args {
if let Some(rest) = a.strip_prefix("--ppid=") {
if let Ok(v) = rest.parse::<u32>() {
ppid = v;
}
}
}
// 等父进程退出后再 runas 启动管理员实例,传入 --elevated 标志
let _ = watchdog::run_watchdog(ppid, "--elevated");
// 看门狗退出
return;
}
}
// 正常应用实例:加载单例插件,防止多实例
let mut builder = tauri::Builder::default();
// 只有在正常/管理员实例下才加载单例插件;看门狗不加载
builder = builder.plugin(build_si_plugin());
builder
.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())
@@ -67,10 +91,11 @@ pub fn run() {
execute_js,
get_dir_size,
create_mhy_client,
#[cfg(target_os = "windows")]
call_yae_dll,
is_in_admin,
run_with_admin
#[cfg(target_os = "windows")]
yae::call_yae_dll,
#[cfg(target_os = "windows")]
watchdog::run_with_admin
])
.run(generate_context!())
.expect("error while running tauri application");

View File

@@ -12,19 +12,13 @@ use tauri_plugin_single_instance::init;
pub fn build_si_plugin<R: Runtime>() -> TauriPlugin<R> {
init(move |app, argv, _cwd| {
// 把 argv 转成 Vec<String>
let args: Vec<String> = argv.iter().map(|s| s.to_string()).collect();
// let args: Vec<String> = argv.iter().map(|s| s.to_string()).collect();
// 如果包含提升约定参数,发出专门事件并短路退出
if args.iter().any(|a| a.starts_with("--elevated-action"))
|| args.iter().any(|a| a == "--elevated")
{
if let Err(e) = app.emit("elevated_launch", args.clone()) {
// 记录错误但不要 panic
eprintln!("emit elevated_launch failed: {}", e);
}
// 提升实例通常只负责传参或执行一次性任务,退出避免与主实例冲突
std::process::exit(0);
}
// if args.iter().any(|a| a == "--elevated") {
// 提升实例通常只负责传参或执行一次性任务,退出避免与主实例冲突
// std::process::exit(0);
// }
// 非提升启动:按原逻辑广播 deep link
if let Err(e) = app.emit("active_deep_link", argv) {

79
src-tauri/src/watchdog.rs Normal file
View File

@@ -0,0 +1,79 @@
//! 重启提权相关处理
//! @since Beta v0.8.7
#![cfg(target_os = "windows")]
use std::ffi::OsStr;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;
use std::time::Duration;
use tauri::AppHandle;
use windows_sys::Win32::Foundation::{HANDLE, HWND};
use windows_sys::Win32::Storage::FileSystem::SYNCHRONIZE;
use windows_sys::Win32::System::Threading::{OpenProcess, WaitForSingleObject, INFINITE};
use windows_sys::Win32::UI::Shell::ShellExecuteW;
use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
// 带参数启动
fn shell_runas_with_args(args: &str) -> Result<(), String> {
fn to_wide(s: &OsStr) -> Vec<u16> {
s.encode_wide().chain(once(0)).collect()
}
let exe_path = std::env::current_exe().map_err(|e| e.to_string())?;
let exe_wide = to_wide(exe_path.as_os_str());
let args_wide = to_wide(OsStr::new(args));
let cwd_wide =
exe_path.parent().map(|p| to_wide(p.as_os_str())).unwrap_or_else(|| to_wide(OsStr::new("")));
unsafe {
let result = ShellExecuteW(
0 as HWND,
to_wide(OsStr::new("runas")).as_ptr(),
exe_wide.as_ptr(),
args_wide.as_ptr(),
if cwd_wide.len() > 1 { cwd_wide.as_ptr() } else { null_mut() },
SW_SHOWNORMAL,
);
if (result as usize) > 32 {
Ok(())
} else {
Err("Failed to ShellExecuteW runas".into())
}
}
}
// 等待父进程退出(释放单例锁)后,再以管理员身份启动新实例
pub fn run_watchdog(parent_pid: u32, args_to_pass: &str) -> Result<(), String> {
// 打开父进程句柄用于等待
let handle: HANDLE = unsafe { OpenProcess(SYNCHRONIZE, 0, parent_pid) };
if handle == std::ptr::null_mut() {
// 如果拿不到句柄,可能父进程已退出,稍作等待后继续
std::thread::sleep(Duration::from_millis(300));
} else {
unsafe {
WaitForSingleObject(handle, INFINITE);
}
}
// 父进程已退出 → 触发 UAC 提权启动新实例
shell_runas_with_args(args_to_pass)
}
// 以管理员权限重启应用
#[tauri::command]
pub fn run_with_admin(app_handle: AppHandle) -> Result<(), String> {
let parent_pid = std::process::id();
let exe = std::env::current_exe().map_err(|e| e.to_string())?;
let mut cmd = std::process::Command::new(exe);
cmd
.arg("--watchdog")
.arg(format!("--ppid={}", parent_pid))
// 看门狗不加载单例插件(通过参数决定 main 的初始化)
.spawn()
.map_err(|e| format!("spawn watchdog failed: {e}"))?;
// 立即退出:单例锁释放
app_handle.exit(0);
Ok(())
}

View File

@@ -23,7 +23,7 @@ fn read_rva(key: &str) -> i32 {
}
// 读取配置文件
fn read_conf(path: &str) -> i32 {
pub fn read_conf(path: &str) -> i32 {
// 编译时嵌入 JSON 文件值都是32位整数
let data = include_str!("../../lib/conf.json");
let json: Value = serde_json::from_str(data).expect("Invalid JSON");

View File

@@ -1,7 +1,8 @@
//! Yae 成就信息的 Protobuf 定义
//! @since Beta v0.8.7
//! @since Beta v0.7.9
#![cfg(target_os = "windows")]
use crate::yae::read_conf;
use prost::encoding::{decode_key, WireType};
use prost::DecodeError;
use prost::Message;
@@ -140,6 +141,8 @@ pub fn parse_achi_list(bytes: &[u8]) -> Result<Vec<UiafAchiItem>, DecodeError> {
let value = prost::encoding::decode_varint(&mut inner)? as u32;
dict.insert(tag, value);
}
// 输出 dict
println!("{:?}", dict);
// dict 至少需要两个 key
if dict.len() > 2 {
dicts.push(dict)
@@ -147,14 +150,20 @@ pub fn parse_achi_list(bytes: &[u8]) -> Result<Vec<UiafAchiItem>, DecodeError> {
}
}
let _id = read_conf("id") as u32;
let _status = read_conf("status") as u32;
let _cur = read_conf("currentProgress") as u32;
let _ts = read_conf("finishTimestamp") as u32;
let achievements = dicts
.into_iter()
.map(|d| UiafAchiItem {
id: d.get(&15).copied().unwrap_or(0),
status: d.get(&11).copied().unwrap_or(0),
current: d.get(&13).copied().unwrap_or(0),
timestamp: d.get(&7).copied().unwrap_or(0),
id: d.get(&_id).copied().unwrap_or(0),
status: d.get(&_status).copied().unwrap_or(0),
current: d.get(&_cur).copied().unwrap_or(0),
timestamp: d.get(&_ts).copied().unwrap_or(0),
})
.filter(|a| a.status != 0)
.collect();
Ok(achievements)

View File

@@ -2,7 +2,7 @@
"$schema": "https://schema.tauri.app/config/2",
"productName": "TeyvatGuide",
"identifier": "TeyvatGuide",
"version": "0.8.6",
"version": "0.8.8",
"build": {
"beforeDevCommand": "pnpm vite:dev",
"beforeBuildCommand": "pnpm vite:build",
@@ -31,9 +31,7 @@
"targets": ["msi", "app", "dmg"],
"windows": { "wix": { "language": "zh-CN" } },
"macOS": {},
"resources": {
"lib/YaeAchievementLib.dll": "resources/YaeAchievementLib.dll"
}
"resources": { "lib/YaeAchievementLib.dll": "resources/YaeAchievementLib.dll" }
},
"app": {
"withGlobalTauri": true,

View File

@@ -4,7 +4,14 @@
class="tp-video-container"
:src="props.data.insert.video"
:allowfullscreen="true"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allow="
accelerometer;
autoplay;
clipboard-write;
encrypted-media;
gyroscope;
picture-in-picture;
"
sandbox="allow-forms allow-same-origin allow-popups allow-presentation allow-scripts"
:id="`tp-video-${props.data.insert.video}`"
/>

View File

@@ -13206,7 +13206,7 @@
"description": "击败一艘至少因过热瘫痪过2次的超重型陆巡舰·机动战垒。",
"reward": 5,
"version": "6.2",
"trigger": { "type": "Unknown" }
"trigger": { "type": "COMBAT_CONFIG_COMMON" }
},
{
"id": 84000,
@@ -15952,7 +15952,10 @@
"description": "节日就是要开开心心。",
"reward": 5,
"version": "6.2",
"trigger": { "type": "Unknown" }
"trigger": {
"type": "FINISH_QUEST_AND",
"task": [{ "questId": 6027, "name": "月亮回家的夜晚", "type": "魔神任务" }]
}
},
{
"id": 84367,
@@ -15962,7 +15965,10 @@
"description": "享受在月下世界最后的夜晚。",
"reward": 5,
"version": "6.2",
"trigger": { "type": "Unknown" }
"trigger": {
"type": "FINISH_QUEST_AND",
"task": [{ "questId": 6027, "name": "月亮回家的夜晚", "type": "魔神任务" }]
}
},
{
"id": 84368,
@@ -15972,7 +15978,10 @@
"description": "月光永远联系着我们,不论日夜。",
"reward": 5,
"version": "6.2",
"trigger": { "type": "Unknown" }
"trigger": {
"type": "FINISH_QUEST_AND",
"task": [{ "questId": 6028, "name": "回到月亮上去", "type": "魔神任务" }]
}
},
{
"id": 84369,
@@ -15982,7 +15991,10 @@
"description": "完成「散于晨雾的月芒」。",
"reward": 10,
"version": "6.2",
"trigger": { "type": "Unknown" }
"trigger": {
"type": "FINISH_QUEST_AND",
"task": [{ "questId": 6028, "name": "回到月亮上去", "type": "魔神任务" }]
}
},
{
"id": 84370,
@@ -15992,7 +16004,10 @@
"description": "说不定会有意外的收获。",
"reward": 5,
"version": "6.2",
"trigger": { "type": "Unknown" }
"trigger": {
"type": "FINISH_QUEST_AND",
"task": [{ "questId": 6025, "name": "月影轮番登台", "type": "魔神任务" }]
}
},
{
"id": 84371,
@@ -16002,7 +16017,10 @@
"description": "目睹过去在这里发生过的「历史」。",
"reward": 5,
"version": "6.2",
"trigger": { "type": "Unknown" }
"trigger": {
"type": "FINISH_QUEST_AND",
"task": [{ "questId": 6025, "name": "月影轮番登台", "type": "魔神任务" }]
}
},
{
"id": 84372,
@@ -16012,7 +16030,10 @@
"description": "你们曾在某个时刻擦肩而过…",
"reward": 5,
"version": "6.2",
"trigger": { "type": "Unknown" }
"trigger": {
"type": "FINISH_QUEST_AND",
"task": [{ "questId": 6026, "name": "无法传达的涟漪", "type": "魔神任务" }]
}
},
{
"id": 84373,
@@ -16022,7 +16043,10 @@
"description": "完成「终北的夜行诗」。",
"reward": 10,
"version": "6.2",
"trigger": { "type": "Unknown" }
"trigger": {
"type": "FINISH_QUEST_AND",
"task": [{ "questId": 6026, "name": "无法传达的涟漪", "type": "魔神任务" }]
}
},
{
"id": 84501,

View File

@@ -3026,5 +3026,41 @@
"postId": "70352228",
"up5List": [13512, 13504],
"up4List": [11427, 12427, 15427, 13401, 14403]
},
{
"name": "白礜赤成",
"version": "6.2",
"order": 1,
"banner": "https://sdk-webstatic.mihoyo.com/upload/ann/2025/11/19/e9291b4ae7e6840d81adf8c3bcf2ad5e_5777095417575400489_transformed.jpg",
"from": "2025-12-03T10:00:00+08:00",
"to": "2025-12-23T17:59:00+08:00",
"type": 301,
"postId": "71075619",
"up5List": [10000123],
"up4List": [10000124, 10000032, 10000076]
},
{
"name": "杯装之诗",
"version": "6.2",
"order": 1,
"banner": "https://sdk-webstatic.mihoyo.com/upload/ann/2025/11/19/123cbe77341ba0337e56f56600effd09_1549480919145244906_transformed.webp",
"from": "2025-12-03T10:00:00+08:00",
"to": "2025-12-23T17:59:00+08:00",
"type": 400,
"postId": "71075617",
"up5List": [10000002],
"up4List": [10000124, 10000032, 10000076]
},
{
"name": "神铸赋形",
"version": "6.2",
"order": 1,
"banner": "https://sdk-webstatic.mihoyo.com/upload/ann/2025/11/19/0a9191e9c94c34f1862223aea72f88d8_6761506822979172855_transformed.jpg",
"from": "2025-12-03T10:00:00+08:00",
"to": "2025-12-23T17:59:00+08:00",
"type": 302,
"postId": "71075615",
"up5List": [11518, 15515],
"up4List": [11410, 13427, 14410, 12405, 15402]
}
]

View File

@@ -350,6 +350,7 @@ async function toYae(): Promise<void> {
}
async function tryParseYaeAchi(payload: TGApp.Plugins.Yae.AchiListRes): Promise<void> {
console.log(payload);
if (payload.length === 0) {
showSnackbar.warn(`未从Yae获取到成就数据`);
return;