Files
hr-position-system/apply_cors_fix.py
DonaldFang 方士碩 b2584772c4 feat: 新增崗位描述與清單整合功能 v2.1
主要功能更新:
- 崗位描述保存功能:保存後資料寫入資料庫
- 崗位清單自動刷新:切換模組時自動載入最新資料
- 崗位清單檢視功能:點擊「檢視」按鈕載入對應描述
- 管理者頁面擴充:新增崗位資料管理與匯出功能
- CSV 批次匯入:支援崗位與職務資料批次匯入

後端 API 新增:
- Position Description CRUD APIs
- Position List Query & Export APIs
- CSV Template Download & Import APIs

文件更新:
- SDD.md 更新至版本 2.1
- README.md 更新功能說明與版本歷史

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 12:46:36 +08:00

237 lines
8.1 KiB
Python
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.

"""
自動修正 index.html 中的 CORS 錯誤
將直接調用 Claude API 改為通過 Flask 後端調用
"""
import os
import re
from pathlib import Path
def fix_cors_in_index_html():
"""修正 index.html 中的 CORS 問題"""
# 文件路徑
index_path = Path(__file__).parent / 'index.html'
backup_path = Path(__file__).parent / 'index.html.backup'
if not index_path.exists():
print(f"❌ 錯誤: 找不到 {index_path}")
return False
print(f"📂 讀取文件: {index_path}")
# 讀取文件內容
with open(index_path, 'r', encoding='utf-8') as f:
content = f.read()
# 檢查是否已經修正過
if '/api/llm/generate' in content:
print("✓ 文件已經修正過,無需重複修正")
return True
# 備份原文件
print(f"💾 創建備份: {backup_path}")
with open(backup_path, 'w', encoding='utf-8') as f:
f.write(content)
# 原始代碼模式
old_pattern = r'''async function callClaudeAPI\(prompt\) \{
try \{
const response = await fetch\("https://api\.anthropic\.com/v1/messages", \{
method: "POST",
headers: \{
"Content-Type": "application/json",
\},
body: JSON\.stringify\(\{
model: "claude-sonnet-4-20250514",
max_tokens: 2000,
messages: \[
\{ role: "user", content: prompt \}
\]
\}\)
\}\);
if \(!response\.ok\) \{
throw new Error\(`API request failed: \$\{response\.status\}`\);
\}
const data = await response\.json\(\);
let responseText = data\.content\[0\]\.text;
responseText = responseText\.replace\(/```json\\n\?/g, ""\)\.replace\(/```\\n\?/g, ""\)\.trim\(\);
return JSON\.parse\(responseText\);
\} catch \(error\) \{
console\.error\("Error calling Claude API:", error\);
throw error;
\}
\}'''
# 新代碼
new_code = '''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 後端已啟動 (python app_updated.py)\\n2. 已在 .env 文件中配置 LLM API Key\\n3. 網路連線正常`);
throw error;
}
}'''
# 簡單替換(如果正則表達式匹配失敗)
old_simple = '''async function callClaudeAPI(prompt) {
try {
const response = await fetch("https://api.anthropic.com/v1/messages", {'''
new_simple = '''async function callClaudeAPI(prompt, api = 'gemini') {
try {
// 調用後端 Flask API避免 CORS 錯誤
const response = await fetch("/api/llm/generate", {'''
print("🔧 應用修正...")
# 嘗試正則表達式替換
new_content = re.sub(old_pattern, new_code, content, flags=re.MULTILINE)
# 如果正則表達式沒有匹配,使用簡單替換
if new_content == content:
print("⚠️ 正則表達式未匹配,使用簡單替換...")
# 找到函數的開始和結束
start_marker = 'async function callClaudeAPI(prompt) {'
end_marker = ' }'
start_idx = content.find(start_marker)
if start_idx == -1:
print("❌ 錯誤: 找不到 callClaudeAPI 函數")
return False
# 找到函數結束(找到第一個與縮進匹配的 }
end_idx = start_idx
brace_count = 0
in_function = False
for i in range(start_idx, len(content)):
if content[i] == '{':
brace_count += 1
in_function = True
elif content[i] == '}':
brace_count -= 1
if in_function and brace_count == 0:
end_idx = i + 1
break
if end_idx == start_idx:
print("❌ 錯誤: 無法找到函數結束位置")
return False
# 替換函數
new_content = content[:start_idx] + new_code + content[end_idx:]
# 寫回文件
print(f"💾 保存修正後的文件: {index_path}")
with open(index_path, 'w', encoding='utf-8') as f:
f.write(new_content)
print("\n✅ CORS 修正完成!")
print("\n📋 接下來的步驟:")
print("1. 確保 .env 文件中已配置至少一個 LLM API Key")
print("2. 啟動 Flask 後端: python app_updated.py")
print("3. 在瀏覽器中重新載入頁面 (Ctrl+F5)")
print("4. 測試 AI 自動填充功能")
print(f"\n💡 原文件已備份至: {backup_path}")
return True
def verify_flask_backend():
"""檢查是否有正確的 Flask 後端文件"""
app_updated = Path(__file__).parent / 'app_updated.py'
if not app_updated.exists():
print("\n⚠️ 警告: 找不到 app_updated.py")
print("請確保使用包含 LLM API 端點的 Flask 後端")
return False
print(f"\n✓ 找到更新版 Flask 後端: {app_updated}")
return True
def check_env_file():
"""檢查 .env 文件配置"""
env_path = Path(__file__).parent / '.env'
if not env_path.exists():
print("\n⚠️ 警告: 找不到 .env 文件")
return False
with open(env_path, 'r', encoding='utf-8') as f:
env_content = f.read()
has_gemini = 'GEMINI_API_KEY=' in env_content and 'your_gemini_api_key_here' not in env_content
has_deepseek = 'DEEPSEEK_API_KEY=' in env_content and 'your_deepseek_api_key_here' not in env_content
has_openai = 'OPENAI_API_KEY=' in env_content and 'your_openai_api_key_here' not in env_content
print("\n📋 LLM API Key 配置狀態:")
print(f" {'' if has_gemini else ''} Gemini API Key")
print(f" {'' if has_deepseek else ''} DeepSeek API Key")
print(f" {'' if has_openai else ''} OpenAI API Key")
if not (has_gemini or has_deepseek or has_openai):
print("\n⚠️ 警告: 沒有配置任何 LLM API Key")
print("請編輯 .env 文件,添加至少一個有效的 API Key")
return False
return True
if __name__ == '__main__':
print("=" * 60)
print("HR Position System - CORS 錯誤自動修正工具")
print("=" * 60)
print()
# 修正 CORS 問題
if fix_cors_in_index_html():
# 驗證其他配置
verify_flask_backend()
check_env_file()
print("\n" + "=" * 60)
print("✅ 修正完成!")
print("=" * 60)
else:
print("\n" + "=" * 60)
print("❌ 修正失敗,請查看上述錯誤訊息")
print("=" * 60)
print("\n您也可以手動修正,請參考: CORS_FIX_GUIDE.md")