123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- import { Button, Cell, Empty, Image, Tab, Tabs } from 'vant'
- import {
- computed,
- defineComponent,
- nextTick,
- onMounted,
- reactive,
- ref
- } from 'vue'
- import styles from './index.module.less'
- import IconTrophy from './image/icon-trophy.png'
- import IconEmtry from './image/icon-emtry.png'
- import IconAvator from '@/common/images/icon_teacher.png'
- import request from '@/helpers/request'
- import { useRoute, useRouter } from 'vue-router'
- import { state as userInfo } from '@/state'
- import { useRect } from '@vant/use'
- interface IMusicItem {
- loaded: boolean
- musicSheetName: string
- musicSubject: string
- musicSheetId: number
- evaluationId: number
- rankingList: any
- [_: string]: any
- }
- export default defineComponent({
- name: 'leaderboard',
- setup() {
- const route = useRoute()
- const router = useRouter()
- const state = reactive({
- tabIndex: 0,
- musicList: [] as IMusicItem[],
- isSignup: false, // 是否报名
- isChallenge: false // 是否挑战过
- })
- const getMusicList = async () => {
- try {
- const { data } = await request.post(
- `/api-student/open/activity/info/${route.query.id}`
- )
- if (Array.isArray(data.activityMusicVoList)) {
- state.musicList = data.activityMusicVoList.map(n => {
- n.rankingList = []
- return n
- })
- state.isChallenge = data.activityMusicVoList.filter(n => n.join)
- .length
- ? true
- : false
- }
- img.value = data.subjectUrl
- state.isSignup = data.join ? true : false
- } catch (error) {}
- }
- const getData = async () => {
- try {
- const { data } = await request.get(
- '/api-student/open/activityEvaluationRecord/queryRankingList',
- {
- params: {
- activityPlanId: route.query.id,
- activityEvaluationId:
- state.musicList[state.tabIndex].evaluationId,
- limit: 10
- }
- }
- )
- if (Array.isArray(data.rankingList)) {
- state.musicList[state.tabIndex].rankingList = data.rankingList
- }
- } catch (error) {}
- }
- const img = ref()
- const imgShow = ref(false)
- const imgHeight = ref(100)
- const openActive = () => {
- router.back()
- // router.replace({
- // path: '/track-review-activity',
- // query: {
- // id: route.query.id
- // }
- // })
- }
- onMounted(async () => {
- await getMusicList()
- await getData()
- })
- const user = computed(() => {
- if (!state.musicList[state.tabIndex]) return {} as any
- const userdata = userInfo.user.data
- if (!userdata.userId) return {} as any
- const rank = state.musicList[state.tabIndex]
- const item = rank?.rankingList?.find(n => n.userId == userdata.userId)
- let step = rank?.rankingList?.findIndex(n => n.userId == userdata.userId)
- step = step > -1 ? step + 1 : 0
- return {
- join: rank.join,
- score: rank.score,
- isTop: item ? true : false,
- heardUrl: userdata.heardUrl,
- username: userdata.username,
- userId: userdata.userId,
- step
- }
- })
- const imgRef = ref()
- const userRef = ref()
- return () => (
- <div class={styles.leaderboard}>
- <div class={styles.container}>
- <div class={styles.headImg} ref={imgRef}>
- <Image
- width="100%"
- fit="cover"
- src={img.value}
- onLoad={img => {
- nextTick(() => {
- const { height } = useRect(imgRef)
- imgShow.value = true
- imgHeight.value = height || 100
- })
- }}
- onError={err => {
- console.log(err)
- }}
- />
- </div>
- {imgShow.value && (
- <Tabs
- v-model:active={state.tabIndex}
- class={styles.tabs}
- animated
- swipeable
- titleInactiveColor="rgba(153,152,155,1)"
- titleActiveColor="#fff"
- onChange={index => getData()}
- >
- {state.musicList.map((item: IMusicItem) => {
- return (
- <Tab title={item.musicSheetName}>
- <div
- class={[
- styles.tabContent,
- !state.isSignup || !state.isChallenge || user.value.join
- ? styles.hasUser
- : null
- ]}
- style={{ height: `calc(100vh - ${imgHeight.value}px)` }}
- >
- <div class={styles.itemContent}>
- <div class={styles.item}>
- <div class={styles.left}>排名</div>
- <div class={styles.center}>昵称</div>
- <div class={styles.right}>评分</div>
- </div>
- {item.rankingList.map((n: any, index: number) => {
- const t = (index + 1).toString().padStart(2, '0')
- return (
- <div class={styles.item}>
- <div class={styles.left}>
- {index == 0 ? <Image src={IconTrophy} /> : t}
- </div>
- <div class={styles.center}>
- <Image
- width="38px"
- height="38px"
- fit="cover"
- round
- src={n.userAvatar || IconAvator}
- />
- <div class={styles.user}>
- <div class={styles.userContent}>
- <span class={styles.name}>
- {n.username}
- </span>
- <span class={styles.tag}>
- {n.userSubject}
- </span>
- </div>
- <div class={styles.times}>{n.joinDate}</div>
- </div>
- </div>
- <div class={styles.right}>
- <div class={styles.fraction}>{n.score}分</div>
- <div class={styles.time}>
- 第 {n.times} 次评测
- </div>
- </div>
- </div>
- )
- })}
- {!item.rankingList.length && (
- <Empty
- image={IconEmtry}
- description="该曲目暂无排名喔~"
- />
- )}
- </div>
- <div class="van-safe-area-bottom"></div>
- </div>
- </Tab>
- )
- })}
- </Tabs>
- )}
- {!state.isSignup ? (
- <div
- ref={userRef}
- class={[styles.activeUser, 'van-safe-area-bottom']}
- >
- <Cell
- center
- title={user.value.username}
- label="您尚未报名参赛"
- v-slots={{
- icon: () => (
- <Image
- class={styles.avator}
- fit="cover"
- round
- src={user.value.heardUrl || IconAvator}
- />
- )
- }}
- />
- </div>
- ) : !state.isChallenge ? (
- <div
- ref={userRef}
- class={[styles.activeUser, 'van-safe-area-bottom']}
- >
- <Cell
- center
- title={user.value.username}
- label="您尚未评测哦!"
- v-slots={{
- icon: () => (
- <Image
- class={styles.avator}
- fit="cover"
- round
- src={user.value.heardUrl || IconAvator}
- />
- )
- }}
- />
- </div>
- ) : user.value.join ? (
- <div
- ref={userRef}
- class={[styles.activeUser, 'van-safe-area-bottom']}
- >
- <Cell
- center
- title={user.value.username}
- v-slots={{
- icon: () => (
- <Image
- class={styles.avator}
- fit="cover"
- round
- src={user.value.heardUrl || IconAvator}
- />
- ),
- label: () => {
- if (user.value.isTop) {
- return (
- <div>
- 您的评测已上榜! 当前排名
- <span style={{ color: '#FA6400' }}>
- {' '}
- {user.value.step}
- </span>
- </div>
- )
- } else {
- return <div>您的评测暂未上榜,快去挑战吧!</div>
- }
- },
- value: () => (
- <span class={styles.num}>{user.value.score}分</span>
- )
- }}
- />
- </div>
- ) : null}
- </div>
- </div>
- )
- }
- })
|