Jelajahi Sumber

移动端 userinfo 外观

任一存 2 tahun lalu
induk
melakukan
e11f4625ab

+ 2 - 2
public/static/js/main_2020_show.js

@@ -3225,7 +3225,7 @@ window.Modernizr = function (n, e, t) {
         var hotList = $('#hotListWrap')[0]
         hotList.classList.remove('hotListActive')
         $('#hotListContent ul .active').removeClass('active')
-        $('#hotList')[0].classList.remove('active')
+        $('#hotList') && $('#hotList')[0] && $('#hotList')[0].classList.remove('active')
       }
       ,
       n.prototype.onTouchMove = function (e) {
@@ -7476,7 +7476,7 @@ window.Modernizr = function (n, e, t) {
           var hotList = $('#hotListWrap')[0]
           hotList.classList.remove('hotListActive')
           $('#hotListContent ul .active').removeClass('active')
-          $('#hotList')[0].classList.remove('active')
+          $('#hotList') && $('#hotList')[0] && $('#hotList')[0].classList.remove('active')
         })
       }
 

TEMPAT SAMPAH
src/assets/images/avatar.png


TEMPAT SAMPAH
src/assets/images/logout.png


TEMPAT SAMPAH
src/assets/images/rule-desc-mobile.png


TEMPAT SAMPAH
src/assets/images/share.png


TEMPAT SAMPAH
src/assets/images/shrink-to-right.png


+ 21 - 5
src/directives/v-click-outside.js

@@ -12,15 +12,31 @@ export default {
         }
         el.__vueClickOutside__ = documentHandler
         if (binding.modifiers.click) {
-          document.addEventListener('click', documentHandler)
+          document.addEventListener('click', documentHandler, {
+            capture: binding.modifiers.capture
+          })
         }
         if (binding.modifiers.mousedown) {
-          document.addEventListener('mousedown', documentHandler)
+          document.addEventListener('mousedown', documentHandler, {
+            capture: binding.modifiers.capture
+          })
+        }
+        if (binding.modifiers.touchstart) {
+          document.addEventListener('touchstart', documentHandler, {
+            capture: binding.modifiers.capture
+          })
         }
       },
-      unbind(el) {
-        document.removeEventListener('click', el.__vueClickOutside__)
-        document.removeEventListener('mousedown', el.__vueClickOutside__)
+      unbind(el, binding) {
+        document.removeEventListener('click', el.__vueClickOutside__, {
+          capture: binding.modifiers.capture
+        })
+        document.removeEventListener('mousedown', el.__vueClickOutside__, {
+          capture: binding.modifiers.capture
+        })
+        document.removeEventListener('tarchstart', el.__vueClickOutside__, {
+          capture: binding.modifiers.capture
+        })
         delete el.__vueClickOutside__
       }
     })

+ 7 - 1
src/pages/Home.vue

@@ -20,7 +20,11 @@
       class="quiz-menu"
     />
     <UserInfo
-      v-if="loginStatus"
+      v-if="loginStatus && !isMobile"
+      class="user-info"
+    />
+    <UserInfoMobile
+      v-if="loginStatus && isMobile"
       class="user-info"
     />
 
@@ -113,6 +117,7 @@ import vOther from "@/views/gui/other"
 import MiniMapDecorator from "@/views/gui/MiniMapDecorator.vue"
 import QuizMenu from "@/views/gui/QuizMenu.vue"
 import UserInfo from "@/views/gui/UserInfo.vue"
