/** * 管理端登录状态(跨页面共享单例)。 * * 参数配置页与 Worker 管理页共用同一份 token(localStorage 的 cm_admin_token), * 在任一页面登录后另一页面无需重复登录。抽成模块级单例而非 Pinia store, * 避免为这点状态引入额外样板。 */ import { computed, ref } from 'vue' import { ElMessage } from 'element-plus' import { login, parseJwt, TOKEN_KEY, type AuthUser } from '@/api/workerAdmin' const token = ref(localStorage.getItem(TOKEN_KEY) || '') const currentUser = ref(null) const username = ref('') const password = ref('') const logging = ref(false) /** 从持久化 token 恢复身份(进入页面时调用;权限校验仍以后端为准) */ export function restoreAuth(): AuthUser | null { const t = token.value.trim() currentUser.value = t ? parseJwt(t) : null return currentUser.value } export function useAdminAuth() { const isLoggedIn = computed(() => !!token.value.trim()) /** * 登录并领取管理 Token。 * @returns 登录成功时的用户信息;失败返回 null(已弹出提示)。 */ const doLogin = async (): Promise => { const name = username.value.trim() if (!name || !password.value) { ElMessage.warning('请输入用户名和密码') return null } logging.value = true try { const data = await login(name, password.value) // 后端登录失败仍返回 HTTP 200,仅 result=fail + 空 token if (data.result !== 'success' || !data.token) { ElMessage.error(`登录失败:${data.message || '用户名或密码错误'}`) return null } token.value = data.token localStorage.setItem(TOKEN_KEY, data.token) username.value = '' password.value = '' const info = parseJwt(data.token) currentUser.value = info ElMessage.success(`登录成功:${(info?.username || '').trim() || '未知用户'}`) if (!info?.is_superuser) { ElMessage.error('权限不足:仅超级管理员可管理配置,操作将被拒绝') return null } return info } catch (e: any) { ElMessage.error(`登录失败:${e.message}`) return null } finally { logging.value = false } } const logout = () => { localStorage.removeItem(TOKEN_KEY) token.value = '' currentUser.value = null ElMessage.success('已退出登录') } return { token, currentUser, username, password, logging, isLoggedIn, doLogin, logout } }