【珍惜時間】 vant-finance-mobile

先說下這個作者大大的項目
運行就跳轉到黃色網頁了,然後我把網頁差掉,接下來就是繼續運行,然後就可以打開網頁了
先放下作者大大的項目地址,接下來我們看下頁面效果
https://github.com/huzongyao/vant-finance-mobile

接下來我們就來看代碼嘍

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <title>Vant Finance</title>
  <style>
    body {
      padding: 0;
      margin: 0
    }

    #h-lb {
      width: 100%;
      height: 100%;
      position: fixed;
      text-align: center;
      background-color: #CA4040;
    }

    #h-con {
      position: fixed;
      top: 50%;
      left: 50%;
      -webkit-transform: translate3d(-50%, -50%, 0);
      transform: translate3d(-50%, -50%, 0);
    }

    #h-con .l-s {
      position: static;
      width: 60px;
      height: 60px;
      -webkit-transform: scale(0.7);
      transform: scale(0.7);
      -webkit-animation: l-2-s 1s ease alternate infinite;
      animation: l-2-s 1s ease alternate infinite;
    }

    #h-con .l-c {
      width: 8px;
      height: 8px;
      background: #ffffff;
      border-radius: 50%;
      position: absolute;
      left: calc(50% - 4px);
      top: calc(50% - 4px);
      -webkit-transition: all 1s ease;
      transition: all 1s ease;
      -webkit-animation: l-2-c 1s ease-in-out alternate infinite;
      animation: l-2-c 1s ease-in-out alternate infinite;
    }

    @-webkit-keyframes l-2-c {
      0% {
        box-shadow: 0 0 0 #ffffff;
        opacity: 1;
        -webkit-transform: rotate(0deg);
        transform: rotate(0deg);
      }
      50% {
        box-shadow: 24px -22px #ffffff, 30px -15px 0 -3px #ffffff, 31px 0 #ffffff, 29px 9px 0 -3px #ffffff,
        24px 23px #ffffff, 17px 30px 0 -3px #ffffff, 0 33px #ffffff, -10px 28px 0 -3px #ffffff,
        -24px 22px #ffffff, -29px 14px 0 -3px #ffffff, -31px -3px #ffffff, -30px -11px 0 -3px #ffffff,
        -20px -25px #ffffff, -12px -30px 0 -3px #ffffff, 5px -29px #ffffff, 13px -25px 0 -3px #ffffff;
        -webkit-transform: rotate(180deg);
        transform: rotate(180deg);
      }
      100% {
        opacity: 0;
        -webkit-transform: rotate(360deg);
        transform: rotate(360deg);
        box-shadow: 25px -22px #ffffff, 15px -22px 0 -3px black, 31px 2px #ffffff, 21px 2px 0 -3px black,
        23px 25px #ffffff, 13px 25px 0 -3px black, 0 33px #ffffff, -10px 33px 0 -3px black,
        -26px 24px #ffffff, -19px 17px 0 -3px black, -32px 0 #ffffff, -23px 0 0 -3px black,
        -25px -23px #ffffff, -16px -23px 0 -3px black, 0 -31px #ffffff, -2px -23px 0 -3px black;
      }
    }

    @keyframes l-2-c {
      0% {
        box-shadow: 0 0 0 #ffffff;
        opacity: 1;
        -webkit-transform: rotate(0deg);
        transform: rotate(0deg);
      }
      50% {
        box-shadow: 24px -22px #ffffff, 30px -15px 0 -3px #ffffff, 31px 0 #ffffff, 29px 9px 0 -3px #ffffff,
        24px 23px #ffffff, 17px 30px 0 -3px #ffffff, 0 33px #ffffff, -10px 28px 0 -3px #ffffff,
        -24px 22px #ffffff, -29px 14px 0 -3px #ffffff, -31px -3px #ffffff, -30px -11px 0 -3px #ffffff,
        -20px -25px #ffffff, -12px -30px 0 -3px #ffffff, 5px -29px #ffffff, 13px -25px 0 -3px #ffffff;
        -webkit-transform: rotate(180deg);
        transform: rotate(180deg);
      }
      100% {
        opacity: 0;
        -webkit-transform: rotate(360deg);
        transform: rotate(360deg);
        box-shadow: 25px -22px #ffffff, 15px -22px 0 -3px black, 31px 2px #ffffff, 21px 2px 0 -3px black,
        23px 25px #ffffff, 13px 25px 0 -3px black, 0 33px #ffffff, -10px 33px 0 -3px black, -26px 24px #ffffff,
        -19px 17px 0 -3px black, -32px 0 #ffffff, -23px 0 0 -3px black, -25px -23px #ffffff,
        -16px -23px 0 -3px black, 0 -31px #ffffff, -2px -23px 0 -3px black;
      }
    }

    @-webkit-keyframes l-2-s {
      0% {
        -webkit-transform: scale(0) rotate(0deg);
        transform: scale(0) rotate(0deg);
      }
      100% {
        -webkit-transform: scale(0.7) rotate(360deg);
        transform: scale(0.7) rotate(360deg);
      }
    }

    @keyframes l-2-s {
      0% {
        -webkit-transform: scale(0) rotate(0deg);
        transform: scale(0) rotate(0deg);
      }
      100% {
        -webkit-transform: scale(0.7) rotate(360deg);
        transform: scale(0.7) rotate(360deg);
      }
    }
  </style>
</head>

<body>
<div id="app">
  <div id="h-lb">
    <div id="h-con">
      <svg class="l-s" xmlns="http://www.w3.org/2000/svg" version="1.1">
        <polygon
          points="29.8 0.3 22.8 21.8 0 21.8 18.5 35.2 11.5 56.7 29.8 43.4 48.2 56.7 41.2 35.1 59.6 21.8 36.8 21.8 "
          fill="#ffffff"></polygon>
      </svg>
      <div class="l-c"></div>
    </div>
  </div>
</div>
</body>
</html>

html文件中定義了不少的動畫
接下來看main.js中引用了哪些東西

//main.js
import Vue from 'vue';
import Vant from 'vant';
import {Lazyload} from 'vant';
import VueClipboards from 'vue-clipboards';
import ScrollPosition from 'vue-keep-scroll-position'

import 'vant/lib/index.less'
//使用本地的icon字體
import 'vant/lib/icon/local.less';
import './assets/style/common.less';

import App from './App.vue';
import VueMixin from './mixins/VueMixin';
import i18n from './locales';
import router from './router';
import store from './vuex';
import stream from './http';
import urls from './http/urls';

Vue.use(Vant);
Vue.use(Lazyload);
Vue.use(VueClipboards);
Vue.use(ScrollPosition);
Vue.mixin(VueMixin);

Vue.prototype.$http = stream;
Vue.prototype.$urls = urls;

