123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- 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 () => (
- <Teleport to="#colexiu-detail-music-sheet">
- <div class={styles.follow}>
- <Transition name="start" duration={300}>
- {!data.start && (
- <Button
- style={{
- backgroundImage: `url(${iconFollwBtn})`,
- marginLeft: detailState.isSpecialShapedScreen ? `${detailState.notchHeight / 4}px` : '',
- }}
- class={[styles.button, styles.start, styles.followBtn]}
- onClick={() => handleStart()}
- ></Button>
- )}
- </Transition>
- {/* <div class={styles.title}>
- <span>音符频率: {noteFrequency.value.toFixed(2)}</span>
- <span style={{ color: 'red', marginLeft: '10px' }}>拾音频率: {audioFrequency.value.toFixed(2)}</span>
- <span style={{ marginLeft: '10px' }}>拾音长度: {data.list.length}</span>
- </div> */}
- </div>
- </Teleport>
- )
- },
- })
|