任一存 2 лет назад
Родитель
Сommit
129250761c

+ 46 - 0
game/src/api.js

@@ -211,4 +211,50 @@ export async function getExamQuestionList() {
   } else {
     return res.data.data
   }
+}
+/*
+createTime: "2024-01-08 19:07:01"
+creatorId: 1
+creatorName: ""
+id: 11
+isEnabled: 1
+name: "可乐"
+recordDate: null
+rtf: "<p>可乐</p><p>123</p><p></p><div class=\"media-wrap image-wrap\"><img src=\"https://sit-cnzhengquan.4dage.com/prize/11/img/20240109_0935085055.png\"/></div><p></p>"
+score: 10
+stock: 10
+thumb: "/prize/11/thumb/20240109_0929514233.png"
+updateTime: "2024-01-09 09:35:10"
+*/
+export async function getPrizeList(pageNum, pageSize) {
+  const res = await axios({
+    method: 'post',
+    url: `${process.env.VUE_APP_API_PREFIX}/api/cms/game/prize/pageList`,
+    data: {
+      pageNum,
+      pageSize,
+    },
+    headers: {
+      token: store.state.token,
+    }
+  })
+  if (res.data.code !== 0) {
+    throw (`获取奖品列表失败:${res.data.msg}`)
+  } else {
+    return res.data.data
+  }
+}
+export async function getBonusPointRecord() {
+  const res = await axios({
+    method: 'get',
+    url: `${process.env.VUE_APP_API_PREFIX}/api/cms/game/point/getList`,
+    headers: {
+      token: store.state.token,
+    }
+  })
+  if (res.data.code !== 0) {
+    throw (`获取积分记录失败:${res.data.msg}`)
+  } else {
+    return res.data.data
+  }
 }

BIN
game/src/assets/images/icon-gift.png


BIN
game/src/assets/images/icon-return.png


BIN
game/src/assets/images/no-stock.png


BIN
game/src/assets/images/redeem-banner.png


BIN
game/src/assets/images/tab-item-bottom-line.png


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

@@ -10,6 +10,7 @@ import ExamPaper2 from '../views/ExamPaper2.vue'
 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 store from '@/store/index.js'
 
 const routes = [
@@ -67,6 +68,11 @@ const routes = [
     path: '/game-by-unity',
     name: 'GameByUnity',
     component: GameByUnity,
+  },
+  {
+    path: '/shop-view',
+    name: 'ShopView',
+    component: ShopView,
   }
 ]
 

+ 1 - 1
game/src/views/ExamPaper2.vue

