feat(auth): 当 API 返回 401 错误时自动打开设置对话框
当 API 返回 401 认证错误(Invalid Token)时,自动弹出设置对话框 让用户重新配置 API Key,同时显示错误提示信息。 - 新增 api-auth-error-event.ts 定义事件常量和工具函数 - apiCalls.ts 检测 401 错误并触发事件 - workflow-submission-service.ts 检测工作流失败的 401 错误 - drawnix.tsx 监听事件并打开设置对话框 + 显示 MessagePlugin 错误提示 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
c2e367fea1
commit
ec60835ebf
4 files changed
+66
No files matched your search
@@ -71,6 +71,8 @@ import { withArrowLineAutoCompleteExtend } from './plugins/with-arrow-line-auto-
|
||||
import { AutoCompleteShapePicker } from './components/auto-complete-shape-picker';
|
||||
import { useAutoCompleteShapePicker } from './hooks/useAutoCompleteShapePicker';
|
||||
import { withDefaultFill } from './plugins/with-default-fill';
|
||||
import { API_AUTH_ERROR_EVENT, ApiAuthErrorDetail } from './utils/api-auth-error-event';
|
||||
import { MessagePlugin } from 'tdesign-react';
|
||||
|
||||
const TTDDialog = lazy(() => import('./components/ttd-dialog/ttd-dialog').then(module => ({ default: module.TTDDialog })));
|
||||
const SettingsDialog = lazy(() => import('./components/settings-dialog/settings-dialog').then(module => ({ default: module.SettingsDialog })));
|
||||
@@ -224,6 +226,30 @@ export const Drawnix: React.FC<DrawnixProps> = ({
|
||||
}
|
||||
}, [board]);
|
||||
|
||||
// 监听 API 认证错误事件,自动打开设置对话框
|
||||
useEffect(() => {
|
||||
const handleApiAuthError = (event: Event) => {
|
||||
const customEvent = event as CustomEvent<ApiAuthErrorDetail>;
|
||||
const { message } = customEvent.detail;
|
||||
|
||||
// 显示错误提示
|
||||
MessagePlugin.error({
|
||||
content: 'API Key 无效或已过期,请重新配置',
|
||||
duration: 5000,
|
||||
});
|
||||
|
||||
console.error('[Drawnix] API auth error:', message);
|
||||
|
||||
// 打开设置对话框
|
||||
setAppState(prev => ({ ...prev, openSettings: true }));
|
||||
};
|
||||
|
||||
window.addEventListener(API_AUTH_ERROR_EVENT, handleApiAuthError);
|
||||
return () => {
|
||||
window.removeEventListener(API_AUTH_ERROR_EVENT, handleApiAuthError);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Handle interrupted WorkZone elements after page refresh
|
||||
// Query task status from Service Worker and restore workflow state
|
||||
useEffect(() => {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
import { Subject, Observable, Subscription } from 'rxjs';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import type { ParsedGenerationParams } from '../utils/ai-input-parser';
|
||||
import { isAuthError, dispatchApiAuthError } from '../utils/api-auth-error-event';
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
@@ -570,6 +571,11 @@ class WorkflowSubmissionService {
|
||||
workflow.error = data.error;
|
||||
}
|
||||
|
||||
// 检测 401 认证错误,触发打开设置对话框
|
||||
if (data.error && isAuthError(data.error)) {
|
||||
dispatchApiAuthError({ message: data.error, source: 'workflow' });
|
||||
}
|
||||
|
||||
this.events$.next({
|
||||
type: 'failed',
|
||||
workflowId: data.workflowId,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* API 认证错误事件
|
||||
* 用于在 API 返回 401 错误时通知主线程打开设置对话框
|
||||
*/
|
||||
|
||||
export const API_AUTH_ERROR_EVENT = 'api-auth-error';
|
||||
|
||||
export interface ApiAuthErrorDetail {
|
||||
message: string;
|
||||
source?: string; // 错误来源,如 'chat', 'workflow' 等
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查错误信息是否包含 401 认证错误
|
||||
*/
|
||||
export function isAuthError(error: string): boolean {
|
||||
return error.includes('401') ||
|
||||
error.toLowerCase().includes('invalid token') ||
|
||||
error.toLowerCase().includes('unauthorized') ||
|
||||
error.toLowerCase().includes('authentication');
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发 API 认证错误事件
|
||||
*/
|
||||
export function dispatchApiAuthError(detail: ApiAuthErrorDetail): void {
|
||||
window.dispatchEvent(new CustomEvent(API_AUTH_ERROR_EVENT, { detail }));
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { shouldUseSWTaskQueue } from '../../services/task-queue';
|
||||
import { swTaskQueueClient } from '../../services/sw-client';
|
||||
import { geminiSettings } from '../settings-manager';
|
||||
import type { ChatParams, ChatMessage as SWChatMessage } from '../../services/sw-client/types';
|
||||
import { isAuthError, dispatchApiAuthError } from '../api-auth-error-event';
|
||||
|
||||
/**
|
||||
* 确保 SW 客户端已初始化
|
||||
@@ -303,6 +304,11 @@ async function callApiStreamViaSW(
|
||||
const duration = Date.now() - startTime;
|
||||
console.error('[ApiCalls/SW] Stream error:', error);
|
||||
|
||||
// 检测 401 认证错误,触发打开设置对话框
|
||||
if (isAuthError(error)) {
|
||||
dispatchApiAuthError({ message: error, source: 'chat' });
|
||||
}
|
||||
|
||||
analytics.trackAPICallFailure({
|
||||
endpoint,
|
||||
model,
|
||||
|
||||
Reference in new issue
Block a user