|
|
@@ -162,15 +162,43 @@ export class ProjectTimelineComponent implements OnInit, OnDestroy {
|
|
|
|
|
|
/**
|
|
|
* 获取项目在时间轴上的位置和宽度
|
|
|
+ * ✅ 修复:处理项目结束日期在过去的情况
|
|
|
*/
|
|
|
getProjectPosition(project: ProjectTimeline): { left: string; width: string; background: string } {
|
|
|
const rangeStart = this.timeRangeStart.getTime();
|
|
|
const rangeEnd = this.timeRangeEnd.getTime();
|
|
|
const rangeDuration = rangeEnd - rangeStart;
|
|
|
|
|
|
+ // ✅ 修复:如果项目完全在过去,显示一个最小宽度的条
|
|
|
+ if (project.endDate.getTime() < rangeStart) {
|
|
|
+ // 项目完全在过去,显示在时间轴最左侧,宽度为最小可见宽度
|
|
|
+ return {
|
|
|
+ left: '0%',
|
|
|
+ width: '2px', // 最小可见宽度
|
|
|
+ background: this.getProjectUrgencyColor(project)
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ // ✅ 修复:如果项目开始日期在过去,但结束日期在未来,从时间轴开始位置显示
|
|
|
const projectStart = Math.max(project.startDate.getTime(), rangeStart);
|
|
|
const projectEnd = Math.min(project.endDate.getTime(), rangeEnd);
|
|
|
|
|
|
+ // ✅ 修复:确保 projectEnd >= projectStart
|
|
|
+ if (projectEnd < projectStart) {
|
|
|
+ // 这种情况不应该发生,但如果发生了,显示最小宽度
|
|
|
+ console.warn(`⚠️ 项目 ${project.projectName} 的结束日期早于开始日期或时间范围开始`, {
|
|
|
+ startDate: project.startDate.toLocaleString('zh-CN'),
|
|
|
+ endDate: project.endDate.toLocaleString('zh-CN'),
|
|
|
+ rangeStart: new Date(rangeStart).toLocaleString('zh-CN'),
|
|
|
+ rangeEnd: new Date(rangeEnd).toLocaleString('zh-CN')
|
|
|
+ });
|
|
|
+ return {
|
|
|
+ left: '0%',
|
|
|
+ width: '2px',
|
|
|
+ background: this.getProjectUrgencyColor(project)
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
const left = ((projectStart - rangeStart) / rangeDuration) * 100;
|
|
|
const width = ((projectEnd - projectStart) / rangeDuration) * 100;
|
|
|
|
|
|
@@ -179,7 +207,7 @@ export class ProjectTimelineComponent implements OnInit, OnDestroy {
|
|
|
|
|
|
return {
|
|
|
left: `${Math.max(0, left)}%`,
|
|
|
- width: `${Math.max(1, Math.min(100 - left, width))}%`,
|
|
|
+ width: `${Math.max(2, Math.min(100 - left, width))}%`, // ✅ 修复:最小宽度改为2px(约2%)
|
|
|
background
|
|
|
};
|
|
|
}
|
|
|
@@ -481,8 +509,19 @@ export class ProjectTimelineComponent implements OnInit, OnDestroy {
|
|
|
private buildDesignerStats(): DesignerInfo[] {
|
|
|
const designerMap = new Map<string, DesignerInfo>();
|
|
|
|
|
|
+ // ✅ 过滤已完成的项目后再统计
|
|
|
+ const now = this.currentTime.getTime();
|
|
|
+ const activeProjects = this.projects.filter(project => {
|
|
|
+ // ✅ 修复:使用相同的过滤逻辑
|
|
|
+ const endDatePast = project.endDate.getTime() < now;
|
|
|
+ const daysPast = endDatePast ? Math.floor((now - project.endDate.getTime()) / (1000 * 60 * 60 * 24)) : 0;
|
|
|
+ const isCompleted = (project.currentStage === 'delivery' && endDatePast) ||
|
|
|
+ (endDatePast && daysPast > 7);
|
|
|
+ return !isCompleted;
|
|
|
+ });
|
|
|
+
|
|
|
// 🔧 统计每个设计师负责的项目(不去重,因为项目列表已经包含了所有设计师-项目关联)
|
|
|
- this.projects.forEach(project => {
|
|
|
+ activeProjects.forEach(project => {
|
|
|
const designerName = project.designerName || '未分配';
|
|
|
|
|
|
if (!designerMap.has(designerName)) {
|
|
|
@@ -525,6 +564,55 @@ export class ProjectTimelineComponent implements OnInit, OnDestroy {
|
|
|
applyFilters(): void {
|
|
|
let result = [...this.projects];
|
|
|
|
|
|
+ // ✅ 过滤已完成的项目
|
|
|
+ const now = this.currentTime.getTime();
|
|
|
+ const filteredOut: any[] = [];
|
|
|
+
|
|
|
+ result = result.filter(project => {
|
|
|
+ // 判断项目是否已完成:
|
|
|
+ // 1. currentStage 为 'delivery'(交付阶段)且 endDate 在过去
|
|
|
+ // 2. 或者 endDate 在过去超过7天(给一个缓冲期)
|
|
|
+ const endDatePast = project.endDate.getTime() < now;
|
|
|
+ const daysPast = endDatePast ? Math.floor((now - project.endDate.getTime()) / (1000 * 60 * 60 * 24)) : 0;
|
|
|
+ const isCompleted = (project.currentStage === 'delivery' && endDatePast) ||
|
|
|
+ (endDatePast && daysPast > 7); // ✅ 修复:只过滤结束日期在过去超过7天的项目
|
|
|
+
|
|
|
+ if (isCompleted) {
|
|
|
+ filteredOut.push({
|
|
|
+ projectId: project.projectId,
|
|
|
+ projectName: project.projectName,
|
|
|
+ currentStage: project.currentStage,
|
|
|
+ endDate: project.endDate.toLocaleString('zh-CN'),
|
|
|
+ daysPast: daysPast
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return !isCompleted; // 只保留未完成的项目
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log(`📊 过滤已完成项目后剩余: ${result.length} 个项目(原始: ${this.projects.length})`);
|
|
|
+ if (filteredOut.length > 0) {
|
|
|
+ console.log(`📊 已过滤的项目(${filteredOut.length}个):`, filteredOut.slice(0, 5));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ✅ 调试:检查特定项目
|
|
|
+ const targetProject = this.projects.find(p => p.projectId === 'qCV9QHROSH');
|
|
|
+ if (targetProject) {
|
|
|
+ const endDatePast = targetProject.endDate.getTime() < now;
|
|
|
+ const daysPast = endDatePast ? Math.floor((now - targetProject.endDate.getTime()) / (1000 * 60 * 60 * 24)) : 0;
|
|
|
+ console.log(`📊 新项目 qCV9QHROSH 详情:`, {
|
|
|
+ projectName: targetProject.projectName,
|
|
|
+ currentStage: targetProject.currentStage,
|
|
|
+ startDate: targetProject.startDate.toLocaleString('zh-CN'),
|
|
|
+ endDate: targetProject.endDate.toLocaleString('zh-CN'),
|
|
|
+ endDatePast: endDatePast,
|
|
|
+ daysPast: daysPast,
|
|
|
+ isFiltered: filteredOut.some(p => p.projectId === 'qCV9QHROSH')
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ console.warn(`⚠️ 未找到项目 qCV9QHROSH,可能数据还未加载`);
|
|
|
+ }
|
|
|
+
|
|
|
// 设计师筛选
|
|
|
if (this.selectedDesigner !== 'all') {
|
|
|
// 选择单个设计师:显示该设计师的所有项目
|