new Vue({
  i18n,
  router,
  store,
  el: '#app',
  render: h => h(App)
});

接下來看App.vue

<template>
  <div id="app">
    <!--緩存的頁面-->
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive">
      </router-view>
    </keep-alive>
    <!--不緩存的頁面-->
    <router-view v-if="!$route.meta.keepAlive">
    </router-view>
  </div>
</template>

<script>
  export default {
    name: "app",
    mounted() {
      this.loadUserInfo();
    },
    methods: {
      loadUserInfo() {
        try {
          // 讀取用戶信息
          let infoStr = localStorage.getItem('userInfo');
          if (infoStr) {
            let info = JSON.parse(infoStr);
            this.$store.commit('setUserInfo', info);
          }
        } catch (e) {
        }
      },
    },
  }
</script>


<style scoped lang="scss">
  #app {
    background-color: #f7f7f7;
    height: 100vh;
  }
</style>

接下來看router.js

import Vue from 'vue'
import VueRouter from 'vue-router';

Vue.use(VueRouter);

import MainPage from '../view/main/MainPage';
import TabHome from '../view/main/tabs/TabHome';
import TabProducts from '../view/main/tabs/TabProducts';
import TabDiscover from '../view/main/tabs/TabDiscover';
import TabMine from '../view/main/tabs/TabMine';

const SettingsPage = r => require.ensure([], () => r(require('../view/mine/SettingsPage')), 'SettingsPage');
const IFrameWebPage = r => require.ensure([], () => r(require('../view/common/IFrameWebPage')), 'IFrameWebPage');
const TestCasePage = r => require.ensure([], () => r(require('../view/mine/TestCasePage')), 'TestCasePage');
const ForumPage = r => require.ensure([], () => r(require('../view/discover/ForumPage')), 'ForumPage');
const MessagePage = r => require.ensure([], () => r(require('../view/mine/MessagePage')), 'MessagePage');
const MessageDetail = r => require.ensure([], () => r(require('../view/mine/MessageDetail')), 'MessageDetail');
const ProductDetail = r => require.ensure([], () => r(require('../view/product/ProductDetail')), 'ProductDetail');
const LoginPage = r => require.ensure([], () => r(require('../view/login/LoginPage')), 'LoginPage');
const GestureCreate = r => require.ensure([], () => r(require('../view/login/GestureCreate')), 'GestureCreate');

const routes = [
  {path: '*', redirect: '/main'},
  {
    name: 'main', redirect: '/main/home', component: MainPage,
    children: [
      {name: 'home', path: 'home', component: TabHome, meta: {keepAlive: true}},
      {name: 'products', path: 'products', component: TabProducts, meta: {keepAlive: true}},
      {name: 'discover', path: 'discover', component: TabDiscover, meta: {keepAlive: true}},
      {name: 'mine', path: 'mine', component: TabMine, meta: {keepAlive: true}},
    ], meta: {keepAlive: true}
  },
  {name: 'LoginPage', component: LoginPage},
  {name: 'GestureCreate', component: GestureCreate},
  {name: 'SettingsPage', component: SettingsPage},
  {name: 'IFrameWebPage', component: IFrameWebPage},
  {name: 'TestCasePage', component: TestCasePage},
  {name: 'ForumPage', component: ForumPage},
  {name: 'MessagePage', component: MessagePage},
  {name: 'ProductDetail', component: ProductDetail},
  {name: 'MessageDetail', component: MessageDetail},
];

// 懶得寫path,給他們自動生成一個,和name同名
routes.forEach(route => {
  route.path = route.path || '/' + (route.name || '');
});

const router = new VueRouter({routes});

// 生命週期之前
router.beforeEach((to, from, next) => {
  // 保存個路由來路,以備不時之需
  localStorage.setItem('fromPage', from.name);
  next();
});

//生命週期之後
router.afterEach((to, from) => {
  // 滑動到頂吧
  window.scrollTo(0, 0);
});

export default router;

這個router.js也是很有意思,作者大大很有想法的
接下來看首頁了

<template>
  <div>
    <div style="position: relative">
      <!--頭部輪播-->
      <van-swipe :autoplay="5000" indicator-color="red">
        <van-swipe-item v-for="(item, index) in swipeImages" :key="index">
          <van-image class="swipe-img" :src="item.img" @click="swipeImageClick(item)" fit="fill"></van-image>
        </van-swipe-item>
      </van-swipe>
      <!--消息按鈕-->
      <div class="msg-con" @click="onMessageClick">
        <van-image src="static/img/home/icon_message_back.png" class="msg-image"></van-image>
        <div class="msg-text">3</div>
      </div>
      <!--文本輪播-->
      <van-swipe :autoplay="3000" vertical :show-indicators="false" class="swipe-text-con">
        <van-swipe-item class="swipe-text-item" v-for="(it,idx) in textSwipes" :key="idx">
          <div class="swipe-text-txt">{{it.text}}</div>
        </van-swipe-item>
      </van-swipe>
    </div>
    <!--新手專享-->
    <div class="fresher-all">
      <div class="fresher-back align-center"
           :style="{'background-image':'url(static/img/home/fresher_ticket_back.png)'}">
        <div class="fresher-top">
          <div class="fresher-left">新手專享</div>
          <div class="fresher-right">2個活動獎勵</div>
        </div>
        <div class="fresh-month">
          <div class="month-line"></div>
          <div class="month-txt light-txt">一個月期限</div>
          <div class="month-line"></div>
        </div>
        <div class="red-txt"><span class="rate-big">14</span>%+0.5%</div>
        <!--二等分區域-->
        <van-row class="num-con">
          <van-col span="12">
            <div><span class="money-big">25.50</span>萬元</div>
            <div class="ins-txt light-txt">剩餘金額</div>
          </van-col>
          <van-col span="12" class="right-con">
            <div><span class="money-big">12</span>萬元</div>
            <div class="ins-txt light-txt">起投金額</div>
          </van-col>
        </van-row>
        <van-button type="danger" round class="buy-btn" @click="onBuyClick">立即搶購</van-button>
      </div>
    </div>
    <!--中部應用入口-->
    <van-row class="mid-app">
      <van-col span="12" v-for="(it, idx) in middleApps" :key="idx" class="mid-item click-box">
        <img :src="'static/img/home/'+it.icon" class="line2-icon"/>
        <div>
          <div class="mid-title">{{it.title}}</div>
          <div class="mid-text light-txt">{{it.text}}</div>
        </div>
      </van-col>
    </van-row>
    <!--我的賬戶-->
    <van-row class="money-all">
      <van-col span="12">
        <div class="light-txt">累計投資</div>
        <div class="red-txt">567,875,565.59</div>
      </van-col>
      <van-col span="12">
        <div class="light-txt">累計賺取</div>
        <div class="red-txt">67,875,565.59</div>
      </van-col>
    </van-row>
    <!--底部說明-->
    <van-row class="bot-app">
      <van-col span="12" v-for="(it, idx) in bottomApps" :key="idx" class="bot-item">
        <img :src="'static/img/home/'+it.icon" class="line4-icon"/>
        <div class="bot-text">
          <div>{{it.title}}</div>
          <div class="light-txt bot-small">{{it.text}}</div>
        </div>
      </van-col>
    </van-row>
  </div>
