瀏覽代碼

dashboard

冯诚 3 年之前
父節點
當前提交
384caf9ea4

+ 2 - 1
src/App.vue

@@ -68,7 +68,8 @@ onMounted(getLocation)
     background: $primary-color url(@img/bg-sm.png) no-repeat;
     background-size: contain;
     @include media-breakpoint-up(md) {
-      background: lightblue;
+      background-image: url(@img/bg-lg.jpeg);
+      background-size: cover;
     }
   }
   &.white-down-md {

二進制
src/assets/bg-lg.jpeg


+ 30 - 16
src/components/nav-bar/index.vue

@@ -57,13 +57,15 @@
         v-if="state.userInfo"
         v-show="showMine"
         class="nav-menu nav-dropdown"
-        :class="{ 'is-member': state.userInfo.orders.length }"
       >
         <div class="nav-menu-header">
           <i class="logo"></i>
           <i class="close" @click="showMine = false"></i>
         </div>
-        <div class="nav-menu-body">
+        <div
+          class="nav-menu-body user-panel"
+          :class="{ 'is-member': state.userInfo.orders.length }"
+        >
           <div class="info" @click.stop>
             <div class="p1">
               <p class="name">Hi, {{ state.userInfo.name }}</p>
@@ -88,6 +90,7 @@
                     v-for="(item, index) of state.userInfo.orders"
                     :key="index"
                     class="swiper-slide"
+                    @click="$router.push(`/order/${item.id}`)"
                   >
                     <div class="service">
                       <div class="service-title">
@@ -115,11 +118,13 @@
             </div>
           </div>
           <div class="role">
-            {{
-              state.userInfo.orders.length
-                ? 'Pro  Member >'
-                : 'Ordinary  Member >'
-            }}
+            <router-link to="/dashboard">
+              {{
+                state.userInfo.orders.length
+                  ? 'Pro  Member >'
+                  : 'Ordinary  Member >'
+              }}
+            </router-link>
           </div>
           <ul class="dropdown-list">
             <template v-if="state.userInfo.orders.length">
@@ -472,21 +477,30 @@ async function signOut() {
       width: 100%;
     }
   }
+}
 
