index.tsx 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import { defineComponent, onMounted, reactive, watch, computed } from "vue";
  2. import { Popover } from "vant";
  3. import styles from "./index.module.less";
  4. import state from "/src/state";
  5. import icon1 from "../icons/1.png";
  6. import { storeData } from "/src/store";
  7. import { evaluatingData } from "/src/view/evaluating";
  8. import iconBack from "/src/page-instrument/header-top/image/icon-back.png";
  9. import bg1Img from "./img/bg1.png";
  10. import bg2Img from "./img/bg2.png";
  11. import ckzpImg from "./img/ckzp.png";
  12. import bczpImg from "./img/bczp.png";
  13. import bczpJzImg from "./img/bczpJz.png";
  14. import zlycImg from "./img/zlyc.png";
  15. import iconBadge from "./img/icon-badge.png";
  16. import yzImg from "./img/yz.png";
  17. import jzImg from "./img/jz.png";
  18. import wzxImg from "./img/wzx.png";
  19. import closeImg from "./img/close.png";
  20. import { getQuery } from "/src/utils/queryString";
  21. import { browser, getBehaviorId } from "/src/utils";
  22. import { api_musicPracticeRecordSave } from "../../api";
  23. import { getAudioDuration } from "/src/view/audio-list";
  24. import { debounce } from "/src/utils";
  25. import { EvaluatingResultDriver } from "../../custom-plugins/guide-driver";
  26. export default defineComponent({
  27. name: "evaluatResult",
  28. emits: ["close"],
  29. setup(props, { emit }) {
  30. const query = getQuery();
  31. const data = reactive({
  32. saveLoading: true,
  33. showPopover: true,
  34. });
  35. const level: any = {
  36. BEGINNER: "入门级",
  37. ADVANCED: "进阶级",
  38. PERFORMER: "大师级",
  39. };
  40. /** 添加评测记录 */
  41. const handleAddRecord = async () => {
  42. console.log("结束", evaluatingData.resultData);
  43. /** 生成评测记录的时候,记录当前评测的谱面类型,用于评测报告默认展示的谱面类型 */
  44. evaluatingData.resultData.scoreData.musicType = state.musicRenderType;
  45. // 评测的速度,如果是选段,则选选段开头小节的速度
  46. const evaluatSpeed = state.sectionStatus && state.section.length === 2 && state.section[0].measureSpeed ? state.section[0].measureSpeed * state.basePlayRate : state.speed;
  47. const rate = state.basePlayRate * state.originAudioPlayRate; // 播放倍率
  48. const body: any = {
  49. deviceType: browser().android ? "ANDROID" : "IOS", // 设备类型
  50. intonation: evaluatingData.resultData.intonation, // 音准
  51. cadence: evaluatingData.resultData.cadence, // 节奏
  52. integrity: evaluatingData.resultData.integrity, // 完成度
  53. scoreData: JSON.stringify(evaluatingData.resultData.scoreData), // 评测数据
  54. behaviorId: getBehaviorId(), // 行为id
  55. sourceTime: getAudioDuration(), // 音频时长
  56. partIndex: state.partIndex, // 音轨
  57. speed: evaluatingData.evaluatSpeed || evaluatSpeed, // 速度
  58. practiceSource: query.workRecord ? "LESSON_TRAINING" : "EVALUATION", // 练习来源
  59. score: evaluatingData.resultData.score, // 分数
  60. clientType: storeData.user.clientType, // 客户端类型
  61. musicSheetId: state.examSongId, // 乐谱id
  62. feature: "EVALUATION", // 特征
  63. playTime: evaluatingData.resultData.playTime / 1000, // 播放时长
  64. heardLevel: state.setting.evaluationDifficulty, // 听力等级
  65. recordFilePath: evaluatingData.resultData.url, // 录音文件路径
  66. delFlag: evaluatingData.oneselfCancleEvaluating,
  67. instrumentId: state.instrumentId,
  68. playRate: rate,
  69. providerType: state.tenantAlbumId ? "TENANT" : "PLATFORM"
  70. };
  71. // 如果是评测作业模式,需要添加作业id
  72. if (query.evaluatingRecord) {
  73. body.lessonDetailId = query.evaluatingRecord
  74. }
  75. data.saveLoading = true;
  76. const res = await api_musicPracticeRecordSave(body);
  77. if (res?.code === 200) {
  78. evaluatingData.resultData.recordId = res.data;
  79. }
  80. evaluatingData.needReplayEvaluat = evaluatingData.oneselfCancleEvaluating ? true : false;
  81. data.saveLoading = false;
  82. };
  83. const saveResult = () => {
  84. emit("close", "update");
  85. };
  86. // 播放倍率不等于1,或者是选段评测,APP暂时不支持保存演奏,需要给出提示
  87. const noSaveTips = computed(() => {
  88. let tipContent = '';
  89. const rate = state.basePlayRate * state.originAudioPlayRate; // 播放倍率
  90. console.log('123456',state.systemType)
  91. if (query.workRecord || state.section.length === 2 || state.isAppPlay || rate != 1 || !state.accompany || state.systemType === 'web') {
  92. tipContent = (state.systemType === 'web') ? '暂不支持保存作品噢~' : query.workRecord ? '评测作业暂不支持保存作品噢~' : (!state.accompany || state.isAppPlay) ? '该曲目暂不支持保存作品噢~' : state.section.length === 2 ? '选段后暂不支持保存作品噢~' : rate != 1 ? '调速后暂不支持保存作品噢~' : '';
  93. }
  94. return tipContent
  95. })
  96. const isHuaWeiPad = navigator?.userAgent?.includes("UAWEIVRD-W09") ? true : false
  97. onMounted(() => {
  98. // if (!evaluatingData.isErrorState) {
  99. // handleAddRecord();
  100. // }
  101. // console.log('评测等级',evaluatingData.resultData.leve)
  102. });
  103. watch(
  104. () => evaluatingData.resulstMode,
  105. (val) => {
  106. // # 9402,评测异常操作:都改为不生成评测记录
  107. if (val) {
  108. setTimeout(() => {
  109. if (!evaluatingData.isErrorState) {
  110. handleAddRecord();
  111. }
  112. }, 0);
  113. }
  114. },
  115. {
  116. immediate: true
  117. }
  118. );
  119. return () => (
  120. <>
  121. {!evaluatingData.hideResultModal && (
  122. <div class={styles.evaluatResult}>
  123. <div class={styles.closeBtn} onClick={() => emit("close")}>
  124. <img src={iconBack} />
  125. </div>
  126. <div class={[styles.fraction, state.isPercussion && styles.fractionPercussion]}>
  127. <img class={styles.bg} src={state.isPercussion ? bg2Img : bg1Img} />
  128. <div class={styles.top}>
  129. {evaluatingData.resultData.score > 79 && <img class={styles.badge} src={iconBadge} />}
  130. <div class={[styles.text, evaluatingData.resultData.score > 79 && styles.badgeText]}>
  131. <div class={[styles.scoreSection, "evaluting-result-1"]}>
  132. <div class={styles.num}>{evaluatingData.resultData.score}</div>
  133. <div class={styles.score}>分</div>
  134. <div class={[styles.level, isHuaWeiPad && styles.huaWeiLevel]}>
  135. <div>{level[evaluatingData.resultData.heardLevel]}</div>
  136. <span>|</span>
  137. <div>速度{evaluatingData.resultData.speed || state.speed}</div>
  138. </div>
  139. </div>
  140. </div>
  141. <img class={styles.rightBadge} src={evaluatingData.resultData.img} />
  142. </div>
  143. {!state.isPercussion && (
  144. <div class={styles.detail}>
  145. <div class={styles.progressitem}>
  146. <div>
  147. <img src={yzImg} />
  148. <span>音准</span>
  149. </div>
  150. <div><span class={styles.scoresNum}>{evaluatingData.resultData.intonation}</span><span class={styles.scores}>分</span></div>
  151. </div>
  152. <div class={styles.progressitem}>
  153. <div>
  154. <img src={jzImg} />
  155. <span>节奏</span>
  156. </div>
  157. <div><span class={styles.scoresNum}>{evaluatingData.resultData.cadence}</span><span class={styles.scores}>分</span></div>
  158. </div>
  159. <div class={styles.progressitem}>
  160. <div>
  161. <img src={wzxImg} />
  162. <span>完成度</span>
  163. </div>
  164. <div><span class={styles.scoresNum}>{evaluatingData.resultData.integrity}</span><span class={styles.scores}>分</span></div>
  165. </div>
  166. </div>
  167. )}
  168. <div class={styles.tips}>{state.isPercussion ? evaluatingData.resultData.djytip : evaluatingData.resultData.clxtip}</div>
  169. <div class={styles.ctrls}>
  170. <img src={zlycImg} class={[styles.ctrlsBtn, "evaluting-result-2"]} onClick={() => emit("close", "tryagain")} />
  171. {evaluatingData.resultData.recordId ? (
  172. <div class={styles.saveBtn}>
  173. <img
  174. src={noSaveTips.value ? bczpJzImg : bczpImg}
  175. class={[styles.ctrlsBtn, "evaluting-result-3"]}
  176. style={{ opacity: state.isHideEvaluatReportSaveBtn ? 0.4 : 1 }}
  177. onClick={() => {
  178. if (!noSaveTips.value && !state.isHideEvaluatReportSaveBtn) {
  179. saveResult();
  180. }
  181. }}
  182. />
  183. {noSaveTips.value && state.noSavePopShow ? (
  184. <div class={[styles.noSaveTip]}>
  185. <span class={styles.arrowIcon}></span>
  186. <span>{noSaveTips.value}</span>
  187. <i onClick={() => (state.noSavePopShow = false)}></i>
  188. </div>
  189. ) : null}
  190. </div>
  191. ) : null}
  192. <img src={ckzpImg} class={[styles.ctrlsBtn, "evaluting-result-4", data.saveLoading ? styles.disablued : ""]} onClick={() => emit("close", "look")} />
  193. </div>
  194. </div>
  195. {/* 评测模式-结果弹窗 功能引导 加载音频完成 不是会员 */}
  196. {evaluatingData.resulstMode && !evaluatingData.hideResultModal && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !data.saveLoading && <EvaluatingResultDriver saveBtn={evaluatingData.resultData.recordId ? true : false} />}
  197. </div>
  198. )}
  199. </>
  200. );
  201. },
  202. });