</template>

<script>
  export default {
    name: "tab-home",
    data() {
      return {
        swipeImages: [
          {img: 'static/img/banner/banner1.png', link: ''},
          {img: 'static/img/banner/banner2.jpg', link: ''},
          {img: 'static/img/banner/banner3.jpg', link: ''},
          {img: 'static/img/banner/banner4.jpg', link: ''},
        ],
        textSwipes: [
          {text: '修復 DatetimePicker 使用 formatter 且爲 time 類型時 confirm 事件參數錯誤的問題'},
          {text: '修復 Tabs 在 sticky 模式下滾動回到頂部時存在 1 像素偏差的問題'},
          {text: 'ActionSheet: 新增多個 less 變量'},
        ],
        middleApps: [
          {icon: 'line2_icon1.png', title: '推薦有禮', 'text': '紅包送不停'},
          {icon: 'line2_icon2.png', title: '每日簽到', 'text': '積分等你加'},
          {icon: 'line2_icon3.png', title: '安全保障', 'text': '貼心小管家'},
          {icon: 'line2_icon4.png', title: '融金數據', 'text': '投資好幫手'},
        ],
        bottomApps: [
          {icon: 'line4_icon1.png', title: '互聯網金融協會', 'text': '會長級別單位'},
          {icon: 'line4_icon2.png', title: '5000萬融資保障', 'text': '保護您的資產安全'},
          {icon: 'line4_icon3.png', title: '國家AAA級企業', 'text': '貼心小管家'},
          {icon: 'line4_icon4.png', title: '銀行風險控制', 'text': '第三方資金託管'},
        ],
      };
    },
    methods: {
      onBuyClick() {
        this._routePushQ('ProductDetail', {id: 1});
      },
      onMessageClick() {
        this._routePush('MessagePage');
      },
      swipeImageClick(item) {
      }
    }
  }
</script>

