Files
claude-relay-service/web/admin-spa/src/utils/toast.js
shaw d2f3f6866c feat: Codex账号管理优化与API Key激活机制
 新功能
- 支持通过refreshToken新增Codex账号,创建时立即验证token有效性
- API Key新增首次使用自动激活机制,支持activation模式设置有效期
- 前端账号表单增加token验证功能,确保账号创建成功

🐛 修复
- 修复Codex token刷新失败问题,增加分布式锁防止并发刷新
- 优化token刷新错误处理,提供更详细的错误信息和建议
- 修复OpenAI账号token过期检测和自动刷新逻辑

📝 文档更新
- 更新README中Codex使用说明,改为config.toml配置方式
- 优化Cherry Studio等第三方工具接入文档
- 添加详细的配置示例和账号类型说明

🎨 界面优化
- 改进账号创建表单UI,支持手动和OAuth两种模式
- 优化API Key过期时间编辑弹窗,支持激活操作
- 调整教程页面布局,提升移动端响应式体验

💡 代码改进
- 重构token刷新服务,增强错误处理和重试机制
- 优化代理配置处理,确保OAuth请求正确使用代理
- 改进webhook通知,增加token刷新失败告警
2025-09-06 18:04:06 +08:00

72 lines
2.0 KiB
JavaScript

// Toast 通知管理
let toastContainer = null
let toastId = 0
export function showToast(message, type = 'info', title = '', duration = 3000) {
// 创建容器
if (!toastContainer) {
toastContainer = document.createElement('div')
toastContainer.id = 'toast-container'
toastContainer.style.cssText = 'position: fixed; top: 20px; right: 20px; z-index: 10000;'
document.body.appendChild(toastContainer)
}
// 创建 toast
const id = ++toastId
const toast = document.createElement('div')
toast.className = `toast rounded-2xl p-4 shadow-2xl backdrop-blur-sm toast-${type}`
toast.style.cssText = `
position: relative;
min-width: 320px;
max-width: 500px;
margin-bottom: 16px;
transform: translateX(100%);
transition: transform 0.3s ease-in-out;
`
const iconMap = {
success: 'fas fa-check-circle',
error: 'fas fa-times-circle',
warning: 'fas fa-exclamation-triangle',
info: 'fas fa-info-circle'
}
// 处理消息中的换行符,转换为 HTML 换行
const formattedMessage = message.replace(/\n/g, '<br>')
toast.innerHTML = `
<div class="flex items-start gap-3">
<div class="flex-shrink-0 mt-0.5">
<i class="${iconMap[type]} text-lg"></i>
</div>
<div class="flex-1 min-w-0">
${title ? `<h4 class="font-semibold text-sm mb-1">${title}</h4>` : ''}
<p class="text-sm opacity-90 leading-relaxed">${formattedMessage}</p>
</div>
<button onclick="this.parentElement.parentElement.remove()"
class="flex-shrink-0 text-white/70 hover:text-white transition-colors ml-2">
<i class="fas fa-times"></i>
</button>
</div>
`
toastContainer.appendChild(toast)
// 触发动画
setTimeout(() => {
toast.style.transform = 'translateX(0)'
}, 10)
// 自动移除
if (duration > 0) {
setTimeout(() => {
toast.style.transform = 'translateX(100%)'
setTimeout(() => {
toast.remove()
}, 300)
}, duration)
}
return id
}