# 客服工作台数据对接真实Parse数据

## 任务概述

将客服工作台（Dashboard）从模拟数据改为对接Parse Server真实数据，确保数据统计准确性，并优化界面显示。

## 修改日期

2024年10月24日

## 涉及文件

1. `src/app/pages/customer-service/dashboard/dashboard.ts` - 组件逻辑
2. `src/app/pages/customer-service/dashboard/dashboard.html` - 模板文件

---

## 修改内容详情

### 1. 数据统计卡片优化

#### 1.1 新增"项目总数"统计卡片

**目的**: 显示公司所有项目的总数

**实现**:
```typescript
// 添加到 stats 对象
totalProjects: signal(0), // 项目总数

// 查询逻辑
const totalProjectQuery = this.createQuery('Project');
const totalProjects = await totalProjectQuery.count();
this.stats.totalProjects.set(totalProjects);
```

**数据来源**: `Project` 表，使用公司过滤条件

#### 1.2 修改"待派单数"为"待分配项目数"

**原名称**: 待派单数  
**新名称**: 待分配项目数

**查询逻辑**:
```typescript
const pendingQuery = this.createQuery('Project');
pendingQuery.equalTo('status', '待分配');
pendingQuery.doesNotExist('assignee');
const pendingAssignments = await pendingQuery.count();
this.stats.pendingAssignments.set(pendingAssignments);
```

**查询条件**:
- 项目状态为 `待分配`
- 未分配设计师 (`assignee` 字段不存在)

---

### 2. 数据对接Parse Server

#### 2.1 项目总数

**查询类**: `Project`  
**过滤条件**:
- `company` = 当前公司指针
- `isDeleted` ≠ true

#### 2.2 新咨询数

**查询类**: `Project`  
**过滤条件**:
- `company` = 当前公司指针
- `isDeleted` ≠ true
- `createdAt` >= 今日0点

**说明**: 统计今日新增的项目数量

#### 2.3 待分配项目数

**查询类**: `Project`  
**过滤条件**:
- `company` = 当前公司指针
- `isDeleted` ≠ true
- `status` = '待分配'
- `assignee` 不存在

#### 2.4 异常项目数

**查询类**: `ProjectIssue`  
**过滤条件**:
- `company` = 当前公司指针
- `isDeleted` ≠ true
- `priority` = 'high'
- `status` = 'open'

**说明**: 统计高优先级且未解决的项目问题

#### 2.5 售后服务数量

**查询类**: `ProjectFeedback`  
**过滤条件**:
- `company` = 当前公司指针
- `isDeleted` ≠ true
- `status` = 'pending'
- `feedbackType` = 'complaint'

**说明**: 统计待处理的客户投诉反馈

---

### 3. 隐藏的功能模块

#### 3.1 核心指标卡片（已移除）

以下核心指标因为没有对应的数据表字段，已从界面移除：
- ❌ 当日成交率（`conversionRateToday`）
- ❌ 待处理投诉数（`pendingComplaints`）
- ❌ 未回复咨询数（`unRepliedConsultations`）

#### 3.2 CRM队列模块（已隐藏）

新客户触达和老客户回访模块已暂时隐藏，等待后续功能开发：
- ❌ 新客户触达列表
- ❌ 老客户回访列表
- ❌ 新客户触达统计（`newCustomerReachCount`、`newCustomerConversionRate`）
- ❌ 老客户回访统计（`oldCustomerFollowUpCount`、`oldCustomerRetentionRate`）

**原因**: 这些功能需要额外的数据表支持，当前数据库schema中没有对应的表结构。

---

### 4. 数据统计看板最终显示

#### 显示的统计卡片（共5个）

| 卡片名称 | 数据来源 | 图标颜色 | 说明 |
|---------|---------|---------|------|
| **项目总数** | `Project` 表计数 | Primary（蓝色） | 显示公司所有项目总数 |
| **新咨询数** | `Project` 表（今日创建） | Secondary（紫色） | 今日新增的咨询项目数 |
| **待分配项目数** | `Project` 表（待分配且无设计师） | Warning（橙色） | 需要分配设计师的项目数 |
| **异常项目** | `ProjectIssue` 表（高优先级未解决） | Danger（红色） | 需要紧急处理的项目问题 |
| **售后服务** | `ProjectFeedback` 表（待处理投诉） | Success（绿色） | 待处理的客户投诉数 |

---

### 5. 代码实现细节

#### 5.1 统计数据结构

```typescript
stats = {
  totalProjects: signal(0),       // 项目总数
  newConsultations: signal(0),    // 新咨询数
  pendingAssignments: signal(0),  // 待分配项目数
  exceptionProjects: signal(0),   // 异常项目数
  afterSalesCount: signal(0)      // 售后服务数量
};
```

#### 5.2 查询实现方式

使用 `createQuery()` 方法创建带公司过滤的查询：