<style scoped lang="scss">
  .swipe-text-con {
    height: 30px;
    .swipe-text-item {
      height: 30px;
      display: flex;
      background-color: #fff7cc;
      align-items: center;
      .swipe-text-txt {
        height: 30px;
        font-size: 14px;
        line-height: 30px;
        padding: 0 10px;
        color: #f60;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }
  }

  .msg-con {
    position: absolute;
    top: 20px;
    right: 20px;
    .msg-image {
      width: 36px;
      height: 36px;
    }
    .msg-text {
      position: absolute;
      top: -2px;
      right: 4px;
      box-sizing: border-box;
      min-width: 18px;
      padding: 1px 5px;
      color: #fff;
      font-size: 12px;
      text-align: center;
      background-color: #f44;
      border-radius: 30px;
      transform: translateX(50%);
      transform-origin: 100%;
    }
  }

  .money-all {
    background-color: white;
    margin-top: 10px;
    text-align: center;
    padding: 20px 0;
  }

  .bot-app {
    margin-top: 10px;
    margin-bottom: 20px;
    .bot-item {
      display: flex;
      padding: 6px 10px;
      align-items: center;
      background-color: white;
      border: 1px solid #f7f7f7;
      .bot-text {
        font-size: 12px;
        .bot-small {
          margin-top: 2px;
        }
      }
      .line4-icon {
        width: 40px;
        height: 40px;
        margin: 6px;
      }
    }
  }

  .mid-app {
    .mid-item {
      display: flex;
      align-items: center;
      border: 1px solid #f7f7f7;
      padding: 10px;
      .line2-icon {
        width: 60px;
        height: 60px;
      }
      .mid-title {
        font-size: 14px;
      }
      .mid-text {
        margin-top: 2px;
        font-size: 12px;
      }
    }
  }

  .num-con {
    margin: 12px 0;
    .money-big {
      font-size: 20px;
    }
    .ins-txt {
      font-size: 12px;
      margin-top: 6px;
    }
    .right-con {
      border-left: 1px solid #dddddd;
    }
  }

  .fresher-all {
    padding: 10px;
    .fresher-back {
      background-size: 100% 100%;
      padding: 10px 16px 16px 16px;
      .rate-big {
        font-size: 30px;
      }
      .fresher-top {
        display: flex;
        justify-content: space-between;
        color: #FE7846;
        .fresher-right {
          font-size: 14px;
          border-radius: 20px;
          padding: 1px 6px;
          border: 1px solid #FE7846;
        }
      }
      .fresh-month {
        display: flex;
        align-items: center;
        justify-content: center;
        margin-top: 30px;
        margin-bottom: 10px;
        .month-txt {
          margin: 0 20px;
        }
        .month-line {
          width: 24%;
          height: 1px;
          background-color: #aaaaaa;
        }
      }
      .buy-btn {
        width: 70%;
        font-size: 16px;
        height: 36px;
        line-height: 30px;
      }
    }
  }

  .swipe-img {
    vertical-align: bottom;
    width: 100%;
    height: 50vw;
  }
</style>

接下來是message頁面

<template>
  <div>
    <van-nav-bar left-arrow @click-left="_routerBack" title="融金公告" fixed :z-index="10"></van-nav-bar>
    <div class="nav-con-16">
      <div v-for="(it, idx) in messageData" :key="idx" class="msg-item click-box" @click="onClickMessage(it)">
        <div class="msg-title">{{it.title}}</div>
        <div class="msg-sub">
          <div class="msg-flag">{{it.flag}}</div>
          <div class="msg-date light-txt">{{it.date}}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "message-page",
    data() {
      return {
        messageData: [
          {title: '新增 Grid、GridItem 組件', flag: '平臺公告', date: '2019-05-02'},
          {title: '修復 Collapse 在 safari 瀏覽器上動畫可能閃爍的問題', flag: '平臺公告', date: '2019-05-02'},
          {title: 'CouponList: 新增 enabled-title、disabled-title 屬性', flag: '平臺公告', date: '2019-03-02'},
          {title: '新增 Grid、GridItem 組件', flag: '平臺公告', date: '2019-05-02'},
          {title: '修復 Collapse 在 safari 瀏覽器上動畫可能閃爍的問題', flag: '平臺公告', date: '2019-05-02'},
          {title: 'CouponList: 新增 enabled-title、disabled-title 屬性', flag: '平臺公告', date: '2019-03-02'},
        ],
      };
    },
    methods: {
      onClickMessage(item) {
        this._routePush('MessageDetail');
      }
    },
  }
</script>

<style scoped lang="scss">
  .msg-item {
    margin-bottom: 12px;
    padding: 12px;
    .msg-title {
      font-size: 14px;
      color: #666666;
    }
    .msg-sub {
      display: flex;
      align-items: center;
      margin-top: 10px;
      justify-content: space-between;
      .msg-date {
        font-size: 12px;
      }
      .msg-flag {
        font-size: 14px;
        border-radius: 20px;
        border: solid 1px #f56723;
        color: #f56723;
        padding: 1px 8px;
      }
    }
  }
</style>

<template>
  <div>
    <van-nav-bar left-arrow @click-left="_routerBack" title="C計劃詳情" fixed :z-index="10"></van-nav-bar>
    <div class="nav-con-16">
      <!--頭部信息-->
      <div class="main-con">
        <div class="van-hairline--bottom prod-name">
          <span class="name-ico">C</span>中小企業-E車貸ECO JKI45002 1654241
        </div>
        <div class="align-center rate-con">
          <div class="red-txt"><span class="big-rate">4.98</span>%</div>
          <div class="rate-tit">預期年化收益</div>
          <div class="period-txt top-mar-16">期限12個月</div>
        </div>
        <div>
          <div class="pro-per">投資進度<span class="red-txt">64.5%</span></div>
          <van-progress :percentage="64.5" color="#ff6611" class="prod-progress" :show-pivot="false">
          </van-progress>
          <div class="pro-amount">
            <div>項目總額180萬</div>
            <div>剩餘可投<span class="red-txt">75萬</span></div>
          </div>
        </div>
      </div>
      <!--中部信息-->
      <div class="top-mar-16 detail-con">
        <div class="top-title van-hairline--bottom">
          <div>C計劃簡介</div>
          <div class="period-txt">優享計劃</div>
        </div>
        <div class="top-intro">優選分散投資,確保穩定收益</div>
        <van-row>
          <van-col span="6" class="row-item" v-for="(it,idx) in statusList" :key="idx">
            <div class="align-center">
              <van-image :src="'static/img/product/'+it.img1" class="status-img"></van-image>
              <div class="status-txt">{{it.text}}</div>
            </div>
            <van-image :src="'static/img/product/'+it.img2" v-if="idx!=3" class="arrow-img"></van-image>
          </van-col>
        </van-row>
      </div>
      <!--底部選項-->
      <div class="top-mar-16">
        <van-cell-group>
          <van-cell title="計劃詳情" is-link size="large"></van-cell>
          <van-cell title="購買記錄" is-link size="large"></van-cell>
          <van-cell title="常見問題" is-link size="large"></van-cell>
        </van-cell-group>
      </div>
      <div class="align-center bottom-txt">個人資產由銀行託管保障安全</div>
      <!--底部按鈕-->
      <van-button type="danger" class="bottom-btn">
        立即投標 <span class="btn-left">(剩餘可投70萬元)</span>
      </van-button>
    </div>
  </div>
</template>

<script>
  export default {
    name: "product-detail",
    data() {
      return {
        statusList: [
          {img1: 'prod_status2.png', img2: 'prod_arrow1.png', text: '啓動計劃'},
          {img1: 'prod_status3.png', img2: 'prod_arrow1.png', text: '啓動計劃'},
          {img1: 'prod_status4.png', img2: 'prod_arrow1.png', text: '啓動計劃'},
          {img1: 'prod_status1.png', img2: 'prod_arrow1.png', text: '啓動計劃'},
        ],
      };
    },
  }
</script>

<style scoped lang="scss">
  .bottom-txt {
    padding: 30px 0 64px 0;
    font-size: 14px;
    background-color: #f7f7f7;
    color: #999999;
  }

  .detail-con {
    background-color: white;
    padding: 10px;
    .top-intro {
      margin-top: 16px;
      color: #999999;
    }
    .row-item {
      display: flex;
      align-items: center;
      padding: 16px 0;
      .status-img {
        width: 10vw;
        height: 10vw;
      }
      .arrow-img {
        width: 6vw;
        height: 6vw;
      }
      .status-txt {
        font-size: 12px;
        color: #999999;
      }
    }
    .top-title {
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 14px;
      padding-bottom: 10px;
      color: #999999;
    }
  }

  .bottom-btn {
    position: fixed;
    bottom: 0;
    width: 100%;
    border-radius: 0;
    font-size: 20px;
    height: 46px;
    .btn-left {
      font-size: 14px;
    }
  }

  .period-txt {
    font-size: 14px;
    color: #ff6611;
    display: inline-block;
    padding: 1px 8px;
    border: 1px solid #ff6611;
    border-radius: 20px;
  }

  .rate-con {
    padding: 20px 0;
    .rate-tit {
      color: #999999;
      font-size: 14px;
      margin-top: 8px;
    }
    .big-rate {
      font-size: 34px;
    }
  }

  .pro-per {
    margin: 4px 0;
    font-size: 14px;
    color: #999999;
  }

  .pro-amount {
    display: flex;
    justify-content: space-between;
    margin-top: 4px;
    font-size: 14px;
    color: #999999;
  }

  .prod-progress {
    height: 6px;
  }

  .main-con {
    background-color: white;
    padding: 10px;
    .prod-name {
      padding: 4px 0;
      font-size: 14px;
      color: #666666;
      .name-ico {
        background-color: #ff6c6c;
        height: 20px;
        padding: 0 4px;
        margin-right: 4px;
        border-radius: 2px;
        color: white;
        line-height: 20px;
      }
    }
  }
</style>

<template>
  <div>
    <div class="top-fixed">
      <van-nav-bar :title="$t('tab_products')" fixed :z-index="10"></van-nav-bar>
      <div class="nav-con navbar-con">
        <van-tabs v-model="activeSort" class="sort-all" sticky @change="onTabChange" line-width="33%" type="card">
          <van-tab :title="it_so.title" v-for="(it_so, idx) in sortItems" :key="idx">
            <div class="prod-item click-box" v-for="(it_po,idx_p) in getProductList(idx)"
                 :key="idx_p" @click="onProductClick(it_po)">
              <van-row>
                <van-col span="12" class="prod-rate">
                  <div class="red-txt rate-txt"><span class="rate-big">{{it_po.rate}}</span>%+{{it_po.add}}%</div>
                  <div class="light-txt rate-ins">預期年化收益率</div>
                </van-col>
                <van-col span="12" class="prod-ins">
                  <div class="prod-title">{{it_po.name}}</div>
                  <div class="prod-tag">期限{{it_po.days}}天</div>
                </van-col>
              </van-row>
              <!--進度條-->
              <van-progress :percentage="it_po.percent" color="#ff6611" class="prod-progress" :show-pivot="false">
              </van-progress>
              <div class="pro-amount">
                <div>項目總額180萬</div>
                <div>剩餘可投<span class="red-txt">75萬</span></div>
              </div>
            </div>
          </van-tab>
        </van-tabs>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "tab-products",
    data() {
      return {
        activeSort: 0,
        sortItems: [
          {title: '推薦'},
          {title: '收益率'},
          {title: '期限'},
        ],
        allProducts: [
          {id: 5, rate: 4.5, add: 0.5, name: 'A計劃064512544', days: 365, percent: 65},
          {id: 6, rate: 4.0, add: 0.5, name: 'B計劃064512542', days: 60, percent: 95},
          {id: 7, rate: 2.5, add: 0.1, name: 'C計劃064512546', days: 30, percent: 23},
          {id: 8, rate: 4.5, add: 0.5, name: 'A計劃064512544', days: 365, percent: 65},
          {id: 9, rate: 4.0, add: 0.5, name: 'B計劃064512542', days: 60, percent: 95},
          {id: 22, rate: 2.5, add: 0.1, name: 'C計劃064512546', days: 30, percent: 23},
          {id: 34, rate: 4.5, add: 0.5, name: 'A計劃064512544', days: 365, percent: 65},
          {id: 21, rate: 4.0, add: 0.5, name: 'B計劃064512542', days: 60, percent: 95},
          {id: 12, rate: 2.5, add: 0.1, name: 'C計劃064512546', days: 30, percent: 23},
          {id: 13, rate: 6.0, add: 0.1, name: 'C計劃064512546(售罄)', days: 10, percent: 100},
          {id: 14, rate: 5.0, add: 0.1, name: 'C計劃064512543(售罄)', days: 120, percent: 100},
          {id: 15, rate: 6.0, add: 0.1, name: 'C計劃064512546(售罄)', days: 10, percent: 100},
          {id: 16, rate: 5.0, add: 0.1, name: 'C計劃064512543(售罄)', days: 120, percent: 100},
          {id: 17, rate: 6.0, add: 0.1, name: 'C計劃064512546(售罄)', days: 10, percent: 100},
          {id: 18, rate: 5.0, add: 0.1, name: 'C計劃064512543(售罄)', days: 120, percent: 100},
        ],
      };
    },
    computed: {
      getProductList() {
        let newList = this.allProducts.slice(0);
        return (index) => {
          if (index == 0) {
            return this.allProducts;
          } else if (index == 1) {
            return newList.sort((a, b) => {
              return a.rate - b.rate;
            });
          } else if (index == 2) {
            return newList.sort((a, b) => {
              return a.days - b.days;
            });
          }
        }
      }
    },
    methods: {
      onProductClick(item) {
        this._routePushQ('ProductDetail', {id: item.id});
      },
      onTabChange() {
      },
    },
  }
