# CORS 錯誤修正指南 ## 🔴 問題說明 您遇到的錯誤有兩個: ### 1. CORS (跨域資源共享) 錯誤 ``` Access to fetch at 'https://api.anthropic.com/v1/messages' from origin 'http://127.0.0.1:5000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. ``` **原因**: 前端代碼直接從瀏覽器調用 Claude API,但 Claude API 不允許來自瀏覽器的直接請求(出於安全考量)。 ### 2. Storage 訪問錯誤 ``` Uncaught (in promise) Error: Access to storage is not allowed from this context. ``` **原因**: 瀏覽器的本地存儲權限問題,通常在使用 `file://` 協議或某些安全限制下出現。 --- ## ✅ 解決方案 ### 方案 1: 修改 index.html 中的 callClaudeAPI 函數(推薦) **步驟 1**: 打開 [index.html](./index.html) **步驟 2**: 找到第 1264 行的 `callClaudeAPI` 函數 **步驟 3**: 將整個函數替換為以下代碼: ```javascript // ==================== AI Generation Functions ==================== async function callClaudeAPI(prompt, api = 'gemini') { try { // 調用後端 Flask API,避免 CORS 錯誤 const response = await fetch("/api/llm/generate", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ api: api, // 使用指定的 LLM API (gemini, deepseek, openai) 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; responseText = responseText.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim(); return JSON.parse(responseText); } catch (error) { console.error("Error calling LLM API:", error); // 顯示友好的錯誤訊息 alert(`AI 生成錯誤: ${error.message}\n\n請確保:\n1. Flask 後端已啟動\n2. 已在 .env 文件中配置 LLM API Key\n3. 網路連線正常`); throw error; } } ``` **步驟 4**: 保存文件 **步驟 5**: 確保使用更新版的 Flask 後端 ```bash # 使用包含 LLM 端點的版本 python app_updated.py ``` **步驟 6**: 重新載入瀏覽器頁面 --- ### 方案 2: 使用已修正的文件(快速方案) 我已經創建了包含完整修正的文件,您可以選擇以下方式之一: #### 選項 A: 手動修改(最安全) 1. 打開 `index.html` 2. 搜尋 `async function callClaudeAPI(prompt)` 3. 用上面方案 1 的代碼替換 #### 選項 B: 使用腳本自動修正 參考 [fix_cors.js](./fix_cors.js) 文件中的完整說明。 --- ## 📋 完整修正步驟 ### 1. 確認後端已啟動並包含 LLM 端點 ```bash # 停止當前運行的 Flask(如果有) # 按 Ctrl+C # 啟動更新版後端 python app_updated.py ``` 您應該看到: ``` ✓ LLM 功能已啟用 已配置的 API: gemini, deepseek, openai ``` ### 2. 配置 LLM API Key 編輯 [.env](./.env) 文件,添加至少一個 API Key: ```env # 至少配置其中一個 GEMINI_API_KEY=your_actual_gemini_api_key_here DEEPSEEK_API_KEY=your_actual_deepseek_api_key_here OPENAI_API_KEY=your_actual_openai_api_key_here ``` **獲取 API Key:** - **Gemini**: https://makersuite.google.com/app/apikey - **DeepSeek**: https://www.deepseek.com/ - **OpenAI**: https://platform.openai.com/api-keys ### 3. 測試 LLM API 連線 訪問測試頁面:http://localhost:5000/api-test 點擊「測試連線」按鈕,確保至少一個 API 顯示「✓ 連線成功」。 ### 4. 修改 index.html 按照方案 1 的步驟修改 `callClaudeAPI` 函數。 ### 5. 重新載入頁面 在瀏覽器中按 `Ctrl+F5` 強制重新載入頁面(清除緩存)。 ### 6. 測試 AI 功能 1. 在主頁面點擊「新增崗位」 2. 填寫部分欄位(例如崗位名稱) 3. 點擊「✨ I'm feeling lucky」按鈕 4. 應該會成功生成內容,不再出現 CORS 錯誤 --- ## 🔍 驗證修正是否成功 打開瀏覽器的開發者工具(F12),切換到 Console 標籤: ### ✅ 成功的表現: - 沒有 CORS 錯誤 - 看到 `POST http://localhost:5000/api/llm/generate` 請求成功 (200 OK) - AI 自動填充正常工作 ### ❌ 仍有問題: #### 如果看到 `403 LLM 功能未啟用` **原因**: 沒有使用 `app_updated.py` **解決**: ```bash python app_updated.py ``` #### 如果看到 `API Key 未設定` **原因**: .env 文件中沒有配置 API Key **解決**: 編輯 `.env` 文件,添加有效的 API Key #### 如果看到 `連線逾時` **原因**: 網路連線問題或 API 伺服器問題 **解決**: 1. 檢查網路連線 2. 嘗試使用不同的 LLM API(修改 `callClaudeAPI(prompt, 'deepseek')`) #### 如果看到 `API Key 無效` **原因**: API Key 錯誤或已過期 **解決**: 重新獲取有效的 API Key --- ## 🎯 架構變更說明 ### 修正前(錯誤): ``` 瀏覽器 → 直接調用 → Claude API (❌ CORS 錯誤) ``` ### 修正後(正確): ``` 瀏覽器 → Flask 後端 → Gemini/DeepSeek/OpenAI API (✅ 正常) ``` --- ## 💡 為什麼這樣修改 ### 1. 安全性 - **API Key 保護**: API Key 只存儲在服務器端(.env 文件),不暴露給前端 - **防止濫用**: 用戶無法看到或竊取 API Key ### 2. CORS 問題 - **同源請求**: 前端只調用同域的 Flask API(http://localhost:5000) - **服務器端請求**: Flask 服務器調用外部 API,不受 CORS 限制 ### 3. 靈活性 - **多 API 支持**: 可以輕鬆切換不同的 LLM API - **統一接口**: 前端代碼無需關心使用哪個 LLM API --- ## 📝 其他建議 ### 1. 添加錯誤處理 UI 在 `
` 標籤中添加錯誤處理腳本: ```html ``` ### 2. 選擇 LLM API 如果想使用特定的 LLM API,可以修改調用: ```javascript // 使用 Gemini(默認) const result = await callClaudeAPI(prompt, 'gemini'); // 使用 DeepSeek const result = await callClaudeAPI(prompt, 'deepseek'); // 使用 OpenAI const result = await callClaudeAPI(prompt, 'openai'); ``` ### 3. 添加 API 選擇器 可以在前端添加一個下拉選單,讓用戶選擇使用哪個 LLM API: ```html ``` 然後在調用時使用: ```javascript const api = document.getElementById('llm-selector').value; const result = await callClaudeAPI(prompt, api); ``` --- ## 🆘 仍然遇到問題? ### 檢查清單 - [ ] Flask 後端是否正在運行? - [ ] 是否使用 `app_updated.py` 而不是 `app.py`? - [ ] .env 文件中是否配置了至少一個 API Key? - [ ] API Key 是否有效?(可以在 http://localhost:5000/api-test 測試) - [ ] 是否已修改 index.html 中的 `callClaudeAPI` 函數? - [ ] 瀏覽器是否已重新載入頁面(Ctrl+F5)? - [ ] 瀏覽器控制台是否還有其他錯誤? ### 調試步驟 1. **測試後端 API**: ```bash curl -X POST http://localhost:5000/api/llm/generate \ -H "Content-Type: application/json" \ -d '{"api":"gemini","prompt":"測試","max_tokens":100}' ``` 2. **檢查 Flask 日誌**: 查看終端中 Flask 的輸出 3. **瀏覽器控制台**: 查看詳細的錯誤訊息 4. **測試頁面**: 訪問 http://localhost:5000/api-test 確認 API 配置 --- ## 📚 相關文件 - [SETUP.md](./SETUP.md) - 完整安裝指南 - [fix_cors.js](./fix_cors.js) - 詳細修正代碼 - [error_handler.js](./error_handler.js) - 全局錯誤處理 - [app_updated.py](./app_updated.py) - 包含 LLM 端點的 Flask 後端 --- **文件版本**: 1.0 **最後更新**: 2024-12-04 **問題類型**: CORS 跨域請求錯誤 **解決狀態**: ✅ 已提供完整解決方案