123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- import ColSticky from '@/components/col-sticky'
- import request from '@/helpers/request'
- import { browser, removeAuth } from '@/helpers/utils'
- import { postMessage } from '@/helpers/native-message'
- import { Button, Cell, CellGroup, Dialog, Image, Notify, Popup } from 'vant'
- import { defineComponent } from 'vue'
- import styles from './index.module.less'
- import logo from '@/common/images/logo.png'
- import { shareCall } from '@/teacher/share-page/share'
- import { getRandomKey } from '@/views/music/music'
- import qs from 'query-string'
- import dayjs from 'dayjs'
- import { orderStatus } from '@/views/order-detail/orderStatus'
- import { difficulty } from '@/constant'
- import { state } from '@/state'
- export const getAssetsHomeFile = (fileName: string) => {
- const path = `./images/${fileName}`
- const modules = import.meta.globEager('./images/*')
- return modules[path].default
- }
- export default defineComponent({
- name: 'track-review-activity',
- data() {
- const query = this.$route.query
- return {
- id: query.id,
- recomUserId: query.recomUserId || '', // 推荐人id
- activeInfo: {} as any,
- popupStatus: false,
- wxStatus: false,
- behaviorId: getRandomKey(),
- selectMusic: {} as any,
- hiddenProperty: null as any
- }
- },
- computed: {
- activityMusic() {
- const activeInfo: any = this.activeInfo
- return activeInfo.activityMusicVoList || []
- },
- // 用户是否有中选的曲子
- userSelectMusic() {
- let status = false
- this.activityMusic.forEach((item: any) => {
- if (item.join === 1) {
- status = true
- }
- })
- return status
- }
- },
- async mounted() {
- await this.getMusicInfo()
- // 判断是否在内容打开页面
- if (!browser().isApp) {
- // this.popupStatus = true
- // removeAuth()
- // return
- } else if (state.platformType === 'TEACHER') {
- this.onBackDialog('请使用酷乐秀学生端扫码打开')
- return
- } else {
- this.hiddenProperty =
- 'hidden' in document
- ? 'hidden'
- : 'webkitHidden' in document
- ? 'webkitHidden'
- : 'mozHidden' in document
- ? 'mozHidden'
- : null
- const visibilityChangeEvent = this.hiddenProperty.replace(
- /hidden/i,
- 'visibilitychange'
- )
- document.addEventListener(visibilityChangeEvent, this.onVisibilityChange)
- }
- // 判断活动状态的活动时间
- this.checkActivityTime()
- },
- methods: {
- onVisibilityChange() {
- if (!document[this.hiddenProperty]) {
- this.getMusicInfo()
- }
- },
- async getMusicInfo() {
- try {
- const res = await request.post(
- '/api-student/open/activity/info/' + this.id
- )
- this.activeInfo = res.data
- document.title = this.activeInfo.activityName
- } catch {
- //
- }
- },
- checkActivityTime() {
- // 判断活动状态的活动时间
- try {
- const activeInfo = this.activeInfo
- if (activeInfo.activityState !== 1) {
- Dialog.alert({
- message: '活动已结束,感谢你的关注!',
- theme: 'round-button',
- confirmButtonColor: '#2dc7aa'
- })
- this.onBackDialog('活动已结束,感谢你的关注!')
- return false
- }
- const nowTime = dayjs()
- const startTime = dayjs(activeInfo.activityStart)
- const endTime = dayjs(activeInfo.activityEnd)
- if (dayjs(nowTime).isBefore(dayjs(startTime))) {
- this.onBackDialog('活动尚未开始,请您耐心等待!')
- return false
- } else if (!dayjs(nowTime).isBefore(dayjs(endTime))) {
- this.onBackDialog('活动已结束,感谢你的关注!')
- return false
- }
- return true
- } catch {
- //
- }
- },
- onBackDialog(str: string) {
- Dialog.alert({
- message: str,
- theme: 'round-button',
- confirmButtonColor: '#2dc7aa'
- }).then(() => {
- postMessage({ api: 'back' })
- })
- },
- async onJoinActve() {
- if (!browser().isApp) {
- this.popupStatus = true
- removeAuth()
- return
- }
- const activeInfo = this.activeInfo
- try {
- if (!this.checkActivityTime()) {
- return
- }
- if (activeInfo.registrationMethod === 'CHARGE') {
- // 判断是否有待支付订单
- const res = await request.post(
- '/api-student/userOrder/getPendingOrder',
- {
- data: {
- goodType: 'ACTI_REGIST',
- bizId: activeInfo.id
- }
- }
- )
- // 判断是否是收费活动
- orderStatus.orderObject.orderType = 'ACTI_REGIST'
- orderStatus.orderObject.orderName = activeInfo.activityName
- orderStatus.orderObject.orderDesc = activeInfo.activityName
- orderStatus.orderObject.actualPrice = activeInfo.registrationPrice
- orderStatus.orderObject.orderNo = res.data?.orderNo || ''
- orderStatus.orderObject.recomUserId = this.recomUserId
- orderStatus.orderObject.orderList = [
- {
- orderType: 'ACTI_REGIST',
- goodsName: activeInfo.activityName,
- activityId: activeInfo.id,
- actualPrice: activeInfo.registrationPrice,
- recomUserId: this.recomUserId
- }
- ]
- this.$router.push({
- path: '/orderDetail',
- query: {
- orderType: 'ACTI_REGIST',
- activityId: activeInfo.id
- }
- })
- } else {
- await request.post(
- `/api-student/activity/joinActivity/${activeInfo.id}`
- )
- // 成功通知
- Notify({ type: 'success', message: '报名成功' })
- this.getMusicInfo()
- }
- } catch {
- //
- }
- },
- async onOpenMusic() {
- try {
- const selectMusic = this.selectMusic
- if (selectMusic.join !== 1) {
- await request.post(
- `/api-student/activity/evaluation/${selectMusic.evaluationId}`
- )
- this.selectMusic.join = 1
- }
- this.popupStatus = false
- const browserInfo = browser()
- const url = qs.stringifyUrl({
- url: location.origin + '/accompany',
- query: {
- id: selectMusic.musicSheetId,
- behaviorId: this.behaviorId,
- client: browserInfo.isTeacher ? 'teacher' : 'student',
- setting: JSON.stringify({
- mode: 'EVALUATING',
- resets: ['SPEED'],
- difficulty: this.activeInfo.evaluationDifficulty,
- feeType: 'FREE',
- submitData: { evaluationId: this.selectMusic.evaluationId }
- })
- }
- })
- postMessage({
- api: 'openAccompanyWebView',
- content: {
- url,
- orientation: 0,
- isHideTitle: true,
- statusBarTextColor: false,
- isOpenLight: true
- }
- })
- } catch {
- //
- }
- },
- onOpenApp() {
- //
- if (!browser().isApp) {
- if (browser().weixin) {
- this.wxStatus = true
- return
- }
- // 如果不在app里面则不需要唤起操作
- const { origin } = location
- const str =
- origin +
- `/student/#/track-review-activity?id=${this.id}&recomUserId=${this.recomUserId}`
- shareCall(str, {})
- // 不管有没有唤起,则跳转到下载页面
- setTimeout(() => {
- window.location.href = location.origin + '/student/#/download'
- }, 3000)
- } else {
- this.popupStatus = false
- }
- }
- },
- render() {
- return (
- <div
- class={styles.review}
- style={{
- background: `url(${this.activeInfo.subjectUrl}) no-repeat top center ${this.activeInfo.backgroundUrl}`,
- backgroundSize: 'contain'
- }}
- >
- <div class={styles.reviewContainer}>
- <div class={[styles.section, styles.activeTime]}>
- <div class={styles.activeBg}>
- <img src={getAssetsHomeFile('icon_time.png')} />
- <p>
- <span>活动时间:</span>
- {dayjs(this.activeInfo.activityStart).format(
- 'YYYY-MM-DD'
- )} ~ {dayjs(this.activeInfo.activityEnd).format('YYYY-MM-DD')}
- </p>
- </div>
- </div>
- <div class={[styles.section]}>
- <div class={styles.title}>
- <img src={getAssetsHomeFile('icon_arrow_left.png')} />
- <span>活动介绍</span>
- <img src={getAssetsHomeFile('icon_arrow_right.png')} />
- </div>
- <div class={styles.tips}>{this.activeInfo.describe}</div>
- </div>
- <div class={[styles.section]}>
- <h2 class={styles.title2}>
- <span>
- <i class={styles.titlePrefix}></i>
- 活动奖品
- </span>
- <img
- src={getAssetsHomeFile('star_bg.png')}
- class={styles.iconStar}
- />
- </h2>
- {this.activeInfo.activityRewardList &&
- this.activeInfo.activityRewardList.map((item: any) => (
- <div class={styles.prize}>
- <Image src={item.imgUrl} />
- <div class={styles.prizeContainer}>
- <div class={styles.prizeName}>{item.rewardName}</div>
- <div class={styles.prizeDesc}>{item.rewardDescribe}</div>
- </div>
- </div>
- ))}
- </div>
- <div class={[styles.section]} style={{ backgroundColor: '#fff' }}>
- <h2 class={styles.title2}>
- <span>
- <i class={styles.titlePrefix}></i>
- 活动曲目
- </span>
- <span class={styles.titleTips}>
- 共{this.activityMusic.length || 0}
- 首曲目
- </span>
- </h2>
- {this.activityMusic.map((item: any) => (
- <CellGroup class={styles.musicItem} border={false}>
- <Cell
- center
- titleClass={styles.musicTitle}
- v-slots={{
- icon: () => (
- <Image
- src={getAssetsHomeFile('icon_music.png')}
- class={styles.iconMusic}
- />
- ),
- title: () => (
- <span class={styles.musicName}>
- {item.musicSheetName}
- </span>
- ),
- value: () => <span>{item.musicSubject}</span>
- }}
- />
- <Cell
- center
- class={styles.cellLevel}
- v-slots={{
- icon: () => (
- <div class={styles.kingSection}>
- <Image
- src={getAssetsHomeFile('icon_king.png')}
- class={styles.iconKing}
- />
- <p class={styles.score}>
- {item.userId ? item.score : '--'}
- <span>分</span>
- </p>
- </div>
- ),
- title: () => (
- <div class={styles.users}>
- <div class={styles.userInfo}>
- <div class={styles.userImg}>
- {item.userId ? (
- <>
- <Image
- src={item.userAvatar}
- class={styles.userLogo}
- fit="cover"
- />
- <img
- src={getAssetsHomeFile('icon_level.png')}
- class={styles.iconLevel}
- />
- </>
- ) : (
- <div class={styles.userLogo}>
- <img
- class={styles.img}
- src={getAssetsHomeFile('icon_no_level.png')}
- />
- </div>
- )}
- </div>
- <div class={styles.userName}>
- {item.userId ? (
- <>
- <p class={styles.name}>{item.username}</p>
- <p>
- <span class={styles.subjectName}>
- {item.userSubject}
- </span>
- </p>{' '}
- </>
- ) : (
- <span class={styles.noText}>虚位以待</span>
- )}
- </div>
- </div>
- <div class={styles.userBtn}>
- <Button
- round
- style={{
- padding: '0 8px',
- height: '32px'
- }}
- color="linear-gradient(180deg, #FFA200 0%, #FF6900 100%)"
- disabled={
- this.activeInfo.join === 0 ||
- (this.userSelectMusic && item.join !== 1)
- }
- onClick={() => {
- if (!this.checkActivityTime()) {
- return
- }
- this.selectMusic = item
- if (item.join === 1) {
- this.onOpenMusic()
- } else {
- this.popupStatus = true
- }
- }}
- >
- 立刻挑战
- </Button>
- </div>
- </div>
- )
- }}
- ></Cell>
- </CellGroup>
- ))}
- </div>
- <div class={[styles.section]}>
- <div class={styles.title}>
- <img src={getAssetsHomeFile('icon_arrow_left.png')} />
- <span>活动规则</span>
- <img src={getAssetsHomeFile('icon_arrow_right.png')} />
- </div>
- <div class={styles.tips}>{this.activeInfo.ruleDescribe}</div>
- </div>
- </div>
- {this.activeInfo.join !== 1 && (
- <ColSticky position="bottom">
- <div class={styles.btnGroup}>
- <Button
- round
- class={styles.submit}
- block
- onClick={this.onJoinActve}
- >
- 报名参与
- </Button>
- </div>
- </ColSticky>
- )}
- <Popup
- v-model:show={this.popupStatus}
- round
- style={{ width: '90%' }}
- closeOnClickOverlay={false}
- >
- <div class={styles.popupContainer}>
- <div class={[styles.popupTitle, 'van-hairline--bottom']}>
- <i class={styles.line}></i>提示
- <img
- src={getAssetsHomeFile('icon_close.png')}
- class={styles.popupClose}
- onClick={()=>this.popupStatus = false}
- />
- </div>
- <div class={styles.popupContent}>
- {browser().isApp ? (
- <>
- <p>
- 确定要参加<span>{this.selectMusic.musicSheetName}</span>评测
- <span>
- {difficulty[this.activeInfo.evaluationDifficulty]}
- </span>
- 的比拼吗?
- </p>
- <p class={styles.popupTips}>
- 每位用户仅可选择一首曲目的一个难度哦!
- </p>
- </>
- ) : (
- <div class={styles.appOut}>
- <img src={logo} />
- <p>请在酷乐秀APP内打开活动链接!</p>
- </div>
- )}
- </div>
- {browser().isApp ? (
- <div class={['btnGroup, btnMore', styles.popupBtn]}>
- <Button
- type="primary"
- round
- plain
- onClick={() => (this.popupStatus = false)}
- >
- 再想想
- </Button>
- <Button type="primary" round onClick={this.onOpenMusic}>
- 就是它了
- </Button>
- </div>
- ) : (
- <div class={['btnGroup, btnMore', styles.popupBtn]}>
- <Button type="primary" round onClick={this.onOpenApp}>
- 确定
- </Button>
- </div>
- )}
- </div>
- </Popup>
- {this.wxStatus && (
- <div
- class={styles.wxpopup}
- onClick={() => {
- this.wxStatus = false
- }}
- >
- <img src={getAssetsHomeFile('wx_bg.png')} alt="" />
- </div>
- )}
- </div>
- )
- }
- })
|