Ver Fonte

老师端活动评测

skyblued há 2 anos atrás
pai
commit
cbde7cf684

+ 9 - 0
src/router/routes-teacher.ts

@@ -272,6 +272,15 @@ export default [
         meta: {
           title: '曲目评测活动'
         }
+      },
+      {
+        path: '/leaderboard',
+        component: () =>
+          import('@/teacher/leaderboard/index'),
+        meta: {
+          title: '曲目挑战排行榜',
+          // isExternal: true // 是否外部浏览器可以打开
+        }
       }
     ]
   },

+ 1 - 0
src/student/leaderboard/index.module.less

@@ -37,6 +37,7 @@
   padding: 12px;
   border-radius: 12px;
   background-color: #fff;
+  min-height: 90%;
 }
 .item {
   display: flex;

BIN
src/teacher/leaderboard/image/icon-emtry.png


BIN
src/teacher/leaderboard/image/icon-trophy.png


+ 93 - 0
src/teacher/leaderboard/index.module.less

@@ -0,0 +1,93 @@
+.headImg {
+  display: flex;
+}
+.tabs {
+  margin-top: -42px;
+  :global {
+    .van-tabs__wrap {
+      height: 42px;
+    }
+    .van-tabs__nav {
+      background-color: rgba(0, 0, 0, 0.68);
+      backdrop-filter: blur(10px);
+      -webkit-backdrop-filter: blur(10px);
+    }
+    .van-tabs__line {
+      background-color: transparent !important;
+      height: 0;
+      width: 0;
+      border: 8px solid transparent;
+      border-bottom-color: #fff;
+      border-radius: 0;
+    }
+    .van-empty__image {
+      width: 100px;
+      height: 114px;
+    }
+  }
+}
+.tabContent {
+  position: relative;
+  padding: 12px;
+  box-sizing: border-box;
+  overflow-y: auto;
+}
+.itemContent {
+  padding: 12px;
+  border-radius: 12px;
+  background-color: #fff;
+  min-height: 90%;
+}
+.item {
+  display: flex;
+  padding: 10px 0;
+  box-sizing: border-box;
+  align-items: center;
+  .left {
+    width: 32px;
+    margin: 0 21px 0 2px;
+    text-align: center;
+  }
+  .center {
+    display: flex;
+  }
+  .right {
+    margin-left: auto;
+    text-align: right;
+    .fraction {
+      font-size: 14px;
+      font-weight: 600;
+      color: #fa6400;
+    }
+    .time {
+      font-size: 12px;
+      color: #999;
+    }
+  }
+  &:first-child {
+    padding-top: 0;
+    border-bottom: 1px solid #eee;
+  }
+  &:last-child {
+    padding-bottom: 0;
+  }
+  .user {
+    margin-left: 6px;
+    .name {
+      font-size: 14px;
+      color: #333;
+      margin-bottom: 2px;
+    }
+    .tag {
+      display: flex;
+      & > span {
+        font-size: 12px;
+        background-color: #ffe2b2;
+        color: #ff8c00;
+        border-radius: 2px;
+        margin-right: 4px;
+        padding: 1px 2px;
+      }
+    }
+  }
+}

+ 194 - 0
src/teacher/leaderboard/index.tsx

@@ -0,0 +1,194 @@
+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'
+
+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[]
+    })
+    const getMusicList = async () => {
+      try {
+        const {
+          data: { activityMusicVoList, shareUrl,subjectUrl }
+        } = await request.post(
+          `/api-student/open/activity/info/${route.query.id}`
+        )
+        if (Array.isArray(activityMusicVoList)) {
+          state.musicList = activityMusicVoList.map(n => {
+            n.rankingList = []
+            n.loaded = false
+            return n
+          })
+        }
+        img.value = subjectUrl
+      } catch (error) {}
+    }
+    const getData = async () => {
+      if (state.musicList[state.tabIndex].loaded) return
+      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
+          state.musicList[state.tabIndex].loaded = true
+        }
+      } 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()
+    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(() => {
+                  imgShow.value = true
+                  imgHeight.value = imgRef.value?.offsetHeight || 100
+                })
+              }}
+              onError={(err) => {
+                console.log(err)
+              }}
+            />
+          </div>
+          {imgShow.value && (
+            <Tabs
+              v-model:active={state.tabIndex}
+              class={styles.tabs}
+              animated
+              swipeable
+              titleInactiveColor="#fff"
+              titleActiveColor="rgba(224,146,144,1)"
+              onChange={index => getData()}
+            >
+              {state.musicList.map((item: IMusicItem) => {
+                return (
+                  <Tab title={item.musicSheetName}>
+                    <div
+                      class={styles.tabContent}
+                      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="34px"
+                                  height="34px"
+                                  fit="cover"
+                                  round
+                                  src={n.userAvatar || IconAvator}
+                                />
+                                <div class={styles.user}>
+                                  <div class={styles.name}>{n.username}</div>
+                                  <div class={styles.tag}>
+                                    <span>{n.userSubject}</span>
+                                  </div>
+                                </div>
+                              </div>
+                              <div class={styles.right}>
+                                <div class={styles.fraction}>{n.score}分</div>
+                                <div class={styles.time}>{n.joinDate}</div>
+                              </div>
+                            </div>
+                          )
+                        })}
+
+                        {!item.rankingList.length && (
+                          <Empty
+                            image={IconEmtry}
+                            description="该曲目暂无排名喔~"
+                          />
+                        )}
+                      </div>
+                    </div>
+                  </Tab>
+                )
+              })}
+            </Tabs>
+          )}
+        </div>
+      </div>
+    )
+  }
+})

BIN
src/teacher/share-page/track-review-activity/images/icon-lv.png


+ 4 - 2
src/teacher/share-page/track-review-activity/index.tsx

@@ -155,8 +155,10 @@ export default defineComponent({
               </span>
 
               <span class={styles.titleTips}>
-                共{this.activityMusic.length || 0}
-                首曲目
+                查看挑战排行榜
+                <img style={{width: '16px', marginLeft: '4px'}} src={getAssetsHomeFile('icon-lv.png')} />
+                {/* 共{this.activityMusic.length || 0}
+                首曲目 */}
               </span>
             </h2>