</script>

<style scoped lang="scss">
  .prod-item {
    padding: 12px;
    margin-top: 12px;
    .pro-amount {
      display: flex;
      justify-content: space-between;
      margin-top: 4px;
      font-size: 14px;
      color: #999999;
    }
    .prod-progress {
      margin-top: 20px;
      height: 6px;
    }
    .prod-rate {
      text-align: center;
      padding: 2px 10px;
      .rate-txt {
        font-size: 14px;
        .rate-big {
          font-size: 24px;
        }
      }
      .rate-ins {
        font-size: 12px;
        margin-top: 4px;
      }
    }
    .prod-ins {
      border-left: 1px solid #aaaaaa;
      padding: 2px 10px;
      .prod-title {
        font-size: 14px;
      }
      .prod-tag {
        display: table;
        font-size: 12px;
        margin-top: 16px;
        border: 1px solid #ff6c6c;
        border-radius: 20px;
        color: #ff6c6c;
        padding: 0 6px;
      }
    }
  }

  .navbar-con {
    .sort-all {
      padding-top: 0;
    }
  }
</style>

<template>
  <div>
    <van-nav-bar :title="$t('tab_discovery')" fixed :z-index="10"></van-nav-bar>
    <div class="nav-con">
      <!--頂部圖片-->
      <van-image src="static/img/discovery/discovery_banner.jpg" class="banner-img"></van-image>
      <!--中部內容-->
      <div style="padding: 10px">
        <div class="align-center commu-all"
             :style="{'background-image':'url(static/img/home/fresher_ticket_back.png)'}">
          <div class="commu-top">
            <div class="commu-left">好帖推薦</div>
            <div class="commu-right">2個活動獎勵</div>
          </div>
          <div class="commu-mid">
            <div class="commu-title">外交部:臺灣同胞可在中國駐外使領館尋求保護協助</div>
            <div class="light-txt commu-txt">
              外交部領保中心常務副主任楊舒介紹了“26條措施”的第14條,臺灣同胞可在中國駐外使領館尋求領事保護與協助的途徑...
            </div>
          </div>
          <van-button type="danger" round class="commu-btn" @click="onCommuClick">進入社區</van-button>
        </div>
      </div>
      <!--下部應用入口-->
      <van-row class="line2-all">
        <van-col span="12" v-for="(it, idx) in middleApps" :key="idx" class="line2-item click-box">
          <img :src="'static/img/discovery/'+it.icon" class="line2-icon"/>
          <div>
            <div class="line2-title">{{it.title}}</div>
            <div class="line2-text light-txt">{{it.text}}</div>
          </div>
        </van-col>
      </van-row>
    </div>
  </div>
</template>

<script>
  export default {
    name: "tab-discover",
    data() {
      return {
        middleApps: [
          {icon: 'discovery_app_icon4.png', title: '積分商城', 'text': '絕不讓每一個積分落空'},
          {icon: 'discovery_app_icon2.png', title: '融金公益', 'text': '時間有愛,融金有益'},
          {icon: 'discovery_app_icon3.png', title: '紅包廣場', 'text': '福利大派送,一起來搶錢'},
          {icon: 'discovery_app_icon1.png', title: '任務大廳', 'text': 'VIP進階之路'},
          {icon: 'discovery_app_icon5.png', title: '理財小公舉', 'text': '算一算我的第一桶金'},
        ],
      };
    },
    methods: {
      onCommuClick() {
        this._loginOr(() => {
          this._routePush('ForumPage');
        })
      }
    },
  }
</script>

