liuyun 5de298a956 feat(auth): 首登强制改密页面 + 创建用户开关
- 独立改密页 + 路由守卫拦截待改密
- auth store 持久化 mustChangePassword
- 用户创建表单加「首登强制改密」开关(默认勾选)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-11 21:54:41 +08:00

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 };
});