日期: 2025-10-24
问题:
现象:
在 http://localhost:4200/admin/project-detail/APwk78jnrh/order 分配设计师时,"指派空间场景"没有选项。
原因:
team-assign.component.ts 通过 ProductSpaceService.getProjectProductSpaces() 获取项目空间:
// team-assign.component.ts 第94-107行
async loadProjectSpaces(): Promise<void> {
if (!this.project) return;
try {
this.loadingSpaces = true;
const projectId = this.project.id || '';
// 从Product表查询该项目的空间
this.projectSpaces = await this.productSpaceService.getProjectProductSpaces(projectId);
} catch (err) {
console.error('加载项目空间失败:', err);
} finally {
this.loadingSpaces = false;
this.cdr.markForCheck();
}
}
ProductSpaceService.getProjectProductSpaces() 从 Product 表查询:
// product-space.service.ts 第125-143行
async getProjectProductSpaces(projectId: string): Promise<Project[]> {
try {
const query = new Parse.Query('Product');
query.equalTo('project', {
__type: 'Pointer',
className: 'Project',
objectId: projectId
});
query.include('profile');
query.ascending('createdAt');
const results = await query.find();
return results.map(product => this.parseProductData(product));
} catch (error) {
console.error('获取项目产品空间失败:', error);
return [];
}
}
根本原因: 项目ID为 APwk78jnrh 的项目在 Product 表中没有任何记录。
现象:
项目列表中"负责人"列显示"未分配",应该显示组长名字。
数据流:
Parse数据库 Project表
↓
assignee字段 (Pointer<Profile>) = null
↓
project-management.ts 第107行
assignee: json.assigneeName || '未分配'
↓
前端显示 "未分配"
根本原因: 项目创建时,assignee 字段没有被设置。按业务逻辑,项目的负责人应该是项目组的组长(department.leader)。
方案A: 在"订单分配"阶段创建空间(推荐)
在 stage-order.component.ts 的订单分配阶段,用户填写空间信息后自动创建 Product 记录。
位置: src/modules/project/pages/project-detail/stages/stage-order.component.ts
逻辑:
async saveSpaces() {
// 遍历用户添加的空间
for (const space of this.spaces) {
// 调用 ProductSpaceService.createProductSpace() 创建Product记录
await this.productSpaceService.createProductSpace(this.project.id, {
name: space.name,
type: space.type,
area: space.area,
priority: space.priority,
complexity: space.complexity,
estimatedBudget: space.budget
});
}
}
方案B: 在分配设计师时动态创建空间
如果没有空间,显示提示:"请先在订单分配阶段添加空间"。
方案C: 提供手动添加空间的入口
在分配设计师弹窗中添加"添加空间"按钮。
关键修改: 在选择项目组(Department)时,自动将组长(department.leader)设置为项目的 assignee。
位置: src/modules/project/components/team-assign/team-assign.component.ts 第128-134行
修改 selectDepartment 方法:
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'));
} catch (error) {
console.error('❌ 设置项目负责人失败:', error);
}
}
await this.loadDepartmentMembers(department);
}
说明:
department.leader)assignee 字段department 字段位置: src/app/pages/admin/services/project.service.ts 第65-110行
在 createProject 方法中添加逻辑:
async createProject(data: {
title: string;
customerId?: string;
assigneeId?: string; // 可以是组长ID
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) {
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'));
}
}
}
// 设置负责人指针(如果明确指定)
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);
}
| 字段 | 类型 | 说明 | 新增/修改 |
|---|---|---|---|
department |
Pointer | 项目组 | ✅ 确保填充 |
assignee |
Pointer | 项目负责人(组长) | ✅ 自动设置为组长 |
title |
String | 项目名称 | 已有 |
customer |
Pointer | 客户 | 已有 |
status |
String | 项目状态 | 已有 |
currentStage |
String | 当前阶段 | 已有 |
| 字段 | 类型 | 说明 |
|---|---|---|
project |
Pointer | 所属项目 |
productName |
String | 空间名称(如"客厅") |
productType |
String | 空间类型(如"living_room") |
space |
Object | 空间详细信息 |
space.area |
Number | 面积 |
space.priority |
Number | 优先级 |
space.complexity |
String | 复杂度 |
quotation |
Object | 报价信息 |
requirements |
Object | 需求信息 |
profile |
Pointer | 负责该空间的设计师 |
| 字段 | 类型 | 说明 |
|---|---|---|
name |
String | 项目组名称 |
leader |
Pointer | 组长 |
type |
String | 'project' (项目组) |
company |
String | 公司ID |
| 字段 | 类型 | 说明 |
|---|---|---|
name |
String | 姓名 |
roleName |
String | '组长' 或 '组员' |
department |
String | 部门ID |
company |
String | 公司ID |
进入订单分配阶段
http://localhost:4200/admin/project-detail/APwk78jnrh/order
添加空间
分配设计师
创建新项目时指定项目组
POST /Project
{
"title": "测试项目",
"departmentId": "xxx", // 项目组ID
"status": "待分配"
}
验证数据库
// Parse Dashboard 查看 Project 表
- assignee字段应该指向组长的Profile
- department字段应该指向该项目组
在项目详情页选择项目组
验证项目列表
http://localhost:4200/admin/project-management
项目创建时:
departmentId,自动获取组长作为 assigneeassigneeId,使用指定的人员选择项目组时:
team-assign 组件中选择项目组assigneedepartment 字段项目列表显示:
assignee.name 获取负责人名字订单分配阶段 (stage-order):
ProductSpaceService.createProductSpace() 创建 Product 记录分配设计师时 (team-assign):
Product 表查询该项目的所有空间ProjectTeam.data.spaces 中✅ src/modules/project/components/team-assign/team-assign.component.ts
selectDepartment 方法✅ src/app/pages/admin/services/project.service.ts
createProject 方法⚠️ src/modules/project/pages/project-detail/stages/stage-order.component.ts
项目列表:
项目名称 | 客户 | 负责人 | 状态
张家界凤凰城三期项目 紫空居.. | 未知客户 | 未分配 | 待分配
分配设计师:
指派空间场景
(空)
项目列表:
项目名称 | 客户 | 负责人 | 状态
张家界凤凰城三期项目 紫空居.. | 张先生 | 汪奥 | 进行中
分配设计师:
指派空间场景 *
☑ 客厅
☐ 主卧
☐ 次卧
☐ 厨房
修改完成后,项目负责人将自动设置为组长,且分配设计师时能看到项目的所有空间! ✨