+import UserInfoMobile from "@/views/gui/UserInfoMobile.vue"
 
 export default {
   name: "Home",
@@ -131,6 +136,7 @@ export default {
     MiniMapDecorator,
     QuizMenu,
     UserInfo,
+    UserInfoMobile,
   },
 
   data() {

+ 1 - 0
src/views/gui/UserInfo.vue

@@ -305,6 +305,7 @@ export default {
           height: 100%;
           border-radius: 50%;
           z-index: 1;
+          border: 3px solid #FFFFFF;
         }
         > span {
           position: absolute;

+ 310 - 0
src/views/gui/UserInfoMobile.vue

@@ -0,0 +1,310 @@
+<template>
+  <div class="user-info">
+    <div
+      v-click-outside.touchstart.capture="onTouchOutsideMenu"
+      class="top-wrapper"
+    >
+      <button
+        class="show-menu"
+        @click.stop="onClickAvatar"
+      >
+        <img
+          v-show="!isExpanded"
+          class=""
+          src="@/assets/images/avatar.png"
+          alt=""
+          draggable="false"
+        >
+        <img
+          v-show="isExpanded"
+          class=""
+          src="@/assets/images/shrink-to-right.png"
+          alt=""
+          draggable="false"
+        >
+      </button>
+      <menu
+        ref="menu"
+        :class="isExpanded ? 'my-show' : 'my-hide'"
+      >
+        <button>
+          <img
+            class=""
+            src="@/assets/images/share.png"
+            alt=""
+            draggable="false"
+          >
+          <span>分享成绩</span>
+        </button>
+        <button>
+          <img
+            class=""
+            src="@/assets/images/rule-desc-mobile.png"
+            alt=""
+            draggable="false"
+          >
+          <span>规则说明</span>
+        </button>
+        <button>
+          <img
+            class=""
+            src="@/assets/images/logout.png"
+            alt=""
+            draggable="false"
+          >
+          <span>退出登录</span>
+        </button>
+      </menu>
+    </div>
+    <div
+      class="badge-info-wrapper"
+      @click="onClickBadgeInfo('1')"
+    >
+      <div class="img-wrapper">
+        <img
+          class=""
+          src="@/assets/images/badge-architecture.png"
+          alt=""
+          draggable="false"
+        >
+        <div
+          class="mask"
+          :style="{
+            background: badgeArchBgStyle,
+          }"
+        />
+        <span>{{ badgeArchForShow }}/{{ badgeArchGoal }}</span>
+      </div>
+      <div class="badge-name">
+        营造专家
+      </div>
+    </div>
+    <div
+      class="badge-info-wrapper"
+      @click="onClickBadgeInfo('2')"
+    >
+      <div class="img-wrapper">
+        <img
+          class=""
+          src="@/assets/images/badge-hitstory.png"
+          alt=""
+          draggable="false"
+        >
+        <div
+          class="mask"
+          :style="{
+            background: badgeHistoryBgStyle,
+          }"
+        />
+        <span>{{ badgeHistoryForShow }}/{{ badgeHistoryGoal }}</span>
+      </div>
+      <div class="badge-name">
+        历史达人
+      </div>
+    </div>
+    <div
+      class="badge-info-wrapper"
+      @click="onClickBadgeInfo('3')"
+    >
+      <div class="img-wrapper">
+        <img
+          class=""
+          src="@/assets/images/badge-protector.png"
+          alt=""
+          draggable="false"
+        >
+        <div
+          class="mask"
+          :style="{
+            background: badgeProtectorBgStyle,
+          }"
+        />
+        <span>{{ badgeProtectorForShow }}/{{ badgeProtectorGoal }}</span>
+      </div>
+      <div class="badge-name">
+        护书使者
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      isExpanded: false,
+    }
+  },
+  computed: {
+    ...globalMapState([
+      'userInfo',
+      'badgeArchGoal',
+      'badgeHistoryGoal',
+      'badgeProtectorGoal',
+    ]),
+    ...globalMapGetters([
+      'badgeArchForShow',
+      'badgeHistoryForShow',
+      'badgeProtectorForShow',
+    ]),
+    badgeArchBgStyle() {
+      if (this.badgeArchForShow === this.badgeArchGoal) {
+        return 'transparent'
+      } else if (this.badgeArchForShow === 0) {
+        return 'rgba(0, 0, 0, 0.8)'
+      } else {
+        return `linear-gradient(180deg,rgba(0,0,0,0.8) ${(1 - this.badgeArchForShow / this.badgeArchGoal) * 100 - 10}%, rgba(0,0,0,0) ${(1 - this.badgeArchForShow / this.badgeArchGoal) * 100 + 10}%)`
+      }
+    },
+    badgeHistoryBgStyle() {
+      if (this.badgeHistoryForShow === this.badgeHistoryGoal) {
+        return 'transparent'
+      } else if (this.badgeHistoryForShow === 0) {
+        return 'rgba(0, 0, 0, 0.8)'
+      } else {
+        return `linear-gradient(180deg,rgba(0,0,0,0.8) ${(1 - this.badgeHistoryForShow / this.badgeHistoryGoal) * 100 - 10}%, rgba(0,0,0,0) ${(1 - this.badgeHistoryForShow / this.badgeHistoryGoal) * 100 + 10}%)`
+      }
+    },
+    badgeProtectorBgStyle() {
+      if (this.badgeProtectorForShow === this.badgeProtectorGoal) {
+        return 'transparent'
+      } else if (this.badgeProtectorForShow === 0) {
+        return 'rgba(0, 0, 0, 0.8)'
+      } else {
+        return `linear-gradient(180deg,rgba(0,0,0,0.8) ${(1 - this.badgeProtectorForShow / this.badgeProtectorGoal) * 100 - 10}%, rgba(0,0,0,0) ${(1 - this.badgeProtectorForShow / this.badgeProtectorGoal) * 100 + 10}%)`
+      }
+    }
+  },
+  methods: {
+    onClickAvatar() {
+      this.isExpanded = !this.isExpanded
+    },
+    onClickLogout() {
+      globalApi.logout()
+    },
+    onClickRuleDesc() {
+      this.$router.push({ name: 'RuleDesc' })
+    },
+    onClickShare() {
+      this.$router.push({ name: 'Share' })
+    },
+    onClickBadgeInfo(badgeCode) {
+      this.$router.push({ name: 'QuestionPositionTip', query: { badgeCode } })
+    },
+    onTouchOutsideMenu(e) {
+      this.isExpanded = false
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.user-info {
+  position: fixed;
+  top: 126px;
+  right: 8px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  > .top-wrapper {
+    position: relative;
+    margin-bottom: 11px;
+    width: 40px;
+    height: 40px;
+    > button.show-menu {
+      position: absolute;
+      top: 0;
+      right: 0;
+      width: 40px;
+      height: 40px;
+      z-index: 2;
+      > img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+    > menu {
+      position: absolute;
+      top: 0;
+      right: 0;
+      height: 40px;
+      border-radius: 5px 20px 20px 5px;
+      background: rgba(164, 87, 63, 0.8);
+      display: flex;
+      justify-content: space-evenly;
+      align-items: center;
+      padding-right: 40px;
+      &.my-hide {
+        display: none;
+      }
+      &.my-show {
+        display: flex;
+      }
+      > button {
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-evenly;
+        align-items: center;
+        margin-left: 10px;
+        margin-right: 10px;
+        > img {
+          width: 18px;
+          height: 18px;
+        }
+        > span {
+          font-size: 10px;
+          font-family: Source Han Sans CN-Regular, Source Han Sans CN;
+          font-weight: 400;
+          color: #F3C67C;
+        }
+      }
+    }
+  }
+  > .badge-info-wrapper {
+    margin-bottom: 11px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    > .img-wrapper {
+      width: 40px;
+      height: 40px;
+      position: relative;
+      > img {
+        width: 100%;
+        height: 100%;
+      }
+      > .mask {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        border-radius: 50%;
+        z-index: 1;
+        border: 1px solid #FFFFFF;
+      }
+      > span {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+        font-size: 12px;
+        font-family: Source Han Sans CN-Bold, Source Han Sans CN;
+        font-weight: bold;
+        color: #999;
+        z-index: 2;
+        mix-blend-mode: difference;
+      }
+    }
+    .badge-name {
+      margin-top: 5px;
+      text-align: center;
+      font-size: 12px;
+      font-family: Source Han Sans CN-Regular, Source Han Sans CN;
+      font-weight: 400;
+      color: #fff;
+    }
+  }
+}
+</style>