dashboard.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import { Component, OnInit, signal } from '@angular/core';
  2. import { CommonModule } from '@angular/common';
  3. import { RouterModule, Router } from '@angular/router';
  4. import { AuthService } from '../../../services/auth.service';
  5. import { WorkHourService } from '../../../services/work-hour.service';
  6. import { WorkHourDashboardData, MonthlyWorkHourStats, PerformanceLevel } from '../../../models/work-hour.model';
  7. @Component({
  8. selector: 'app-dashboard',
  9. imports: [CommonModule, RouterModule],
  10. templateUrl: './dashboard.html',
  11. styleUrl: './dashboard.scss'
  12. })
  13. export class Dashboard implements OnInit {
  14. // 添加today属性用于模板中的日期显示
  15. today = new Date();
  16. // 待办任务数据
  17. todoTasks = signal([
  18. { id: 1, title: '临时收款待核定', priority: 'high', source: 'reconciliation', dueTime: '10:30' },
  19. { id: 2, title: '报价待审核', priority: 'medium', source: 'project-records', dueTime: '14:00' },
  20. { id: 3, title: '素材成本待录入', priority: 'low', source: 'reconciliation', dueTime: '16:30' },
  21. { id: 4, title: '临时收款待核定', priority: 'high', source: 'reconciliation', dueTime: '11:00' },
  22. { id: 5, title: '销售监管提醒', priority: 'high', source: 'project-records', dueTime: '09:30' }
  23. ]);
  24. // 数据概览数据
  25. dashboardStats = signal({
  26. todayOrders: 12,
  27. pendingPayment: 156800,
  28. quotedProjects: 28,
  29. materialCostSaved: 8900
  30. });
  31. // 用户角色
  32. userRole = signal('teamLead'); // teamLead 或 juniorMember
  33. // 工时统计数据
  34. workHourDashboard = signal<WorkHourDashboardData | null>(null);
  35. monthlyStats = signal<MonthlyWorkHourStats[]>([]);
  36. showWorkHourModule = signal(false);
  37. constructor(private authService: AuthService, private workHourService: WorkHourService, private router: Router) {}
  38. ngOnInit(): void {
  39. // 初始化用户角色
  40. this.initializeUserRole();
  41. // 加载工时统计数据
  42. this.loadWorkHourData();
  43. }
  44. // 初始化用户角色
  45. initializeUserRole(): void {
  46. // 从AuthService获取用户角色
  47. const roles = this.authService.getUserRoles();
  48. // 默认使用teamLead角色
  49. let userRole = 'teamLead';
  50. // 如果用户有admin角色,也视为teamLead
  51. if (roles.includes('admin')) {
  52. userRole = 'teamLead';
  53. } else if (roles.length > 0) {
  54. // 否则使用第一个角色
  55. userRole = roles[0];
  56. }
  57. this.userRole.set(userRole);
  58. // 根据用户角色过滤待办任务
  59. this.filterTasksByRole();
  60. }
  61. // 根据用户角色过滤待办任务
  62. filterTasksByRole(): void {
  63. if (this.userRole() !== 'teamLead') {
  64. // 初级组员只显示非财务审批类任务
  65. const filteredTasks = this.todoTasks().filter(task =>
  66. task.title !== '临时收款待核定' && task.title !== '报价待审核'
  67. );
  68. this.todoTasks.set(filteredTasks);
  69. }
  70. }
  71. // 检查用户角色
  72. checkUserRole(requiredRole: string): boolean {
  73. return this.authService.hasRole(requiredRole);
  74. }
  75. // 处理待办任务点击
  76. handleTaskClick(task: any) {
  77. // 检查财务相关任务的权限
  78. if ((task.title === '临时收款待核定' || task.title === '报价待审核') && !this.checkUserRole('teamLead')) {
  79. console.warn('权限不足:只有组长可以处理此任务');
  80. return;
  81. }
  82. // 根据任务来源跳转到对应页面
  83. switch(task.source) {
  84. case 'reconciliation':
  85. window.location.href = '/finance/reconciliation';
  86. break;
  87. case 'project-records':
  88. window.location.href = '/finance/project-records';
  89. break;
  90. }
  91. }
  92. // 处理快捷操作点击
  93. handleQuickAction(action: string) {
  94. // 检查权限
  95. if ((action === 'recordPayment' || action === 'generateReport') && !this.checkUserRole('teamLead')) {
  96. console.warn('权限不足:只有组长可以执行此操作');
  97. return;
  98. }
  99. switch(action) {
  100. case 'newQuote':
  101. window.location.href = '/finance/project-records';
  102. break;
  103. case 'recordPayment':
  104. window.location.href = '/finance/reconciliation';
  105. break;
  106. case 'generateReport':
  107. window.location.href = '/finance/reports';
  108. break;
  109. case 'quotationApproval':
  110. this.router.navigate(['/finance/quotation-approval']);
  111. break;
  112. }
  113. }
  114. // 格式化金额显示
  115. formatAmount(amount: number): string {
  116. return new Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY' }).format(amount);
  117. }
  118. // 加载工时统计数据
  119. loadWorkHourData(): void {
  120. this.workHourService.getDashboardData().subscribe(data => {
  121. this.workHourDashboard.set(data);
  122. });
  123. this.workHourService.getMonthlyStats().subscribe(stats => {
  124. this.monthlyStats.set(stats);
  125. });
  126. }
  127. // 切换工时模块显示
  128. toggleWorkHourModule(): void {
  129. this.showWorkHourModule.set(!this.showWorkHourModule());
  130. }
  131. // 获取绩效等级颜色
  132. getPerformanceLevelColor(level: string): string {
  133. const colors: Record<string, string> = {
  134. 'S': '#ff6b6b',
  135. 'A': '#4ecdc4',
  136. 'B': '#45b7d1',
  137. 'C': '#96ceb4'
  138. };
  139. return colors[level] || '#ccc';
  140. }
  141. // 获取绩效等级人数
  142. getPerformanceLevelCount(level: string): number {
  143. const dashboard = this.workHourDashboard();
  144. if (!dashboard) return 0;
  145. const distribution = dashboard.performanceDistribution as Record<string, number>;
  146. return distribution[level] || 0;
  147. }
  148. // 获取绩效等级描述
  149. getPerformanceLevelDescription(level: string): string {
  150. const descriptions: Record<string, string> = {
  151. 'S': '卓越表现',
  152. 'A': '优秀表现',
  153. 'B': '良好表现',
  154. 'C': '待提升'
  155. };
  156. return descriptions[level] || '未知';
  157. }
  158. // 格式化工时显示
  159. formatWorkHours(hours: number): string {
  160. const days = Math.floor(hours / 8);
  161. const remainingHours = hours % 8;
  162. if (days > 0 && remainingHours > 0) {
  163. return `${days}天${remainingHours}小时`;
  164. } else if (days > 0) {
  165. return `${days}天`;
  166. } else {
  167. return `${remainingHours}小时`;
  168. }
  169. }
  170. }