统一错误处理和通知系统使用指南

📋 概述

已实现基于消息队列的统一错误处理和通知系统,提供:

  • ✅ 消息队列管理(FIFO,优先级支持)
  • ✅ 统一错误处理 Hook
  • ✅ 自动去重和过期
  • ✅ 类型安全
  • ✅ 美观的 UI 展示

🚀 快速开始

1. 基本使用

发送通知

import { notify } from '../utils/notificationQueue'

// 成功通知
notify.success('操作成功', '知识库已创建')

// 错误通知
notify.error('操作失败', '网络连接错误')

// 警告通知
notify.warning('注意', '文件大小超过限制')

// 信息通知
notify.info('提示', '正在处理中...')

使用错误处理 Hook

import { useErrorHandler } from '../hooks/useErrorHandler'

function MyComponent() {
  const { handleError, handleAsync } = useErrorHandler()

  // 方式1:手动处理错误
  const handleClick = async () => {
    try {
      await someAsyncOperation()
      notify.success('操作成功')
    } catch (error) {
      await handleError(error, {
        title: '操作失败',
        showNotification: true,
      })
    }
  }

  // 方式2:自动处理(推荐)
  const handleClickAuto = async () => {
    await handleAsync(
      () => someAsyncOperation(),
      {
        successTitle: '操作成功',
        successMessage: '数据已保存',
        onSuccess: (result) => {
          console.log('结果:', result)
        },
      }
    )
  }

  return <button onClick={handleClickAuto}>执行操作</button>
}

📚 API 参考

notify 方法

notify.success(title, message?, options?)

发送成功通知

notify.success('知识库创建成功', '已成功创建知识库"我的知识库"', {
  duration: 5000, // 自定义显示时长
  priority: NotificationPriority.HIGH, // 优先级
  persistent: false, // 是否持久化
})

notify.error(title, message?, options?)

发送错误通知

notify.error('创建失败', '网络连接错误,请检查网络设置', {
  duration: 6000, // 错误消息默认显示更久
  priority: NotificationPriority.HIGH,
  actions: [
    {
      label: '重试',
      action: () => retryOperation(),
      style: 'primary',
    },
  ],
})

notify.warning(title, message?, options?)

发送警告通知

notify.info(title, message?, options?)

发送信息通知


useErrorHandler Hook

handleError(error, options?)

手动处理错误

const { handleError } = useErrorHandler()

await handleError(error, {
  showNotification: true, // 是否显示通知(默认:true)
  title: '自定义标题', // 自定义错误标题
  message: '自定义消息', // 自定义错误消息
  priority: NotificationPriority.HIGH, // 优先级
  persistent: false, // 是否持久化
  onError: (error) => {
    // 错误处理后的回调
    console.log('错误已处理:', error)
  },
  logError: true, // 是否记录日志(默认:true)
  retry: async () => {
    // 重试函数
    return await retryOperation()
  },
  retryCount: 3, // 重试次数
})

handleAsync(asyncFn, options?)

自动处理异步操作的错误

const { handleAsync } = useErrorHandler()

const result = await handleAsync(
  () => knowledgeService.createKnowledgeBase(data),
  {
    successTitle: '创建成功',
    successMessage: '知识库已创建',
    onSuccess: (kb) => {
      console.log('创建的知识库:', kb)
      // 刷新列表等操作
    },
    onError: (error) => {
      // 错误处理回调
    },
    retry: () => knowledgeService.createKnowledgeBase(data),
    retryCount: 2,
  }
)

if (result) {
  // 操作成功
} else {
  // 操作失败(已自动显示错误通知)
}

🔄 迁移现有代码

替换 console.error + alert

之前:

try {
  await knowledgeService.createKnowledgeBase(data)
  alert('创建成功')
} catch (error: any) {
  console.error('Failed to create knowledge base:', error)
  alert(`创建失败:${error.response?.data?.detail || error.message}`)
}

之后:

const { handleAsync } = useErrorHandler()

await handleAsync(
  () => knowledgeService.createKnowledgeBase(data),
  {
    successTitle: '创建成功',
    successMessage: '知识库已创建',
  }
)

替换 console.log

之前:

console.log('📤 批量上传开始:', { kbId, fileCount: files.length })

之后:

import { logger } from '../utils/logger'

logger.info('批量上传开始', { kbId, fileCount: files.length }, 'KnowledgeBase')

