This commit is contained in:
fengchuanhn@gmail.com
2026-05-16 12:04:31 +08:00
parent f2d33ee356
commit e119327ac2
6 changed files with 77 additions and 1 deletions

View File

@@ -0,0 +1,37 @@
//! 与前端 localStorage 会话镜像:通过 `sync_auth_session` 命令更新。
use serde::{Deserialize, Serialize};
use std::sync::Mutex;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthUser {
pub id: i64,
pub username: String,
}
#[derive(Debug, Clone, Default)]
struct Inner {
token: String,
user: Option<AuthUser>,
}
#[derive(Debug, Default)]
pub struct AuthSession {
inner: Mutex<Inner>,
}
impl AuthSession {
pub fn set(&self, token: String, user: Option<AuthUser>) {
let mut g = self.inner.lock().expect("auth session mutex poisoned");
g.token = token;
g.user = user;
}
pub fn token(&self) -> String {
self.inner.lock().expect("auth session mutex poisoned").token.clone()
}
pub fn user(&self) -> Option<AuthUser> {
self.inner.lock().expect("auth session mutex poisoned").user.clone()
}
}

View File

@@ -0,0 +1,12 @@
use tauri::State;
use crate::auth_session::{AuthSession, AuthUser};
#[tauri::command]
pub fn sync_auth_session(
session: State<'_, AuthSession>,
token: String,
user: Option<AuthUser>,
) {
session.set(token, user);
}

View File

@@ -1 +1,2 @@
pub mod auth;
pub mod quickjs; pub mod quickjs;

View File

@@ -1,4 +1,5 @@
pub mod asr; pub mod asr;
pub mod auth_session;
pub mod chat; pub mod chat;
pub mod commands; pub mod commands;
pub mod ffmpeg; pub mod ffmpeg;
@@ -13,6 +14,7 @@ pub fn run() {
let _ = env_logger::try_init(); let _ = env_logger::try_init();
tauri::Builder::default() tauri::Builder::default()
.manage(auth_session::AuthSession::default())
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| { .plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
if let Some(window) = app.get_webview_window("main") { if let Some(window) = app.get_webview_window("main") {
let _ = window.unminimize(); let _ = window.unminimize();
@@ -22,6 +24,7 @@ pub fn run() {
})) }))
.plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_opener::init())
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
commands::auth::sync_auth_session,
commands::quickjs::run_quickjs_script, commands::quickjs::run_quickjs_script,
commands::quickjs::list_quickjs_scripts, commands::quickjs::list_quickjs_scripts,
]) ])

View File

@@ -23,11 +23,13 @@ import Dialog from "primevue/dialog";
import DashboardCard from "./components/dashboard/DashboardCard.vue"; import DashboardCard from "./components/dashboard/DashboardCard.vue";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; import router from "./router";
import { useAuthStore } from "./stores/auth.js";
import "./styles/main.css"; import "./styles/main.css";
const app = createApp(App); const app = createApp(App);
app.use(createPinia()); const pinia = createPinia();
app.use(pinia);
app.use(router); app.use(router);
app.use(PrimeVue, { app.use(PrimeVue, {
theme: { theme: {
@@ -58,4 +60,6 @@ app.component("TabPanel", TabPanel);
app.component("DashboardCard", DashboardCard); app.component("DashboardCard", DashboardCard);
app.component("Dialog", Dialog); app.component("Dialog", Dialog);
useAuthStore(pinia).hydrateRustSession();
app.mount("#app"); app.mount("#app");

View File

@@ -1,9 +1,21 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { invoke } from "@tauri-apps/api/core";
import { loginApi, logoutApi, registerApi } from "../api/auth.js"; import { loginApi, logoutApi, registerApi } from "../api/auth.js";
const TOKEN_KEY = "aiclient_token"; const TOKEN_KEY = "aiclient_token";
const USER_KEY = "aiclient_current_user"; const USER_KEY = "aiclient_current_user";
async function syncAuthSessionToRust(token, user) {
try {
await invoke("sync_auth_session", {
token: token || "",
user: user ?? null,
});
} catch {
// 浏览器独立预览或未就绪的非 Tauri 环境
}
}
function applyTokenResponse(store, res, fallbackMessage) { function applyTokenResponse(store, res, fallbackMessage) {
if (!res.ok) { if (!res.ok) {
return { ok: false, message: res.message || fallbackMessage }; return { ok: false, message: res.message || fallbackMessage };
@@ -45,6 +57,7 @@ export const useAuthStore = defineStore("auth", {
this.currentUser = user; this.currentUser = user;
localStorage.setItem(TOKEN_KEY, accessToken); localStorage.setItem(TOKEN_KEY, accessToken);
localStorage.setItem(USER_KEY, JSON.stringify(user)); localStorage.setItem(USER_KEY, JSON.stringify(user));
syncAuthSessionToRust(accessToken, user);
}, },
clearSession() { clearSession() {
@@ -52,6 +65,12 @@ export const useAuthStore = defineStore("auth", {
this.currentUser = null; this.currentUser = null;
localStorage.removeItem(TOKEN_KEY); localStorage.removeItem(TOKEN_KEY);
localStorage.removeItem(USER_KEY); localStorage.removeItem(USER_KEY);
syncAuthSessionToRust("", null);
},
/** 将当前内存中的会话同步到 Rust启动时 localStorage 已恢复后调用) */
hydrateRustSession() {
syncAuthSessionToRust(this.token, this.currentUser);
}, },
async register({ username, password, confirmPassword }) { async register({ username, password, confirmPassword }) {