fix: 前端 API 调用改为相对路径,通过 Vite 代理避免 CORS
前端 5 个文件中硬编码了 http://localhost:8080 绝对路径, 浏览器从 127.0.0.1:5173 访问时触发 CORS 预检失败。 改为相对路径 /api/v1/... 通过 Vite 代理转发, WebSocket URL 改为动态构造(基于当前页面 host)。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import type { AuthResponse } from '@/types/session';
|
||||
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8080/api/v1';
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || '/api/v1';
|
||||
|
||||
/** localStorage key 前缀 */
|
||||
const LS_TOKEN_KEY = 'token';
|
||||
|
||||
@@ -38,7 +38,7 @@ interface FileResponse {
|
||||
thumbnail_url?: string;
|
||||
}
|
||||
|
||||
const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:8080/api/v1';
|
||||
const API_BASE = import.meta.env.VITE_API_URL || '/api/v1';
|
||||
|
||||
/**
|
||||
* 获取带授权头的文件下载/缩略图 URL (用于 fetch 直接获取 blob)
|
||||
|
||||
@@ -170,7 +170,7 @@ export async function exportSession(
|
||||
): Promise<void> {
|
||||
const token = localStorage.getItem('token');
|
||||
const resp = await fetch(
|
||||
`${import.meta.env.VITE_API_URL || 'http://localhost:8080/api/v1'}/sessions/${encodeURIComponent(sessionId)}/export?format=${format}`,
|
||||
`${import.meta.env.VITE_API_URL || '/api/v1'}/sessions/${encodeURIComponent(sessionId)}/export?format=${format}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
|
||||
@@ -73,7 +73,7 @@ async function transcribeAudio(audioBlob: Blob, language?: string): Promise<ApiR
|
||||
// 不设置 Content-Type,让浏览器自动处理 multipart boundary
|
||||
|
||||
try {
|
||||
const response = await fetch('http://localhost:8080/api/v1/voice/transcribe', {
|
||||
const response = await fetch('/api/v1/voice/transcribe', {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: formData,
|
||||
@@ -110,7 +110,7 @@ async function synthesizeSpeech(req: TTSSynthesizeRequest): Promise<string> {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const response = await fetch('http://localhost:8080/api/v1/voice/tts', {
|
||||
const response = await fetch('/api/v1/voice/tts', {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(req),
|
||||
|
||||
@@ -5,8 +5,11 @@ import { useNotificationStore } from '@/store/notificationStore';
|
||||
import { getToken } from '@/api/client';
|
||||
import type { Message, WSClientMessage, WSServerMessage } from '@/types/chat';
|
||||
|
||||
const WS_BASE_URL =
|
||||
import.meta.env.VITE_WS_URL || 'ws://localhost:8080/ws/chat';
|
||||
function getWsUrl(): string {
|
||||
if (import.meta.env.VITE_WS_URL) return import.meta.env.VITE_WS_URL;
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
return `${protocol}//${window.location.host}/ws/chat`;
|
||||
}
|
||||
|
||||
// ========== 指数退避重连配置 ==========
|
||||
const INITIAL_RECONNECT_DELAY_MS = 1000; // 初始延迟 1 秒
|
||||
@@ -77,8 +80,8 @@ export function useWebSocket() {
|
||||
|
||||
const sessionID = useSessionStore.getState().currentSessionId || '';
|
||||
const url = sessionID
|
||||
? `${WS_BASE_URL}?token=${token}&session_id=${sessionID}`
|
||||
: `${WS_BASE_URL}?token=${token}`;
|
||||
? `${getWsUrl()}?token=${token}&session_id=${sessionID}`
|
||||
: `${getWsUrl()}?token=${token}`;
|
||||
|
||||
console.log(`[WS#${instanceId}] 正在连接, session_id=${sessionID || '(无)'}, reconnectAttempt=${reconnectCountRef.current}`);
|
||||
const ws = new WebSocket(url);
|
||||
|
||||
Reference in New Issue
Block a user