- 独立改密页 + 路由守卫拦截待改密 - auth store 持久化 mustChangePassword - 用户创建表单加「首登强制改密」开关(默认勾选) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
49 lines
1.7 KiB
TypeScript
49 lines
1.7 KiB
TypeScript
import { computed, ref } from 'vue';
|
|
import { defineStore } from 'pinia';
|
|
import { http } from '@/api/http';
|
|
import { login as loginApi, type LoginResult } from '@/api/auth';
|
|
import { clearTokens, getAccessToken, getMustChangePassword, getRefreshToken, setMustChangePassword, setTokens } from '@/utils/token';
|
|
|
|
export const useAuthStore = defineStore('authStore', () => {
|
|
const accessToken = ref<string | null>(getAccessToken());
|
|
const refreshToken = ref<string | null>(getRefreshToken());
|
|
const mustChangePassword = ref<boolean>(getMustChangePassword());
|
|
|
|
const isAuthenticated = computed(() => !!accessToken.value);
|
|
|
|
async function login(username: string, password: string, tenantCode?: string): Promise<LoginResult> {
|
|
const data = await loginApi(username, password, tenantCode);
|
|
if ('accessToken' in data) {
|
|
setTokens(data.accessToken, data.refreshToken);
|
|
accessToken.value = data.accessToken;
|
|
refreshToken.value = data.refreshToken;
|
|
mustChangePassword.value = data.mustChangePassword;
|
|
setMustChangePassword(data.mustChangePassword);
|
|
}
|
|
return data;
|
|
}
|
|
|
|
async function logout(): Promise<void> {
|
|
const rt = refreshToken.value;
|
|
if (rt) {
|
|
try {
|
|
await http.post('/auth/logout', { refreshToken: rt });
|
|
} catch {
|
|
// 忽略登出接口错误
|
|
}
|
|
}
|
|
reset();
|
|
}
|
|
|
|
/** 本地清空会话状态(不调用登出接口,供 401 强退使用)。 */
|
|
function reset(): void {
|
|
clearTokens();
|
|
accessToken.value = null;
|
|
refreshToken.value = null;
|
|
mustChangePassword.value = false;
|
|
setMustChangePassword(false);
|
|
}
|
|
|
|
return { accessToken, refreshToken, isAuthenticated, mustChangePassword, login, logout, reset };
|
|
});
|