<style scoped lang="scss">
  .commu-all {
    background-size: 100% 100%;
    padding: 6px 16px 20px 16px;
    .commu-mid {
      padding: 10px;
      text-align: left;
      .commu-title {
        font-size: 16px;
        margin-top: 14px;
      }
      .commu-txt {
        font-size: 14px;
        margin-top: 10px;
      }
    }
    .commu-btn {
      margin-top: 10px;
      width: 70%;
      font-size: 16px;
      height: 36px;
      line-height: 30px;
    }
    .commu-top {
      display: flex;
      justify-content: space-between;
      color: #FE7846;
      .commu-right {
        font-size: 14px;
        border-radius: 20px;
        padding: 0 6px;
        border: 1px solid #FE7846;
      }
    }
  }

  .banner-img {
    width: 100%;
    height: 35vw;
  }

  .line2-all {
    margin-bottom: 20px;
    .line2-item {
      display: flex;
      border: 1px solid #f7f7f7;
      align-items: center;
      padding: 10px;
      .line2-icon {
        width: 60px;
        height: 60px;
      }
      .line2-title {
        font-size: 14px;
      }
      .line2-text {
        font-size: 12px;
        margin-top: 2px;
      }
    }
  }
</style>

<template>
  <div>
    <van-nav-bar left-arrow @click-left="_routerBack" title="登錄" fixed :z-index="10"></van-nav-bar>
    <div class="nav-con align-center login-con"
         :style="{'background-image':'url(static/img/login/login_back.png)'}">
      <div class="top-area">
        <van-image src="static/img/login/vant_logo.png" class="top-logo"></van-image>
        <div>Vant Finance</div>
      </div>
      <!--用戶名密碼登錄-->
      <div v-if="loginWay==1">
        <van-cell-group>
          <!--輸入賬號-->
          <van-field v-model="userName" left-icon="static/img/login/login_user.png" required clearable label="用戶名"
                     placeholder="請輸入手機號/用戶名(隨便填)" label-align="left" size="large" maxlength="20"></van-field>
          <!--輸入密碼-->
          <van-field v-model="password" left-icon="static/img/login/login_pass.png" label="密 碼"
                     placeholder="請輸入密碼(隨便填)" size="large" required clearable
                     :type="showPassword?'text':'password'" maxlength="20"
                     :right-icon="'static/img/login/eye_'+(showPassword?'open':'close')+'.png'"
                     @click-right-icon="showPassword=!showPassword"></van-field>
        </van-cell-group>
        <!--賬密登錄按鈕-->
        <div class="button-con">
          <van-button type="danger" round class="login-btn" :disabled="!canPwdLogin" @click="onLoginClick">登錄
          </van-button>
          <van-button type="danger" plain round class="login-btn" @click="loginWay=3-loginWay">短信登錄</van-button>
        </div>
      </div>
      <!--驗證碼登陸-->
      <div v-else>
        <van-cell-group>
          <!--輸入賬號-->
          <van-field v-model="userName" left-icon="static/img/login/login_user.png" required clearable label="手機號"
                     placeholder="請輸入手機號(隨便填)" label-align="left" size="large" maxlength="11"></van-field>
          <!--填寫驗證碼-->
          <van-field v-model="smsCode" clearable label="驗證碼" placeholder="請輸入短信驗證碼" size="large"
                     left-icon="envelop-o" maxlength="6" required>
            <van-button slot="button" size="small" plain type="danger" class="send-btn" @click="onSMSSend"
                        :disabled="!isSendSMSEnable">
              {{getSendBtnText}}
            </van-button>
          </van-field>
        </van-cell-group>
        <!--賬密登錄按鈕-->
        <div class="button-con">
          <van-button type="danger" round class="login-btn" :disabled="!canSMSLogin" @click="onSMSLogin">登錄
          </van-button>
          <van-button type="danger" plain round class="login-btn" @click="loginWay=3-loginWay">賬號登錄</van-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "login-page",
    data() {
      return {
        userName: '',
        password: '',
        smsCode: '',
        showPassword: false, //是否顯示明文
        loginWay: 1, //1: 賬密,2:驗證碼
        smsCountDown: 0,
        smsCountInterval: null,
      };
    },
    computed: {
      isSendSMSEnable() {
        return this.smsCountDown <= 0 && this.userName.length > 4;
      },
      getSendBtnText() {
        if (this.smsCountDown > 0) {
          return this.smsCountDown + '秒後發送';
        } else {
          return '發送驗證碼';
        }
      },
      canSMSLogin() {
        return this.userName.length > 4 && this.smsCode.length > 4;
      },
      canPwdLogin() {
        return this.userName.length > 4 && this.password.length > 4;
      },
    },
    mounted() {
    },
    beforeDestroy() {
      if (this.smsCountInterval) {
        clearInterval(this.smsCountInterval);
      }
    },
    methods: {
      onSMSSend() {
        this._showLoading();
        setTimeout(() => {
          this._dismissLoading();
          this._showToast('已發送');
          this.smsCountDown = 60;
          this.startSMSTimer();
        }, 300);
      },
      startSMSTimer() {
        this.smsCountInterval = setInterval(() => {
          this.smsCountDown--;
          if (this.smsCountDown <= 0) {
            clearInterval(this.smsCountInterval);
          }
        }, 1000);
      },
      onSMSLogin() {
        this.onLoginClick();
      },
      // 模擬登陸
      onLoginClick() {
        this._showLoading();
        setTimeout(() => {
          this._dismissLoading();
          this.saveUserInfo();
          this._showConfirm('登陸成功, 去設置手勢密碼?', () => {
            this._routeReplace('GestureCreate');
          }, this._routerBack);
        }, 1000);
      },
      //保存用戶信息
      saveUserInfo() {
        let info = {userName: this.userName};
        // 全局修改
        this.$store.commit('setUserInfo', info);
        // 持久化修改
        localStorage.setItem('userInfo', JSON.stringify(info));
      },
    },
  }
</script>

<style scoped>
  .send-btn {
    height: 26px;
    line-height: 24px;
  }

  .button-con {
    margin-top: 36px;
  }

  .top-area {
    margin: 30px 0;
  }

  .login-con {
    background-size: 100% 100%;
    height: calc(100vh - 46px);
  }

  .login-btn {
    width: 60%;
    margin: 12px;
  }

  .top-logo {
    width: 100px;
    margin: 16px 0;
  }
</style>

