Files
hr-position-system/js/fix_cors.js
DonaldFang 方士碩 a6af297623 backup: 完成 HR_position_ 表格前綴重命名與欄位對照表整理
變更內容:
- 所有資料表加上 HR_position_ 前綴
- 整理完整欄位顯示名稱與 ID 對照表
- 模組化 JS 檔案 (admin.js, ai.js, csv.js 等)
- 專案結構優化 (docs/, scripts/, tests/ 等)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 12:05:20 +08:00

156 lines
4.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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<Object>} - 生成的 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 = '<div class="spinner"></div><span>AI 生成中...</span>';
} else {
btn.disabled = false;
btn.innerHTML = '<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg><span>✨ I\'m feeling lucky</span>';
}
}
// ==================== 選擇 LLM API 提供者 ====================
/**
* 讓用戶選擇使用哪個 LLM API
* @returns {Promise<string>} - 選擇的 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<Object>} - 生成的 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);
*/