dashboard.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import { Component, OnInit } from '@angular/core';
  2. import { CommonModule } from '@angular/common';
  3. import { RouterModule } from '@angular/router';
  4. import { ProjectService } from '../../../services/project.service';
  5. import { Task, RenderProgress, CustomerFeedback } from '../../../models/project.model';
  6. @Component({
  7. selector: 'app-dashboard',
  8. imports: [CommonModule, RouterModule],
  9. templateUrl: './dashboard.html',
  10. styleUrl: './dashboard.scss'
  11. })
  12. export class Dashboard implements OnInit {
  13. tasks: Task[] = [];
  14. overdueTasks: Task[] = [];
  15. urgentTasks: Task[] = [];
  16. pendingFeedbacks: {task: Task, feedback: CustomerFeedback}[] = [];
  17. reminderMessage: string = '';
  18. feedbackProjectId: string = '';
  19. countdowns: Map<string, string> = new Map();
  20. constructor(private projectService: ProjectService) {}
  21. ngOnInit(): void {
  22. this.loadTasks();
  23. }
  24. loadTasks(): void {
  25. this.projectService.getTasks().subscribe(tasks => {
  26. // 按阶段优先级排序:建模 > 渲染 > 对图 > 反馈处理 > 后期 > 其他
  27. this.tasks = tasks.sort((a, b) => {
  28. const stagePriority: Record<string, number> = {
  29. '建模': 5,
  30. '渲染': 4,
  31. '对图': 3,
  32. '反馈处理': 2,
  33. '后期': 1,
  34. '完成': 0
  35. };
  36. const priorityA = stagePriority[a.stage] || 0;
  37. const priorityB = stagePriority[b.stage] || 0;
  38. if (priorityA !== priorityB) {
  39. return priorityB - priorityA;
  40. }
  41. // 优先级相同时,按截止日期排序
  42. return a.deadline.getTime() - b.deadline.getTime();
  43. });
  44. // 筛选超期任务
  45. this.overdueTasks = this.tasks.filter(task => task.isOverdue);
  46. // 筛选紧急任务(渲染超时预警,交付前3小时/1小时)
  47. this.urgentTasks = this.tasks.filter(task => {
  48. const now = new Date();
  49. const diffHours = (task.deadline.getTime() - now.getTime()) / (1000 * 60 * 60);
  50. return diffHours <= 3 && diffHours > 0 && task.stage === '渲染';
  51. });
  52. // 设置反馈项目ID
  53. if (this.overdueTasks.length > 0) {
  54. this.feedbackProjectId = this.overdueTasks[0].projectId;
  55. }
  56. // 加载待处理反馈
  57. this.loadPendingFeedbacks();
  58. // 启动倒计时
  59. this.startCountdowns();
  60. });
  61. }
  62. loadPendingFeedbacks(): void {
  63. this.pendingFeedbacks = [];
  64. // 模拟加载待处理反馈数据
  65. this.tasks.forEach(task => {
  66. // 使用模拟数据代替API调用
  67. const mockFeedbacks = [
  68. {
  69. id: 'fb-' + task.id,
  70. projectId: task.projectId,
  71. content: '客户对色彩不满意,需要调整',
  72. isSatisfied: false,
  73. problemLocation: '色彩',
  74. expectedEffect: '更明亮的色调',
  75. referenceCase: '无',
  76. status: '待处理' as const,
  77. createdAt: new Date(Date.now() - 30 * 60 * 1000) // 30分钟前
  78. },
  79. {
  80. id: 'fb-' + task.id + '-2',
  81. projectId: task.projectId,
  82. content: '家具款式需要调整',
  83. isSatisfied: false,
  84. problemLocation: '家具',
  85. expectedEffect: '更现代的款式',
  86. referenceCase: '无',
  87. status: '待处理' as const,
  88. createdAt: new Date(Date.now() - 45 * 60 * 1000) // 45分钟前
  89. }
  90. ];
  91. const pending = mockFeedbacks.filter(feedback =>
  92. feedback.status === '待处理' &&
  93. !feedback.isSatisfied
  94. );
  95. if (pending.length > 0) {
  96. this.pendingFeedbacks.push({task, feedback: pending[0]});
  97. }
  98. });
  99. }
  100. startCountdowns(): void {
  101. // 清除之前的定时器
  102. this.countdowns.clear();
  103. // 为渲染任务启动倒计时
  104. this.tasks.forEach(task => {
  105. if (task.stage === '渲染') {
  106. this.updateCountdown(task.id, task.deadline);
  107. }
  108. });
  109. // 定期更新倒计时
  110. setInterval(() => {
  111. this.tasks.forEach(task => {
  112. if (task.stage === '渲染') {
  113. this.updateCountdown(task.id, task.deadline);
  114. }
  115. });
  116. }, 60000); // 每分钟更新一次
  117. }
  118. updateCountdown(taskId: string, deadline: Date): void {
  119. const now = new Date();
  120. const diffMs = deadline.getTime() - now.getTime();
  121. if (diffMs <= 0) {
  122. this.countdowns.set(taskId, '已超期');
  123. return;
  124. }
  125. const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
  126. const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
  127. if (diffHours > 0) {
  128. this.countdowns.set(taskId, `${diffHours}小时${diffMinutes}分钟`);
  129. } else {
  130. this.countdowns.set(taskId, `${diffMinutes}分钟`);
  131. }
  132. }
  133. getTaskCountdown(taskId: string): string {
  134. return this.countdowns.get(taskId) || '';
  135. }
  136. getTaskStageProgress(taskId: string): number {
  137. const task = this.tasks.find(t => t.id === taskId);
  138. if (!task) return 0;
  139. // 为不同阶段设置固定的模拟进度值
  140. const stageProgressMap: Record<string, number> = {
  141. '建模': 22,
  142. '渲染': 23,
  143. '对图': 50,
  144. '反馈处理': 80,
  145. '后期': 75,
  146. '完成': 100
  147. };
  148. // 对于渲染任务,如果有实际的渲染进度数据,使用它
  149. if (task.stage === '渲染') {
  150. // 在实际应用中,这里会从服务中获取真实的进度
  151. // this.projectService.getRenderProgress(task.projectId).subscribe(progress => {
  152. // if (progress) {
  153. // return progress.completionRate;
  154. // }
  155. // });
  156. }
  157. return stageProgressMap[task.stage] || 0;
  158. }
  159. markTaskAsCompleted(taskId: string): void {
  160. this.projectService.markTaskAsCompleted(taskId).subscribe(() => {
  161. this.loadTasks(); // 重新加载任务列表
  162. });
  163. }
  164. handleFeedback(taskId: string): void {
  165. const task = this.tasks.find(t => t.id === taskId);
  166. if (task) {
  167. // 跳转到项目详情的反馈处理页面
  168. window.location.href = `/designer/project-detail/${task.projectId}#feedback`;
  169. }
  170. }
  171. generateReminderMessage(): void {
  172. this.projectService.generateReminderMessage('overdue').subscribe(message => {
  173. this.reminderMessage = message;
  174. });
  175. }
  176. clearReminder(): void {
  177. this.reminderMessage = '';
  178. }
  179. }