customer-review-form.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import { Component, Input, Output, EventEmitter } from '@angular/core';
  2. import { CommonModule } from '@angular/common';
  3. import { FormsModule } from '@angular/forms';
  4. // 评价维度接口
  5. export interface ReviewDimension {
  6. id: string;
  7. label: string;
  8. description?: string;
  9. score: number;
  10. subDimensions?: ReviewDimension[];
  11. }
  12. // 评价数据接口
  13. export interface CustomerReviewData {
  14. // 总体评价 (0-5分)
  15. overallSatisfaction: number;
  16. // 服务质量维度 (0-5分)
  17. serviceTimeliness: number; // 服务时效
  18. suggestionResponse: number; // 建议回应
  19. smallImageDelivery: number; // 小图交付
  20. revisionEfficiency: number; // 改图不及时
  21. // 图纸渲染质量 (0-5分)
  22. renderingQuality: {
  23. materials: number; // 材质
  24. lighting: number; // 灯光
  25. texture: number; // 纹理
  26. structure: number; // 硬装结构
  27. };
  28. // 沟通体验 (0-5分)
  29. communication: {
  30. documentation: number; // 资料齐情况
  31. requirementUnderstanding: number; // 需求误解
  32. communicationSufficiency: number; // 缺少沟通
  33. contentRelevance: number; // 文不对题
  34. };
  35. // 多个场景评价 - 对应设计师
  36. scenes: SceneReview[];
  37. // 改进建议
  38. improvementSuggestions: string;
  39. // 下次合作优化点
  40. nextCooperationOptimization: string;
  41. // 合作意愿
  42. willCooperateAgain: boolean;
  43. // 投诉内容(可选)
  44. complaintContent?: string;
  45. // 评价时间
  46. reviewDate: Date;
  47. }
  48. // 场景评价接口
  49. export interface SceneReview {
  50. sceneName: string;
  51. designerName: string;
  52. score: number;
  53. comments?: string;
  54. }
  55. @Component({
  56. selector: 'app-customer-review-form',
  57. standalone: true,
  58. imports: [CommonModule, FormsModule],
  59. templateUrl: './customer-review-form.html',
  60. styleUrls: ['./customer-review-form.scss']
  61. })
  62. export class CustomerReviewFormComponent {
  63. @Input() projectName: string = '';
  64. @Input() designerName: string = '';
  65. @Input() scenes: string[] = ['客厅', '餐厅', '卧室', '厨房', '卫生间', '阳台'];
  66. @Output() reviewSubmitted = new EventEmitter<CustomerReviewData>();
  67. // 默认评价数据
  68. reviewData: CustomerReviewData = {
  69. overallSatisfaction: 5,
  70. serviceTimeliness: 5,
  71. suggestionResponse: 5,
  72. smallImageDelivery: 5,
  73. revisionEfficiency: 5,
  74. renderingQuality: {
  75. materials: 5,
  76. lighting: 5,
  77. texture: 5,
  78. structure: 5
  79. },
  80. communication: {
  81. documentation: 5,
  82. requirementUnderstanding: 5,
  83. communicationSufficiency: 5,
  84. contentRelevance: 5
  85. },
  86. scenes: [],
  87. improvementSuggestions: '',
  88. nextCooperationOptimization: '',
  89. willCooperateAgain: true,
  90. complaintContent: '',
  91. reviewDate: new Date()
  92. };
  93. // 是否显示投诉内容
  94. showComplaint: boolean = false;
  95. constructor() {
  96. // 初始化场景评价
  97. this.scenes.forEach(scene => {
  98. this.reviewData.scenes.push({
  99. sceneName: scene,
  100. designerName: this.designerName,
  101. score: 5,
  102. comments: ''
  103. });
  104. });
  105. }
  106. // 提交评价
  107. submitReview(): void {
  108. // 验证数据
  109. if (this.validateReview()) {
  110. this.reviewSubmitted.emit(this.reviewData);
  111. this.resetForm();
  112. } else {
  113. window?.fmode?.alert('请完成所有必填的评价项目');
  114. }
  115. }
  116. // 验证评价数据
  117. private validateReview(): boolean {
  118. // 检查总体评分
  119. if (this.reviewData.overallSatisfaction === 0) return false;
  120. // 检查所有场景评分
  121. for (const scene of this.reviewData.scenes) {
  122. if (scene.score === 0) return false;
  123. }
  124. return true;
  125. }
  126. // 重置表单
  127. private resetForm(): void {
  128. this.reviewData = {
  129. overallSatisfaction: 5,
  130. serviceTimeliness: 5,
  131. suggestionResponse: 5,
  132. smallImageDelivery: 5,
  133. revisionEfficiency: 5,
  134. renderingQuality: {
  135. materials: 5,
  136. lighting: 5,
  137. texture: 5,
  138. structure: 5
  139. },
  140. communication: {
  141. documentation: 5,
  142. requirementUnderstanding: 5,
  143. communicationSufficiency: 5,
  144. contentRelevance: 5
  145. },
  146. scenes: this.scenes.map(scene => ({
  147. sceneName: scene,
  148. designerName: this.designerName,
  149. score: 5,
  150. comments: ''
  151. })),
  152. improvementSuggestions: '',
  153. nextCooperationOptimization: '',
  154. willCooperateAgain: true,
  155. complaintContent: '',
  156. reviewDate: new Date()
  157. };
  158. this.showComplaint = false;
  159. }
  160. // 获取平均分
  161. getAverageScore(): number {
  162. const scores = [
  163. this.reviewData.overallSatisfaction,
  164. this.reviewData.serviceTimeliness,
  165. this.reviewData.suggestionResponse,
  166. this.reviewData.smallImageDelivery,
  167. this.reviewData.revisionEfficiency,
  168. this.reviewData.renderingQuality.materials,
  169. this.reviewData.renderingQuality.lighting,
  170. this.reviewData.renderingQuality.texture,
  171. this.reviewData.renderingQuality.structure,
  172. this.reviewData.communication.documentation,
  173. this.reviewData.communication.requirementUnderstanding,
  174. this.reviewData.communication.communicationSufficiency,
  175. this.reviewData.communication.contentRelevance,
  176. ...this.reviewData.scenes.map(scene => scene.score)
  177. ];
  178. const sum = scores.reduce((total, score) => total + score, 0);
  179. return Math.round((sum / scores.length) * 10) / 10;
  180. }
  181. // 切换投诉显示
  182. toggleComplaint(): void {
  183. this.showComplaint = !this.showComplaint;
  184. if (!this.showComplaint) {
  185. this.reviewData.complaintContent = '';
  186. }
  187. }
  188. // 生成星级显示
  189. generateStars(score: number): string[] {
  190. const stars = [];
  191. for (let i = 1; i <= 5; i++) {
  192. if (i <= score) {
  193. stars.push('★');
  194. } else if (i - 0.5 <= score) {
  195. stars.push('☆');
  196. } else {
  197. stars.push('☆');
  198. }
  199. }
  200. return stars;
  201. }
  202. }