use-app.ts 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. import { onBeforeUnmount, onMounted, Ref, ref } from 'vue'
  2. import { useClientType, useOriginSearch } from '.'
  3. import request from '/src/helpers/request'
  4. import originRequest from 'umi-request'
  5. import store from 'store'
  6. import runtime, * as RuntimeUtils from '/src/pages/detail/runtime'
  7. import detailState from '/src/pages/detail/state'
  8. import SettingState from '/src/pages/detail/setting-state'
  9. import { listenerMessage, postMessage } from '/src/helpers/native-message'
  10. import audiosInstance from '/src/helpers/multiple-audio'
  11. import { formatXML, onlyVisible, getCustomInfo } from '/src/pages/detail/helpers'
  12. import { MusicSheelDetail, ShaeetStatusType } from '../index.d'
  13. import { browser, getRequestHostname } from '/src/helpers/utils'
  14. import formatId, { getSubjectIdCode } from '../fingering/format-id'
  15. import { evaluatStopPlay } from '../buttons/evaluating'
  16. const search = useOriginSearch()
  17. const skpList = ['Ukulele']
  18. /**
  19. * 获取xml并前置格式化
  20. * @param url xml地址
  21. * @param detail 音乐详情
  22. * @returns Ref<string>
  23. */
  24. export const useXml = async (url: string, detail: MusicSheelDetail) => {
  25. let score = ref<string>('')
  26. try {
  27. const xml = await originRequest(url)
  28. const parseXmlInfo = getCustomInfo(xml)
  29. if (skpList.includes(parseXmlInfo.code)) {
  30. score.value = xml
  31. } else {
  32. score.value = formatXML(parseXmlInfo.parsedXML, {
  33. title: detail.musicSheetName,
  34. })
  35. const partIndex = Number(search['part-index']) || 0
  36. score.value = onlyVisible(score.value, partIndex)
  37. }
  38. } catch (error) {}
  39. return score
  40. }
  41. /**
  42. * 设置音频信息
  43. * @param detail 音乐详情
  44. */
  45. export const useMp3s = async (detail: MusicSheelDetail) => {
  46. const search = useOriginSearch()
  47. const partIndex = ((search['part-index'] as string) || 0) as unknown as number
  48. const activebg = detail.background?.[partIndex]
  49. // 兼容未修改之前
  50. runtime.songs = {
  51. background: encodeURI(detail.audioFileUrl || detail.metronomeUrl || detail.url || ''),
  52. music: encodeURI(activebg?.audioFileUrl || activebg?.metronomeUrl || ''),
  53. // music: '/m1.mp3'
  54. }
  55. // console.log('backgroundUrl', runtime.songs.background)
  56. // console.log('musicUrl', runtime.songs.music)
  57. detailState.isAppPlay = detail.audioType === 'MIDI'
  58. let defaultExtConfigJson = {
  59. skipTick: false,
  60. repeatedBeats: true,
  61. scoreSize: 'middle'
  62. }
  63. let extConfigJson = {}
  64. detailState.activeDetail = {
  65. ...detail,
  66. examSongId: detail.id,
  67. originalSpeed: 90,
  68. isAppPlay: detail.audioType === 'MIDI',
  69. extConfigJson: {
  70. ...defaultExtConfigJson,
  71. },
  72. }
  73. /** 按照后台配置的设置频率 */
  74. SettingState.sett.hertz = detail.aiDefaultFrequency ? parseInt('' + detail.aiDefaultFrequency || '440') || 440 : 440
  75. try {
  76. extConfigJson = JSON.parse(detail?.extConfigJson || '')
  77. } catch (error) {}
  78. detailState.activeDetail.extConfigJson = {
  79. ...detailState.activeDetail.extConfigJson,
  80. ...extConfigJson,
  81. }
  82. const setZoom = detailState.activeDetail.extConfigJson.scoreSize
  83. const zooms = store.get('zooms') || {}
  84. if (setZoom && !zooms['' + detail.id]) {
  85. store.set('zooms', {...zooms, ['' + detail.id]: setZoom})
  86. SettingState.sett.scoreSize = setZoom
  87. }
  88. detailState.needTick = (detail.audioType === 'MP3' && detail.mp3Type === 'MP3') || detail.audioType === 'MIDI'
  89. detailState.skipTick = detailState.activeDetail.extConfigJson.skipTick
  90. detailState.repeatedBeats = detailState.activeDetail.extConfigJson.repeatedBeats
  91. if (!runtime.songs['music']) {
  92. RuntimeUtils.changeMode('background')
  93. }
  94. // console.log({ ...detailState.activeDetail })
  95. if (!runtime.audiosInstance) {
  96. runtime.audiosInstance = new audiosInstance(Object.values(runtime.songs) as string[])
  97. }
  98. }
  99. /**
  100. * 获取异形屏信息
  101. * @returns {Promise<void>}
  102. */
  103. export const useSpecialShapedScreen = () => {
  104. const heightRef = ref<number>(0)
  105. postMessage(
  106. {
  107. api: 'isSpecialShapedScreen',
  108. },
  109. (evt) => {
  110. const height = evt?.content.notchHeight
  111. detailState.notchHeight =
  112. (browser().ios ? height * 2 : height) || (evt?.content.isSpecialShapedScreen && browser().ios ? 100 : 0)
  113. heightRef.value = detailState.notchHeight
  114. detailState.isSpecialShapedScreen = evt?.content.isSpecialShapedScreen
  115. }
  116. )
  117. return [heightRef]
  118. }
  119. /**
  120. * 获取当前曲目信息
  121. * @param id 歌曲id
  122. */
  123. export const useDetail = (id: number | string): [Ref<ShaeetStatusType>, Ref<MusicSheelDetail>] => {
  124. const prefix = getRequestHostname()
  125. const status = ref<ShaeetStatusType>('loading')
  126. const data = ref<MusicSheelDetail>({})
  127. status.value = 'loading'
  128. request
  129. .get(`/musicSheet/detail/${id}`, {
  130. prefix: prefix,
  131. })
  132. .then((res) => {
  133. useMp3s(res.data)
  134. data.value = {
  135. ...res.data,
  136. code: Array.isArray(res?.data?.background) && res.data.background.length ? getSubjectIdCode(res.data.background[0].musicSubject) : ''
  137. }
  138. if (data.value.notation == 0) {
  139. SettingState.sett.type = 'staff'
  140. }
  141. detailState.subjectId = (res.data.musicSubject || '').split(',')[0] || 0
  142. ;(window as any).DYSubjectId = formatId(data.value.code as any)
  143. status.value = 'success'
  144. })
  145. .catch(() => (status.value = 'error'))
  146. return [status, data]
  147. }
  148. /**
  149. * 监听后台切换状态,暂停播放与评测
  150. */
  151. export const useSuspendPlay = () => {
  152. listenerMessage('suspendPlay', () => {
  153. if (detailState.activeTick > -1) {
  154. RuntimeUtils.stopTick()
  155. }
  156. console.log(runtime.playState)
  157. if (runtime.playState === 'play') {
  158. RuntimeUtils.resetPlayStatus()
  159. if (runtime.evaluatingStatus) {
  160. // postMessage(
  161. // {
  162. // api: 'pauseRecording',
  163. // },
  164. // () => {
  165. // detailState.isPauseRecording = true
  166. // }
  167. // )
  168. evaluatStopPlay(false)
  169. }
  170. }
  171. })
  172. }