diff --git a/src-tauri/src/auth_session.rs b/src-tauri/src/auth_session.rs new file mode 100644 index 0000000..c716f30 --- /dev/null +++ b/src-tauri/src/auth_session.rs @@ -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, +} + +#[derive(Debug, Default)] +pub struct AuthSession { + inner: Mutex, +} + +impl AuthSession { + pub fn set(&self, token: String, user: Option) { + 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 { + self.inner.lock().expect("auth session mutex poisoned").user.clone() + } +} diff --git a/src-tauri/src/commands/auth.rs b/src-tauri/src/commands/auth.rs new file mode 100644 index 0000000..0a5c577 --- /dev/null +++ b/src-tauri/src/commands/auth.rs @@ -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, +) { + session.set(token, user); +} diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index 932bf50..0114e08 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -1 +1,2 @@ +pub mod auth; pub mod quickjs; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index dde76c0..cb783b6 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,4 +1,5 @@ pub mod asr; +pub mod auth_session; pub mod chat; pub mod commands; pub mod ffmpeg; @@ -13,6 +14,7 @@ pub fn run() { let _ = env_logger::try_init(); tauri::Builder::default() + .manage(auth_session::AuthSession::default()) .plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| { if let Some(window) = app.get_webview_window("main") { let _ = window.unminimize(); @@ -22,6 +24,7 @@ pub fn run() { })) .plugin(tauri_plugin_opener::init()) .invoke_handler(tauri::generate_handler![ + commands::auth::sync_auth_session, commands::quickjs::run_quickjs_script, commands::quickjs::list_quickjs_scripts, ]) diff --git a/src/main.js b/src/main.js index 1ddbf27..cd9cebd 100644 --- a/src/main.js +++ b/src/main.js @@ -23,11 +23,13 @@ import Dialog from "primevue/dialog"; import DashboardCard from "./components/dashboard/DashboardCard.vue"; import App from "./App.vue"; import router from "./router"; +import { useAuthStore } from "./stores/auth.js"; import "./styles/main.css"; const app = createApp(App); -app.use(createPinia()); +const pinia = createPinia(); +app.use(pinia); app.use(router); app.use(PrimeVue, { theme: { @@ -58,4 +60,6 @@ app.component("TabPanel", TabPanel); app.component("DashboardCard", DashboardCard); app.component("Dialog", Dialog); +useAuthStore(pinia).hydrateRustSession(); + app.mount("#app"); diff --git a/src/stores/auth.js b/src/stores/auth.js index c5cf517..8d07972 100644 --- a/src/stores/auth.js +++ b/src/stores/auth.js @@ -1,9 +1,21 @@ import { defineStore } from "pinia"; +import { invoke } from "@tauri-apps/api/core"; import { loginApi, logoutApi, registerApi } from "../api/auth.js"; const TOKEN_KEY = "aiclient_token"; 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) { if (!res.ok) { return { ok: false, message: res.message || fallbackMessage }; @@ -45,6 +57,7 @@ export const useAuthStore = defineStore("auth", { this.currentUser = user; localStorage.setItem(TOKEN_KEY, accessToken); localStorage.setItem(USER_KEY, JSON.stringify(user)); + syncAuthSessionToRust(accessToken, user); }, clearSession() { @@ -52,6 +65,12 @@ export const useAuthStore = defineStore("auth", { this.currentUser = null; localStorage.removeItem(TOKEN_KEY); localStorage.removeItem(USER_KEY); + syncAuthSessionToRust("", null); + }, + + /** 将当前内存中的会话同步到 Rust(启动时 localStorage 已恢复后调用) */ + hydrateRustSession() { + syncAuthSessionToRust(this.token, this.currentUser); }, async register({ username, password, confirmPassword }) {