feat: 新增演示账号逻辑,添加登录页面提示,并修复后端异常时的自动登出竞争问题

develop
hnu202326010131 1 month ago
parent 527c6cae39
commit 5d2014516d

@ -140,6 +140,14 @@ api.interceptors.response.use(
if (status === 401) {
const auth = useAuthStore()
const url = error.config?.url || ''
// 如果是演示 Token或者是一些基础检查接口不触发自动登出
if (auth.token?.startsWith('demo.') || url.includes('/v1/health') || url.includes('/v1/auth/me')) {
return Promise.reject({
...error,
friendlyMessage: '鉴权失效 (演示模式或基础接口)'
})
}
const current = window.location.hash.startsWith('#') ? window.location.hash.slice(1) : window.location.hash
auth.logout()
if (!window.location.hash.includes('login')) {

@ -58,6 +58,16 @@ export const useAuthStore = defineStore('auth', {
},
async login(username: string, password: string) {
try {
// 特例处理演示账号:账号密码均为 123 时,直接以管理员身份登录
if (username === '123' && password === '123') {
const token = makeDemoToken()
this.user = { id: 888, username: 'demo-admin', role: 'admin' }
this.token = token
this.refreshToken = 'demo-refresh-token'
this.persist()
return { ok: true, role: 'admin' }
}
const r: any = await AuthService.login({ username, password })
const token = r?.token
const refreshToken = r?.refreshToken || r?.refresh_token || r?.tokens?.refresh || null
@ -95,6 +105,15 @@ export const useAuthStore = defineStore('auth', {
return { ok: false, message: e.friendlyMessage || '注册失败' }
}
},
logout() { this.user = null; this.token = null; this.refreshToken = null; this.persist() }
logout() {
// 如果是演示账号,忽略来自 API 拦截器的登出请求,防止在后端异常时被强制踢出
if (this.token?.startsWith('demo.')) {
return
}
this.user = null;
this.token = null;
this.refreshToken = null;
this.persist()
}
}
})

@ -56,6 +56,11 @@
还没有账号
<el-link type="primary" @click="router.push('/register')"></el-link>
</div>
<div class="demo-hint">
<el-icon class="hint-icon"><CircleCheck /></el-icon>
演示账号: <span class="hint-value">123</span> / 密码: <span class="hint-value">123</span>
</div>
</el-form>
<div class="health-status">
@ -76,7 +81,7 @@ import { useUIStore } from "../stores/ui";
import { AuthService } from "../api/auth.service";
import { ElMessage } from "element-plus";
import type { FormInstance, FormRules } from "element-plus";
import { Monitor, User, Lock, Moon, Sunny } from '@element-plus/icons-vue'
import { Monitor, User, Lock, Moon, Sunny, CircleCheck } from '@element-plus/icons-vue'
const router = useRouter();
const route = useRoute();
@ -234,6 +239,29 @@ async function onSubmit() {
margin-top: 8px;
}
.demo-hint {
text-align: center;
font-size: 13px;
color: var(--el-color-info);
margin-top: 16px;
padding: 8px;
border-radius: 6px;
background-color: var(--el-fill-color-light);
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.hint-icon {
color: var(--el-color-success);
}
.hint-value {
color: var(--el-color-primary);
font-weight: 600;
}
.health-status {
text-align: center;
margin-top: 20px;

Loading…
Cancel
Save