@@ -257,7 +257,7 @@ function onClickNext() {
     currentQuestionIdx.value++
     selectedIdx.value = null
   } else {
-    if (store.state.loginStatus && !store.state.ifScoreLimitReached) {
+    if (store.state.loginStatus && !store.state.ifScoreLimitReached && bonusPoint.value !== 0) {
       addScore(bonusPoint.value).then(() => {
         getScore().then((res) => {
           store.commit('setScore', res.total)

+ 3 - 0
game/src/views/HomeView.vue

@@ -174,6 +174,9 @@
       <button
         v-if="store.state.loginStatus"
         class="redeem"
+        @click="router.push({
+          name: 'ShopView'
+        })"
       >
         <img
           class=""

+ 1 - 1
game/src/views/PairUp.vue

@@ -189,7 +189,7 @@ function replay() {
 
 watch(isOver, (vNew) => {
   if (vNew) {
-    if (store.state.loginStatus && !store.state.ifScoreLimitReached) {
+    if (store.state.loginStatus && !store.state.ifScoreLimitReached && bonusPoint.value !== 0) {
       addScore(bonusPoint.value).then(() => {
         getScore().then((res) => {
           store.commit('setScore', res.total)

+ 1 - 1
game/src/views/PlantTree.vue

@@ -257,7 +257,7 @@ const isOver = computed(() => {
 watch(isOver, (vNew) => {
   if (vNew) {
     localStorage.setItem('plant-tree-last-time', (new Date()).getTime())
-    if (store.state.loginStatus && !store.state.ifScoreLimitReached) {
+    if (store.state.loginStatus && !store.state.ifScoreLimitReached && bonusPoint.value !== 0) {
       addScore(bonusPoint.value).then(() => {
         getScore().then((res) => {
           store.commit('setScore', res.total)

+ 368 - 0
game/src/views/ShopView.vue

@@ -0,0 +1,368 @@
+<template>
+  <div class="shop-view">
+    <!-- todo -->
+    <img
+      class="banner"
+      src="@/assets/images/redeem-banner.png"
+      alt=""
+      draggable="false"
+    >
+    <button
+      class="return"
+      @click="router.go(-1)"
+    />
+    <div class="my-bonus-point-title">
+      我的积分
+    </div>
+    <div class="my-bonus-point-value">
+      {{ store.state.score }}
+    </div>
+    <div class="main-wrap">
+      <div class="tabbar">
+        <button
+          class="redeem"
+          :class="{
+            active: currentTabIdx === 0,
+          }"
+          @click="currentTabIdx = 0"
+        >
+          兑换
+          <div
+            class="bottom-line"
+            :class="{
+              active: currentTabIdx === 0,
+            }"
+          />
+        </button>
+        <button
+          class="record"
+          :class="{
+            active: currentTabIdx === 1,
+          }"
+          @click="currentTabIdx = 1"
+        >
+          记录
+          <div
+            class="bottom-line"
+            :class="{
+              active: currentTabIdx === 1,
+            }"
+          />
+        </button>
+      </div>
+      <div
+        v-if="prizeList.length && currentTabIdx === 0"
+        class="prize-list"
+      >
+        <article
+          v-for="prizeItem in prizeList"
+          :key="prizeItem.id"
+          class="prize-item"
+          :class="{
+            disabled: prizeItem.stock === 0
+          }"
+        >
+          <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="recordList.length && currentTabIdx === 1"
+        class="record-list"
+      >
+        <div
+          v-for="recordItem in recordList"
+          :key="recordItem.id"
+          class="record-item"
+        >
+          <div class="left">
+            <div class="type">
+              {{ recordTypeForShowMap[recordItem.type] ? recordTypeForShowMap[recordItem.type] : recordItem.type }}
+            </div>
+            <div class="time">
+              {{ recordItem.updateTime }}
+            </div>
+          </div>
+          <div class="right">
+            {{ recordItem.score >= 0 ? '+' : '-' }}{{ recordItem.score }}
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, watch, onMounted } from "vue"
+import { useRoute, useRouter } from "vue-router"
+import { useStore } from "vuex"
+import { getPrizeList, getBonusPointRecord } from '@/api.js'
+const route = useRoute()
+const router = useRouter()
+const store = useStore()
+
+const {
+  windowSizeInCssForRef,
+  windowSizeWhenDesignForRef,
+} = useSizeAdapt(390, 752)
+
+const currentTabIdx = ref(0)
+
+const prizeList = ref([])
+getPrizeList(0, 20).then((res) => {
+  prizeList.value = res.records
+  console.log(prizeList.value)
+})
+
+const recordList = ref([])
+getBonusPointRecord().then((res) => {
+  recordList.value = res.reverse()
+})
+
+const recordTypeForShowMap = {
+  'game': '游戏积分',
+  'online': '观看视频',
+  'redeem': '奖品兑换',
+}
+</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;
+  }
+  >.my-bonus-point-title{
+    position: absolute;
+    top: calc(70 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    left: calc(24 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    font-size: calc(14 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    font-family: heiti;
+    font-weight: 400;
+    color: #FFFFFF;
+    line-height: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+  }
+  >.my-bonus-point-value{
+    position: absolute;
+    top: calc(80 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    left: calc(24 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    font-size: calc(40 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    font-family: Source Han Sans SC, Source Han Sans SC;
+    font-weight: 800;
+    color: #FFFFFF;
+    line-height: calc(47 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+  }
+  >.main-wrap{
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    width: 100%;
+    height: calc(598 / 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;
+    >.tabbar{
+      height: calc(60 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      display: flex;
+      justify-content: space-around;
+      align-items: center;
+      margin-bottom: calc(10 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      >button{
+        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'));
+        position: relative;
+        >.bottom-line{
+          position: absolute;
+          top: 100%;
+          left: 50%;
+          transform: translate(-50%, 0);
+          width: calc(33 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          height: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          background-image: url(@/assets/images/tab-item-bottom-line.png);
+          background-size: cover;
+          background-repeat: no-repeat;
+          background-position: center center;
+          display: none;
+        }
+      }
+      >button.active{
+        font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        font-family: Source Han Sans SC, Source Han Sans SC;
+        font-weight: bold;
+        color: #414141;
+        line-height: calc(23 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        >.bottom-line{
+          display: initial;
+        }
+      }
+    }
+    >div.prize-list{
+      height: calc(513 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      overflow: auto;
+      padding-left: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      >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(15 / 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;
+      }
+    }
+    >div.record-list{
+      height: calc(515 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      overflow: auto;
+      padding-left: calc(26 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      padding-right: calc(26 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      >.record-item{
+        width: 100%;
+        margin-bottom: calc(15 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        >.left{
+          >.type{
+            font-size: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            font-family: Source Han Sans SC, Source Han Sans SC;
+            font-weight: 400;
+            color: #414141;
+            line-height: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          }
+          >.time{
+            margin-top: calc(3 / 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;
+            line-height: calc(14 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            opacity: 0.5;
+          }
+        }
+        .right{
+          font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-family: heiti;
+          font-weight: bold;
+          color: #FFCC45;
+          line-height: calc(23 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          letter-spacing: 0.05em;
+        }
+      }
+    }
+  }
+}
+</style>