/** * CORS 錯誤修正 * 將直接調用 Claude API 改為通過後端 Flask API 調用 * * 使用方法: * 1. 在 index.html 中找到 callClaudeAPI 函數 * 2. 將其替換為下面的新版本 */ // ==================== 修正後的 AI Generation Functions ==================== /** * 調用後端 LLM API 生成文字 * @param {string} prompt - 提示詞 * @param {string} api - API 名稱 (gemini, deepseek, openai) * @returns {Promise} - 生成的 JSON 數據 */ async function callClaudeAPI(prompt, api = 'gemini') { try { // 調用後端 Flask API,而不是直接調用 Claude API const response = await fetch("/api/llm/generate", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ api: api, // 使用 Gemini 作為默認 prompt: prompt, max_tokens: 2000 }) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || `API 請求失敗: ${response.status}`); } const data = await response.json(); if (!data.success) { throw new Error(data.error || 'API 調用失敗'); } // 解析返回的文字為 JSON let responseText = data.text; // 移除可能的 markdown 代碼塊標記 responseText = responseText.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim(); // 解析 JSON return JSON.parse(responseText); } catch (error) { console.error("Error calling LLM API:", error); // 使用全局錯誤處理器顯示錯誤 if (window.errorHandler) { window.errorHandler.showError({ title: 'AI 生成錯誤', message: error.message || '調用 AI API 時發生錯誤', type: 'error', details: error.stack }); } else { alert(`AI 生成錯誤: ${error.message}`); } throw error; } } /** * 設置按鈕載入狀態 * @param {HTMLElement} btn - 按鈕元素 * @param {boolean} loading - 是否載入中 */ function setButtonLoading(btn, loading) { if (loading) { btn.disabled = true; btn.innerHTML = '
AI 生成中...'; } else { btn.disabled = false; btn.innerHTML = '✨ I\'m feeling lucky'; } } // ==================== 選擇 LLM API 提供者 ==================== /** * 讓用戶選擇使用哪個 LLM API * @returns {Promise} - 選擇的 API 名稱 */ async function selectLLMProvider() { // 獲取可用的 API 列表 try { const response = await fetch('/api/llm/config'); const config = await response.json(); const enabledAPIs = []; for (const [key, value] of Object.entries(config)) { if (value.enabled) { enabledAPIs.push({ key: key, name: value.name }); } } if (enabledAPIs.length === 0) { throw new Error('沒有可用的 LLM API,請先配置 API Key'); } // 如果只有一個 API,直接使用 if (enabledAPIs.length === 1) { return enabledAPIs[0].key; } // 多個 API 時,使用第一個(默認 Gemini) return enabledAPIs[0].key; } catch (error) { console.error('無法獲取 LLM 配置:', error); // 默認使用 Gemini return 'gemini'; } } /** * 增強版的 callClaudeAPI - 自動選擇最佳 API * @param {string} prompt - 提示詞 * @returns {Promise} - 生成的 JSON 數據 */ async function callAIAPI(prompt) { const api = await selectLLMProvider(); return callClaudeAPI(prompt, api); } // ==================== 使用示例 ==================== /* // 原來的調用方式(會導致 CORS 錯誤): const result = await callClaudeAPI(prompt); // 修正後的調用方式 1(使用默認 Gemini): const result = await callClaudeAPI(prompt, 'gemini'); // 修正後的調用方式 2(使用 DeepSeek): const result = await callClaudeAPI(prompt, 'deepseek'); // 修正後的調用方式 3(使用 OpenAI): const result = await callClaudeAPI(prompt, 'openai'); // 修正後的調用方式 4(自動選擇最佳 API): const result = await callAIAPI(prompt); */