fix: refresh uploads and remember login
This commit is contained in:
@@ -154,7 +154,7 @@ function notifyBackendUnavailable(message: string) {
|
||||
}
|
||||
|
||||
apiClient.interceptors.request.use((config) => {
|
||||
const token = localStorage.getItem("live-recorder-token");
|
||||
const token = localStorage.getItem("live-recorder-token") ?? sessionStorage.getItem("live-recorder-token");
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
@@ -172,6 +172,8 @@ apiClient.interceptors.response.use(
|
||||
markBackendAvailable();
|
||||
localStorage.removeItem("live-recorder-token");
|
||||
localStorage.removeItem("live-recorder-user");
|
||||
sessionStorage.removeItem("live-recorder-token");
|
||||
sessionStorage.removeItem("live-recorder-user");
|
||||
|
||||
if (window.location.pathname !== "/login") {
|
||||
window.location.href = "/login";
|
||||
|
||||
+24
-10
@@ -6,38 +6,51 @@ import type { AuthenticatedUser, LoginResponse } from "@/types";
|
||||
const USER_STORAGE_KEY = "live-recorder-user";
|
||||
const TOKEN_STORAGE_KEY = "live-recorder-token";
|
||||
|
||||
function readStoredValue(key: string) {
|
||||
return localStorage.getItem(key) ?? sessionStorage.getItem(key);
|
||||
}
|
||||
|
||||
function clearStoredSession() {
|
||||
[localStorage, sessionStorage].forEach((storage) => {
|
||||
storage.removeItem(TOKEN_STORAGE_KEY);
|
||||
storage.removeItem(USER_STORAGE_KEY);
|
||||
});
|
||||
}
|
||||
|
||||
export const useAuthStore = defineStore("auth", () => {
|
||||
const token = ref(localStorage.getItem(TOKEN_STORAGE_KEY) ?? "");
|
||||
const token = ref(readStoredValue(TOKEN_STORAGE_KEY) ?? "");
|
||||
const user = ref<AuthenticatedUser | null>(
|
||||
(() => {
|
||||
const raw = localStorage.getItem(USER_STORAGE_KEY);
|
||||
const raw = readStoredValue(USER_STORAGE_KEY);
|
||||
return raw ? (JSON.parse(raw) as AuthenticatedUser) : null;
|
||||
})()
|
||||
);
|
||||
|
||||
const isAuthenticated = computed(() => Boolean(token.value));
|
||||
|
||||
function persistSession(session: LoginResponse) {
|
||||
function persistSession(session: LoginResponse, rememberMe: boolean) {
|
||||
token.value = session.token;
|
||||
user.value = session.user;
|
||||
localStorage.setItem(TOKEN_STORAGE_KEY, session.token);
|
||||
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(session.user));
|
||||
clearStoredSession();
|
||||
const storage = rememberMe ? localStorage : sessionStorage;
|
||||
storage.setItem(TOKEN_STORAGE_KEY, session.token);
|
||||
storage.setItem(USER_STORAGE_KEY, JSON.stringify(session.user));
|
||||
}
|
||||
|
||||
function clearSession() {
|
||||
token.value = "";
|
||||
user.value = null;
|
||||
localStorage.removeItem(TOKEN_STORAGE_KEY);
|
||||
localStorage.removeItem(USER_STORAGE_KEY);
|
||||
clearStoredSession();
|
||||
}
|
||||
|
||||
async function login(username: string, password: string) {
|
||||
async function login(username: string, password: string, rememberMe: boolean) {
|
||||
const { data } = await apiClient.post<LoginResponse>("/auth/login", {
|
||||
username,
|
||||
password
|
||||
password,
|
||||
rememberMe
|
||||
});
|
||||
|
||||
persistSession(data);
|
||||
persistSession(data, rememberMe);
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -54,6 +67,7 @@ export const useAuthStore = defineStore("auth", () => {
|
||||
currentPassword,
|
||||
newPassword
|
||||
});
|
||||
clearSession();
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -16,7 +16,8 @@ const { themeMode } = useUiPreferences();
|
||||
|
||||
const form = reactive({
|
||||
username: "admin",
|
||||
password: ""
|
||||
password: "",
|
||||
rememberMe: false
|
||||
});
|
||||
|
||||
const currentThemeIcon = computed(() => {
|
||||
@@ -35,7 +36,7 @@ async function handleLogin() {
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
await authStore.login(form.username, form.password);
|
||||
await authStore.login(form.username, form.password, form.rememberMe);
|
||||
ElMessage.success("登录成功");
|
||||
await router.push({ name: "dashboard" });
|
||||
} catch (error) {
|
||||
@@ -94,10 +95,12 @@ async function handleLogin() {
|
||||
:description="backendMessage"
|
||||
/>
|
||||
|
||||
<el-form label-position="top" class="login-form" @submit.prevent="handleLogin">
|
||||
<el-form label-position="top" class="login-form" autocomplete="on" @submit.prevent="handleLogin">
|
||||
<el-form-item label="用户名">
|
||||
<el-input
|
||||
v-model="form.username"
|
||||
id="username"
|
||||
name="username"
|
||||
:prefix-icon="User"
|
||||
autocomplete="username"
|
||||
spellcheck="false"
|
||||
@@ -107,6 +110,8 @@ async function handleLogin() {
|
||||
<el-form-item label="密码">
|
||||
<el-input
|
||||
v-model="form.password"
|
||||
id="password"
|
||||
name="password"
|
||||
:prefix-icon="Lock"
|
||||
type="password"
|
||||
autocomplete="current-password"
|
||||
@@ -115,7 +120,9 @@ async function handleLogin() {
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-button class="login-form__submit" type="primary" :loading="loading" @click="handleLogin">
|
||||
<el-checkbox v-model="form.rememberMe" name="rememberMe">记住登录状态(30 天)</el-checkbox>
|
||||
|
||||
<el-button class="login-form__submit" native-type="submit" type="primary" :loading="loading">
|
||||
登录控制台 <el-icon class="el-icon--right"><ArrowRight /></el-icon>
|
||||
</el-button>
|
||||
</el-form>
|
||||
|
||||
@@ -691,11 +691,12 @@ async function changePassword() {
|
||||
changingPassword.value = true;
|
||||
try {
|
||||
await authStore.changePassword(pwdForm.currentPassword, pwdForm.newPassword);
|
||||
ElMessage.success("密码已更新");
|
||||
ElMessage.success("密码已更新,请重新登录");
|
||||
pwdForm.currentPassword = "";
|
||||
pwdForm.newPassword = "";
|
||||
pwdForm.confirmPassword = "";
|
||||
pwdFormRef.value?.resetFields();
|
||||
await router.push({ name: "login" });
|
||||
} catch (error) {
|
||||
ElMessage.error(getApiErrorMessage(error, "密码修改失败,请稍后重试。"));
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user