# 修复项目负责人和空间场景问题

**日期**: 2025-10-24  
**问题**: 
1. 分配设计师时没有空间场景可选
2. 项目列表中负责人显示"未分配"，应该显示组长名字

---

## 🔍 问题分析

### 问题1: 空间场景为空

**现象**:  
在 `http://localhost:4200/admin/project-detail/APwk78jnrh/order` 分配设计师时，"指派空间场景"没有选项。

**原因**:  
`team-assign.component.ts` 通过 `ProductSpaceService.getProjectProductSpaces()` 获取项目空间：

```typescript
// 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` 表查询：

```typescript
// 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` 表中没有任何记录。

---

### 问题2: 项目负责人显示"未分配"

**现象**:  
项目列表中"负责人"列显示"未分配"，应该显示组长名字。

**数据流**:

```
Parse数据库 Project表
  ↓
  assignee字段 (Pointer<Profile>) = null
  ↓
project-management.ts 第107行
  assignee: json.assigneeName || '未分配'
  ↓
前端显示 "未分配"
```

**根本原因**: 项目创建时，`assignee` 字段没有被设置。按业务逻辑，项目的负责人应该是项目组的组长（`department.leader`）。

---

## ✅ 解决方案

### 方案1: 空间场景问题

**方案A: 在"订单分配"阶段创建空间（推荐）**

在 `stage-order.component.ts` 的订单分配阶段，用户填写空间信息后自动创建 `Product` 记录。

**位置**: `src/modules/project/pages/project-detail/stages/stage-order.component.ts`

**逻辑**:
```typescript
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: 提供手动添加空间的入口**

在分配设计师弹窗中添加"添加空间"按钮。

---

### 方案2: 项目负责人问题

**关键修改**: 在选择项目组（Department）时，自动将组长（`department.leader`）设置为项目的 `assignee`。

#### 修改1: team-assign.component.ts

**位置**: `src/modules/project/components/team-assign/team-assign.component.ts` 第128-134行

**修改 `selectDepartment` 方法**:

```typescript
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` 字段
- 保存到数据库

#### 修改2: 项目创建时的默认逻辑

**位置**: `src/app/pages/admin/services/project.service.ts` 第65-110行

**在 `createProject` 方法中添加逻辑**:

```typescript
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);
}
```

---

## 📊 数据库结构

### Project 表

| 字段 | 类型 | 说明 | 新增/修改 |
|------|------|------|----------|
| `department` | Pointer<Department> | 项目组 | ✅ 确保填充 |
| `assignee` | Pointer<Profile> | 项目负责人（组长） | ✅ 自动设置为组长 |
| `title` | String | 项目名称 | 已有 |
| `customer` | Pointer<ContactInfo> | 客户 | 已有 |
| `status` | String | 项目状态 | 已有 |
| `currentStage` | String | 当前阶段 | 已有 |

### Product 表

| 字段 | 类型 | 说明 |
|------|------|------|
| `project` | Pointer<Project> | 所属项目 |
| `productName` | String | 空间名称（如"客厅"） |
| `productType` | String | 空间类型（如"living_room"） |
| `space` | Object | 空间详细信息 |
| `space.area` | Number | 面积 |
| `space.priority` | Number | 优先级 |
| `space.complexity` | String | 复杂度 |
| `quotation` | Object | 报价信息 |
| `requirements` | Object | 需求信息 |
| `profile` | Pointer<Profile> | 负责该空间的设计师 |

### Department 表

| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | String | 项目组名称 |
| `leader` | Pointer<Profile> | 组长 |
| `type` | String | 'project' (项目组) |
| `company` | String | 公司ID |

### Profile 表

| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | String | 姓名 |
| `roleName` | String | '组长' 或 '组员' |
| `department` | String | 部门ID |
| `company` | String | 公司ID |

---

## 🧪 测试步骤

### 测试1: 空间场景

1. **进入订单分配阶段**
   ```
   http://localhost:4200/admin/project-detail/APwk78jnrh/order
   ```

2. **添加空间**
   - 点击"添加空间"按钮
   - 填写空间信息（客厅、卧室等）
   - 保存

3. **分配设计师**
   - 选择项目组
   - 选择设计师
   - **预期**: 能看到刚才添加的空间列表
   - 选择空间并确认分配

### 测试2: 项目负责人

1. **创建新项目时指定项目组**
   ```
   POST /Project
   {
     "title": "测试项目",
     "departmentId": "xxx", // 项目组ID
     "status": "待分配"
   }
   ```

2. **验证数据库**
   ```
   // Parse Dashboard 查看 Project 表
   - assignee字段应该指向组长的Profile
   - department字段应该指向该项目组
   ```

3. **在项目详情页选择项目组**
   - 进入项目详情页订单分配阶段
   - 选择一个项目组
   - **预期**: 
     - 项目的assignee自动更新为该组长
     - 刷新项目列表，负责人列显示组长名字

4. **验证项目列表**
   ```
   http://localhost:4200/admin/project-management
   ```
   - **预期**: "负责人"列显示组长名字，而不是"未分配"

---

## 🎯 核心逻辑总结

### 项目负责人（assignee）的设置规则

1. **项目创建时**:
   - 如果指定了 `departmentId`，自动获取组长作为 `assignee`
   - 如果明确指定了 `assigneeId`，使用指定的人员

2. **选择项目组时**:
   - 在 `team-assign` 组件中选择项目组
   - 自动将组长设置为项目的 `assignee`
   - 更新 `department` 字段

3. **项目列表显示**:
   - 从 `assignee.name` 获取负责人名字
   - 如果为空，显示"未分配"

### 空间场景的创建流程

1. **订单分配阶段** (stage-order):
   - 用户填写空间信息（客厅、卧室等）
   - 调用 `ProductSpaceService.createProductSpace()` 创建 Product 记录

2. **分配设计师时** (team-assign):
   - 从 `Product` 表查询该项目的所有空间
   - 显示空间列表供选择
   - 将选中的空间保存到 `ProjectTeam.data.spaces` 中

---

## 📁 需要修改的文件

1. ✅ `src/modules/project/components/team-assign/team-assign.component.ts`
   - 第128-134行：修改 `selectDepartment` 方法

2. ✅ `src/app/pages/admin/services/project.service.ts`
   - 第65-110行：修改 `createProject` 方法

3. ⚠️ `src/modules/project/pages/project-detail/stages/stage-order.component.ts`
   - 需要确保空间信息保存时创建 Product 记录

---

## 🎉 预期效果

### 修改前

**项目列表**:
```
项目名称                             | 客户      | 负责人    | 状态
张家界凤凰城三期项目 紫空居..        | 未知客户  | 未分配    | 待分配
```

**分配设计师**:
```
指派空间场景
（空）
```

### 修改后

**项目列表**:
```
项目名称                             | 客户      | 负责人    | 状态
张家界凤凰城三期项目 紫空居..        | 张先生    | 汪奥      | 进行中
```

**分配设计师**:
```
指派空间场景 *
☑ 客厅
☐ 主卧
☐ 次卧
☐ 厨房
```

---

**修改完成后，项目负责人将自动设置为组长，且分配设计师时能看到项目的所有空间！** ✨


