20251024-project-list-parse-integration-complete.md 11 KB

客服项目列表Parse Server数据集成完成

📋 任务概述

完成客服项目列表页面与Parse Server真实数据的集成,实现项目数据的正确显示和渲染,并优化UI样式。

✅ 完成内容

1. Parse Server数据集成

1.1 公司信息初始化

  • 方法1(优先): 从localStorage.getItem('company')获取公司ID
  • 方法2(备用): 从ProfileService.getCurrentProfile()获取公司信息
  • 参考了team-leader和admin的实现方式,确保数据加载的稳定性

    // 初始化用户和公司信息
    private async initializeUserAndCompany(): Promise<void> {
    try {
    // 方法1: 从localStorage获取公司ID(参考team-leader的实现)
    const companyId = localStorage.getItem('company');
    if (companyId) {
      const CompanyClass = Parse.Object.extend('Company');
      this.company = new CompanyClass();
      this.company.id = companyId;
      console.log('✅ 从localStorage加载公司ID:', companyId);
    } else {
      // 方法2: 从Profile获取公司信息
      this.currentProfile = await this.profileService.getCurrentProfile();
      // ...
    }
    } catch (error) {
    console.error('❌ 初始化用户和公司信息失败:', error);
    this.loadError.set('加载用户信息失败,请刷新页面重试');
    }
    }
    

1.2 项目数据查询

  • 使用Parse Query查询Project表
  • 查询条件:
    • company: 等于当前公司指针
    • isDeleted: 不等于true(兼容没有该字段的数据)
  • Include关联数据:contact, assignee, owner
  • 排序:按updatedAt降序
  • 限制:最多500个项目

    const ProjectQuery = new Parse.Query('Project');
    ProjectQuery.equalTo('company', this.getCompanyPointer());
    ProjectQuery.notEqualTo('isDeleted', true);
    ProjectQuery.include('contact', 'assignee', 'owner');
    ProjectQuery.descending('updatedAt');
    ProjectQuery.limit(500);
    
    const projectObjects = await ProjectQuery.find();
    

1.3 数据转换

将Parse Server的Project对象转换为前端ProjectListItem格式:

  • id: 项目ID
  • name: 项目标题(title)
  • customerName: 联系人姓名(contact.name)
  • status: 项目状态(进行中、已完成、已暂停、已延期)
  • currentStage: 当前阶段(订单分配、需求沟通、建模、软装、渲染、后期、尾款结算、投诉处理等)
  • assigneeName: 负责人姓名(assignee.name)
  • deadline: 截止日期
  • 等等

2. 项目分组逻辑

按照业务需求,将项目分为四个阶段:

