189 lines
4.8 KiB
TypeScript
189 lines
4.8 KiB
TypeScript
/**
|
|
* 登录逻辑 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<FormInstance>()
|
|
|
|
// 加载状态
|
|
const loading = ref(false)
|
|
|
|
// 表单数据
|
|
const formData = reactive<LoginForm>({
|
|
username: '',
|
|
password: '',
|
|
rememberPassword: true
|
|
})
|
|
|
|
// 验证规则
|
|
const rules = computed<FormRules>(() => ({
|
|
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
|
|
}
|
|
}
|