project-phase-implementation-guide.md 10 KB

项目阶段截止时间功能实施指南

✅ 已完成的实施内容

1. 前端类型定义 ✅

文件位置: src/app/models/project-phase.model.ts

包含内容:

  • PhaseInfo - 单个阶段信息接口
  • PhaseDeadlines - 阶段截止时间集合接口
  • ProjectData - Project.data字段类型定义
  • PHASE_INFO - 阶段常量配置(建模/软装/渲染/后期)
  • PHASE_STATUS_INFO - 阶段状态信息
  • PHASE_PRIORITY_INFO - 优先级信息
  • 工具函数:
    • generateDefaultPhaseDeadlines() - 生成默认阶段截止时间
    • isPhaseDelayed() - 检查阶段是否延期
    • getPhaseDaysRemaining() - 获取阶段剩余天数
    • getPhaseProgress() - 获取阶段进度百分比

2. 项目时间轴组件更新 ✅

文件位置:

  • src/app/pages/team-leader/project-timeline/project-timeline.ts
  • src/app/pages/team-leader/project-timeline/project-timeline.html

更新内容:

  • ✅ 导入阶段类型定义和工具函数
  • ✅ 扩展 ProjectTimeline 接口添加 phaseDeadlines 字段
  • ✅ 添加 TimelineEvent 接口支持多种事件类型
  • ✅ 新增 getProjectEvents() 方法统一获取所有事件(含阶段截止)
  • ✅ 新增阶段相关工具方法:
    • getPhaseLabel() - 获取阶段标签
    • getPhaseIcon() - 获取阶段图标
    • getPhaseColor() - 获取阶段颜色
  • ✅ 模板更新:
    • 使用统一的事件标记循环显示所有事件
    • 图例添加阶段截止时间说明(🎨建模/🪑软装/🖼️渲染/✨后期)

3. Dashboard组件数据传递 ✅

文件位置: src/app/pages/team-leader/dashboard/dashboard.ts

更新内容:

  • convertToProjectTimeline() 方法中读取 project.data.phaseDeadlines
  • ✅ 将阶段截止时间数据传递给时间轴组件

4. Cloud Code数据迁移脚本 ✅

文件位置: cloud/jobs/migrate-project-phase-deadlines.js