<template>
  <div>
    <!--頂部導航-->
    <div class="top-nav">
      <van-image lazy-load src="https://img.yzcdn.cn/vant/cat.jpeg" class="head-img" fit="cover"></van-image>
      <div>憤怒的小貓</div>
      <div class="top-right">
        <van-icon name="static/img/mine/mine_nav_message2.png" size="28px" style="margin-right: 6px"
                  @click="onMessageClick"></van-icon>
        <van-icon name="static/img/mine/mine_nav_settings2.png" size="28px" @click="onSettingsClick"></van-icon>
      </div>
    </div>
    <!--下部內容-->
    <div class="nav-con">
      <div class="amount-con">
        <div class="red-txt amount-txt">15,564,589,744.63</div>
        <div class="light-txt amount-ins">資產總額(元)></div>
      </div>
      <!--代收收益-->
      <van-row class="receive-all">
        <van-col span="12">
          <div>567,875,565.59</div>
          <div class="light-txt receive-ins">累計投資</div>
        </van-col>
        <van-col span="12" class="receive-right">
          <div>67,875,56</div>
          <div class="light-txt receive-ins">累計賺取</div>
        </van-col>
      </van-row>
      <!--我的餘額-->
      <div class="remain-con">
        <div>
          <div class="red-txt avail-amount">6850.65</div>
          <div class="light-txt avail-ins">可用餘額(元)</div>
        </div>
        <div class="remain-right">
          <div class="remain-draw">提現</div>
          <div class="remain-divi"></div>
          <van-button type="danger" round size="small" class="remain-charge">充值</van-button>
        </div>
      </div>
      <!--下方應用入口-->
      <van-row class="app-con">
        <van-col span="8" v-for="(it,idx) in bottomApps" :key="idx" class="app-item click-box">
          <van-image v-if="it.flag" :src="'static/img/mine/'+it.flag" class="flag-icon"></van-image>
          <div>
            <van-image :src="'static/img/mine/'+it.icon" class="app-icon"></van-image>
            <div class="app-text light-txt">{{it.title}}</div>
          </div>
        </van-col>
      </van-row>
    </div>
  </div>
</template>

<script>
  export default {
    name: "tab-mine",
    data() {
      return {
        bottomApps: [
          {icon: 'mine_app_icon3.png', flag: '', title: '我的投資',},
          {icon: 'mine_app_icon8.png', flag: '', title: '回款日曆',},
          {icon: 'mine_app_icon2.png', flag: '', title: '投資設置',},
          {icon: 'mine_app_icon6.png', flag: 'mine_app_flag2.png', title: '卡券包',},
          {icon: 'mine_app_icon9.png', flag: '', title: '積分',},
          {icon: 'mine_app_icon5.png', flag: 'mine_app_flag1.png', title: '邀請好友',},
          {icon: 'mine_app_icon4.png', flag: '', title: '我要借款',},
          {icon: 'mine_app_icon7.png', flag: '', title: '關於我們',},
          {icon: 'mine_app_icon1.png', flag: '', title: '聯繫客服',},
        ],
      };
    },
    methods: {
      onMessageClick() {
        this._routePush('MessagePage');
      },
      onSettingsClick() {
        this._routePush('SettingsPage')
      },
    },
  }
</script>

<style scoped lang="scss">
  .app-con {
    margin: 12px 0;
    .app-item {
      border: 1px solid #f7f7f7;
      text-align: center;
      position: relative;
      padding: 24px 0;
      .flag-icon {
        position: absolute;
        right: 0;
        top: 0;
        width: 36px;
        height: 36px;
      }
      .app-text {
        font-size: 14px;
      }
      .app-icon {
        width: 36px;
        height: 36px;
      }
    }
  }

  .remain-con {
    margin-top: 12px;
    background-color: white;
    display: flex;
    justify-content: space-between;
    padding: 14px;
    .avail-amount {
      font-size: 20px;
    }
    .avail-ins {
      margin-top: 4px;
      font-size: 14px;
    }
    .remain-right {
      display: flex;
      align-items: center;
      font-size: 16px;
      .remain-divi {
        width: 1px;
        height: 24px;
        margin: 0 18px;
        background-color: #cccccc;
      }
      .remain-charge {
        height: 24px;
        line-height: 21px;
      }
    }
  }

  .receive-all {
    text-align: center;
    margin-top: 12px;
    background-color: white;
    padding: 16px;
    .receive-right {
      border-left: 1px solid #cccccc;
    }
    .receive-ins {
      font-size: 14px;
      margin-top: 6px;
    }
  }

  .amount-con {
    width: 100%;
    background-color: white;
    text-align: center;
    padding-top: 30px;
    padding-bottom: 20px;
    .amount-ins {
      font-size: 14px;
      margin-top: 10px;
    }
    .amount-txt {
      font-size: 28px;
    }
  }

  .top-nav {
    background-color: white;
    position: fixed;
    height: 50px;
    z-index: 10;
    border-bottom: 1px solid #f7f7f7;
    top: 0;
    left: 0;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    .top-right {
      margin-right: 16px;
    }
    .head-img {
      width: 30px;
      height: 30px;
      border-radius: 40px;
      overflow: hidden;
      margin-left: 16px;
    }
  }
</style>

<template>
  <div>
    <van-nav-bar left-arrow @click-left="_routerBack" :title="$t('settings')" fixed :z-index="10"></van-nav-bar>
    <!--內容區-->
    <div class="nav-con-16">
      <van-cell-group>
        <van-cell :title="$t('version')" icon="info-o" :value="versionName" size="large" @click="onVersionClick">
        </van-cell>
        <van-cell :title="$t('language')" icon="flag-o" :value="$t(langOptions[currentLang])" size="large"
                  @click="onLangClick" is-link>
        </van-cell>
        <van-cell title="Vant文檔" is-link size="large" @click="onVantDocClick"></van-cell>
        <van-cell title="手勢密碼設置" icon="eye-o" size="large" @click="_routePush('GestureCreate')" is-link>
        </van-cell>
      </van-cell-group>
    </div>
    <!--語言彈窗-->
    <van-popup v-model="showLangPop" class="lang-pop">
      <van-radio-group v-model="currentLang" @change="onLangChange">
        <van-cell clickable @click="currentLang = 'en'">
          <van-radio name="en" @click="showLangPop=false">{{$t(langOptions.en)}}</van-radio>
        </van-cell>
        <van-cell clickable @click="currentLang = 'zh'">
          <van-radio name="zh" @click="showLangPop=false">{{$t(langOptions.zh)}}</van-radio>
        </van-cell>
      </van-radio-group>
    </van-popup>
  </div>
</template>

<script>
  import 'vant/lib/radio/index.less'

  export default {
    name: "settings-page",
    data() {
      return {
        versionName: 'V ' + pack.PACK_VERSION,
        currentLang: this.$i18n.locale,
        showLangPop: false,
        langOptions: {
          'en': 'english',
          'zh': 'chinese',
        },
        versionClickTime: 0,
      };
    },
    methods: {
      onVantDocClick() {
        location.href = 'https://youzan.github.io/vant/mobile.html';
      },
      onLangChange(val) {
        this.showLangPop = false;
        window.localStorage.setItem('language', val);
        this.$i18n.reload();
      },
      onLangClick() {
        this.showLangPop = true;
      },
      onVersionClick() {
        this._showToast(pack.PACK_DATE + ' ' + process.env.HOST_ENV);
        this.versionClickTime += 1;
        // 打開測試菜單
        if (this.versionClickTime == 4) {
          this._routePush('TestCasePage');
        }
      },
    }
  }
