feat: 實作三個錦囊 AI 功能
- 新增 AI 錦囊 CSS 樣式到 components.css - 創建 js/ai-bags.js 模組,包含: * 5個模組各3個錦囊的預設 prompt 模板 * executeAIBag() - 執行 AI 生成並填充表單 * editBagPrompt() - 編輯自定義 prompt * LocalStorage 管理自定義 prompt - 更新 index.html: * 替換 5 處 AI 按鈕為三個錦囊(崗位基礎、招聘要求、職務、部門職責、崗位描述) * 新增 Prompt 編輯模態框 - 更新 main.js 引入 ai-bags.js 並初始化 - 新增設計文檔:三個錦囊設計.md - 新增欄位對照文檔:表單欄位清單.md、更新欄位名稱.md、ID重命名對照表.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
286
ID重命名對照表.md
Normal file
286
ID重命名對照表.md
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
# HTML ID 重命名對照表
|
||||||
|
|
||||||
|
## 變更概覽
|
||||||
|
- **總計需變更:72 個**
|
||||||
|
- **無需變更:13 個**
|
||||||
|
- **總欄位數:85 個**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模組 1: 崗位基礎資料 - 基礎資料頁籤
|
||||||
|
**需變更:15 / 15**
|
||||||
|
|
||||||
|
| 舊 ID | 新 ID | 欄位名稱 | 備註 |
|
||||||
|
|-------|-------|---------|------|
|
||||||
|
| `businessUnit` | `pos_businessUnit` | 事業體 (Business Unit) | |
|
||||||
|
| `division` | `pos_division` | 處級單位 (Division) | |
|
||||||
|
| `department` | `pos_department` | 部級單位 (Department) | |
|
||||||
|
| `section` | `pos_section` | 課級單位 (Section) | |
|
||||||
|
| `positionCode` | `pos_code` | 崗位編號 | 必填欄位 |
|
||||||
|
| `effectiveDate` | `pos_effectiveDate` | 生效日期 | |
|
||||||
|
| `positionName` | `pos_name` | 崗位名稱 | 必填欄位 |
|
||||||
|
| `positionLevel` | `pos_level` | 崗位級別 | |
|
||||||
|
| `positionCategory` | `pos_category` | 崗位類別 | onchange 事件 |
|
||||||
|
| `positionCategoryName` | `pos_categoryName` | 崗位類別名稱 | readonly |
|
||||||
|
| `positionNature` | `pos_type` | 崗位性質 | onchange 事件,注意:資料庫改為 positionType |
|
||||||
|
| `positionNatureName` | `pos_typeName` | 崗位性質名稱 | readonly,資料庫改為 positionTypeName |
|
||||||
|
| `headcount` | `pos_headcount` | 編制人數 | |
|
||||||
|
| `positionDesc` | `pos_desc` | 崗位描述 | 資料庫改為 description |
|
||||||
|
| `positionRemark` | `pos_remark` | 崗位備注 | 資料庫改為 remark |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模組 2: 崗位基礎資料 - 招聘要求頁籤
|
||||||
|
**需變更:18 / 18**
|
||||||
|
|
||||||
|
| 舊 ID | 新 ID | 欄位名稱 | 備註 |
|
||||||
|
|-------|-------|---------|------|
|
||||||
|
| `minEducation` | `rec_eduLevel` | 最低學歷 | 資料庫改為 educationLevel |
|
||||||
|
| `requiredGender` | `rec_gender` | 要求性別 | |
|
||||||
|
| `salaryRange` | `rec_salaryRange` | 薪酬范圍 | |
|
||||||
|
| `workExperience` | `rec_expYears` | 工作經驗 | 資料庫改為 experienceYears |
|
||||||
|
| `minAge` | `rec_minAge` | 最小年齡 | |
|
||||||
|
| `maxAge` | `rec_maxAge` | 最大年齡 | |
|
||||||
|
| `jobType` | `rec_jobType` | 工作性質 | |
|
||||||
|
| `recruitPosition` | `rec_position` | 招聘職位 | 資料庫改為 recruitPosition |
|
||||||
|
| `jobTitle` | `rec_jobTitle` | 職位名稱(對外) | |
|
||||||
|
| `superiorPosition` | `rec_superiorCode` | 上級崗位編號 | 資料庫改為 superiorPositionCode |
|
||||||
|
| `jobDesc` | `rec_jobDesc` | 職位描述(JD) | 資料庫改為 recruitJobDesc |
|
||||||
|
| `positionReq` | `rec_positionReq` | 崗位要求(Req) | 資料庫改為 recruitRequirements |
|
||||||
|
| `titleReq` | `rec_certReq` | 職稱要求 | 語義更正為「證照要求」,資料庫改為 certRequirements |
|
||||||
|
| `majorReq` | `rec_majorReq` | 專業要求 | 資料庫改為 majorRequirements |
|
||||||
|
| `skillReq` | `rec_skillReq` | 技能要求 | 資料庫改為 skillRequirements |
|
||||||
|
| `langReq` | `rec_langReq` | 語言要求 | 資料庫改為 langRequirements |
|
||||||
|
| `otherReq` | `rec_otherReq` | 其他要求 | 資料庫改為 otherRequirements |
|
||||||
|
| `recruitRemark` | `rec_remark` | 招聘備注 | 資料庫改為 recruitRemark |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模組 3: 職務基礎資料
|
||||||
|
**需變更:12 / 12**
|
||||||
|
|
||||||
|
| 舊 ID | 新 ID | 欄位名稱 | 備註 |
|
||||||
|
|-------|-------|---------|------|
|
||||||
|
| `jobCategoryCode` | `job_category` | 職務類別編號 | 必填欄位,onchange 事件 |
|
||||||
|
| `jobCategoryName` | `job_categoryName` | 職務類別名稱 | readonly |
|
||||||
|
| `jobCode` | `job_code` | 職務編號 | 必填欄位 |
|
||||||
|
| `jobName` | `job_name` | 職務名稱 | 必填欄位 |
|
||||||
|
| `jobNameEn` | `job_nameEn` | 職務英文 | |
|
||||||
|
| `jobEffectiveDate` | `job_effectiveDate` | 生效日期 | 資料庫改為 effectiveDate |
|
||||||
|
| `jobLevel` | `job_level` | 職務層級 | 敏感欄位 |
|
||||||
|
| `jobHeadcount` | `job_headcount` | 編制人數 | 資料庫改為 headcount |
|
||||||
|
| `jobSortOrder` | `job_sortOrder` | 排列順序 | 資料庫改為 sortOrder |
|
||||||
|
| `hasAttendanceBonus` | `job_hasAttBonus` | 全勤獎金 | Toggle Switch |
|
||||||
|
| `hasHousingAllowance` | `job_hasHouseAllow` | 住房補貼 | Toggle Switch |
|
||||||
|
| `jobRemark` | `job_remark` | 職務備注 | 資料庫改為 remark |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模組 4: 部門職責
|
||||||
|
**需變更:19 / 19**
|
||||||
|
|
||||||
|
| 舊 ID | 新 ID | 欄位名稱 | 備註 |
|
||||||
|
|-------|-------|---------|------|
|
||||||
|
| `deptFunctionCode` | `df_code` | 部門職責編號 | 必填欄位,資料庫改為 dfCode |
|
||||||
|
| `deptFunctionName` | `df_name` | 部門職責名稱 | 必填欄位,資料庫改為 dfName |
|
||||||
|
| `deptFunctionBU` | `df_businessUnit` | 事業體 (第1個) | 必填欄位,已合併重複欄位 |
|
||||||
|
| `deptFunc_businessUnit` | `df_businessUnit` | 事業體 (第2個) | **合併為同一欄位** |
|
||||||
|
| `deptFunc_division` | `df_division` | 處級單位 | 必填欄位 |
|
||||||
|
| `deptFunc_department` | `df_department` | 部級單位 | 必填欄位 |
|
||||||
|
| `deptFunc_section` | `df_section` | 課級單位 | |
|
||||||
|
| `deptFunc_positionTitle` | `df_posTitle` | 崗位名稱 | 必填欄位,資料庫改為 positionTitle |
|
||||||
|
| `deptFunc_positionLevel` | `df_posLevel` | 崗位級別 | 資料庫保持 positionLevel |
|
||||||
|
| `deptManager` | `df_managerTitle` | 部門主管職稱 | 資料庫改為 managerTitle |
|
||||||
|
| `deptFunctionEffectiveDate` | `df_effectiveDate` | 生效日期 | 必填欄位,資料庫改為 effectiveDate |
|
||||||
|
| `deptHeadcount` | `df_headcountLimit` | 部門人數上限 | 資料庫改為 headcountLimit |
|
||||||
|
| `deptStatus` | `df_status` | 部門狀態 | 資料庫改為 status |
|
||||||
|
| `deptMission` | `df_mission` | 部門使命 | 資料庫改為 mission |
|
||||||
|
| `deptVision` | `df_vision` | 部門願景 | 資料庫改為 vision |
|
||||||
|
| `deptCoreFunctions` | `df_coreFunc` | 核心職責 | 必填欄位,資料庫改為 coreFunctions |
|
||||||
|
| `deptKPIs` | `df_kpis` | 關鍵績效指標 | 資料庫改為 kpis |
|
||||||
|
| `deptCollaboration` | `df_collab` | 協作部門 | 資料庫改為 collaboration |
|
||||||
|
| `deptFunctionRemark` | `df_remark` | 備注 | 資料庫改為 remark |
|
||||||
|
|
||||||
|
**特別注意:** 原本有兩個事業體欄位 (`deptFunctionBU` 和 `deptFunc_businessUnit`),新規範已合併為單一欄位 `df_businessUnit`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模組 5: 崗位描述 - 基本信息
|
||||||
|
**需變更:3 / 4**
|
||||||
|
|
||||||
|
| 舊 ID | 新 ID | 欄位名稱 | 備註 |
|
||||||
|
|-------|-------|---------|------|
|
||||||
|
| `jd_empNo` | `jd_empNo` | 工號 | ✓ 無需變更 |
|
||||||
|
| `jd_empName` | `jd_empName` | 姓名 | ✓ 無需變更 |
|
||||||
|
| `jd_positionCode` | `jd_posCode` | 崗位代碼 | |
|
||||||
|
| `jd_versionDate` | `jd_versionDate` | 版本更新日期 | ✓ 無需變更 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模組 6: 崗位描述 - 崗位基本信息
|
||||||
|
**需變更:10 / 14**
|
||||||
|
|
||||||
|
| 舊 ID | 新 ID | 欄位名稱 | 備註 |
|
||||||
|
|-------|-------|---------|------|
|
||||||
|
| `jd_positionName` | `jd_posName` | 崗位名稱 | |
|
||||||
|
| `jd_businessUnit` | `jd_businessUnit` | 事業體 | ✓ 無需變更 |
|
||||||
|
| `jd_division` | `jd_division` | 處級單位 | ✓ 無需變更 |
|
||||||
|
| `jd_department` | `jd_department` | 部級單位 | ✓ 無需變更 |
|
||||||
|
| `jd_section` | `jd_section` | 課級單位 | ✓ 無需變更 |
|
||||||
|
| `jd_positionTitle` | `(刪除)` | 崗位名稱 (重複) | 與 positionName 重複,建議刪除 |
|
||||||
|
| `jd_positionLevel` | `jd_posLevel` | 崗位級別 | |
|
||||||
|
| `jd_positionEffectiveDate` | `jd_posEffDate` | 崗位生效日期 | |
|
||||||
|
| `jd_directSupervisor` | `jd_supervisor` | 直接領導職務 | |
|
||||||
|
| `jd_positionGradeJob` | `jd_gradeJob` | 崗位職等&職務 | Modal 選擇器 |
|
||||||
|
| `jd_reportTo` | `jd_reportTo` | 匯報對象職務 | ✓ 無需變更 |
|
||||||
|
| `jd_directReports` | `jd_directReports` | 直接下級 | ✓ 無需變更 |
|
||||||
|
| `jd_workLocation` | `jd_location` | 任職地點 | |
|
||||||
|
| `jd_empAttribute` | `jd_empAttr` | 員工屬性 | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模組 7: 崗位描述 - 部門職責資訊
|
||||||
|
**需變更:3 / 5**
|
||||||
|
|
||||||
|
| 舊 ID | 新 ID | 欄位名稱 | 備註 |
|
||||||
|
|-------|-------|---------|------|
|
||||||
|
| `jd_deptFunctionCode` | `jd_dfCode` | 部門職責編號 | readonly |
|
||||||
|
| `jd_deptFunctionBU` | `(保留)` | 事業體 | 建議保留或改為 jd_dfBU |
|
||||||
|
| `jd_deptMission` | `jd_deptMission` | 部門使命 | ✓ 無需變更 |
|
||||||
|
| `jd_deptCoreFunctions` | `jd_deptCoreFunctions` | 部門核心職責 | ✓ 無需變更 |
|
||||||
|
| `jd_deptKPIs` | `jd_deptKPIs` | 部門 KPIs | ✓ 無需變更 |
|
||||||
|
|
||||||
|
**說明:** 這些是 readonly 欄位,自動帶入,可保持現有命名以維持與來源資料的一致性。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模組 8: 崗位描述 - 職責描述
|
||||||
|
**需變更:1 / 2**
|
||||||
|
|
||||||
|
| 舊 ID | 新 ID | 欄位名稱 | 備註 |
|
||||||
|
|-------|-------|---------|------|
|
||||||
|
| `jd_positionPurpose` | `jd_purpose` | 崗位設置目的 | |
|
||||||
|
| `jd_mainResponsibilities` | `jd_mainResp` | 主要崗位職責 | Numbered textarea |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模組 9: 崗位描述 - 崗位要求
|
||||||
|
**需變更:5 / 5**
|
||||||
|
|
||||||
|
| 舊 ID | 新 ID | 欄位名稱 | 備註 |
|
||||||
|
|-------|-------|---------|------|
|
||||||
|
| `jd_education` | `jd_eduLevel` | 教育程度 | |
|
||||||
|
| `jd_basicSkills` | `jd_basicSkills` | 基本技能 | ✓ 無需變更 |
|
||||||
|
| `jd_professionalKnowledge` | `jd_proKnowledge` | 專業知識 | |
|
||||||
|
| `jd_workExperienceReq` | `jd_expReq` | 工作經驗 | |
|
||||||
|
| `jd_otherRequirements` | `jd_otherReq` | 其他 | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 重要變更說明
|
||||||
|
|
||||||
|
### 1. 前綴標準化
|
||||||
|
所有欄位統一採用模組前綴:
|
||||||
|
- `pos_` - 崗位基礎資料
|
||||||
|
- `rec_` - 招聘要求
|
||||||
|
- `job_` - 職務基礎資料
|
||||||
|
- `df_` - 部門職責
|
||||||
|
- `jd_` - 崗位描述
|
||||||
|
|
||||||
|
### 2. 命名簡化
|
||||||
|
- `positionCode` → `pos_code`
|
||||||
|
- `positionName` → `pos_name`
|
||||||
|
- `positionCategory` → `pos_category`
|
||||||
|
- `positionNature` → `pos_type` (語義更精確)
|
||||||
|
- `hasAttendanceBonus` → `job_hasAttBonus` (縮寫簡化)
|
||||||
|
|
||||||
|
### 3. 語義改善
|
||||||
|
- `titleReq` → `rec_certReq` (職稱要求 → 證照要求)
|
||||||
|
- `positionNature` → `pos_type` (性質 → 類型,更符合英文語義)
|
||||||
|
- `workExperience` → `rec_expYears` (經驗年數更明確)
|
||||||
|
|
||||||
|
### 4. 資料庫欄位同步變更
|
||||||
|
部分 HTML ID 變更時,資料庫欄位名稱也需要對應修改:
|
||||||
|
- `positionNature` → `positionType`
|
||||||
|
- `positionDesc` → `description`
|
||||||
|
- `positionRemark` → `remark`
|
||||||
|
- `minEducation` → `educationLevel`
|
||||||
|
|
||||||
|
### 5. 重複欄位合併
|
||||||
|
部門職責模組中的兩個事業體欄位:
|
||||||
|
- 原:`deptFunctionBU` 和 `deptFunc_businessUnit`
|
||||||
|
- 新:統一為 `df_businessUnit`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 實施建議
|
||||||
|
|
||||||
|
### 階段 1: 資料庫遷移
|
||||||
|
1. 執行資料庫欄位重命名 SQL 腳本
|
||||||
|
2. 更新所有 ORM Model 定義
|
||||||
|
3. 更新 API 回應的欄位名稱
|
||||||
|
|
||||||
|
### 階段 2: 前端更新
|
||||||
|
1. 全局搜尋替換 HTML ID
|
||||||
|
2. 更新所有 JavaScript 選擇器
|
||||||
|
3. 更新 CSS 樣式選擇器
|
||||||
|
4. 更新表單驗證邏輯
|
||||||
|
|
||||||
|
### 階段 3: 測試驗證
|
||||||
|
1. 單元測試:驗證所有表單欄位綁定
|
||||||
|
2. 整合測試:驗證資料儲存與讀取
|
||||||
|
3. E2E 測試:完整流程測試
|
||||||
|
4. 回歸測試:確保無遺漏欄位
|
||||||
|
|
||||||
|
### 階段 4: 文檔更新
|
||||||
|
1. API 文檔更新
|
||||||
|
2. 資料字典更新
|
||||||
|
3. 開發指南更新
|
||||||
|
4. 使用者手冊更新(如有影響)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 風險評估
|
||||||
|
|
||||||
|
### 高風險變更 (必填欄位)
|
||||||
|
- `positionCode` → `pos_code`
|
||||||
|
- `positionName` → `pos_name`
|
||||||
|
- `jobCode` → `job_code`
|
||||||
|
- `jobName` → `job_name`
|
||||||
|
- `deptFunctionCode` → `df_code`
|
||||||
|
|
||||||
|
**建議:** 優先測試這些欄位的儲存與驗證邏輯。
|
||||||
|
|
||||||
|
### 中風險變更 (聯動欄位)
|
||||||
|
- 組織結構欄位:`businessUnit`, `division`, `department`, `section`
|
||||||
|
- 自動帶出欄位:`positionCategoryName`, `positionNatureName`
|
||||||
|
|
||||||
|
**建議:** 仔細測試聯動邏輯和 onchange 事件。
|
||||||
|
|
||||||
|
### 低風險變更 (選填欄位)
|
||||||
|
- 備注類欄位
|
||||||
|
- 描述類欄位
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 檢查清單
|
||||||
|
|
||||||
|
- [ ] 資料庫遷移腳本已準備
|
||||||
|
- [ ] Model 定義已更新
|
||||||
|
- [ ] HTML 表單 ID 已更新
|
||||||
|
- [ ] JavaScript 選擇器已更新
|
||||||
|
- [ ] CSS 樣式已更新
|
||||||
|
- [ ] API 端點已更新
|
||||||
|
- [ ] 驗證邏輯已更新
|
||||||
|
- [ ] 單元測試已通過
|
||||||
|
- [ ] 整合測試已通過
|
||||||
|
- [ ] E2E 測試已通過
|
||||||
|
- [ ] 文檔已更新
|
||||||
|
- [ ] 程式碼審查已完成
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**文檔版本:** v1.0
|
||||||
|
**建立日期:** 2025-12-06
|
||||||
|
**最後更新:** 2025-12-06
|
||||||
|
**維護者:** 系統開發團隊
|
||||||
160
index.html
160
index.html
@@ -98,10 +98,27 @@
|
|||||||
|
|
||||||
<form id="positionForm">
|
<form id="positionForm">
|
||||||
<div class="tab-content active" id="tab-position-basic">
|
<div class="tab-content active" id="tab-position-basic">
|
||||||
<button type="button" class="ai-generate-btn" onclick="generatePositionBasic()">
|
<!-- AI 錦囊:三個可自定義的 AI 生成按鈕 -->
|
||||||
<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>
|
<div class="ai-bags-container">
|
||||||
<span>✨ I'm feeling lucky</span>
|
<div class="ai-bag" data-module="positionBasic" data-bag="1" onclick="executeAIBag('positionBasic', 1)">
|
||||||
</button>
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊一</div>
|
||||||
|
<div class="bag-subtitle">簡化版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'positionBasic', 1)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="positionBasic" data-bag="2" onclick="executeAIBag('positionBasic', 2)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊二</div>
|
||||||
|
<div class="bag-subtitle">標準版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'positionBasic', 2)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="positionBasic" data-bag="3" onclick="executeAIBag('positionBasic', 3)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊三</div>
|
||||||
|
<div class="bag-subtitle">詳細版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'positionBasic', 3)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<!-- 事業體 -->
|
<!-- 事業體 -->
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -212,10 +229,27 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-content" id="tab-position-recruit">
|
<div class="tab-content" id="tab-position-recruit">
|
||||||
<button type="button" class="ai-generate-btn" onclick="generatePositionRecruit()">
|
<!-- AI 錦囊:三個可自定義的 AI 生成按鈕 -->
|
||||||
<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>
|
<div class="ai-bags-container">
|
||||||
<span>✨ I'm feeling lucky</span>
|
<div class="ai-bag" data-module="positionRecruit" data-bag="1" onclick="executeAIBag('positionRecruit', 1)">
|
||||||
</button>
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊一</div>
|
||||||
|
<div class="bag-subtitle">基本需求</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'positionRecruit', 1)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="positionRecruit" data-bag="2" onclick="executeAIBag('positionRecruit', 2)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊二</div>
|
||||||
|
<div class="bag-subtitle">標準需求</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'positionRecruit', 2)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="positionRecruit" data-bag="3" onclick="executeAIBag('positionRecruit', 3)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊三</div>
|
||||||
|
<div class="bag-subtitle">完整需求</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'positionRecruit', 3)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>最低學歷</label>
|
<label>最低學歷</label>
|
||||||
@@ -402,10 +436,27 @@
|
|||||||
|
|
||||||
<form id="jobForm">
|
<form id="jobForm">
|
||||||
<div class="tab-content active" id="tab-job-basic">
|
<div class="tab-content active" id="tab-job-basic">
|
||||||
<button type="button" class="ai-generate-btn" onclick="generateJobBasic()">
|
<!-- AI 錦囊:三個可自定義的 AI 生成按鈕 -->
|
||||||
<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>
|
<div class="ai-bags-container">
|
||||||
<span>✨ I'm feeling lucky</span>
|
<div class="ai-bag" data-module="jobBasic" data-bag="1" onclick="executeAIBag('jobBasic', 1)">
|
||||||
</button>
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊一</div>
|
||||||
|
<div class="bag-subtitle">簡化版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'jobBasic', 1)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="jobBasic" data-bag="2" onclick="executeAIBag('jobBasic', 2)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊二</div>
|
||||||
|
<div class="bag-subtitle">標準版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'jobBasic', 2)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="jobBasic" data-bag="3" onclick="executeAIBag('jobBasic', 3)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊三</div>
|
||||||
|
<div class="bag-subtitle">完整版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'jobBasic', 3)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label><span class="required">*</span> 職務類別編號</label>
|
<label><span class="required">*</span> 職務類別編號</label>
|
||||||
@@ -546,10 +597,27 @@
|
|||||||
<div class="form-card">
|
<div class="form-card">
|
||||||
<form id="deptFunctionForm">
|
<form id="deptFunctionForm">
|
||||||
<div class="tab-content active">
|
<div class="tab-content active">
|
||||||
<button type="button" class="ai-generate-btn" onclick="generateDeptFunction()">
|
<!-- AI 錦囊:三個可自定義的 AI 生成按鈕 -->
|
||||||
<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>
|
<div class="ai-bags-container">
|
||||||
<span>✨ I'm feeling lucky</span>
|
<div class="ai-bag" data-module="deptFunction" data-bag="1" onclick="executeAIBag('deptFunction', 1)">
|
||||||
</button>
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊一</div>
|
||||||
|
<div class="bag-subtitle">基本版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'deptFunction', 1)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="deptFunction" data-bag="2" onclick="executeAIBag('deptFunction', 2)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊二</div>
|
||||||
|
<div class="bag-subtitle">標準版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'deptFunction', 2)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="deptFunction" data-bag="3" onclick="executeAIBag('deptFunction', 3)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊三</div>
|
||||||
|
<div class="bag-subtitle">完整版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'deptFunction', 3)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="csv-buttons" style="margin-bottom: 15px;">
|
<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="importDeptFunctionCSV()">匯入 CSV</button>
|
||||||
@@ -732,10 +800,27 @@
|
|||||||
|
|
||||||
<form id="jobDescForm">
|
<form id="jobDescForm">
|
||||||
<div class="tab-content active" id="tab-jobdesc-basic">
|
<div class="tab-content active" id="tab-jobdesc-basic">
|
||||||
<button type="button" class="ai-generate-btn" onclick="generateJobDesc()">
|
<!-- AI 錦囊:三個可自定義的 AI 生成按鈕 -->
|
||||||
<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>
|
<div class="ai-bags-container">
|
||||||
<span>✨ I'm feeling lucky</span>
|
<div class="ai-bag" data-module="jobDesc" data-bag="1" onclick="executeAIBag('jobDesc', 1)">
|
||||||
</button>
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊一</div>
|
||||||
|
<div class="bag-subtitle">基本版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'jobDesc', 1)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="jobDesc" data-bag="2" onclick="executeAIBag('jobDesc', 2)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊二</div>
|
||||||
|
<div class="bag-subtitle">標準版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'jobDesc', 2)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-module="jobDesc" data-bag="3" onclick="executeAIBag('jobDesc', 3)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title">錦囊三</div>
|
||||||
|
<div class="bag-subtitle">完整版</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'jobDesc', 3)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- 頂部區域 -->
|
<!-- 頂部區域 -->
|
||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -4024,5 +4109,40 @@ ${contextInfo}
|
|||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- ==================== Prompt 編輯模態框 ==================== -->
|
||||||
|
<div class="modal-overlay" id="promptEditModal">
|
||||||
|
<div class="modal" style="max-width: 700px;">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 id="promptModalTitle">編輯 Prompt</h3>
|
||||||
|
<button class="modal-close" onclick="closePromptEditModal()">✕</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>錦囊標題</label>
|
||||||
|
<input type="text" id="promptTitle" placeholder="例如:簡化版、標準版、詳細版">
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="margin-top: 16px;">
|
||||||
|
<label>副標題(選填)</label>
|
||||||
|
<input type="text" id="promptSubtitle" placeholder="例如:僅必填欄位、常用欄位">
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="margin-top: 16px;">
|
||||||
|
<label>Prompt 內容</label>
|
||||||
|
<textarea id="promptContent" rows="12" placeholder="請輸入 AI Prompt 內容 可使用的變數: {existingData} - 當前表單已填寫的資料 {positionName} - 崗位名稱"></textarea>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 12px; padding: 12px; background: #f8fafc; border-radius: 6px; font-size: 0.85rem; color: #64748b;">
|
||||||
|
<strong>提示:</strong>Prompt 會自動替換以下變數:<br>
|
||||||
|
• <code>{existingData}</code> → 當前表單已填寫的資料(JSON 格式)<br>
|
||||||
|
• <code>{positionName}</code> → 崗位名稱(用於招聘要求頁籤)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-secondary" onclick="resetToDefaultPrompt()">重置為預設</button>
|
||||||
|
<button class="btn btn-cancel" onclick="closePromptEditModal()">取消</button>
|
||||||
|
<button class="btn btn-primary" onclick="savePromptEdit()">保存</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
628
js/ai-bags.js
Normal file
628
js/ai-bags.js
Normal file
@@ -0,0 +1,628 @@
|
|||||||
|
/**
|
||||||
|
* AI Bags - 三個錦囊功能
|
||||||
|
* 提供可自定義 prompt 的 AI 生成按鈕
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { callClaudeAPI } from './api.js';
|
||||||
|
import { showToast, fillIfEmpty } from './utils.js';
|
||||||
|
import { getPositionFormData, getJobFormData, getJobDescFormData, getDeptFunctionFormData } from './ui.js';
|
||||||
|
|
||||||
|
// ==================== 預設 Prompt 模板 ====================
|
||||||
|
|
||||||
|
const DEFAULT_PROMPTS = {
|
||||||
|
positionBasic: {
|
||||||
|
bag1: {
|
||||||
|
title: '簡化版',
|
||||||
|
subtitle: '僅必填欄位',
|
||||||
|
prompt: `你是專業人資顧問,熟悉半導體製造業。請生成崗位基礎資料(僅必填欄位)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:positionCode, positionName
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag2: {
|
||||||
|
title: '標準版',
|
||||||
|
subtitle: '常用欄位',
|
||||||
|
prompt: `你是專業人資顧問,熟悉半導體製造業。請生成崗位基礎資料(標準版)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:positionCode, positionName, positionCategory, positionLevel, headcount
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- positionCode: 崗位編號(格式如 ENG-001)
|
||||||
|
- positionName: 崗位名稱
|
||||||
|
- positionCategory: 崗位類別代碼(01=技術職, 02=管理職, 03=業務職, 04=行政職)
|
||||||
|
- positionLevel: 崗位級別(L1-L7)
|
||||||
|
- headcount: 編制人數(1-10)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag3: {
|
||||||
|
title: '詳細版',
|
||||||
|
subtitle: '所有欄位',
|
||||||
|
prompt: `你是專業人資顧問,熟悉半導體製造業的人資所有流程。請生成完整的崗位基礎資料。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:positionCode, positionName, positionCategory, positionNature, headcount, positionLevel, positionDesc, positionRemark
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- positionCode: 崗位編號(格式如 ENG-001, MGR-002)
|
||||||
|
- positionName: 崗位名稱
|
||||||
|
- positionCategory: 崗位類別代碼(01=技術職, 02=管理職, 03=業務職, 04=行政職)
|
||||||
|
- positionNature: 崗位性質代碼(FT=全職, PT=兼職, CT=約聘, IN=實習)
|
||||||
|
- headcount: 編制人數(1-10之間的數字字串)
|
||||||
|
- positionLevel: 崗位級別(L1到L7)
|
||||||
|
- positionDesc: 崗位描述(條列式,用換行分隔)
|
||||||
|
- positionRemark: 崗位備注(條列式,用換行分隔)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
positionRecruit: {
|
||||||
|
bag1: {
|
||||||
|
title: '基本需求',
|
||||||
|
subtitle: '核心要求',
|
||||||
|
prompt: `請生成「{positionName}」的基本招聘要求。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:minEducation, workExperience, jobType, jobTitle
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag2: {
|
||||||
|
title: '標準需求',
|
||||||
|
subtitle: '完整資訊',
|
||||||
|
prompt: `請生成「{positionName}」的標準招聘要求。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:minEducation, salaryRange, workExperience, jobType, recruitPosition, jobTitle, positionReq, skillReq
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- minEducation: 最低學歷代碼(HS=高中職, JC=專科, BA=大學, MA=碩士, PHD=博士)
|
||||||
|
- salaryRange: 薪酬范圍代碼(A=30000以下, B=30000-50000, C=50000-80000, D=80000-120000, E=120000以上, N=面議)
|
||||||
|
- workExperience: 工作經驗年數(0=不限, 1, 3, 5, 10)
|
||||||
|
- jobType: 工作性質代碼(FT=全職, PT=兼職, CT=約聘, DP=派遣)
|
||||||
|
- recruitPosition: 招聘職位代碼(ENG=工程師, MGR=經理, AST=助理, OP=作業員, SAL=業務)
|
||||||
|
- positionReq: 崗位要求(條列式,用換行分隔)
|
||||||
|
- skillReq: 技能要求(條列式,用換行分隔)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag3: {
|
||||||
|
title: '完整需求',
|
||||||
|
subtitle: '18個欄位',
|
||||||
|
prompt: `請生成「{positionName}」的完整招聘要求資料。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成所有空白欄位。
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- minEducation: 最低學歷代碼(HS=高中職, JC=專科, BA=大學, MA=碩士, PHD=博士)
|
||||||
|
- requiredGender: 性別要求代碼(M=限男性, F=限女性, N=不限)
|
||||||
|
- salaryRange: 薪酬范圍代碼(A=30000以下, B=30000-50000, C=50000-80000, D=80000-120000, E=120000以上, N=面議)
|
||||||
|
- workExperience: 工作經驗年數(0=不限, 1, 3, 5, 10)
|
||||||
|
- minAge: 最低年齡(18-65)
|
||||||
|
- maxAge: 最高年齡(18-65)
|
||||||
|
- jobType: 工作性質代碼(FT=全職, PT=兼職, CT=約聘, DP=派遣)
|
||||||
|
- recruitPosition: 招聘職位代碼(ENG=工程師, MGR=經理, AST=助理, OP=作業員, SAL=業務)
|
||||||
|
- jobTitle: 職位名稱
|
||||||
|
- jobDesc: 工作內容(條列式,用換行分隔)
|
||||||
|
- positionReq: 崗位要求(條列式,用換行分隔)
|
||||||
|
- titleReq: 職稱要求(條列式,用換行分隔)
|
||||||
|
- majorReq: 科系要求(多個科系用逗號分隔)
|
||||||
|
- skillReq: 技能要求(條列式,用換行分隔)
|
||||||
|
- langReq: 語言要求(條列式,用換行分隔)
|
||||||
|
- otherReq: 其他要求(條列式,用換行分隔)
|
||||||
|
- superiorPosition: 直屬主管職位
|
||||||
|
- recruitRemark: 招聘備注
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
jobBasic: {
|
||||||
|
bag1: {
|
||||||
|
title: '簡化版',
|
||||||
|
subtitle: '核心欄位',
|
||||||
|
prompt: `請生成職務基礎資料(簡化版)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:jobCode, jobName, jobCategoryCode
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag2: {
|
||||||
|
title: '標準版',
|
||||||
|
subtitle: '常用欄位',
|
||||||
|
prompt: `請生成職務基礎資料(標準版)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:jobCode, jobName, jobNameEn, jobCategoryCode, jobLevel, jobHeadcount
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- jobCode: 職務編號(格式如 J001)
|
||||||
|
- jobName: 職務名稱(繁體中文)
|
||||||
|
- jobNameEn: 職務名稱英文
|
||||||
|
- jobCategoryCode: 職務類別代碼(01=技術類, 02=管理類, 03=業務類, 04=行政類)
|
||||||
|
- jobLevel: 職務級別(J1-J7)
|
||||||
|
- jobHeadcount: 職務人數(1-100)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag3: {
|
||||||
|
title: '完整版',
|
||||||
|
subtitle: '所有欄位',
|
||||||
|
prompt: `請生成完整的職務基礎資料。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成所有空白欄位。
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- jobCode: 職務編號(格式如 J001)
|
||||||
|
- jobName: 職務名稱(繁體中文)
|
||||||
|
- jobNameEn: 職務名稱英文
|
||||||
|
- jobCategoryCode: 職務類別代碼(01=技術類, 02=管理類, 03=業務類, 04=行政類)
|
||||||
|
- jobLevel: 職務級別(J1-J7)
|
||||||
|
- jobHeadcount: 職務人數(1-100)
|
||||||
|
- jobEffectiveDate: 生效日期(YYYY-MM-DD)
|
||||||
|
- jobSortOrder: 排序順序(1-999)
|
||||||
|
- hasAttendanceBonus: 是否有全勤獎金(true/false)
|
||||||
|
- hasHousingAllowance: 是否有住宿津貼(true/false)
|
||||||
|
- jobRemark: 職務備註
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deptFunction: {
|
||||||
|
bag1: {
|
||||||
|
title: '基本版',
|
||||||
|
subtitle: '核心資訊',
|
||||||
|
prompt: `請生成部門職責資料(基本版)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:deptFunctionCode, deptFunctionName, deptFunctionBU, deptFunctionDept
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag2: {
|
||||||
|
title: '標準版',
|
||||||
|
subtitle: '含職責描述',
|
||||||
|
prompt: `請生成部門職責資料(標準版)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:deptFunctionCode, deptFunctionName, deptFunctionBU, deptFunctionDept, deptManager, deptMission, deptCoreFunctions
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- deptFunctionCode: 部門職責編號(格式如 DF001)
|
||||||
|
- deptFunctionName: 部門職責名稱
|
||||||
|
- deptFunctionBU: 事業單位代碼(BU1-BU5)
|
||||||
|
- deptFunctionDept: 部門代碼(DEPT1-DEPT20)
|
||||||
|
- deptManager: 部門主管
|
||||||
|
- deptMission: 部門使命(簡短描述)
|
||||||
|
- deptCoreFunctions: 核心職能(條列式,用換行分隔)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag3: {
|
||||||
|
title: '完整版',
|
||||||
|
subtitle: '含KPI指標',
|
||||||
|
prompt: `請生成完整的部門職責資料。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成所有空白欄位。
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- deptFunctionCode: 部門職責編號(格式如 DF001)
|
||||||
|
- deptFunctionName: 部門職責名稱
|
||||||
|
- deptFunctionBU: 事業單位代碼(BU1-BU5)
|
||||||
|
- deptFunctionDept: 部門代碼(DEPT1-DEPT20)
|
||||||
|
- deptManager: 部門主管
|
||||||
|
- deptMission: 部門使命(簡短描述)
|
||||||
|
- deptVision: 部門願景(條列式,用換行分隔)
|
||||||
|
- deptCoreFunctions: 核心職能(條列式,用換行分隔)
|
||||||
|
- deptKPIs: KPI 指標(條列式,用換行分隔)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
jobDesc: {
|
||||||
|
bag1: {
|
||||||
|
title: '基本版',
|
||||||
|
subtitle: '核心資訊',
|
||||||
|
prompt: `請生成崗位描述資料(基本版)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:positionName, department, positionPurpose
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag2: {
|
||||||
|
title: '標準版',
|
||||||
|
subtitle: '含職責說明',
|
||||||
|
prompt: `請生成崗位描述資料(標準版)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:positionName, department, directSupervisor, positionPurpose, mainResponsibilities, education, basicSkills
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- positionName: 崗位名稱
|
||||||
|
- department: 所屬部門
|
||||||
|
- directSupervisor: 直屬主管
|
||||||
|
- positionPurpose: 崗位目的(簡短描述)
|
||||||
|
- mainResponsibilities: 主要職責(條列式,用換行分隔)
|
||||||
|
- education: 學歷要求
|
||||||
|
- basicSkills: 基本技能(條列式,用換行分隔)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
},
|
||||||
|
bag3: {
|
||||||
|
title: '完整版',
|
||||||
|
subtitle: '33個欄位',
|
||||||
|
prompt: `請生成完整的崗位描述資料。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成所有空白欄位。
|
||||||
|
|
||||||
|
包含以下區塊:
|
||||||
|
1. 基本資訊:empNo, empName, positionCode, versionDate
|
||||||
|
2. 崗位資訊:positionName, department, positionEffectiveDate, directSupervisor, positionGradeJob, reportTo, directReports, workLocation, empAttribute
|
||||||
|
3. 職責與目的:positionPurpose, mainResponsibilities
|
||||||
|
4. 任職要求:education, basicSkills, professionalKnowledge, workExperienceReq, otherRequirements
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================== LocalStorage 管理 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 獲取模組的 prompts(優先使用自定義,否則使用預設)
|
||||||
|
* @param {string} module - 模組名稱
|
||||||
|
* @returns {Object} - 包含三個 bag 的 prompt 物件
|
||||||
|
*/
|
||||||
|
function getModulePrompts(module) {
|
||||||
|
try {
|
||||||
|
const saved = localStorage.getItem('aiPrompts');
|
||||||
|
const prompts = saved ? JSON.parse(saved) : {};
|
||||||
|
|
||||||
|
// 如果沒有保存的 prompts,使用預設值
|
||||||
|
if (!prompts[module]) {
|
||||||
|
return DEFAULT_PROMPTS[module] || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return prompts[module];
|
||||||
|
} catch (e) {
|
||||||
|
console.error('讀取 prompts 失敗:', e);
|
||||||
|
return DEFAULT_PROMPTS[module] || {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存模組的 prompts
|
||||||
|
* @param {string} module - 模組名稱
|
||||||
|
* @param {number} bagNumber - 錦囊編號 (1-3)
|
||||||
|
* @param {Object} bagData - 包含 title, subtitle, prompt 的物件
|
||||||
|
*/
|
||||||
|
function saveModulePrompt(module, bagNumber, bagData) {
|
||||||
|
try {
|
||||||
|
const saved = localStorage.getItem('aiPrompts');
|
||||||
|
const prompts = saved ? JSON.parse(saved) : {};
|
||||||
|
|
||||||
|
if (!prompts[module]) {
|
||||||
|
prompts[module] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
prompts[module][`bag${bagNumber}`] = bagData;
|
||||||
|
localStorage.setItem('aiPrompts', JSON.stringify(prompts));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('保存 prompt 失敗:', e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化所有模組的預設 prompts(如果尚未設定)
|
||||||
|
*/
|
||||||
|
function initializeDefaultPrompts() {
|
||||||
|
const saved = localStorage.getItem('aiPrompts');
|
||||||
|
if (!saved) {
|
||||||
|
localStorage.setItem('aiPrompts', JSON.stringify(DEFAULT_PROMPTS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 執行 AI 錦囊 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 執行 AI 錦囊
|
||||||
|
* @param {string} module - 模組名稱
|
||||||
|
* @param {number} bagNumber - 錦囊編號 (1-3)
|
||||||
|
*/
|
||||||
|
export async function executeAIBag(module, bagNumber) {
|
||||||
|
const bagElement = document.querySelector(`.ai-bag[data-module="${module}"][data-bag="${bagNumber}"]`);
|
||||||
|
if (!bagElement) return;
|
||||||
|
|
||||||
|
// 防止重複點擊
|
||||||
|
if (bagElement.classList.contains('loading')) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 顯示載入狀態
|
||||||
|
bagElement.classList.add('loading');
|
||||||
|
const icon = bagElement.querySelector('.bag-icon');
|
||||||
|
const originalIcon = icon.textContent;
|
||||||
|
icon.innerHTML = '<div class="spinner"></div>';
|
||||||
|
|
||||||
|
// 獲取當前表單資料
|
||||||
|
let existingData = {};
|
||||||
|
if (module === 'positionBasic' || module === 'positionRecruit') {
|
||||||
|
const positionData = getPositionFormData();
|
||||||
|
existingData = module === 'positionBasic' ? positionData.basicInfo : positionData.recruitInfo;
|
||||||
|
} else if (module === 'jobBasic') {
|
||||||
|
existingData = getJobFormData();
|
||||||
|
} else if (module === 'jobDesc') {
|
||||||
|
existingData = getJobDescFormData();
|
||||||
|
} else if (module === 'deptFunction') {
|
||||||
|
existingData = getDeptFunctionFormData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 獲取 prompt 模板
|
||||||
|
const prompts = getModulePrompts(module);
|
||||||
|
const bagPrompt = prompts[`bag${bagNumber}`];
|
||||||
|
|
||||||
|
if (!bagPrompt || !bagPrompt.prompt) {
|
||||||
|
throw new Error('Prompt 模板不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替換 prompt 中的變數
|
||||||
|
let finalPrompt = bagPrompt.prompt
|
||||||
|
.replace('{existingData}', JSON.stringify(existingData, null, 2))
|
||||||
|
.replace('{positionName}', existingData.positionName || '此崗位');
|
||||||
|
|
||||||
|
// 調用 AI API
|
||||||
|
const result = await callClaudeAPI(finalPrompt);
|
||||||
|
|
||||||
|
// 填充表單
|
||||||
|
fillFormWithAIResult(module, result);
|
||||||
|
|
||||||
|
showToast('✨ AI 生成成功!');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('AI 錦囊執行失敗:', error);
|
||||||
|
showToast('❌ AI 生成失敗: ' + error.message);
|
||||||
|
} finally {
|
||||||
|
// 恢復正常狀態
|
||||||
|
bagElement.classList.remove('loading');
|
||||||
|
const icon = bagElement.querySelector('.bag-icon');
|
||||||
|
icon.textContent = '🎁';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根據 AI 結果填充表單
|
||||||
|
* @param {string} module - 模組名稱
|
||||||
|
* @param {Object} result - AI 返回的 JSON 結果
|
||||||
|
*/
|
||||||
|
function fillFormWithAIResult(module, result) {
|
||||||
|
if (module === 'positionBasic') {
|
||||||
|
// 崗位基礎資料 - 基礎資料頁籤
|
||||||
|
Object.entries(result).forEach(([key, value]) => {
|
||||||
|
fillIfEmpty(key, value);
|
||||||
|
});
|
||||||
|
} else if (module === 'positionRecruit') {
|
||||||
|
// 崗位基礎資料 - 招聘要求頁籤
|
||||||
|
Object.entries(result).forEach(([key, value]) => {
|
||||||
|
fillIfEmpty(key, value);
|
||||||
|
});
|
||||||
|
} else if (module === 'jobBasic') {
|
||||||
|
// 職務基礎資料
|
||||||
|
Object.entries(result).forEach(([key, value]) => {
|
||||||
|
if (key === 'hasAttendanceBonus' || key === 'hasHousingAllowance') {
|
||||||
|
const checkbox = document.getElementById(key);
|
||||||
|
if (checkbox) checkbox.checked = value;
|
||||||
|
} else {
|
||||||
|
fillIfEmpty(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (module === 'deptFunction') {
|
||||||
|
// 部門職責
|
||||||
|
Object.entries(result).forEach(([key, value]) => {
|
||||||
|
fillIfEmpty('df_' + key, value);
|
||||||
|
});
|
||||||
|
} else if (module === 'jobDesc') {
|
||||||
|
// 崗位描述
|
||||||
|
if (result.basicInfo) {
|
||||||
|
Object.entries(result.basicInfo).forEach(([key, value]) => {
|
||||||
|
fillIfEmpty('jd_' + key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (result.positionInfo) {
|
||||||
|
Object.entries(result.positionInfo).forEach(([key, value]) => {
|
||||||
|
fillIfEmpty('jd_' + key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (result.responsibilities) {
|
||||||
|
Object.entries(result.responsibilities).forEach(([key, value]) => {
|
||||||
|
fillIfEmpty('jd_' + key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (result.requirements) {
|
||||||
|
Object.entries(result.requirements).forEach(([key, value]) => {
|
||||||
|
fillIfEmpty('jd_' + key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 編輯 Prompt ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 編輯錦囊 Prompt
|
||||||
|
* @param {Event} event - 點擊事件
|
||||||
|
* @param {string} module - 模組名稱
|
||||||
|
* @param {number} bagNumber - 錦囊編號 (1-3)
|
||||||
|
*/
|
||||||
|
export function editBagPrompt(event, module, bagNumber) {
|
||||||
|
event.stopPropagation(); // 防止觸發父元素的 click 事件
|
||||||
|
|
||||||
|
const prompts = getModulePrompts(module);
|
||||||
|
const bagPrompt = prompts[`bag${bagNumber}`];
|
||||||
|
|
||||||
|
if (!bagPrompt) {
|
||||||
|
showToast('❌ Prompt 不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 顯示編輯對話框
|
||||||
|
showPromptEditModal(module, bagNumber, bagPrompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 顯示 Prompt 編輯對話框
|
||||||
|
* @param {string} module - 模組名稱
|
||||||
|
* @param {number} bagNumber - 錦囊編號 (1-3)
|
||||||
|
* @param {Object} bagData - 包含 title, subtitle, prompt 的物件
|
||||||
|
*/
|
||||||
|
function showPromptEditModal(module, bagNumber, bagData) {
|
||||||
|
const modal = document.getElementById('promptEditModal');
|
||||||
|
if (!modal) {
|
||||||
|
console.error('找不到編輯對話框');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 填充對話框內容
|
||||||
|
document.getElementById('promptModalTitle').textContent = `編輯錦囊 ${bagNumber} - ${bagData.title}`;
|
||||||
|
document.getElementById('promptTitle').value = bagData.title || '';
|
||||||
|
document.getElementById('promptSubtitle').value = bagData.subtitle || '';
|
||||||
|
document.getElementById('promptContent').value = bagData.prompt || '';
|
||||||
|
|
||||||
|
// 保存當前編輯的模組和錦囊編號
|
||||||
|
modal.dataset.module = module;
|
||||||
|
modal.dataset.bagNumber = bagNumber;
|
||||||
|
|
||||||
|
// 顯示對話框
|
||||||
|
modal.classList.add('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存編輯的 Prompt
|
||||||
|
*/
|
||||||
|
export function savePromptEdit() {
|
||||||
|
const modal = document.getElementById('promptEditModal');
|
||||||
|
const module = modal.dataset.module;
|
||||||
|
const bagNumber = parseInt(modal.dataset.bagNumber);
|
||||||
|
|
||||||
|
const title = document.getElementById('promptTitle').value.trim();
|
||||||
|
const subtitle = document.getElementById('promptSubtitle').value.trim();
|
||||||
|
const prompt = document.getElementById('promptContent').value.trim();
|
||||||
|
|
||||||
|
if (!title || !prompt) {
|
||||||
|
showToast('⚠️ 標題和 Prompt 內容不能為空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存到 LocalStorage
|
||||||
|
const success = saveModulePrompt(module, bagNumber, { title, subtitle, prompt });
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
// 更新頁面上的錦囊標題
|
||||||
|
const bagElement = document.querySelector(`.ai-bag[data-module="${module}"][data-bag="${bagNumber}"]`);
|
||||||
|
if (bagElement) {
|
||||||
|
const titleElement = bagElement.querySelector('.bag-title');
|
||||||
|
const subtitleElement = bagElement.querySelector('.bag-subtitle');
|
||||||
|
if (titleElement) titleElement.textContent = title;
|
||||||
|
if (subtitleElement) {
|
||||||
|
if (subtitle) {
|
||||||
|
if (!subtitleElement.classList) {
|
||||||
|
const newSubtitle = document.createElement('div');
|
||||||
|
newSubtitle.className = 'bag-subtitle';
|
||||||
|
newSubtitle.textContent = subtitle;
|
||||||
|
bagElement.querySelector('.bag-title').after(newSubtitle);
|
||||||
|
} else {
|
||||||
|
subtitleElement.textContent = subtitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closePromptEditModal();
|
||||||
|
showToast('✅ Prompt 已保存');
|
||||||
|
} else {
|
||||||
|
showToast('❌ 保存失敗');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 關閉編輯對話框
|
||||||
|
*/
|
||||||
|
export function closePromptEditModal() {
|
||||||
|
const modal = document.getElementById('promptEditModal');
|
||||||
|
if (modal) {
|
||||||
|
modal.classList.remove('show');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置為預設 Prompt
|
||||||
|
*/
|
||||||
|
export function resetToDefaultPrompt() {
|
||||||
|
const modal = document.getElementById('promptEditModal');
|
||||||
|
const module = modal.dataset.module;
|
||||||
|
const bagNumber = parseInt(modal.dataset.bagNumber);
|
||||||
|
|
||||||
|
const defaultPrompt = DEFAULT_PROMPTS[module]?.[`bag${bagNumber}`];
|
||||||
|
|
||||||
|
if (!defaultPrompt) {
|
||||||
|
showToast('❌ 找不到預設 Prompt');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirm('確定要重置為預設 Prompt 嗎?')) {
|
||||||
|
document.getElementById('promptTitle').value = defaultPrompt.title || '';
|
||||||
|
document.getElementById('promptSubtitle').value = defaultPrompt.subtitle || '';
|
||||||
|
document.getElementById('promptContent').value = defaultPrompt.prompt || '';
|
||||||
|
|
||||||
|
showToast('✅ 已重置為預設值');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 初始化 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化錦囊標題
|
||||||
|
*/
|
||||||
|
export function initializeBagTitles() {
|
||||||
|
document.querySelectorAll('.ai-bag').forEach(bag => {
|
||||||
|
const module = bag.dataset.module;
|
||||||
|
const bagNumber = parseInt(bag.dataset.bag);
|
||||||
|
|
||||||
|
const prompts = getModulePrompts(module);
|
||||||
|
const bagPrompt = prompts[`bag${bagNumber}`];
|
||||||
|
|
||||||
|
if (bagPrompt) {
|
||||||
|
const titleElement = bag.querySelector('.bag-title');
|
||||||
|
const subtitleElement = bag.querySelector('.bag-subtitle');
|
||||||
|
|
||||||
|
if (titleElement) titleElement.textContent = bagPrompt.title || `錦囊${bagNumber}`;
|
||||||
|
if (subtitleElement && bagPrompt.subtitle) {
|
||||||
|
subtitleElement.textContent = bagPrompt.subtitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 頁面載入時初始化
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
initializeDefaultPrompts();
|
||||||
|
initializeBagTitles();
|
||||||
|
});
|
||||||
|
|
||||||
|
// ==================== 掛載到 window ====================
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.executeAIBag = executeAIBag;
|
||||||
|
window.editBagPrompt = editBagPrompt;
|
||||||
|
window.savePromptEdit = savePromptEdit;
|
||||||
|
window.closePromptEditModal = closePromptEditModal;
|
||||||
|
window.resetToDefaultPrompt = resetToDefaultPrompt;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import { showToast } from './utils.js';
|
import { showToast } from './utils.js';
|
||||||
import { switchModule, updatePreview, updateCategoryName, updateNatureName, updateJobCategoryName } from './ui.js';
|
import { switchModule, updatePreview, updateCategoryName, updateNatureName, updateJobCategoryName } from './ui.js';
|
||||||
|
import { initializeBagTitles } from './ai-bags.js';
|
||||||
|
|
||||||
// ==================== 初始化 ====================
|
// ==================== 初始化 ====================
|
||||||
|
|
||||||
@@ -187,6 +188,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
setupFormListeners();
|
setupFormListeners();
|
||||||
setupKeyboardShortcuts();
|
setupKeyboardShortcuts();
|
||||||
|
|
||||||
|
// 初始化 AI 錦囊標題
|
||||||
|
initializeBagTitles();
|
||||||
|
|
||||||
// 初始化預覽
|
// 初始化預覽
|
||||||
updatePreview();
|
updatePreview();
|
||||||
|
|
||||||
|
|||||||
@@ -265,7 +265,87 @@ select {
|
|||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================== AI Button ==================== */
|
/* ==================== AI Bags (Three Fortune Bags) ==================== */
|
||||||
|
.ai-bags-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag {
|
||||||
|
position: relative;
|
||||||
|
padding: 20px;
|
||||||
|
background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(155, 89, 182, 0.3);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 6px 20px rgba(155, 89, 182, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag:active {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .bag-icon {
|
||||||
|
font-size: 2rem;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .bag-title {
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .bag-subtitle {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .bag-edit-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
right: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .bag-edit-btn:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag.loading {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .spinner {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||||
|
border-top-color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 0.8s linear infinite;
|
||||||
|
margin: 8px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================== Old AI Button (Deprecated) ==================== */
|
||||||
.ai-generate-btn {
|
.ai-generate-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
263
三個錦囊設計.md
Normal file
263
三個錦囊設計.md
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
# 三個錦囊功能設計
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
將原本的單一 "I'm feeling lucky" 按鈕改為三個可自定義的 AI 生成按鈕("三個錦囊")。
|
||||||
|
|
||||||
|
## UI 設計
|
||||||
|
|
||||||
|
### 視覺效果
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ 🎁 錦囊一 🎁 錦囊二 🎁 錦囊三 │
|
||||||
|
│ [標題] [標題] [標題] │
|
||||||
|
│ ⚙️ 編輯 ⚙️ 編輯 ⚙️ 編輯 │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 互動流程
|
||||||
|
1. **點擊錦囊按鈕** → 使用預設或自定義的 prompt 調用 AI
|
||||||
|
2. **點擊編輯圖示** → 彈出對話框,顯示並可編輯當前 prompt
|
||||||
|
3. **Prompt 儲存** → 儲存至 localStorage(按模組區分)
|
||||||
|
|
||||||
|
## 資料結構
|
||||||
|
|
||||||
|
### LocalStorage 結構
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"prompts": {
|
||||||
|
"positionBasic": {
|
||||||
|
"bag1": { "title": "簡化版", "prompt": "..." },
|
||||||
|
"bag2": { "title": "標準版", "prompt": "..." },
|
||||||
|
"bag3": { "title": "詳細版", "prompt": "..." }
|
||||||
|
},
|
||||||
|
"positionRecruit": {
|
||||||
|
"bag1": { "title": "一般需求", "prompt": "..." },
|
||||||
|
"bag2": { "title": "高階需求", "prompt": "..." },
|
||||||
|
"bag3": { "title": "專業需求", "prompt": "..." }
|
||||||
|
},
|
||||||
|
"jobBasic": { ... },
|
||||||
|
"deptFunction": { ... },
|
||||||
|
"jobDesc": { ... }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 預設 Prompt 模板
|
||||||
|
|
||||||
|
### 崗位基礎資料 - 基礎資料頁籤
|
||||||
|
|
||||||
|
#### 錦囊一:簡化版(僅填必填欄位)
|
||||||
|
```
|
||||||
|
你是專業人資顧問,熟悉半導體製造業。請生成崗位基礎資料(僅必填欄位)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:positionCode, positionName
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式。
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 錦囊二:標準版(常用欄位)
|
||||||
|
```
|
||||||
|
你是專業人資顧問,熟悉半導體製造業。請生成崗位基礎資料(標準版)。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:positionCode, positionName, positionCategory, positionLevel, headcount
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- positionCode: 崗位編號(格式如 ENG-001)
|
||||||
|
- positionName: 崗位名稱
|
||||||
|
- positionCategory: 崗位類別代碼(01=技術職, 02=管理職, 03=業務職, 04=行政職)
|
||||||
|
- positionLevel: 崗位級別(L1-L7)
|
||||||
|
- headcount: 編制人數(1-10)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式。
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 錦囊三:詳細版(所有欄位)
|
||||||
|
```
|
||||||
|
你是專業人資顧問,熟悉半導體製造業的人資所有流程。請生成完整的崗位基礎資料。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:positionCode, positionName, positionCategory, positionNature, headcount, positionLevel, positionDesc, positionRemark
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- positionCode: 崗位編號(格式如 ENG-001, MGR-002)
|
||||||
|
- positionName: 崗位名稱
|
||||||
|
- positionCategory: 崗位類別代碼(01=技術職, 02=管理職, 03=業務職, 04=行政職)
|
||||||
|
- positionNature: 崗位性質代碼(FT=全職, PT=兼職, CT=約聘, IN=實習)
|
||||||
|
- headcount: 編制人數(1-10之間的數字字串)
|
||||||
|
- positionLevel: 崗位級別(L1到L7)
|
||||||
|
- positionDesc: 崗位描述(條列式,用換行分隔)
|
||||||
|
- positionRemark: 崗位備注(條列式,用換行分隔)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式,不要有任何其他文字。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 崗位基礎資料 - 招聘要求頁籤
|
||||||
|
|
||||||
|
#### 錦囊一:基本需求
|
||||||
|
```
|
||||||
|
請生成「{positionName}」的基本招聘要求。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:minEducation, workExperience, jobType, jobTitle
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式。
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 錦囊二:標準需求
|
||||||
|
```
|
||||||
|
請生成「{positionName}」的標準招聘要求。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成的欄位:minEducation, salaryRange, workExperience, jobType, recruitPosition, jobTitle, positionReq, skillReq
|
||||||
|
|
||||||
|
欄位說明:
|
||||||
|
- minEducation: 最低學歷代碼(HS=高中職, JC=專科, BA=大學, MA=碩士, PHD=博士)
|
||||||
|
- salaryRange: 薪酬范圍代碼(A=30000以下, B=30000-50000, C=50000-80000, D=80000-120000, E=120000以上, N=面議)
|
||||||
|
- workExperience: 工作經驗年數(0=不限, 1, 3, 5, 10)
|
||||||
|
- jobType: 工作性質代碼(FT=全職, PT=兼職, CT=約聘, DP=派遣)
|
||||||
|
- recruitPosition: 招聘職位代碼(ENG=工程師, MGR=經理, AST=助理, OP=作業員, SAL=業務)
|
||||||
|
- positionReq: 崗位要求(條列式,用換行分隔)
|
||||||
|
- skillReq: 技能要求(條列式,用換行分隔)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式。
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 錦囊三:完整需求
|
||||||
|
```
|
||||||
|
請生成「{positionName}」的完整招聘要求資料。
|
||||||
|
|
||||||
|
已填寫的資料:{existingData}
|
||||||
|
需要生成所有空白欄位。
|
||||||
|
|
||||||
|
(完整欄位說明同標準版,包含所有 18 個欄位)
|
||||||
|
|
||||||
|
請用繁體中文,返回 JSON 格式。
|
||||||
|
```
|
||||||
|
|
||||||
|
## 實作步驟
|
||||||
|
|
||||||
|
### 1. HTML 結構更新
|
||||||
|
將單一按鈕:
|
||||||
|
```html
|
||||||
|
<button type="button" class="ai-generate-btn" onclick="generatePositionBasic()">
|
||||||
|
<span>✨ I'm feeling lucky</span>
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
改為三個錦囊:
|
||||||
|
```html
|
||||||
|
<div class="ai-bags-container">
|
||||||
|
<div class="ai-bag" data-bag="1" onclick="executeAIBag('positionBasic', 1)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title" id="bag1-title-positionBasic">錦囊一</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'positionBasic', 1)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-bag="2" onclick="executeAIBag('positionBasic', 2)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title" id="bag2-title-positionBasic">錦囊二</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'positionBasic', 2)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
<div class="ai-bag" data-bag="3" onclick="executeAIBag('positionBasic', 3)">
|
||||||
|
<div class="bag-icon">🎁</div>
|
||||||
|
<div class="bag-title" id="bag3-title-positionBasic">錦囊三</div>
|
||||||
|
<button class="bag-edit-btn" onclick="editBagPrompt(event, 'positionBasic', 3)">⚙️</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. CSS 樣式
|
||||||
|
```css
|
||||||
|
.ai-bags-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag {
|
||||||
|
position: relative;
|
||||||
|
padding: 20px;
|
||||||
|
background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%);
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(155, 89, 182, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 6px 20px rgba(155, 89, 182, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .bag-icon {
|
||||||
|
font-size: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .bag-title {
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .bag-edit-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
right: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-bag .bag-edit-btn:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. JavaScript 函式
|
||||||
|
|
||||||
|
#### 執行 AI 錦囊
|
||||||
|
```javascript
|
||||||
|
async function executeAIBag(module, bagNumber) {
|
||||||
|
const prompts = getModulePrompts(module);
|
||||||
|
const bagPrompt = prompts[`bag${bagNumber}`];
|
||||||
|
|
||||||
|
// 使用 prompt 調用 AI
|
||||||
|
await callClaudeAPI(bagPrompt.prompt);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 編輯 Prompt
|
||||||
|
```javascript
|
||||||
|
function editBagPrompt(event, module, bagNumber) {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// 顯示編輯對話框
|
||||||
|
showPromptEditModal(module, bagNumber);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 優點
|
||||||
|
|
||||||
|
1. ✅ **靈活性高** - 用戶可自定義每個錦囊的用途
|
||||||
|
2. ✅ **效率提升** - 三個預設選項涵蓋不同需求場景
|
||||||
|
3. ✅ **學習友好** - 顯示 prompt 有助於理解 AI 運作
|
||||||
|
4. ✅ **可擴展** - 未來可增加更多錦囊或分享功能
|
||||||
|
|
||||||
|
## 待實作功能
|
||||||
|
|
||||||
|
- [ ] HTML 結構更新(5 個模組)
|
||||||
|
- [ ] CSS 樣式新增
|
||||||
|
- [ ] JavaScript 函式實作
|
||||||
|
- [ ] LocalStorage 管理
|
||||||
|
- [ ] 編輯 Modal 對話框
|
||||||
|
- [ ] 預設 Prompt 初始化
|
||||||
176
更新欄位名稱.md
Normal file
176
更新欄位名稱.md
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
# 系統表單欄位規範書 (Standardized Field Specifications)
|
||||||
|
|
||||||
|
## 1. 命名規範與前綴定義 (Naming Conventions)
|
||||||
|
|
||||||
|
為了確保系統一致性,HTML 元素 ID 採用 `[模組前綴]_[標準欄位名]` 的命名方式。
|
||||||
|
|
||||||
|
| 模組名稱 | 模組前綴 (Prefix) | 說明 |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **崗位管理 (Position)** | `pos_` | 崗位基礎資料 |
|
||||||
|
| **招聘條件 (Recruit)** | `rec_` | 崗位內的招聘頁籤 |
|
||||||
|
| **職務管理 (Job)** | `job_` | 全公司通用的職務定義 |
|
||||||
|
| **部門職責 (DeptFunc)** | `df_` | 部門功能與職責定義 |
|
||||||
|
| **崗位描述 (JobDesc)** | `jd_` | 最終的 JD 產出表單 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 崗位基礎資料模組 (Position Module)
|
||||||
|
|
||||||
|
**表單代號**: `positionForm`
|
||||||
|
**資料表**: `Position`
|
||||||
|
|
||||||
|
### 2.1 基礎資料頁籤 (tab-position-basic)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | 標準化 HTML ID | 資料庫欄位名稱 | 類型 | 必填 | 預設 | 備註 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| 1 | 事業體 | `pos_businessUnit` | `businessUnit` | select | 否 | - | SBU, MBU... (聯動L1) |
|
||||||
|
| 2 | 處級單位 | `pos_division` | `division` | select | 否 | - | (聯動L2) |
|
||||||
|
| 3 | 部級單位 | `pos_department` | `department` | select | 否 | - | (聯動L3) |
|
||||||
|
| 4 | 課級單位 | `pos_section` | `section` | text | 否 | - | - |
|
||||||
|
| 5 | **崗位編號** | `pos_code` | `positionCode` | text | **是** | - | 唯一識別碼 (PK) |
|
||||||
|
| 6 | 生效日期 | `pos_effectiveDate` | `effectiveDate` | date | 否 | Today | - |
|
||||||
|
| 7 | **崗位名稱** | `pos_name` | `positionName` | text | **是** | - | - |
|
||||||
|
| 8 | 崗位級別 | `pos_level` | `positionLevel` | select | 否 | - | L1-L7 |
|
||||||
|
| 9 | 崗位類別 | `pos_category` | `positionCategory` | select | 否 | - | onchange 觸發 |
|
||||||
|
| 10 | 崗位類別名稱 | `pos_categoryName` | `positionCategoryName` | text | 否 | - | readonly |
|
||||||
|
| 11 | 崗位性質 | `pos_type` | `positionType` | select | 否 | - | FT, PT, CT, IN |
|
||||||
|
| 12 | 崗位性質名稱 | `pos_typeName` | `positionTypeName` | text | 否 | - | readonly |
|
||||||
|
| 13 | 編制人數 | `pos_headcount` | `headcount` | number | 否 | 0 | min=0 |
|
||||||
|
| 14 | 崗位描述 | `pos_desc` | `description` | textarea | 否 | - | rows=6 |
|
||||||
|
| 15 | 崗位備注 | `pos_remark` | `remark` | textarea | 否 | - | rows=6 |
|
||||||
|
|
||||||
|
### 2.2 招聘要求資料頁籤 (tab-position-recruit)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | 標準化 HTML ID | 資料庫欄位名稱 | 類型 | 必填 | 預設 | 備註 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| 1 | 最低學歷 | `rec_eduLevel` | `educationLevel` | select | 否 | - | HS, BA, MA, PHD |
|
||||||
|
| 2 | 要求性別 | `rec_gender` | `requiredGender` | select | 否 | Any | M, F, Any |
|
||||||
|
| 3 | 薪酬范圍 | `rec_salaryRange` | `salaryRange` | select | 否 | - | A-E, Negotiable |
|
||||||
|
| 4 | 工作經驗 | `rec_expYears` | `experienceYears` | select | 否 | - | 0, 1, 3, 5, 10+ |
|
||||||
|
| 5 | 最小年齡 | `rec_minAge` | `minAge` | number | 否 | - | min=18 |
|
||||||
|
| 6 | 最大年齡 | `rec_maxAge` | `maxAge` | number | 否 | - | max=65 |
|
||||||
|
| 7 | 工作性質 | `rec_jobType` | `jobType` | select | 否 | - | 招聘用性質分類 |
|
||||||
|
| 8 | 招聘職位 | `rec_position` | `recruitPosition` | select | 否 | - | ENG, MGR... |
|
||||||
|
| 9 | 職位名稱(對外) | `rec_jobTitle` | `jobTitle` | text | 否 | - | 對外招聘用Title |
|
||||||
|
| 10 | 上級崗位編號 | `rec_superiorCode` | `superiorPositionCode` | text | 否 | - | - |
|
||||||
|
| 11 | 職位描述(JD) | `rec_jobDesc` | `recruitJobDesc` | textarea | 否 | - | 招聘廣告用 |
|
||||||
|
| 12 | 崗位要求(Req) | `rec_positionReq` | `recruitRequirements` | textarea | 否 | - | 招聘廣告用 |
|
||||||
|
| 13 | 證照要求 | `rec_certReq` | `certRequirements` | select | 否 | - | - |
|
||||||
|
| 14 | 專業要求 | `rec_majorReq` | `majorRequirements` | text | 否 | - | Modal選擇 |
|
||||||
|
| 15 | 技能要求 | `rec_skillReq` | `skillRequirements` | text | 否 | - | Tags input |
|
||||||
|
| 16 | 語言要求 | `rec_langReq` | `langRequirements` | text | 否 | - | - |
|
||||||
|
| 17 | 其他要求 | `rec_otherReq` | `otherRequirements` | text | 否 | - | - |
|
||||||
|
| 18 | 招聘備注 | `rec_remark` | `recruitRemark` | textarea | 否 | - | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 職務基礎資料模組 (Job Module)
|
||||||
|
|
||||||
|
**表單代號**: `jobForm`
|
||||||
|
**資料表**: `Job`
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | 標準化 HTML ID | 資料庫欄位名稱 | 類型 | 必填 | 預設 | 備註 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| 1 | **職務類別編號** | `job_category` | `jobCategoryCode` | select | **是** | - | onchange 觸發 |
|
||||||
|
| 2 | 職務類別名稱 | `job_categoryName` | `jobCategoryName` | text | 否 | - | readonly |
|
||||||
|
| 3 | **職務編號** | `job_code` | `jobCode` | text | **是** | - | 唯一識別碼 |
|
||||||
|
| 4 | **職務名稱** | `job_name` | `jobName` | text | **是** | - | - |
|
||||||
|
| 5 | 職務英文 | `job_nameEn` | `jobNameEn` | text | 否 | - | - |
|
||||||
|
| 6 | 生效日期 | `job_effectiveDate`| `effectiveDate` | date | 否 | - | - |
|
||||||
|
| 7 | 職務層級 | `job_level` | `jobLevel` | text | 否 | *保密* | **敏感欄位** |
|
||||||
|
| 8 | 編制人數 | `job_headcount` | `headcount` | number | 否 | - | - |
|
||||||
|
| 9 | 排列順序 | `job_sortOrder` | `sortOrder` | number | 否 | - | - |
|
||||||
|
| 10 | 全勤獎金 | `job_hasAttBonus` | `hasAttendanceBonus` | checkbox| 否 | false| Toggle Switch |
|
||||||
|
| 11 | 住房補貼 | `job_hasHouseAllow`| `hasHousingAllowance` | checkbox| 否 | false| Toggle Switch |
|
||||||
|
| 12 | 職務備注 | `job_remark` | `remark` | textarea | 否 | - | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 部門職責模組 (DeptFunction Module)
|
||||||
|
|
||||||
|
**表單代號**: `deptFunctionForm`
|
||||||
|
**資料表**: `DeptFunction`
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | 標準化 HTML ID | 資料庫欄位名稱 | 類型 | 必填 | 預設 | 備註 |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| 1 | **職責編號** | `df_code` | `dfCode` | text | **是** | - | DF-001 |
|
||||||
|
| 2 | **職責名稱** | `df_name` | `dfName` | text | **是** | - | - |
|
||||||
|
| 3 | **事業體** | `df_businessUnit` | `businessUnit` | select | **是** | - | (已合併重複欄位) |
|
||||||
|
| 4 | **處級單位** | `df_division` | `division` | select | **是** | - | - |
|
||||||
|
| 5 | **部級單位** | `df_department` | `department` | select | **是** | - | - |
|
||||||
|
| 6 | 課級單位 | `df_section` | `section` | text | 否 | - | - |
|
||||||
|
| 7 | **對應崗位** | `df_posTitle` | `positionTitle` | select | **是** | - | 關聯 Position |
|
||||||
|
| 8 | 崗位級別 | `df_posLevel` | `positionLevel` | select | 否 | - | 自動帶出或指定 |
|
||||||
|
| 9 | 部門主管職稱 | `df_managerTitle` | `managerTitle` | text | 否 | - | - |
|
||||||
|
| 10 | **生效日期** | `df_effectiveDate` | `effectiveDate` | date | **是** | - | - |
|
||||||
|
| 11 | 人數上限 | `df_headcountLimit`| `headcountLimit` | number | 否 | - | - |
|
||||||
|
| 12 | 狀態 | `df_status` | `status` | select | 否 | active | - |
|
||||||
|
| 13 | 部門使命 | `df_mission` | `mission` | textarea | 否 | - | - |
|
||||||
|
| 14 | 部門願景 | `df_vision` | `vision` | textarea | 否 | - | - |
|
||||||
|
| 15 | **核心職責** | `df_coreFunc` | `coreFunctions` | textarea | **是** | - | - |
|
||||||
|
| 16 | KPIs | `df_kpis` | `kpis` | textarea | 否 | - | - |
|
||||||
|
| 17 | 協作部門 | `df_collab` | `collaboration` | textarea | 否 | - | - |
|
||||||
|
| 18 | 備注 | `df_remark` | `remark` | textarea | 否 | - | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 崗位描述模組 (JobDescription Module)
|
||||||
|
|
||||||
|
**表單代號**: `jobDescForm`
|
||||||
|
**資料表**: `JobDescription` (部分欄位為 View)
|
||||||
|
|
||||||
|
### 5.1 基本信息 (Header)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | 標準化 HTML ID | 資料庫欄位名稱 | 類型 | 必填 | 備註 |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| 1 | 工號 | `jd_empNo` | `empNo` | text | 否 | Search Modal |
|
||||||
|
| 2 | 姓名 | `jd_empName` | `empName` | text | 否 | Readonly |
|
||||||
|
| 3 | 崗位代碼 | `jd_posCode` | `positionCode` | text | 否 | 關聯鍵 |
|
||||||
|
| 4 | 版本日期 | `jd_versionDate` | `versionDate` | date | 否 | - |
|
||||||
|
|
||||||
|
### 5.2 崗位資訊 (Position Info - Readonly/Derived)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | 標準化 HTML ID | 資料庫欄位名稱 | 類型 | 必填 | 備註 |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| 1 | 崗位名稱 | `jd_posName` | `positionName` | text | 否 | - |
|
||||||
|
| 2 | 事業體 | `jd_businessUnit` | `businessUnit` | select | 否 | - |
|
||||||
|
| 3 | 處級單位 | `jd_division` | `division` | select | 否 | - |
|
||||||
|
| 4 | 部級單位 | `jd_department` | `department` | select | 否 | - |
|
||||||
|
| 5 | 課級單位 | `jd_section` | `section` | text | 否 | - |
|
||||||
|
| 6 | 崗位級別 | `jd_posLevel` | `positionLevel` | select | 否 | - |
|
||||||
|
| 7 | 生效日期 | `jd_posEffDate` | `positionEffectiveDate`| date | 否 | - |
|
||||||
|
| 8 | **直接主管** | `jd_supervisor` | `directSupervisor` | text | 否 | - |
|
||||||
|
| 9 | 職等&職務 | `jd_gradeJob` | `positionGradeJob` | text | 否 | Modal |
|
||||||
|
| 10 | **匯報對象** | `jd_reportTo` | `reportTo` | text | 否 | Modal |
|
||||||
|
| 11 | 直接下屬 | `jd_directReports` | `directReports` | text | 否 | - |
|
||||||
|
| 12 | 任職地點 | `jd_location` | `workLocation` | select | 否 | - |
|
||||||
|
| 13 | 員工屬性 | `jd_empAttr` | `empAttribute` | select | 否 | - |
|
||||||
|
|
||||||
|
### 5.3 職責與要求 (Details)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | 標準化 HTML ID | 資料庫欄位名稱 | 類型 | 必填 | 備註 |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| 1 | 部門職責代碼 | `jd_dfCode` | `dfCode` | text | 否 | 關聯 DeptFunction |
|
||||||
|
| 2 | 崗位設置目的 | `jd_purpose` | `positionPurpose` | text | 否 | - |
|
||||||
|
| 3 | **主要職責** | `jd_mainResp` | `mainResponsibilities`| textarea | 否 | 編號清單 |
|
||||||
|
| 4 | 教育程度 | `jd_eduLevel` | `educationLevel` | text | 否 | - |
|
||||||
|
| 5 | 基本技能 | `jd_basicSkills` | `basicSkills` | textarea | 否 | - |
|
||||||
|
| 6 | 專業知識 | `jd_proKnowledge` | `professionalKnowledge` | textarea | 否 | - |
|
||||||
|
| 7 | 工作經驗 | `jd_expReq` | `experienceRequirements`| textarea | 否 | - |
|
||||||
|
| 8 | 其他要求 | `jd_otherReq` | `otherRequirements` | textarea | 否 | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 共用設定與資料字典
|
||||||
|
|
||||||
|
### 6.1 模態框 (Modals)
|
||||||
|
* `MajorModal` (專業要求)
|
||||||
|
* `EmpSearchModal` (員工搜索)
|
||||||
|
* `OrgSearchModal` (組織搜索)
|
||||||
|
* `GradeJobModal` (職等職務)
|
||||||
|
* `ReportToModal` (匯報對象)
|
||||||
|
|
||||||
|
### 6.2 特殊控件
|
||||||
|
* **Toggle Switch**: 用於所有布林值 (Boolean) 欄位。
|
||||||
|
* **Numbered Textarea**: 用於 `mainResponsibilities`,自動產生序號。
|
||||||
|
* **Cascading Selects**: 組織層級 (BU -> Div -> Dept -> Section) 統一使用標準聯動邏輯。
|
||||||
347
表單欄位清單.md
Normal file
347
表單欄位清單.md
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
# 表單欄位完整清單
|
||||||
|
|
||||||
|
## 1. 崗位基礎資料模組 - 基礎資料頁籤 (positionForm - tab-position-basic)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | HTML元素ID | 資料庫欄位名稱 | 資料類型 | 是否必填 | 預設值 | 備註 |
|
||||||
|
|---|-----------|---------|------------|------|------|------|------|
|
||||||
|
| 1 | 事業體 (Business Unit) | businessUnit | businessUnit | select | 否 | 空值 | SBU, MBU, HQBU, ITBU, HRBU, ACCBU |
|
||||||
|
| 2 | 處級單位 (Division) | division | division | select | 否 | 空值 | 根據事業體變動 |
|
||||||
|
| 3 | 部級單位 (Department) | department | department | select | 否 | 空值 | 根據處級單位變動 |
|
||||||
|
| 4 | 課級單位 (Section) | section | section | text | 否 | 選填 | - |
|
||||||
|
| 5 | 崗位編號 * | positionCode | positionCode | text | **是** | 空值 | 唯一識別碼,可更改 |
|
||||||
|
| 6 | 生效日期 | effectiveDate | effectiveDate | date | 否 | 2001-01-01 | - |
|
||||||
|
| 7 | 崗位名稱 * | positionName | positionName | text | **是** | 空值 | - |
|
||||||
|
| 8 | 崗位級別 | positionLevel | positionLevel | select | 否 | 空值 | L1-L7 (基層至總經理) |
|
||||||
|
| 9 | 崗位類別 | positionCategory | positionCategory | select | 否 | 空值 | 01, 02, 03, 04;有onchange事件 |
|
||||||
|
| 10 | 崗位類別名稱 | positionCategoryName | positionCategoryName | text | 否 | 自動帶出 | readonly |
|
||||||
|
| 11 | 崗位性質 | positionNature | positionNature | select | 否 | 空值 | FT(全職), PT(兼職), CT(約聘), IN(實習);有onchange事件 |
|
||||||
|
| 12 | 崗位性質名稱 | positionNatureName | positionNatureName | text | 否 | 自動帶出 | readonly |
|
||||||
|
| 13 | 編制人數 | headcount | headcount | number | 否 | 空值 | min=0 |
|
||||||
|
| 14 | 崗位描述(條列式說明) | positionDesc | positionDesc | textarea | 否 | 空值 | rows=6;有範例提示 |
|
||||||
|
| 15 | 崗位備注(條列式說明) | positionRemark | positionRemark | textarea | 否 | 空值 | rows=6;有範例提示 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 崗位基礎資料模組 - 招聘要求資料頁籤 (positionForm - tab-position-recruit)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | HTML元素ID | 資料庫欄位名稱 | 資料類型 | 是否必填 | 預設值 | 備註 |
|
||||||
|
|---|-----------|---------|------------|------|------|------|------|
|
||||||
|
| 1 | 最低學歷 | minEducation | minEducation | select | 否 | 空值 | HS, JC, BA, MA, PHD |
|
||||||
|
| 2 | 要求性別 | requiredGender | requiredGender | select | 否 | 不限 | M(男), F(女) |
|
||||||
|
| 3 | 薪酬范圍 | salaryRange | salaryRange | select | 否 | 空值 | A-E, N(面議) |
|
||||||
|
| 4 | 工作經驗 | workExperience | workExperience | select | 否 | 空值 | 0, 1, 3, 5, 10 (年) |
|
||||||
|
| 5 | 最小年齡 | minAge | minAge | number | 否 | 空值 | min=18, max=65 |
|
||||||
|
| 6 | 最大年齡 | maxAge | maxAge | number | 否 | 空值 | min=18, max=65 |
|
||||||
|
| 7 | 工作性質 | jobType | jobType | select | 否 | 空值 | FT, PT, CT, DP |
|
||||||
|
| 8 | 職位名稱 | jobTitle | jobTitle | text | 否 | 空值 | - |
|
||||||
|
| 9 | 招聘職位 | recruitPosition | recruitPosition | select | 否 | 空值 | ENG, MGR, AST, OP, SAL |
|
||||||
|
| 10 | 上級崗位編號 | superiorPosition | superiorPosition | text | 否 | 空值 | - |
|
||||||
|
| 11 | 職位描述 | jobDesc | jobDesc | textarea | 否 | 空值 | rows=3 |
|
||||||
|
| 12 | 崗位要求 | positionReq | positionReq | textarea | 否 | 空值 | rows=3 |
|
||||||
|
| 13 | 職稱要求 | titleReq | titleReq | select | 否 | 空值 | NONE, CERT, LIC |
|
||||||
|
| 14 | 專業要求 | majorReq | majorReq | text | 否 | 點擊選擇 | readonly;有modal選擇器 |
|
||||||
|
| 15 | 技能要求 | skillReq | skillReq | text | 否 | 空值 | 例:Excel, Python, SAP... |
|
||||||
|
| 16 | 語言要求 | langReq | langReq | text | 否 | 空值 | 例:英文中級、日文N2... |
|
||||||
|
| 17 | 其他要求 | otherReq | otherReq | text | 否 | 空值 | - |
|
||||||
|
| 18 | 備注說明 | recruitRemark | recruitRemark | textarea | 否 | 空值 | rows=4 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 職務基礎資料模組 (jobForm - tab-job-basic)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | HTML元素ID | 資料庫欄位名稱 | 資料類型 | 是否必填 | 預設值 | 備註 |
|
||||||
|
|---|-----------|---------|------------|------|------|------|------|
|
||||||
|
| 1 | 職務類別編號 * | jobCategoryCode | jobCategoryCode | select | **是** | 空值 | MGR, TECH, SALE, ADMIN, RD, PROD;有onchange事件 |
|
||||||
|
| 2 | 職務類別名稱 | jobCategoryName | jobCategoryName | text | 否 | 自動帶出 | readonly |
|
||||||
|
| 3 | 職務編號 * | jobCode | jobCode | text | **是** | 空值 | 可更改職務編號 |
|
||||||
|
| 4 | 職務名稱 * | jobName | jobName | text | **是** | 空值 | - |
|
||||||
|
| 5 | 職務英文 | jobNameEn | jobNameEn | text | 否 | 空值 | - |
|
||||||
|
| 6 | 生效日期 | jobEffectiveDate | jobEffectiveDate | date | 否 | 空值 | - |
|
||||||
|
| 7 | 編制人數 | jobHeadcount | jobHeadcount | number | 否 | 空值 | min=0 |
|
||||||
|
| 8 | 排列順序 | jobSortOrder | jobSortOrder | number | 否 | 空值 | min=0 |
|
||||||
|
| 9 | 備注說明 | jobRemark | jobRemark | textarea | 否 | 空值 | rows=4 |
|
||||||
|
| 10 | 職務層級 | jobLevel | jobLevel | text | 否 | 如:*保密* | 敏感信息欄位 |
|
||||||
|
| 11 | 是否有全勤 | hasAttendanceBonus | hasAttendanceBonus | checkbox | 否 | 否 | toggle-switch 控件 |
|
||||||
|
| 12 | 是否住房補貼 | hasHousingAllowance | hasHousingAllowance | checkbox | 否 | 否 | toggle-switch 控件 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 部門職責模組 (deptFunctionForm)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | HTML元素ID | 資料庫欄位名稱 | 資料類型 | 是否必填 | 預設值 | 備註 |
|
||||||
|
|---|-----------|---------|------------|------|------|------|------|
|
||||||
|
| 1 | 部門職責編號 * | deptFunctionCode | deptFunctionCode | text | **是** | 空值 | 例如: DF-001 |
|
||||||
|
| 2 | 部門職責名稱 * | deptFunctionName | deptFunctionName | text | **是** | 空值 | 例如: 軟體研發部職責 |
|
||||||
|
| 3 | 事業體 (Business Unit) * (第1個) | deptFunctionBU | deptFunctionBU | select | **是** | 空值 | SBU, MBU, HQBU, ITBU, HRBU, ACCBU |
|
||||||
|
| 4 | 事業體 (Business Unit) * (第2個) | deptFunc_businessUnit | businessUnit | select | **是** | 空值 | 聯動選擇 |
|
||||||
|
| 5 | 處級單位 (Division) * | deptFunc_division | division | select | **是** | 空值 | 聯動選擇 |
|
||||||
|
| 6 | 部級單位 (Department) * | deptFunc_department | department | select | **是** | 空值 | 聯動選擇 |
|
||||||
|
| 7 | 課級單位 (Section) | deptFunc_section | section | text | 否 | 選填 | - |
|
||||||
|
| 8 | 崗位名稱 * | deptFunc_positionTitle | positionTitle | select | **是** | 空值 | 根據部級單位變動 |
|
||||||
|
| 9 | 崗位級別 | deptFunc_positionLevel | positionLevel | select | 否 | 空值 | E, M, S, D, VP, C |
|
||||||
|
| 10 | 部門主管職稱 | deptManager | deptManager | text | 否 | 例如: 部門經理 | - |
|
||||||
|
| 11 | 生效日期 * | deptFunctionEffectiveDate | deptFunctionEffectiveDate | date | **是** | 空值 | - |
|
||||||
|
| 12 | 部門人數上限 | deptHeadcount | deptHeadcount | number | 否 | 例如: 50 | min=1 |
|
||||||
|
| 13 | 部門狀態 | deptStatus | deptStatus | select | 否 | active | active, inactive, planning |
|
||||||
|
| 14 | 部門使命 (Mission) | deptMission | deptMission | textarea | 否 | 空值 | rows=3;有範例提示 |
|
||||||
|
| 15 | 部門願景 (Vision) | deptVision | deptVision | textarea | 否 | 空值 | rows=3;有範例提示 |
|
||||||
|
| 16 | 核心職責 (Core Functions) * | deptCoreFunctions | deptCoreFunctions | textarea | **是** | 空值 | rows=6;有範例提示 |
|
||||||
|
| 17 | 關鍵績效指標 (KPIs) | deptKPIs | deptKPIs | textarea | 否 | 空值 | rows=4;有範例提示 |
|
||||||
|
| 18 | 協作部門 | deptCollaboration | deptCollaboration | textarea | 否 | 空值 | rows=3;有範例提示 |
|
||||||
|
| 19 | 備注 | deptFunctionRemark | deptFunctionRemark | textarea | 否 | 空值 | rows=3 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 崗位描述模組 (jobDescForm - tab-jobdesc-basic)
|
||||||
|
|
||||||
|
### 5.1 基本信息區塊
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | HTML元素ID | 資料庫欄位名稱 | 資料類型 | 是否必填 | 預設值 | 備註 |
|
||||||
|
|---|-----------|---------|------------|------|------|------|------|
|
||||||
|
| 1 | 工號 | jd_empNo | empNo | text | 否 | 空值 | 有員工搜索modal |
|
||||||
|
| 2 | 姓名 | jd_empName | empName | text | 否 | 自動帶出 | readonly |
|
||||||
|
| 3 | 崗位代碼 | jd_positionCode | positionCode | text | 否 | 空值 | - |
|
||||||
|
| 4 | 版本更新日期 | jd_versionDate | versionDate | date | 否 | 空值 | - |
|
||||||
|
|
||||||
|
### 5.2 崗位基本信息區塊
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | HTML元素ID | 資料庫欄位名稱 | 資料類型 | 是否必填 | 預設值 | 備註 |
|
||||||
|
|---|-----------|---------|------------|------|------|------|------|
|
||||||
|
| 1 | 崗位名稱 | jd_positionName | positionName | text | 否 | 空值 | - |
|
||||||
|
| 2 | 事業體 (Business Unit) | jd_businessUnit | businessUnit | select | 否 | 空值 | 聯動選擇 |
|
||||||
|
| 3 | 處級單位 (Division) | jd_division | division | select | 否 | 空值 | 聯動選擇 |
|
||||||
|
| 4 | 部級單位 (Department) | jd_department | department | select | 否 | 空值 | 聯動選擇 |
|
||||||
|
| 5 | 課級單位 (Section) | jd_section | section | text | 否 | 選填 | - |
|
||||||
|
| 6 | 崗位名稱 (重複) | jd_positionTitle | positionTitle | select | 否 | 空值 | 根據部級單位變動 |
|
||||||
|
| 7 | 崗位級別 | jd_positionLevel | positionLevel | select | 否 | 空值 | E, M, S, D, VP, C |
|
||||||
|
| 8 | 崗位生效日期 | jd_positionEffectiveDate | positionEffectiveDate | date | 否 | 空值 | - |
|
||||||
|
| 9 | 直接領導職務 | jd_directSupervisor | directSupervisor | text | 否 | 空值 | - |
|
||||||
|
| 10 | 崗位職等&職務 | jd_positionGradeJob | positionGradeJob | text | 否 | 點擊選擇 | readonly;有modal選擇器 |
|
||||||
|
| 11 | 匯報對象職務 | jd_reportTo | reportTo | text | 否 | 點擊選擇 | readonly;有modal選擇器 |
|
||||||
|
| 12 | 直接下級(職位及人數) | jd_directReports | directReports | text | 否 | 例:工程師 x 5人 | - |
|
||||||
|
| 13 | 任職地點 | jd_workLocation | workLocation | select | 否 | 空值 | HQ, TPE, TYC, KHH, SH, SZ |
|
||||||
|
| 14 | 員工屬性 | jd_empAttribute | empAttribute | select | 否 | 空值 | FT, CT, PT, IN, DP |
|
||||||
|
|
||||||
|
### 5.3 部門職責資訊區塊 (自動帶入,隱藏顯示)
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | HTML元素ID | 資料庫欄位名稱 | 資料類型 | 是否必填 | 預設值 | 備註 |
|
||||||
|
|---|-----------|---------|------------|------|------|------|------|
|
||||||
|
| 1 | 部門職責編號 | jd_deptFunctionCode | deptFunctionCode | text | 否 | 自動帶出 | readonly;id="deptFunctionInfoSection" |
|
||||||
|
| 2 | 事業體 | jd_deptFunctionBU | deptFunctionBU | text | 否 | 自動帶出 | readonly |
|
||||||
|
| 3 | 部門使命 | jd_deptMission | deptMission | textarea | 否 | 自動帶出 | readonly;rows=2 |
|
||||||
|
| 4 | 部門核心職責 | jd_deptCoreFunctions | deptCoreFunctions | textarea | 否 | 自動帶出 | readonly;rows=4 |
|
||||||
|
| 5 | 部門 KPIs | jd_deptKPIs | deptKPIs | textarea | 否 | 自動帶出 | readonly;rows=3 |
|
||||||
|
|
||||||
|
### 5.4 職責描述區塊
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | HTML元素ID | 資料庫欄位名稱 | 資料類型 | 是否必填 | 預設值 | 備註 |
|
||||||
|
|---|-----------|---------|------------|------|------|------|------|
|
||||||
|
| 1 | 崗位設置目的 | jd_positionPurpose | positionPurpose | text | 否 | 空值 | 有展開編輯按鈕 |
|
||||||
|
| 2 | 主要崗位職責 | jd_mainResponsibilities | mainResponsibilities | textarea | 否 | 空值 | rows=8;numbered-textarea;有數字編號 |
|
||||||
|
|
||||||
|
### 5.5 崗位要求區塊
|
||||||
|
|
||||||
|
| # | 欄位顯示名稱 | HTML元素ID | 資料庫欄位名稱 | 資料類型 | 是否必填 | 預設值 | 備註 |
|
||||||
|
|---|-----------|---------|------------|------|------|------|------|
|
||||||
|
| 1 | 教育程度 | jd_education | education | text | 否 | 例:大學本科及以上 | - |
|
||||||
|
| 2 | 基本技能 | jd_basicSkills | basicSkills | textarea | 否 | 空值 | rows=2;有展開編輯按鈕 |
|
||||||
|
| 3 | 專業知識 | jd_professionalKnowledge | professionalKnowledge | textarea | 否 | 空值 | rows=2;有展開編輯按鈕 |
|
||||||
|
| 4 | 工作經驗 | jd_workExperienceReq | workExperienceReq | textarea | 否 | 空值 | rows=2;有展開編輯按鈕 |
|
||||||
|
| 5 | 其他 | jd_otherRequirements | otherRequirements | textarea | 否 | 空值 | rows=3 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 崗位清單模組 (positionListTable)
|
||||||
|
|
||||||
|
### 6.1 表格列(只讀顯示)
|
||||||
|
|
||||||
|
| # | 列標題 | 資料鍵值 | 資料類型 | 可排序 | 備註 |
|
||||||
|
|---|------|--------|------|------|------|
|
||||||
|
| 1 | 崗位編號 | positionCode | text | 是 | 可點擊排序 |
|
||||||
|
| 2 | 崗位名稱 | positionName | text | 是 | 可點擊排序 |
|
||||||
|
| 3 | 崗位類別 | positionCategory | text | 是 | 可點擊排序 |
|
||||||
|
| 4 | 崗位性質 | positionNature | text | 是 | 可點擊排序 |
|
||||||
|
| 5 | 編制人數 | headcount | number | 是 | 可點擊排序 |
|
||||||
|
| 6 | 崗位等級 | positionLevel | text | 是 | 可點擊排序 |
|
||||||
|
| 7 | 生效日期 | effectiveDate | date | 是 | 可點擊排序 |
|
||||||
|
| 8 | 操作 | - | button | 否 | 編輯/刪除按鈕 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 數據結構對應關係
|
||||||
|
|
||||||
|
### Position (崗位基礎資料)
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
id: string,
|
||||||
|
basicInfo: {
|
||||||
|
positionCode: string,
|
||||||
|
positionName: string,
|
||||||
|
positionCategory: string,
|
||||||
|
positionCategoryName: string,
|
||||||
|
positionNature: string,
|
||||||
|
positionNatureName: string,
|
||||||
|
headcount: number,
|
||||||
|
positionLevel: string,
|
||||||
|
effectiveDate: date,
|
||||||
|
positionDesc: string,
|
||||||
|
positionRemark: string
|
||||||
|
},
|
||||||
|
recruitInfo: {
|
||||||
|
minEducation: string,
|
||||||
|
requiredGender: string,
|
||||||
|
salaryRange: string,
|
||||||
|
workExperience: number,
|
||||||
|
minAge: number,
|
||||||
|
maxAge: number,
|
||||||
|
jobType: string,
|
||||||
|
recruitPosition: string,
|
||||||
|
jobTitle: string,
|
||||||
|
jobDesc: string,
|
||||||
|
positionReq: string,
|
||||||
|
titleReq: string,
|
||||||
|
majorReq: string,
|
||||||
|
skillReq: string,
|
||||||
|
langReq: string,
|
||||||
|
otherReq: string,
|
||||||
|
superiorPosition: string,
|
||||||
|
recruitRemark: string
|
||||||
|
},
|
||||||
|
createdAt: datetime,
|
||||||
|
updatedAt: datetime
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Job (職務基礎資料)
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
id: string,
|
||||||
|
jobCategoryCode: string,
|
||||||
|
jobCategoryName: string,
|
||||||
|
jobCode: string,
|
||||||
|
jobName: string,
|
||||||
|
jobNameEn: string,
|
||||||
|
jobEffectiveDate: date,
|
||||||
|
jobHeadcount: number,
|
||||||
|
jobSortOrder: number,
|
||||||
|
jobRemark: string,
|
||||||
|
jobLevel: string,
|
||||||
|
hasAttendanceBonus: boolean,
|
||||||
|
hasHousingAllowance: boolean,
|
||||||
|
createdAt: datetime,
|
||||||
|
updatedAt: datetime
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### DeptFunction (部門職責)
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
deptFunctionCode: string,
|
||||||
|
deptFunctionName: string,
|
||||||
|
deptFunctionBU: string,
|
||||||
|
businessUnit: string,
|
||||||
|
division: string,
|
||||||
|
department: string,
|
||||||
|
section: string,
|
||||||
|
positionTitle: string,
|
||||||
|
positionLevel: string,
|
||||||
|
deptManager: string,
|
||||||
|
deptFunctionEffectiveDate: date,
|
||||||
|
deptHeadcount: number,
|
||||||
|
deptStatus: string,
|
||||||
|
deptMission: string,
|
||||||
|
deptVision: string,
|
||||||
|
deptCoreFunctions: string,
|
||||||
|
deptKPIs: string,
|
||||||
|
deptCollaboration: string,
|
||||||
|
deptFunctionRemark: string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### JobDescription (崗位描述)
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
basicInfo: {
|
||||||
|
empNo: string,
|
||||||
|
empName: string,
|
||||||
|
positionCode: string,
|
||||||
|
versionDate: date
|
||||||
|
},
|
||||||
|
positionInfo: {
|
||||||
|
positionName: string,
|
||||||
|
businessUnit: string,
|
||||||
|
division: string,
|
||||||
|
department: string,
|
||||||
|
section: string,
|
||||||
|
positionTitle: string,
|
||||||
|
positionLevel: string,
|
||||||
|
positionEffectiveDate: date,
|
||||||
|
directSupervisor: string,
|
||||||
|
positionGradeJob: string,
|
||||||
|
reportTo: string,
|
||||||
|
directReports: string,
|
||||||
|
workLocation: string,
|
||||||
|
empAttribute: string,
|
||||||
|
deptFunctionCode: string,
|
||||||
|
deptFunctionBU: string,
|
||||||
|
deptMission: string,
|
||||||
|
deptCoreFunctions: string,
|
||||||
|
deptKPIs: string
|
||||||
|
},
|
||||||
|
responsibilities: {
|
||||||
|
positionPurpose: string,
|
||||||
|
mainResponsibilities: string
|
||||||
|
},
|
||||||
|
requirements: {
|
||||||
|
education: string,
|
||||||
|
basicSkills: string,
|
||||||
|
professionalKnowledge: string,
|
||||||
|
workExperienceReq: string,
|
||||||
|
otherRequirements: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 關鍵特性總結
|
||||||
|
|
||||||
|
### 聯動選擇(Cascading Select)
|
||||||
|
- **事業體 → 處級單位 → 部級單位 → 課級單位**
|
||||||
|
- 在崗位基礎資料、部門職責、崗位描述中都有此聯動
|
||||||
|
- 觸發事件:onchange="onXXXBusinessUnitChange/onXXXDivisionChange" 等
|
||||||
|
|
||||||
|
### 自動帶出欄位 (readonly)
|
||||||
|
- 崗位類別名稱 (根據崗位類別自動帶出)
|
||||||
|
- 崗位性質名稱 (根據崗位性質自動帶出)
|
||||||
|
- 職務類別名稱 (根據職務類別編號自動帶出)
|
||||||
|
- 員工姓名 (根據工號自動帶出)
|
||||||
|
- 部門職責相關資訊 (自動帶入到崗位描述)
|
||||||
|
|
||||||
|
### Modal/模態框
|
||||||
|
- 專業要求選擇 (Major Modal - majorModal)
|
||||||
|
- 員工搜索 (EmpSearchModal)
|
||||||
|
- 組織搜索 (OrgSearchModal)
|
||||||
|
- 職等職務選擇 (GradeJobModal)
|
||||||
|
- 匯報對象選擇 (ReportToModal)
|
||||||
|
|
||||||
|
### CSV 操作
|
||||||
|
- 職務基礎資料支援: 下載範本、匯出、匯入
|
||||||
|
- 部門職責支援: 匯入、匯出
|
||||||
|
|
||||||
|
### 特殊欄位
|
||||||
|
- **敏感信息欄位**: jobLevel (職務層級) - 標記為 *保密*
|
||||||
|
- **布林值(Checkbox)**: hasAttendanceBonus, hasHousingAllowance
|
||||||
|
- **Toggle Switch**: 用於布林值的友善UI
|
||||||
|
|
||||||
|
### 表單驗證
|
||||||
|
- 必填欄位用 `<span class="required">*</span>` 標記
|
||||||
|
- HTML5 required 屬性用於部分欄位
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 變更紀錄
|
||||||
|
|
||||||
|
| 日期 | 版本 | 變更內容 |
|
||||||
|
|------|------|--------|
|
||||||
|
| 2025-12-05 | v1.0 | 初版完整表單欄位清單 |
|
||||||
Reference in New Issue
Block a user