功能:

  • migrateProjectPhaseDeadlines - 批量为现有项目添加阶段截止时间
    • 支持干跑模式(dryRun: true
    • 支持批量处理(batchSize: 100
    • 根据项目deadline反推各阶段时间
    • 详细的进度和统计信息
  • testProjectPhaseDeadlines - 测试单个项目的阶段时间生成

5. Cloud Code工具函数 ✅

文件位置: cloud/utils/project-phase-utils.js

功能:

  • generatePhaseDeadlines() - 生成阶段截止时间
  • getCompanyPhaseDurations() - 获取公司级默认工期配置
  • updatePhaseStatus() - 更新阶段状态
  • getCurrentPhase() - 获取当前阶段
  • isPhaseDelayed() - 检查是否延期
  • getPhaseDaysRemaining() - 获取剩余天数

Cloud Function:

  • generateProjectPhaseDeadlines - 生成阶段截止时间
  • updateProjectPhaseStatus - 更新阶段状态

6. 设计方案文档 ✅

文件位置: docs/schema/project-phase-deadlines-design.md

包含完整的:

  • 数据结构设计
  • JSON示例
  • 前后端代码示例
  • 可视化建议
  • 实施步骤

🚀 如何使用

前端使用示例

1. 在组件中使用类型定义

import { PhaseDeadlines, PHASE_INFO, generateDefaultPhaseDeadlines } from '../models/project-phase.model';

// 生成默认阶段截止时间
const phaseDeadlines = generateDefaultPhaseDeadlines(new Date());

// 访问阶段信息
const modelingPhase = phaseDeadlines.modeling;
console.log('建模截止时间:', modelingPhase?.deadline);

// 使用常量获取阶段信息
const phaseConfig = PHASE_INFO.modeling;
console.log('建模阶段:', phaseConfig.label, phaseConfig.icon, phaseConfig.color);

2. 在项目时间轴中展示

时间轴组件已自动支持阶段截止时间展示,只需确保传入的项目数据包含 phaseDeadlines 字段:

const projectData: ProjectTimeline = {
  projectId: 'xxx',
  projectName: '李总现代简约全案',
  // ... 其他字段
  phaseDeadlines: {
    modeling: {
      deadline: new Date('2024-12-08'),
      status: 'in_progress',
      estimatedDays: 7
    },
    // ... 其他阶段
  }
};

Cloud Code使用示例

1. 数据迁移(为现有项目添加阶段时间)

// 干跑模式(只计算不保存)
Parse.Cloud.startJob('migrateProjectPhaseDeadlines', {
  dryRun: true,
  batchSize: 50
});

// 正式迁移
Parse.Cloud.startJob('migrateProjectPhaseDeadlines', {
  dryRun: false,
  batchSize: 100
});

2. 创建项目时生成阶段截止时间

// 在afterSave钩子中自动生成
Parse.Cloud.afterSave("Project", async (request) => {
  const project = request.object;
  
  // 检查是否是新项目且有deadline
  if (project.existed() || !project.get("deadline")) {
    return;
  }
  
  const data = project.get("data") || {};
  
  // 如果已经有phaseDeadlines,跳过
  if (data.phaseDeadlines) {
    return;
  }
  
  // 生成阶段截止时间
  const { generatePhaseDeadlines } = require('./utils/project-phase-utils');
  const phaseDeadlines = generatePhaseDeadlines(
    project.get("createdAt"),
    project.get("deadline")
  );
  
  data.phaseDeadlines = phaseDeadlines;
  project.set("data", data);
  
  await project.save(null, { useMasterKey: true });
});

3. 更新阶段状态

// 方式1:使用Cloud Function
await Parse.Cloud.run('updateProjectPhaseStatus', {
  projectId: 'xxx',
  phaseName: 'modeling',
  status: 'completed',
  additionalData: {
    completedAt: new Date(),
    notes: '建模阶段已完成'
  }
});

// 方式2:直接使用工具函数
const { updatePhaseStatus } = require('./utils/project-phase-utils');
await updatePhaseStatus('projectId', 'modeling', 'completed', {
  completedAt: new Date()
});

4. 设置公司默认工期

// 在Company.data中添加配置
const company = await new Parse.Query("Company").get(companyId);
const data = company.get("data") || {};

data.phaseDefaultDurations = {
  modeling: 8,        // 建模8天
  softDecor: 5,       // 软装5天
  rendering: 7,       // 渲染7天
  postProcessing: 4   // 后期4天
};

company.set("data", data);
await company.save(null, { useMasterKey: true });

📊 数据结构说明

Project.data.phaseDeadlines 字段结构

{
  "phaseDeadlines": {
    "modeling": {
      "startDate": "2024-12-01T00:00:00.000Z",
      "deadline": "2024-12-08T23:59:59.999Z",
      "estimatedDays": 7,
      "status": "in_progress",
      "completedAt": "2024-12-07T18:30:00.000Z",
      "assignee": {
        "__type": "Pointer",
        "className": "Profile",
        "objectId": "prof001"
      },
      "priority": "high",
      "notes": "客户要求加急"
    },
    "softDecor": {
      "deadline": "2024-12-13T23:59:59.999Z",
      "estimatedDays": 4,
      "status": "not_started",
      "priority": "medium"
    },
    "rendering": {
      "deadline": "2024-12-20T23:59:59.999Z",
      "estimatedDays": 6,
      "status": "not_started",
      "priority": "high"
    },
    "postProcessing": {
      "deadline": "2024-12-24T23:59:59.999Z",
      "estimatedDays": 3,
      "status": "not_started",
      "priority": "medium"
    }
  }
}

字段说明

字段 类型 必填 说明
startDate Date 阶段开始时间
deadline Date 阶段截止时间
estimatedDays Number 预计工期(天数)
status String 阶段状态 (not_started/in_progress/completed/delayed)
completedAt Date 实际完成时间
assignee Pointer 负责人
priority String 优先级 (low/medium/high/urgent)
notes String 备注信息

🎨 可视化效果

阶段图标和颜色

  • 🎨 建模 - 蓝色 (#2196F3)
  • 🪑 软装 - 紫色 (#9C27B0)
  • 🖼️ 渲染 - 橙色 (#FF9800)
  • 后期 - 绿色 (#4CAF50)

时间轴展示

  • 项目条形图按紧急程度显示颜色
  • 阶段截止时间在时间轴上显示为彩色标记
  • 悬停显示详细信息(阶段名称、截止时间)
  • 只显示今日线之后的未来事件

🧪 测试建议

1. 单元测试

describe('PhaseDeadlines', () => {
  it('should generate default phase deadlines', () => {
    const startDate = new Date('2024-12-01');
    const phaseDeadlines = generateDefaultPhaseDeadlines(startDate);
    
    expect(phaseDeadlines.modeling).toBeDefined();
    expect(phaseDeadlines.softDecor).toBeDefined();
    expect(phaseDeadlines.rendering).toBeDefined();
    expect(phaseDeadlines.postProcessing).toBeDefined();
  });
  
  it('should check if phase is delayed', () => {
    const pastPhase: PhaseInfo = {
      deadline: new Date('2024-01-01'),
      status: 'in_progress'
    };
    expect(isPhaseDelayed(pastPhase)).toBe(true);
    
    const futurePhase: PhaseInfo = {
      deadline: new Date('2025-12-31'),
      status: 'in_progress'
    };
    expect(isPhaseDelayed(futurePhase)).toBe(false);
  });
});

2. E2E测试

  1. 创建新项目,验证自动生成阶段截止时间
  2. 切换到时间轴视图,验证阶段标记显示
  3. 悬停阶段标记,验证工具提示信息
  4. 更新阶段状态,验证UI更新

📋 待办事项

已完成 ✅

  • 创建前端类型定义文件
  • 更新项目时间轴组件
  • 创建数据迁移脚本
  • 创建工具函数
  • 编写使用文档

可选增强功能 🔮

  • 添加阶段管理界面(手动调整截止时间)
  • 阶段延期自动提醒功能
  • 阶段进度追踪报表
  • 支持自定义阶段(不限于4个阶段)
  • 阶段依赖关系管理

🐛 故障排查

问题1:时间轴没有显示阶段标记

原因:项目数据中没有 phaseDeadlines 字段

解决方案

  1. 运行数据迁移脚本为现有项目添加数据
  2. 或手动为项目添加 phaseDeadlines 数据

问题2:阶段时间计算不正确

原因:项目没有 deadline 字段

解决方案: 确保所有项目都设置了 deadline 字段

问题3:时间轴性能问题

原因:项目数量过多

解决方案

  1. 使用筛选功能减少显示的项目数量
  2. 考虑添加分页或虚拟滚动

📞 技术支持

如有问题,请参考:

  1. 设计方案文档:docs/schema/project-phase-deadlines-design.md
  2. schemas.md数据范式文档:rules/schemas.md
  3. 代码注释和类型定义

最后更新: 2024年11月6日
版本: 1.0.0