Files
hr-position-system/rename_field_ids.py
DonaldFang 方士碩 ea745ffefc refactor: 優化三個錦囊 UI 設計
- 縮小錦囊按鈕至原大小的 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>
2025-12-06 01:25:47 +08:00

256 lines
8.8 KiB
Python
Raw 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.

#!/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()