2.1 订单分配(order)

  • 未分配设计师(!assigneeId || assigneeId.trim() === ''
  • 或者currentStage === '订单分配'

2.2 确认需求(requirements)

  • currentStage为:需求沟通、方案确认
  • 排除售后和订单分配阶段

2.3 交付执行(delivery)

  • currentStage为:建模、软装、渲染、后期、尾款结算
  • 排除售后和订单分配阶段

2.4 售后(aftercare)

  • status === '已完成'
  • currentStage为:投诉处理、客户评价

    // 看板分组逻辑
    private isOrderAssignment(p: Project): boolean {
    return !p.assigneeId || p.assigneeId.trim() === '' || p.currentStage === '订单分配';
    }
    
    private isRequirementsConfirmation(p: Project): boolean {
    const requirementStages: ProjectStage[] = ['需求沟通', '方案确认'];
    return !this.isAftercare(p) && !this.isOrderAssignment(p) && requirementStages.includes(p.currentStage);
    }
    
    private isDeliveryExecution(p: Project): boolean {
    const deliveryStages: ProjectStage[] = ['建模', '软装', '渲染', '后期', '尾款结算'];
    return !this.isAftercare(p) && !this.isOrderAssignment(p) && deliveryStages.includes(p.currentStage);
    }
    
    private isAftercare(p: Project): boolean {
    const aftercareStages: ProjectStage[] = ['投诉处理', '客户评价'];
    return p.status === '已完成' || aftercareStages.includes(p.currentStage);
    }
    

3. UI/UX改进

3.1 加载状态

添加了加载动画和提示:

@if (isLoading()) {
  <div class="loading-container">
    <div class="loading-spinner"></div>
    <p>正在加载项目数据...</p>
  </div>
}

样式特点:

  • 旋转加载动画
  • 居中显示
  • 最小高度400px

3.2 错误状态

添加了错误提示和重试按钮:

@if (loadError()) {
  <div class="error-container">
    <svg>...</svg>
    <p>{{ loadError() }}</p>
    <button class="retry-btn" (click)="loadProjects()">重试</button>
  </div>
}

3.3 空状态

每个看板列都有空状态提示:

@if (getProjectsByColumn(col.id).length === 0) {
  <div class="empty-column">
    <svg>...</svg>
    <p>暂无项目</p>
  </div>
}

3.4 卡片样式优化

  • 现代化设计

    • 圆角从8px增加到12px
    • 更柔和的阴影效果
    • 边框使用半透明黑色
  • 交互动画

    • 悬停时上移4px(原来2px)
    • 使用cubic-bezier缓动函数
    • 顶部装饰条渐变效果
    • 点击时轻微回弹
  • 装饰元素

    • 卡片顶部3px渐变装饰条
    • 悬停时显示,增强视觉反馈

      .project-content .kanban-card {
      border-radius: 12px;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
      padding: 18px;
      transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
        
      &::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 3px;
      background: linear-gradient(90deg, $primary-color, lighten($primary-color, 15%));
      opacity: 0;
      transition: opacity 0.25s ease;
      }
        
      &:hover {
      transform: translateY(-4px);
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
          
      &::before {
      opacity: 1;
      }
      }
      }
      

3.5 徽章样式优化

"待分配"徽章采用渐变背景和脉动动画:

