Просмотр исходного кода

不登录时可以进入给游客准备的奖品列表页

任一存 1 год назад
Родитель
Сommit
085eab15c9
4 измененных файлов с 297 добавлено и 8 удалено
  1. 1 4
      game/src/api.js
  2. 6 0
      game/src/router/index.js
  3. 13 4
      game/src/views/HomeView.vue
  4. 277 0
      game/src/views/ShopForVisitor.vue

+ 1 - 4
game/src/api.js

@@ -243,14 +243,11 @@ updateTime: "2024-01-09 09:35:10"
 export async function getPrizeList(pageNum, pageSize) {
   const res = await axios({
     method: 'post',
-    url: `${process.env.VUE_APP_DEPLOY_ORIGIN}/api/cms/game/prize/pageList`,
+    url: `${process.env.VUE_APP_DEPLOY_ORIGIN}/api/show/prize/pageList`,
     data: {
       pageNum,
       pageSize,
     },
-    headers: {
-      token: store.state.token,
-    }
   })
   if (res.data.code !== 0) {
     throw (`获取奖品列表失败:${res.data.msg}`)

+ 6 - 0
game/src/router/index.js

@@ -11,6 +11,7 @@ import ExamPaper3 from '../views/ExamPaper3.vue'
 import PairUp from '../views/PairUp.vue'
 import GameByUnity from '../views/GameByUnity.vue'
 import ShopView from '../views/ShopView.vue'
+import ShopForVisitor from '../views/ShopForVisitor.vue'
 import RedeemForm from '../views/RedeemForm.vue'
 // import store from '@/store/index.js'
 
@@ -76,6 +77,11 @@ const routes = [
     component: ShopView,
   },
   {
+    path: '/shop-for-visitor',
+    name: 'ShopForVisitor',
+    component: ShopForVisitor,
+  },
+  {
     path: '/redeem-form',
     name: 'RedeemForm',
     component: RedeemForm,

+ 13 - 4
game/src/views/HomeView.vue

@@ -172,11 +172,8 @@
     <!-- 悬浮按钮 -->
     <div class="floating-btn-group">
       <button
-        v-if="store.state.loginStatus"
         class="redeem"
-        @click="router.push({
-          name: 'ShopView'
-        })"
+        @click="onClickRedeem"
       >
         <img
           class=""
@@ -299,6 +296,18 @@ function onClickLogout() {
   logout()
 }
 
+function onClickRedeem() {
+  if (loginStatus.value) {
+    router.push({
+      name: 'ShopView'
+    })
+  } else {
+    router.push({
+      name: 'ShopForVisitor'
+    })
+  }
+}
+
 const shareText = location.href
 const clipboard = new ClipboardJS('button.share')
 clipboard.on('success', function(e) {

+ 277 - 0
game/src/views/ShopForVisitor.vue

@@ -0,0 +1,277 @@
+<template>
+  <div class="shop-view">
+    <img
+      class="banner"
+      src="@/assets/images/redeem-banner.png"
+      alt=""
+      draggable="false"
+    >
+    <button
+      class="return"
+      @click="router.go(-1)"
+    />
+    <div class="main-wrap">
+      <div
+        v-if="prizeList && prizeList.length"
+        ref="prizeListRef"
+        class="prize-list"
+        @scroll="onPrizeListScroll"
+      >
+        <article
+          v-for="prizeItem in prizeList"
+          :key="prizeItem.id"
+          class="prize-item"
+          :class="{
+            disabled: prizeItem.stock === 0
+          }"
+          @click="onClickPrizeItem(prizeItem)"
+        >
+          <img
+            class="thumb"
+            :src="prizeItem.thumb"
+            alt=""
+            draggable="false"
+          >
+          <div class="title">
+            {{ prizeItem.name }}
+          </div>
+          <div class="remaining">
+            剩余:{{ prizeItem.stock }}
+          </div>
+          <div class="price">
+            <span class="number">{{ prizeItem.score }}</span>
+            <span class="not-number">积分</span>
+          </div>
+          <img
+            v-show="prizeItem.isEnabled && prizeItem.stock > 0"
+            class="icon-enabled"
+            src="@/assets/images/icon-gift.png"
+            alt=""
+            draggable="false"
+          >
+          <img
+            v-show="prizeItem.isEnabled && prizeItem.stock === 0"
+            class="icon-no-stock"
+            src="@/assets/images/no-stock.png"
+            alt=""
+            draggable="false"
+          >
+        </article>
+      </div>
+      <div
+        v-if="prizeList?.length === 0"
+        class="prize-list"
+      >
+        <img
+          class="no-data"
+          src="@/assets/images/no-prize.png"
+          alt=""
+          draggable="false"
+        >
+        <p class="no-data">
+          礼物准备中
+        </p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, watch, onMounted } from "vue"
+import { useRoute, useRouter } from "vue-router"
+import { useStore } from "vuex"
+import { getScore, getPrizeList, getBonusPointRecord } from '@/api.js'
+
+const route = useRoute()
+const router = useRouter()
+const store = useStore()
+
+const {
+  windowSizeInCssForRef,
+  windowSizeWhenDesignForRef,
+} = useSizeAdapt(390, 752)
+
+/**
+ * 奖品列表
+ */
+const prizeListRef = ref(null)
+const prizeList = ref(null)
+const isFetchingMorePrize = ref(false)
+const haveGotAllPrize = ref(false)
+
+function fetchMorePrizeData() {
+  if (haveGotAllPrize.value) {
+    return
+  }
+  if (isFetchingMorePrize.value) {
+    return
+  }
+  isFetchingMorePrize.value = true
+  getPrizeList(prizeList.value?.length / 10 + 1 || 0, 10).then((res) => {
+    if (prizeList.value) {
+      prizeList.value = prizeList.value.concat(res.records)
+    } else {
+      prizeList.value = res.records
+    }
+    console.log(prizeList.value.length, res.total)
+    if (prizeList.value.length >= res.total) {
+      haveGotAllPrize.value = true
+    }
+  }).finally(() => {
+    isFetchingMorePrize.value = false
+  })
+}
+
+fetchMorePrizeData()
+
+function onPrizeListScroll(e) {
+  console.log(prizeListRef.value.scrollHeight)
+  console.log(prizeListRef.value.scrollTop + prizeListRef.value.clientHeight)
+  if (Math.abs(prizeListRef.value.scrollTop + prizeListRef.value.clientHeight - prizeListRef.value.scrollHeight) < 10) {
+    fetchMorePrizeData()
+  }
+}
+
+function onClickPrizeItem(prizeItem) {
+  router.push({
+    name: 'LoginView',
+  })
+}
+
+</script>
+
+<style lang="less" scoped>
+.shop-view{
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  >img.banner{
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+  }
+  >button.return {
+    position: absolute;
+    top: calc(12 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    left: calc(24 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    width: calc(24 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(24 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    background-image: url(@/assets/images/icon-return.png);
+    background-size: cover;
+    background-repeat: no-repeat;
+    background-position: center center;
+  }
+  >.main-wrap{
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    width: 100%;
+    height: calc(700 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    background: #F6F6F6;
+    border-radius: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef')) calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef')) 0 0;
+    padding-top: calc(25 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    >div.prize-list{
+      height: calc(674 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      overflow: auto;
+      padding-left: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      position: relative;
+      >article.prize-item{
+        display: inline-block;
+        width: calc(168 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        height: calc(200 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        background: #FFFFFF;
+        border-radius: calc(11 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        padding: calc(15 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef')) calc(12 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        position: relative;
+        margin-right: calc(14 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        margin-bottom: calc(15 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        cursor: pointer;
+        >img.thumb{
+          width: 100%;
+          height: calc(92 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          object-fit: cover;
+        }
+        >.title{
+          margin-top: calc(3 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-family: Source Han Sans SC, Source Han Sans SC;
+          font-weight: 400;
+          color: #414141;
+          line-height: calc(23 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          overflow: hidden;
+          white-space: pre;
+          text-overflow: ellipsis;
+        }
+        >.remaining{
+          margin-top: calc(5 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-size: calc(12 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-family: Source Han Sans SC, Source Han Sans SC;
+          font-weight: 400;
+          color: #414141;
+          opacity: 0.5;
+          line-height: calc(14 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          overflow: hidden;
+          white-space: pre;
+          text-overflow: ellipsis;
+        }
+        >.price{
+          margin-top: calc(3 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          >.number{
+            font-size: calc(24 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            font-family: heiti;
+            font-weight: 800;
+            color: #C5A16C;
+            line-height: calc(28 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          }
+          >.not-number{
+            font-size: calc(12 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            font-family: Source Han Sans SC, Source Han Sans SC;
+            font-weight: 400;
+            color: #C5A16C;
+            line-height: calc(14 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            margin-left: 0.3em;
+          }
+        }
+        >img.icon-enabled{
+          position: absolute;
+          right: calc(12 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          bottom: calc(15 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          width: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          height: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        }
+        >img.icon-no-stock{
+          position: absolute;
+          right: calc(12 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          bottom: calc(7 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          width: calc(64 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          height: calc(64 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        }
+      }
+      >article.prize-item.disabled{
+        pointer-events: none;
+      }
+      >img.no-data{
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        top: calc(120 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        transform: translate(-50%, 0);
+      }
+      >p.no-data{
+        position: absolute;
+        left: 50%;
+        top: calc(265 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        transform: translate(-50%, 0);
+        font-size: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        font-family: Source Han Sans SC, Source Han Sans SC;
+        font-weight: 400;
+        color: #AF9D85;
+        line-height: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      }
+    }
+  }
+}
+</style>