```typescript
private createQuery(className: string): any {
  const query = new Parse.Query(className);
  query.equalTo('company', this.getCompanyPointer());
  query.notEqualTo('isDeleted', true);
  return query;
}
```

#### 5.3 公司指针获取

```typescript
private getCompanyPointer(): any {
  if (!this.company()) {
    throw new Error('公司信息未加载');
  }
  return {
    __type: 'Pointer',
    className: 'Company',
    objectId: this.company().id
  };
}
```

---

### 6. 数据表依赖关系

#### 使用的Parse Server表

1. **Project** - 项目表
   - `objectId`: 项目ID
   - `title`: 项目名称
   - `status`: 项目状态
   - `assignee`: 分配的设计师（Pointer → Profile）
   - `company`: 所属公司（Pointer → Company）
   - `createdAt`: 创建时间
   - `isDeleted`: 是否已删除

2. **ProjectIssue** - 项目问题表
   - `priority`: 优先级（high/medium/low）
   - `status`: 状态（open/closed）
   - `company`: 所属公司
   - `isDeleted`: 是否已删除

3. **ProjectFeedback** - 项目反馈表
   - `status`: 状态（pending/resolved）
   - `feedbackType`: 反馈类型（complaint/suggestion/praise）
   - `company`: 所属公司
   - `isDeleted`: 是否已删除

4. **Company** - 公司表
   - `objectId`: 公司ID（固定为 'cDL6R1hgSi' - 映三色帐套）

---

### 7. 界面变化对比

#### 修改前
- 5个基础统计卡片
- 3个核心指标卡片（渐变样式）
- 新客户触达列表
- 老客户回访列表
- 数据全部为模拟数据

#### 修改后
- 5个基础统计卡片（含新增的"项目总数"）
- ✅ 数据来源于Parse Server真实数据
- ✅ "待派单数"改名为"待分配项目数"
- ❌ 移除3个核心指标卡片
- ❌ 隐藏CRM队列模块（新客户触达、老客户回访）

---

### 8. 数据加载流程

```
ngOnInit()
  ↓
initializeUserAndCompany()
  ↓
loadDashboardData()
  ↓
loadConsultationStats() ←── 加载所有统计数据
  ├─ 项目总数
  ├─ 新咨询数
  ├─ 待分配项目数
  ├─ 异常项目数
  └─ 售后服务数量
```

---

### 9. 错误处理

所有数据加载方法都包含错误处理：

```typescript
try {
  // 查询数据
  const result = await query.count();
  this.stats.xxx.set(result);
  console.log(`✅ 数据加载成功`);
} catch (error) {
  console.error('❌ 数据加载失败:', error);
  // 不抛出错误，允许其他数据继续加载
}
```

---

### 10. 控制台日志

成功加载时的日志格式：
```
✅ 用户和公司信息初始化完成
✅ 咨询统计: 项目总数128, 新咨询12, 待分配5, 异常2, 售后15
✅ 紧急任务加载完成: 8 个任务
✅ 项目动态加载完成: 20 条动态
✅ 客服仪表板数据加载完成
```

---

## 后续优化建议

### 1. 待实现功能

1. **核心指标统计**
   - 需要在数据库中添加相关字段或新建统计表
   - 建议字段：成交率、投诉统计、咨询回复状态

2. **CRM客户管理**
   - 新建 `CustomerContact` 表记录客户触达情况
   - 新建 `CustomerFollowUp` 表记录客户回访记录
   - 添加客户标签系统（价格敏感/品质敏感）

3. **实时数据更新**
   - 考虑使用 Parse Live Query 实现实时数据更新
   - 避免频繁轮询造成服务器压力

### 2. 性能优化

1. **查询优化**
   - 对于频繁查询的字段添加索引（status、createdAt、company）
   - 考虑使用 Parse Cloud Code 实现聚合查询

2. **缓存策略**
   - 对于统计数据考虑添加本地缓存
   - 设置合理的刷新间隔（如5分钟）

---

## 测试验证

### 验证清单

- [x] 项目总数显示正确
- [x] 新咨询数统计今日新增项目
- [x] 待分配项目数仅显示未分配设计师的项目
- [x] 异常项目数统计高优先级问题
- [x] 售后服务数统计待处理投诉
- [x] 所有统计卡片点击跳转正常
- [x] CRM模块已正确隐藏
- [x] 核心指标卡片已移除
- [x] 控制台无错误信息

---

## 相关文档

- [Parse Server数据范式文档](../../rules/schema/project.md)
- [管理员仪表板数据对接](./20251024-admin-dashboard-data-fix.md)
- [客服端滚动问题修复](./20251024-customer-service-scroll-fix.md)

---

## 修改人员

AI Assistant (Claude)

## 备注

此次修改严格遵循了Parse Server的数据表结构，确保数据查询的准确性和安全性。所有查询都包含了公司过滤和软删除过滤，保证了数据的隔离性。

