import { PropType, computed, defineComponent, nextTick, onBeforeMount, onMounted, onUnmounted, reactive, ref,toRef } from "vue"; import styles from "./index.module.less"; import icons from "./image/icons.json"; import { FIGNER_INSTRUMENT_DATA, FIGNER_INSTRUMENT_REALKEY, IFIGNER_INSTRUMENT_Note } from "/src/view/figner-preview"; import { ITypeFingering, IVocals, getFingeringConfig, mappingVoicePart, subjectFingering } from "/src/view/fingering/fingering-config"; import { Howl } from "howler"; import { storeData } from "/src/store"; import { api_back, api_cloudLoading, api_setRequestedOrientation, api_setStatusBarVisibility, isSpecialShapedScreen } from "/src/helpers/communication"; import Hammer from "hammerjs"; import { Button, Icon, Loading, Popover, Popup, Progress, Space, showToast } from "vant"; import GuideIndex from "./guide/guide-index"; import { getQuery } from "/src/utils/queryString"; import { browser } from "/src/utils"; import { usePageVisibility } from "@vant/use"; import { watch } from "vue"; import icon_loading_img from "./image/icon_loading_img.png"; import state, { IPlatform } from "/src/state"; import { api_musicalInstrumentList, api_subjectList, getSubjectList } from "../api"; import ChangeSubject from "./change-subject"; import { Tabs,Tab } from "vant" import useDrag from '/src/hooks/useDrag'; import Dragbom from '/src/hooks/useDrag/dragbom'; export default defineComponent({ name: "viewFigner", emits: ["close"], props: { show: { type: Boolean, default: true, }, isComponent: { type: Boolean, default: false, }, subject: { type: String as PropType, default: "", }, }, setup(props, { emit }) { const query = getQuery(); const browsInfo = browser(); const code = mappingVoicePart(query.code, "INSTRUMENT"); const subject = props.isComponent ? props.subject || "pan-flute" : code || "pan-flute"; const data = reactive({ linkSource: query.linkSource, // 来源,目前只有课件里使用 loading: true, subject: subject as any, realKey: 0, notes: [] as IFIGNER_INSTRUMENT_Note[], tones: [] as IFIGNER_INSTRUMENT_Note[], activeTone: {} as IFIGNER_INSTRUMENT_Note, popupActiveTone: {} as IFIGNER_INSTRUMENT_Note, activeToneName: "", soundFonts: {} as any, viewIndex: 0, viewTotal: 1, noteAudio: null as unknown as Howl, transform: { scale: 1, x: 0, y: 0, startScale: 1, startX: 0, startY: 0, transition: "", }, tipShow: false, tips: [] as IFIGNER_INSTRUMENT_Note[], tnoteShow: false, loadingSoundFonts: true, loadingSoundProgress: 0, changeSubjectShow: false, huaweiPad: navigator?.userAgent?.includes("UAWEIVRD-W09") ? true : false, paddingTop: "", paddingLeft: "", subjects: [] as any, fingeringModeList: [ { text: "指法模式", value: "fingeringMode", icon: icons.icon_click, }, { text: "听音模式", value: "listenMode", icon: icons.icon_listen, }, { text: "音阶模式", value: "scaleMode", icon: icons.icon_mode, }, ], fingeringMode: query.type || ("scaleMode" as "fingeringMode" | "listenMode" | "scaleMode"), // 模式 noteType: "all" as "#c" | "all", // 音调 loadingDom: false, // 切换乐器时需要重置 loadingImg: false, // 切换模式,加载图片 }); const fingerData = reactive({ relationshipIndex: 0, subject: null as unknown as ITypeFingering, fingeringInfo: subjectFingering(data.subject), }); if (!props.isComponent) { state.fingeringInfo = fingerData.fingeringInfo; } const getAPPData = async (type: "top" | "left") => { const screenData = await isSpecialShapedScreen(); if (screenData?.content) { console.log("🚀 ~ screenData:", screenData.content); const { isSpecialShapedScreen, notchHeight } = screenData.content; if (isSpecialShapedScreen) { if (type === "top") { data.paddingTop = 25 + "px"; } if (type === "left") { data.paddingLeft = 25 + "px"; } } } }; const getHeadTop = () => { if (fingerData.fingeringInfo.orientation === 1) { getAPPData("top"); } if (fingerData.fingeringInfo.orientation === 0) { getAPPData("left"); } }; const getNotes = () => { const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA]; if (fignerData) { data.tones = fignerData.tones || []; if (data.tones.length) { data.activeTone = data.tones[0]; data.popupActiveTone = data.tones[0]; } data.tips = fignerData.tips || []; setNotes(); setTimeout(() => { data.loading = false; }, 600); } }; const setNotes = () => { const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA]; if (fignerData) { const tempNotes = fignerData[`list${data.activeTone.realName || ""}`]; const appendNote: any = []; tempNotes.forEach((note: any) => { note.steps = new Array(Math.abs(note.step)).fill(1); if (FIGNER_INSTRUMENT_REALKEY.includes(note.realKey)) { appendNote.push(note); } }); // 判断是音符状态 data.notes = data.noteType === "#c" ? appendNote : tempNotes; // data.notes = fignerData[`list${data.activeTone.realName || ""}`]; } }; const getFingeringData = async () => { const subject: any = data.subject + (data.viewIndex === 0 ? "" : data.viewIndex); console.log("🚀 ~ subject:模式", subject, data.viewIndex, data.fingeringMode); fingerData.subject = await getFingeringConfig(subject); }; const createAudio = (url: string) => { return new Promise((resolve, reject) => { const noteAudio = new Howl({ src: url, loop: true, onload: () => { resolve(noteAudio); }, onloaderror: () => { reject(new Error(`加载音频失败`)); }, }); }); }; const getSounFonts = async () => { const pathname = /(192|localhost)/.test(location.origin) ? "/" : location.pathname; data.loadingSoundFonts = true; try { data.loadingSoundProgress = 0; for (let i = 0; i < data.notes.length; i++) { const note = data.notes[i]; // console.log("🚀 ~ note:", i); let url = `${pathname}soundfonts/${data.subject}/`; url += note.realName; url += ".mp3"; data.soundFonts[note.realKey] = await createAudio(url); data.loadingSoundProgress = Math.floor(((i + 1) / data.notes.length) * 100); } data.loadingSoundProgress = 100; } catch (e: any) { // showToast(e.message); } api_cloudLoading(); data.loadingSoundFonts = false; }; // const selectSubjectType = (subject: string) => { // data.subjects.forEach((item: any) => { // if (item.value === subject) { // item.className = styles.selected; // } else { // item.className = ""; // } // }); // }; // 切换当前模式 const onChangeFingeringModel = (e: any) => { e.stopPropagation(); // if (playAction.listenLock) return; if (playAction.showAnswerLoading) return; data.loadingImg = true; if (data.fingeringMode === "scaleMode") { if (["pan-flute", "ocarina", "whistling"].includes(data.subject)) { data.viewIndex = 1; } else { data.viewIndex = 0; } const o: any = { "pan-flute": 2, ocarina: 2, whistling: 2, piccolo: 2, "hulusi-flute": 2, "baroque-recorder": 2, }; data.viewTotal = o[data.subject] || 1; data.fingeringMode = "listenMode"; } else if (data.fingeringMode === "listenMode") { data.fingeringMode = "fingeringMode"; } else if (data.fingeringMode === "fingeringMode") { data.fingeringMode = "scaleMode"; data.viewIndex = 0; data.noteType = "all"; } data.tipShow = false; resetMode(true, 0); setTimeout(() => { __init(false); }, 100); }; const __init = async (loadSong = true) => { data.loadingDom = true; getNotes(); // selectSubjectType(data.subject); if (data.fingeringMode === "fingeringMode") { if (data.subject === "pan-flute") { data.viewIndex = 3; } else if (["pan-flute", "ocarina", "melodica", "whistling"].includes(data.subject)) { data.viewIndex = 1; } } else { if (["pan-flute", "ocarina", "whistling"].includes(data.subject)) { data.viewIndex = 1; } } const o: any = { "pan-flute": 2, ocarina: 2, whistling: 2, piccolo: 2, "hulusi-flute": 2, "baroque-recorder": 2, }; data.viewTotal = o[data.subject] || 1; getFingeringData(); getHeadTop(); if (loadSong) { await getSounFonts(); } data.loadingDom = false; data.loadingImg = false; }; // 获取声部 const getSubjects = async () => { try { // api_subjectList // const subjects = await api_musicalInstrumentList({ // enableFlag: true, // }); // const rows = subjects.data || []; // rows.forEach((row: any) => { // const tempList: any = { // text: row.name, // value: mappingVoicePart(row.code, "INSTRUMENT"), // mappingVoicePart(row.code, "INSTRUMENT"), // id: row.id, // }; // data.subjects.push(tempList); // }); const subjects = await api_subjectList({ enableFlag: true, delFlag: 0, page: 1, rows: 999, }); const rows = subjects.data || []; const tempSubjects: any[] = []; rows.forEach((row: any) => { const tempList: any = { text: row.name, value: "", // mappingVoicePart(row.code, "INSTRUMENT"), id: row.id, children: [] as any, }; if (Array.isArray(row.instruments)) { row.instruments.forEach((i: any) => { tempList.children.push({ text: i.name, id: i.id, value: mappingVoicePart(i.code, "INSTRUMENT"), }); }); } tempSubjects.push(tempList); // if (row.instruments && row.instruments.length > 0) { // if (row.instruments.length > 1) { // row.instruments.forEach((i: any) => { // tempList.children.push({ // text: i.name, // id: i.id, // value: mappingVoicePart(i.code, "INSTRUMENT"), // }); // }); // } else { // const singleRow = row.instruments[0]; // if (singleRow.code) { // tempList.value = mappingVoicePart(singleRow.code, "INSTRUMENT"); // tempList.id = singleRow.id; // } // } // } // data.subjects.push(tempList); }); console.log(data.subject, "data.subject"); // tempSubjects.forEach((item: any) => { // if (item.value === data.subject && item.children?.length > 1) { // data.subject = item.children[0].value; // } // }); data.subjects = tempSubjects; } catch (e) { // console.log(e, "e"); } }; onBeforeMount(async () => { if (browser().isApp) { state.platform = "APP" as IPlatform; } else { state.platform = query.platform?.toLocaleUpperCase() || ""; } if (state.platform === IPlatform.PC) { document.title = "听音练习"; } await getSubjects(); __init(); }); /** * 播放音频 * @param item 音频节点 * @param showNote 是否显示对应的指法 * @returns */ const noteClick = (item: IFIGNER_INSTRUMENT_Note, showNote = true) => { // console.log('音高', item.realKey) if (data.noteAudio) { data.noteAudio.stop(); if (data.realKey === item.realKey) { data.realKey = 0; data.noteAudio = null as unknown as Howl; return; } } if (showNote) { data.realKey = item.realKey; } console.log("key:", item.realKey, data.soundFonts); data.noteAudio = data.soundFonts[item.realKey]; if (data.noteAudio) { data.noteAudio.play(); } }; const handleStop = () => { if (data.noteAudio) { data.noteAudio.stop(); data.realKey = 0; data.noteAudio = null as unknown as Howl; } }; /** 返回 */ const handleBack = () => { // platform: query.platform, handleStop(); if (props.isComponent) { // 返回的时候默认横屏 // api_setRequestedOrientation(0); emit("close"); return; } else if (state.platform === IPlatform.PC) { console.log(1, query); if (query.matchMedia == 1) { // 老师端,首页 window.parent.postMessage( { api: "iframe_exit", }, "*" ); return; } else { window.close(); return; } // if (fingerData.fingeringInfo.orientation === 0) { // api_setRequestedOrientation(1); // } } // 不在APP中, if (!storeData.isApp) { window.close(); return; } api_back(); }; // 排箫,默认0.9显示 const setDefaultScale = () => { if (data.subject === "pan-flute") { data.transform.scale = 0.9; data.transform.startScale = 0.9; } }; onMounted(() => { loadElement(); api_setStatusBarVisibility(); }); const loadElement = () => { const fingeringContainer = document.getElementById("fingeringContainer"); setDefaultScale(); // console.log("🚀 ~ fingeringContainer:", fingeringContainer); const mc = new Hammer.Manager(fingeringContainer as HTMLElement); mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 })); mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get("pan")]); // mc.get("pan").set({ direction: Hammer.DIRECTION_ALL }); // mc.get("pinch").set({ enable: true }); mc.on("panstart pinchstart", function (ev) { data.transform.transition = ""; }); mc.on("panmove pinchmove", function (ev) { if (ev.type === "pinchmove") { // console.log("🚀 ~ ev:", ev.type, ev.scale, ev.deltaX, ev.deltaY); data.transform.scale = ev.scale * data.transform.startScale; data.transform.x = data.transform.startX + ev.deltaX; data.transform.y = data.transform.startY + ev.deltaY; } if (ev.type === "panmove") { // console.log("🚀 ~ ev:", ev.type, ev.deltaX, ev.deltaY); data.transform.x = data.transform.startX + ev.deltaX; data.transform.y = data.transform.startY + ev.deltaY; } }); // mc.on("hammer.input", function (ev) { if (ev.isFinal) { data.transform.startScale = data.transform.scale; data.transform.startX = data.transform.x; data.transform.startY = data.transform.y; } }); }; const resetElement = () => { data.transform.transition = "all 0.3s"; nextTick(() => { data.transform.scale = data.subject === "pan-flute" ? 0.9 : 1; data.transform.x = 0; data.transform.y = 0; data.transform.startScale = data.subject === "pan-flute" ? 0.9 : 1; data.transform.startX = 0; data.transform.startY = 0; }); }; // 判断乐器是否移动 const instrumentTranstion = computed(() => { const transform = data.transform; let scale = 1; if (data.subject === "pan-flute") { scale = 0.9; } if (transform.scale !== scale || transform.x !== 0 || transform.y !== 0 || transform.startScale !== scale || transform.startX !== 0 || transform.startY !== 0) { return true; } else { return false; } }); const pageVisible = usePageVisibility(); watch( () => pageVisible.value, (val) => { if (val === "hidden") { clearTimeout(playAction.timer); playAction.listenLock = false; playAction.listenTipsStatus = false; playAction.exampleAnser = {}; resetMode(true, 0); handleStop(); gaumntPause(); } } ); /** 课件播放 */ const changePlay = (res: any) => { if (res?.data?.api === "setPlayState") { clearTimeout(playAction.timer); playAction.listenLock = false; playAction.listenTipsStatus = false; playAction.exampleAnser = {}; resetMode(true, 0); handleStop(); gaumntPause(); // 重置乐器 if (res?.data?.data.code) { data.subject = code; data.viewIndex = 0; data.tipShow = false; data.loadingDom = true; fingerData.fingeringInfo = subjectFingering(data.subject); data.activeTone = {} as any; resetElement(); // 设置屏幕方向 setTimeout(() => { __init(); }, 100); } } }; const noteBoxRef = ref(); const scrollNoteBox = (type: "left" | "right") => { const width = noteBoxRef.value.offsetWidth / 2; (noteBoxRef.value as unknown as HTMLElement).scrollBy({ left: type === "left" ? -width : width, behavior: "smooth", }); }; const playStatus = reactive({ gamut: false, // 是否播放音阶 gamutTimer: null as any, // 播放音阶定时器 answer: false, // 是否显示答案 action: false, // 是否开始播放 }); /** 音符切换 */ const noteChangeShow = () => { if (playStatus.action) { if (playAction.listenLock) return; playAction.resetAction = true; resetMode(true, 0); } // // 播放音阶时不能切换 // if (playStatus.gamut) return; // // 开始答题不能切换 // if (playStatus.action) return; playStatus.gamut = false; gaumntPause(); if (data.noteType === "all") { data.noteType = "#c"; } else { data.noteType = "all"; } getNotes(); setTimeout(() => { playAction.resetAction = false; }, 2000); }; // 开始播放音阶 const onGamutPlayOrPause = async () => { playAction.resetAction = false; if (playStatus.gamut) { playStatus.gamut = false; gaumntPause(); } else { // 不管当前显示在哪个音老师滚动到开始位置 (noteBoxRef.value as unknown as HTMLElement).scroll({ left: 0, top: 0, behavior: "smooth", }); playStatus.gamut = true; const notes = data.notes; let scrollCount = 0; for (let i = 0; i < notes.length; i++) { if (!playStatus.gamut) return false; const activeDom = document.querySelectorAll(".note-class")[i] as any; if (activeDom.offsetLeft >= noteBoxRef.value.offsetWidth + (noteBoxRef.value.offsetWidth / 2) * scrollCount - activeDom.offsetWidth) { scrollNoteBox("right"); scrollCount++; } await gaumtPlay(notes[i]); } // // 处理播放到最后一个 setTimeout(() => { playStatus.gamut = false; gaumntPause(); }, 667); } }; const gaumtPlay = (note: any, status?: boolean) => { return new Promise((resolve) => { playStatus.gamutTimer = setTimeout(() => { if (playStatus.gamut || status) { noteClick(note); } resolve(note); }, 667); }); }; const gaumntPause = () => { clearTimeout(playStatus.gamutTimer); if (data.noteAudio) { data.noteAudio.stop(); data.realKey = 0; data.noteAudio = null as unknown as Howl; } }; /** 开始播放 */ const playAction = reactive({ exampleAnser: {} as any, // 示例声音 standardAnswer: {} as any, // 标准答案key showAnswerLoading: false, // 显示按答案中 listenModeStatus: false, // 是否开始了模式 listenLock: false, listenTipsStatus: false, // 开始播放状态 resetAction: false, // 是否重置 /** 0: 未答,1: 答对,2: 答错 */ userAnswerStatus: 0 as 0 | 1 | 2, // 用户回答状态 userAnswer: {} as any, // 用户答的数据 timer: null as any, }); const onActionPlay = async () => { playAction.resetAction = false; if (playAction.listenLock) return; if (playAction.showAnswerLoading) return; playStatus.action = true; playStatus.answer = true; // 先暂停播放声音 gaumntPause(); if (data.fingeringMode === "fingeringMode") { onFingeringMode(); } else if (data.fingeringMode === "listenMode") { if (playAction.listenModeStatus) { playAction.listenLock = true; await fingeringPlay(playAction.standardAnswer, 1500, false); gaumntPause(); playAction.listenLock = false; } else { onListenMode(); } } }; // 指法模式 const fingeringPlay = (note: any, timer = 1500, showNote = true) => { return new Promise((resolve) => { noteClick(note, showNote); playAction.timer = setTimeout(() => { resolve(note); }, timer); }); }; const onFingeringMode = () => { const randomIndex = Math.floor(Math.random() * data.notes.length); playAction.standardAnswer = data.notes[randomIndex]; data.realKey = data.notes[randomIndex].realKey; if (playAction.listenModeStatus) { return; } playAction.listenModeStatus = true; // 是否开始听音 playAction.listenLock = true; // 锁 playAction.listenTipsStatus = true; playAction.timer = setTimeout(() => { playAction.listenTipsStatus = false; playAction.listenLock = false; // 锁 }, 2000); }; // 听音模式 const onListenMode = async () => { playAction.listenModeStatus = true; // 是否开始听音 playAction.listenLock = true; // 锁 playAction.listenTipsStatus = true; // 设置并保存示例数据 let randomIndex = data.notes.findIndex((item: any) => item.realKey === 67); // Math.floor(Math.random() * data.notes.length); playAction.exampleAnser = data.notes[randomIndex]; data.realKey = playAction.exampleAnser.realKey; scrollAnswer(playAction.exampleAnser.realKey); await fingeringPlay(playAction.exampleAnser); data.realKey = 0; playAction.exampleAnser = {}; gaumntPause(); playAction.timer = setTimeout(async () => { // 设置答题数据 randomIndex = Math.floor(Math.random() * data.notes.length); playAction.standardAnswer = data.notes[randomIndex]; await fingeringPlay(data.notes[randomIndex], 1500, false); gaumntPause(); playAction.listenLock = false; playAction.listenTipsStatus = false; }, 1000); }; // 显示答案 const onShowAnswer = async () => { if (playAction.listenLock) return; playAction.showAnswerLoading = true; scrollAnswer(playAction.standardAnswer.realKey); await fingeringPlay(playAction.standardAnswer); resetMode(true, 0); // } }; // 滚动到对应答案位置 const scrollAnswer = (realKey?: any) => { const tempRealKey = realKey || data.realKey; const index = data.notes.findIndex((item: any) => item.realKey === tempRealKey); const activeDom = document.querySelectorAll(".note-class")[index] as any; if (activeDom) { const aWidth = activeDom.offsetWidth; const width = noteBoxRef.value.offsetWidth; const aLeft = Math.max(activeDom?.offsetLeft - aWidth, 0); (noteBoxRef.value as unknown as HTMLElement).scroll({ left: Math.max(aLeft - width / 2, 0), top: 0, behavior: "smooth", }); } }; /** * 重置播放状态 * @param status 是否全部重置 * @param timer 延时时长(默认2s) */ const resetMode = (status = true, timer = 2000) => { // 2秒钟后重置 setTimeout(() => { gaumntPause(); if (status) { playAction.standardAnswer = {}; playAction.showAnswerLoading = false; playAction.userAnswerStatus = 0; playAction.userAnswer = {}; playAction.listenModeStatus = false; playStatus.action = false; playStatus.answer = false; playStatus.gamut = false; data.realKey = 0; } else { playAction.userAnswerStatus = 0; playAction.userAnswer = {}; } }, timer); }; /** 滚轮缩放 */ const handleWheel = (e: WheelEvent) => { e.preventDefault(); if (e.deltaY > 0) { data.transform.scale -= 0.1; if (data.transform.scale <= 0.5) { data.transform.scale = 0.5; } } else { data.transform.scale += 0.1; if (data.transform.scale >= 2) { data.transform.scale = 2; } } }; onMounted(() => { window.addEventListener("message", changePlay); const fingeringContainer = document.getElementById("fingeringContainer"); fingeringContainer?.addEventListener("wheel", handleWheel); }); onUnmounted(() => { window.removeEventListener("message", changePlay); const fingeringContainer = document.getElementById("fingeringContainer"); fingeringContainer?.removeEventListener("wheel", handleWheel); document.title = "Ai学练"; }); const containerBox = computed(() => { if (state.platform === IPlatform.PC || query.modelType) { return { paddingTop: "1.3rem", paddingBottom: "", }; } if (data.fingeringMode === "scaleMode") { if (data.subject === "hulusi-flute") { return { paddingTop: "1.3rem", paddingBottom: ".5rem", }; } else if (data.subject === "piccolo" || data.subject === "baroque-recorder") { return { paddingTop: "1.3rem", paddingBottom: ".5rem", }; } else if (data.subject === "pan-flute") { return { paddingTop: "1.3rem", paddingBottom: "0", }; } else if (data.subject === "ocarina" || data.subject === "whistling") { return { paddingTop: "1.3rem", paddingBottom: "0", }; } else if (data.subject === "melodica") { return { paddingTop: "1.8rem", paddingBottom: "0.2rem", }; } else { return { paddingTop: "", paddingBottom: "", }; } } else { if (data.subject === "hulusi-flute") { return { paddingTop: "1.3rem", paddingBottom: "0rem", }; } else if (data.subject === "piccolo" || data.subject === "baroque-recorder") { return { paddingTop: "1.3rem", paddingBottom: ".5rem", }; } else if (data.subject === "pan-flute") { return { paddingTop: "1.3rem", paddingBottom: "0", }; } else if (data.subject === "ocarina" || data.subject === "whistling") { return { paddingTop: "1.3rem", paddingBottom: "0", }; } else if (data.subject === "melodica") { return { paddingTop: "1.8rem", paddingBottom: "0.2rem", }; } else { return { paddingTop: "", paddingBottom: "", }; } } }); const listenText = computed(() => { if (data.fingeringMode === "fingeringMode") { if (playStatus.action) { return "换一换"; } else { return "开始练习"; } } else if (data.fingeringMode === "listenMode") { if (playStatus.action) { return "再听一遍"; } else { return "开始听音"; } } return "开始听音"; }); const modeText = computed(() => { let text = ""; let icon = icons.icon_mode; data.fingeringModeList.forEach((item: any) => { if (item.value === data.fingeringMode) { text = item.text; icon = item.icon; } }); return { text, icon, }; }); // 屏幕方向 0 竖,1 横 const orientationDirection = computed(() => { return ["hulusi-flute", "piccolo", "baroque-recorder"].includes(data.subject) ? 1 : 0; }); const resultImg = (note: any) => { if (data.realKey === note.realKey && !playStatus.action) { return { icon: icons.icon_btn_ylow, status: false, }; } else if (playAction.exampleAnser.realKey === note.realKey) { return { icon: icons.icon_btn_ylow, status: false, }; } else if (playAction.standardAnswer.realKey === note.realKey) { // 没有开始答题 if (!playStatus.action) { return { icon: icons.icon_btn_ylow, status: false, }; } // 显示答案中 if (playAction.showAnswerLoading) { return { icon: icons.icon_btn_green, status: true, }; } // 用户答对 if (playAction.userAnswerStatus === 1) { return { icon: icons.icon_btn_green, status: true, }; } } else { // 用户答错 if (playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey) { return { icon: icons.icon_btn_red, status: true, }; } } return { icon: icons.icon_btn_blue, status: true, }; }; const userTabActive=ref<"1"|"2">("1") const userTabs=[ { name:"音阶", value:"1" }, { name:"功能", value:"2" } ] // 切换乐器弹窗 let changeSubjectShowBoxDragData: any; let changeSubjectShowBoxClass: string; if (query.platform==="pc") { changeSubjectShowBoxClass = 'changeSubjectShowBoxClass_drag'; changeSubjectShowBoxDragData = useDrag( [`${changeSubjectShowBoxClass} .dragTopBox`, `${changeSubjectShowBoxClass} .dragbomBox`], changeSubjectShowBoxClass, toRef(data, 'changeSubjectShow'), storeData.user.id as string ); } return () => { const relationship = fingerData.subject?.relationship?.[data.realKey] || []; const rs: number[] = Array.isArray(relationship[1]) ? relationship[fingerData.relationshipIndex] : relationship; const canTizhi = Array.isArray(relationship[1]); return (
{ if (data.linkSource === "class") { window.parent.postMessage( { api: "clickViewFigner", }, "*" ); } }} > {/* 老师端过来隐藏 */} { query.platform!=='pc'&&(
{ e.stopPropagation(); // // 播放音阶时不能切换 if (playStatus.gamut) { return; } // 开始答题不能切换 if (playAction.listenLock) { return; } data.changeSubjectShow = true; }} > 切换乐器
{modeText.value.text}
{/* */}
{/* */}
) }
{!data.loadingImg && } {rs.map((key: number | string, index: number) => { const nk: string = typeof key === "string" ? key.replace("active-", "") : String(key); return ; })}
(fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0)}> 替指
(fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0)}>
{/* 老师端过来隐藏 */} { query.platform==='pc'?(
{ userTabs.map(item=>{ return { item.value==="1"?(<>
{playAction.listenTipsStatus &&
} {playAction.userAnswerStatus === 1 &&
} {playAction.userAnswerStatus === 2 &&
} {playAction.resetAction &&
}
{modeText.value.text}
{ e.stopPropagation(); }} > {((data.noteType !== "#c" && (orientationDirection.value === 0 || (orientationDirection.value === 1 && state.platform === IPlatform.PC))) || (orientationDirection.value === 1 && state.platform === IPlatform.APP)) && ( )} {/* 判断是否为音阶模式 */} {data.fingeringMode !== "scaleMode" && (
)} {/* [styles.noteContent, browsInfo.ios ? "" : styles.noteContentWrap, data.huaweiPad && styles.huaweiPad] */}
{data.notes.map((note: IFIGNER_INSTRUMENT_Note, index: number) => { const steps = new Array(Math.abs(note.step)).fill(1); return (
{ // 判断是否在播放音阶 if (playStatus.gamut) return; if (playAction.listenLock) return; if (playAction.showAnswerLoading) return; if (playStatus.action) { playAction.userAnswer = note; // 判断用户答题 const userResult = note.realKey === playAction.standardAnswer.realKey ? 1 : 2; playAction.userAnswerStatus = userResult; playAction.listenLock = true; data.realKey = note.realKey; await fingeringPlay(note, 1000); resetMode(userResult === 1 ? true : false, 0); data.realKey = 0; // 如果是指法模式显示完之后要还原 if (data.fingeringMode === "fingeringMode" && userResult === 2) { // 延迟显示,因为重置的时候有一个异步操作 setTimeout(() => { data.realKey = playAction.standardAnswer.realKey; }, 10); } playAction.listenLock = false; } else { noteClick(note); } }} > {playStatus.action && ((playAction.showAnswerLoading && playAction.standardAnswer.realKey === note.realKey) || (playAction.userAnswerStatus === 1 && playAction.userAnswer.realKey === note.realKey)) ? : ""} {playStatus.action && playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey ? : ""}
{/* 显示对应的点 */} {note.step > 0 ? steps.map((n: any) => ) : null}
{note.mark && (note.mark === "rise" ? "#" : "b")} {note.key}
{/* 显示对应的点 */} {note.step < 0 ? steps.map((n: any) => ) : null}
); })}
{((data.noteType !== "#c" && (orientationDirection.value === 0 || (orientationDirection.value === 1 && state.platform === IPlatform.PC))) || (orientationDirection.value === 1 && state.platform === IPlatform.APP)) && ( )}
{data.fingeringMode !== "scaleMode" && (
{ e.stopPropagation(); }} >
)} ):(<>
{ e.stopPropagation(); // // 播放音阶时不能切换 if (playStatus.gamut) { return; } // 开始答题不能切换 if (playAction.listenLock) { return; } data.changeSubjectShow = true; }} > 切换乐器
{data.subject !== "melodica" && data.fingeringMode === "scaleMode" && (
{ data.viewIndex++; if (data.viewIndex > data.viewTotal) { if (["pan-flute", "ocarina", "whistling"].includes(data.subject)) { data.viewIndex = 1; } else { data.viewIndex = 0; } } getFingeringData(); }} > 视图
)}
{ resetElement(); data.tipShow = !data.tipShow; }} > 说明
{!!data.tones.length && data.fingeringMode === "scaleMode" && ( <> {fingerData.fingeringInfo.name == "hulusi-flute" ? (
(data.tnoteShow = true)}>
全按作
{data.activeTone.step > 0 ? : null}
{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")} {data.activeTone.key}
{data.activeTone.step < 0 ? : null}
) : (
(data.tnoteShow = true)}>
{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")} {data.activeTone.name}
)} )} { instrumentTranstion.value &&
resetElement()}> 还原
}
) }
}) }
): ( <>
{playAction.listenTipsStatus &&
} {playAction.userAnswerStatus === 1 &&
} {playAction.userAnswerStatus === 2 &&
} {playAction.resetAction &&
} {((data.noteType !== "#c" && (orientationDirection.value === 0 || (orientationDirection.value === 1 && state.platform === IPlatform.PC))) || (orientationDirection.value === 1 && state.platform === IPlatform.APP)) && ( )}
{ e.stopPropagation(); }} > {/* 判断是否为音阶模式 */} {data.fingeringMode !== "scaleMode" && (
)} {/* [styles.noteContent, browsInfo.ios ? "" : styles.noteContentWrap, data.huaweiPad && styles.huaweiPad] */}
{data.notes.map((note: IFIGNER_INSTRUMENT_Note, index: number) => { const steps = new Array(Math.abs(note.step)).fill(1); return (
{ // 判断是否在播放音阶 if (playStatus.gamut) return; if (playAction.listenLock) return; if (playAction.showAnswerLoading) return; if (playStatus.action) { playAction.userAnswer = note; // 判断用户答题 const userResult = note.realKey === playAction.standardAnswer.realKey ? 1 : 2; playAction.userAnswerStatus = userResult; playAction.listenLock = true; data.realKey = note.realKey; await fingeringPlay(note, 1000); resetMode(userResult === 1 ? true : false, 0); data.realKey = 0; // 如果是指法模式显示完之后要还原 if (data.fingeringMode === "fingeringMode" && userResult === 2) { // 延迟显示,因为重置的时候有一个异步操作 setTimeout(() => { data.realKey = playAction.standardAnswer.realKey; }, 10); } playAction.listenLock = false; } else { noteClick(note); } }} > {playStatus.action && ((playAction.showAnswerLoading && playAction.standardAnswer.realKey === note.realKey) || (playAction.userAnswerStatus === 1 && playAction.userAnswer.realKey === note.realKey)) ? : ""} {playStatus.action && playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey ? : ""}
{/* 显示对应的点 */} {note.step > 0 ? steps.map((n: any) => ) : null}
{note.mark && (note.mark === "rise" ? "#" : "b")} {note.key}
{/* 显示对应的点 */} {note.step < 0 ? steps.map((n: any) => ) : null}
); })}
{((data.noteType !== "#c" && (orientationDirection.value === 0 || (orientationDirection.value === 1 && state.platform === IPlatform.PC))) || (orientationDirection.value === 1 && state.platform === IPlatform.APP)) && ( )}
{data.fingeringMode !== "scaleMode" && (
{ e.stopPropagation(); }} >
)} ) }
{/* 老师端过来隐藏 */} { query.platform!=='pc'&&(
{ e.stopPropagation(); }} >
{data.subject !== "melodica" && data.fingeringMode === "scaleMode" && (
{ data.viewIndex++; if (data.viewIndex > data.viewTotal) { if (["pan-flute", "ocarina", "whistling"].includes(data.subject)) { data.viewIndex = 1; } else { data.viewIndex = 0; } } getFingeringData(); }} > 视图
)}
{ resetElement(); data.tipShow = !data.tipShow; }} > 说明
{!!data.tones.length && data.fingeringMode === "scaleMode" && ( <> {fingerData.fingeringInfo.name == "hulusi-flute" ? (
(data.tnoteShow = true)}>
全按作
{data.activeTone.step > 0 ? : null}
{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")} {data.activeTone.key}
{data.activeTone.step < 0 ? : null}
) : (
(data.tnoteShow = true)}>
{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")} {data.activeTone.name}
)} )}
resetElement()}> 还原
) } {/* 老师端加上遮罩点击关闭 */} { query.platform==='pc'&&data.tipShow&&(
{data.tipShow=false}}>
) }
{fingerData.fingeringInfo.code}使用说明
{data.tips.map((tip, tipIndex) => (
{tipIndex + 1}
{tip.name}: {tip.realName}
))}
{data.loadingSoundFonts && (
加载中,请稍后…
)}
移调
{data.tones.map((tone: IFIGNER_INSTRUMENT_Note) => { const steps = new Array(Math.abs(tone.step)).fill(1); return ( ); })}
{ e.stopPropagation(); data.tnoteShow = false; }} src={icons.icon_action_cancel} /> { e.stopPropagation(); data.activeTone = data.popupActiveTone; setNotes(); data.tnoteShow = false; }} src={icons.icon_action_confirm} />
{ e.stopPropagation(); }} > (data.changeSubjectShow = false)} onConfirm={(code: any) => { if (data.subject === code) { data.changeSubjectShow = false; return; } const originalSubject = JSON.parse(JSON.stringify(data.subject)); data.subject = code; data.viewIndex = 0; data.tipShow = false; data.loadingDom = true; fingerData.fingeringInfo = subjectFingering(data.subject); data.activeTone = {} as any; resetElement(); resetMode(true, 0); // api_setRequestedOrientation(orientationDirection.value); data.changeSubjectShow = false; // 设置屏幕方向 setTimeout(() => { const before = ["hulusi-flute", "piccolo", "baroque-recorder"].includes(originalSubject) ? 0 : 0; if (orientationDirection.value !== before) { data.paddingTop = ""; data.paddingLeft = ""; } __init(); }, 100); }} /> {query.platform==="pc" && <>
}
{props.show && !data.loading && !data.loadingSoundFonts && }
); }; }, });