page-crm-training.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
  2. import { CommonModule } from '@angular/common';
  3. import { FormsModule } from '@angular/forms';
  4. import { TrainingReportsComponent } from './report-viewer.component';
  5. import { TrainingService } from './training.service';
  6. import { Report, Scene } from './report.interface';
  7. @Component({
  8. selector: 'page-crm-training',
  9. standalone: true,
  10. imports: [CommonModule, FormsModule, TrainingReportsComponent],
  11. templateUrl: './page-crm-training.html',
  12. styleUrls: ['./page-crm-training.scss']
  13. })
  14. export class PageCrmTraining implements OnInit {
  15. @ViewChild('chatMessagesContainer') chatMessagesContainer!: ElementRef;
  16. // 场景数据
  17. sceneLevels: { value: string; label: string }[] = [];
  18. customerTypes: { value: string; label: string }[] = [];
  19. allScenes: Scene[] = [];
  20. filteredScenes: Scene[] = [];
  21. selectedLevel: string = '';
  22. selectedCustomerType: string = '';
  23. selectedScene: Scene | null = null;
  24. // 对话数据
  25. chatMessages: Array<{
  26. type: 'user' | 'bot';
  27. content: string;
  28. timestamp: Date;
  29. }> = [];
  30. chatInput: string = '';
  31. currentRound: number = 1;
  32. maxRounds: number = 5;
  33. conversationScore: number | null = null;
  34. // 报告数据
  35. generatedReports: Report[] = [];
  36. selectedReport: Report | null = null;
  37. constructor(private trainingService: TrainingService) {}
  38. ngOnInit(): void {
  39. this.loadInitialData();
  40. }
  41. private loadInitialData(): void {
  42. this.trainingService.getSceneLevels().subscribe(levels => {
  43. this.sceneLevels = levels;
  44. });
  45. this.trainingService.getCustomerTypes().subscribe(types => {
  46. this.customerTypes = types;
  47. });
  48. this.trainingService.getAllScenes().subscribe(scenes => {
  49. this.allScenes = scenes;
  50. this.filteredScenes = [...scenes];
  51. });
  52. }
  53. filterScenes(): void {
  54. this.filteredScenes = this.allScenes.filter(scene => {
  55. const levelMatch = !this.selectedLevel || scene.level === this.selectedLevel;
  56. const typeMatch = !this.selectedCustomerType || scene.customerType === this.selectedCustomerType;
  57. return levelMatch && typeMatch;
  58. });
  59. }
  60. getLevelLabel(levelValue: string): string {
  61. const level = this.sceneLevels.find(l => l.value === levelValue);
  62. return level ? level.label : levelValue;
  63. }
  64. getCustomerLabel(typeValue: string): string {
  65. const type = this.customerTypes.find(t => t.value === typeValue);
  66. return type ? type.label : typeValue;
  67. }
  68. selectScene(scene: Scene): void {
  69. this.selectedScene = scene;
  70. this.currentRound = 1;
  71. this.conversationScore = null;
  72. this.chatMessages = [{
  73. type: 'bot',
  74. content: scene.initialMessage,
  75. timestamp: new Date()
  76. }];
  77. this.scrollToBottom();
  78. }
  79. sendMessage(): void {
  80. if (!this.chatInput.trim() || !this.selectedScene) return;
  81. // 添加用户消息
  82. const userMessage = {
  83. type: 'user' as const,
  84. content: this.chatInput,
  85. timestamp: new Date()
  86. };
  87. this.chatMessages.push(userMessage);
  88. this.chatInput = '';
  89. this.scrollToBottom();
  90. // 模拟AI回复
  91. setTimeout(() => {
  92. const botResponse = this.trainingService.generateResponse(
  93. this.selectedScene!.id,
  94. userMessage.content
  95. );
  96. this.chatMessages.push({
  97. type: 'bot' as const,
  98. content: botResponse,
  99. timestamp: new Date()
  100. });
  101. // 更新轮次和评分
  102. this.currentRound = Math.ceil(this.chatMessages.length / 2);
  103. if (this.currentRound <= this.maxRounds) {
  104. this.updateScore();
  105. }
  106. this.scrollToBottom();
  107. }, 800);
  108. }
  109. private updateScore(): void {
  110. const baseScore = 80;
  111. const roundBonus = (this.currentRound - 1) * 5;
  112. const randomVariation = Math.floor(Math.random() * 10);
  113. this.conversationScore = Math.min(baseScore + roundBonus + randomVariation, 100);
  114. // 如果完成所有轮次,生成报告
  115. if (this.currentRound === this.maxRounds) {
  116. this.generateReport();
  117. }
  118. }
  119. private generateReport(): void {
  120. if (!this.selectedScene) return;
  121. const newReport: Report = {
  122. id: `report-${Date.now()}`,
  123. name: this.selectedScene.name,
  124. sceneId: this.selectedScene.id,
  125. date: new Date().toISOString(),
  126. difficulty: this.selectedScene.level,
  127. customerRole: this.selectedScene.customerType,
  128. score: this.conversationScore || 0,
  129. evaluations: {
  130. responsiveness: Math.min(this.conversationScore! + Math.floor(Math.random() * 10) - 5, 100),
  131. 话术: Math.min((this.conversationScore || 80) + Math.floor(Math.random() * 8) - 4, 100),
  132. persuasion: Math.min((this.conversationScore || 75) + Math.floor(Math.random() * 12) - 6, 100),
  133. professionalism: Math.min((this.conversationScore || 85) + Math.floor(Math.random() * 6) - 3, 100)
  134. },
  135. summary: this.generateSummaryText()
  136. };
  137. this.generatedReports.unshift(newReport);
  138. }
  139. private generateSummaryText(): string {
  140. const strengths = [
  141. '展现了出色的沟通技巧',
  142. '对产品知识掌握扎实',
  143. '能够有效处理客户异议',
  144. '表现出了高度的专业性',
  145. '对话流畅自然',
  146. '反应迅速准确'
  147. ];
  148. const improvements = [
  149. '可以进一步提高反应速度',
  150. '建议丰富案例说明',
  151. '需要加强价格谈判技巧',
  152. '可优化话术结构',
  153. '应更关注客户需求',
  154. '可增加数据支持论点'
  155. ];
  156. return `在${this.selectedScene?.name}场景训练中,${
  157. strengths[Math.floor(Math.random() * strengths.length)]
  158. },${improvements[Math.floor(Math.random() * improvements.length)]}。`;
  159. }
  160. resetConversation(): void {
  161. if (this.selectedScene) {
  162. this.selectScene(this.selectedScene);
  163. }
  164. }
  165. viewReport(report: Report): void {
  166. this.selectedReport = report;
  167. console.log('查看完整报告:', report);
  168. }
  169. closeReport(): void {
  170. this.selectedReport = null;
  171. }
  172. private scrollToBottom(): void {
  173. setTimeout(() => {
  174. if (this.chatMessagesContainer) {
  175. this.chatMessagesContainer.nativeElement.scrollTop =
  176. this.chatMessagesContainer.nativeElement.scrollHeight;
  177. }
  178. }, 100);
  179. }
  180. }