+.user-panel {
   .info {
     margin: 20px 36px 24px;
-    // width: 678px;
+    @include media-breakpoint-up(md) {
+      margin: 0 0 24px 0;
+    }
   }
   .p1 {
+    position: relative;
     padding: 48px 0 0 50px;
     height: 202px;
     color: $primary-color;
     background-color: #e9ebf0;
-    background-repeat: no-repeat;
-    background-size: 190px 190px;
-    background-position: 446px 46px;
-    background-image: url(@img/user-lg.png);
     border-radius: 8px 8px 0px 0px;
+    overflow: hidden;
+    &::after {
+      content: '';
+      @include icon('@img/user-lg.png', 190px);
+      position: absolute;
+      top: 46px;
+      right: 42px;
+    }
 
     .name {
       font-size: 48px;
@@ -525,7 +539,7 @@ async function signOut() {
     }
   }
   .p3 {
-    height: 436px;
+    padding-bottom: 32px;
     border-radius: 0 0 8px 8px;
     background: #e9ebf0;
 
@@ -597,15 +611,15 @@ async function signOut() {
     }
   }
 
-  .is-member {
+  &.is-member {
     .p1,
     .role {
       color: #fff;
       background-color: $primary-color;
     }
-    .p1 {
+    .p1::after {
       background-image: url(@img/pro-lg.png);
-      background-position: 446px 64px;
+      top: 64px;
     }
   }
 

+ 1 - 1
src/components/toast/index.ts

@@ -60,7 +60,7 @@ export default function Toast(options: string | ToastOptions) {
   return toast
 }
 
-Toast.loading = (message = '加载中...') =>
+Toast.loading = (message = 'Loading...') =>
   Toast({ message, duration: 0, icon: 'loading' })
 Toast.hide = () => {
   instance?.close()

+ 117 - 0
src/pages/dashboard/index.vue

@@ -0,0 +1,117 @@
+<template>
+  <div v-if="state.userInfo" class="p-dashboard ptc-block">
+    <div
+      class="user-panel ptc-inner-md"
+      :class="{ 'is-member': state.userInfo.orders.length }"
+    >
+      <div class="info">
+        <div class="p1">
+          <p class="name">Hi, {{ state.userInfo.name }}</p>
+          <p class="intro">
+            {{ state.userInfo.orders.length ? 'Pro' : 'Ordinary' }} member
+          </p>
+        </div>
+        <div v-if="!state.userInfo.orders.length" class="p2">
+          <p class="txt">You have not purchased a member</p>
+          <button class="btn" @click="$router.push('/fill-order')">BUY</button>
+        </div>
+        <div v-else class="p3">
+          <div class="txt">
+            $10 off for additional services |
+            <strong class="primary">Buy now ></strong>
+          </div>
+          <div class="swiper">
+            <div class="swiper-wrapper">
+              <div
+                v-for="(item, index) of state.userInfo.orders"
+                :key="index"
+                class="swiper-slide"
+                @click="$router.push(`/order/${item.id}`)"
+              >
+                <div class="service">
+                  <div class="service-title">
+                    <i class="service-icon icon-lite fls0"></i>
+                    <div class="service-type fls0">
+                      {{ item.product_name }}
+                    </div>
+                    <div class="service-period">
+                      {{ item.start_time }} to {{ item.end_time }}
+                    </div>
+                  </div>
+                  <div class="service-model tac">{{ item.phone_info }}</div>
+                  <div class="service-code tac">{{ item.phone_imei }}</div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <ul class="dropdown-list">
+        <template v-if="state.userInfo.orders.length">
+          <li class="dropdown-item i1">
+            <router-link to="/repaire/history">MY REPAIR REQUEST</router-link>
+          </li>
+          <li class="dropdown-item i2">
+            <router-link to="/order">MY ORDER</router-link>
+          </li>
+        </template>
+        <li class="dropdown-item i3">
+          <router-link to="/gift-card">MY DISCOUNT COUPON</router-link>
+        </li>
+        <li class="dropdown-item i4">
+          <router-link to="/invite"
+            >INVITE FRIENDS
+            <span class="ptc-tag">Get a $10 coupon</span></router-link
+          >
+        </li>
+        <li class="dropdown-item i5">
+          <router-link to="/account">ACCOUNT INFORMATION</router-link>
+        </li>
+        <li class="dropdown-item i6" @click="signOut">SIGN OUT</li>
+      </ul>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useRouter } from 'vue-router'
+import { state, logout } from '@/store'
+import Dialog from '@/components/dialog'
+
+const router = useRouter()
+
+async function signOut() {
+  await Dialog.confirm('TIPS', 'Are you sure you want to sign out?', {
+    confirmText: 'YES',
+  })
+  await logout()
+  router.push('/')
+}
+</script>
+
+<style lang="scss">
+.p-dashboard {
+  @include media-breakpoint-up(lg) {
+    margin-top: 64px;
+  }
+
+  @include media-breakpoint-up(md) {
+    .swiper-wrapper {
+      display: flex;
+      justify-content: center;
+      overflow-x: auto;
+      padding-bottom: 34px;
+    }
+    .swiper-slide {
+      flex-shrink: 0;
+      width: 526px;
+      + .swiper-slide {
+        margin-left: 28px;
+      }
+    }
+    .dropdown-list {
+      padding-left: 16px;
+    }
+  }
+}
+</style>

+ 42 - 47
src/pages/gift-card/index.vue

@@ -17,53 +17,43 @@
         </div>
       </div>
     </div>
-    <div class="card-list-wrap">
-      <div v-if="!list.length" class="ptc-empty">
-        <i class="ptc-empty-img"></i>
-        <p class="ptc-empty-txt">No gift card yet</p>
-      </div>
-      <div v-else class="card-list">
-        <div
-          v-for="(item, index) of list"
-          :key="index"
-          class="card"
-          :class="{
-            'card-a': type === 0,
-            'card-c': type === 1,
-            'card-e': type === 2,
-          }"
-        >
-          <p class="card-title">{{ item.title }}</p>
-          <p class="card-period">
-            Validity: {{ item.used_at }}-{{ item.expired_at }}
-          </p>
-          <p class="card-value">- {{ item.gift_card_amount }}</p>
-          <p class="card-desc">PTC offline store use</p>
-        </div>
-        <!-- <div class="card card-b">
-          <p class="card-title">Pull new reward gift card</p>
-          <p class="card-period">Validity: 2020/12/01-2020/05/01</p>
-          <p class="card-value">- $10 <span class="sub">100 available</span></p>
-          <p class="card-desc">PTC offline store use</p>
-        </div>
-        <div class="card card-c">
-          <p class="card-title">Pull new reward gift card</p>
-          <p class="card-period">Validity: 2020/12/01-2020/05/01</p>
-          <p class="card-value">- $10</p>
-          <p class="card-desc">PTC offline store use</p>
+    <div :class="{ 'ptc-loading': loading }">
+      <div class="card-list-wrap">
+        <div v-if="!list.length" class="ptc-empty">
+          <i class="ptc-empty-img"></i>
+          <p class="ptc-empty-txt">No gift card yet</p>
         </div>
-        <div class="card card-d">
-          <p class="card-title">Pull new reward gift card</p>
-          <p class="card-period">Validity: 2020/12/01-2020/05/01</p>
-          <p class="card-value">- $10 <span class="sub">100 available</span></p>
-          <p class="card-desc">PTC offline store use</p>
+        <div v-else class="card-list">
+          <div
+            v-for="(item, index) of list"
+            :key="index"
+            class="card"
+            :class="{
+              'card-a': item.status == 0,
+              'card-c': item.status == 1,
+              'card-e': item.status == 2,
+            }"
+          >
+            <p class="card-title">{{ item.title }}</p>
+            <p class="card-period">
+              Validity: {{ item.used_at }}-{{ item.expired_at }}
+            </p>
+            <p class="card-value">- {{ item.gift_card_amount }}</p>
+            <p class="card-desc">PTC offline store use</p>
+          </div>
+          <!-- <div class="card card-b">
+            <p class="card-title">Pull new reward gift card</p>
+            <p class="card-period">Validity: 2020/12/01-2020/05/01</p>
+            <p class="card-value">- $10 <span class="sub">100 available</span></p>
+            <p class="card-desc">PTC offline store use</p>
+          </div>
+          <div class="card card-d">
+            <p class="card-title">Pull new reward gift card</p>
+            <p class="card-period">Validity: 2020/12/01-2020/05/01</p>
+            <p class="card-value">- $10 <span class="sub">100 available</span></p>
+            <p class="card-desc">PTC offline store use</p>
+          </div> -->
         </div>
-        <div class="card card-e">
-          <p class="card-title">Pull new reward gift card</p>
-          <p class="card-period">Validity: 2020/12/01-2020/05/01</p>
-          <p class="card-value">- $10 <span class="sub">100 available</span></p>
-          <p class="card-desc">PTC offline store use</p>
-        </div> -->
       </div>
     </div>
   </div>
@@ -88,12 +78,17 @@ export default defineComponent({
       list: [],
       /** @type {any} */
       stat: {},
+      loading: false,
     }
   },
   watch: {
     async type(val) {
-      const { results } = await getGiftCardList(val)
-      this.list = results.items
+      this.loading = true
+      try {
+        const { results } = await getGiftCardList(val)
+        this.list = results.items
+      } catch {}
+      this.loading = false
     },
   },
 })

