# HR Portal Phase 1.3 完成報告 **階段**: Phase 1.3 - 前端專案架構 (React + TypeScript + Tailwind) **完成日期**: 2026-02-15 **狀態**: ✅ 完成 --- ## 📋 執行摘要 完成 HR Portal 前端架構的擴展,為 Phase 1.2 新增的郵件帳號管理和系統權限管理功能建立完整的前端支援。所有類型定義和服務層都已更新,確保與後端 API 完全對接。 --- ## ✅ 完成項目 ### 1. 類型定義更新 (TypeScript Types) **檔案**: [`types/index.ts`](frontend/types/index.ts) #### 郵件帳號類型 ```typescript // 更新為符合後端 API 結構 export interface EmailAccount extends BaseEntity { tenant_id: number employee_id: number email_address: string quota_mb: number forward_to?: string | null auto_reply?: string | null is_active: boolean employee_name?: string employee_number?: string } export interface CreateEmailAccountInput { employee_id: number email_address: string quota_mb?: number forward_to?: string auto_reply?: string is_active?: boolean } export interface UpdateEmailAccountInput { quota_mb?: number forward_to?: string | null auto_reply?: string | null is_active?: boolean } export interface EmailAccountQuotaUpdate { quota_mb: number } ``` #### 系統權限類型 (新增) ```typescript export type SystemName = 'gitea' | 'portainer' | 'traefik' | 'keycloak' export type AccessLevel = 'admin' | 'user' | 'readonly' export interface Permission extends BaseEntity { tenant_id: number employee_id: number system_name: SystemName access_level: AccessLevel granted_at: string granted_by?: number | null employee_name?: string employee_number?: string granted_by_name?: string } export interface CreatePermissionInput { employee_id: number system_name: SystemName access_level: AccessLevel granted_by?: number } export interface UpdatePermissionInput { access_level: AccessLevel granted_by?: number } export interface PermissionBatchCreateInput { employee_id: number permissions: Array<{ system_name: SystemName access_level: AccessLevel }> granted_by?: number } export interface SystemInfo { systems: SystemName[] access_levels: AccessLevel[] system_descriptions: Record access_level_descriptions: Record } ``` ### 2. 服務層建立 (Service Layer) #### 郵件帳號服務 **檔案**: [`services/email-accounts.ts`](frontend/services/email-accounts.ts) **提供的方法**: - `list(params?)` - 獲取郵件帳號列表 (支援分頁、篩選、搜尋) - `get(id)` - 獲取郵件帳號詳情 - `create(data)` - 創建郵件帳號 - `update(id, data)` - 更新郵件帳號 - `updateQuota(id, data)` - 更新郵件配額 - `delete(id)` - 停用郵件帳號 (軟刪除) - `getByEmployee(employeeId)` - 獲取員工的所有郵件帳號 **查詢參數**: ```typescript interface EmailAccountListParams { page?: number page_size?: number employee_id?: number is_active?: boolean search?: string } ``` #### 系統權限服務 **檔案**: [`services/permissions.ts`](frontend/services/permissions.ts) **提供的方法**: - `list(params?)` - 獲取權限列表 (支援分頁、篩選) - `get(id)` - 獲取權限詳情 - `create(data)` - 創建權限 - `update(id, data)` - 更新權限 - `delete(id)` - 刪除權限 - `getByEmployee(employeeId)` - 獲取員工的所有系統權限 - `batchCreate(data)` - 批量創建權限 - `getSystems()` - 獲取可授權的系統列表 **查詢參數**: ```typescript interface PermissionListParams { page?: number page_size?: number employee_id?: number system_name?: SystemName access_level?: AccessLevel } ``` ### 3. 現有架構確認 #### 技術棧 ✅ - **Next.js** 15.5.12 - React 框架 - **React** 19.2.3 - UI 函式庫 - **TypeScript** 5.x - 型別系統 - **Tailwind CSS** 4.x - CSS 框架 - **React Query** 5.90.21 - 資料獲取與快取 - **Axios** 1.13.5 - HTTP 客戶端 - **Keycloak JS** 26.2.3 - SSO 認證 - **NextAuth** 4.24.11 - 認證框架 #### 目錄結構 ✅ ``` frontend/ ├── app/ # Next.js App Router │ ├── api/ # API 路由 │ ├── auth/ # 認證頁面 │ ├── dashboard/ # 儀表板 │ ├── employees/ # 員工管理 │ ├── departments/ # 部門管理 │ └── business-units/ # 事業部管理 ├── components/ # React 元件 │ ├── auth/ # 認證元件 │ ├── employees/ # 員工元件 │ ├── layout/ # 佈局元件 │ └── ui/ # UI 元件 ├── hooks/ # React Hooks ├── lib/ # 工具函式庫 │ ├── api-client.ts # API 客戶端 │ └── auth.ts # 認證工具 ├── services/ # API 服務層 │ ├── employees.ts # 員工服務 │ ├── departments.ts # 部門服務 │ ├── business-units.ts # 事業部服務 │ ├── email-accounts.ts # 郵件帳號服務 ✨ 新增 │ └── permissions.ts # 系統權限服務 ✨ 新增 ├── types/ # TypeScript 類型定義 │ └── index.ts # 主要類型定義 (已更新) ├── .env.local # 環境變數配置 ├── package.json # 專案配置 └── tsconfig.json # TypeScript 配置 ``` #### API 客戶端 ✅ **檔案**: [`lib/api-client.ts`](frontend/lib/api-client.ts) **功能**: - 統一的 API 請求管理 - 自動 Token 注入 (Bearer) - 請求/回應攔截器 - 401 自動導向登入 - 支援所有 HTTP 方法 (GET, POST, PUT, PATCH, DELETE) **配置**: - Base URL: `http://localhost:10181/api/v1` (開發環境) - Timeout: 30 秒 - Content-Type: `application/json` #### 環境配置 ✅ **檔案**: [`.env.local`](frontend/.env.local) ```bash # API 配置 NEXT_PUBLIC_API_URL=http://localhost:10181 NEXT_PUBLIC_API_BASE_URL=http://localhost:10181/api/v1 # Keycloak 配置 (開發環境) NEXT_PUBLIC_KEYCLOAK_URL=https://auth.lab.taipei NEXT_PUBLIC_KEYCLOAK_REALM=porscheworld NEXT_PUBLIC_KEYCLOAK_CLIENT_ID=hr-portal-web KEYCLOAK_CLIENT_SECRET=HdQMzecymLixWDJ1dgdH0Ql5rEVU1S5S # NextAuth 配置 NEXTAUTH_URL=http://localhost:10180 NEXTAUTH_SECRET=ddyW9zuy7sHDMF8HRh60gEoiGBh698Ew6XHKenwp2c0= # 環境 NEXT_PUBLIC_ENVIRONMENT=development ``` --- ## 🏗️ 架構特色 ### 型別安全 - 完整的 TypeScript 型別定義 - 與後端 API 完全對應 - 編譯時型別檢查 ### 服務層分離 - 清晰的關注點分離 - 可重用的 API 呼叫 - 易於測試和維護 ### React Query 整合 (現有) - 自動快取管理 - 背景資料更新 - 樂觀更新支援 ### 錯誤處理 - API 攔截器統一處理 - 401 自動導向登入 - 詳細的錯誤訊息 --- ## 📊 統計數據 ### 新增程式碼 - **新增檔案**: 2 個 - `services/email-accounts.ts` (~75 行) - `services/permissions.ts` (~90 行) - **更新檔案**: 1 個 - `types/index.ts` (+85 行) ### 類型定義 - **EmailAccount 類型**: 4 個介面 - **Permission 類型**: 6 個介面 + 2 個類型別名 - **總計新增**: 10 個類型定義 ### 服務方法 - **郵件帳號服務**: 7 個方法 - **系統權限服務**: 8 個方法 - **總計**: 15 個服務方法 --- ## 🔧 技術棧總覽 ### 核心框架 - **Next.js** 15.5.12 - React 全端框架 - **React** 19.2.3 - UI 函式庫 - **TypeScript** 5.x - 靜態型別系統 ### 樣式 - **Tailwind CSS** 4.x - Utility-first CSS 框架 - **PostCSS** - CSS 處理工具 ### 資料管理 - **React Query** (@tanstack/react-query) 5.90.21 - 伺服器狀態管理 - **Axios** 1.13.5 - HTTP 客戶端 ### 認證 - **Keycloak JS** 26.2.3 - SSO 客戶端 - **NextAuth.js** 4.24.11 - 認證框架 --- ## 🎯 與後端 API 對接 ### 端點對應 #### 郵件帳號管理 | 前端方法 | HTTP | 後端端點 | 說明 | |---------|------|---------|------| | `list()` | GET | `/api/v1/email-accounts` | 列表查詢 | | `get(id)` | GET | `/api/v1/email-accounts/{id}` | 詳情查詢 | | `create()` | POST | `/api/v1/email-accounts` | 創建帳號 | | `update()` | PUT | `/api/v1/email-accounts/{id}` | 更新帳號 | | `updateQuota()` | PATCH | `/api/v1/email-accounts/{id}/quota` | 更新配額 | | `delete()` | DELETE | `/api/v1/email-accounts/{id}` | 停用帳號 | | `getByEmployee()` | GET | `/api/v1/email-accounts/employees/{id}/email-accounts` | 員工帳號 | #### 系統權限管理 | 前端方法 | HTTP | 後端端點 | 說明 | |---------|------|---------|------| | `list()` | GET | `/api/v1/permissions` | 列表查詢 | | `get(id)` | GET | `/api/v1/permissions/{id}` | 詳情查詢 | | `create()` | POST | `/api/v1/permissions` | 創建權限 | | `update()` | PUT | `/api/v1/permissions/{id}` | 更新權限 | | `delete()` | DELETE | `/api/v1/permissions/{id}` | 刪除權限 | | `getByEmployee()` | GET | `/api/v1/permissions/employees/{id}/permissions` | 員工權限 | | `batchCreate()` | POST | `/api/v1/permissions/batch` | 批量創建 | | `getSystems()` | GET | `/api/v1/permissions/systems` | 系統列表 | --- ## 📝 使用範例 ### 郵件帳號服務使用 ```typescript import { emailAccountsService } from '@/services/email-accounts' // 獲取郵件帳號列表 const accounts = await emailAccountsService.list({ page: 1, page_size: 20, employee_id: 1, is_active: true, }) // 創建郵件帳號 const newAccount = await emailAccountsService.create({ employee_id: 1, email_address: 'porsche.chen@porscheworld.tw', quota_mb: 5120, // 5GB }) // 更新配額 const updated = await emailAccountsService.updateQuota(1, { quota_mb: 10240, // 10GB }) ``` ### 系統權限服務使用 ```typescript import { permissionsService } from '@/services/permissions' // 獲取員工的所有權限 const permissions = await permissionsService.getByEmployee(1) // 批量授予權限 const newPermissions = await permissionsService.batchCreate({ employee_id: 1, permissions: [ { system_name: 'gitea', access_level: 'user' }, { system_name: 'portainer', access_level: 'readonly' }, ], granted_by: 2, }) // 獲取系統列表 const systemInfo = await permissionsService.getSystems() console.log(systemInfo.systems) // ['gitea', 'portainer', 'traefik', 'keycloak'] ``` ### React Query 整合範例 ```typescript import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { emailAccountsService } from '@/services/email-accounts' // 查詢鉤子 function useEmailAccounts(params) { return useQuery({ queryKey: ['email-accounts', params], queryFn: () => emailAccountsService.list(params), }) } // 變更鉤子 function useCreateEmailAccount() { const queryClient = useQueryClient() return useMutation({ mutationFn: emailAccountsService.create, onSuccess: () => { // 重新獲取列表 queryClient.invalidateQueries({ queryKey: ['email-accounts'] }) }, }) } // 元件中使用 function EmailAccountList() { const { data, isLoading, error } = useEmailAccounts({ page: 1 }) const createMutation = useCreateEmailAccount() if (isLoading) return
載入中...
if (error) return
錯誤: {error.message}
return (
{data?.items.map(account => (
{account.email_address}
))}
) } ``` --- ## 🧪 待開發項目 (Phase 2) ### UI 元件開發 - [ ] 郵件帳號列表元件 - [ ] 郵件帳號表單元件 (創建/編輯) - [ ] 配額更新對話框 - [ ] 系統權限列表元件 - [ ] 權限授予表單元件 - [ ] 批量權限授予元件 ### 頁面開發 - [ ] `/email-accounts` - 郵件帳號管理頁面 - [ ] `/permissions` - 系統權限管理頁面 - [ ] `/employees/[id]/email-accounts` - 員工郵件帳號頁面 - [ ] `/employees/[id]/permissions` - 員工權限頁面 ### React Hooks - [ ] `useEmailAccounts` - 郵件帳號查詢 - [ ] `useCreateEmailAccount` - 創建郵件帳號 - [ ] `useUpdateEmailAccount` - 更新郵件帳號 - [ ] `usePermissions` - 權限查詢 - [ ] `useCreatePermission` - 創建權限 - [ ] `useBatchCreatePermissions` - 批量創建權限 ### 表單驗證 - [ ] Email 格式驗證 - [ ] 配額範圍驗證 (1GB-100GB) - [ ] 系統名稱驗證 - [ ] 權限層級驗證 --- ## 💡 開發建議 ### 命名規範 - 元件名稱: PascalCase (如 `EmailAccountList`) - 檔案名稱: kebab-case (如 `email-account-list.tsx`) - 服務方法: camelCase (如 `getByEmployee`) ### 程式碼組織 - 將相關元件放在同一目錄 - 使用 barrel exports (index.ts) - 保持元件單一職責 ### 效能優化 - 使用 React.memo 避免不必要的重渲染 - 使用 useCallback/useMemo 快取函式和值 - 實作虛擬滾動處理大列表 ### 錯誤處理 - 使用 Error Boundary 捕捉元件錯誤 - 顯示友善的錯誤訊息 - 提供重試機制 --- ## 📚 下一步 (Phase 1.4) ### Keycloak SSO 深度整合 - [ ] 完善 Keycloak 認證流程 - [ ] 實作角色與權限檢查 - [ ] 整合 Keycloak 使用者資訊 - [ ] 設定自動 Token 刷新 --- ## 📋 檢查清單 - [x] TypeScript 類型定義更新 - [x] 郵件帳號服務建立 - [x] 系統權限服務建立 - [x] API 客戶端確認 - [x] 環境配置確認 - [x] 與後端 API 對接規劃 - [ ] UI 元件開發 (Phase 2) - [ ] 頁面路由建立 (Phase 2) - [ ] React Hooks 建立 (Phase 2) - [ ] 單元測試 (Phase 2) - [ ] E2E 測試 (Phase 2) --- ## 🎯 結論 Phase 1.3 成功完成了前端專案架構的擴展,為 Phase 1.2 新增的後端功能建立了完整的前端支援。所有的類型定義和服務層都已就緒,確保前後端完全對接。 現有的技術棧(Next.js 15 + React 19 + TypeScript + Tailwind CSS)提供了強大的開發基礎,配合 React Query 和 Axios,可以高效地開發出現代化的單頁應用。 **準備進入 Phase 1.4**: Keycloak SSO 整合 --- **報告產出日期**: 2026-02-15 **撰寫者**: Claude AI **審核者**: (待填寫)