index.tsx 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. import { Transition, computed, defineComponent, onMounted, onUnmounted, reactive, ref, watch, toRef, ComputedRef, nextTick, defineAsyncComponent } from "vue";
  2. import styles from "./index.module.less";
  3. import iconBack from "./image/icon-back.png";
  4. import listImg from "./image/list.png";
  5. import iconMode from "./image/mode.png";
  6. import { headImg } from "./image";
  7. import { Badge, Circle, Popover, Popup, showConfirmDialog, showToast, NoticeBar } from "vant";
  8. import Speed from "./speed";
  9. import { evaluatingData, handleStartEvaluat } from "/src/view/evaluating";
  10. import Settting from "./settting";
  11. import state, { IPlatform, handleChangeSection, handleResetPlay, handleRessetState, togglePlay, IPlayState, refreshMusicSvg, EnumMusicRenderType, resetSettings, handleGuide, resetCursorPosition } from "/src/state";
  12. import { audioData, getAudioCurrentTime } from "/src/view/audio-list";
  13. import { followData, toggleFollow } from "/src/view/follow-practice";
  14. import { api_back } from "/src/helpers/communication";
  15. import MusicType from "./music-type";
  16. import { getQuery } from "/src/utils/queryString";
  17. import { storeData } from "/src/store";
  18. import TeacherTop from "../custom-plugins/guide-page/teacher-top";
  19. import StudentTop from "../custom-plugins/guide-page/student-top";
  20. import { HANDLE_WORK_ADD } from "../custom-plugins/work-index";
  21. import { browser } from "/src/utils";
  22. import store from "store";
  23. import "../component/the-modal-tip/index.module.less";
  24. import { metronomeData } from "../../helpers/metronome";
  25. import { toggleMusicSheet } from "/src/view/plugins/toggleMusicSheet";
  26. import useDrag from "/src/view/plugins/useDrag/index";
  27. import Dragbom from "/src/view/plugins/useDrag/dragbom";
  28. import { getGuidance, setGuidance } from "../custom-plugins/guide-page/api";
  29. // import ModeView from "./modeView";
  30. import { smoothAnimationState } from "../view-detail/smoothAnimation";
  31. import { isMusicList, musicListShow } from "../component/the-music-list";
  32. import { EvaluatingDriver, FollowDriver, PractiseDriver } from "../custom-plugins/guide-driver";
  33. import { fingerRef } from "/src/page-instrument/view-detail/index"
  34. import { permissionPopup } from "/src/page-instrument/component/vip/permission";
  35. const ModeView = defineAsyncComponent(() =>
  36. import('./modeView')
  37. )
  38. /** 校验是否能切换模式,会员的曲子,酷乐秀跟练模式、评测模式需要svip */
  39. export const checkMusicBuy = (item: any, type?: string) => {
  40. let checked = true;
  41. // 学生端或者老师端需要校验点播和会员曲目;通过专辑进入的,不需要校验点播和会员曲目,默认都可以使用
  42. if ((state.systemType === "student" || state.systemType === "teacher") && !state.tenantAlbumId) {
  43. // 如果是点播的曲子,并且还没有购买,需要弹窗提醒
  44. if (item.paymentType === "CHARGE" && !item.buyed) {
  45. permissionPopup.active = "demand"
  46. permissionPopup.musicId = item.id
  47. permissionPopup.musicPrice = item.musicPrice
  48. permissionPopup.show = true
  49. checked = false
  50. }
  51. /**
  52. * 如果是vip的曲子,当前用户不是会员时,需要弹窗提醒
  53. * 如果是vip的曲子,当前用户不是svip会员,点击跟练或评测时,需要弹窗提醒(会员曲子,跟练和评测需要开通svip会员才能使用)
  54. */
  55. if ( (state.vipType === "NOT_VIP" && item.paymentType !== "FREE") || (item.paymentType !== "FREE" && !state.vipType.includes("SVIP") && (type === "follow" || type === "evaluating")) ) {
  56. permissionPopup.active = item.paymentType.includes('CHARGE') ? "memberAndDemand" : "member"
  57. permissionPopup.musicId = item.id
  58. permissionPopup.musicPrice = item.musicPrice
  59. permissionPopup.show = true
  60. checked = false
  61. }
  62. }
  63. return checked;
  64. };
  65. /** 头部数据和方法 */
  66. export const headTopData = reactive({
  67. /** 模式 */
  68. modeType: "" as "init" | "show",
  69. /** 显示返回按钮 */
  70. showBack: true,
  71. /** 设置弹窗 */
  72. settingMode: false,
  73. /** 切换模式 */
  74. handleChangeModeType(value: "practise" | "follow" | "evaluating") {
  75. // 后台设置为不能评测
  76. if (value === "evaluating" && !state.enableEvaluation) return;
  77. // 打击乐&节奏练习不支持跟练模式
  78. if (value === "follow" && state.isPercussion) return;
  79. // 跟练模式,光标只有音符模式,无节拍模式
  80. if (value === "follow" && metronomeData.cursorMode === 2) {
  81. metronomeData.cursorMode = 1;
  82. }
  83. if (value === "practise") {
  84. // state.playIngSpeed = state.speed
  85. }
  86. if (value === "evaluating") {
  87. // 如果延迟检测资源还在加载中,给出提示
  88. if (!evaluatingData.jsonLoadDone) {
  89. evaluatingData.jsonLoading = true;
  90. state.audioDone && showToast("资源加载中,请稍后"); //音频资源加载完之后才提示
  91. return;
  92. }
  93. // 如果是pc端, 评测模式暂不可用
  94. if (state.platform === IPlatform.PC) {
  95. showConfirmDialog({
  96. className: "modalTip",
  97. title: "温馨提示",
  98. message: "该功能暂未开放,敬请期待!",
  99. showCancelButton: false,
  100. });
  101. return;
  102. }
  103. // 评测模式,只有一行谱模式
  104. // if (!state.isSingleLine) {
  105. // state.isSingleLine = true;
  106. // refreshMusicSvg();
  107. // }
  108. smoothAnimationState.isShow.value = false; // 隐藏旋律线
  109. state.playIngSpeed = state.originSpeed;
  110. handleStartEvaluat();
  111. resetCursorPosition()
  112. // 开发模式,把此处打开
  113. // state.modeType = "evaluating";
  114. // evaluatingData.rendered = true;
  115. // evaluatingData.soundEffectMode = true;
  116. } else if (value === "follow") {
  117. // 跟练模式,只有一行谱模式
  118. if (!state.isSingleLine) {
  119. state.isSingleLine = true;
  120. refreshMusicSvg();
  121. }
  122. smoothAnimationState.isShow.value = false;
  123. toggleFollow();
  124. }
  125. headTopData.modeType = "show";
  126. },
  127. // 改变模式之前的状态
  128. oldPlayType: "play",
  129. // 记录切换模式前的状态
  130. oldModeType: "practise" as "practise" | "follow" | "evaluating",
  131. });
  132. export const headData = reactive({
  133. speedShow: false,
  134. musicTypeShow: false,
  135. });
  136. let resetBtn: ComputedRef<{
  137. display: boolean;
  138. disabled: boolean;
  139. }>;
  140. // 点击切换的时候才触发提醒
  141. let isClickMode = false;
  142. /**
  143. * 处理模式切换
  144. * @param oldPlayType 没改变之前的播放模式
  145. * @param oldPlaySource 没改变之前的播放类型
  146. * @param isforceReset 是否强制刷新播放状态 模式times时值改变时候也刷新
  147. */
  148. export function handlerModeChange(oldPlayType: "play" | "sing", oldPlaySource: IPlayState, isforceReset?: boolean) {
  149. const isModeChange = modeChangeHandleTimes(oldPlayType, oldPlaySource);
  150. // 没有切换的时候 不处理下面的
  151. if (isModeChange) {
  152. try {
  153. metronomeData.metro.calculation(state.times);
  154. } catch (error) {}
  155. console.log("重新之后的times", state.times, state.fixtime);
  156. }
  157. if (isModeChange || isforceReset) {
  158. // 重置播放状态
  159. handleRessetState();
  160. // 隐藏重播按钮
  161. resetBtn && (resetBtn.value.display = false);
  162. }
  163. // 当模式改变的时候 放在这里是因为需要等谱面加载完成之后再提示(点击按钮模式切换才提示)
  164. if (isClickMode) {
  165. showToast({
  166. message: state.playType === "play" ? "已切换为演奏场景" : "已切换为演唱场景",
  167. position: "top",
  168. className: "selectionToast",
  169. });
  170. isClickMode = false;
  171. }
  172. }
  173. // 模式切换之后重新给times赋值
  174. function modeChangeHandleTimes(oldPlayType: "play" | "sing", oldPlaySource: IPlayState) {
  175. const playType = state.playType;
  176. const playSource = state.playSource;
  177. const { notBeatFixtime, xmlMp3BeatFixTime, difftime } = state.times[0];
  178. const { isOpenMetronome, isSingOpenMetronome } = state;
  179. // 演奏向演唱切
  180. if (oldPlayType === "play" && playType === "sing") {
  181. if (playSource === "mingSong") {
  182. // 唱名文件也要加上弱起时间 他们制作曲子加了弱起时间 注意这修改了之后给总控平台的时值也需要改
  183. state.fixtime = difftime;
  184. state.times.map((item) => {
  185. item.time = item.xmlNoteTime + difftime;
  186. item.endtime = item.xmlNoteEndTime + difftime;
  187. item.fixtime = difftime;
  188. });
  189. return true;
  190. } else {
  191. //演奏开了节拍器,演唱没开节拍器
  192. if (isOpenMetronome && !isSingOpenMetronome) {
  193. state.fixtime = notBeatFixtime;
  194. state.times.map((item) => {
  195. item.time = item.notBeatTime;
  196. item.endtime = item.notBeatEndTime;
  197. item.fixtime = notBeatFixtime;
  198. });
  199. return true;
  200. } else if (!isOpenMetronome && isSingOpenMetronome) {
  201. state.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
  202. state.times.map((item) => {
  203. item.time = item.notBeatTime + xmlMp3BeatFixTime;
  204. item.endtime = item.notBeatEndTime + xmlMp3BeatFixTime;
  205. item.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
  206. });
  207. return true;
  208. }
  209. }
  210. } else if (oldPlayType === "sing" && playType === "play") {
  211. // 演唱向演奏切
  212. if (oldPlaySource === "mingSong") {
  213. // 有节拍器
  214. if (isOpenMetronome) {
  215. state.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
  216. state.times.map((item) => {
  217. item.time = item.notBeatTime + xmlMp3BeatFixTime;
  218. item.endtime = item.notBeatEndTime + xmlMp3BeatFixTime;
  219. item.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
  220. });
  221. return true;
  222. } else {
  223. state.fixtime = notBeatFixtime;
  224. state.times.map((item) => {
  225. item.time = item.notBeatTime;
  226. item.endtime = item.notBeatEndTime;
  227. item.fixtime = notBeatFixtime;
  228. });
  229. return true;
  230. }
  231. }
  232. // 演奏开了节拍器,演唱没开节拍器
  233. if (isOpenMetronome && !isSingOpenMetronome) {
  234. state.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
  235. state.times.map((item) => {
  236. item.time = item.notBeatTime + xmlMp3BeatFixTime;
  237. item.endtime = item.notBeatEndTime + xmlMp3BeatFixTime;
  238. item.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
  239. });
  240. return true;
  241. } else if (!isOpenMetronome && isSingOpenMetronome) {
  242. state.fixtime = notBeatFixtime;
  243. state.times.map((item) => {
  244. item.time = item.notBeatTime;
  245. item.endtime = item.notBeatEndTime;
  246. item.fixtime = notBeatFixtime;
  247. });
  248. return true;
  249. }
  250. } else if (oldPlayType === "sing" && playType === "sing") {
  251. // 演唱之间切换
  252. // 切到唱名时候
  253. if (playSource === "mingSong") {
  254. // 唱名文件也要加上弱起时间 他们制作曲子加了弱起时间 注意这修改了之后给总控平台的时值也需要改
  255. state.fixtime = difftime;
  256. state.times.map((item) => {
  257. item.time = item.xmlNoteTime + difftime;
  258. item.endtime = item.xmlNoteEndTime + difftime;
  259. item.fixtime = difftime;
  260. });
  261. return true;
  262. } else if (oldPlaySource === "mingSong") {
  263. // 有节拍器
  264. if (isSingOpenMetronome) {
  265. state.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
  266. state.times.map((item) => {
  267. item.time = item.notBeatTime + xmlMp3BeatFixTime;
  268. item.endtime = item.notBeatEndTime + xmlMp3BeatFixTime;
  269. item.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
  270. });
  271. return true;
  272. } else {
  273. state.fixtime = notBeatFixtime;
  274. state.times.map((item) => {
  275. item.time = item.notBeatTime;
  276. item.endtime = item.notBeatEndTime;
  277. item.fixtime = notBeatFixtime;
  278. });
  279. return true;
  280. }
  281. }
  282. }
  283. return false;
  284. }
  285. export default defineComponent({
  286. name: "header-top",
  287. emits: ["close"],
  288. setup(props, { emit }) {
  289. const query = getQuery();
  290. // 是否显示引导
  291. const showGuide = ref(false);
  292. const showStudentGuide = ref(false);
  293. const showWebGuide = ref(true);
  294. let displayFingeringCache = false; // 指法缓存
  295. /** 设置按钮 */
  296. const settingBtn = computed(() => {
  297. // 音频播放中 禁用
  298. if (state.playState === "play") return { display: true, disabled: true };
  299. // 评测开始 禁用, 跟练开始 禁用
  300. if (evaluatingData.startBegin || followData.start) return { display: true, disabled: true };
  301. return {
  302. display: true,
  303. disabled: false,
  304. };
  305. });
  306. /** 转谱按钮 */
  307. const converBtn = computed(() => {
  308. // 音频播放中 禁用
  309. if (state.playState === "play") return { display: true, disabled: true };
  310. // 评测开始 禁用
  311. if (evaluatingData.startBegin || followData.start) return { display: true, disabled: true };
  312. return {
  313. disabled: false,
  314. display: true,
  315. };
  316. });
  317. /** 速度按钮 */
  318. const speedBtn = computed(() => {
  319. // 选择模式, 跟练模式 不显示
  320. //if (headTopData.modeType !== "show" || state.modeType === "follow") return { display: false, disabled: true };
  321. if (state.modeType === "follow") return { display: false, disabled: true };
  322. // 评测模式, 音频播放中 禁用
  323. if (state.modeType === "evaluating" || state.playState === "play") return { display: true, disabled: true };
  324. return {
  325. disabled: false,
  326. display: true,
  327. };
  328. });
  329. /** 节拍器按钮 */
  330. const metronomeBtn = computed(() => {
  331. // 选择模式 不显示
  332. //if (headTopData.modeType !== "show") return { display: false, disabled: true };
  333. // 音频播放中 禁用
  334. if (state.playState === "play") return { display: true, disabled: true };
  335. return {
  336. disabled: false,
  337. display: true,
  338. };
  339. });
  340. /** 指法按钮 */
  341. const fingeringBtn = computed(() => {
  342. // 后台设置不显示指法
  343. if (!state.isShowFingering) return { display: true, disabled: true };
  344. // 没有指法 选择模式 评测模式 跟练模式 不显示
  345. //if (headTopData.modeType !== "show" || !state.fingeringInfo.name || ["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
  346. if (!state.fingeringInfo.name || ["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
  347. // 音频播放中 禁用
  348. if (state.playState === "play") return { display: true, disabled: true };
  349. return {
  350. disabled: false,
  351. display: true,
  352. };
  353. });
  354. /** 摄像头按钮 */
  355. const cameraBtn = computed(() => {
  356. // 选择模式 不显示
  357. if (headTopData.modeType !== "show" || state.modeType !== "evaluating") return { display: false, disabled: true };
  358. // 音频播放中 禁用
  359. if (state.playState === "play") return { display: true, disabled: true };
  360. return {
  361. disabled: false,
  362. display: true,
  363. };
  364. });
  365. /** 选段按钮 */
  366. const selectBtn = computed(() => {
  367. // 选择模式 不显示
  368. //if (headTopData.modeType !== "show" || ["follow"].includes(state.modeType)) return { display: false, disabled: true };
  369. if (["follow"].includes(state.modeType)) return { display: false, disabled: true };
  370. // 音频播放中 禁用
  371. if (state.playState === "play" || state.isHomeWork) return { display: true, disabled: true };
  372. return {
  373. disabled: false,
  374. display: true,
  375. };
  376. });
  377. /** 原声按钮 */
  378. const originBtn = computed(() => {
  379. // 没有音源不显示
  380. if (state.noMusicSource) return { display: false, disabled: false };
  381. // 选择模式,跟练模式 不显示
  382. //if (headTopData.modeType !== "show" || state.modeType === "follow") return { display: false, disabled: false };
  383. if (state.modeType === "follow") return { display: false, disabled: false };
  384. // 评测开始 禁用
  385. if (state.modeType === "evaluating") return { display: false, disabled: true };
  386. // 总谱渲染在播放过程中 不能切换
  387. if(state.isCombineRender && state.playState === "play") return { display: true, disabled: true }
  388. if (!state.isAppPlay) {
  389. if (state.playType === "play") {
  390. // 原声, 伴奏 少一个,就不能切换
  391. if (state.music && state.accompany) return { display: true, disabled: false };
  392. } else {
  393. // 播放过程中不能切换
  394. if (state.playState === "play") {
  395. return { display: true, disabled: true };
  396. }
  397. // 范唱
  398. let index = 0;
  399. state.fanSong && index++;
  400. state.banSong && index++;
  401. state.mingSong && index++;
  402. if (index > 1) {
  403. return { display: true, disabled: false };
  404. }
  405. }
  406. }
  407. return {
  408. disabled: true,
  409. display: true,
  410. };
  411. });
  412. /** 播放类型按钮 */
  413. const playTypeBtn = computed(() => {
  414. // 选择模式,跟练模式,评测模式 不显示
  415. //if (headTopData.modeType !== "show" || state.modeType === "follow" || state.modeType === "evaluating" || state.isHomeWork) return { display: false, disabled: false };
  416. if (state.modeType === "follow" || state.modeType === "evaluating" || state.isHomeWork) return { display: false, disabled: false };
  417. if (!state.isAppPlay) {
  418. let index = 0;
  419. state.music && index++;
  420. state.accompany && index++;
  421. let songIndex = 0;
  422. state.fanSong && songIndex++;
  423. state.banSong && songIndex++;
  424. state.mingSong && songIndex++;
  425. // 演唱和演奏 都有数据的时间不禁用
  426. if (songIndex > 0 && index > 0) {
  427. // 音频播放中 禁用
  428. if (state.playState === "play") {
  429. return { display: true, disabled: true };
  430. }
  431. return { display: true, disabled: false };
  432. }
  433. }
  434. return {
  435. disabled: false,
  436. display: false,
  437. };
  438. });
  439. /** 模式切换按钮 */
  440. const toggleBtn = computed(() => {
  441. // 乐教通不限
  442. if (query["isYjt"] == "1") return { display: false, disabled: false };
  443. // 老师端,打击乐&节奏练习不显示
  444. if (state.isPercussion && state.platform === IPlatform.PC) return { display: false, disabled: false };
  445. if(state.isCombineRender) return { display: false, disabled: false };
  446. // 没有音源不显示
  447. if (state.noMusicSource) return { display: false, disabled: false };
  448. // 不是演奏模式 影藏
  449. if (state.playType !== "play") return { display: false, disabled: false };
  450. // 选择模式, url设置模式 不显示
  451. if (headTopData.modeType !== "show" || !headTopData.showBack) return { display: false, disabled: false };
  452. // 跟练开始, 评测开始 播放开始 隐藏
  453. if (state.playState == "play" || followData.start || evaluatingData.startBegin) return { display: true, disabled: true };
  454. // 课件播放,上课页面潜入云教练,不显示模式切换
  455. if (query.hideMode == 1) return { display: false, disabled: false };
  456. return {
  457. display: true,
  458. disabled: false,
  459. };
  460. });
  461. /** 播放按钮 */
  462. const playBtn = computed(() => {
  463. // 没有音源不显示
  464. if (state.noMusicSource) return { display: false, disabled: false };
  465. // 选择模式 不显示
  466. if (headTopData.modeType !== "show") return { display: false, disabled: false };
  467. // 评测模式 不显示,跟练模式 不显示
  468. if (["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
  469. // midi音频未初始化完成不可点击
  470. if (state.isAppPlay && state.midiPlayIniting) return { display: true, disabled: true };
  471. return {
  472. display: true,
  473. disabled: false,
  474. };
  475. });
  476. /** 重播按钮 */
  477. resetBtn = computed(() => {
  478. // 没有音源不显示
  479. if (state.noMusicSource) return { display: false, disabled: false };
  480. // 选择模式 不显示
  481. if (headTopData.modeType !== "show") return { display: false, disabled: false };
  482. // 评测模式 不显示,跟练模式 不显示
  483. if (["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
  484. // 播放状态 不显示
  485. if (state.playState === "play") return { display: false, disabled: true };
  486. // 播放进度为0 不显示
  487. const currentTime = getAudioCurrentTime();
  488. // midi音频未初始化完成不可点击
  489. if (state.isAppPlay && state.midiPlayIniting) return { display: false, disabled: true };
  490. if (!currentTime) return { display: false, disabled: true };
  491. return {
  492. display: true,
  493. disabled: false,
  494. };
  495. });
  496. /** 重置按钮 */
  497. const restoreBtn = computed(() => {
  498. // 播放中 禁用
  499. if (state.playState === "play" || evaluatingData.startBegin || followData.start || state.isHomeWork) return { display: true, disabled: true };
  500. return {
  501. disabled: false,
  502. display: true,
  503. };
  504. });
  505. const browInfo = browser();
  506. /** 返回 */
  507. const handleBack = () => {
  508. // 如果是乐教通,点击返回按钮,需要关闭当前窗口
  509. if (query["isYjt"] == "1") {
  510. window.parent.postMessage(
  511. {
  512. api: "api_YjtClose"
  513. },
  514. "*"
  515. );
  516. return
  517. }
  518. // 练习作业,完整练习才记录练习次数
  519. // HANDLE_WORK_ADD();
  520. // 不在APP中,
  521. if (!storeData.isApp) {
  522. window.parent.postMessage(
  523. {
  524. api: "back",
  525. },
  526. "*"
  527. );
  528. window.close();
  529. return;
  530. }
  531. if ((browInfo.iPhone || browInfo.ios) && state.isHomeWork) {
  532. setTimeout(() => {
  533. api_back();
  534. }, 550);
  535. return;
  536. }
  537. api_back();
  538. };
  539. /** 根据参数设置模式 */
  540. const getQueryModelSetModelType = () => {
  541. /** 作业模式 start, 如果为作业模式不处理,让作业模块处理 */
  542. if (state.isHomeWork) {
  543. return;
  544. }
  545. /** 作业模式 end */
  546. if (state.defaultModeType == 1) {
  547. headTopData.handleChangeModeType("practise");
  548. // if (state.platform === IPlatform.PC || state.isPreView) {
  549. // headTopData.showBack = false;
  550. // }
  551. if (state.isPreView) {
  552. headTopData.showBack = false;
  553. }
  554. } else {
  555. if (query.modelType) {
  556. if (query.modelType === "practise") {
  557. headTopData.handleChangeModeType("practise");
  558. } else if (query.modelType === "evaluating") {
  559. headTopData.handleChangeModeType("evaluating");
  560. }
  561. headTopData.showBack = false;
  562. } else {
  563. setTimeout(() => {
  564. headTopData.modeType = "init";
  565. }, 500);
  566. }
  567. }
  568. };
  569. /** 课件播放 */
  570. const changePlay = (res: any) => {
  571. // console.log('监听上课页面message',res)
  572. if (res?.data?.api === "setPlayState") {
  573. togglePlay("paused", true);
  574. }
  575. if(res?.data?.api === 'togglePlayState') {
  576. // if(state.playState === "play") {
  577. // togglePlay("paused");
  578. // }
  579. // if(state.playState === 'paused') {
  580. // togglePlay("play");
  581. // }
  582. console.log('togglePlayState', state.playState)
  583. togglePlay(state.playState === "play" ? "paused" : "play");
  584. }
  585. // 上课页面,按钮方向
  586. if (res?.data?.api === "imagePos") {
  587. if (res?.data.data) {
  588. state.playBtnDirection = res.data.data === "right" ? "right" : "left";
  589. // if (state.fingeringInfo.direction === "vertical" && state.setting.displayFingering) {
  590. // state.musicScoreBtnDirection = state.playBtnDirection === 'right' ? 'left' : 'right';
  591. // } else {
  592. // state.musicScoreBtnDirection = state.playBtnDirection;
  593. // }
  594. state.musicScoreBtnDirection = state.playBtnDirection;
  595. }
  596. }
  597. };
  598. const parentClassName = "settingBoxClass_drag";
  599. const userId = storeData.user?.id ? String(storeData.user?.id) : "";
  600. const positionInfo =
  601. state.platform !== IPlatform.PC
  602. ? {
  603. styleDrag: { value: null },
  604. }
  605. : useDrag([`${parentClassName} .top_draging`, `${parentClassName} .bom_drag`], parentClassName, toRef(headTopData, "settingMode"), userId);
  606. const speedClassName = "speedBoxClass_drag";
  607. const speedInfo =
  608. state.platform !== IPlatform.PC
  609. ? {
  610. styleDrag: { value: null },
  611. }
  612. : useDrag([`${speedClassName} .top_draging`, `${speedClassName} .bom_drag`], speedClassName, toRef(headData, "speedShow"), userId);
  613. onMounted(() => {
  614. getQueryModelSetModelType();
  615. window.addEventListener("message", changePlay);
  616. if (state.platform === IPlatform.PC) {
  617. showGuide.value = true;
  618. } else {
  619. showStudentGuide.value = true;
  620. }
  621. if (query.showWebGuide === "false") {
  622. showWebGuide.value = false;
  623. }
  624. document.addEventListener("keydown", (e: KeyboardEvent) => {
  625. if (e.code === "Tab") {
  626. e.stopPropagation();
  627. e.preventDefault();
  628. // onStartPlayState();
  629. togglePlay(state.playState === "play" ? "paused" : "play");
  630. }
  631. });
  632. });
  633. onUnmounted(() => {
  634. window.removeEventListener("message", changePlay);
  635. });
  636. const noticeBarWidth = ref<number>();
  637. watch(
  638. () => smoothAnimationState.isShow.value,
  639. () => {
  640. // NoticeBar能不能滚动
  641. if ((smoothAnimationState.isShow.value || state.isCombineRender) && isMusicList.value) {
  642. nextTick(() => {
  643. const widthCon = (document.querySelector("#noticeBarRollDom .van-notice-bar__content") as any)?.offsetWidth || undefined;
  644. noticeBarWidth.value = widthCon;
  645. });
  646. }
  647. },
  648. { immediate: true }
  649. );
  650. // 设置改变触发
  651. watch(state.setting, () => {
  652. console.log(state.setting, "state.setting");
  653. store.set("musicscoresetting", state.setting);
  654. });
  655. const isPad = navigator?.userAgent?.includes("UAWEIVRD-W09") || browInfo?.iPad || browInfo.isTablet;
  656. return () => (
  657. <>
  658. <div
  659. class={[styles.headerTop, state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.headerTopRight : ""]}
  660. onClick={(e: Event) => {
  661. e.stopPropagation();
  662. if (state.platform === IPlatform.PC) {
  663. // 显示隐藏菜单
  664. window.parent.postMessage(
  665. {
  666. api: "onAttendToggleMenu",
  667. },
  668. "*"
  669. );
  670. }
  671. }}
  672. >
  673. {/* 返回和标题 */}
  674. {
  675. <div id="noticeBarRollDom" class={[styles.headTopLeftBox, (state.playState == "play" || followData.practiceStart || evaluatingData.startBegin) && styles.headTopLeftHide]}>
  676. {
  677. !query.isMove && !query.isHideBack && <img src={iconBack} class={["headTopBackBtn", styles.img, !headTopData.showBack && styles.hidenBack]} onClick={handleBack} />
  678. }
  679. {smoothAnimationState.isShow.value || state.isCombineRender ? (
  680. <div
  681. style={
  682. noticeBarWidth.value
  683. ? {
  684. "--noticeBarWidth": noticeBarWidth.value + "px",
  685. }
  686. : {}
  687. }
  688. class={[styles.title, state.isCbsView && styles.blackTitle, "headeTopTitleBtn", isPad && styles.isIpad]}
  689. onClick={() => {
  690. isMusicList.value && (musicListShow.value = true);
  691. }}
  692. >
  693. {isMusicList.value && <div class={[styles.symbolNote, "driver-8"]}></div>}
  694. <NoticeBar text={state.examSongName} background="none" />
  695. </div>
  696. ) : (
  697. isMusicList.value && (
  698. <img
  699. src={listImg}
  700. class={[styles.img, styles.listImg, "driver-8"]}
  701. onClick={() => {
  702. musicListShow.value = true;
  703. }}
  704. />
  705. )
  706. )}
  707. </div>
  708. }
  709. {/* 模式提醒 */}
  710. {/* {state.modeType === "practise" && (
  711. <div class={[styles.modeWarn, "practiseModeWarn", state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.modeWarnRight : ""]}>
  712. <img src={state.playType === "play" ? headImg("perform1.png") : headImg("sing1.png")} />
  713. <div>{state.playType === "play" ? "演奏场景" : "演唱场景"}</div>
  714. </div>
  715. )} */}
  716. {/* 功能按钮 */}
  717. <div
  718. class={[styles.headRight]}
  719. onClick={(e: Event) => {
  720. e.stopPropagation();
  721. }}
  722. >
  723. {/* 模式切换 */}
  724. {
  725. <div
  726. id={state.platform === IPlatform.PC ? "teacherTop-0" : "studnetT-0"}
  727. style={{ display: toggleBtn.value.display ? "" : "none"}}
  728. class={["driver-9", styles.modeChangeBox, toggleBtn.value.disabled && styles.disabled, styles.modeType]}
  729. onClick={() => {
  730. headTopData.oldModeType = state.modeType;
  731. handleRessetState();
  732. headTopData.modeType = "init";
  733. }}
  734. >
  735. <img class={styles.img} src={iconMode} />
  736. <div class={styles.title}>{state.modeType === "practise" ? "练习模式" : state.modeType === "follow" ? "跟练模式" : state.modeType === "evaluating" ? "评测模式" : ""}</div>
  737. </div>
  738. }
  739. {/* 一行谱模式,暂不支持节拍指针 */}
  740. {/* {(
  741. <div
  742. class={[styles.btn, state.platform === IPlatform.PC ? styles.pcBtn : ""]}
  743. onClick={() => {
  744. // 切换光标模式
  745. let mode = metronomeData.cursorMode;
  746. if (["follow"].includes(state.modeType)) {
  747. mode = metronomeData.cursorMode === 1 ? 3 : 1;
  748. } else {
  749. mode = metronomeData.cursorMode === 1 ? 3 : metronomeData.cursorMode === 2 ? 1 : 2;
  750. }
  751. metronomeData.cursorMode = mode;
  752. }}
  753. >
  754. <img class={styles.iconBtn} src={headImg(metronomeData.cursorMode === 1 ? "cursor_icon1.png" : metronomeData.cursorMode === 2 ? "cursor_icon2.png" : metronomeData.cursorMode === 3 ? "cursor_icon3.png" : "")} />
  755. <span class={styles.iconContent}>
  756. {metronomeData.cursorMode === 1 ? "音符指针" : metronomeData.cursorMode === 2 ? "节拍指针" : metronomeData.cursorMode === 3 ? "关闭指针" : ""}
  757. {metronomeData.cursorTips && (
  758. <div class={[styles["botton-tips"], metronomeData.cursorMode === 3 ? styles.tipSpec : ""]}>{metronomeData.cursorTips}</div>
  759. )}
  760. </span>
  761. </div>
  762. )} */}
  763. <div
  764. style={{ display: playTypeBtn.value.display ? "" : "none" }}
  765. class={["driver-2", styles.btn, playTypeBtn.value.disabled && styles.disabled, styles.playType]}
  766. onClick={() => {
  767. const oldPlayType = state.playType;
  768. headTopData.oldPlayType = oldPlayType;
  769. const oldPlaySource = state.playSource;
  770. if (state.playType === "play") {
  771. state.playType = "sing";
  772. state.playSource = state.fanSong ? "music" : state.banSong ? "background" : "mingSong";
  773. } else {
  774. state.playType = "play";
  775. state.playSource = state.music ? "music" : "background";
  776. }
  777. isClickMode = true;
  778. // 有指法并且显示指法的时候 切换到演唱模式 需要影藏指法
  779. let isRefresh = false;
  780. if (state.isShowFingering && state.fingeringInfo.name && (state.setting.displayFingering || displayFingeringCache)) {
  781. if (state.playType === "sing") {
  782. state.setting.displayFingering = false;
  783. displayFingeringCache = true;
  784. } else {
  785. state.setting.displayFingering = displayFingeringCache;
  786. displayFingeringCache = false;
  787. }
  788. // 如果是竖屏指法和一行谱的时候 改变指法值的时候state 会调用刷新 refreshMusicSvg 所以下面不调用
  789. if (state.fingeringInfo.direction === "vertical" && !state.isSingleLine) {
  790. isRefresh = true;
  791. }
  792. }
  793. // 有歌词的时候,切换播放模式,需要重新渲染谱面 指法不刷新谱面的时候
  794. if (state.xmlHasLyric && !isRefresh) {
  795. refreshMusicSvg();
  796. } else if (!isRefresh) {
  797. handlerModeChange(oldPlayType, oldPlaySource, true);
  798. }
  799. }}
  800. >
  801. <img style={{ display: state.playType === "play" ? "" : "none" }} class={styles.iconBtn} src={headImg(`perform.png`)} />
  802. <img style={{ display: state.playType === "play" ? "none" : "" }} class={styles.iconBtn} src={headImg(`sing.png`)} />
  803. <span>{state.playType === "play" ? "演奏" : "演唱"}</span>
  804. </div>
  805. <div
  806. id={state.platform === IPlatform.PC ? "teacherTop-1" : "studnetT-1"}
  807. style={{ display: originBtn.value.display ? "" : "none" }}
  808. class={["driver-3", styles.btn, originBtn.value.disabled && styles.disabled, state.playType === "play" ? styles.playSource : styles.songSource]}
  809. onClick={() => {
  810. const oldPlayType = state.playType;
  811. const oldPlaySource = state.playSource;
  812. if (state.playType === "play") {
  813. state.playSource = state.playSource === "music" ? "background" : "music";
  814. } else {
  815. if (state.playSource === "music") {
  816. state.playSource = state.banSong ? "background" : "mingSong";
  817. } else if (state.playSource === "background") {
  818. state.playSource = state.mingSong ? "mingSong" : "music";
  819. } else {
  820. state.playSource = state.fanSong ? "music" : "background";
  821. }
  822. }
  823. handlerModeChange(oldPlayType, oldPlaySource);
  824. // 总谱 并且开启了单个声轨音频时候
  825. if(state.isCombineRender && state.playSource === "background") {
  826. audioData.combineIndex = -1
  827. state.music = ""
  828. }
  829. showToast({
  830. message: state.playType === "play" ? (state.playSource === "music" ? "已切换为原声" : "已切换为伴奏") : state.playSource === "music" ? "已切换为范唱" : state.playSource === "background" ? "已切换为伴唱" : "已切换为唱名",
  831. position: "top",
  832. className: "selectionToast",
  833. });
  834. }}
  835. >
  836. <img style={{ display: state.playSource === "music" ? "" : "none" }} class={styles.iconBtn} src={state.playType === "play" ? headImg(`music.png`) : headImg(`music1.png`)} />
  837. <img style={{ display: state.playSource === "background" ? "" : "none" }} class={styles.iconBtn} src={state.playType === "play" ? headImg(`background.png`) : headImg(`background1.png`)} />
  838. <img style={{ display: state.playSource === "mingSong" ? "" : "none" }} class={styles.iconBtn} src={headImg(`mingsong.png`)} />
  839. <span>{state.playSource === "music" ? (state.playType === "play" ? "原声" : "范唱") : state.playSource === "background" ? (state.playType === "play" ? "伴奏" : "伴唱") : "唱名"}</span>
  840. </div>
  841. <div
  842. id={state.platform === IPlatform.PC ? "teacherTop-2" : "studnetT-2"}
  843. style={{ display: selectBtn.value.display ? "" : "none" }}
  844. class={["driver-4", styles.btn, selectBtn.value.disabled && styles.disabled, styles.section, state.sectionStatus && styles.isSection]}
  845. onClick={() => handleChangeSection()}
  846. >
  847. <img style={{ display: state.section.length === 0 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section0.png`)} />
  848. <img style={{ display: state.section.length === 1 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section1.png`)} />
  849. <img style={{ display: state.section.length === 2 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section2.png`)} />
  850. <span>选段</span>
  851. </div>
  852. {
  853. <>
  854. <div
  855. style={{ display: metronomeBtn.value.display ? "" : "none" }}
  856. class={["driver-5", styles.btn, styles.metronomeBtn, metronomeBtn.value.disabled && styles.disabled, headData.speedShow && styles.isSpeed, styles.speed]}
  857. onClick={async () => {
  858. headData.speedShow = !headData.speedShow;
  859. }}
  860. >
  861. <img style={{ display: metronomeData.disable ? "block" : "none" }} class={styles.iconBtn} src={headImg("tickon.png")} />
  862. <img style={{ display: !metronomeData.disable ? "block" : "none" }} class={styles.iconBtn} src={headImg("tickoff.png")} />
  863. <span style={{ whiteSpace: "nowrap" }}>节拍</span>
  864. <div class={styles.speedCon}>
  865. <img src={headImg(`${state.speedIcon}.png`)} />
  866. <div>{Math.floor(state.speed)}</div>
  867. </div>
  868. </div>
  869. {
  870. <Popup v-model:show={headData.speedShow} class="popup-custom van-scale center-closeBtn speedBoxClass_drag" transition="van-scale" teleport="body" style={speedInfo.styleDrag.value} overlay-style={{ background: "rgba(0, 0, 0, 0.7)" }}>
  871. <Speed />
  872. {state.platform === IPlatform.PC && <Dragbom showGuide={!state.guideInfo?.teacherDrag} onGuideDone={handleGuide} />}
  873. </Popup>
  874. }
  875. </>
  876. }
  877. {/* {state.enableNotation ? (
  878. <Popover trigger="manual" v-model:show={headData.musicTypeShow} class={state.platform === IPlatform.PC && styles.pcTransPop} placement={state.platform === IPlatform.PC ? "top-end" : "bottom-end"} overlay={false} offset={state.platform === IPlatform.PC ? [0, 40] : [0, 8]}>
  879. {{
  880. reference: () => (
  881. <div
  882. id={state.platform === IPlatform.PC ? "teacherTop-5" : "studnetT-5"}
  883. style={{ display: converBtn.value.display ? "" : "none" }}
  884. class={[styles.btn, converBtn.value.disabled && styles.disabled]}
  885. onClick={(e: Event) => {
  886. e.stopPropagation();
  887. headData.musicTypeShow = !headData.musicTypeShow;
  888. }}
  889. >
  890. <img class={styles.iconBtn} src={headImg("icon_zhuanpu.svg")} />
  891. <span>{state.musicRenderType === "staff" ? "转简谱" : "转五线谱"}</span>
  892. </div>
  893. ),
  894. default: () => <MusicType />,
  895. }}
  896. </Popover>
  897. ) : null} */}
  898. {state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert && (
  899. <div
  900. class={[styles.btn, state.playState === "play" && fingeringBtn.value.disabled && styles.disabled, toggleMusicSheet.show && styles.isMusicSheet, styles.musicSheet, "driver-10"]}
  901. onClick={() => {
  902. toggleMusicSheet.toggle(true);
  903. }}
  904. >
  905. <img class={styles.iconBtn} src={headImg(`shenggui.png`)} />
  906. <span>声部</span>
  907. </div>
  908. )}
  909. {
  910. <div
  911. class={[styles.btn, restoreBtn.value.disabled && styles.disabled, styles.cxSetBtn, "driver-5-1"]}
  912. onClick={() => resetSettings()}
  913. >
  914. <img class={styles.iconBtn} src={headImg("reset.png")} />
  915. <span>重置</span>
  916. </div>
  917. }
  918. <div
  919. id={state.platform === IPlatform.PC ? "teacherTop-6" : "studnetT-6"}
  920. style={{ display: settingBtn.value.display ? "" : "none" }}
  921. class={["driver-6", styles.btn, settingBtn.value.disabled && styles.disabled, headTopData.settingMode && styles.isSettingMode, styles.settingMode]}
  922. onClick={() => (headTopData.settingMode = true)}
  923. >
  924. <img class={styles.iconBtn} src={headImg("icon_menu.png")} />
  925. <span>设置</span>
  926. </div>
  927. </div>
  928. </div>
  929. {/** 指法点击区域 */}
  930. {/* {
  931. state.fingeringInfo.direction === "transverse" && state.setting.displayFingering ?
  932. <div class={styles.headerMid} onClick={() => {
  933. fingerRef.value?.doubeClick()
  934. }}></div> : null
  935. } */}
  936. {/* 播放按钮 */}
  937. <div
  938. id="studnetT-7"
  939. style={{ display: playBtn.value.display ? "" : "none" }}
  940. class={[
  941. // 引导使用的类
  942. "driver-1",
  943. styles.playBtn,
  944. playBtn.value.disabled && styles.disabled,
  945. state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.playLeftButton : state.platform === IPlatform.PC && state.musicScoreBtnDirection === "right" ? styles.playRightButton : "",
  946. ]}
  947. onClick={() => {
  948. // C调能播放唱名,非C调时,只有谱面类型是首调时,才能播放唱名
  949. if (!state.isCTone && state.playSource === 'mingSong') {
  950. const notPlayDesc = state.musicRenderType === EnumMusicRenderType.staff ? '该曲目的五线谱目前还不支持播放唱名' : state.musicRenderType === EnumMusicRenderType.fixedTone ? '该曲目的固定调目前还不支持播放唱名' : '';
  951. if (notPlayDesc) {
  952. showToast({
  953. message: notPlayDesc,
  954. position: "top",
  955. className: "selectionToast",
  956. });
  957. return
  958. }
  959. }
  960. togglePlay(state.playState === "play" ? "paused" : "play")
  961. }}
  962. >
  963. <div class={styles.btnWrap}>
  964. <img style={{ display: state.playState === "play" ? "none" : "" }} class={styles.iconBtn} src={headImg("icon_play.png")} />
  965. <img style={{ display: state.playState === "play" ? "" : "none" }} class={styles.iconBtn} src={headImg("icon_pause.png")} />
  966. <Circle style={{ opacity: state.playState === "play" ? 1 : 0 }} class={styles.progress} stroke-width={60} stroke-linecap={"square"} currentRate={state.playProgress} rate={100} color="#FFED78" layer-color="rgba(255,255,255,0.5)" />
  967. </div>
  968. </div>
  969. {/* 重播按钮 */}
  970. <div
  971. id="tips-step-9"
  972. style={{ display: resetBtn.value.display ? "" : "none" }}
  973. class={[styles.resetBtn, resetBtn.value.disabled && styles.disabled, state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.pauseLeftButton : state.platform === IPlatform.PC && state.musicScoreBtnDirection === "right" ? styles.pauseRightButton : ""]}
  974. onClick={() => handleResetPlay()}
  975. >
  976. <img class={styles.iconBtn} src={headImg("icon_reset.png")} />
  977. </div>
  978. <Popup v-model:show={headTopData.settingMode} class="popup-custom van-scale center-closeBtn settingBoxClass_drag" transition="van-scale" teleport="body" style={positionInfo.styleDrag.value} overlay-style={{ background: "rgba(0, 0, 0, 0.7)" }}>
  979. <Settting />
  980. {state.platform === IPlatform.PC && <Dragbom showGuide={!state.guideInfo?.teacherDrag} onGuideDone={handleGuide} />}
  981. </Popup>
  982. {/* 模式切换 */}
  983. {/* <ModeTypeMode /> */}
  984. <ModeView></ModeView>
  985. {/* isAllBtns */}
  986. {/* {isAllBtns.value && !query.isCbs && showGuideIndex.value && <TeacherTop></TeacherTop>}
  987. {isAllBtnsStudent.value && !query.isCbs && showGuideIndex.value && <StudentTop></StudentTop>} */}
  988. {/* 练习模式功能引导 加载音频完成 不是会员 */}
  989. {state.modeType === "practise" && headTopData.modeType !== "init" && !query.isCbs && state.audioDone && !state.isLoading && showWebGuide.value && (
  990. <PractiseDriver
  991. statusAll={{
  992. playBtnStatus: playBtn.value.display,
  993. subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
  994. modelTypeStatus: toggleBtn.value.display,
  995. playType: playTypeBtn.value.display,
  996. originPlayType: state.playType === "play" ? true : false,
  997. originBtnStatus: originBtn.value.display,
  998. backTitle: !(state.playState == "play" || followData.start || evaluatingData.startBegin) && isMusicList.value,
  999. titleType: smoothAnimationState.isShow.value ? "TEXT" : isMusicList.value ? "IMG" : "NONE",
  1000. showSwitchList: isMusicList.value && !state.isHomeWork && !query.isHideMusicList,
  1001. }}
  1002. />
  1003. )}
  1004. {/* 跟练模式功能引导 加载音频完成 不是会员 */}
  1005. {state.modeType === "follow" && headTopData.modeType !== "init" && !query.isCbs && state.audioDone && !state.isLoading && showWebGuide.value && (
  1006. <FollowDriver
  1007. statusAll={{
  1008. subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
  1009. }}
  1010. />
  1011. )}
  1012. {/* 评测模式功能引导 加载音频完成 不是会员 */}
  1013. {state.modeType === "evaluating" && headTopData.modeType !== "init" && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !state.isLoading && evaluatingData.websocketState && !evaluatingData.startBegin && evaluatingData.checkEnd && showWebGuide.value && (
  1014. <EvaluatingDriver
  1015. statusAll={{
  1016. subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
  1017. }}
  1018. />
  1019. )}
  1020. </>
  1021. );
  1022. },
  1023. });