+ 1 - 1
src/pages/login/index.vue

@@ -80,7 +80,7 @@ async function handleLogin() {
   const { message } = await login(values as any)
   Toast(message)
   const { need_change } = await getUserInfo()
-  router.replace(need_change ? '/password/change' : from || '/')
+  router.replace(+need_change ? '/password/change' : from || '/')
 }
 </script>
 

+ 6 - 0
src/router.ts

@@ -1,6 +1,7 @@
 import { createRouter, createWebHistory } from 'vue-router'
 import { state } from './store'
 import NProgress from 'nprogress'
+import Dashboard from './pages/dashboard/index.vue'
 
 NProgress.configure({ showSpinner: false })
 
@@ -91,6 +92,11 @@ const router = createRouter({
       component: () => import('./pages/invite/index.vue'),
       meta: { auth: true },
     },
+    {
+      path: '/dashboard',
+      component: Dashboard,
+      meta: { auth: true },
+    },
   ],
 })
 

+ 33 - 0
src/style/components.scss

@@ -175,3 +175,36 @@
     color: #999;
   }
 }
+
+.ptc-loading {
+  @include media-breakpoint-up(md) {
+    position: relative;
+    overflow: hidden !important;
+    &::before {
+      content: '';
+      position: absolute;
+      left: 0;
+      right: 0;
+      top: 0;
+      bottom: 0;
+      background: rgba(255, 255, 255, 0.85);
+      z-index: 10;
+    }
+    &::after {
+      content: '';
+      @include icon('@img/loading.svg', 100px);
+      position: absolute;
+      left: 50%;
+      top: 45%;
+      transform: translate(-50%, -50%);
+      animation: rotate2 1s ease-in-out infinite;
+      z-index: 11;
+    }
+  }
+
+  @keyframes rotate2 {
+    100% {
+      transform: translate(-50%, -50%) rotate(360deg);
+    }
+  }
+}