ResultView.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. <script setup lang="ts">
  2. import {
  3. ref,
  4. reactive,
  5. toRefs,
  6. onMounted,
  7. watch,
  8. computed,
  9. onBeforeUnmount,
  10. } from "vue";
  11. import NavBarPage from "../components/NavBarPage.vue";
  12. import randarPage from "./result/randarPage.vue";
  13. import { useRoute } from "vue-router";
  14. import { fetchTaskScore } from "./utils/api";
  15. import { Toast } from "vant";
  16. const route = useRoute();
  17. const score = ref(0);
  18. const data = ref(null);
  19. const scoresList = ref(null);
  20. const taskId = computed(() => route.query.conversationId); // 会话ID "2c64eb8b69be432ca0bb9ae55bc78def"
  21. const randarlist = ref([0, 0, 0, 0]);
  22. const nameMapping = {
  23. introduction_profession: "自我介绍专业性",
  24. basic_information: "客户画像采集",
  25. purchase_intent: "需求挖掘能力",
  26. invitation_results: "沟通转化效果",
  27. penalty_points: "扣分项",
  28. };
  29. const handleResult = async () => {
  30. let res;
  31. let shouldContinue = true; // 控制是否继续调用接口的标志
  32. while (shouldContinue) {
  33. res = await fetchTaskScore(taskId.value);
  34. if (res.code !== 200) {
  35. // 当返回错误时,停止调用接口
  36. shouldContinue = false;
  37. } else if (res.body && Object.keys(res.body).length !== 0) {
  38. // 当res.body有值时,停止调用接口
  39. data.value = res.body;
  40. shouldContinue = false;
  41. } else {
  42. await new Promise((resolve) => setTimeout(resolve, 3000));
  43. }
  44. }
  45. if (res && res.code === 200 && res.body) {
  46. const scores = extractScores(res.body);
  47. score.value = scores.reduce((sum, score) => sum + score, 0);
  48. scoresList.value = Object.keys(res.body).reduce((acc, key) => {
  49. // if (key !== "penalty_points") {
  50. acc[key] = {
  51. ...res.body[key],
  52. name: nameMapping[key], // 添加 name 字段
  53. };
  54. // }
  55. return acc;
  56. }, {});
  57. console.log(scoresList.value,'000000000');
  58. const obj = extractScores(scoresList.value);
  59. randarlist.value = Object.values(obj);
  60. }
  61. };
  62. // 处理“分”字
  63. const extractScores = (data) => {
  64. return Object.values(data).map((item) => {
  65. // 确保 score 是一个字符串,并且去除可能的 "分" 字
  66. let scoreStr = String(item.score).replace("分", "");
  67. // 将 score 转换为整数,如果转换失败则返回 0
  68. const score = parseInt(scoreStr, 10);
  69. return isNaN(score) ? 0 : score;
  70. });
  71. };
  72. onMounted(() => {
  73. handleResult();
  74. window.addEventListener("popstate", function (event) {
  75. // 执行一些操作,例如关闭当前页面或跳转到其他页面
  76. window.location.href = "/#/home";
  77. });
  78. });
  79. onBeforeUnmount(() => {
  80. window.removeEventListener("popstate", function (event) {
  81. // 执行一些操作,例如关闭当前页面或跳转到其他页面
  82. window.location.href = "/#/home";
  83. });
  84. });
  85. </script>
  86. <template>
  87. <div class="result" style="overflow: hidden">
  88. <NavBarPage title="考试" type="home" />
  89. <div style="height: 46px"></div>
  90. <div class="score">
  91. <span>最终得分</span>
  92. <p class="score-num">
  93. <span style="margin-right: 0.2rem;">{{ score }}</span
  94. >分
  95. </p>
  96. </div>
  97. <div style="height: 9.06rem; visibility: hidden"></div>
  98. <div class="content">
  99. <div style="width: 100vw; height: 19.06rem">
  100. <randarPage :randarList="randarlist" />
  101. </div>
  102. <div class="standard">
  103. <div class="standard-title">
  104. <img src="../assets/robot.jpg" alt="" />
  105. <span>评分标准</span>
  106. </div>
  107. <div
  108. class="standard-content"
  109. v-for="(item, key) in scoresList"
  110. :key="key"
  111. >
  112. <div class="standard-subtitle">
  113. <span class="pro"
  114. >{{
  115. item.name == "扣分项" ? item.name : `${item.name}(50分)`
  116. }}:</span
  117. >
  118. <span>{{ item.score }}</span>
  119. </div>
  120. <p>
  121. <span>得分原因:</span>
  122. <span>{{ item.reason }}</span>
  123. </p>
  124. </div>
  125. </div>
  126. </div>
  127. </div>
  128. </template>
  129. <style scoped lang="less">
  130. html,
  131. body {
  132. margin: 0;
  133. padding: 0;
  134. height: 100vh;
  135. overflow: hidden;
  136. /* 禁止页面整体滚动 */
  137. }
  138. .result {
  139. width: 100%;
  140. height: 100%;
  141. /* height: 100vh; */
  142. overflow: hidden;
  143. }
  144. .score {
  145. position: fixed;
  146. z-index: 999;
  147. width: 100%;
  148. height: 9.06rem;
  149. background-color: rgba(243, 249, 255, 1);
  150. display: flex;
  151. flex-direction: column;
  152. align-items: center;
  153. justify-content: center;
  154. span {
  155. display: flex;
  156. width: 5.06rem;
  157. height: 2.88rem;
  158. font-weight: bold;
  159. line-height: 2.88rem;
  160. color: rgba(64, 149, 229, 1);
  161. font-size: 1rem;
  162. text-align: center;
  163. font-family: Times New Roman-regular;
  164. }
  165. .score-num {
  166. display: flex;
  167. align-items: last baseline;
  168. color: rgba(64, 149, 229, 1);
  169. font-size: 1rem;
  170. span {
  171. display: block;
  172. width: 5.06rem;
  173. height: 3.31rem;
  174. line-height: 4.25rem;
  175. font-size: 3rem;
  176. text-align: center;
  177. font-family: Times New Roman-regular;
  178. }
  179. }
  180. }
  181. .content {
  182. width: 100%;
  183. height: 100%;
  184. overflow: scroll;
  185. }
  186. .standard-title {
  187. display: flex;
  188. align-items: center;
  189. padding: 0 0.94rem;
  190. margin-bottom: 0.63rem;
  191. img {
  192. width: 1.5rem;
  193. height: 1.5rem;
  194. }
  195. span {
  196. display: inline-block;
  197. width: 4rem;
  198. height: 1.44rem;
  199. line-height: 1.44rem;
  200. margin-left: 0.33rem;
  201. color: rgba(64, 149, 229, 1);
  202. font-size: 1rem;
  203. text-align: center;
  204. font-family: Times New Roman-regular;
  205. }
  206. }
  207. .standard-subtitle {
  208. padding: 0.56rem 1rem;
  209. height: 1.06rem;
  210. font-size: 0.88rem;
  211. font-family: Times New Roman-regular;
  212. span {
  213. color: rgba(64, 149, 229, 1);
  214. font-weight: 600;
  215. }
  216. .pro {
  217. display: inline-block;
  218. height: 1.06rem;
  219. line-height: 1.06rem;
  220. padding: 0 0.3rem;
  221. font-weight: normal;
  222. color: rgba(102, 102, 102, 1);
  223. border-left: 0.3rem solid rgba(64, 149, 229, 1);
  224. }
  225. }
  226. .standard-content p {
  227. padding: 0 1.63rem;
  228. margin-bottom: 0.31rem;
  229. line-height: 1.25rem;
  230. color: rgba(102, 102, 102, 1);
  231. font-size: 0.88rem;
  232. text-align: left;
  233. font-family: SourceHanSansSC-bold;
  234. }
  235. .standard-content p span:nth-child(1) {
  236. font-weight: 600;
  237. }
  238. </style>