You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

6.5 KiB

Login/Register Toast 体验优化

Goal: 用 vue3-toastify 替换登录/注册页面的静态错误提示,提升用户体验。

Architecture: 在 login.vue 和 register.vue 中注入 toast 服务,移除静态 form-error div,改为 toast 弹出提示。成功/加载状态同样使用 toast 反馈。

Tech Stack: vue3-toastify (已安装), Nuxt 3, Vue 3 Composition API


文件变更

  • Modify: app/pages/auth/login.vue
  • Modify: app/pages/auth/register.vue

Task 1: 优化 login.vue

Files:

  • Modify: app/pages/auth/login.vue

  • Step 1: 注入 toast 服务

<script setup> 开头添加:

const { $toast } = useNuxtApp()
  • Step 2: 移除 form-error div 并添加 toast 注入

删除模板中的:

<div v-if="loginError" class="form-error">{{ loginError }}</div>
  • Step 3: 修改 handleLogin 错误处理

将:

loginError.value = e?.data?.statusMessage || e?.message || '登录失败'

改为:

$toast.error(e?.data?.statusMessage || e?.message || '登录失败')
await fetchCaptcha()
  • Step 4: 修改 handleLogin 成功处理

将:

await refresh(true)
await navigateTo(redirect.value)

改为:

$toast.success('登录成功!')
await refresh(true)
await navigateTo(redirect.value)
  • Step 5: 修改 fetchCaptcha 加载状态

将:

async function fetchCaptcha() {
    captcha.loading = true
    try {
        const res = await $fetch<{ code: number; data: { captchaId: string; imageSvg: string } }>('/api/auth/captcha')
        captcha.id = res.data.captchaId
        captcha.svg = res.data.imageSvg
        captcha.answer = ''
    } catch (e: any) {
        console.error('获取验证码失败', e)
    } finally {
        captcha.loading = false
    }
}

改为:

async function fetchCaptcha() {
    captcha.loading = true
    const loadingToast = $toast.loading('加载验证码...', { toastId: 'captcha-loading' })
    try {
        const res = await $fetch<{ code: number; data: { captchaId: string; imageSvg: string } }>('/api/auth/captcha')
        captcha.id = res.data.captchaId
        captcha.svg = res.data.imageSvg
        captcha.answer = ''
        $toast.update(loadingToast, { render: '验证码加载成功', type: 'success', isLoading: false, autoClose: 1500 })
    } catch (e: any) {
        console.error('获取验证码失败', e)
        $toast.update(loadingToast, { render: '验证码加载失败', type: 'error', isLoading: false, autoClose: 3000 })
    } finally {
        captcha.loading = false
    }
}
  • Step 6: 删除 form-error 相关样式

删除 CSS 中的 .form-error { ... } 样式块

  • Step 7: 提交代码
git add app/pages/auth/login.vue
git commit -m "feat(auth): add toast notifications to login page"

Task 2: 优化 register.vue

Files:

  • Modify: app/pages/auth/register.vue

  • Step 1: 注入 toast 服务

<script setup> 开头添加:

const { $toast } = useNuxtApp()
  • Step 2: 移除 form-error div

删除模板中的:

<div v-if="registerError" class="form-error">{{ registerError }}</div>
  • Step 3: 移除 registerError ref

删除:

const registerError = ref('')
  • Step 4: 修改 handleRegister 表单验证错误

将:

if (registerForm.password !== registerForm.confirmPassword) {
    registerError.value = '两次密码输入不一致'
    return
}

改为:

if (registerForm.password !== registerForm.confirmPassword) {
    $toast.error('两次密码输入不一致')
    return
}
  • Step 5: 修改 handleRegister 请求错误处理

将:

} catch (e: any) {
    registerError.value = e?.data?.statusMessage || e?.message || '注册失败'
    await fetchCaptcha()

改为:

} catch (e: any) {
    $toast.error(e?.data?.statusMessage || e?.message || '注册失败')
    await fetchCaptcha()
  • Step 6: 修改 handleRegister 成功处理

将:

await navigateTo('/auth/login?tab=login')

改为:

$toast.success('注册成功!正在跳转...')
setTimeout(() => navigateTo('/auth/login?tab=login'), 1500)
  • Step 7: 修改 fetchCaptcha 加载状态 (同 login.vue)

将:

async function fetchCaptcha() {
    captcha.loading = true
    try {
        const res = await $fetch<{ code: number; data: { captchaId: string; imageSvg: string } }>('/api/auth/captcha')
        captcha.id = res.data.captchaId
        captcha.svg = res.data.imageSvg
        captcha.answer = ''
    } catch (e: any) {
        console.error('获取验证码失败', e)
    } finally {
        captcha.loading = false
    }
}

改为:

async function fetchCaptcha() {
    captcha.loading = true
    const loadingToast = $toast.loading('加载验证码...', { toastId: 'captcha-loading' })
    try {
        const res = await $fetch<{ code: number; data: { captchaId: string; imageSvg: string } }>('/api/auth/captcha')
        captcha.id = res.data.captchaId
        captcha.svg = res.data.imageSvg
        captcha.answer = ''
        $toast.update(loadingToast, { render: '验证码加载成功', type: 'success', isLoading: false, autoClose: 1500 })
    } catch (e: any) {
        console.error('获取验证码失败', e)
        $toast.update(loadingToast, { render: '验证码加载失败', type: 'error', isLoading: false, autoClose: 3000 })
    } finally {
        captcha.loading = false
    }
}
  • Step 8: 删除 form-error 和 registerError 相关样式/逻辑

删除 CSS 中的 .form-error { ... } 样式块

  • Step 9: 提交代码
git add app/pages/auth/register.vue
git commit -m "feat(auth): add toast notifications to register page"

验证步骤

  1. 启动开发服务器: npm run dev
  2. 访问 /auth/login,测试以下场景:
    • 输入错误信息点击登录 → 应看到 toast 错误提示
    • 登录成功 → 应看到 toast 成功提示并跳转
    • 刷新页面 → 验证码加载中应有 toast 提示
  3. 访问 /auth/register,测试以下场景:
    • 两次密码不一致 → 应看到 toast 错误提示
    • 注册成功 → 应看到 toast 成功提示并延迟跳转
    • 验证码加载 → 应看到 toast 加载状态

Plan complete. 可选执行方式:

1. Subagent-Driven (推荐) - 我派发独立 subagent 执行每个任务 2. Inline Execution - 本会话内顺序执行

选择哪种方式?