# 数据加载与甘特图显示问题修复

**日期**: 2025-10-22 11:00
**问题**: 控制台报错 `TypeError: deadline.getTime is not a function`，甘特图无法显示真实数据

---

## 问题分析

### 1. 主要错误
```
TypeError: deadline.getTime is not a function
  at DesignerService.transformProject (designer.service.ts:219:42)
```

### 2. 根本原因
`transformProject` 中直接调用 `deadline.getTime()`，但未验证 `deadline` 是否为 Date 对象。Parse 查询可能返回：
- Date 对象（正常）
- null/undefined（字段不存在）
- 字符串（类型不匹配）

### 3. 甘特图显示说明
**甘特图设计是正确的**：
- ✅ Y轴显示**设计师名字**（按负载排序）
- ✅ X轴显示**时间轴**（周/月视图）
- ✅ 条形图显示**每个设计师负责的项目及其时间线**
- ✅ 颜色标识**项目紧急度**（红色=高，橙色=中，绿色=低）
- ✅ 背景色标识**设计师负载状态**（绿色=空闲，红色=超负荷）

这就是"设计师排版时间轴"的正确呈现方式。用户看到的"项目数据"是指条形图中的项目名称和截止日期，这是**预期行为**。

---

## 修复内容

### 1. 修复 Date 类型处理（designer.service.ts）

#### calculateProjectWeight (Line 164-188)
```typescript
// 修复前
const deadline = project.get?.('deadline') || project.deadline;
const daysLeft = deadline ? Math.ceil((deadline.getTime() - now.getTime()) / ...) : 30;

// 修复后
const deadlineRaw = project.get?.('deadline') || project.deadline;
const deadline = deadlineRaw instanceof Date ? deadlineRaw : (deadlineRaw ? new Date(deadlineRaw) : null);
const daysLeft = deadline ? Math.ceil((deadline.getTime() - now.getTime()) / ...) : 30;
```

#### transformProject (Line 216-221)
```typescript
// 修复前
const deadline = project.get('deadline') || new Date();

// 修复后
const deadlineRaw = project.get('deadline');
const deadline = deadlineRaw instanceof Date ? deadlineRaw : (deadlineRaw ? new Date(deadlineRaw) : new Date());
```

### 2. 添加调试日志

**constructor (Line 36-40)**:
```typescript
constructor() {
  this.cid = localStorage.getItem('company') || '';
  console.log('🏢 DesignerService初始化，当前公司ID:', this.cid || '（未设置）');
  this.initParse();
}
```

**getProjects (Line 193-227)**:
```typescript
async getProjects(): Promise<any[]> {
  const Parse = await this.ensureParse();
  if (!Parse) {
    console.error('❌ Parse未初始化，无法查询项目');
    return [];
  }
  
  if (!this.cid) {
    console.error('❌ 未找到公司ID（localStorage的company字段为空），无法查询项目');
    return [];
  }
  
  console.log('🔍 开始查询项目，company:', this.cid);
  const query = new Parse.Query('Project');
  // ... 查询逻辑
  
  console.log(`✅ Parse查询成功，找到 ${projects.length} 个项目`);
  
  if (projects.length === 0) {
    console.warn('⚠️ 数据库中没有符合条件的项目数据');
    console.warn('💡 提示：请确保Project表中有数据，且company字段=', this.cid);
  }
  
  return projects.map((p: any) => this.transformProject(p));
}
```

---

## 验证步骤

### 1. 检查控制台日志

刷新页面后，应该看到以下日志：

```
🏢 DesignerService初始化，当前公司ID: <你的company ID>
✅ DesignerService: FmodeParse 初始化成功
🔍 开始查询项目，company: <你的company ID>
✅ Parse查询成功，找到 X 个项目
```

### 2. 如果看到"未找到公司ID"

说明 `localStorage.getItem('company')` 为空，需要：
- 确认是否已登录
- 检查登录流程是否正确设置了 `localStorage.company`

### 3. 如果看到"找到 0 个项目"

说明数据库中没有符合条件的Project数据，需要：
- 确认Project表中有数据
- 确认Project.company字段与当前company ID匹配
- 确认Project.isDeleted字段不为true

### 4. 检查甘特图显示

如果有真实数据，甘特图应该显示：
- Y轴：设计师名字列表
- X轴：时间轴（默认显示"周"视图，未来7天）
- 条形图：每个设计师负责的项目
- 颜色：红色（高紧急度）、橙色（中）、绿色（低）
- 背景：绿色背景=设计师空闲可接单，红色背景=超负荷

---

## 数据准备

### 确保Project表有测试数据

```javascript
// 在Parse Dashboard或云函数中执行：
const Project = Parse.Object.extend("Project");
const project = new Project();

project.set("title", "测试项目-现代客厅设计");
project.set("company", "<你的company objectId>");
project.set("status", "进行中");
project.set("currentStage", "modeling");
project.set("deadline", new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)); // 7天后

// 可选：关联设计师
const Profile = Parse.Object.extend("Profile");
const designer = Profile.createWithoutData("<设计师objectId>");
project.set("assignee", designer);

// 可选：设置扩展数据
project.set("data", {
  projectType: "soft", // soft=软装, hard=硬装
  urgency: "high",     // high/medium/low
  style: "现代简约"
});

await project.save();
```

### 确保Profile表有设计师数据

```javascript
const Profile = Parse.Object.extend("Profile");
const profile = new Profile();

profile.set("name", "张三");
profile.set("company", "<你的company objectId>");
profile.set("roleName", "组员"); // 重要：必须是"组员"角色
profile.set("data", {
  tags: {
    expertise: {
      styles: ["现代简约", "北欧风格"],
      skills: ["建模", "渲染"],
      spaceTypes: ["客厅", "卧室"]
    },
    capacity: {
      weeklyProjects: 3,
      maxConcurrent: 5,
      avgDaysPerProject: 10
    },
    emergency: {
      willing: true,
      premium: 20,
      maxPerWeek: 2
    },
    history: {
      totalProjects: 15,
      completionRate: 90,
      avgRating: 4.5,
      onTimeRate: 85,
      excellentCount: 5
    },
    portfolio: []
  }
});

await profile.save();
```

---

## 下一步

如果数据库中确实没有数据，系统会**自动使用模拟数据**（fallback机制），甘特图仍然可以正常显示和测试。

等数据准备好后，刷新页面即可看到真实数据。

---

## 相关文件

- `src/app/pages/team-leader/services/designer.service.ts` - 修复Date处理，添加调试日志
- `src/app/pages/team-leader/dashboard/dashboard.ts` - 调用数据服务
- `rules/schemas.md` - YSS项目的数据表结构


