<app-designer-team-assignment-modal
[visible]="showTeamAssignmentModal"
[loadRealData]="true" ← ✅ 新增:启用真实数据加载
[projectId]="selectedProject?.id || ''" ← ✅ 新增:传递项目ID(关键!)
[loadRealSpaces]="false" ← ✅ 新增:禁用空间加载(项目管理端不需要)
[enableSpaceAssignment]="false" ← ✅ 新增:禁用空间分配(项目管理端不需要)
[projectTeams]="projectTeams"
[selectedTeamId]="currentTeamAssignment.primaryTeamId"
[selectedDesigners]="currentTeamAssignment.quotationAssignments"
[crossTeamCollaborators]="currentTeamAssignment.crossTeamCollaborators"
[quotationItems]="currentQuotationItems"
[calendarViewMode]="'month'"
(close)="closeTeamAssignmentModal()"
(confirm)="confirmTeamAssignment($event)"
></app-designer-team-assignment-modal>
openTeamAssignmentModal(project: Project): void {
this.selectedProject = project;
// ✅ 修改:不再使用模拟数据,让弹窗组件自动加载真实数据
// ❌ 旧代码:this.projectTeams = this.mockProjectTeams;
this.projectTeams = []; // 空数组,让弹窗自动加载
this.currentTeamAssignment = {
primaryTeamId: project.assigneeId || null,
quotationAssignments: [],
crossTeamCollaborators: []
};
this.currentQuotationItems = [];
this.showTeamAssignmentModal = true;
// ✅ 新增:详细的日志输出
console.log('✅ [项目管理] 打开团队分配弹窗:', {
projectId: project.id,
projectTitle: project.title,
currentAssignee: project.assignee
});
}
npm start
访问:http://localhost:4200/admin/project-management
找到项目列表中的任意项目,点击操作列的"分配设计师"按钮。
打开浏览器开发者工具(F12),查看 Console 面板,应该看到以下日志:
✅ [项目管理] 打开团队分配弹窗: {
projectId: "abc123",
projectTitle: "某某项目",
currentAssignee: "张三"
}
🚀 [设计师分配弹窗] 初始化,loadRealData: true
成功加载项目组数据: (3) [{…}, {…}, {…}]
═════════════════════════════════════════════════════════════════════════════
🚀🚀🚀 [项目数据加载] ===== 开始加载所有成员的项目分配 =====
═════════════════════════════════════════════════════════════════════════════
📊 [项目数据加载] 总成员数: 6
📊 [项目数据加载] 成员列表: 张佳乐, 未知设计师, 江集, 李明, 王芳, 赵磊
🔍 [项目数据加载] 目标成员 IDs:
- 张佳乐 (ID: designer-1)
- 未知设计师 (ID: designer-2)
- 江集 (ID: designer-3)
...
✅ [项目数据加载] ProjectTeam 查询成功!
📊 [项目数据加载] 查询结果: 8 条记录
📋 [ProjectTeam 记录详情]
1. Profile: 张佳乐 (designer-1)
Project: 某某项目 (project-1)
状态: 进行中, 阶段: 建模
2. Profile: 张佳乐 (designer-1)
Project: 另一个项目 (project-2)
状态: 进行中, 阶段: 渲染
...
📊 [项目数据加载] 查询阶段完成,开始处理数据...
🔍 [张佳乐] Member ID: designer-1
从 profileIdToProjects 获取到 3 个项目
📋 项目详情:
1. 某某项目 (状态: 进行中, 阶段: 建模)
2. 另一个项目 (状态: 进行中, 阶段: 渲染)
3. 第三个项目 (状态: 进行中, 阶段: 方案深化)
✅ 已设置 currentProjects(所有项目) = 3
🟠 [张佳乐] 3个项目 - 有项目 (工作量:60%, 闲置:0天)
🔍 [未知设计师] Member ID: designer-2
从 profileIdToProjects 获取到 0 个项目
⚠️ 没有找到项目!
✅ 已设置 currentProjects(所有项目) = 0
🟢 [未知设计师] 0个项目 - 空闲 (工作量:0%, 闲置:6天)
✅ [项目数据加载] 所有成员项目数据加载完成
💾 [项目数据加载] 已更新缓存,有效期30秒
❌ [项目数据加载] ProjectTeam 查询失败
错误详情: {message: "...", code: ...}
可能原因:
解决方案:
在弹窗中,应该看到:
┌─────────────────────────────────────┐
│ 🟠 张佳乐 (组长) │
├─────────────────────────────────────┤
│ 状态: 有项目 │
│ 当前项目: 3个 │
│ 工作量: ████████░░ 60% │
│ 近30天接单: 3单 │
│ 闲置天数: 0天 │
│ │
│ [📅 查看日历] [选择设计师] │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 🟢 未知设计师 │
├─────────────────────────────────────┤
│ 状态: 空闲 │
│ 当前项目: 0个 │
│ 工作量: ░░░░░░░░░░ 0% │
│ 近30天接单: 0单 │
│ 闲置天数: 6天 │
│ │
│ [📅 查看日历] [选择设计师] │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 🔴 李明 │
├─────────────────────────────────────┤
│ 状态: 繁忙 │
│ 当前项目: 7个 │
│ 工作量: ██████████ 100% │
│ 近30天接单: 7单 │
│ 闲置天数: 0天 │
│ │
│ [📅 查看日历] [选择设计师] │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 🟢 张佳乐 (组长) │
├─────────────────────────────────────┤
│ 状态: 空闲 │
│ 当前项目: 0个 ← ❌ 错误! │
│ 工作量: ░░░░░░░░░░ 0% │
│ 近30天接单: 0单 │
│ 闲置天数: 0天 │
└─────────────────────────────────────┘
可能原因:
projectId 参数点击任意设计师卡片的"📅 查看日历"按钮,应该:
| 项目 | 其他端 | 项目管理端 | 结果 |
|---|---|---|---|
| 张佳乐 - 状态 | 🟠 有项目 | 🟠 有项目 | ✅ 一致 |
| 张佳乐 - 项目数 | 3个 | 3个 | ✅ 一致 |
| 张佳乐 - 工作量 | 60% | 60% | ✅ 一致 |
| 未知设计师 - 状态 | 🟢 空闲 | 🟢 空闲 | ✅ 一致 |
| 未知设计师 - 闲置天数 | 6天 | 6天 | ✅ 一致 |
原因:
projectId 参数未正确传递解决方案:
[projectId]="selectedProject?.id || ''"原因:
解决方案:
原因:
解决方案:
原因:
解决方案:
1. 用户点击"分配设计师"按钮
↓
2. openTeamAssignmentModal(project)
- 设置 selectedProject = project
- 清空 projectTeams 数组
↓
3. 弹窗组件接收输入参数
- [loadRealData]="true"
- [projectId]="project.id"
↓
4. ngOnInit() 自动执行
- 调用 loadRealProjectTeams()
↓
5. 查询 Department 和 Profile 表
- 加载所有项目组和设计师
↓
6. enrichMembersWithProjectAssignments()
- 查询 ProjectTeam 表(优先)
- 或查询 Project.assignee(降级)
↓
7. 为每个设计师统计项目数据
- currentProjects = 实际项目数
- workload = min(100, projects * 20)
- status = idle/reviewing/stagnant
- idleDays = 计算闲置天数
- recentOrders = 近30天接单数
↓
8. 显示设计师卡片
- 状态指示器(绿/橙/红)
- 项目数量
- 工作量进度条
- 接单情况
↓
9. 用户选择设计师并确认
↓
10. 保存分配结果到数据库
| 设计师 | 状态 | 项目数 | 工作量 | 接单情况 |
|---|---|---|---|---|
| 张佳乐 | 🟢 空闲 | 0个 | 0% | 0单 |
| 未知设计师 | 🟢 空闲 | 0个 | 0% | 0单 |
| 江集 | 🟢 空闲 | 0个 | 0% | 0单 |
问题:所有设计师都显示为空闲状态,无法看到真实的繁忙情况。
| 设计师 | 状态 | 项目数 | 工作量 | 接单情况 |
|---|---|---|---|---|
| 张佳乐 | 🟠 有项目 | 3个 | 60% | 3单 |
| 未知设计师 | 🟢 空闲 | 0个 | 0% | 已闲置6天 |
| 江集 | 🟠 有项目 | 2个 | 40% | 2单 |
| 李明 | 🔴 繁忙 | 7个 | 100% | 7单 |
效果:显示真实的繁忙情况,方便管理员合理分配任务。
虽然 projectId 在 enrichMembersWithProjectAssignments() 中没有直接使用,但它是必需的,原因如下:
loadRealSpaces,需要 projectId 加载空间数据项目管理端主要用于:
不需要:
弹窗组件使用30秒缓存,避免频繁查询:
private projectDataCache: Map<string, any> = new Map();
private lastCacheTime: number = 0;
private CACHE_DURATION = 30000; // 30秒
// 检查缓存
if (now - this.lastCacheTime < this.CACHE_DURATION) {
console.log('⚡ 使用缓存数据,跳过查询');
this.applyProjectDataFromCache(allMembers);
return;
}
注意: 如果需要强制刷新,关闭弹窗等待30秒后重新打开。
loadRealData、projectId、loadRealSpaces、enableSpaceAssignment 参数如果验证过程中发现任何问题,请参考"常见问题排查"部分。