日期: 2025-10-24
问题: 组长端工作量负载概览图未显示全部组员,且项目负责人显示"未分配"
原因: 数据库中 Project 表的 assignee 字段为空或null
数据流:
Parse数据库
↓
Project表.assignee字段 = null
↓
transformProject() 转换
↓
designerName = assignee?.get('name') || '未分配'
↓
前端显示"未分配"
原因: 只统计了有项目的设计师,没有项目的组员不显示
旧逻辑 (错误):
// ❌ 只从项目中提取设计师
const assigned = this.filteredProjects.filter(p => !!p.designerName);
const designers = Array.from(new Set(assigned.map(p => p.designerName)));
// 结果:只显示有项目的设计师,且包含"未分配"
// 例如:['未分配', '张三', '李四']
问题:
文件: src/app/pages/team-leader/dashboard/dashboard.ts
位置: 第1869-1900行(updateWorkloadGantt方法内)
修改内容:
// ✅ 获取所有真实设计师(优先使用realDesigners)
let designers: string[] = [];
if (this.realDesigners && this.realDesigners.length > 0) {
// 使用真实的设计师列表
designers = this.realDesigners.map(d => d.name);
console.log('✅ 使用真实设计师列表:', designers.length, '人');
} else {
// 降级:从已分配的项目中提取设计师(过滤掉"未分配")
const assigned = this.filteredProjects.filter(p => p.designerName && p.designerName !== '未分配');
designers = Array.from(new Set(assigned.map(p => p.designerName)));
console.warn('⚠️ 使用项目中提取的设计师列表:', designers.length, '人');
}
if (designers.length === 0) {
// 没有设计师数据,显示空状态
const emptyOption = {
title: {
text: '暂无组员数据',
subtext: '请先在系统中添加设计师(组员角色)',
left: 'center',
top: 'center',
textStyle: { fontSize: 16, color: '#9ca3af' },
subtextStyle: { fontSize: 13, color: '#d1d5db' }
}
};
this.workloadGanttChart.setOption(emptyOption, true);
return;
}
// 获取所有已分配的项目(过滤掉"未分配")
const assigned = this.filteredProjects.filter(p => p.designerName && p.designerName !== '未分配');
改进点:
优先使用真实设计师列表 (this.realDesigners)
过滤"未分配"
p.designerName !== '未分配'友好的空状态提示
甘特图显示:
未分配 (5个项目) ❌ 不应该显示
张三 (3个项目)
李四 (2个项目)
问题:
甘特图显示:
张三 (3个项目) ✅ 有项目,显示
李四 (2个项目) ✅ 有项目,显示
王五 (0个项目) ✅ 无项目,也显示
优点:
代码示例:
// 在组长端调用
async assignProjectToDesigner(projectId: string, designerId: string) {
try {
const success = await this.designerService.assignProject(projectId, designerId);
if (success) {
console.log('✅ 项目分配成功');
// 刷新项目列表
await this.loadProjects();
// 更新甘特图
this.updateWorkloadGantt();
} else {
console.error('❌ 项目分配失败');
}
} catch (error) {
console.error('❌ 分配出错:', error);
}
}
DesignerService中的实现 (已有):
// src/app/pages/team-leader/services/designer.service.ts
async assignProject(projectId: string, designerId: string): Promise<boolean> {
const Parse = await this.ensureParse();
if (!Parse) return false;
try {
const project = Parse.Object.extend('Project').createWithoutData(projectId);
const designer = Parse.Object.extend('Profile').createWithoutData(designerId);
project.set('assignee', designer);
project.set('status', '进行中');
await project.save();
console.log('✅ 项目分配成功');
return true;
} catch (error) {
console.error('❌ 项目分配失败:', error);
return false;
}
}
步骤:
打开Parse Dashboard
找到Project表
Project 表设置assignee字段
字段: assignee
类型: Pointer<Profile>
值: 选择设计师的Profile记录
设置status
字段: status
类型: String
值: '进行中'
保存
组长端操作:
智能推荐逻辑:
设计师数据 (Profile表):
// 应该有至少3个组员
设计师1: { name: '张三', roleName: '组员' }
设计师2: { name: '李四', roleName: '组员' }
设计师3: { name: '王五', roleName: '组员' }
项目数据 (Project表):
项目1: { title: '项目A', assignee: 指向张三 }
项目2: { title: '项目B', assignee: 指向张三 }
项目3: { title: '项目C', assignee: 指向李四 }
项目4: { title: '项目D', assignee: null } // 未分配
访问组长端Dashboard
http://localhost:4200/team-leader/dashboard
查看工作量负载概览图
预期显示:
张三 (2个项目) 🔥 ← 有项目,显示项目数
李四 (1个项目) ✓ ← 有项目,显示项目数
王五 (0个项目) ○ ← 无项目,也显示
不应显示:
❌ 未分配 (1个项目) ← 不应该出现
验证控制台日志
✅ 使用真实设计师列表: 3 人
✅ 加载设计师数据成功: 3 人
✅ 加载真实项目数据成功: 4 个项目
测试项目分配
在浏览器控制台执行:
// 获取组件实例
const dashboard = angular.element(document.querySelector('app-dashboard')).scope();
// 分配项目D给王五
await dashboard.designerService.assignProject('项目D的ID', '王五的ID');
// 刷新页面
location.reload();
预期结果:
-- 查询所有组员
SELECT objectId, name, roleName, company
FROM Profile
WHERE roleName = '组员'
AND isDeleted != true;
-- 预期:应该看到多个组员记录
-- 查询未分配的项目
SELECT objectId, title, assignee, status
FROM Project
WHERE (assignee IS NULL OR assignee = '')
AND isDeleted != true;
-- 预期:未分配的项目列表
-- 方式1: 分配给指定设计师
UPDATE Project
SET assignee = {Profile的Pointer},
status = '进行中'
WHERE objectId = '项目ID';
-- 方式2: 批量分配(循环分配给不同设计师)
-- 需要在应用层或脚本中处理
// ❌ 旧方式:从项目中提取
const designers = projects.map(p => p.designerName);
// ✅ 新方式:使用真实设计师数据
const designers = this.realDesigners.map(d => d.name);
// ✅ 过滤"未分配"
const assigned = this.filteredProjects.filter(
p => p.designerName && p.designerName !== '未分配'
);
if (this.realDesigners && this.realDesigners.length > 0) {
// 优先使用真实数据
designers = this.realDesigners.map(d => d.name);
} else {
// 降级到从项目提取(开发模式)
designers = projects.map(p => p.designerName);
}
src/app/pages/team-leader/dashboard/dashboard.ts
updateWorkloadGantt() 方法src/app/pages/team-leader/services/designer.service.ts
getDesigners(): 获取所有组员getProjects(): 获取所有项目assignProject(): 分配项目transformProject(): 转换项目数据(设置designerName)Profile表 (设计师/组员)
name: 姓名roleName: '组员'company: 公司IDisDeleted: 软删除标记Project表 (项目)
title: 项目名称assignee: Pointer (负责人)
status: 项目状态company: 公司IDisDeleted: 软删除标记短期:修改前端逻辑(本次修改)
长期:数据质量保证
修复完成! ✨
现在刷新浏览器,应该能看到: