index.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. import ColSticky from '@/components/col-sticky'
  2. import request from '@/helpers/request'
  3. import { Button, Cell, CellGroup, Dialog, Image, Popup } from 'vant'
  4. import { defineComponent } from 'vue'
  5. import styles from './index.module.less'
  6. import dayjs from 'dayjs'
  7. import ShareModel from './share-model'
  8. import { postMessage } from '@/helpers/native-message'
  9. import { state } from '@/state'
  10. export const getAssetsHomeFile = (fileName: string) => {
  11. const path = `./images/${fileName}`
  12. const modules = import.meta.globEager('./images/*')
  13. return modules[path].default
  14. }
  15. export default defineComponent({
  16. name: 'track-review-activity',
  17. data() {
  18. const query = this.$route.query
  19. return {
  20. id: query.id,
  21. activeInfo: {} as any,
  22. shareStatus: false,
  23. shareUrl: ''
  24. }
  25. },
  26. computed: {
  27. activityMusic() {
  28. const activeInfo: any = this.activeInfo
  29. return activeInfo.activityMusicVoList || []
  30. },
  31. rewardList() {
  32. const activityRewardList = this.activeInfo.activityRewardList
  33. console.log(activityRewardList)
  34. let list = activityRewardList || []
  35. if (activityRewardList && activityRewardList.length > 0) {
  36. const last = activityRewardList.sort((a: any, b: any) => {
  37. return Number(a.group) < Number(b.group) ? -1 : 1
  38. })
  39. list = this.groupBy(last, (item: any) => {
  40. return [item.group]
  41. })
  42. console.log(list, 'list')
  43. }
  44. return list || []
  45. }
  46. },
  47. async mounted() {
  48. await this.getMusicInfo()
  49. // 判断活动状态的活动时间
  50. this.checkActivityTime()
  51. },
  52. methods: {
  53. groupBy(array: any, f: any) {
  54. const groups = {}
  55. array.forEach(function (o) {
  56. //注意这里必须是forEach 大写
  57. const group = JSON.stringify(f(o))
  58. groups[group] = groups[group] || []
  59. groups[group].push(o)
  60. })
  61. return Object.keys(groups).map(function (group) {
  62. return groups[group]
  63. })
  64. },
  65. async getMusicInfo() {
  66. try {
  67. // 获取活动基本信息
  68. const res = await request.post(
  69. '/api-teacher/open/activity/info/' + this.id
  70. )
  71. this.activeInfo = res.data
  72. document.title = this.activeInfo.activityName
  73. // 设置连接
  74. this.shareUrl = `${location.origin}/student/#/track-review-activity?recomUserId=${state.user.data?.userId}&id=${this.activeInfo.id}`
  75. } catch {
  76. //
  77. }
  78. },
  79. checkActivityTime() {
  80. // 判断活动状态的活动时间
  81. try {
  82. const activeInfo = this.activeInfo
  83. if (activeInfo.activityState !== 1) {
  84. Dialog.alert({
  85. message: '活动已结束,感谢你的关注!',
  86. theme: 'round-button',
  87. confirmButtonColor: '#2dc7aa'
  88. })
  89. this.onBackDialog('活动已结束,感谢你的关注!')
  90. return false
  91. }
  92. const nowTime = dayjs()
  93. const startTime = dayjs(activeInfo.activityStart)
  94. const endTime = dayjs(activeInfo.activityEnd)
  95. if (dayjs(nowTime).isBefore(dayjs(startTime))) {
  96. this.onBackDialog('活动尚未开始,请您耐心等待!')
  97. return false
  98. } else if (!dayjs(nowTime).isBefore(dayjs(endTime))) {
  99. this.onBackDialog('活动已结束,感谢你的关注!')
  100. return false
  101. }
  102. return true
  103. } catch {
  104. //
  105. }
  106. },
  107. onBackDialog(str: string) {
  108. Dialog.alert({
  109. message: str,
  110. theme: 'round-button',
  111. confirmButtonColor: '#2dc7aa'
  112. }).then(() => {
  113. postMessage({ api: 'back' })
  114. })
  115. }
  116. },
  117. render() {
  118. return (
  119. <div
  120. class={styles.review}
  121. style={{
  122. background: `url(${this.activeInfo.subjectUrl}) no-repeat top center ${this.activeInfo.backgroundUrl}`,
  123. backgroundSize: 'contain'
  124. }}
  125. >
  126. <div class={styles.reviewContainer}>
  127. <div class={[styles.section, styles.activeTime]}>
  128. <div class={styles.activeBg}>
  129. <img src={getAssetsHomeFile('icon_time.png')} />
  130. <p>
  131. <span>活动时间:</span>
  132. {dayjs(this.activeInfo.activityStart).format(
  133. 'YYYY-MM-DD'
  134. )} ~ {dayjs(this.activeInfo.activityEnd).format('YYYY-MM-DD')}
  135. </p>
  136. </div>
  137. </div>
  138. <div class={[styles.section]}>
  139. <div class={styles.title}>
  140. <img src={getAssetsHomeFile('icon_arrow_left.png')} />
  141. <span>活动介绍</span>
  142. <img src={getAssetsHomeFile('icon_arrow_right.png')} />
  143. </div>
  144. <div class={styles.tips}>{this.activeInfo.describe}</div>
  145. </div>
  146. <div class={[styles.section]}>
  147. <h2 class={styles.title2}>
  148. <span>
  149. <i class={styles.titlePrefix}></i>
  150. 活动奖品
  151. </span>
  152. {/* <img
  153. src={getAssetsHomeFile('star_bg.png')}
  154. class={styles.iconStar}
  155. /> */}
  156. <span
  157. class={styles.titleTips}
  158. onClick={() =>
  159. this.$router.push({
  160. path: '/leaderboard',
  161. query: { id: this.id }
  162. })
  163. }
  164. >
  165. 查看挑战排行榜
  166. <img
  167. style={{ width: '16px', marginLeft: '4px' }}
  168. src={getAssetsHomeFile('icon-lv.png')}
  169. />
  170. {/* 共{this.activityMusic.length || 0}
  171. 首曲目 */}
  172. </span>
  173. </h2>
  174. {this.rewardList.map((item: any, index: number) => (
  175. <>
  176. <div class={styles.prizeTitle}>
  177. {index === 0 && (
  178. <Image
  179. class={styles.prizeLevel}
  180. src={getAssetsHomeFile('icon_level.png')}
  181. />
  182. )}
  183. {index === 1 && (
  184. <Image
  185. class={styles.prizeLevel}
  186. src={getAssetsHomeFile('icon_level2.png')}
  187. />
  188. )}
  189. {index === 2 && (
  190. <Image
  191. class={styles.prizeLevel}
  192. src={getAssetsHomeFile('icon_level3.png')}
  193. />
  194. )}
  195. 第{++index}名奖品
  196. </div>
  197. <div class={styles.prizeSection}>
  198. {item.map((child: any) => (
  199. <div class={[styles.prize]}>
  200. <Image src={child.imgUrl} />
  201. <div class={styles.prizeContainer}>
  202. <div class={styles.prizeName}>{child.rewardName}</div>
  203. <div class={styles.prizeDesc}>
  204. {child.rewardDescribe}
  205. </div>
  206. </div>
  207. </div>
  208. ))}
  209. </div>
  210. </>
  211. ))}
  212. {/* {this.activeInfo.activityRewardList &&
  213. this.activeInfo.activityRewardList.map((item: any) => (
  214. <div class={styles.prize}>
  215. <Image src={item.imgUrl} />
  216. <div class={styles.prizeContainer}>
  217. <div class={styles.prizeName}>{item.rewardName}</div>
  218. <div class={styles.prizeDesc}>{item.rewardDescribe}</div>
  219. </div>
  220. </div>
  221. ))} */}
  222. </div>
  223. <div class={[styles.section]} style={{ backgroundColor: '#fff' }}>
  224. <h2 class={styles.title2}>
  225. <span>
  226. <i class={styles.titlePrefix}></i>
  227. 活动曲目
  228. </span>
  229. <span
  230. class={styles.titleTips}
  231. // onClick={() =>
  232. // this.$router.push({
  233. // path: '/leaderboard',
  234. // query: { id: this.id }
  235. // })
  236. // }
  237. >
  238. {/* 查看挑战排行榜
  239. <img
  240. style={{ width: '16px', marginLeft: '4px' }}
  241. src={getAssetsHomeFile('icon-lv.png')}
  242. /> */}
  243. 共{this.activityMusic.length || 0}首曲目
  244. </span>
  245. </h2>
  246. {this.activityMusic.map((item: any) => (
  247. <CellGroup class={styles.musicItem} border={false}>
  248. <Cell
  249. center
  250. titleClass={styles.musicTitle}
  251. v-slots={{
  252. icon: () => (
  253. <Image
  254. src={getAssetsHomeFile('icon_music.png')}
  255. class={styles.iconMusic}
  256. />
  257. ),
  258. title: () => (
  259. <span class={styles.musicName}>
  260. {item.musicSheetName}
  261. </span>
  262. ),
  263. value: () => <span>{item.musicSubject}</span>
  264. }}
  265. />
  266. <Cell
  267. center
  268. class={styles.cellLevel}
  269. v-slots={{
  270. icon: () => (
  271. <div class={styles.kingSection}>
  272. <Image
  273. src={getAssetsHomeFile('icon_king.png')}
  274. class={styles.iconKing}
  275. />
  276. <p class={styles.score}>
  277. {item.userId ? item.score : '--'}
  278. <span>分</span>
  279. </p>
  280. </div>
  281. ),
  282. title: () => (
  283. <div class={styles.users}>
  284. <div class={styles.userInfo}>
  285. <div class={styles.userImg}>
  286. {item.userId ? (
  287. <>
  288. <Image
  289. src={item.userAvatar}
  290. class={styles.userLogo}
  291. fit="cover"
  292. />
  293. <img
  294. src={getAssetsHomeFile('icon_level.png')}
  295. class={styles.iconLevel}
  296. />
  297. </>
  298. ) : (
  299. <div class={styles.userLogo}>
  300. <img
  301. class={styles.img}
  302. src={getAssetsHomeFile('icon_no_level.png')}
  303. />
  304. </div>
  305. )}
  306. </div>
  307. <div class={styles.userName}>
  308. {item.userId ? (
  309. <>
  310. <p class={styles.name}>{item.username}</p>
  311. <p>
  312. <span class={styles.subjectName}>
  313. {item.userSubject}
  314. </span>
  315. </p>{' '}
  316. </>
  317. ) : (
  318. <span class={styles.noText}>虚位以待</span>
  319. )}
  320. </div>
  321. </div>
  322. <div class={styles.userBtn}>
  323. <Button
  324. round
  325. style={{
  326. padding: '0 8px',
  327. height: '32px'
  328. }}
  329. color="linear-gradient(180deg, #FFA200 0%, #FF6900 100%)"
  330. disabled={
  331. // this.activeInfo.join === 0 ||
  332. // (this.userSelectMusic && item.join !== 1)
  333. true
  334. }
  335. >
  336. 立刻挑战
  337. </Button>
  338. </div>
  339. </div>
  340. )
  341. }}
  342. ></Cell>
  343. </CellGroup>
  344. ))}
  345. </div>
  346. <div class={[styles.section]}>
  347. <div class={styles.title}>
  348. <img src={getAssetsHomeFile('icon_arrow_left.png')} />
  349. <span>活动规则</span>
  350. <img src={getAssetsHomeFile('icon_arrow_right.png')} />
  351. </div>
  352. <div class={styles.tips}>{this.activeInfo.ruleDescribe}</div>
  353. </div>
  354. </div>
  355. <ColSticky position="bottom">
  356. <div class={styles.btnGroup}>
  357. <Button
  358. round
  359. class={styles.submit}
  360. block
  361. onClick={() => {
  362. if (!this.checkActivityTime()) {
  363. return
  364. }
  365. this.shareStatus = true
  366. }}
  367. >
  368. 立即分享
  369. </Button>
  370. </div>
  371. </ColSticky>
  372. <Popup
  373. v-model:show={this.shareStatus}
  374. style={{ background: 'transparent' }}
  375. >
  376. <ShareModel shareUrl={this.shareUrl} activeInfo={this.activeInfo} />
  377. </Popup>
  378. </div>
  379. )
  380. }
  381. })