/** * 登录逻辑 Composable */ import { ref, reactive, computed, onMounted } from 'vue' import { useRouter, useRoute } from 'vue-router' import { useI18n } from 'vue-i18n' import { ElMessage, ElNotification } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus' import { useUserStore } from '@/store/modules/user' import { HOME_PAGE } from '@/router/routesAlias' import AppConfig from '@/config' import { AuthService } from '@/api/modules' import { ApiStatus } from '@/utils/http/status' import { MOCK_ACCOUNTS, mockLogin, mockGetUserInfo, type MockAccount } from '@/mock/auth' import { saveCredentials, getRememberedCredentials } from '@/utils/auth/rememberPassword' import { usernameRules, passwordRules } from '@/utils/auth/loginValidation' import { getRedirectPath } from '@/router/guards/permission' // 开发模式:是否使用 Mock 数据 const USE_MOCK = false /** * 登录表单数据 */ interface LoginForm { account: string username: string password: string rememberPassword: boolean } export function useLogin() { const { t } = useI18n() const router = useRouter() const route = useRoute() const userStore = useUserStore() // 表单引用 const formRef = ref() // 加载状态 const loading = ref(false) // 表单数据 const formData = reactive({ account: '', username: '', password: '', rememberPassword: true }) // 验证规则 const rules = computed(() => ({ username: usernameRules(t), password: passwordRules(t) })) // Mock 账号列表 const mockAccounts = computed(() => MOCK_ACCOUNTS) /** * 初始化表单 */ const initForm = () => { // 尝试加载记住的密码 const remembered = getRememberedCredentials() if (remembered) { formData.username = remembered.username formData.password = remembered.password formData.rememberPassword = remembered.rememberPassword // 如果使用 Mock,尝试匹配 Mock 账号 if (USE_MOCK) { const matchedAccount = MOCK_ACCOUNTS.find((acc) => acc.username === remembered.username) if (matchedAccount) { formData.account = matchedAccount.key } } } else { // 开发环境:使用真实 API 默认账号 if (import.meta.env.MODE === 'development') { formData.username = 'admin' formData.password = 'Admin@123456' formData.rememberPassword = false } // 生产环境:不填充默认值 } } /** * 设置 Mock 账号 */ const setupAccount = (key: string) => { const selectedAccount = MOCK_ACCOUNTS.find((account) => account.key === key) if (selectedAccount) { formData.account = key formData.username = selectedAccount.username formData.password = selectedAccount.password } } /** * 执行登录 */ const handleLogin = async () => { if (!formRef.value) return try { // 验证表单 const valid = await formRef.value.validate() if (!valid) return loading.value = true // 判断使用 Mock 还是真实 API if (USE_MOCK) { await handleMockLogin() } else { await handleRealLogin() } } catch (error: any) { console.error('登录失败:', error) } finally { loading.value = false } } /** * Mock 登录(开发测试用) */ const handleMockLogin = async () => { const loginResult = mockLogin(formData.username, formData.password) if (!loginResult) { console.log(t('login.error.invalidCredentials')) return } // 保存 Token userStore.setToken(loginResult.access_token, loginResult.refresh_token) // 获取用户信息 const userInfo = mockGetUserInfo(loginResult.access_token) if (!userInfo) { console.log(t('login.error.getUserInfoFailed')) return } // 保存用户信息 userStore.setUserInfo(userInfo) userStore.setLoginStatus(true) // 保存记住密码 saveCredentials(formData.username, formData.password, formData.rememberPassword) // 显示登录成功提示 showLoginSuccessNotice() // 跳转到重定向页面或首页 const redirectPath = getRedirectPath(route) await router.push(redirectPath || HOME_PAGE) } /** * 真实 API 登录 */ 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 && response.data.user.user_type === 4) { console.log('企业账号无法登录后台管理系统') return } // 保存 Token userStore.setToken(response.data.access_token, response.data.refresh_token) // 保存用户信息 if (response.data.user) { userStore.setUserInfo(response.data.user) userStore.setLoginStatus(true) } else { console.log(t('login.error.getUserInfoFailed')) return } // 保存权限、菜单和按钮 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)) // 跳转到重定向页面或首页 const redirectPath = getRedirectPath(route) await router.push(redirectPath || HOME_PAGE) } /** * 显示登录成功通知 */ 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, mockAccounts, setupAccount, handleLogin } }