# 员工信息侧边栏组件使用示例 ## 在管理员端(Admin)使用 ```typescript // yss-project/src/app/pages/admin/employees/employees.ts import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { EmployeeInfoPanelComponent, EmployeeFullInfo } from '../../../shared/components/employee-info-panel'; import { EmployeeService } from '../services/employee.service'; import { DepartmentService } from '../services/department.service'; @Component({ selector: 'app-employees', standalone: true, imports: [ CommonModule, FormsModule, EmployeeInfoPanelComponent // 导入新组件 ], templateUrl: './employees.html', styleUrls: ['./employees.scss'] }) export class Employees { // 原有代码保持不变... employees = []; departments = []; // 新增:员工信息面板状态 showEmployeeInfoPanel = false; selectedEmployeeForPanel: EmployeeFullInfo | null = null; constructor( private employeeService: EmployeeService, private departmentService: DepartmentService ) {} // 点击查看按钮时,打开新的侧边栏 viewEmployeeInfo(emp: Employee) { // 将员工数据转换为 EmployeeFullInfo 格式 this.selectedEmployeeForPanel = { id: emp.id, name: emp.name, realname: emp.realname, mobile: emp.mobile, userid: emp.userid, roleName: emp.roleName, department: emp.department, departmentId: emp.departmentId, isDisabled: emp.isDisabled, createdAt: emp.createdAt, avatar: emp.avatar, email: emp.email, position: emp.position, gender: emp.gender, level: emp.level, skills: emp.skills, joinDate: emp.joinDate, workload: emp.workload }; this.showEmployeeInfoPanel = true; } // 关闭侧边栏 closeEmployeeInfoPanel() { this.showEmployeeInfoPanel = false; this.selectedEmployeeForPanel = null; } // 更新员工信息 async updateEmployeeInfo(updates: Partial) { try { await this.employeeService.updateEmployee(updates.id!, { name: updates.name, mobile: updates.mobile, roleName: updates.roleName, departmentId: updates.departmentId, isDisabled: updates.isDisabled, data: { realname: updates.realname } }); // 重新加载员工列表 await this.loadEmployees(); // 关闭面板 this.closeEmployeeInfoPanel(); alert('员工信息更新成功!'); } catch (error) { console.error('更新员工失败:', error); alert('更新员工失败,请重试'); } } } ``` ```html ``` 在表格操作按钮中添加: ```html ``` ## 在设计师组长端(Team Leader)使用 ```typescript // yss-project/src/app/pages/team-leader/dashboard/dashboard.ts import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; import { EmployeeInfoPanelComponent, EmployeeFullInfo, EmployeeCalendarData } from '../../../shared/components/employee-info-panel'; import { DesignerService } from '../services/designer.service'; @Component({ selector: 'app-dashboard', standalone: true, imports: [ CommonModule, EmployeeInfoPanelComponent // 导入新组件 ], templateUrl: './dashboard.html', styleUrls: ['./dashboard.scss'] }) export class Dashboard { // 原有代码... designers = []; departments = []; // 新增:员工信息面板状态 showEmployeeInfoPanel = false; selectedDesignerForPanel: EmployeeFullInfo | null = null; constructor( private designerService: DesignerService, private router: Router ) {} // 点击设计师时,打开新的侧边栏(包含项目负载信息) async viewDesignerFullInfo(designer: any) { // 查询设计师的项目负载信息 const projects = await this.loadDesignerProjects(designer.id); const calendarData = await this.loadDesignerCalendar(designer.id); const leaveRecords = await this.loadLeaveRecords(designer.id); const surveyData = await this.loadEmployeeSurvey(designer.id); // 构建完整的员工信息 this.selectedDesignerForPanel = { // 基本信息 id: designer.id, name: designer.name, realname: designer.realname, mobile: designer.mobile, userid: designer.userid, roleName: designer.roleName || '组员', department: designer.department, departmentId: designer.departmentId, isDisabled: designer.isDisabled, createdAt: designer.createdAt, avatar: designer.avatar, email: designer.email, position: designer.position, gender: designer.gender, level: designer.level, skills: designer.skills, joinDate: designer.joinDate, workload: designer.workload, // 项目负载信息 currentProjects: projects.length, projectNames: projects.map(p => p.name), projectData: projects.map(p => ({ id: p.id, name: p.name })), calendarData: calendarData, leaveRecords: leaveRecords, redMarkExplanation: this.getRedMarkExplanation(designer, projects.length), // 能力问卷 surveyCompleted: !!surveyData, surveyData: surveyData, profileId: designer.profileId }; this.showEmployeeInfoPanel = true; } // 关闭侧边栏 closeEmployeeInfoPanel() { this.showEmployeeInfoPanel = false; this.selectedDesignerForPanel = null; } // 切换月份 async handleCalendarMonthChange(direction: number) { if (!this.selectedDesignerForPanel) return; const currentMonth = this.selectedDesignerForPanel.calendarData!.currentMonth; const newMonth = new Date(currentMonth); newMonth.setMonth(newMonth.getMonth() + direction); // 重新加载该月的日历数据 const newCalendarData = await this.loadDesignerCalendar( this.selectedDesignerForPanel.id, newMonth ); // 更新日历数据 this.selectedDesignerForPanel = { ...this.selectedDesignerForPanel, calendarData: newCalendarData }; } // 点击项目 handleProjectClick(projectId: string) { // 跳转到项目详情页 this.router.navigate(['/project-detail', projectId]); } // 刷新问卷 async handleRefreshSurvey() { if (!this.selectedDesignerForPanel) return; try { const surveyData = await this.loadEmployeeSurvey(this.selectedDesignerForPanel.id); this.selectedDesignerForPanel = { ...this.selectedDesignerForPanel, surveyCompleted: !!surveyData, surveyData: surveyData }; } catch (error) { console.error('刷新问卷失败:', error); } } // 辅助方法:加载设计师项目 private async loadDesignerProjects(designerId: string) { // 实现查询逻辑 return []; } // 辅助方法:加载设计师日历 private async loadDesignerCalendar(designerId: string, month?: Date): Promise { const targetMonth = month || new Date(); // 实现查询逻辑,生成日历数据 return { currentMonth: targetMonth, days: [] // 生成日历天数数据 }; } // 辅助方法:加载请假记录 private async loadLeaveRecords(designerId: string) { // 实现查询逻辑 return []; } // 辅助方法:加载员工问卷 private async loadEmployeeSurvey(designerId: string) { // 实现查询逻辑 return null; } // 辅助方法:生成红色标记说明 private getRedMarkExplanation(designer: any, projectCount: number): string { if (projectCount >= 5) { return `${designer.name}当前负载过高(${projectCount}个项目),建议暂缓分配新项目`; } else if (projectCount >= 3) { return `${designer.name}当前负载较高(${projectCount}个项目),可分配轻量级项目`; } else { return `${designer.name}当前负载正常(${projectCount}个项目)`; } } } ``` ```html

