262 lines
5.6 KiB
TypeScript
262 lines
5.6 KiB
TypeScript
/**
|
|
* 认证相关组合式函数
|
|
*/
|
|
|
|
import { ref, computed } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { ElMessage } from 'element-plus'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
import AuthService from '@/services/auth'
|
|
import type { LoginRequest, RegisterRequest, CaptchaResponse } from '@/types/auth'
|
|
|
|
/**
|
|
* 使用认证功能
|
|
*/
|
|
export const useAuth = () => {
|
|
const router = useRouter()
|
|
const authStore = useAuthStore()
|
|
|
|
// 加载状态
|
|
const loading = ref(false)
|
|
|
|
// 验证码相关
|
|
const captchaData = ref<CaptchaResponse | null>(null)
|
|
const captchaImage = computed(() =>
|
|
captchaData.value ? `data:image/png;base64,${captchaData.value.captchaImage}` : ''
|
|
)
|
|
|
|
/**
|
|
* 获取验证码
|
|
*/
|
|
const getCaptcha = async () => {
|
|
try {
|
|
const response = await AuthService.getCaptcha()
|
|
captchaData.value = response
|
|
return response
|
|
} catch (error) {
|
|
console.error('获取验证码失败:', error)
|
|
ElMessage.error('获取验证码失败')
|
|
throw error
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 刷新验证码
|
|
*/
|
|
const refreshCaptcha = async () => {
|
|
return getCaptcha()
|
|
}
|
|
|
|
/**
|
|
* 登录
|
|
*/
|
|
const login = async (loginData: LoginRequest) => {
|
|
try {
|
|
loading.value = true
|
|
const success = await authStore.login(loginData)
|
|
|
|
if (success) {
|
|
ElMessage.success('登录成功')
|
|
return true
|
|
}
|
|
return false
|
|
} catch (error: any) {
|
|
console.error('登录失败:', error)
|
|
ElMessage.error(error.message || '登录失败')
|
|
return false
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 注册
|
|
*/
|
|
const register = async (registerData: RegisterRequest) => {
|
|
try {
|
|
loading.value = true
|
|
const success = await authStore.register(registerData)
|
|
|
|
if (success) {
|
|
ElMessage.success('注册成功')
|
|
return true
|
|
}
|
|
return false
|
|
} catch (error: any) {
|
|
console.error('注册失败:', error)
|
|
ElMessage.error(error.message || '注册失败')
|
|
return false
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 登出
|
|
*/
|
|
const logout = async () => {
|
|
try {
|
|
await authStore.logout()
|
|
router.push('/login')
|
|
} catch (error) {
|
|
console.error('登出失败:', error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检查账号是否存在
|
|
*/
|
|
const checkAccountExists = async (account: string) => {
|
|
if (!account || !/^[a-zA-Z0-9_]{4,20}$/.test(account)) {
|
|
return false
|
|
}
|
|
|
|
try {
|
|
return await AuthService.checkAccountExists(account)
|
|
} catch (error) {
|
|
console.error('检查账号失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检查邮箱是否存在
|
|
*/
|
|
const checkEmailExists = async (email: string) => {
|
|
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
return false
|
|
}
|
|
|
|
try {
|
|
return await AuthService.checkEmailExists(email)
|
|
} catch (error) {
|
|
console.error('检查邮箱失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检查手机号是否存在
|
|
*/
|
|
const checkPhoneExists = async (phone: string) => {
|
|
if (!phone || !/^1[3-9]\d{9}$/.test(phone)) {
|
|
return false
|
|
}
|
|
|
|
try {
|
|
return await AuthService.checkPhoneExists(phone)
|
|
} catch (error) {
|
|
console.error('检查手机号失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
return {
|
|
// 状态
|
|
loading,
|
|
captchaData,
|
|
captchaImage,
|
|
|
|
// 计算属性
|
|
isLoggedIn: authStore.isLoggedIn,
|
|
userInfo: authStore.userInfo,
|
|
|
|
// 方法
|
|
getCaptcha,
|
|
refreshCaptcha,
|
|
login,
|
|
register,
|
|
logout,
|
|
checkAccountExists,
|
|
checkEmailExists,
|
|
checkPhoneExists
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 使用表单验证
|
|
*/
|
|
export const useFormValidation = () => {
|
|
/**
|
|
* 账号验证规则
|
|
*/
|
|
const validateAccount = (rule: any, value: string, callback: any) => {
|
|
if (!value) {
|
|
callback(new Error('请输入账号'))
|
|
return
|
|
}
|
|
if (!/^[a-zA-Z0-9_]{4,20}$/.test(value)) {
|
|
callback(new Error('账号只能包含字母、数字和下划线,长度4-20位'))
|
|
return
|
|
}
|
|
callback()
|
|
}
|
|
|
|
/**
|
|
* 密码验证规则
|
|
*/
|
|
const validatePassword = (rule: any, value: string, callback: any) => {
|
|
if (!value) {
|
|
callback(new Error('请输入密码'))
|
|
return
|
|
}
|
|
if (value.length < 6 || value.length > 20) {
|
|
callback(new Error('密码长度必须在6-20位之间'))
|
|
return
|
|
}
|
|
callback()
|
|
}
|
|
|
|
/**
|
|
* 确认密码验证规则
|
|
*/
|
|
const validateConfirmPassword = (password: string) => {
|
|
return (rule: any, value: string, callback: any) => {
|
|
if (!value) {
|
|
callback(new Error('请再次输入密码'))
|
|
return
|
|
}
|
|
if (value !== password) {
|
|
callback(new Error('两次输入的密码不一致'))
|
|
return
|
|
}
|
|
callback()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 邮箱验证规则
|
|
*/
|
|
const validateEmail = (rule: any, value: string, callback: any) => {
|
|
if (!value) {
|
|
callback(new Error('请输入邮箱地址'))
|
|
return
|
|
}
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
if (!emailRegex.test(value)) {
|
|
callback(new Error('请输入正确的邮箱格式'))
|
|
return
|
|
}
|
|
callback()
|
|
}
|
|
|
|
/**
|
|
* 手机号验证规则
|
|
*/
|
|
const validatePhone = (rule: any, value: string, callback: any) => {
|
|
if (value && !/^1[3-9]\d{9}$/.test(value)) {
|
|
callback(new Error('请输入正确的手机号格式'))
|
|
return
|
|
}
|
|
callback()
|
|
}
|
|
|
|
return {
|
|
validateAccount,
|
|
validatePassword,
|
|
validateConfirmPassword,
|
|
validateEmail,
|
|
validatePhone
|
|
}
|
|
}
|