# 修复"未分配"问题 - 完整显示所有组员 **日期**: 2025-10-24 **问题**: 组长端工作量负载概览图未显示全部组员,且项目负责人显示"未分配" --- ## 🔴 问题根源 ### 问题1: 项目显示"未分配" **原因**: 数据库中 `Project` 表的 `assignee` 字段为空或null **数据流**: ``` Parse数据库 ↓ Project表.assignee字段 = null ↓ transformProject() 转换 ↓ designerName = assignee?.get('name') || '未分配' ↓ 前端显示"未分配" ``` ### 问题2: 甘特图不显示所有组员 **原因**: 只统计了有项目的设计师,没有项目的组员不显示 **旧逻辑** (错误): ```typescript // ❌ 只从项目中提取设计师 const assigned = this.filteredProjects.filter(p => !!p.designerName); const designers = Array.from(new Set(assigned.map(p => p.designerName))); // 结果:只显示有项目的设计师,且包含"未分配" // 例如:['未分配', '张三', '李四'] ``` **问题**: - ❌ 没有项目的设计师不显示(如"王五") - ❌ "未分配"也被当作设计师显示 - ❌ 无法看到团队全貌 --- ## ✅ 解决方案 ### 修改1: 甘特图使用真实设计师列表 **文件**: `src/app/pages/team-leader/dashboard/dashboard.ts` **位置**: 第1869-1900行(updateWorkloadGantt方法内) **修改内容**: ```typescript // ✅ 获取所有真实设计师(优先使用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 !== '未分配'); ``` **改进点**: 1. **优先使用真实设计师列表** (`this.realDesigners`) - 从Parse数据库查询的所有组员 - 不依赖项目数据 - 包含没有项目的设计师 2. **过滤"未分配"** - `p.designerName !== '未分配'` - 不将"未分配"当作设计师显示 3. **友好的空状态提示** - 明确提示"暂无组员数据" - 给出操作建议 --- ## 📊 效果对比 ### 修改前 **甘特图显示**: ``` 未分配 (5个项目) ❌ 不应该显示 张三 (3个项目) 李四 (2个项目) ``` **问题**: - ❌ "未分配"占据第一行 - ❌ "王五"(无项目)不显示 - ❌ 无法看到团队完整负载 ### 修改后 **甘特图显示**: ``` 张三 (3个项目) ✅ 有项目,显示 李四 (2个项目) ✅ 有项目,显示 王五 (0个项目) ✅ 无项目,也显示 ``` **优点**: - ✅ 显示所有真实组员 - ✅ 不显示"未分配" - ✅ 清晰看到谁有空闲 - ✅ 便于分配新项目 --- ## 🔧 如何分配项目给组员 ### 方式1: 使用DesignerService的assignProject方法 **代码示例**: ```typescript // 在组长端调用 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中的实现** (已有): ```typescript // src/app/pages/team-leader/services/designer.service.ts async assignProject(projectId: string, designerId: string): Promise { 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; } } ``` ### 方式2: 在Parse Dashboard手动分配 **步骤**: 1. **打开Parse Dashboard** - 访问Parse管理后台 - 进入数据库 2. **找到Project表** - 点击 `Project` 表 - 找到需要分配的项目 3. **设置assignee字段** ``` 字段: assignee 类型: Pointer 值: 选择设计师的Profile记录 ``` 4. **设置status** ``` 字段: status 类型: String 值: '进行中' ``` 5. **保存** - 点击保存按钮 - 刷新组长端页面查看 ### 方式3: 使用智能推荐(快速分配) **组长端操作**: 1. 在项目卡片上点击"🤖 智能推荐"按钮 2. 系统自动推荐最合适的设计师 3. 确认后自动分配 **智能推荐逻辑**: - 风格匹配度 - 当前负载 - 历史表现 - 紧急适配度 --- ## 🧪 测试验证 ### 测试步骤 1. **准备测试数据** **设计师数据** (Profile表): ```javascript // 应该有至少3个组员 设计师1: { name: '张三', roleName: '组员' } 设计师2: { name: '李四', roleName: '组员' } 设计师3: { name: '王五', roleName: '组员' } ``` **项目数据** (Project表): ```javascript 项目1: { title: '项目A', assignee: 指向张三 } 项目2: { title: '项目B', assignee: 指向张三 } 项目3: { title: '项目C', assignee: 指向李四 } 项目4: { title: '项目D', assignee: null } // 未分配 ``` 2. **访问组长端Dashboard** ``` http://localhost:4200/team-leader/dashboard ``` 3. **查看工作量负载概览图** **预期显示**: ``` 张三 (2个项目) 🔥 ← 有项目,显示项目数 李四 (1个项目) ✓ ← 有项目,显示项目数 王五 (0个项目) ○ ← 无项目,也显示 ``` **不应显示**: ``` ❌ 未分配 (1个项目) ← 不应该出现 ``` 4. **验证控制台日志** ```javascript ✅ 使用真实设计师列表: 3 人 ✅ 加载设计师数据成功: 3 人 ✅ 加载真实项目数据成功: 4 个项目 ``` 5. **测试项目分配** **在浏览器控制台执行**: ```javascript // 获取组件实例 const dashboard = angular.element(document.querySelector('app-dashboard')).scope(); // 分配项目D给王五 await dashboard.designerService.assignProject('项目D的ID', '王五的ID'); // 刷新页面 location.reload(); ``` **预期结果**: - 项目D的负责人从"未分配"变为"王五" - 甘特图中王五显示 (1个项目) --- ## 📋 数据库检查清单 ### 检查Profile表 ```sql -- 查询所有组员 SELECT objectId, name, roleName, company FROM Profile WHERE roleName = '组员' AND isDeleted != true; -- 预期:应该看到多个组员记录 ``` ### 检查Project表 ```sql -- 查询未分配的项目 SELECT objectId, title, assignee, status FROM Project WHERE (assignee IS NULL OR assignee = '') AND isDeleted != true; -- 预期:未分配的项目列表 ``` ### 修复未分配的项目 ```sql -- 方式1: 分配给指定设计师 UPDATE Project SET assignee = {Profile的Pointer}, status = '进行中' WHERE objectId = '项目ID'; -- 方式2: 批量分配(循环分配给不同设计师) -- 需要在应用层或脚本中处理 ``` --- ## 🎯 核心改进 ### 1. 数据源优化 ```typescript // ❌ 旧方式:从项目中提取 const designers = projects.map(p => p.designerName); // ✅ 新方式:使用真实设计师数据 const designers = this.realDesigners.map(d => d.name); ``` ### 2. 过滤逻辑 ```typescript // ✅ 过滤"未分配" const assigned = this.filteredProjects.filter( p => p.designerName && p.designerName !== '未分配' ); ``` ### 3. 降级策略 ```typescript if (this.realDesigners && this.realDesigners.length > 0) { // 优先使用真实数据 designers = this.realDesigners.map(d => d.name); } else { // 降级到从项目提取(开发模式) designers = projects.map(p => p.designerName); } ``` --- ## 📖 相关文件 ### 修改的文件 1. ✅ `src/app/pages/team-leader/dashboard/dashboard.ts` - 第1869-1900行:修改 `updateWorkloadGantt()` 方法 - 使用真实设计师列表 - 过滤"未分配" ### 相关服务 1. `src/app/pages/team-leader/services/designer.service.ts` - `getDesigners()`: 获取所有组员 - `getProjects()`: 获取所有项目 - `assignProject()`: 分配项目 - `transformProject()`: 转换项目数据(设置designerName) ### 数据表 1. **Profile表** (设计师/组员) - `name`: 姓名 - `roleName`: '组员' - `company`: 公司ID - `isDeleted`: 软删除标记 2. **Project表** (项目) - `title`: 项目名称 - `assignee`: Pointer (负责人) - `status`: 项目状态 - `company`: 公司ID - `isDeleted`: 软删除标记 --- ## 🎉 总结 ### 修改前的问题 - ❌ 甘特图只显示有项目的设计师 - ❌ "未分配"占据甘特图第一行 - ❌ 无法看到空闲的设计师 - ❌ 项目负责人显示"未分配" ### 修改后的效果 - ✅ 甘特图显示所有真实组员 - ✅ 不显示"未分配"伪设计师 - ✅ 清晰显示谁有空闲(0个项目) - ✅ 便于识别和分配新项目 - ✅ 数据来源可靠(从数据库查询) ### 解决路径 1. **短期**:修改前端逻辑(本次修改) - 使用真实设计师列表 - 过滤"未分配" 2. **长期**:数据质量保证 - 新项目创建时必须分配设计师 - 使用智能推荐功能 - 定期检查未分配项目 --- **修复完成!** ✨ 现在刷新浏览器,应该能看到: 1. 所有真实组员都显示在甘特图中 2. 不再显示"未分配" 3. 可以清楚看到谁有空闲