|
|
@@ -378,6 +378,7 @@ export class Dashboard implements OnInit, OnDestroy {
|
|
|
const deadlineValue = project.get('deadline');
|
|
|
const deliveryDateValue = project.get('deliveryDate');
|
|
|
const expectedDeliveryDateValue = project.get('expectedDeliveryDate');
|
|
|
+ const demodayValue = project.get('demoday'); // 🆕 小图对图日期
|
|
|
|
|
|
// 🔧 如果 get() 方法都返回假值,尝试从 createdAt/updatedAt 属性直接获取
|
|
|
// Parse 对象的 createdAt/updatedAt 是内置属性
|
|
|
@@ -395,6 +396,7 @@ export class Dashboard implements OnInit, OnDestroy {
|
|
|
status: project.get('status') || '进行中',
|
|
|
currentStage: project.get('currentStage') || '未知阶段',
|
|
|
deadline: deadlineValue || deliveryDateValue || expectedDeliveryDateValue,
|
|
|
+ demoday: demodayValue, // 🆕 小图对图日期
|
|
|
createdAt: finalCreatedAt,
|
|
|
designerName: profileName
|
|
|
};
|
|
|
@@ -461,6 +463,7 @@ export class Dashboard implements OnInit, OnDestroy {
|
|
|
const deadlineValue = project.get('deadline');
|
|
|
const deliveryDateValue = project.get('deliveryDate');
|
|
|
const expectedDeliveryDateValue = project.get('expectedDeliveryDate');
|
|
|
+ const demodayValue = project.get('demoday'); // 🆕 小图对图日期
|
|
|
|
|
|
// 🔧 如果 get() 方法都返回假值,尝试从 createdAt/updatedAt 属性直接获取
|
|
|
let finalCreatedAt = createdAtValue || updatedAtValue;
|
|
|
@@ -477,6 +480,7 @@ export class Dashboard implements OnInit, OnDestroy {
|
|
|
status: project.get('status') || '进行中',
|
|
|
currentStage: project.get('currentStage') || '未知阶段',
|
|
|
deadline: deadlineValue || deliveryDateValue || expectedDeliveryDateValue,
|
|
|
+ demoday: demodayValue, // 🆕 小图对图日期
|
|
|
createdAt: finalCreatedAt,
|
|
|
designerName: assigneeName
|
|
|
};
|
|
|
@@ -535,48 +539,45 @@ export class Dashboard implements OnInit, OnDestroy {
|
|
|
|
|
|
console.log('📊 重新计算项目时间轴数据...');
|
|
|
|
|
|
- // 从 designerWorkloadMap 获取所有组员的项目数据(去重)
|
|
|
- const projectMap = new Map<string, any>(); // 使用Map去重,key为projectId
|
|
|
+ // 🔧 不去重,保留所有项目-设计师关联关系(一个项目可能有多个设计师)
|
|
|
const allDesignerProjects: any[] = [];
|
|
|
|
|
|
- // 调试:打印所有的 designerKey
|
|
|
+ // 调试:打印所有的 designerKey 和项目数量
|
|
|
const allKeys: string[] = [];
|
|
|
+ let totalProjectsInMap = 0;
|
|
|
this.designerWorkloadMap.forEach((projects, designerKey) => {
|
|
|
- allKeys.push(designerKey);
|
|
|
+ allKeys.push(`${designerKey}(${projects.length})`);
|
|
|
+ totalProjectsInMap += projects.length;
|
|
|
});
|
|
|
console.log('📊 designerWorkloadMap所有key:', allKeys);
|
|
|
+ console.log('📊 designerWorkloadMap 总项目数(含重复,因为一个项目可能有多个设计师):', totalProjectsInMap);
|
|
|
|
|
|
this.designerWorkloadMap.forEach((projects, designerKey) => {
|
|
|
- // 只处理真实的设计师名称(中文姓名),跳过ID形式的key
|
|
|
- // 判断条件:
|
|
|
- // 1. 是字符串
|
|
|
- // 2. 长度在2-10之间(中文姓名通常2-4个字)
|
|
|
- // 3. 包含中文字符(最可靠的判断)
|
|
|
- const isChineseName = typeof designerKey === 'string'
|
|
|
- && designerKey.length >= 2
|
|
|
- && designerKey.length <= 10
|
|
|
- && /[\u4e00-\u9fa5]/.test(designerKey); // 包含中文字符
|
|
|
-
|
|
|
- if (isChineseName) {
|
|
|
+ // 🔧 改进判断逻辑:跳过明显的 ID 格式(Parse objectId 是10位字母数字组合)
|
|
|
+ // 只要包含中文字符,就认为是设计师名称
|
|
|
+ const isParseId = typeof designerKey === 'string'
|
|
|
+ && designerKey.length === 10
|
|
|
+ && /^[a-zA-Z0-9]{10}$/.test(designerKey); // Parse ID 格式:10位字母数字
|
|
|
+
|
|
|
+ const isDesignerName = !isParseId && typeof designerKey === 'string' && /[\u4e00-\u9fa5]/.test(designerKey);
|
|
|
+
|
|
|
+ if (isDesignerName) {
|
|
|
console.log('✅ 使用设计师名称:', designerKey, '项目数:', projects.length);
|
|
|
projects.forEach(proj => {
|
|
|
- const projectId = proj.id;
|
|
|
- // 使用projectId去重
|
|
|
- if (!projectMap.has(projectId)) {
|
|
|
- const projectWithDesigner = {
|
|
|
- ...proj,
|
|
|
- designerName: designerKey
|
|
|
- };
|
|
|
- projectMap.set(projectId, projectWithDesigner);
|
|
|
- allDesignerProjects.push(projectWithDesigner);
|
|
|
- }
|
|
|
+ // ✅ 不去重,保留每个设计师-项目的关联
|
|
|
+ const projectWithDesigner = {
|
|
|
+ ...proj,
|
|
|
+ designerName: designerKey // 使用当前的设计师名称
|
|
|
+ };
|
|
|
+ allDesignerProjects.push(projectWithDesigner);
|
|
|
});
|
|
|
} else {
|
|
|
- console.log('⏭️ 跳过key:', designerKey, '(不是中文姓名)');
|
|
|
+ console.log('⏭️ 跳过key:', designerKey, '(Parse ID 或无效格式)', '类型:', typeof designerKey, '长度:', designerKey.length);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- console.log('📊 从designerWorkloadMap转换项目数据:', allDesignerProjects.length, '个项目(已去重)');
|
|
|
+ console.log('📊 从designerWorkloadMap转换项目数据:', allDesignerProjects.length, '个项目-设计师关联');
|
|
|
+ console.log('📊 对比 this.projects 数量:', this.projects?.length || 0, '(不重复的项目数)');
|
|
|
|
|
|
this.projectTimelineData = allDesignerProjects.map((project, index) => {
|
|
|
const now = new Date();
|
|
|
@@ -591,9 +592,17 @@ export class Dashboard implements OnInit, OnDestroy {
|
|
|
const projectDuration = 3 + (index % 5); // 3-7天的项目周期
|
|
|
const adjustedStartDate = new Date(adjustedEndDate.getTime() - projectDuration * 24 * 60 * 60 * 1000);
|
|
|
|
|
|
- // 对图时间:交付前1-2天
|
|
|
- const reviewDaysBefore = 1 + (index % 2); // 交付前1-2天
|
|
|
- const adjustedReviewDate = new Date(adjustedEndDate.getTime() - reviewDaysBefore * 24 * 60 * 60 * 1000);
|
|
|
+ // 🆕 小图对图时间:优先使用真实的 demoday,否则默认为交付前1-2天
|
|
|
+ let adjustedReviewDate: Date;
|
|
|
+ if (project.demoday && project.demoday instanceof Date) {
|
|
|
+ // 使用真实的小图对图日期
|
|
|
+ adjustedReviewDate = project.demoday;
|
|
|
+ console.log(`📋 项目 ${project.name} 使用真实小图日期:`, adjustedReviewDate.toLocaleDateString());
|
|
|
+ } else {
|
|
|
+ // 默认计算:交付前1-2天
|
|
|
+ const reviewDaysBefore = 1 + (index % 2);
|
|
|
+ adjustedReviewDate = new Date(adjustedEndDate.getTime() - reviewDaysBefore * 24 * 60 * 60 * 1000);
|
|
|
+ }
|
|
|
|
|
|
// 计算距离交付还有几天
|
|
|
const daysUntilDeadline = Math.ceil((adjustedEndDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
|
|
@@ -733,12 +742,12 @@ export class Dashboard implements OnInit, OnDestroy {
|
|
|
|
|
|
// 调试:打印前3个项目的时间信息
|
|
|
if (this.projectTimelineData.length > 0) {
|
|
|
- console.log('📅 示例项目时间:');
|
|
|
- this.projectTimelineData.slice(0, 3).forEach(p => {
|
|
|
- console.log(` - ${p.projectName}:`, {
|
|
|
- 开始: p.startDate.toLocaleDateString(),
|
|
|
- 对图: p.reviewDate.toLocaleDateString(),
|
|
|
- 交付: p.deliveryDate.toLocaleDateString(),
|
|
|
+ console.log('📅 示例项目时间(前5个):');
|
|
|
+ this.projectTimelineData.slice(0, 5).forEach(p => {
|
|
|
+ console.log(` 🎨 ${p.projectName}:`, {
|
|
|
+ 开始: p.startDate.toLocaleDateString() + ' ' + p.startDate.toLocaleTimeString(),
|
|
|
+ 小图对图: p.reviewDate.toLocaleDateString() + ' ' + p.reviewDate.toLocaleTimeString(),
|
|
|
+ 交付: p.deliveryDate.toLocaleDateString() + ' ' + p.deliveryDate.toLocaleTimeString(),
|
|
|
状态: p.status,
|
|
|
阶段: p.stageName
|
|
|
});
|