todo-task.service.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import { Injectable } from '@angular/core';
  2. import { FmodeParse } from 'fmode-ng/parse';
  3. import { IssueStatus, IssuePriority, IssueType } from '../../../../modules/project/services/project-issue.service';
  4. import { TodoTaskFromIssue } from '../dashboard/dashboard.model';
  5. @Injectable({
  6. providedIn: 'root'
  7. })
  8. export class TodoTaskService {
  9. constructor() { }
  10. /**
  11. * 从问题板块加载待办任务
  12. */
  13. async getTodoTasks(): Promise<TodoTaskFromIssue[]> {
  14. try {
  15. const Parse: any = FmodeParse.with('nova');
  16. const query = new Parse.Query('ProjectIssue');
  17. // 筛选条件:待处理 + 处理中
  18. query.containedIn('status', ['待处理', '处理中']);
  19. query.notEqualTo('isDeleted', true);
  20. // 关联数据
  21. query.include(['project', 'creator', 'assignee']);
  22. // 排序:更新时间倒序
  23. query.descending('updatedAt');
  24. // 限制数量
  25. query.limit(50);
  26. const results = await query.find();
  27. console.log(`📥 查询到 ${results.length} 条问题记录`);
  28. // 数据转换
  29. const tasks = await Promise.all(results.map(async (obj: any) => {
  30. let project = obj.get('project');
  31. const assignee = obj.get('assignee');
  32. const creator = obj.get('creator');
  33. const data = obj.get('data') || {};
  34. let projectName = '未知项目';
  35. let projectId = '';
  36. if (project) {
  37. projectId = project.id;
  38. projectName = project.get('name');
  39. if (!projectName && projectId) {
  40. try {
  41. const projectQuery = new Parse.Query('Project');
  42. const fetchedProject = await projectQuery.get(projectId);
  43. projectName = fetchedProject.get('name') || fetchedProject.get('title') || '未知项目';
  44. } catch (error) {
  45. console.warn(`⚠️ 无法加载项目 ${projectId}:`, error);
  46. projectName = `项目-${projectId.slice(0, 6)}`;
  47. }
  48. }
  49. } else {
  50. console.warn('⚠️ 问题缺少关联项目:', {
  51. issueId: obj.id,
  52. title: obj.get('title')
  53. });
  54. }
  55. return {
  56. id: obj.id,
  57. title: obj.get('title') || obj.get('description')?.slice(0, 40) || '未命名问题',
  58. description: obj.get('description'),
  59. priority: obj.get('priority') as IssuePriority || 'medium',
  60. type: obj.get('issueType') as IssueType || 'task',
  61. status: this.zh2enStatus(obj.get('status')) as IssueStatus,
  62. projectId,
  63. projectName,
  64. relatedSpace: obj.get('relatedSpace') || data.relatedSpace,
  65. relatedStage: obj.get('relatedStage') || data.relatedStage,
  66. assigneeName: assignee?.get('name') || assignee?.get('realname') || '未指派',
  67. creatorName: creator?.get('name') || creator?.get('realname') || '未知',
  68. createdAt: obj.createdAt || new Date(),
  69. updatedAt: obj.updatedAt || new Date(),
  70. dueDate: obj.get('dueDate'),
  71. tags: (data.tags || []) as string[]
  72. } as TodoTaskFromIssue;
  73. }));
  74. // 排序:优先级 -> 时间
  75. return tasks.sort((a, b) => {
  76. const priorityA = this.getPriorityOrder(a.priority);
  77. const priorityB = this.getPriorityOrder(b.priority);
  78. if (priorityA !== priorityB) {
  79. return priorityA - priorityB;
  80. }
  81. return +new Date(b.updatedAt) - +new Date(a.updatedAt);
  82. });
  83. } catch (error) {
  84. console.error('❌ 加载待办任务失败:', error);
  85. throw error;
  86. }
  87. }
  88. // 状态映射辅助方法
  89. private zh2enStatus(status: string): IssueStatus {
  90. const map: Record<string, IssueStatus> = {
  91. '待处理': 'open',
  92. '处理中': 'in_progress',
  93. '已解决': 'resolved',
  94. '已关闭': 'closed'
  95. };
  96. return map[status] || 'open';
  97. }
  98. private getPriorityOrder(priority: IssuePriority): number {
  99. const config: Record<IssuePriority, number> = {
  100. urgent: 0,
  101. critical: 0,
  102. high: 1,
  103. medium: 2,
  104. low: 3
  105. };
  106. return config[priority] || 2;
  107. }
  108. }