track-song.tsx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import ColHeader from '@/components/col-header'
  2. import { useRect } from '@vant/use'
  3. import { useEventListener, useWindowScroll } from '@vueuse/core'
  4. import { defineComponent } from 'vue'
  5. import { Button, Cell, CellGroup, Image } from 'vant'
  6. import styles from './index.module.less'
  7. import { browser, getRandomKey } from '@/helpers/utils'
  8. import qs from 'query-string'
  9. import request from '@/helpers/request'
  10. import { postMessage } from '@/helpers/native-message'
  11. export const getAssetsHomeFile = (fileName: string) => {
  12. const path = `./images/${fileName}`
  13. const modules = import.meta.globEager('./images/*')
  14. return modules[path].default
  15. }
  16. export default defineComponent({
  17. name: 'track-song',
  18. data() {
  19. const query = this.$route.query
  20. console.log(query)
  21. const subjectName = query.subjectName || ''
  22. return {
  23. id: query.id,
  24. subjectId: query.subjectId,
  25. background: 'rgba(55, 205, 177, 0)',
  26. headColor: '#fff',
  27. height: 'auto' as any,
  28. backIconColor: 'white',
  29. title: subjectName + '曲目评测',
  30. behaviorId: getRandomKey(),
  31. musicList: [] as any,
  32. rankingScore: 0,
  33. hiddenProperty: null as any
  34. }
  35. },
  36. async mounted() {
  37. useEventListener(document, 'scroll', () => {
  38. const { y } = useWindowScroll()
  39. if (y.value > 52) {
  40. this.headColor = '#000'
  41. this.background = '#fff'
  42. this.backIconColor = 'black'
  43. } else {
  44. this.background = 'transparent'
  45. this.headColor = '#fff'
  46. this.backIconColor = 'white'
  47. }
  48. })
  49. await this.getMusicInfo()
  50. this.hiddenProperty =
  51. 'hidden' in document
  52. ? 'hidden'
  53. : 'webkitHidden' in document
  54. ? 'webkitHidden'
  55. : 'mozHidden' in document
  56. ? 'mozHidden'
  57. : null
  58. const visibilityChangeEvent = this.hiddenProperty.replace(
  59. /hidden/i,
  60. 'visibilitychange'
  61. )
  62. document.addEventListener(visibilityChangeEvent, this.onVisibilityChange)
  63. },
  64. unmounted() {
  65. if (this.hiddenProperty) {
  66. const visibilityChangeEvent = this.hiddenProperty.replace(
  67. /hidden/i,
  68. 'visibilitychange'
  69. )
  70. document.removeEventListener(
  71. visibilityChangeEvent,
  72. this.onVisibilityChange
  73. )
  74. }
  75. },
  76. methods: {
  77. onVisibilityChange() {
  78. if (!document[this.hiddenProperty]) {
  79. this.getMusicInfo()
  80. }
  81. },
  82. async getMusicInfo() {
  83. try {
  84. const { data } = await request.post(
  85. '/api-student/open/activity/info/' + this.id
  86. )
  87. const activityMusicVoList = data.activityMusicVoList || []
  88. const musicList = activityMusicVoList.filter(
  89. (activity: any) => activity.subjectId == this.subjectId
  90. )
  91. this.musicList = musicList
  92. this.rankingScore = data.rankingScore || 0
  93. } catch {
  94. //
  95. }
  96. },
  97. onOpenMusic(item: any) {
  98. try {
  99. const browserInfo = browser()
  100. const url = qs.stringifyUrl({
  101. url: location.origin + '/accompany',
  102. query: {
  103. id: item.musicSheetId,
  104. behaviorId: this.behaviorId,
  105. client: browserInfo.isTeacher ? 'teacher' : 'student',
  106. setting: JSON.stringify({
  107. mode: 'EVALUATING',
  108. resets: ['SPEED'],
  109. difficulty: item.evaluationDifficulty,
  110. feeType: 'FREE',
  111. submitData: { evaluationId: item.evaluationId }
  112. })
  113. }
  114. })
  115. postMessage({
  116. api: 'openAccompanyWebView',
  117. content: {
  118. url,
  119. orientation: 0,
  120. isHideTitle: true,
  121. statusBarTextColor: false,
  122. isOpenLight: true
  123. }
  124. })
  125. } catch {
  126. //
  127. }
  128. }
  129. },
  130. computed: {
  131. allScore() {
  132. const musicList = this.musicList || []
  133. let score = 0
  134. musicList.forEach((item: any) => {
  135. score += item.score
  136. })
  137. return score
  138. },
  139. calcScore() {
  140. const allScore = this.allScore as number
  141. const rankingScore = this.rankingScore as number
  142. return Number(rankingScore - allScore)
  143. }
  144. },
  145. render() {
  146. return (
  147. <div class={styles.trackSong}>
  148. <div ref="headers">
  149. <ColHeader
  150. title={this.title}
  151. background={this.background}
  152. border={false}
  153. color={this.headColor}
  154. backIconColor={this.backIconColor as any}
  155. onHeaderBack={() => {
  156. this.$nextTick(() => {
  157. const { height } = useRect((this as any).$refs.headers)
  158. this.height = height
  159. // this.homeContaiterHeight = `calc(100vh - var(--van-tabs-line-height) - ${height}px - 15px)`
  160. })
  161. }}
  162. >
  163. <div class={styles.trackScore}>
  164. <div class={styles.trackCountScore}>
  165. 我的总分 <span>{this.allScore}</span>
  166. </div>
  167. <div class={styles.trackIf}>
  168. 距离要求分数还有{this.calcScore}分,继续加油!
  169. </div>
  170. <Image
  171. class={styles.trackImg}
  172. src={getAssetsHomeFile('icon_score.png')}
  173. />
  174. </div>
  175. </ColHeader>
  176. </div>
  177. <div class={styles.bg}></div>
  178. <CellGroup class={styles.cellGroup}>
  179. {this.musicList.map((item: any) => (
  180. <Cell
  181. center
  182. v-slots={{
  183. icon: () => (
  184. <Image src={item.musicImage} class={styles.musicPic} />
  185. ),
  186. title: () => (
  187. <div class={styles.musicName}>{item.musicSheetName}</div>
  188. ),
  189. label: () =>
  190. item.score ? (
  191. <div class={[styles.labelClass, styles.labelScore]}>
  192. 我的评分:{item.score}
  193. </div>
  194. ) : (
  195. <div class={styles.labelClass}>暂无评分,快来挑战吧~</div>
  196. ),
  197. value: () => (
  198. <div class={styles.valueClass}>
  199. <Button
  200. type="primary"
  201. size="small"
  202. round
  203. color="linear-gradient(180deg, #FFA200 0%, #FF6900 100%)"
  204. onClick={() => {
  205. this.onOpenMusic(item)
  206. }}
  207. >
  208. 立刻挑战
  209. </Button>
  210. </div>
  211. )
  212. }}
  213. />
  214. ))}
  215. </CellGroup>
  216. </div>
  217. )
  218. }
  219. })