💡 最佳实践

1. 统一使用 handleAsync

对于所有异步操作,优先使用 handleAsync

// ✅ 推荐
const { handleAsync } = useErrorHandler()

await handleAsync(
  () => knowledgeService.uploadFile(kbId, file),
  {
    successTitle: '上传成功',
    successMessage: '文件已上传并处理',
  }
)

// ❌ 不推荐
try {
  await knowledgeService.uploadFile(kbId, file)
  notify.success('上传成功')
} catch (error) {
  notify.error('上传失败', error.message)
}

2. 提供重试机制

对于可能失败的操作,提供重试按钮:

await handleAsync(
  () => knowledgeService.uploadFile(kbId, file),
  {
    successTitle: '上传成功',
    retry: () => knowledgeService.uploadFile(kbId, file),
    retryCount: 3,
  }
)

3. 使用 logger 替代 console

开发时使用 logger,生产环境自动过滤:

import { logger } from '../utils/logger'

logger.debug('调试信息', { data }, 'ComponentName')
logger.info('信息', { data }, 'ComponentName')
logger.warn('警告', { data }, 'ComponentName')
logger.error('错误', error, 'ComponentName')

4. 错误消息要友好

提取用户友好的错误消息:

// ✅ 推荐:自动提取友好消息
await handleError(error)

// ✅ 也可以自定义
await handleError(error, {
  title: '网络错误',
  message: '请检查网络连接后重试',
})

🎨 自定义通知

添加操作按钮

notify.error('操作失败', '请重试', {
  actions: [
    {
      label: '重试',
      action: () => {
        retryOperation()
      },
      style: 'primary',
    },
    {
      label: '取消',
      action: () => {
        cancelOperation()
      },
      style: 'secondary',
    },
  ],
})

持久化通知

notify.info('重要提示', '请完成设置', {
  persistent: true, // 不自动关闭
})

自定义优先级

import { NotificationPriority } from '../utils/notificationQueue'

notify.error('紧急错误', '系统异常', {
  priority: NotificationPriority.URGENT, // 最高优先级
})

🔧 高级用法

批量操作通知

const { handleAsync } = useErrorHandler()

const results = await Promise.allSettled(
  files.map(file =>
    handleAsync(
      () => knowledgeService.uploadFile(kbId, file),
      {
        successTitle: `${file.name} 上传成功`,
        showNotification: false, // 不显示单个通知
      }
    )
  )
)

// 显示汇总通知
const successCount = results.filter(r => r.status === 'fulfilled').length
const failCount = results.filter(r => r.status === 'rejected').length

if (failCount === 0) {
  notify.success('全部上传成功', `成功上传 ${successCount} 个文件`)
} else {
  notify.warning('部分上传失败', `成功:${successCount},失败:${failCount}`)
}

队列管理

import { notificationQueue } from '../utils/notificationQueue'

// 清空所有通知
notificationQueue.clear()

// 清空特定类型的通知
notificationQueue.clearByType(NotificationType.ERROR)

// 获取队列统计
const stats = notificationQueue.getStats()
console.log('通知统计:', stats)

📝 示例:知识库页面迁移

迁移前

const handleCreateKB = async () => {
  try {
    const result = await knowledgeService.createKnowledgeBase(formData)
    setSuccessMessage('✅ 知识库创建成功')
    setTimeout(() => setSuccessMessage(null), 3000)
    await loadKnowledgeBases()
  } catch (error: any) {
    const errorMsg = error.response?.data?.detail || error.message || '创建失败'
    alert(`创建失败:${errorMsg}`)
  }
}

迁移后

const { handleAsync } = useErrorHandler()

const handleCreateKB = async () => {
  await handleAsync(
    () => knowledgeService.createKnowledgeBase(formData),
    {
      successTitle: '创建成功',
      successMessage: '知识库已创建',
      onSuccess: async () => {
        await loadKnowledgeBases()
      },
    }
  )
}

🎯 总结

使用统一错误处理和通知系统的优势:

  1. 代码更简洁:减少重复的错误处理代码
  2. 用户体验更好:统一的错误提示和通知
  3. 易于维护:集中管理错误处理逻辑
  4. 类型安全:完整的 TypeScript 类型支持
  5. 功能强大:支持重试、优先级、操作按钮等

立即开始迁移现有代码,享受更好的开发体验!