</script>

<style scoped>
  .lang-pop {
    width: 80%;
    padding: 10px;
    border-radius: 8px;
  }
</style>

這個頁面也挺有意思的,作者大大的代碼很有趣

<template>
  <div>
    <van-nav-bar left-arrow @click-left="_routerBack" title="設置手勢密碼" fixed :z-index="10"></van-nav-bar>
    <div class="align-center navbar-con-16">
      <!--上方小框-->
      <div class="top-small-con">
        <div class="top-small">
          <div v-for="i in 9" :key="i" class="top-dot" :class="{'high-dot':isHighlight(i)}"></div>
        </div>
      </div>
      <!--提示語-->
      <div class="info-tip" :class="{'error-tips': isTipsError}">{{infoTips}}</div>
      <!--密碼輸入-->
      <gesture-lock @input="onLockInput" ref="inputLock" class="main-lock">
      </gesture-lock>
      <div class="reinput-entry" @click="onResetInput" v-if="lastInput.length">
        重新設置手勢密碼
      </div>
    </div>
  </div>
</template>

<script>
  import GestureLock from "../common/GestureLock";

  export default {
    components: {GestureLock},
    name: "gesture-create",
    data() {
      return {
        isTipsError: false,
        infoTips: '',
        lastInput: [],
      };
    },
    computed: {
      isHighlight() {
        return (idx) => {
          if (this.lastInput) {
            for (let ii in this.lastInput) {
              if (this.lastInput[ii] == idx - 1) {
                return true;
              }
            }
          }
        }
      }
    },
    mounted() {
      this.showMessage('請輸入手勢密碼')
    },
    methods: {
      onResetInput() {
        this.lastInput = [];
        this.showMessage('請輸入手勢密碼')
      },
      requestSetGesturePwd(pwd) {
        this._showLoading();
        // 持久化修改
        localStorage.setItem('gesturePassword', pwd);
        setTimeout(() => {
          this._dismissLoading();
          this._showToast('手勢密碼設置成功!');
          this._routerBack();
        }, 1000);
      },
      checkPwdAndUpdate(code) {
        let lastPwd = this.lastInput.join('');
        let pwd = code.join('');
        if (pwd && pwd == lastPwd) {
          this.showMessage('請輸入手勢密碼')
          this.$refs.inputLock.clear();
          this.requestSetGesturePwd(pwd);
        } else {
          this.showLockError('兩次輸入不一致,請重新輸入');
        }
      },
      onLockInput(res) {
        if (res.length < 4) {
          this.showLockError('至少需要連接四個點');
          return
        }
        // 第二次輸入
        if (this.lastInput.length) {
          this.checkPwdAndUpdate(res)
        } else {
          this.lastInput = res;
          this.showMessage('請再重複一遍');
          this.$refs.inputLock.clear();
        }
      },
      showMessage(msg) {
        this.isTipsError = false;
        this.infoTips = msg;
      },
      showLockError(msg) {
        this.isTipsError = true;
        this.infoTips = msg;
        this.$refs.inputLock.showError()
      }
    }
  }
</script>

<style scoped lang="less">
  .reinput-entry {
    color: @blue;
    margin-top: 40px;
    text-decoration: underline;
  }

  .top-small-con {
    display: flex;
    justify-content: center;
    .top-small {
      width: 42px;
      display: flex;
      flex-wrap: wrap;
      .top-dot {
        margin: 2px;
        width: 10px;
        height: 10px;
        background-color: #aaaaaa;
        border-radius: 20px;
        display: block;
      }
      .high-dot {
        background-color: @blue;
      }
    }
  }

  .info-tip {
    margin-top: 20px;
    font-size: 14px;
  }

  .error-tips {
    color: red;
  }

  .main-lock {
    margin: 20px 0;
  }
</style>

代碼看了這麼久,有沒有發現他們好像沒有底部的導航欄
在這裏呢

<template>
  <div>
    <!--緩存的頁面-->
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive" class="main-router-view" v-keep-scroll-position>
      </router-view>
    </keep-alive>
    <!--不緩存的頁面-->
    <router-view v-if="!$route.meta.keepAlive" class="main-router-view">
    </router-view>
    <!--下方的TabBar-->
    <van-tabbar v-model="tabBarSelect">
      <!--TabBar項目-->
      <van-tabbar-item v-for="(item, i) in tabItemList" :key="i" :to="item.to" replace>
        <div class="tab-txt">{{$t(item.name)}}</div>
        <img :src="getTabIconSrc(item, props.active)" slot="icon" slot-scope="props" class="icon-img"/>
      </van-tabbar-item>
    </van-tabbar>
  </div>
</template>

<script>
  export default {
    name: "main-page",
    watch: {
      '$route'() {
        this.checkTabSelection();
      }
    },
    computed: {
      // 獲取圖標資源
      getTabIconSrc() {
        return (item, active) => {
          let img = active ? item.active : item.normal;
          return 'static/img/main/' + img;
        }
      },
    },
    data() {
      return {
        tabBarSelect: 0,
        // Tab欄數據
        tabItemList: [
          {
            active: 'main_tab_3.png',
            normal: 'main_tab_2.png',
            name: 'tab_home',
            to: "home"
          },
          {
            active: 'main_tab_5.png',
            normal: 'main_tab_4.png',
            name: 'tab_products',
            to: "products"
          },
          {
            active: 'main_tab_7.png',
            normal: 'main_tab_6.png',
            name: 'tab_discovery',
            to: "discover"
          },
          {
            active: 'main_tab_1.png',
            normal: 'main_tab_8.png',
            name: 'tab_mine',
            to: "mine"
          },
        ],
      };
    },
    methods: {
      // 看一下tab欄應給高亮哪一個
      checkTabSelection() {
        for (let i = 0; i < this.tabItemList.length; i++) {
          let p = this.tabItemList[i];
          if (this.$route.path.endsWith(p.to)) {
            this.tabBarSelect = i;
          }
        }
      }
    },
    mounted() {
      this.checkTabSelection();
    }
  }
</script>

<style scoped>
  .tab-txt {
    text-align: center;
    margin-top: -2px;
  }

  .main-router-view {
    height: calc(100vh - 50px);
    overflow-y: auto;
    box-sizing: border-box;
    background-color: #f8f8f8;
  }

  .icon-img {
    margin-bottom: -1px;
    height: 25px;
  }
</style>

這個項目很有意思,裏面的東西還有許多有趣的,等着你去發現呢~~~給這個博主大大點贊,不過他的黃色網址差評
看了一下代碼,好像是在這裏配置的

不過作者大大的項目確實寫的很好,所以,贊贊贊 老實說有些點我沒有消化,不過項目很有趣,有些實現的點,還是第一次見呢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章