Files
hr-position-system/add_dept_relation.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

207 lines
11 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_dept_field = ''' <div class="form-group">
<label>所屬部門</label>
<input type="text" id="jd_department" name="department" placeholder="請輸入所屬部門">
</div>
<div class="form-group">
<label>崗位生效日期</label>'''
new_dept_field = ''' <div class="form-group">
<label>所屬部門</label>
<input type="text" id="jd_department" name="department" placeholder="請輸入所屬部門">
</div>
<div class="form-group">
<label>部門職責</label>
<div class="input-wrapper">
<select id="jd_deptFunction" name="deptFunction" onchange="loadDeptFunctionInfo()">
<option value="">-- 請選擇部門職責 --</option>
</select>
<button type="button" class="btn-icon" onclick="refreshDeptFunctionList()" title="重新載入">
<svg viewBox="0 0 24 24"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>
</button>
</div>
</div>
<div class="form-group">
<label>崗位生效日期</label>'''
if old_dept_field in content and 'jd_deptFunction' not in content:
content = content.replace(old_dept_field, new_dept_field)
print("[OK] Added Department Function dropdown to Job Description form")
else:
print("[INFO] Department Function field already exists or pattern not found")
# ==================== 2. 添加部門職責資訊顯示區塊 ====================
# 在崗位基本信息 section 後面添加部門職責資訊區塊
old_section_end = ''' <div class="form-group">
<label>直接下級(職位及人數)</label>
<input type="text" id="jd_directReports" name="directReports" placeholder="如:工程師 x 5人">
</div>'''
# 找到直接下級後面的結構
new_section_end = ''' <div class="form-group">
<label>直接下級(職位及人數)</label>
<input type="text" id="jd_directReports" name="directReports" placeholder="如:工程師 x 5人">
</div>
</div>
</div>
</div>
<!-- 部門職責資訊 Section (關聯顯示) -->
<div class="section-box" id="deptFunctionInfoSection" style="margin-top: 24px; display: none;">
<div class="section-header" style="background: linear-gradient(135deg, #8e44ad 0%, #9b59b6 100%);">部門職責資訊 (自動帶入)</div>
<div class="section-body">
<div class="form-grid">
<div class="form-group">
<label>部門職責編號</label>
<input type="text" id="jd_deptFunctionCode" readonly style="background: #f8f9fa;">
</div>
<div class="form-group">
<label>事業體</label>
<input type="text" id="jd_deptFunctionBU" readonly style="background: #f8f9fa;">
</div>
</div>
<div class="form-group full-width">
<label>部門使命</label>
<textarea id="jd_deptMission" readonly rows="2" style="background: #f8f9fa;"></textarea>
</div>
<div class="form-group full-width">
<label>部門核心職責</label>
<textarea id="jd_deptCoreFunctions" readonly rows="4" style="background: #f8f9fa;"></textarea>
</div>
<div class="form-group full-width">
<label>部門 KPIs</label>
<textarea id="jd_deptKPIs" readonly rows="3" style="background: #f8f9fa;"></textarea>
</div>
</div>
</div>
<!-- 崗位職責 Section '''
# 找到崗位職責 Section 的開始位置
jobdesc_section_pattern = ''' </div>
</div>
</div>
<!-- 崗位職責 Section -->'''
if jobdesc_section_pattern in content and 'deptFunctionInfoSection' not in content:
content = content.replace(old_section_end + '''
</div>
</div>
</div>
<!-- 崗位職責 Section -->''', new_section_end + '''-->''')
print("[OK] Added Department Function info section to Job Description")
else:
print("[INFO] Dept Function info section already exists or pattern not found - trying alternative approach")
# ==================== 3. 添加相關 JavaScript 函數 ====================
dept_relation_js = '''
// ==================== 部門職責關聯功能 ====================
// 重新載入部門職責下拉選單
function refreshDeptFunctionList() {
const select = document.getElementById('jd_deptFunction');
if (!select) return;
// 清空現有選項
select.innerHTML = '<option value="">-- 請選擇部門職責 --</option>';
// 從 deptFunctionData 載入選項
if (typeof deptFunctionData !== 'undefined' && deptFunctionData.length > 0) {
deptFunctionData.forEach(df => {
const option = document.createElement('option');
option.value = df.deptFunctionCode;
option.textContent = `${df.deptFunctionCode} - ${df.deptFunctionName} (${df.deptFunctionDept})`;
select.appendChild(option);
});
showToast('已載入 ' + deptFunctionData.length + ' 筆部門職責資料');
} else {
showToast('尚無部門職責資料,請先建立部門職責');
}
}
// 載入選中的部門職責資訊
function loadDeptFunctionInfo() {
const select = document.getElementById('jd_deptFunction');
const infoSection = document.getElementById('deptFunctionInfoSection');
if (!select || !infoSection) return;
const selectedCode = select.value;
if (!selectedCode) {
infoSection.style.display = 'none';
return;
}
// 從 deptFunctionData 找到對應的資料
if (typeof deptFunctionData !== 'undefined') {
const deptFunc = deptFunctionData.find(d => d.deptFunctionCode === selectedCode);
if (deptFunc) {
// 填入部門職責資訊
document.getElementById('jd_deptFunctionCode').value = deptFunc.deptFunctionCode || '';
document.getElementById('jd_deptFunctionBU').value = deptFunc.deptFunctionBU || '';
document.getElementById('jd_deptMission').value = deptFunc.deptMission || '';
document.getElementById('jd_deptCoreFunctions').value = deptFunc.deptCoreFunctions || '';
document.getElementById('jd_deptKPIs').value = deptFunc.deptKPIs || '';
// 自動填入所屬部門
const deptInput = document.getElementById('jd_department');
if (deptInput && !deptInput.value) {
deptInput.value = deptFunc.deptFunctionDept;
}
// 顯示部門職責資訊區塊
infoSection.style.display = 'block';
showToast('已載入部門職責: ' + deptFunc.deptFunctionName);
}
}
}
// 在頁面載入時初始化部門職責下拉選單
document.addEventListener('DOMContentLoaded', function() {
// 延遲載入,確保 deptFunctionData 已初始化
setTimeout(refreshDeptFunctionList, 500);
});
'''
# 在部門職責模組功能之後插入
dept_module_js_end = ' // ==================== 管理者頁面功能 ===================='
if dept_module_js_end in content and 'refreshDeptFunctionList' not in content:
content = content.replace(dept_module_js_end, dept_relation_js + dept_module_js_end)
print("[OK] Added Department Function relation JavaScript functions")
else:
print("[INFO] Dept Function relation JS already exists or pattern not found")
# 寫回檔案
with open('index.html', 'w', encoding='utf-8') as f:
f.write(content)
print("\n[DONE] Department Function relation added!")
print("- Added Department Function dropdown to Job Description form")
print("- Added Department Function info display section")
print("- Added JavaScript functions for loading dept function data")