主要功能更新: - 崗位描述保存功能:保存後資料寫入資料庫 - 崗位清單自動刷新:切換模組時自動載入最新資料 - 崗位清單檢視功能:點擊「檢視」按鈕載入對應描述 - 管理者頁面擴充:新增崗位資料管理與匯出功能 - 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>
488 lines
25 KiB
Python
488 lines
25 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
添加部門職責頁籤和修正檢視按鈕功能
|
||
"""
|
||
import sys
|
||
import codecs
|
||
|
||
if sys.platform == 'win32':
|
||
sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, 'strict')
|
||
sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer, 'strict')
|
||
|
||
# 讀取 index.html
|
||
with open('index.html', 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
# ==================== 1. 修正檢視按鈕功能 ====================
|
||
old_view_function = ''' // 檢視崗位
|
||
function viewPosition(code) {
|
||
const position = positionListData.find(p => p.positionCode === code);
|
||
if (position) {
|
||
showToast('檢視崗位: ' + position.positionName);
|
||
}
|
||
}'''
|
||
|
||
new_view_function = ''' // 檢視崗位 - 切換到崗位基礎資料頁籤並載入資料
|
||
function viewPosition(code) {
|
||
const position = positionListData.find(p => p.positionCode === code);
|
||
if (position) {
|
||
// 切換到崗位基礎資料模組
|
||
document.querySelectorAll('.module-btn').forEach(b => {
|
||
b.classList.remove('active', 'job-active', 'desc-active');
|
||
});
|
||
document.querySelector('.module-btn[data-module="position"]').classList.add('active');
|
||
|
||
document.querySelectorAll('.module-content').forEach(m => m.classList.remove('active'));
|
||
document.getElementById('module-position').classList.add('active');
|
||
|
||
// 填入崗位資料
|
||
document.getElementById('positionCode').value = position.positionCode || '';
|
||
document.getElementById('positionName').value = position.positionName || '';
|
||
|
||
// 根據崗位類別設定下拉選單
|
||
const categoryMap = {'技術職': '01', '管理職': '02', '業務職': '03', '行政職': '04', '專業職': '05'};
|
||
const categoryCode = categoryMap[position.positionCategory] || '';
|
||
document.getElementById('positionCategory').value = categoryCode;
|
||
if (typeof updateCategoryName === 'function') updateCategoryName();
|
||
|
||
document.getElementById('headcount').value = position.headcount || '';
|
||
document.getElementById('effectiveDate').value = position.effectiveDate || '';
|
||
|
||
// 填入組織欄位
|
||
if (document.getElementById('businessUnit')) {
|
||
document.getElementById('businessUnit').value = position.businessUnit || '';
|
||
}
|
||
if (document.getElementById('department')) {
|
||
document.getElementById('department').value = position.department || '';
|
||
}
|
||
|
||
showToast('已載入崗位: ' + position.positionName);
|
||
}
|
||
}'''
|
||
|
||
if old_view_function in content:
|
||
content = content.replace(old_view_function, new_view_function)
|
||
print("[OK] Fixed viewPosition function")
|
||
else:
|
||
print("[INFO] viewPosition function pattern not found or already updated")
|
||
|
||
# ==================== 2. 添加部門職責頁籤按鈕 ====================
|
||
# 在崗位描述按鈕後面添加部門職責按鈕
|
||
old_module_buttons = ''' <button class="module-btn" data-module="jobdesc">
|
||
<svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></svg>
|
||
崗位描述
|
||
</button>
|
||
<button class="module-btn" data-module="positionlist">'''
|
||
|
||
new_module_buttons = ''' <button class="module-btn" data-module="deptfunction">
|
||
<svg viewBox="0 0 24 24"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"/></svg>
|
||
部門職責
|
||
</button>
|
||
<button class="module-btn" data-module="jobdesc">
|
||
<svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></svg>
|
||
崗位描述
|
||
</button>
|
||
<button class="module-btn" data-module="positionlist">'''
|
||
|
||
if old_module_buttons in content and 'data-module="deptfunction"' not in content:
|
||
content = content.replace(old_module_buttons, new_module_buttons)
|
||
print("[OK] Added Department Function tab button")
|
||
else:
|
||
print("[INFO] Department Function tab button already exists or pattern not found")
|
||
|
||
# ==================== 3. 添加部門職責模組內容 ====================
|
||
# 在崗位描述模組之前添加部門職責模組
|
||
dept_function_module = '''
|
||
<!-- ==================== 部門職責模組 ==================== -->
|
||
<div class="module-content" id="module-deptfunction">
|
||
<header class="app-header">
|
||
<div class="icon">
|
||
<svg viewBox="0 0 24 24"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"/></svg>
|
||
</div>
|
||
<div>
|
||
<h1>部門職責維護</h1>
|
||
<div class="subtitle">Department Function Management</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="form-card">
|
||
<form id="deptFunctionForm">
|
||
<div class="tab-content active">
|
||
<button type="button" class="ai-generate-btn" onclick="generateDeptFunction()">
|
||
<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>
|
||
</button>
|
||
|
||
<div class="csv-buttons" style="margin-bottom: 15px;">
|
||
<button type="button" class="btn btn-secondary" onclick="importDeptFunctionCSV()">匯入 CSV</button>
|
||
<button type="button" class="btn btn-secondary" onclick="exportDeptFunctionCSV()">匯出 CSV</button>
|
||
<input type="file" id="deptFunctionCsvInput" accept=".csv" style="display: none;" onchange="handleDeptFunctionCSVImport(event)">
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>部門職責編號 <span class="required">*</span></label>
|
||
<input type="text" id="deptFunctionCode" name="deptFunctionCode" required placeholder="例如: DF-001">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>部門職責名稱 <span class="required">*</span></label>
|
||
<input type="text" id="deptFunctionName" name="deptFunctionName" required placeholder="例如: 軟體研發部職責">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>事業體 (Business Unit) <span class="required">*</span></label>
|
||
<select id="deptFunctionBU" name="deptFunctionBU" required>
|
||
<option value="">-- 請選擇 --</option>
|
||
<option value="SBU">SBU - 業務事業體</option>
|
||
<option value="MBU">MBU - 製造事業體</option>
|
||
<option value="HQBU">HQBU - 總部事業體</option>
|
||
<option value="ITBU">ITBU - 資訊事業體</option>
|
||
<option value="HRBU">HRBU - 人資事業體</option>
|
||
<option value="ACCBU">ACCBU - 財會事業體</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>部門名稱 <span class="required">*</span></label>
|
||
<input type="text" id="deptFunctionDept" name="deptFunctionDept" required placeholder="例如: 軟體研發部">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>部門主管職稱</label>
|
||
<input type="text" id="deptManager" name="deptManager" placeholder="例如: 部門經理">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>生效日期 <span class="required">*</span></label>
|
||
<input type="date" id="deptFunctionEffectiveDate" name="deptFunctionEffectiveDate" required>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label>部門人數上限</label>
|
||
<input type="number" id="deptHeadcount" name="deptHeadcount" min="1" placeholder="例如: 50">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>部門狀態</label>
|
||
<select id="deptStatus" name="deptStatus">
|
||
<option value="active">啟用中</option>
|
||
<option value="inactive">停用</option>
|
||
<option value="planning">規劃中</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group full-width">
|
||
<label>部門使命 (Mission)</label>
|
||
<textarea id="deptMission" name="deptMission" placeholder="• 請描述部門的核心使命..." rows="3"></textarea>
|
||
</div>
|
||
|
||
<div class="form-group full-width">
|
||
<label>部門願景 (Vision)</label>
|
||
<textarea id="deptVision" name="deptVision" placeholder="• 請描述部門的長期願景..." rows="3"></textarea>
|
||
</div>
|
||
|
||
<div class="form-group full-width">
|
||
<label>核心職責 (Core Functions) <span class="required">*</span></label>
|
||
<textarea id="deptCoreFunctions" name="deptCoreFunctions" required placeholder="• 職責一:...
|
||
• 職責二:...
|
||
• 職責三:..." rows="6"></textarea>
|
||
</div>
|
||
|
||
<div class="form-group full-width">
|
||
<label>關鍵績效指標 (KPIs)</label>
|
||
<textarea id="deptKPIs" name="deptKPIs" placeholder="• KPI 1:...
|
||
• KPI 2:...
|
||
• KPI 3:..." rows="4"></textarea>
|
||
</div>
|
||
|
||
<div class="form-group full-width">
|
||
<label>協作部門</label>
|
||
<textarea id="deptCollaboration" name="deptCollaboration" placeholder="• 與XX部門協作進行...
|
||
• 與YY部門共同負責..." rows="3"></textarea>
|
||
</div>
|
||
|
||
<div class="form-group full-width">
|
||
<label>備注</label>
|
||
<textarea id="deptFunctionRemark" name="deptFunctionRemark" placeholder="請輸入其他補充說明..." rows="3"></textarea>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="action-bar">
|
||
<div class="nav-buttons">
|
||
<button class="nav-btn" title="第一筆"><svg viewBox="0 0 24 24"><path d="M18.41 16.59L13.82 12l4.59-4.59L17 6l-6 6 6 6 1.41-1.41zM6 6h2v12H6V6z"/></svg></button>
|
||
<button class="nav-btn" title="上一筆"><svg viewBox="0 0 24 24"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg></button>
|
||
<button class="nav-btn" title="下一筆"><svg viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg></button>
|
||
<button class="nav-btn" title="最後一筆"><svg viewBox="0 0 24 24"><path d="M5.59 7.41L10.18 12l-4.59 4.59L7 18l6-6-6-6-1.41 1.41zM16 6h2v12h-2V6z"/></svg></button>
|
||
</div>
|
||
<div class="action-buttons">
|
||
<button class="btn btn-secondary" onclick="clearDeptFunctionForm()">清除</button>
|
||
<button class="btn btn-cancel" onclick="cancelDeptFunction()">取消</button>
|
||
<button class="btn btn-primary" onclick="saveDeptFunctionAndNew()">存檔續建</button>
|
||
<button class="btn btn-primary" onclick="saveDeptFunctionAndExit()">存檔離開</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
'''
|
||
|
||
# 在崗位描述模組之前插入
|
||
jobdesc_module_start = ' <!-- ==================== 崗位描述模組 ===================='
|
||
|
||
if jobdesc_module_start in content and 'id="module-deptfunction"' not in content:
|
||
content = content.replace(jobdesc_module_start, dept_function_module + jobdesc_module_start)
|
||
print("[OK] Added Department Function module content")
|
||
else:
|
||
print("[INFO] Department Function module already exists or pattern not found")
|
||
|
||
# ==================== 4. 添加部門職責相關 JavaScript 函數 ====================
|
||
dept_function_js = '''
|
||
// ==================== 部門職責模組功能 ====================
|
||
let deptFunctionData = [
|
||
{
|
||
deptFunctionCode: 'DF-001',
|
||
deptFunctionName: '軟體研發部職責',
|
||
deptFunctionBU: 'ITBU',
|
||
deptFunctionDept: '軟體研發部',
|
||
deptManager: '研發部經理',
|
||
deptFunctionEffectiveDate: '2024-01-01',
|
||
deptHeadcount: 30,
|
||
deptStatus: 'active',
|
||
deptMission: '• 開發高品質軟體產品\\n• 持續創新技術解決方案',
|
||
deptVision: '• 成為業界領先的軟體研發團隊',
|
||
deptCoreFunctions: '• 軟體系統設計與開發\\n• 程式碼品質管理\\n• 技術架構規劃\\n• 新技術研究與導入',
|
||
deptKPIs: '• 專案準時交付率 > 90%\\n• 程式碼缺陷率 < 1%\\n• 客戶滿意度 > 4.5/5',
|
||
deptCollaboration: '• 與產品部協作需求分析\\n• 與品保部協作測試驗證',
|
||
deptFunctionRemark: ''
|
||
},
|
||
{
|
||
deptFunctionCode: 'DF-002',
|
||
deptFunctionName: '人力資源部職責',
|
||
deptFunctionBU: 'HRBU',
|
||
deptFunctionDept: '人力資源部',
|
||
deptManager: '人資部經理',
|
||
deptFunctionEffectiveDate: '2024-01-01',
|
||
deptHeadcount: 15,
|
||
deptStatus: 'active',
|
||
deptMission: '• 吸引並留住優秀人才\\n• 建立高效能組織文化',
|
||
deptVision: '• 成為最佳雇主品牌的推手',
|
||
deptCoreFunctions: '• 人才招募與甄選\\n• 員工培訓與發展\\n• 薪酬福利管理\\n• 員工關係維護',
|
||
deptKPIs: '• 人才留任率 > 85%\\n• 招募周期 < 45天\\n• 培訓滿意度 > 4.0/5',
|
||
deptCollaboration: '• 與各部門協作人力規劃\\n• 與財務部協作薪酬預算',
|
||
deptFunctionRemark: ''
|
||
}
|
||
];
|
||
|
||
function generateDeptFunction() {
|
||
const btn = event.target.closest('.ai-generate-btn');
|
||
const allFields = ['deptFunctionCode', 'deptFunctionName', 'deptFunctionBU', 'deptFunctionDept', 'deptManager', 'deptMission', 'deptVision', 'deptCoreFunctions', 'deptKPIs'];
|
||
const emptyFields = getEmptyFields(allFields);
|
||
|
||
if (emptyFields.length === 0) {
|
||
showToast('所有欄位都已填寫完成!');
|
||
return;
|
||
}
|
||
|
||
setButtonLoading(btn, true);
|
||
|
||
const existingData = {};
|
||
allFields.forEach(field => {
|
||
const value = getFieldValue(field);
|
||
if (value) existingData[field] = value;
|
||
});
|
||
|
||
const contextInfo = Object.keys(existingData).length > 0
|
||
? `\\n\\n已填寫的資料(請參考這些內容來生成相關的資料):\\n${JSON.stringify(existingData, null, 2)}`
|
||
: '';
|
||
|
||
const prompt = `請為HR部門職責管理系統生成部門職責資料。請用繁體中文回覆。
|
||
${contextInfo}
|
||
|
||
請「只生成」以下這些尚未填寫的欄位:${emptyFields.join(', ')}
|
||
|
||
欄位說明:
|
||
- deptFunctionCode: 部門職責編號(格式如 DF-001, DF-002)
|
||
- deptFunctionName: 部門職責名稱(例如:軟體研發部職責)
|
||
- deptFunctionBU: 事業體代碼(SBU/MBU/HQBU/ITBU/HRBU/ACCBU 之一)
|
||
- deptFunctionDept: 部門名稱
|
||
- deptManager: 部門主管職稱
|
||
- deptMission: 部門使命(使用「•」開頭的條列式,2-3項)
|
||
- deptVision: 部門願景(使用「•」開頭的條列式,1-2項)
|
||
- deptCoreFunctions: 核心職責(使用「•」開頭的條列式,4-6項)
|
||
- deptKPIs: 關鍵績效指標(使用「•」開頭的條列式,3-4項)
|
||
|
||
請直接返回JSON格式,只包含需要生成的欄位,不要有任何其他文字:
|
||
{
|
||
${emptyFields.map(f => `"${f}": "..."`).join(',\\n ')}
|
||
}`;
|
||
|
||
callClaudeAPI(prompt).then(data => {
|
||
let filledCount = 0;
|
||
if (fillIfEmpty('deptFunctionCode', data.deptFunctionCode)) filledCount++;
|
||
if (fillIfEmpty('deptFunctionName', data.deptFunctionName)) filledCount++;
|
||
if (fillIfEmpty('deptFunctionBU', data.deptFunctionBU)) filledCount++;
|
||
if (fillIfEmpty('deptFunctionDept', data.deptFunctionDept)) filledCount++;
|
||
if (fillIfEmpty('deptManager', data.deptManager)) filledCount++;
|
||
if (fillIfEmpty('deptMission', data.deptMission)) filledCount++;
|
||
if (fillIfEmpty('deptVision', data.deptVision)) filledCount++;
|
||
if (fillIfEmpty('deptCoreFunctions', data.deptCoreFunctions)) filledCount++;
|
||
if (fillIfEmpty('deptKPIs', data.deptKPIs)) filledCount++;
|
||
|
||
showToast(`已自動填入 ${filledCount} 個欄位!`);
|
||
}).catch(error => {
|
||
showToast('AI 生成失敗: ' + error.message);
|
||
}).finally(() => {
|
||
setButtonLoading(btn, false);
|
||
});
|
||
}
|
||
|
||
function clearDeptFunctionForm() {
|
||
document.getElementById('deptFunctionForm').reset();
|
||
showToast('表單已清除');
|
||
}
|
||
|
||
function cancelDeptFunction() {
|
||
if (confirm('確定要取消編輯嗎?未儲存的資料將會遺失。')) {
|
||
clearDeptFunctionForm();
|
||
}
|
||
}
|
||
|
||
function saveDeptFunctionAndNew() {
|
||
if (!validateDeptFunctionForm()) return;
|
||
|
||
const formData = getDeptFunctionFormData();
|
||
deptFunctionData.push(formData);
|
||
|
||
showToast('部門職責資料已儲存!');
|
||
clearDeptFunctionForm();
|
||
|
||
// 設定新的編號
|
||
const nextCode = 'DF-' + String(deptFunctionData.length + 1).padStart(3, '0');
|
||
document.getElementById('deptFunctionCode').value = nextCode;
|
||
}
|
||
|
||
function saveDeptFunctionAndExit() {
|
||
if (!validateDeptFunctionForm()) return;
|
||
|
||
const formData = getDeptFunctionFormData();
|
||
deptFunctionData.push(formData);
|
||
|
||
showToast('部門職責資料已儲存!');
|
||
clearDeptFunctionForm();
|
||
}
|
||
|
||
function validateDeptFunctionForm() {
|
||
const required = ['deptFunctionCode', 'deptFunctionName', 'deptFunctionBU', 'deptFunctionDept', 'deptFunctionEffectiveDate', 'deptCoreFunctions'];
|
||
for (const field of required) {
|
||
const el = document.getElementById(field);
|
||
if (!el || !el.value.trim()) {
|
||
showToast('請填寫必填欄位: ' + field);
|
||
el && el.focus();
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function getDeptFunctionFormData() {
|
||
return {
|
||
deptFunctionCode: document.getElementById('deptFunctionCode').value,
|
||
deptFunctionName: document.getElementById('deptFunctionName').value,
|
||
deptFunctionBU: document.getElementById('deptFunctionBU').value,
|
||
deptFunctionDept: document.getElementById('deptFunctionDept').value,
|
||
deptManager: document.getElementById('deptManager').value,
|
||
deptFunctionEffectiveDate: document.getElementById('deptFunctionEffectiveDate').value,
|
||
deptHeadcount: document.getElementById('deptHeadcount').value,
|
||
deptStatus: document.getElementById('deptStatus').value,
|
||
deptMission: document.getElementById('deptMission').value,
|
||
deptVision: document.getElementById('deptVision').value,
|
||
deptCoreFunctions: document.getElementById('deptCoreFunctions').value,
|
||
deptKPIs: document.getElementById('deptKPIs').value,
|
||
deptCollaboration: document.getElementById('deptCollaboration').value,
|
||
deptFunctionRemark: document.getElementById('deptFunctionRemark').value
|
||
};
|
||
}
|
||
|
||
function importDeptFunctionCSV() {
|
||
document.getElementById('deptFunctionCsvInput').click();
|
||
}
|
||
|
||
function handleDeptFunctionCSVImport(event) {
|
||
const file = event.target.files[0];
|
||
if (!file) return;
|
||
|
||
CSVUtils.importFromCSV(file, (data) => {
|
||
if (data && data.length > 0) {
|
||
const row = data[0];
|
||
Object.keys(row).forEach(key => {
|
||
const el = document.getElementById(key);
|
||
if (el) el.value = row[key];
|
||
});
|
||
showToast('已匯入 CSV 資料!');
|
||
}
|
||
});
|
||
event.target.value = '';
|
||
}
|
||
|
||
function exportDeptFunctionCSV() {
|
||
const formData = getDeptFunctionFormData();
|
||
const headers = Object.keys(formData);
|
||
CSVUtils.exportToCSV([formData], 'dept_function.csv', headers);
|
||
showToast('部門職責資料已匯出!');
|
||
}
|
||
|
||
// 獲取部門職責清單(供崗位職責選擇使用)
|
||
function getDeptFunctionList() {
|
||
return deptFunctionData.map(d => ({
|
||
code: d.deptFunctionCode,
|
||
name: d.deptFunctionName,
|
||
dept: d.deptFunctionDept,
|
||
bu: d.deptFunctionBU
|
||
}));
|
||
}
|
||
|
||
'''
|
||
|
||
# 在 usersData 定義之前插入
|
||
users_data_pattern = ' // ==================== 管理者頁面功能 ===================='
|
||
|
||
if users_data_pattern in content and 'deptFunctionData' not in content:
|
||
content = content.replace(users_data_pattern, dept_function_js + users_data_pattern)
|
||
print("[OK] Added Department Function JavaScript functions")
|
||
else:
|
||
print("[INFO] Department Function JS already exists or pattern not found")
|
||
|
||
# ==================== 5. 更新模組切換邏輯 ====================
|
||
# 找到現有的模組切換代碼並更新
|
||
old_module_switch = ''' document.querySelectorAll('.module-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('.module-btn').forEach(b => {
|
||
b.classList.remove('active', 'job-active', 'desc-active');
|
||
});
|
||
btn.classList.add('active');'''
|
||
|
||
new_module_switch = ''' document.querySelectorAll('.module-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('.module-btn').forEach(b => {
|
||
b.classList.remove('active', 'job-active', 'desc-active', 'dept-active');
|
||
});
|
||
btn.classList.add('active');'''
|
||
|
||
if old_module_switch in content:
|
||
content = content.replace(old_module_switch, new_module_switch)
|
||
print("[OK] Updated module switch logic")
|
||
|
||
# 寫回檔案
|
||
with open('index.html', 'w', encoding='utf-8') as f:
|
||
f.write(content)
|
||
|
||
print("\n[DONE] All modifications completed!")
|
||
print("- Fixed viewPosition button to load position data")
|
||
print("- Added Department Function tab")
|
||
print("- Added Department Function form with AI generation")
|