// 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<EmployeeFullInfo>) {
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('更新员工失败,请重试');
}
}
}
<!-- yss-project/src/app/pages/admin/employees/employees.html -->
<!-- 原有内容保持不变... -->
<!-- 在文件末尾添加新的侧边栏组件 -->
<app-employee-info-panel
[visible]="showEmployeeInfoPanel"
[employee]="selectedEmployeeForPanel"
[departments]="departments()"
[roles]="roles"
(close)="closeEmployeeInfoPanel()"
(update)="updateEmployeeInfo($event)">
</app-employee-info-panel>
在表格操作按钮中添加:
<td>
<!-- 原有按钮 -->
<button class="btn-icon" (click)="viewEmployee(emp)" title="查看(原面板)">👁</button>
<button class="btn-icon" (click)="editEmployee(emp)" title="编辑">✏️</button>
<!-- 新增按钮:打开新的侧边栏 -->
<button class="btn-icon" (click)="viewEmployeeInfo(emp)" title="详细信息(新面板)">📋</button>
<button class="btn-icon" (click)="toggleEmployee(emp)" [title]="emp.isDisabled ? '启用' : '禁用'">
{{ emp.isDisabled ? '✓' : '🚫' }}
</button>
</td>
// 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<EmployeeCalendarData> {
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}个项目)`;
}
}
}
<!-- yss-project/src/app/pages/team-leader/dashboard/dashboard.html -->
<!-- 原有内容保持不变... -->
<!-- 在设计师卡片中添加按钮 -->
<div class="designer-card" *ngFor="let designer of designers">
<div class="designer-info">
<h3>{{ designer.name }}</h3>
<p>当前项目: {{ designer.currentProjects }}</p>
</div>
<div class="designer-actions">
<!-- 原有按钮 -->
<button (click)="viewDesignerDetail(designer)">查看(原面板)</button>
<!-- 新增按钮:打开新的侧边栏 -->
<button (click)="viewDesignerFullInfo(designer)">完整信息(新面板)</button>
</div>
</div>
<!-- 在文件末尾添加新的侧边栏组件 -->
<app-employee-info-panel
[visible]="showEmployeeInfoPanel"
[employee]="selectedDesignerForPanel"
[departments]="departments"
[roles]="['客服', '组员', '组长', '人事', '财务', '管理员']"
(close)="closeEmployeeInfoPanel()"
(update)="updateEmployeeInfo($event)"
(calendarMonthChange)="handleCalendarMonthChange($event)"
(projectClick)="handleProjectClick($event)"
(refreshSurvey)="handleRefreshSurvey()">
</app-employee-info-panel>
// 生成员工日历数据的辅助函数
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
};
}
shared/components 下创建组件# 组件文件已经创建在:
# yss-project/src/app/shared/components/employee-info-panel/
import { EmployeeInfoPanelComponent, EmployeeFullInfo } from '@shared/components/employee-info-panel';
@Component({
// ...
imports: [
CommonModule,
FormsModule,
EmployeeInfoPanelComponent // 添加这行
]
})
<app-employee-info-panel
[visible]="showPanel"
[employee]="selectedEmployee"
[departments]="departments"
(close)="handleClose()"
(update)="handleUpdate($event)">
</app-employee-info-panel>
employees.html 面板和 employee-detail-panel