{{ designer.name }}

当前项目: {{ designer.currentProjects }}

``` ## 日历数据生成示例 ```typescript // 生成员工日历数据的辅助函数 function generateEmployeeCalendar( targetMonth: Date, projects: Array<{ id: string; name: string; startDate: Date; endDate: Date }> ): EmployeeCalendarData { const days: EmployeeCalendarDay[] = []; // 获取当月第一天和最后一天 const firstDay = new Date(targetMonth.getFullYear(), targetMonth.getMonth(), 1); const lastDay = new Date(targetMonth.getFullYear(), targetMonth.getMonth() + 1, 0); // 获取第一天是星期几(0-6,0是周日) const firstDayOfWeek = firstDay.getDay(); // 获取上个月需要显示的天数 const prevMonthDays = firstDayOfWeek; const prevMonthLastDay = new Date(targetMonth.getFullYear(), targetMonth.getMonth(), 0).getDate(); // 添加上个月的天数 for (let i = prevMonthDays - 1; i >= 0; i--) { const date = new Date( targetMonth.getFullYear(), targetMonth.getMonth() - 1, prevMonthLastDay - i ); days.push({ date, projectCount: 0, projects: [], isToday: false, isCurrentMonth: false }); } // 添加当月的天数 for (let day = 1; day <= lastDay.getDate(); day++) { const date = new Date(targetMonth.getFullYear(), targetMonth.getMonth(), day); const today = new Date(); today.setHours(0, 0, 0, 0); // 查找该日期有哪些项目 const dayProjects = projects.filter(p => { return date >= p.startDate && date <= p.endDate; }); days.push({ date, projectCount: dayProjects.length, projects: dayProjects.map(p => ({ id: p.id, name: p.name, deadline: p.endDate })), isToday: date.getTime() === today.getTime(), isCurrentMonth: true }); } // 添加下个月的天数(填充到42格,6行x7列) const remainingDays = 42 - days.length; for (let day = 1; day <= remainingDays; day++) { const date = new Date( targetMonth.getFullYear(), targetMonth.getMonth() + 1, day ); days.push({ date, projectCount: 0, projects: [], isToday: false, isCurrentMonth: false }); } return { currentMonth: targetMonth, days }; } ``` ## 完整示例:集成到现有项目 ### 步骤1:在 `shared/components` 下创建组件 ```bash # 组件文件已经创建在: # yss-project/src/app/shared/components/employee-info-panel/ ``` ### 步骤2:在需要使用的页面导入 ```typescript import { EmployeeInfoPanelComponent, EmployeeFullInfo } from '@shared/components/employee-info-panel'; ``` ### 步骤3:添加到 imports 数组 ```typescript @Component({ // ... imports: [ CommonModule, FormsModule, EmployeeInfoPanelComponent // 添加这行 ] }) ``` ### 步骤4:在模板中使用 ```html ``` ## 注意事项 1. **不影响原有功能**:新组件是独立的,不会影响原有的 `employees.html` 面板和 `employee-detail-panel` 2. **按需使用**:可以只在需要展示完整信息的地方使用新组件 3. **数据灵活**:基本信息是必填的,项目负载信息是可选的 4. **样式独立**:新组件有自己的样式,不会影响原有样式 ## 渐进式迁移建议 1. **阶段1**:先在一个页面测试(如管理员端),只使用基本信息功能 2. **阶段2**:逐步添加项目负载数据,测试组长端功能 3. **阶段3**:验证无误后,可以考虑在其他页面也使用此组件 4. **阶段4**(可选):如果新组件完全满足需求,可以考虑废弃旧的面板组件