/** * 登录逻辑 Composable */ import { ref, reactive, computed, onMounted } from 'vue' import { useRouter } from 'vue-router' import { useI18n } from 'vue-i18n' import { ElNotification, ElMessage } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus' import { useUserStore } from '@/store/modules/user' import { RoutesAlias } from '@/router/routesAlias' import AppConfig from '@/config' import { AuthService } from '@/api/modules' import { ApiStatus } from '@/utils/http/status' import { saveCredentials, getRememberedCredentials } from '@/utils/auth/rememberPassword' import { usernameRules, passwordRules } from '@/utils/auth/loginValidation' /** * 登录表单数据 */ interface LoginForm { username: string password: string rememberPassword: boolean } export function useLogin() { const { t } = useI18n() const router = useRouter() const userStore = useUserStore() // 表单引用 const formRef = ref() // 加载状态 const loading = ref(false) // 表单数据 const formData = reactive({ username: '', password: '', rememberPassword: true }) // 验证规则 const rules = computed(() => ({ username: usernameRules(t), password: passwordRules(t) })) // 初始化表单 const initForm = () => { const remembered = getRememberedCredentials() if (remembered) { formData.username = remembered.username formData.password = remembered.password formData.rememberPassword = remembered.rememberPassword } else { if (import.meta.env.DEV) { formData.username = 'admin' formData.password = 'Admin@123456' formData.rememberPassword = false } } } /** * 执行登录 */ const handleLogin = async () => { if (!formRef.value) return try { // 验证表单 const valid = await formRef.value.validate() if (!valid) return loading.value = true await handleRealLogin() } catch (error: any) { console.error('登录失败:', error) } finally { loading.value = false } } /** * 登录 */ const handleRealLogin = async () => { // 调用登录接口 const response = await AuthService.login({ username: formData.username, password: formData.password }) // 检查响应状态 if (response.code !== ApiStatus.success) { console.log(response.msg || t('login.error.invalidCredentials')) return } // 检查返回数据 if (!response.data || !response.data.access_token) { console.log(t('login.error.loginFailed')) return } if (!response.data.user) { ElMessage.error(t('login.error.getUserInfoFailed')) return } // 登录成功但没有后台菜单或权限时,仅提示并停止后续流程。 // 这里不保存登录态,也不触发后续跳转,避免进入路由守卫后再连续调用退出接口。 const hasPermissions = Array.isArray(response.data.permissions) && response.data.permissions.length > 0 const hasMenus = Array.isArray(response.data.menus) && response.data.menus.length > 0 if (!hasPermissions || !hasMenus) { ElMessage.warning({ message: '当前账号暂无任何权限,请联系管理员分配角色和权限', duration: 4000, showClose: true }) saveCredentials(formData.username, formData.password, formData.rememberPassword) return } // 保存 Token userStore.setToken(response.data.access_token, response.data.refresh_token) // 保存用户信息 userStore.setUserInfo(response.data.user) userStore.setLoginStatus(true) // 保存权限、菜单和按钮 if (response.data.permissions) { userStore.setPermissions(response.data.permissions) } if (response.data.menus) { userStore.setMenus(response.data.menus) } if (response.data.buttons) { userStore.setButtons(response.data.buttons) } // 保存记住密码 saveCredentials(formData.username, formData.password, formData.rememberPassword) // 显示登录成功提示 showLoginSuccessNotice() // 等待数据持久化完成 await new Promise((resolve) => setTimeout(resolve, 100)) // 跳转到资产信息页面 await router.push(RoutesAlias.AssetInformation) } /** * 显示登录成功通知 */ const showLoginSuccessNotice = () => { setTimeout(() => { ElNotification({ title: t('login.success.title'), type: 'success', duration: 2500, zIndex: 10000, message: `${t('login.success.message')}, ${AppConfig.systemInfo.name}!` }) }, 150) } // 组件挂载时初始化 onMounted(() => { initForm() }) return { formRef, formData, rules, loading, handleLogin } }