先说下这个作者大大的项目
运行就跳转到黄色网页了,然后我把网页差掉,接下来就是继续运行,然后就可以打开网页了
先放下作者大大的项目地址,接下来我们看下页面效果
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>
这个项目很有意思,里面的东西还有许多有趣的,等着你去发现呢~~~给这个博主大大点赞,不过他的黄色网址差评
看了一下代码,好像是在这里配置的
不过作者大大的项目确实写的很好,所以,赞赞赞 老实说有些点我没有消化,不过项目很有趣,有些实现的点,还是第一次见呢
来源:oschina
链接:https://my.oschina.net/u/4288740/blog/4299999