日期: 2025-10-22 12:30 需求: 恢复点击甘特图中设计师时弹出详情面板的功能
原先的功能:点击甘特图中的设计师会弹出一个详情面板,显示:
在重新设计工作负载甘特图后,这个功能需要恢复。
位置: 第1793-1801行
// 添加点击事件:点击设计师行时显示详情
this.workloadGanttChart.on('click', (params: any) => {
if (params.componentType === 'series' && params.seriesType === 'custom') {
const designerName = params.value[3]; // value[3]是设计师名称
if (designerName && designerName !== '未分配') {
this.onEmployeeClick(designerName);
}
}
});
说明:
click 事件params.value[3] 提取设计师名称onEmployeeClick(designerName) 触发详情面板位置: 第1718-1737行
tooltip: {
formatter: (params: any) => {
const [yIndex, start, end, name, status, projectCount] = params.value;
const startDate = new Date(start);
const statusText = status === 'overload' ? '超负荷' :
status === 'busy' ? '忙碌' :
status === 'leave' ? '请假' : '空闲';
return `<div style="padding: 8px;">
<strong style="font-size: 16px; color: #1f2937;">${name}</strong><br/>
<div style="margin-top: 8px; color: #6b7280;">
📅 ${startDate.getMonth() + 1}月${startDate.getDate()}日<br/>
📊 状态: <span style="font-weight: 600; color: ${status === 'overload' ? '#dc2626' : status === 'busy' ? '#2563eb' : '#059669'};">${statusText}</span><br/>
🎯 项目数: ${projectCount}<br/>
<div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid #e5e7eb; color: #3b82f6; font-size: 12px;">
💡 点击查看详细信息
</div>
</div>
</div>`;
}
}
改进:
位置: 第563-574行
.gantt-container {
width: 100%;
height: 500px;
min-height: 400px;
cursor: pointer; // 提示可点击
// ECharts会覆盖cursor,所以在全局添加
canvas {
cursor: pointer !important;
}
}
说明:
cursor: pointer 让鼠标变为手型!important 覆盖 ECharts 的默认样式interface EmployeeDetail {
name: string;
currentProjects: number; // 当前负责项目数
projectNames: string[]; // 项目名称列表(用于显示)
leaveRecords: LeaveRecord[]; // 未来7天请假记录
redMarkExplanation: string; // 红色标记说明
}
onEmployeeClick(employeeName: string): void {
if (!employeeName || employeeName === '未分配') {
return;
}
// 生成员工详情数据
this.selectedEmployeeDetail = this.generateEmployeeDetail(employeeName);
this.showEmployeeDetailPanel = true;
}
private generateEmployeeDetail(employeeName: string): EmployeeDetail {
// 获取该员工负责的项目
const employeeProjects = this.filteredProjects.filter(p => p.designerName === employeeName);
const currentProjects = employeeProjects.length;
const projectNames = employeeProjects.slice(0, 3).map(p => p.name);
// 获取该员工的请假记录(未来7天)
const today = new Date();
const next7Days = Array.from({ length: 7 }, (_, i) => {
const date = new Date(today);
date.setDate(date.getDate() + i);
const dateStr = date.toISOString().split('T')[0];
// 查找该日期的请假记录
const leaveRecord = this.leaveRecords.find(
r => r.employeeName === employeeName && r.date === dateStr
);
return leaveRecord || {
id: `${employeeName}-${i}`,
employeeName,
date: dateStr,
isLeave: false
};
});
// 生成红色标记说明
let redMarkExplanation = '';
if (currentProjects >= 3) {
redMarkExplanation = '⚠️ 当前负载较高,建议合理调配任务';
}
return {
name: employeeName,
currentProjects,
projectNames,
leaveRecords: next7Days,
redMarkExplanation
};
}
closeEmployeeDetailPanel(): void {
this.showEmployeeDetailPanel = false;
this.selectedEmployeeDetail = null;
}
面板包含两个主要部分:
+N 标记private leaveRecords: LeaveRecord[] = [
{ id: '1', employeeName: '张三', date: '2024-01-20', isLeave: true, leaveType: 'personal', reason: '事假' },
{ id: '2', employeeName: '张三', date: '2024-01-21', isLeave: false },
{ id: '3', employeeName: '李四', date: '2024-01-22', isLeave: true, leaveType: 'sick', reason: '病假' },
{ id: '4', employeeName: '王五', date: '2024-01-23', isLeave: true, leaveType: 'annual', reason: '年假' }
];
getLeaveTypeText(leaveType?: string): string {
const typeMap: Record<string, string> = {
'annual': '年假',
'sick': '病假',
'personal': '事假',
'compensatory': '调休',
'marriage': '婚假',
'maternity': '产假',
'paternity': '陪产假',
'other': '其他'
};
return typeMap[leaveType || ''] || '其他';
}
用户操作流程:
1. 用户打开团队长工作台
2. 查看"工作负载概览"甘特图
3. 鼠标悬浮在某个设计师的时间块上
→ 显示 Tooltip:设计师名、日期、状态、项目数、点击提示
4. 点击时间块
→ 触发 onEmployeeClick(designerName)
→ 生成 EmployeeDetail 数据
→ 显示员工详情面板
5. 查看详情:
- 负载概况:项目数、项目列表
- 请假明细:未来7天的请假情况表格
6. 点击面板外或关闭按钮
→ 面板关闭
建议创建 LeaveRecord 表并从 Parse Server 查询:
async loadLeaveRecords(): Promise<void> {
const Parse = await this.ensureParse();
if (!Parse) return;
try {
const query = new Parse.Query('LeaveRecord');
query.equalTo('company', this.cid);
// 查询未来7天的请假记录
const today = new Date();
const next7Days = new Date();
next7Days.setDate(today.getDate() + 7);
query.greaterThanOrEqualTo('date', today);
query.lessThan('date', next7Days);
query.equalTo('status', 'approved'); // 只显示已批准的请假
const records = await query.find();
this.leaveRecords = records.map(r => ({
id: r.id,
employeeName: r.get('designer')?.get('name') || '',
date: r.get('date')?.toISOString().split('T')[0] || '',
isLeave: true,
leaveType: r.get('type'),
reason: r.get('reason')
}));
console.log('✅ 加载请假记录成功:', this.leaveRecords.length);
} catch (error) {
console.error('❌ 加载请假记录失败:', error);
}
}
| 文件 | 变更内容 |
|---|---|
dashboard.ts |
添加工作负载甘特图点击事件,增强Tooltip |
dashboard-new-styles.scss |
添加鼠标样式提示 |
dashboard.html |
无需修改(面板已存在) |
┌─────────────────────────────────┐
│ 张三 │
├─────────────────────────────────┤
│ 📅 10月23日 │
│ 📊 状态: 忙碌 (蓝色) │
│ 🎯 项目数: 2 │
│ ─────────────────────────────── │
│ 💡 点击查看详细信息 │
└─────────────────────────────────┘
┌────────────────────────────────────┐
│ 👤 张三 详情 ✕ │
├────────────────────────────────────┤
│ 📋 负载概况 │
│ 当前负责项目数: 2 个 │
│ 核心项目: │
│ ┌──────────┬──────────┬───────┐ │
│ │现代客厅 │轻奢卧室 │ │ │
│ └──────────┴──────────┴───────┘ │
│ │
│ 📅 请假明细(未来7天) │
│ ┌─────┬──────┬────────┐ │
│ │日期 │状态 │备注 │ │
│ ├─────┼──────┼────────┤ │
│ │10/23│正常 │- │ │
│ │10/24│请假 │年假 │ │
│ │10/25│正常 │- │ │
│ └─────┴──────┴────────┘ │
└────────────────────────────────────┘
实施完成时间: 2025-10-22 12:30 状态: ✅ 已完成并测试通过