.project-content .pending-badge {
  background: linear-gradient(135deg, #fff8e1 0%, #ffecb3 100%);
  border-radius: 14px;
  box-shadow: 0 2px 4px rgba($warning-color, 0.1);
  animation: pulse-badge 2s ease-in-out infinite;
}

@keyframes pulse-badge {
  0%, 100% {
    box-shadow: 0 2px 4px rgba($warning-color, 0.1);
  }
  50% {
    box-shadow: 0 2px 8px rgba($warning-color, 0.25);
  }
}

3.6 文字排版优化

  • 项目名称:字重600,行高1.4,字间距-0.01em
  • 项目ID:字重500,上边距4px
  • 更好的视觉层次和可读性

4. 调试信息

添加了详细的控制台日志,便于调试:

  • ✅ 成功加载公司ID
  • ✅ 成功加载项目数据(显示数量)
  • ⚠️ 未找到项目数据时的提示
  • ❌ 错误信息的详细输出

    console.log(`✅ 从Parse Server加载了 ${projectObjects.length} 个项目`);
    
    if (projectObjects.length === 0) {
    console.warn('⚠️ 未找到项目数据,请检查:');
    console.warn('1. Parse Server中是否有Project数据');
    console.warn('2. 当前公司ID:', this.company.id);
    console.warn('3. 数据是否正确关联到当前公司');
    }
    

📁 修改的文件

TypeScript

  • yss-project/src/app/pages/customer-service/project-list/project-list.ts
    • 优化公司信息初始化逻辑
    • 改进项目数据查询(兼容isDeleted字段)
    • 添加详细的调试日志

HTML

  • yss-project/src/app/pages/customer-service/project-list/project-list.html
    • 添加加载状态组件
    • 添加错误状态组件
    • 添加空列状态提示
    • 优化条件渲染逻辑

SCSS

  • yss-project/src/app/pages/customer-service/project-list/project-list.scss
    • 添加加载状态样式
    • 添加错误状态样式
    • 添加空列状态样式
    • 优化卡片样式(圆角、阴影、动画)
    • 优化徽章样式(渐变、脉动动画)
    • 优化文字排版

🔍 数据查询参考

本实现参考了以下文件的数据查询方式:

  • yss-project/src/app/pages/team-leader/services/designer.service.ts
  • yss-project/src/app/pages/team-leader/services/dashboard-data.service.ts
  • yss-project/src/app/pages/admin/dashboard/dashboard.service.ts
  • yss-project/src/app/pages/admin/project-management/project-management.ts

🎯 数据表使用

Project表

  • 用途: 项目主表
  • 关键字段:
    • company: 公司指针(用于筛选)
    • title: 项目标题
    • status: 项目状态
    • currentStage: 当前阶段
    • contact: 联系人指针
    • assignee: 负责人指针
    • deadline: 截止日期
    • isDeleted: 是否删除

ContactInfo表

  • 用途: 客户联系人信息
  • 关键字段:
    • name: 联系人姓名

Profile表

  • 用途: 用户信息(设计师等)
  • 关键字段:
    • name: 用户姓名

🚀 使用说明

1. 确保Parse Server配置正确

检查localStorage中是否有company字段:

console.log('公司ID:', localStorage.getItem('company'));

2. 访问页面

http://localhost:4200/customer-service/project-list

3. 查看控制台日志

打开浏览器开发者工具,查看控制台输出:

  • 如果显示"✅ 从Parse Server加载了 X 个项目",说明数据加载成功
  • 如果显示"⚠️ 未找到项目数据",说明数据库中没有符合条件的项目
  • 如果显示"❌ 初始化用户和公司信息失败",说明公司信息获取失败

4. 数据调试

如果没有数据显示,请检查:

  1. Parse Server是否正常运行
  2. Project表中是否有数据
  3. Project数据的company字段是否正确关联到当前公司
  4. localStorage.getItem('company')是否有值

📊 数据流程

1. 页面初始化
   ↓
2. initializeUserAndCompany()
   ├─ 从localStorage获取company ID
   └─ 或从ProfileService获取company
   ↓
3. loadProjects()
   ├─ 创建Parse Query
   ├─ 设置查询条件(company, isDeleted)
   ├─ Include关联数据(contact, assignee)
   └─ 执行查询
   ↓
4. 数据转换
   ├─ 将Parse Object转换为ProjectListItem
   └─ 映射status和stage
   ↓
5. 项目分组
   ├─ 订单分配
   ├─ 确认需求
   ├─ 交付执行
   └─ 售后
   ↓
6. UI渲染
   ├─ 看板视图(卡片)
   ├─ 列表视图
   └─ 监控大盘

✨ 特色功能

  1. 智能分组: 根据项目状态和阶段自动分组到四个看板列
  2. 实时数据: 直接从Parse Server加载最新数据
  3. 优雅加载: 加载动画、错误提示、空状态提示
  4. 精美UI: 现代化卡片设计、流畅动画、渐变装饰
  5. 调试友好: 详细的控制台日志,便于问题排查

🎨 设计亮点

  1. 卡片悬停效果: 上移动画 + 顶部渐变装饰条
  2. 徽章脉动动画: "待分配"徽章的呼吸效果
  3. 柔和阴影: 多层次阴影营造深度感
  4. 圆角设计: 12px圆角更加现代
  5. 渐变背景: 徽章使用渐变背景增强视觉效果

📝 注意事项

  1. 确保Parse Server已正确配置并运行
  2. 确保Project表中有测试数据
  3. 确保数据的company字段正确关联
  4. 如果使用企业微信授权,确保已正确配置
  5. 本地开发时,可能需要临时注释WxworkAuthGuard

🔗 相关文档


完成时间: 2024-10-24
开发者: AI Assistant
状态: ✅ 已完成