import { useToggle } from '@vant/use' import { Button } from 'vant' import { defineComponent, nextTick, onMounted, onUnmounted, reactive, ref, Teleport, Transition, watch } from 'vue' import { useClientType, useOriginSearch } from '../../uses' import styles from './index.module.less' import { IPostMessage, listenerMessage, postMessage, removeListenerMessage } from '/src/helpers/native-message' import request from '/src/helpers/request' import { getPlatform, getRequestHostname } from '/src/helpers/utils' import { setStepIndex } from '/src/pages/detail/helpers' import state, { refreshView, setCurrentTime } from '/src/pages/detail/runtime' import detailState from '/src/pages/detail/state' import iconFollwBtn from './icons/icon-follwBtn.png' import { unitTestData } from '/src/subpages/colexiu/unitTest/index' // 显示或隐藏播放按钮 const togglePlayer = (show: boolean = false) => { let globalPlayer: HTMLElement = document.querySelector('#globalPlayer')! if (globalPlayer) { globalPlayer.style.display = show ? '' : 'none' } } const data = reactive({ list: [] as any, // 频率列表 index: 0, start: false, times: [] as any[], // 音符列表 endIndex: 0, // 如果为选段结束的小节 }) const [isOpen, changeOpen] = useToggle(true) const noteFrequency = ref(0) const audioFrequency = ref(0) const followTime = ref(0) // 切换录音 const openToggleRecord = (open: boolean = true) => { postMessage({ api: 'cloudToggleFollow', content: { state: open ? 'start' : 'end', }, }) // 记录跟练时长 if (open) { followTime.value = Date.now() } else { const playTime = Date.now() - followTime.value if (followTime.value !== 0 && playTime > 0) { followTime.value = 0 // 已有全局记录时长,不用单独记录了 // updatePlayTime(playTime / 1000) } } } const initBehaviorId = '' + new Date().valueOf() /** * 记录时长 */ async function updatePlayTime(time: number) { const search = useOriginSearch() const behaviorId = sessionStorage.getItem('behaviorId') || search.behaviorId || initBehaviorId const prefix = getRequestHostname() const seearchid = useOriginSearch().id as string const id = location.hash.split('?')[0].split('/').pop() || seearchid || '' try { const res = await request.post('/musicPracticeRecord/save', { prefix: prefix, data: { musicSheetId: id, sysMusicScoreId: id, feature: search.feature, playTime: time, deviceType: getPlatform(), behaviorId, }, }) } catch (err) {} } // 清除音符状态 const onClear = () => { detailState.times.forEach((item) => { const note: HTMLElement = document.querySelector(`div[data-vf=vf${item.id}]`)! if (note) { note.classList.remove('follow-error') note.classList.remove('follow-success') // note.classList.add('follow-error') } }) } /** 获取默认开始的音符 */ const getDefaultIndex = () => { if (unitTestData.isSelectMeasureMode) { data.endIndex = detailState.times.findIndex( (n: any) => n.NoteToGraphicalNoteObjectId == detailState.section[1].NoteToGraphicalNoteObjectId ) const index = detailState.times.findIndex( (n: any) => n.NoteToGraphicalNoteObjectId == detailState.section[0].NoteToGraphicalNoteObjectId ) return index > -1 ? index : 0 } return 0 } // 开始 const handleStart = () => { onClear() data.start = true openToggleRecord(true) data.index = getDefaultIndex() data.list = [] setStepIndex(state.osmd, data.index) // state.osmd.cursor.reset() getNoteIndex() refreshView() } // 结束 const handleEnd = () => { data.start = false openToggleRecord(false) data.index = getDefaultIndex() setStepIndex(state.osmd, data.index) // state.osmd.cursor.reset() getNoteIndex() } // 下一个 const next = () => { if (state.osmd.product) { state.osmd.cursor.setPosition(detailState.times[data.index].cursorBox) } else { state.osmd.cursor.next() } refreshView() } // 获取当前音符 const getNoteIndex = (): any => { const item = detailState.times[data.index] if (!item.frequency) { data.index = data.index + 1 next() return getNoteIndex() } noteFrequency.value = item.frequency detailState.fixedKey = item.realKey return { // ...item, id: item.id, min: item.frequency - (item.frequency - item.noteElement.pitch.prevFrequency) * 0.1, max: item.frequency + (item.noteElement.pitch.nextFrequency - item.frequency) * 0.1, } } let checking = false const onFollowTime = (evt?: IPostMessage) => { if (unitTestData.isSelectMeasureMode && data.index >= data.endIndex) { handleEnd() return } const frequency: number = evt?.content?.frequency audioFrequency.value = frequency data.list.push(frequency) checked() } const checked = () => { if (checking) return checking = true const item = getNoteIndex() for (let i = 0; i < data.list.length; i++) { const frequency = data.list[i] if (frequency > item.min && frequency < item.max) { console.log(item.min, frequency, item.max) next() data.index += 1 data.list = data.list.slice(i + 1) setColor(item, true) checking = false return } } setColor(item) checking = false } const setColor = (item: any, isRight = false) => { const note: HTMLElement = document.querySelector(`div[data-vf=vf${item.id}]`)! if (note) { if (isRight) { note.classList.remove('follow-error') note.classList.add('follow-success') } else { note.classList.remove('follow-success') note.classList.add('follow-error') } } } export default defineComponent({ name: 'follow', setup(props, { expose }) { onMounted(() => { togglePlayer() listenerMessage('cloudFollowTime', onFollowTime) }) onUnmounted(() => { removeListenerMessage('cloudFollowTime', onFollowTime) togglePlayer(true) onClear() setStepIndex(state.osmd, 0) }) expose({ data, handleEnd, }) return () => (
{!data.start && ( )} {/*
音符频率: {noteFrequency.value.toFixed(2)} 拾音频率: {audioFrequency.value.toFixed(2)} 拾音长度: {data.list.length}
*/}
) }, })