feat(ops-web/auth): add remember-me with session/local storage split

Persistent logins land in localStorage, ephemeral ones in sessionStorage,
and we recall the last username + remember preference on the login form.
Also propagate the indigo brand color through the antd ConfigProvider
theme token so the side nav and avatar match the redesigned login.
This commit is contained in:
2026-04-29 15:59:23 +08:00
parent 2d66e32938
commit a5cef078f5
6 changed files with 133 additions and 40 deletions
+29 -14
View File
@@ -5,7 +5,9 @@ import { http } from "@/lib/http";
import {
type OperatorView,
clearStoredSession,
readLoginPreference,
readStoredSession,
writeLoginPreference,
writeStoredSession,
} from "@/lib/storage";
@@ -20,25 +22,32 @@ export const useAuthStore = defineStore("ops-auth", () => {
const expiresAt = ref<number | null>(null);
const operator = ref<OperatorView | null>(null);
const initialized = ref(false);
const persistent = ref(false);
function hydrate(): void {
const stored = readStoredSession();
accessToken.value = stored.accessToken;
expiresAt.value = stored.expiresAt;
operator.value = stored.operator;
accessToken.value = stored.session.accessToken;
expiresAt.value = stored.session.expiresAt;
operator.value = stored.session.operator;
persistent.value = stored.persistent;
initialized.value = true;
}
async function login(username: string, password: string): Promise<void> {
async function login(username: string, password: string, remember: boolean): Promise<void> {
const result = await http.post<LoginResponse>("/auth/login", { username, password });
accessToken.value = result.access_token;
expiresAt.value = result.expires_at;
operator.value = result.operator;
writeStoredSession({
accessToken: result.access_token,
expiresAt: result.expires_at,
operator: result.operator,
});
persistent.value = remember;
writeStoredSession(
{
accessToken: result.access_token,
expiresAt: result.expires_at,
operator: result.operator,
},
remember,
);
writeLoginPreference({ remember, lastUsername: username });
}
async function refreshSelf(): Promise<void> {
@@ -53,11 +62,14 @@ export const useAuthStore = defineStore("ops-auth", () => {
role: me.role,
status: me.status,
};
writeStoredSession({
accessToken: accessToken.value,
expiresAt: expiresAt.value,
operator: operator.value,
});
writeStoredSession(
{
accessToken: accessToken.value,
expiresAt: expiresAt.value,
operator: operator.value,
},
persistent.value,
);
} catch {
logout();
}
@@ -67,6 +79,7 @@ export const useAuthStore = defineStore("ops-auth", () => {
accessToken.value = null;
expiresAt.value = null;
operator.value = null;
persistent.value = false;
clearStoredSession();
}
@@ -78,9 +91,11 @@ export const useAuthStore = defineStore("ops-auth", () => {
operator,
initialized,
isAuthenticated,
persistent,
hydrate,
login,
refreshSelf,
logout,
readLoginPreference,
};
});