- 縮小錦囊按鈕至原大小的 1/4: * padding: 20px → 8px 12px * font-size: 圖標 2rem → 1rem,標題 0.95rem → 0.75rem * gap: 16px → 8px * 整體更緊湊,節省空間 - 優化 Prompt 編輯模態框 Layout: * 寬度增加:700px → 900px * 高度限制:90vh,防止超出螢幕 * 標題和副標題改為兩欄並排顯示 * Textarea 高度增加:12 → 16 行 * 使用等寬字體 Consolas/Monaco,提升 prompt 編輯體驗 * 提示區塊優化為藍色主題,更醒目 * 按鈕添加 SVG 圖標,更直觀 * 使用 flexbox 確保 footer 固定底部 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
256 lines
8.8 KiB
Python
256 lines
8.8 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
欄位 ID 自動重命名腳本
|
||
根據 ID重命名對照表.md 批量替換 HTML 和 JavaScript 中的欄位 ID
|
||
"""
|
||
|
||
import re
|
||
import os
|
||
from pathlib import Path
|
||
|
||
# ID 重命名對照表
|
||
ID_MAPPINGS = {
|
||
# 模組 1: 崗位基礎資料 - 基礎資料頁籤 (15個)
|
||
'businessUnit': 'pos_businessUnit',
|
||
'division': 'pos_division',
|
||
'department': 'pos_department',
|
||
'section': 'pos_section',
|
||
'positionCode': 'pos_code',
|
||
'effectiveDate': 'pos_effectiveDate',
|
||
'positionName': 'pos_name',
|
||
'positionLevel': 'pos_level',
|
||
'positionCategory': 'pos_category',
|
||
'positionCategoryName': 'pos_categoryName',
|
||
'positionNature': 'pos_type',
|
||
'positionNatureName': 'pos_typeName',
|
||
'headcount': 'pos_headcount',
|
||
'positionDesc': 'pos_desc',
|
||
'positionRemark': 'pos_remark',
|
||
|
||
# 模組 2: 崗位基礎資料 - 招聘要求頁籤 (18個)
|
||
'minEducation': 'rec_eduLevel',
|
||
'requiredGender': 'rec_gender',
|
||
'salaryRange': 'rec_salaryRange',
|
||
'workExperience': 'rec_expYears',
|
||
'minAge': 'rec_minAge',
|
||
'maxAge': 'rec_maxAge',
|
||
'jobType': 'rec_jobType',
|
||
'recruitPosition': 'rec_position',
|
||
'jobTitle': 'rec_jobTitle',
|
||
'superiorPosition': 'rec_superiorCode',
|
||
'jobDesc': 'rec_jobDesc',
|
||
'positionReq': 'rec_positionReq',
|
||
'titleReq': 'rec_certReq',
|
||
'majorReq': 'rec_majorReq',
|
||
'skillReq': 'rec_skillReq',
|
||
'langReq': 'rec_langReq',
|
||
'otherReq': 'rec_otherReq',
|
||
'recruitRemark': 'rec_remark',
|
||
|
||
# 模組 3: 職務基礎資料 (12個)
|
||
'jobCategoryCode': 'job_category',
|
||
'jobCategoryName': 'job_categoryName',
|
||
'jobCode': 'job_code',
|
||
'jobName': 'job_name',
|
||
'jobNameEn': 'job_nameEn',
|
||
'jobEffectiveDate': 'job_effectiveDate',
|
||
'jobLevel': 'job_level',
|
||
'jobHeadcount': 'job_headcount',
|
||
'jobSortOrder': 'job_sortOrder',
|
||
'hasAttendanceBonus': 'job_hasAttBonus',
|
||
'hasHousingAllowance': 'job_hasHouseAllow',
|
||
'jobRemark': 'job_remark',
|
||
|
||
# 模組 4: 部門職責 (19個 - 包含合併重複欄位)
|
||
'deptFunctionCode': 'df_code',
|
||
'deptFunctionName': 'df_name',
|
||
'deptFunctionBU': 'df_businessUnit',
|
||
'deptFunc_businessUnit': 'df_businessUnit', # 合併
|
||
'deptFunc_division': 'df_division',
|
||
'deptFunc_department': 'df_department',
|
||
'deptFunc_section': 'df_section',
|
||
'deptFunc_positionTitle': 'df_posTitle',
|
||
'deptFunc_positionLevel': 'df_posLevel',
|
||
'deptManager': 'df_managerTitle',
|
||
'deptFunctionEffectiveDate': 'df_effectiveDate',
|
||
'deptHeadcount': 'df_headcountLimit',
|
||
'deptStatus': 'df_status',
|
||
'deptMission': 'df_mission',
|
||
'deptVision': 'df_vision',
|
||
'deptCoreFunctions': 'df_coreFunc',
|
||
'deptKPIs': 'df_kpis',
|
||
'deptCollaboration': 'df_collab',
|
||
'deptFunctionRemark': 'df_remark',
|
||
|
||
# 模組 5: 崗位描述 (8個需要變更的)
|
||
'jd_positionCode': 'jd_posCode',
|
||
'jd_positionName': 'jd_posName',
|
||
'jd_positionLevel': 'jd_posLevel',
|
||
'jd_positionEffectiveDate': 'jd_posEffDate',
|
||
'jd_directSupervisor': 'jd_supervisor',
|
||
'jd_positionGradeJob': 'jd_gradeJob',
|
||
'jd_workLocation': 'jd_location',
|
||
'jd_empAttribute': 'jd_empAttr',
|
||
'jd_deptFunctionCode': 'jd_dfCode',
|
||
'jd_positionPurpose': 'jd_purpose',
|
||
'jd_mainResponsibilities': 'jd_mainResp',
|
||
'jd_education': 'jd_eduLevel',
|
||
'jd_basicSkills': 'jd_basicSkills',
|
||
'jd_professionalKnowledge': 'jd_proKnowledge',
|
||
'jd_workExperienceReq': 'jd_expReq',
|
||
'jd_otherRequirements': 'jd_otherReq',
|
||
}
|
||
|
||
# 需要特殊處理的函數名映射(onchange事件等)
|
||
FUNCTION_MAPPINGS = {
|
||
'updateCategoryName': 'updateCategoryName', # 保持不變,但內部需要更新
|
||
'updateNatureName': 'updateTypeName', # positionNature -> pos_type
|
||
'updateJobCategoryName': 'updateJobCategoryName', # 保持不變
|
||
}
|
||
|
||
|
||
def replace_in_file(file_path, dry_run=False):
|
||
"""
|
||
在文件中替換所有匹配的 ID
|
||
|
||
Args:
|
||
file_path: 文件路徑
|
||
dry_run: 如果為 True,只輸出變更不實際修改
|
||
|
||
Returns:
|
||
(總替換次數, 變更詳情列表)
|
||
"""
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
original_content = content
|
||
changes = []
|
||
total_replacements = 0
|
||
|
||
# 排序:按舊ID長度降序,避免短ID誤替換長ID
|
||
sorted_mappings = sorted(ID_MAPPINGS.items(), key=lambda x: len(x[0]), reverse=True)
|
||
|
||
for old_id, new_id in sorted_mappings:
|
||
if old_id == new_id:
|
||
continue
|
||
|
||
# 匹配模式:
|
||
# 1. HTML id="oldId"
|
||
# 2. JavaScript getElementById('oldId') 或 getElementById("oldId")
|
||
# 3. HTML for="oldId"
|
||
# 4. HTML name="oldId"
|
||
# 5. 對象屬性 {oldId: ...} 或 data.oldId
|
||
|
||
patterns = [
|
||
# HTML id 屬性
|
||
(rf'\bid=["\']({re.escape(old_id)})["\']', rf'id="\1"', lambda m: f'id="{new_id}"'),
|
||
# HTML for 屬性
|
||
(rf'\bfor=["\']({re.escape(old_id)})["\']', rf'for="\1"', lambda m: f'for="{new_id}"'),
|
||
# HTML name 屬性
|
||
(rf'\bname=["\']({re.escape(old_id)})["\']', rf'name="\1"', lambda m: f'name="{new_id}"'),
|
||
# getElementById
|
||
(rf'getElementById\(["\']({re.escape(old_id)})["\']', rf'getElementById("\1")', lambda m: f'getElementById("{new_id}")'),
|
||
# 對象屬性訪問 .oldId (謹慎使用,確保前面是合理的對象)
|
||
(rf'\.({re.escape(old_id)})\b', rf'.\1', lambda m: f'.{new_id}'),
|
||
# 對象字面量屬性 oldId: 或 "oldId":
|
||
(rf'\b({re.escape(old_id)}):', rf'\1:', lambda m: f'{new_id}:'),
|
||
]
|
||
|
||
for pattern, _, replacement_func in patterns:
|
||
matches = list(re.finditer(pattern, content))
|
||
if matches:
|
||
# 從後往前替換,避免索引偏移
|
||
for match in reversed(matches):
|
||
start, end = match.span()
|
||
old_text = content[start:end]
|
||
new_text = replacement_func(match)
|
||
|
||
if old_text != new_text:
|
||
content = content[:start] + new_text + content[end:]
|
||
changes.append({
|
||
'old': old_text,
|
||
'new': new_text,
|
||
'line': content[:start].count('\n') + 1
|
||
})
|
||
total_replacements += 1
|
||
|
||
# 如果有變更且非 dry run,寫回文件
|
||
if content != original_content and not dry_run:
|
||
with open(file_path, 'w', encoding='utf-8', newline='') as f:
|
||
f.write(content)
|
||
|
||
return total_replacements, changes
|
||
|
||
|
||
def main():
|
||
"""主函數"""
|
||
base_dir = Path(__file__).parent
|
||
|
||
# 需要處理的文件列表
|
||
files_to_process = [
|
||
base_dir / 'index.html',
|
||
base_dir / 'js' / 'ui.js',
|
||
base_dir / 'js' / 'ai-bags.js',
|
||
base_dir / 'js' / 'main.js',
|
||
]
|
||
|
||
print("=" * 80)
|
||
print("欄位 ID 重命名工具")
|
||
print("=" * 80)
|
||
print(f"\n📋 總計需要重命名:{len(ID_MAPPINGS)} 個 ID")
|
||
print(f"📂 需要處理:{len(files_to_process)} 個文件\n")
|
||
|
||
# 先 dry run 顯示變更
|
||
print("🔍 掃描變更(Dry Run)...")
|
||
print("-" * 80)
|
||
|
||
total_changes = 0
|
||
for file_path in files_to_process:
|
||
if not file_path.exists():
|
||
print(f"⚠️ 文件不存在:{file_path.name}")
|
||
continue
|
||
|
||
count, changes = replace_in_file(file_path, dry_run=True)
|
||
total_changes += count
|
||
|
||
if count > 0:
|
||
print(f"\n📄 {file_path.name}: {count} 處變更")
|
||
# 顯示前 5 個變更示例
|
||
for i, change in enumerate(changes[:5]):
|
||
print(f" L{change['line']}: {change['old']} → {change['new']}")
|
||
if len(changes) > 5:
|
||
print(f" ... 還有 {len(changes) - 5} 處變更")
|
||
|
||
print("\n" + "=" * 80)
|
||
print(f"📊 總計:{total_changes} 處需要替換")
|
||
print("=" * 80)
|
||
|
||
# 詢問是否執行
|
||
response = input("\n是否執行替換?(y/n): ").strip().lower()
|
||
|
||
if response == 'y':
|
||
print("\n🚀 開始執行替換...")
|
||
print("-" * 80)
|
||
|
||
for file_path in files_to_process:
|
||
if not file_path.exists():
|
||
continue
|
||
|
||
count, _ = replace_in_file(file_path, dry_run=False)
|
||
if count > 0:
|
||
print(f"✅ {file_path.name}: 已替換 {count} 處")
|
||
|
||
print("\n✨ 替換完成!")
|
||
print("\n⚠️ 請執行以下步驟:")
|
||
print(" 1. 測試所有表單功能")
|
||
print(" 2. 檢查瀏覽器控制台是否有錯誤")
|
||
print(" 3. 使用 git diff 檢查變更")
|
||
print(" 4. 提交變更:git add -A && git commit -m 'refactor: 標準化欄位 ID 命名'")
|
||
else:
|
||
print("\n❌ 已取消執行")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|