日期: 2025-10-24
完成状态: ✅ 已完成
文件: src/modules/project/components/team-assign/team-assign.component.ts
位置: 第128-151行
修改内容:
async selectDepartment(department: FmodeObject) {
this.selectedDepartment = department;
this.selectedDesigner = null;
this.departmentMembers = [];
// ✅ 自动设置组长为项目负责人
const leader = department.get('leader');
if (leader && this.project) {
try {
// 更新项目的assignee字段为组长
this.project.set('assignee', leader);
this.project.set('department', department);
await this.project.save();
console.log('✅ 项目负责人已设置为组长:', leader.get('name'));
// 触发界面更新
this.cdr.markForCheck();
} catch (error) {
console.error('❌ 设置项目负责人失败:', error);
}
}
await this.loadDepartmentMembers(department);
}
效果:
assigneedepartment 字段文件: src/app/pages/admin/services/project.service.ts
位置: 第4-6行(导入)、第70-137行(createProject方法)
2.1 添加Parse导入:
import { FmodeParse } from 'fmode-ng/parse';
const Parse = FmodeParse.with('nova');
2.2 修改createProject方法:
async createProject(data: {
title: string;
customerId?: string;
assigneeId?: string;
departmentId?: string; // ✅ 新增:项目组ID
status?: string;
currentStage?: string;
deadline?: Date;
data?: any;
}): Promise<FmodeObject> {
const projectData: any = {
title: data.title,
status: data.status || '待分配',
currentStage: data.currentStage || '订单分配'
};
// 设置客户指针
if (data.customerId) {
projectData.customer = {
__type: 'Pointer',
className: 'ContactInfo',
objectId: data.customerId
};
}
// ✅ 新增:如果提供了项目组,获取组长作为默认负责人
if (data.departmentId) {
try {
const departmentQuery = new Parse.Query('Department');
departmentQuery.include('leader');
const department = await departmentQuery.get(data.departmentId);
if (department) {
projectData.department = department.toPointer();
// 获取组长
const leader = department.get('leader');
if (leader && !data.assigneeId) {
// 如果没有明确指定负责人,使用组长
projectData.assignee = leader.toPointer();
console.log('✅ 项目负责人默认为组长:', leader.get('name'));
}
}
} catch (error) {
console.error('❌ 获取项目组失败:', error);
}
}
// 设置负责人指针(如果明确指定,覆盖组长)
if (data.assigneeId) {
projectData.assignee = {
__type: 'Pointer',
className: 'Profile',
objectId: data.assigneeId
};
}
if (data.deadline) {
projectData.deadline = data.deadline;
}
if (data.data) {
projectData.data = data.data;
}
const project = this.adminData.createObject('Project', projectData);
return await this.adminData.save(project);
}
效果:
departmentIdassigneeId,优先使用指定的人员文件: src/app/pages/admin/services/project.service.ts
位置: 第17-44行(findProjects)、第57-67行(getProject)
3.1 修改findProjects:
async findProjects(options?: {
status?: string;
keyword?: string;
skip?: number;
limit?: number;
}): Promise<FmodeObject[]> {
return await this.adminData.findAll('Project', {
include: ['customer', 'assignee', 'department', 'department.leader'], // ✅ 添加department和leader
skip: options?.skip || 0,
limit: options?.limit || 20,
descending: 'updatedAt',
additionalQuery: query => {
if (options?.status) {
query.equalTo('status', options.status);
}
if (options?.keyword) {
const kw = options.keyword.trim();
if (kw) {
// 搜索项目标题
query.matches('title', new RegExp(kw, 'i'));
}
}
}
});
}
3.2 修改getProject:
async getProject(objectId: string): Promise<FmodeObject | null> {
return await this.adminData.getById('Project', objectId, [
'customer',
'assignee',
'department',
'department.leader' // ✅ 添加department和leader
]);
}
效果:
department 和 department.leader 关联数据文件: src/app/pages/admin/services/project.service.ts
位置: 第231-257行
修改内容:
toJSON(project: FmodeObject): any {
const json = this.adminData.toJSON(project);
// 处理关联对象
if (json.customer && typeof json.customer === 'object') {
json.customerName = json.customer.name || '';
json.customerId = json.customer.objectId;
}
// ✅ 处理负责人:优先使用assignee,如果为空则使用department.leader
if (json.assignee && typeof json.assignee === 'object') {
json.assigneeName = json.assignee.name || '';
json.assigneeId = json.assignee.objectId;
} else if (json.department && typeof json.department === 'object') {
// 如果没有assignee,但有department和leader,使用leader
const leader = json.department.leader;
if (leader && typeof leader === 'object') {
json.assigneeName = leader.name || '';
json.assigneeId = leader.objectId;
}
}
return json;
}
效果:
assignee.nameassignee 为空,自动使用 department.leader.name用户创建项目
↓
指定departmentId
↓
createProject()查询Department
↓
获取department.leader
↓
设置project.assignee = leader
↓
保存到数据库
↓
项目列表显示组长名字
用户在项目详情页
↓
选择项目组(team-assign组件)
↓
selectDepartment()自动触发
↓
获取department.leader
↓
更新project.assignee = leader
↓
保存到数据库
↓
刷新项目列表,负责人更新
加载项目列表
↓
include: ['assignee', 'department', 'department.leader']
↓
toJSON()转换
↓
如果有assignee → 显示assignee.name
如果没有assignee但有department.leader → 显示leader.name
否则 → 显示"未分配"
↓
项目列表展示
步骤:
http://localhost:4200/admin/project-detail/APwk78jnrh/order✅ 项目负责人已设置为组长: xxxhttp://localhost:4200/admin/project-management预期结果:
assignee 自动设置为组长步骤:
调用 projectService.createProject() 创建项目:
await projectService.createProject({
title: '测试项目',
departmentId: 'xxx项目组ID',
status: '待分配'
});
查看控制台输出:✅ 项目负责人默认为组长: xxx
在项目管理页面查看新项目
验证"负责人"列显示组长名字
预期结果:
project.assignee 指向组长的Profileproject.department 指向该项目组当前状态:
APwk78jnrh 在 Product 表中没有记录解决方案:
ProductSpaceService.createProductSpace() 创建 Product 记录Product 表project 字段为项目指针productName 为 "客厅"、"卧室" 等productType 为 "living_room"、"bedroom" 等修改前:
assignee 为空修改后:
数据获取优先级:
assigneedepartment.leader代码实现:
// toJSON方法中的逻辑
if (json.assignee && typeof json.assignee === 'object') {
// 优先使用assignee
json.assigneeName = json.assignee.name || '';
} else if (json.department && typeof json.department === 'object') {
// 降级使用department.leader
const leader = json.department.leader;
if (leader && typeof leader === 'object') {
json.assigneeName = leader.name || '';
}
}
| 文件 | 修改内容 | 状态 |
|---|---|---|
src/modules/project/components/team-assign/team-assign.component.ts |
选择项目组时自动设置组长为负责人 | ✅ 完成 |
src/app/pages/admin/services/project.service.ts |
添加Parse导入 | ✅ 完成 |
src/app/pages/admin/services/project.service.ts |
修改createProject方法,支持departmentId | ✅ 完成 |
src/app/pages/admin/services/project.service.ts |
修改findProjects,include department | ✅ 完成 |
src/app/pages/admin/services/project.service.ts |
修改getProject,include department | ✅ 完成 |
src/app/pages/admin/services/project.service.ts |
修改toJSON,优先显示leader | ✅ 完成 |
docs/task/2025102221-fix-project-assignee-and-spaces.md |
问题分析文档 | ✅ 完成 |
docs/task/2025102221-implementation-summary.md |
实现总结文档 | ✅ 完成 |
修改完成!现在刷新浏览器测试,项目列表应该能正确显示组长名字了! 🚀