# Admin项目管理 - 设计师分配弹窗增强

**日期**: 2025-10-24
**任务**: 在Admin项目管理中增强设计师分配功能
**状态**: 🚧 进行中

---

## 📋 需求概述

### 核心需求
1. 在Admin项目管理列表中添加"分配设计师"操作按钮
2. 复用`designer-team-assignment-modal`组件
3. 对接Parse Server真实数据，显示实际项目成员
4. 修改弹窗中的日历组件，改为**按月日历显示**（单屏完整显示）
5. 增加**工序分工**功能：
   - 空间分配
   - 建模分配
   - 软装分配
   - 渲染分配
   - 后期分配

---

## 🎯 实现步骤

### 步骤1: 在项目管理列表添加"分配设计师"按钮 ✅

**文件**: `src/app/pages/admin/project-management/project-management.html`

在操作列添加新按钮：
```html
<button mat-icon-button class="action-btn" color="accent"
        title="分配设计师"
        (click)="openTeamAssignmentModal(project)">
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
    <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
    <circle cx="9" cy="7" r="4"></circle>
    <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
    <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
  </svg>
</button>
```

### 步骤2: 在TypeScript中实现弹窗逻辑

**文件**: `src/app/pages/admin/project-management/project-management.ts`

添加：
- 导入`DesignerTeamAssignmentModalComponent`
- 添加弹窗状态管理
- 实现`openTeamAssignmentModal(project)`方法
- 实现`closeTeamAssignmentModal()`方法
- 实现`confirmTeamAssignment(result)`方法
- 从Parse加载真实项目数据和团队数据

### 步骤3: 创建工序分工数据结构

**新增接口**:
```typescript
export interface WorkflowAssignment {
  workflowType: 'space' | 'modeling' | 'furnishing' | 'rendering' | 'postprocessing';
  workflowName: string;
  assignedDesigners: string[]; // Designer IDs
  productIds?: string[]; // 关联的产品/空间ID
  estimatedHours?: number;
  deadline?: Date;
}

export interface EnhancedDesignerAssignmentData {
  projectId: string;
  primaryTeamId: string;
  workflowAssignments: WorkflowAssignment[];
  crossTeamCollaborators: string[];
  notes?: string;
}
```

### 步骤4: 修改弹窗组件以支持工序分工

**文件**: `src/app/pages/designer/project-detail/components/designer-team-assignment-modal/designer-team-assignment-modal.component.html`

在弹窗中添加新的"工序分工"部分：

```html
<!-- 工序分工部分 -->
@if (internalSelectedTeamId && showWorkflowAssignment) {
  <div class="workflow-assignment-section">
    <h3>工序分工</h3>
    <div class="workflow-grid">
      <div class="workflow-item" *ngFor="let workflow of workflowTypes">
        <div class="workflow-header">
          <h4>{{ workflow.name }}</h4>
          <span class="assigned-count">已分配: {{ getWorkflowAssignedCount(workflow.type) }}人</span>
        </div>
        
        <div class="designer-assignment">
          <div class="designer-chips">
            @for (designerId of getWorkflowAssignedDesigners(workflow.type); track designerId) {
              <div class="designer-chip">
                {{ getDesignerById(designerId)?.name }}
                <button class="remove-chip" (click)="removeWorkflowDesigner(workflow.type, designerId)">×</button>
              </div>
            }
          </div>
          
          <button class="add-designer-btn" (click)="openDesignerSelector(workflow.type)">
            + 添加设计师
          </button>
        </div>
      </div>
    </div>
  </div>
}
```

### 步骤5: 修改日历组件为月视图

**目标**: 修改`designer-calendar.component`，使其显示类似iOS日历的月视图

**参考图片要求**:
- 单月视图，所有日期在一屏内显示
- 清晰标注工作日、休息日、已占用日期
- 支持点击查看当日详情
- 不需要左右滑动

**实现方案**:

创建新的月历组件或修改现有组件：
```html
<div class="month-calendar">
  <div class="calendar-header">
    <button (click)="previousMonth()">‹</button>
    <span class="month-year">{{ currentMonth }} {{ currentYear }}</span>
    <button (click)="nextMonth()">›</button>
  </div>
  
  <div class="calendar-grid">
    <div class="weekday-header" *ngFor="let day of weekDays">{{ day }}</div>
    
    <div class="calendar-day" 
         *ngFor="let date of calendarDates"
         [class.weekend]="isWeekend(date)"
         [class.busy]="isDesignerBusy(date)"
         [class.review]="isReviewDate(date)"
         [class.available]="isAvailable(date)"
         [class.today]="isToday(date)"
         (click)="selectDate(date)">
      <span class="date-number">{{ date.getDate() }}</span>
      @if (hasEvents(date)) {
        <div class="event-dots">
          <span class="dot" *ngFor="let event of getDateEvents(date)"></span>
        </div>
      }
    </div>
  </div>
  
  <!-- 选中日期的详情 -->
  @if (selectedDate) {
    <div class="date-details">
      <h4>{{ selectedDate | date:'yyyy-MM-dd' }}</h4>
      <div class="events-list">
        <div class="event-item" *ngFor="let event of selectedDateEvents">
          {{ event.description }}
        </div>
      </div>
    </div>
  }
</div>
```

### 步骤6: Parse数据对接

**查询项目团队成员**:
```typescript
async loadProjectTeamMembers(projectId: string): Promise<Designer[]> {
  const query = new Parse.Query('ProjectTeam');
  query.equalTo('project', { __type: 'Pointer', className: 'Project', objectId: projectId });
  query.include('profile');
  query.notEqualTo('isDeleted', true);
  
  const teamMembers = await query.find();
  
  return teamMembers.map(member => {
    const profile = member.get('profile');
    return {
      id: profile.id,
      name: profile.get('name'),
      teamId: member.get('team')?.id,
      teamName: member.get('team')?.get('name'),
      // ... 其他字段
    };
  });
}
```

**查询工序分配**:
```typescript
async loadWorkflowAssignments(projectId: string): Promise<WorkflowAssignment[]> {
  const query = new Parse.Query('ProjectWorkflowAssignment');
  query.equalTo('project', { __type: 'Pointer', className: 'Project', objectId: projectId });
  query.include(['assignedTo', 'product']);
  
  const assignments = await query.find();
  
  return assignments.map(assignment => ({
    workflowType: assignment.get('workflowType'),
    workflowName: assignment.get('workflowName'),
    assignedDesigners: assignment.get('assignedTo').map(d => d.id),
    productIds: assignment.get('products')?.map(p => p.id),
  }));
}
```

**保存分配结果**:
```typescript
async saveTeamAssignment(projectId: string, data: EnhancedDesignerAssignmentData): Promise<void> {
  // 1. 更新ProjectTeam表
  for (const designerId of data.selectedDesigners) {
    const ProjectTeam = Parse.Object.extend('ProjectTeam');
    const teamMember = new ProjectTeam();
    teamMember.set('project', { __type: 'Pointer', className: 'Project', objectId: projectId });
    teamMember.set('profile', { __type: 'Pointer', className: 'Profile', objectId: designerId });
    teamMember.set('role', 'member');
    await teamMember.save();
  }
  
  // 2. 保存工序分配
  for (const workflow of data.workflowAssignments) {
    const WorkflowAssignment = Parse.Object.extend('ProjectWorkflowAssignment');
    const assignment = new WorkflowAssignment();
    assignment.set('project', { __type: 'Pointer', className: 'Project', objectId: projectId });
    assignment.set('workflowType', workflow.workflowType);
    assignment.set('workflowName', workflow.workflowName);
    assignment.set('assignedTo', workflow.assignedDesigners.map(id => ({ 
      __type: 'Pointer', 
      className: 'Profile', 
      objectId: id 
    })));
    await assignment.save();
  }
}
```

---

## 📐 UI/UX设计要点

### 1. 弹窗布局优化
- **单屏显示**: 所有关键信息在一屏内，避免过度滚动
- **左右布局**: 左侧团队选择+工序分工，右侧设计师列表+日历
- **固定高度**: 弹窗最大高度90vh，内容区域可滚动

### 2. 工序分工设计
```
┌─────────────┬──────────────────────────────┐
│ 工序分工    │                              │
├─────────────┼──────────────────────────────┤
│ 🏠 空间设计  │ [张三] [李四] [+ 添加]        │
│ 🔨 建模制作  │ [王五] [+ 添加]               │
│ 🪑 软装搭配  │ [赵六] [+ 添加]               │
│ 🎨 效果渲染  │ [+ 添加]                      │
│ ✨ 后期处理  │ [+ 添加]                      │
└─────────────┴──────────────────────────────┘
```

### 3. 月历视图设计
```
        2025年 10月
一  二  三  四  五  六  日
         1   2   3   4   5
 6   7   8   9  10  11  12
13  14  15  16  17  18  19
20  21  22  23  24  25  26
27  28  29  30  31

图例:
🟢 空闲可分配
🔴 已占用
🟡 对图日期
🔵 当前选中
```

---

## 🔧 技术实现细节

### Parse Schema扩展

可能需要新增表：
```typescript
TABLE(ProjectWorkflowAssignment, "项目工序分配表") {
  FIELD(objectId, String)
  FIELD(project, Pointer→Project)
  FIELD(company, Pointer→Company)
  FIELD(workflowType, String) // "space" | "modeling" | "furnishing" | "rendering" | "postprocessing"
  FIELD(workflowName, String)
  FIELD(assignedTo, Array<Pointer→Profile>)
  FIELD(products, Array<Pointer→Product>) // 关联的空间产品
  FIELD(estimatedHours, Number)
  FIELD(deadline, Date)
  FIELD(isDeleted, Boolean)
  FIELD(createdAt, Date)
  FIELD(updatedAt, Date)
}
```

---

## ✅ 验收标准

1. ✅ 项目管理列表中有"分配设计师"按钮
2. ✅ 点击按钮弹出设计师分配弹窗
3. ✅ 弹窗显示真实的项目团队成员（从Parse加载）
4. ✅ 弹窗中有工序分工区域，可分配5种工序
5. ✅ 日历组件改为月视图，单屏完整显示
6. ✅ 可以查看每个设计师的月度日历
7. ✅ 保存后数据写入Parse Server
8. ✅ 刷新页面后分配信息保持

---

## 📝 开发备注

- 复用现有的`designer-team-assignment-modal`组件
- 日历组件可参考iOS原生日历风格
- 工序分工为新增功能，需要扩展数据模型
- 注意多租户隔离（company字段）
- 所有查询都要过滤`isDeleted`

---

**开发者**: Claude AI
**预计完成时间**: 2025-10-24

