Commit f4d6e876 authored by ziyu's avatar ziyu

feat: 合并master

parents 007efc5c cb939d61
...@@ -6248,11 +6248,6 @@ ...@@ -6248,11 +6248,6 @@
"builtins": "^1.0.3" "builtins": "^1.0.3"
} }
}, },
"vant-weapp": {
"version": "0.5.28",
"resolved": "http://npmprivate.quantgroups.com/vant-weapp/-/vant-weapp-0.5.28.tgz",
"integrity": "sha512-GAJ2PTLuhXHWpAD5B7DdRQdkEFMdjdduuMzKkThUjIiQ63ESnaJvIEUbW3RgiUNNV7PYXwhOFOd6woR/JsTFLA=="
},
"verror": { "verror": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "http://npmprivate.quantgroups.com/verror/-/verror-1.10.0.tgz", "resolved": "http://npmprivate.quantgroups.com/verror/-/verror-1.10.0.tgz",
......
...@@ -18,8 +18,7 @@ ...@@ -18,8 +18,7 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@wepy/core": "^2.0.0-alpha.16", "@wepy/core": "^2.0.0-alpha.16",
"@wepy/x": "^2.0.2", "@wepy/x": "^2.0.2"
"vant-weapp": "^0.5.28"
}, },
"devDependencies": { "devDependencies": {
"@wepy/cli": "^2.0.0-alpha.28", "@wepy/cli": "^2.0.0-alpha.28",
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
</style> </style>
<script> <script>
import wepy from '@wepy/core'; import wepy from '@wepy/core';
import eventHub from './common/eventHub'; import http from './common/wxRequest';
import vuex from '@wepy/x'; import vuex from '@wepy/x';
wepy.use(vuex); wepy.use(vuex);
...@@ -18,33 +18,45 @@ wepy.app({ ...@@ -18,33 +18,45 @@ wepy.app({
// 同时存在 Page hook 和 App hook 时,优先执行 Page hook,返回值再交由 App hook 处 // 同时存在 Page hook 和 App hook 时,优先执行 Page hook,返回值再交由 App hook 处
}, },
globalData: { globalData: {
statusBarHeight:'' statusBarHeight: ''
}, },
onLaunch() { onLaunch() {
// this.$options.globalData.info = '333';
let that = this; let that = this;
wx.getSystemInfo({ wx.getSystemInfo({
success: function (res) { success: function (res) {
that.$options.globalData.statusBarHeight = res.statusBarHeight that.$options.globalData.statusBarHeight = res.statusBarHeight;
} }
}); });
if (!wx.getStorageSync('openId')) {
wx.login({
success (res) {
if (res.code) {
// 发起网络请求,告诉后端
http.post('/');
wx.setStorageSync('wxCode', res.code);
} else {
console.log('登录失败!' + res.errMsg);
}
}
});
}
wx.checkSession({ wx.checkSession({
success () { success () {
console.log('已登录') console.log('已登录');
//session_key 未过期,并且在本生命周期一直有效 // session_key 未过期,并且在本生命周期一直有效
}, },
fail () { fail () {
// session_key 已经失效,需要重新执行登录流程 // session_key 已经失效,需要重新执行登录流程
wx.login({ wx.login({
success (res) { success (res) {
if (res.code) { if (res.code) {
//发起网络请求,告诉后端 // 发起网络请求,告诉后端
wx.setStorageSync('wxCode',res.code); wx.setStorageSync('wxCode', res.code);
} else { } else {
console.log('登录失败!' + res.errMsg) console.log('登录失败!' + res.errMsg);
} }
} }
}) });
} }
}); });
wx.setStorageSync('onNetworkStatusChange', true); wx.setStorageSync('onNetworkStatusChange', true);
...@@ -63,7 +75,8 @@ wepy.app({ ...@@ -63,7 +75,8 @@ wepy.app({
'pages/prize', 'pages/prize',
'pages/myraffles', 'pages/myraffles',
'pages/help', 'pages/help',
'pages/morehelp' 'pages/morehelp',
'pages/awards',
], ],
window: { window: {
backgroundTextStyle: 'light', backgroundTextStyle: 'light',
......
import http from './wxRequest';
module.exports = {
login() {
return http.post();
}
};
import wepy from 'wepy'; import wepy from '@wepy/core';
const baseUrl = 'localhost:8000';
const request = (url, options) => {
const defaultOptions = {
method: 'post',
header: { 'content-type': 'applicction/x-www-form-urlencoded' }
};
options = { ...defaultOptions, ...options };
url = baseUrl + url;
const wxRequest = async (params = {}, url) => {
console.log('wxRequest', params);
const isConnected = wx.getStorageSync('onNetworkStatusChange'); const isConnected = wx.getStorageSync('onNetworkStatusChange');
if (!isConnected) { if (!isConnected) {
wx.showToast({ wx.showToast({
...@@ -11,20 +19,49 @@ const wxRequest = async (params = {}, url) => { ...@@ -11,20 +19,49 @@ const wxRequest = async (params = {}, url) => {
}); });
return; return;
} }
// tip.loading()
let data = params.query || {}; const promise = new Promise((resolve, reject) => {
const header = params.header || {}; /*wepy.request({
let res = await wepy.request({
url: url, url: url,
method: params.method || 'GET', data: options.data,
data: data, method: options.method,
header: header header: options.header,
success: res => {
if (res.statusCode == 200) {
if (res.data.code == '2000') {
resolve(res.data.data);
}
}
reject(res);
},
fail: res => {
reject(res);
}
});*/
}); });
// tip.loaded() return promise;
console.log('wxRequest', res); };
return res;
const post = (url, data, header) => {
const options = {
method: 'post',
data,
header
};
if (!header) delete options.header;
return request(url, options);
};
const get = (url, data) => {
const options = {
method: 'get',
data
};
return request(url, options);
}; };
module.exports = { module.exports = {
wxRequest post: post,
get: get,
request
}; };
<template> <template>
<div class="network-container"> <div class="network-container" :class="{'show': show}">
<div class="network-wrapper"> <div class="network-wrapper">
<span class="network-text">网络状况不佳,请刷新重试</span> <span class="network-text">网络状况不佳,请刷新重试</span>
<van-button custom-class="network-button" round type="info" @tap="setIsConnected">刷新</van-button> <van-button custom-class="network-button" round type="info" @tap="setIsConnected">刷新</van-button>
...@@ -12,9 +12,15 @@ ...@@ -12,9 +12,15 @@
import store from '../../store'; import store from '../../store';
wepy.component({ wepy.component({
data: {
show: false
},
store, store,
methods: { methods: {
...mapActions(['setIsConnected']) ...mapActions(['setIsConnected'])
},
created() {
this.show = true;
} }
}); });
</script> </script>
...@@ -27,7 +33,7 @@ ...@@ -27,7 +33,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
z-index: 10; z-index: -1;
.network-wrapper { .network-wrapper {
display: flex; display: flex;
justify-content: center; justify-content: center;
...@@ -35,19 +41,22 @@ ...@@ -35,19 +41,22 @@
flex-direction: column; flex-direction: column;
.network-text { .network-text {
color: #AAA; color: #AAA;
font-size: 12px; font-size: 24rpx;
} }
.network-button { .network-button {
margin-top: 10px; margin-top: 20rpx;
width: 90px; width: 180rpx;
font-size: 12px; font-size: 24rpx;
height: 28px; height: 56rpx;
line-height: 28px; line-height: 56rpx;
background: #FF6600; background: #FF6600;
border-color: #FF6600; border-color: #FF6600;
} }
} }
} }
.show {
z-index: 10;
}
</style> </style>
<config> <config>
{ {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<div class="gift" @tap="click"></div> <div class="gift" @tap="click"></div>
</div> </div>
<div class="chest-open" :class="{'show': show, 'blur': blur}"> <div class="chest-open" :class="{'show': show, 'blur': blur}">
<div class="mod-chest-cont"> <!-- <div class="mod-chest-cont">
<div class="content"> <div class="content">
<div>您可真幸运~</div> <div>您可真幸运~</div>
<image class="gift-image" src="/static/images/peo2.jpg"></image> <image class="gift-image" src="/static/images/peo2.jpg"></image>
...@@ -16,6 +16,32 @@ ...@@ -16,6 +16,32 @@
<button class="chest-btn" @tap="go">再去挑战</button> <button class="chest-btn" @tap="go">再去挑战</button>
<button class="chest-btn" @tap="go">查看</button> <button class="chest-btn" @tap="go">查看</button>
</div> </div>
</div> -->
<div class="dialog" :class="{'fail-dialog': !isWin}">
<div class="star">
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
</div>
<div class="fail-content" v-if="!isWin">
<div class="des">很遗憾,未中奖</div>
<div class="des">感谢您的参与!</div>
</div>
<div class="success-content" v-if="isWin">
<div class="des">恭喜您中奖!</div>
<image class="image" src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1590418868788&di=5f7d14c51ea4d224c68d2f84b528c6f0&imgtype=0&src=http%3A%2F%2Fimg2.imgtn.bdimg.com%2Fit%2Fu%3D2413142997%2C2945797382%26fm%3D214%26gp%3D0.jpg"></image>
<div class="name">勃垦地进口红酒精装版</div>
</div>
<div class="dialog-footer">
<button class="btn" @tap="go">立即查看</button>
<button class="btn" @tap="go">再次挑战</button>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -25,8 +51,11 @@ ...@@ -25,8 +51,11 @@
import wepy from '@wepy/core'; import wepy from '@wepy/core';
wepy.component({ wepy.component({
props: {
isWin: false
},
data: { data: {
showAnimation: false, showAnimation: true,
showChest: true, showChest: true,
shake: false, shake: false,
show: false, show: false,
...@@ -39,6 +68,16 @@ ...@@ -39,6 +68,16 @@
setTimeout(() => { setTimeout(() => {
this.opened = true; this.opened = true;
setTimeout(() => { setTimeout(() => {
const innerAudioContext = wx.createInnerAudioContext();
innerAudioContext.autoplay = true;
innerAudioContext.src = '/static/audio/winning.mp3';
innerAudioContext.onPlay(() => {
console.log('开始播放');
});
innerAudioContext.onError((res) => {
console.log(res.errMsg);
console.log(res.errCode);
});
this.showChest = false; this.showChest = false;
this.blur = true; this.blur = true;
this.show = true; this.show = true;
...@@ -51,10 +90,10 @@ ...@@ -51,10 +90,10 @@
} }
}, },
created() { created() {
setTimeout(() => { // setTimeout(() => {
this.showAnimation = true; this.showAnimation = true;
this.click(); this.click();
},1000); // }, 1000);
} }
}); });
</script> </script>
...@@ -131,6 +170,243 @@ ...@@ -131,6 +170,243 @@
top: 200rpx; top: 200rpx;
display: flex; display: flex;
justify-content: center; justify-content: center;
box-sizing: border-box;
.dialog {
position: absolute;
top:-460rpx;
width: 500rpx;
height: 500rpx;
border-radius: 20rpx;
color: #fff;
background: linear-gradient(#FF5D15 5%, #FDA13E 60%, rgba(255, 255, 255, 0.8) 100%),
;
padding: 39rpx 40rpx 0rpx 40rpx;
z-index: 10;
.star {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
.star-image {
&:nth-child(1) {
position: absolute;
top: 120rpx;
left: 32rpx;
width: 86rpx;
height: 86rpx;
}
&:nth-child(2) {
position: absolute;
top: 70rpx;
left: 121rpx;
width: 55rpx;
height: 55rpx;
transform: rotateZ(20deg);
filter: blur(5rpx);
}
&:nth-child(3) {
position: absolute;
top: 110rpx;
left: 349rpx;
width: 58rpx;
height: 58rpx;
transform: rotateZ(30deg);
filter: blur(3rpx);
}
&:nth-child(4) {
position: absolute;
top: 89rpx;
left: 471rpx;
width: 50rpx;
height: 50rpx;
transform: rotateZ(15deg);
filter: blur(5rpx);
}
&:nth-child(5) {
position: absolute;
top: 250rpx;
left: 14rpx;
width: 50rpx;
height: 50rpx;
transform: rotateZ(25deg);
filter: blur(6rpx);
}
&:nth-child(6) {
position: absolute;
top: 223rpx;
left: 145rpx;
width: 57rpx;
height: 57rpx;
transform: rotateZ(23deg);
filter: blur(3rpx);
}
&:nth-child(7) {
position: absolute;
top: 223rpx;
left: 391rpx;
width: 68rpx;
height: 68rpx;
transform: rotateZ(20deg);
filter: blur(2rpx);
}
&:nth-child(8) {
position: absolute;
top: 318rpx;
left: 494rpx;
width: 51rpx;
height: 51rpx;
transform: rotateZ(15deg);
filter: blur(5rpx);
}
}
}
.fail-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 235rpx;
.des {
font-size: 40rpx;
z-index: 11;
}
}
.success-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.des {
font-size: 40rpx;
}
.image {
width: 200rpx;
height: 200rpx;
border-radius: 50%;
margin: 22rpx auto;
z-index: 11;
}
.name {
width: 200rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 24rpx;
}
}
.dialog-footer {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 158rpx;
z-index: 11;
.btn {
font-size: 24rpx;
width: 160rpx;
height: 70rpx;
line-height: 70rpx;
border: 1rpx solid #FF5D15;
z-index: 11;
border-radius: 10rpx;
&:nth-child(1) {
background: #fff;
color: #FF5D15;
}
&:nth-child(2) {
background: #FF5D15;
color: #fff;
}
}
}
}
.fail-dialog {
height: 400rpx;
top: -370rpx;
.star {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
.star-image {
&:nth-child(1) {
position: absolute;
top: 120rpx;
left: 32rpx;
width: 86rpx;
height: 86rpx;
}
&:nth-child(2) {
position: absolute;
top: 70rpx;
left: 121rpx;
width: 55rpx;
height: 55rpx;
transform: rotateZ(20deg);
filter: blur(5rpx);
}
&:nth-child(3) {
position: absolute;
top: 33rpx;
left: 349rpx;
width: 58rpx;
height: 58rpx;
transform: rotateZ(16deg);
filter: blur(3rpx);
}
&:nth-child(4) {
position: absolute;
top: 89rpx;
left: 471rpx;
width: 50rpx;
height: 50rpx;
transform: rotateZ(15deg);
filter: blur(5rpx);
}
&:nth-child(5) {
position: absolute;
top: 250rpx;
left: 14rpx;
width: 50rpx;
height: 50rpx;
transform: rotateZ(25deg);
filter: blur(6rpx);
}
&:nth-child(6) {
position: absolute;
top: 223rpx;
left: 145rpx;
width: 57rpx;
height: 57rpx;
transform: rotateZ(23deg);
filter: blur(5rpx);
}
&:nth-child(7) {
position: absolute;
top: 223rpx;
left: 391rpx;
width: 68rpx;
height: 68rpx;
transform: rotateZ(20deg);
filter: blur(2rpx);
}
&:nth-child(8) {
position: absolute;
top: 318rpx;
left: 494rpx;
width: 51rpx;
height: 51rpx;
transform: rotateZ(15deg);
filter: blur(5rpx);
}
}
}
}
.mod-chest-cont { .mod-chest-cont {
position: absolute; position: absolute;
background: url('http://activitystatic.xyqb.com/open-bg-top.png') center top no-repeat, url('http://activitystatic.xyqb.com/open-bg-bottom.png') center bottom no-repeat; background: url('http://activitystatic.xyqb.com/open-bg-top.png') center top no-repeat, url('http://activitystatic.xyqb.com/open-bg-bottom.png') center bottom no-repeat;
...@@ -193,6 +469,11 @@ ...@@ -193,6 +469,11 @@
-webkit-animation:move2 .5s .0s linear; -webkit-animation:move2 .5s .0s linear;
-webkit-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards;
} }
.dialog {
-webkit-animation:move2 .5s .0s linear;
-webkit-animation-fill-mode: forwards;
}
} }
.blur{ .blur{
&:after { &:after {
......
<template>
<div v-if="show" class="{{hide ? 'popup-container popup-container_hide' : 'popup-container popup-container_show'}}" @tap="hideMenu" >
<div style="{{popupStyle}}" class="{{hide ? 'popup-wrapper popup-wrapper_hide': 'popup-wrapper popup-wrapper_show'}}">
<div class="popup-item" v-for="item in menus" @tap.stop="goNextPage(item.path)">
<image class="image" :src="item.img"></image>
<span class="desc">{{item.title}}</span>
</div>
</div>
</div>
</template>
<script>
import wepy from '@wepy/core';
wepy.component({
props: {
showMenus: {
type: Boolean,
default: false
}
},
data: {
menus: [
{ img: '/static/images/awards@2x.png', title: '我的抽奖', path: '/pages/awards' },
{ img: '/static/images/feedback@2x.png', title: '规则与帮助', path: '/pages/feedback' },
{ img: '/static/images/help@2x.png', title: '问题反馈', path: '/pages/help' }
],
show: false,
popupStyle: ''
},
watch: {
showMenus(v) {
if (!v) {
setTimeout(() => {
this.show = false;
}, 300);
} else {
this.show = true;
}
}
},
computed: {
hide() {
return !this.showMenus;
}
},
methods: {
hideMenu: function() {
this.$emit('showMenu', false);
},
goNextPage: function(path) {
this.$emit('showMenu', false);
wx.navigateTo({
url: path
});
}
},
created() {
let statusHeight = this.$app.$options.globalData.statusBarHeight || '';
statusHeight && (this.popupStyle = 'top:' + (statusHeight + 56) + 'px');
}
});
</script>
<style lang="less">
.popup-container {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
z-index: 9;
// animation: menuEnter .3s linear forwards;
.popup-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
width: 350rpx;
height: 114rpx;
position: absolute;
left: 20rpx;
top: 155rpx;
background: #fff;
border-radius: 10rpx;
padding: 10rpx 19rpx;
box-sizing: border-box;
// animation: menuShow .3s linear forwards;
&:before {
position: absolute;
top: -29rpx;
left: 35rpx;
content: "";
width: 0;
height: 0;
border-top: 0;
border-left: 15rpx solid transparent;
border-right: 15rpx solid transparent;
border-bottom: 30rpx solid #fff;
}
.popup-item {
display: flex;
flex-direction: column;
align-items: center;
.image {
width: 50rpx;
height: 50rpx;
}
.desc {
color: #FF5D15;
font-size: 20rpx;
margin-top: 9rpx
}
}
}
.popup-wrapper_show{
animation: menuShow .3s linear forwards;
}
.popup-wrapper_hide {
animation: menuHides .3s linear forwards;
}
}
.popup-container_hide {
animation: menuLeave .3s linear forwards;
}
.popup-container_show {
animation: menuEnter .3s linear forwards;
}
@keyframes menuLeave {
from { background: rgba(0, 0, 0, 0.7); }
to { background: rgba(0, 0, 0, 0); }
}
@keyframes menuHides {
0% {
transform: none;
opacity: 1;
}
100% {
transform: translate3d(0, -5%, 0);
opacity: 0;
}
}
@keyframes menuEnter {
from { background: rgba(0, 0, 0, 0); }
to { background: rgba(0, 0, 0, 0.7); }
}
@keyframes menuShow {
0% {
transform: translate3d(0, -5%, 0);
opacity: 0;
}
100% {
transform: none;
opacity: 1;
}
}
</style>
<template>
<div class="share-container" @tap="hideMenu" >
<div class="dialog">
<div class="star">
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
<image class="star-image" src="/static/images/star@2x.png"></image>
</div>
<div class="gold">
<image class="gold-image" src="/static/images/gold-bg@2x.png"></image>
<image class="gold-image" src="/static/images/gold-bg@2x.png"></image>
<image class="gold-image" src="/static/images/gold-bg@2x.png"></image>
<image class="gold-image" src="/static/images/gold-bg@2x.png"></image>
</div>
<div class="content">
<div class="des">恭喜您!</div>
<image class="image" src="/static/images/gold@2x.png"></image>
<div class="info">通过邀请以下好友,您获得15克币</div>
<div class="user">
<image class="user-img" src="/static/images/test1.jpg"></image>
<image class="user-img" src="/static/images/test1.jpg"></image>
<image class="user-img" src="/static/images/test1.jpg"></image>
</div>
</div>
<div class="dialog-footer">
<button class="btn" @tap="go">立即领取</button>
</div>
</div>
</div>
</template>
<script>
import wepy from '@wepy/core';
wepy.component({
props: {
showMenus: {
type: Boolean,
default: false
}
},
data: {
menus: [
{ img: '/static/images/awards@2x.png', title: '我的抽奖', path: '/pages/awards' },
{ img: '/static/images/feedback@2x.png', title: '规则与帮助', path: '/pages/feedback' },
{ img: '/static/images/help@2x.png', title: '问题反馈', path: '/pages/help' }
],
show: false,
popupStyle: ''
},
watch: {
showMenus(v) {
if (!v) {
setTimeout(() => {
this.show = false;
}, 300);
} else {
this.show = true;
}
}
},
computed: {
hide() {
return !this.showMenus;
}
},
methods: {
getAwards: function() {
this.show = false;
}
}
});
</script>
<style lang="less">
.share-container {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
z-index: 10;
display: flex;
justify-content: center;
align-items: center;
.dialog {
position: relative;
width: 530rpx;
height: 530rpx;
border-radius: 20rpx;
color: #fff;
background: linear-gradient(#E6401F, #FDA13E),
;
padding: 39rpx 40rpx 0rpx 40rpx;
z-index: 10;
.star {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: url('http://activitystatic.xyqb.com/light-1@2x.png') 0% 0%/contain no-repeat;
.star-image {
&:nth-child(1) {
position: absolute;
top: 120rpx;
left: 32rpx;
width: 86rpx;
height: 86rpx;
}
&:nth-child(2) {
position: absolute;
top: 70rpx;
left: 121rpx;
width: 55rpx;
height: 55rpx;
transform: rotateZ(20deg);
filter: blur(5rpx);
}
&:nth-child(3) {
position: absolute;
top: 110rpx;
left: 349rpx;
width: 58rpx;
height: 58rpx;
transform: rotateZ(30deg);
filter: blur(3rpx);
}
&:nth-child(4) {
position: absolute;
top: 89rpx;
left: 471rpx;
width: 50rpx;
height: 50rpx;
transform: rotateZ(15deg);
filter: blur(5rpx);
}
&:nth-child(5) {
position: absolute;
top: 250rpx;
left: 14rpx;
width: 50rpx;
height: 50rpx;
transform: rotateZ(25deg);
filter: blur(6rpx);
}
&:nth-child(6) {
position: absolute;
top: 223rpx;
left: 145rpx;
width: 57rpx;
height: 57rpx;
transform: rotateZ(23deg);
filter: blur(3rpx);
}
&:nth-child(7) {
position: absolute;
top: 223rpx;
left: 391rpx;
width: 68rpx;
height: 68rpx;
transform: rotateZ(20deg);
filter: blur(2rpx);
}
&:nth-child(8) {
position: absolute;
top: 318rpx;
left: 494rpx;
width: 51rpx;
height: 51rpx;
transform: rotateZ(15deg);
filter: blur(5rpx);
}
}
}
.gold {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
.gold-image {
&:nth-child(1) {
position: absolute;
top: 227rpx;
left: -51rpx;
width: 78rpx;
height: 78rpx;
}
&:nth-child(2) {
position: absolute;
top: -38rpx;
left: 180rpx;
width: 56rpx;
height: 56rpx;
filter: blur(3rpx);
}
&:nth-child(3) {
position: absolute;
top: 85rpx;
left: 580rpx;
width: 86rpx;
height: 86rpx;
filter: blur(2px);
}
&:nth-child(4) {
position: absolute;
top: 380rpx;
left: 560rpx;
width: 98rpx;
height: 98rpx;
filter: blur(2rpx);
}
}
}
.content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.des {
font-size: 40rpx;
}
.image {
width: 150rpx;
height: 164rpx;
margin: 29rpx auto;
z-index: 11;
}
.info {
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 28rpx;
text-align: center;
}
.user {
height: 84rpx;
width: 210rpx;
line-height: 84rpx;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
.user-img {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
}
&:after {
content: '...';
position: absolute;
bottom: -5rpx;
right: -46rpx;
}
}
}
.dialog-footer {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 120rpx;
z-index: 11;
.btn {
font-size: 30rpx;
width: 200rpx;
height: 70rpx;
line-height: 70rpx;
z-index: 11;
border-radius: 10rpx;
background: #FF5D15;
color: #FFF;
&:before {
content: '';
width: 73rpx;
height: 43rpx;
position: absolute;
background: url('http://activitystatic.xyqb.com/btn-shadow@2x.png') center center/contain no-repeat;
top: 3rpx;
left: 4rpx;
};
}
}
}
}
</style>
<template> <template>
<div class="icon-container"> <div style="{{containerStyle}}" class="icon-container">
<star-animation v-if='flyAnimation'></star-animation>
<div class="sign" v-if="type === 'sign'" @tap="signIn"> <div class="sign" v-if="type === 'sign'" @tap="signIn">
<image class="sign-in" :src="signNotCompletedUrl" v-if="!signComplete" :class="{'jump': !sign, 'fly': sign}" ></image> <image class="sign-in" :src="signNotCompletedUrl" v-if="!signComplete" :class="{'jump': !sign, 'fly': sign}" ></image>
<image class="sign-comlete" :src="signCompletedUrl" v-if="sign"></image> <image class="sign-comlete" :src="signCompletedUrl" v-if="sign"></image>
...@@ -10,7 +11,7 @@ ...@@ -10,7 +11,7 @@
<div v-if="type === 'gold'" class="gold"> <div v-if="type === 'gold'" class="gold">
<div class="add-gold" v-if="addGold"> <div class="add-gold" v-if="addGold">
<image class="add-gold-image" :src="addGoldUrl"></image> <image class="add-gold-image" :src="addGoldUrl"></image>
<span class="add-gold-num">+1</span> <span class="add-gold-num">+10</span>
</div> </div>
<div class="show-gold" @tap="showAnimation"> <div class="show-gold" @tap="showAnimation">
<div class="sunshine" v-if="addsunshine"></div> <div class="sunshine" v-if="addsunshine"></div>
...@@ -24,6 +25,7 @@ ...@@ -24,6 +25,7 @@
<button open-type="share" plain="true" class="share-button"> <button open-type="share" plain="true" class="share-button">
<image class="share-image" :src="shareUrl"></image> <image class="share-image" :src="shareUrl"></image>
</button> </button>
<span class="title">{{des}}</span>
</div> </div>
<div v-if="type === 'lottery'" class="lottery"> <div v-if="type === 'lottery'" class="lottery">
<image class="lottery-image" :src="lotteryUrl"></image> <image class="lottery-image" :src="lotteryUrl"></image>
...@@ -60,7 +62,9 @@ ...@@ -60,7 +62,9 @@
signNotCompletedUrl: '/static/images/sign@2x.png', signNotCompletedUrl: '/static/images/sign@2x.png',
signCompletedUrl: '/static/images/sign-completed@2x-70_70px.png', signCompletedUrl: '/static/images/sign-completed@2x-70_70px.png',
shareUrl: '/static/images/share@2x.png', shareUrl: '/static/images/share@2x.png',
lotteryUrl: '/static/images/lottery@2x.png' lotteryUrl: '/static/images/lottery@2x.png',
containerStyle: '',
flyAnimation: false
}, },
props: { props: {
title: '', title: '',
...@@ -125,14 +129,16 @@ ...@@ -125,14 +129,16 @@
}, },
sign(v) { sign(v) {
this.signComplete = false; this.signComplete = false;
this.flyAnimation = false;
console.log(v, this.signComplete); console.log(v, this.signComplete);
if (!v) { if (!v) {
timeout = null; timeout = null;
} else { } else {
timeout = setTimeout(() => { timeout = setTimeout(() => {
this.signComplete = true; this.signComplete = true;
this.flyAnimation = true;
console.log('signComplete'); console.log('signComplete');
}, 1300); }, 1100);
} }
} }
}, },
...@@ -149,7 +155,9 @@ ...@@ -149,7 +155,9 @@
} }
}, },
created() { created() {
console.log(this.type); let statusHeight = this.$app.$options.globalData.statusBarHeight || '';
statusHeight && (this.containerStyle = 'position:relative; top:' + statusHeight + 'px');
console.log(this.type, this.$app.$options.globalData.statusBarHeight, this.containerStyle);
} }
}); });
</script> </script>
...@@ -158,8 +166,8 @@ ...@@ -158,8 +166,8 @@
.lottery { .lottery {
position: absolute; position: absolute;
top: 513rpx; top: 469rpx;
right: 30rpx; right: 32rpx;
.lottery-image { .lottery-image {
display: flex; display: flex;
width: 78rpx; width: 78rpx;
...@@ -176,8 +184,8 @@ ...@@ -176,8 +184,8 @@
.share { .share {
position: absolute; position: absolute;
top: 679rpx; top: 635rpx;
right: 33rpx; right: 32rpx;
.share-button { .share-button {
width: 78rpx; width: 78rpx;
height: 70rpx; height: 70rpx;
...@@ -188,11 +196,18 @@ ...@@ -188,11 +196,18 @@
height: 70rpx; height: 70rpx;
} }
} }
.title {
width: 100%;
text-align: center;
display: block;
color: #fff;
font-size: 22rpx;
}
} }
.sign { .sign {
position: absolute; position: absolute;
top: 356rpx; top: 312rpx;
right: 32rpx; right: 32rpx;
width: 78rpx; width: 78rpx;
height: 78rpx; height: 78rpx;
...@@ -213,7 +228,7 @@ ...@@ -213,7 +228,7 @@
animation: jump 1.2s infinite ease; animation: jump 1.2s infinite ease;
} }
.fly { .fly {
animation: fly1 1.2s forwards linear; animation: fly1 1s forwards linear;
} }
.sign-shine { .sign-shine {
overflow: hidden; overflow: hidden;
...@@ -247,7 +262,7 @@ ...@@ -247,7 +262,7 @@
top: 65rpx; top: 65rpx;
border-radius: 50%; border-radius: 50%;
z-index: -1; z-index: -1;
animation: swift 1.2s infinite ease; animation: swift 1s infinite ease;
} }
.title { .title {
...@@ -318,8 +333,8 @@ ...@@ -318,8 +333,8 @@
.gold { .gold {
position: absolute; position: absolute;
top: 270rpx; top: 130rpx;
left: 39rpx; left: 40rpx;
.add-gold{ .add-gold{
position: absolute; position: absolute;
display: flex; display: flex;
...@@ -329,19 +344,21 @@ ...@@ -329,19 +344,21 @@
// transform: translateY(-50rpx); // transform: translateY(-50rpx);
animation:addGold .6s ease-in forwards; animation:addGold .6s ease-in forwards;
.add-gold-image { .add-gold-image {
width: 35rpx; width: 20rpx;
height: 35rpx; height: 20rpx;
vertical-align: middle;
animation:addGoldRotate .6s linear infinite; animation:addGoldRotate .6s linear infinite;
} }
.add-gold-num { .add-gold-num {
color: #fff; color: #fff;
font-size: 24rpx; font-size: 16rpx;
vertical-align: middle;
} }
} }
@keyframes addGold { @keyframes addGold {
0% { transform: translateY(-90rpx);} 0% { transform: translateY(-45rpx);}
99% { transform: translateY(-30rpx);opacity: 1;} 99% { transform: translateY(-20rpx);opacity: 1;}
100% { opacity: 0; } 100% { opacity: 0; }
} }
...@@ -401,7 +418,8 @@ ...@@ -401,7 +418,8 @@
<config> <config>
{ {
usingComponents: { usingComponents: {
'van-icon': '~@/components/vant/icon/index' 'van-icon': '~@/components/vant/icon/index',
'star-animation': '~@/components/custom/starAnimation'
} }
} }
</config> </config>
<template> <template>
<div class="loading-container"> <!-- <div class="loading-container"> -->
<!-- <van-loading size="24px" vertical>加载中...</van-loading> --> <!-- <van-loading size="24px" vertical>加载中...</van-loading> -->
<div class="loader"> <div class="meteor">
<div class="face"> <div class="star"></div>
<div class="circle"></div>
</div>
</div>
</div> </div>
<!-- </div> -->
</template> </template>
<script> <script>
import wepy from '@wepy/core'; import wepy from '@wepy/core';
wepy.component({ wepy.component({
methods: {
onShareAppMessage: function(res) {
if (res.from === 'button') {
console.log('onShareAppMessage1', res.target);
}
}
}
}); });
</script> </script>
<style lang="less"> <style lang="less">
.loading-container { // .loading-container {
// position: absolute;
// width: 100%;
// height: 100%;
// display: flex;
// justify-content: center;
// align-items: center;
// z-index: 1;
.meteor {
position: absolute; position: absolute;
width: 100%; top: 153rpx;
height: 100%; left: 94rpx;
background: grey; width: calc(100% - 170rpx);;
display: flex; height: 0;
justify-content: center; // border: 2rpx solid #000;
align-items: center; z-index: 10;
z-index: 1; transform: rotateZ(-2deg)
.loader {
width: 20em;
height: 20em;
font-size: 10px;
position: relative;
display: flex;
justify-content: center;
align-items: center;
.face {
position: absolute;
border-radius: 50%;
border-style: solid;
animation: animate 3s linear infinite;
&:nth-child(1) {
width: 100%;
height: 100%;
color: black;
border-color: currentColor transparent transparent currentColor;
border-width: 0.2em 0.2em 0 0;
--deg: -45deg;
animation-direction: normal;
} }
.circle { .star {
position: absolute; position: absolute;
width: 50%; left: -3rpx;
height: 0.1em; // bottom: -220rpx;
top: 50%; top: -4rpx;
left: 50%; // left: -43%;
background-color: transparent; height: 10rpx;
transform: rotate(var(--deg)); width: 150rpx;
transform-origin: left; background: linear-gradient(-45deg,rgba(255,255,255,0),yellow);
&::before { transform: translateX(605rpx);
// background: -webkit-linear-gradient(-45deg,rgba(255,255,255,0),yellow);
/*此处为下一步的添加动画*/
// -webkit-animation: tail 1s ease-in forwards, shooting 1s ease-in forwards;
// -o-animation: tail 1s ease-in forwards, shooting 1s ease-in forwards;
animation: tail .6s ease-in forwards, shooting .6s ease-in forwards;
}
.star::before{
content: "";
position: absolute; position: absolute;
top: -0.5em; top: -29rpx;
right: -0.5em; left: -52rpx;
content: ''; width: 78rpx;
width: 1em; height: 78rpx;
height: 1em; // top: calc(100% - 1px);
background-color: currentColor; // left: 100%;
border-radius: 50%; background: url('http://activitystatic.xyqb.com/sign@2x.png') 0 0/contain no-repeat;
box-shadow: 0 0 2em, // background: -webkit-linear-gradient(45deg,rgba(255,255,255,0),yellow,rgba(255,255,255,0));
0 0 4em, /*此处为下一步的添加动画*/
0 0 6em, // -webkit-animation: shining 3s ease-in-out infinite;
0 0 8em, // -o-animation: shining 3s ease-in-out infinite;
0 0 10em, animation: shining .6s ease-in-out forwards;
0 0 0.5em rgba(255, 255, 0, 0.1);
} }
.star:before {
@keyframes animate { transform: rotateZ(-2deg);
to { // transform: -webkit-translateX(-50%) -webkit-rotateZ(-45deg);
transform: rotate(1turn);
} }
.star:after {
// transform: translateX(-50%) rotateZ(45deg);
// transform: -webkit-translateX(-50%) -webkit-rotateZ(45deg);
}
// @-webkit-keyframes shining {
// 0% {width: 0;}
// 50% {width: 30px;}
// 100% {width: 0;}
// }
@keyframes shining {
0% {transform: scale(1);}
// 50% {transform: scale(0.8);}
99% {transform: scale(0.3);}
100% {transform: scale(0);}
} }
// @-webkit-keyframes tail {
// 0% {width: 0;}
// 30% {width: 50px;}
// 100% {width: 0;}
// }
@keyframes tail {
0% {width: 0;}
10% {width: 0;}
50% {width: 150rpx;}
65% {width: 50rpx;}
80% {width: 150rpx;}
100% {width: 0;}
} }
// @-webkit-keyframes shooting {
// 0% {
// -webkit-transform: translateX(0);
// transform: translateX(0);
// }
// 100% {
// -webkit-transform: translateX(350px);
// transform: translateX(350px);
// }
// }
@keyframes shooting {
0% {
// -webkit-transform: translateX(0);
transform: translateX(605rpx);
} }
100% {
// -webkit-transform: translateX(350px);
transform: translateX(30rpx);
} }
} }
// }
</style> </style>
<config> <config>
{ {
......
<template>
<!-- <div class="loading-container"> -->
<!-- <van-loading size="24px" vertical>加载中...</van-loading> -->
<div class="meteor">
<div class="star"></div>
</div>
<!-- </div> -->
</template>
<script>
import wepy from '@wepy/core';
wepy.component({
methods: {
onShareAppMessage: function(res) {
if (res.from === 'button') {
console.log('onShareAppMessage1', res.target);
}
}
}
});
</script>
<style lang="less">
// .loading-container {
// position: absolute;
// width: 100%;
// height: 100%;
// display: flex;
// justify-content: center;
// align-items: center;
// z-index: 1;
.meteor {
position: fixed;
top: 247rpx;
left: 94rpx;
width: calc(100% - 170rpx);;
height: 0;
// border: 2rpx solid #000;
z-index: 10;
transform: rotateZ(-10deg)
}
.star {
position: absolute;
left: -3rpx;
// bottom: -220rpx;
top: -7rpx;
// left: -43%;
height: 10rpx;
width: 150rpx;
background: linear-gradient(-45deg,rgba(255,255,255,0),yellow);
transform: translateX(300rpx);
// background: -webkit-linear-gradient(-45deg,rgba(255,255,255,0),yellow);
/*此处为下一步的添加动画*/
// -webkit-animation: tail 1s ease-in forwards, shooting 1s ease-in forwards;
// -o-animation: tail 1s ease-in forwards, shooting 1s ease-in forwards;
animation: tail 1s ease-in forwards, shooting 1s ease-in forwards;
}
.star::before{
content: "";
position: absolute;
top: -29rpx;
left: -52rpx;
width: 78rpx;
height: 78rpx;
// top: calc(100% - 1px);
// left: 100%;
background: url('http://activitystatic.xyqb.com/sign@2x.png') 0 0/contain no-repeat;
// background: -webkit-linear-gradient(45deg,rgba(255,255,255,0),yellow,rgba(255,255,255,0));
/*此处为下一步的添加动画*/
// -webkit-animation: shining 3s ease-in-out infinite;
// -o-animation: shining 3s ease-in-out infinite;
animation: shining 1s ease-in-out forwards;
}
.star:before {
transform: rotateZ(15deg);
// transform: -webkit-translateX(-50%) -webkit-rotateZ(-45deg);
}
.star:after {
// transform: translateX(-50%) rotateZ(45deg);
// transform: -webkit-translateX(-50%) -webkit-rotateZ(45deg);
}
// @-webkit-keyframes shining {
// 0% {width: 0;}
// 50% {width: 30px;}
// 100% {width: 0;}
// }
@keyframes shining {
0% {transform: scale(1);}
// 50% {transform: scale(0.8);}
99% {transform: scale(0.6);}
100% {transform: scale(0);}
}
// @-webkit-keyframes tail {
// 0% {width: 0;}
// 30% {width: 50px;}
// 100% {width: 0;}
// }
@keyframes tail {
0% {width: 0;}
10% {width: 0;}
50% {width: 150rpx;}
65% {width: 50rpx;}
80% {width: 150rpx;}
100% {width: 0;}
}
// @-webkit-keyframes shooting {
// 0% {
// -webkit-transform: translateX(0);
// transform: translateX(0);
// }
// 100% {
// -webkit-transform: translateX(350px);
// transform: translateX(350px);
// }
// }
@keyframes shooting {
0% {
// -webkit-transform: translateX(0);
transform: translateX(610rpx);
}
100% {
// -webkit-transform: translateX(350px);
transform: translateX(20rpx);
}
}
// }
</style>
<config>
{
usingComponents: {
'van-loading': '~@/components/vant/loading/index'
}
}
</config>
...@@ -115,7 +115,7 @@ ...@@ -115,7 +115,7 @@
}, },
total: { total: {
type: Number, type: Number,
value: 0, value: 0
} }
}, },
data: { data: {
...@@ -129,8 +129,8 @@ ...@@ -129,8 +129,8 @@
_invalidUp: 0, _invalidUp: 0,
_invalidDown: 0, _invalidDown: 0,
_videoContexts: [], _videoContexts: [],
progress:0, progress: 0,
progressStyle:'', progressStyle: '',
loading: false loading: false
}, },
watch: { watch: {
...@@ -142,7 +142,7 @@ ...@@ -142,7 +142,7 @@
}, },
attached() { attached() {
this.progress = 47; this.progress = 47;
this.progressStyle = 'width:'+this.progress+'%'; this.progressStyle = 'width:' + this.progress + '%';
this._videoContexts = [ this._videoContexts = [
wx.createVideoContext('video_0', this.$wx), wx.createVideoContext('video_0', this.$wx),
wx.createVideoContext('video_1', this.$wx), wx.createVideoContext('video_1', this.$wx),
...@@ -166,7 +166,7 @@ ...@@ -166,7 +166,7 @@
if (diff === 0) return; if (diff === 0) return;
this._last = current; this._last = current;
this.playCurrent(current); this.playCurrent(current);
// this.$emit('change', { activeId: this.curQueue[current].id }); this.$emit('change', { activeId: this.curQueue[current].id });
this.loading = true; this.loading = true;
this.circular = false; this.circular = false;
...@@ -217,8 +217,7 @@ ...@@ -217,8 +217,7 @@
// console.log('circular2'); // console.log('circular2');
// this.circular = false; // this.circular = false;
// } // }
});
})
}, },
onWaiting (e) { onWaiting (e) {
this.trigger(e, 'wait'); this.trigger(e, 'wait');
......
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area'; import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({ VantComponent({
mixins: [safeArea()], mixins: [button, openType],
props: { props: {
show: Boolean, show: Boolean,
title: String, title: String,
cancelText: String, cancelText: String,
customStyle: String, description: String,
overlayStyle: String, round: {
type: Boolean,
value: true,
},
zIndex: { zIndex: {
type: Number, type: Number,
value: 100 value: 100,
}, },
actions: { actions: {
type: Array, type: Array,
value: [] value: [],
}, },
overlay: { overlay: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
closeOnClickOverlay: { closeOnClickOverlay: {
type: Boolean, type: Boolean,
value: true value: true,
} },
closeOnClickAction: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
}, },
methods: { methods: {
onSelect(event) { onSelect(event) {
...@@ -31,6 +43,9 @@ VantComponent({ ...@@ -31,6 +43,9 @@ VantComponent({
const item = this.data.actions[index]; const item = this.data.actions[index];
if (item && !item.disabled && !item.loading) { if (item && !item.disabled && !item.loading) {
this.$emit('select', item); this.$emit('select', item);
if (this.data.closeOnClickAction) {
this.onClose();
}
} }
}, },
onCancel() { onCancel() {
...@@ -38,6 +53,10 @@ VantComponent({ ...@@ -38,6 +53,10 @@ VantComponent({
}, },
onClose() { onClose() {
this.$emit('close'); this.$emit('close');
} },
} onClickOverlay() {
this.$emit('click-overlay');
this.onClose();
},
},
}); });
...@@ -3,14 +3,13 @@ ...@@ -3,14 +3,13 @@
<van-popup <van-popup
show="{{ show }}" show="{{ show }}"
position="bottom" position="bottom"
round="{{ round }}"
z-index="{{ zIndex }}" z-index="{{ zIndex }}"
overlay="{{ overlay }}" overlay="{{ overlay }}"
custom-style="{{ customStyle }}"
overlay-style="{{ overlayStyle }}"
custom-class="van-action-sheet" custom-class="van-action-sheet"
safe-area-inset-bottom="{{ safeAreaInsetBottom }}" safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
close-on-click-overlay="{{ closeOnClickOverlay }}" close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClose" bind:close="onClickOverlay"
> >
<view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header"> <view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
{{ title }} {{ title }}
...@@ -20,22 +19,39 @@ ...@@ -20,22 +19,39 @@
bind:click="onClose" bind:click="onClose"
/> />
</view> </view>
<view wx:if="{{ description }}" class="van-action-sheet__description">
{{ description }}
</view>
<view wx:if="{{ actions && actions.length }}"> <view wx:if="{{ actions && actions.length }}">
<!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 --> <!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
<button <button
wx:for="{{ actions }}" wx:for="{{ actions }}"
wx:key="index" wx:key="index"
open-type="{{ item.openType }}" open-type="{{ item.openType }}"
style="{{ item.color ? 'color: ' + item.color : '' }}"
class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ item.className || '' }}" class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ item.className || '' }}"
hover-class="van-action-sheet__item--hover" hover-class="van-action-sheet__item--hover"
data-index="{{ index }}" data-index="{{ index }}"
bind:tap="onSelect" bind:tap="onSelect"
bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindlaunchapp="bindLaunchApp"
bindopensetting="bindOpenSetting"
lang="{{ lang }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
> >
<block wx:if="{{ !item.loading }}"> <block wx:if="{{ !item.loading }}">
{{ item.name }} {{ item.name }}
<text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text> <text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
</block> </block>
<van-loading wx:else size="20px" /> <van-loading wx:else custom-class="van-action-sheet__loading" size="20px" />
</button> </button>
</view> </view>
<slot /> <slot />
......
@import '../common/index.wxss';.van-action-sheet{max-height:90%!important;color:#333}.van-action-sheet__cancel,.van-action-sheet__item{height:50px;font-size:16px;line-height:50px;text-align:center;background-color:#fff}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel{height:60px}.van-action-sheet__cancel:before{display:block;height:10px;background-color:#f8f8f8;content:" "}.van-action-sheet__item--disabled{color:#c9c9c9}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff}.van-action-sheet__subname{margin-left:5px;font-size:12px;color:#7d7e80}.van-action-sheet__header{font-size:16px;font-weight:500;line-height:44px;text-align:center}.van-action-sheet__close{position:absolute!important;top:0;right:0;padding:0 15px;font-size:18px!important;line-height:inherit!important;color:#999} @import '../common/index.wxss';.van-action-sheet{max-height:90%!important;max-height:var(--action-sheet-max-height,90%)!important;color:#323233;color:var(--action-sheet-item-text-color,#323233)}.van-action-sheet__cancel,.van-action-sheet__item{text-align:center;font-size:16px;font-size:var(--action-sheet-item-font-size,16px);line-height:50px;line-height:var(--action-sheet-item-height,50px);background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}.van-action-sheet__cancel:before{display:block;content:" ";height:8px;height:var(--action-sheet-cancel-padding-top,8px);background-color:#f7f8fa;background-color:var(--action-sheet-cancel-padding-color,#f7f8fa)}.van-action-sheet__item--disabled{color:#c8c9cc;color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{margin-left:4px;margin-left:var(--padding-base,4px);font-size:12px;font-size:var(--action-sheet-subname-font-size,12px);color:#646566;color:var(--action-sheet-subname-color,#646566)}.van-action-sheet__header{text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--action-sheet-header-font-size,16px);line-height:44px;line-height:var(--action-sheet-header-height,44px)}.van-action-sheet__description{text-align:center;padding:16px;padding:var(--padding-md,16px);color:#646566;color:var(--action-sheet-description-color,#646566);font-size:14px;font-size:var(--action-sheet-description-font-size,14px);line-height:20px;line-height:var(--action-sheet-description-line-height,20px)}.van-action-sheet__close{position:absolute!important;top:0;right:0;line-height:inherit!important;padding:0 12px;padding:var(--action-sheet-close-icon-padding,0 12px);font-size:18px!important;font-size:var(--action-sheet-close-icon-size,18px)!important;color:#969799;color:var(--action-sheet-close-icon-color,#969799)}.van-action-sheet__loading{display:-webkit-flex!important;display:flex!important;height:50px;height:var(--action-sheet-item-height,50px)}
\ No newline at end of file \ No newline at end of file
...@@ -3,13 +3,29 @@ import { pickerProps } from '../picker/shared'; ...@@ -3,13 +3,29 @@ import { pickerProps } from '../picker/shared';
const COLUMNSPLACEHOLDERCODE = '000000'; const COLUMNSPLACEHOLDERCODE = '000000';
VantComponent({ VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'], classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign({}, pickerProps, { value: String, areaList: { props: Object.assign(Object.assign({}, pickerProps), {
value: {
type: String,
observer(value) {
this.code = value;
this.setValues();
},
},
areaList: {
type: Object, type: Object,
value: {} value: {},
}, columnsNum: { observer: 'setValues',
type: [String, Number], },
value: 3 columnsNum: {
}, columnsPlaceholder: { type: null,
value: 3,
observer(value) {
this.setData({
displayColumns: this.data.columns.slice(0, +value),
});
},
},
columnsPlaceholder: {
type: Array, type: Array,
observer(val) { observer(val) {
this.setData({ this.setData({
...@@ -17,26 +33,15 @@ VantComponent({ ...@@ -17,26 +33,15 @@ VantComponent({
province: val[0] || '', province: val[0] || '',
city: val[1] || '', city: val[1] || '',
county: val[2] || '', county: val[2] || '',
} },
}); });
} },
} }), },
}),
data: { data: {
columns: [{ values: [] }, { values: [] }, { values: [] }], columns: [{ values: [] }, { values: [] }, { values: [] }],
displayColumns: [{ values: [] }, { values: [] }, { values: [] }], displayColumns: [{ values: [] }, { values: [] }, { values: [] }],
typeToColumnsPlaceholder: {} typeToColumnsPlaceholder: {},
},
watch: {
value(value) {
this.code = value;
this.setValues();
},
areaList: 'setValues',
columnsNum(value) {
this.set({
displayColumns: this.data.columns.slice(0, +value)
});
}
}, },
mounted() { mounted() {
setTimeout(() => { setTimeout(() => {
...@@ -69,8 +74,7 @@ VantComponent({ ...@@ -69,8 +74,7 @@ VantComponent({
const { columnsPlaceholder } = this.data; const { columnsPlaceholder } = this.data;
return values.map((value, index) => { return values.map((value, index) => {
// save undefined value // save undefined value
if (!value) if (!value) return value;
return value;
value = JSON.parse(JSON.stringify(value)); value = JSON.parse(JSON.stringify(value));
if (!value.code || value.name === columnsPlaceholder[index]) { if (!value.code || value.name === columnsPlaceholder[index]) {
value.code = ''; value.code = '';
...@@ -82,13 +86,11 @@ VantComponent({ ...@@ -82,13 +86,11 @@ VantComponent({
onChange(event) { onChange(event) {
const { index, picker, value } = event.detail; const { index, picker, value } = event.detail;
this.code = value[index].code; this.code = value[index].code;
let getValues = picker.getValues();
getValues = this.parseOutputValues(getValues);
this.setValues().then(() => { this.setValues().then(() => {
this.$emit('change', { this.$emit('change', {
picker, picker,
values: getValues, values: this.parseOutputValues(picker.getValues()),
index index,
}); });
}); });
}, },
...@@ -103,23 +105,28 @@ VantComponent({ ...@@ -103,23 +105,28 @@ VantComponent({
return result; return result;
} }
const list = this.getConfig(type); const list = this.getConfig(type);
result = Object.keys(list).map(code => ({ result = Object.keys(list).map((code) => ({
code, code,
name: list[code] name: list[code],
})); }));
if (code) { if (code) {
// oversea code // oversea code
if (code[0] === '9' && type === 'city') { if (code[0] === '9' && type === 'city') {
code = '9'; code = '9';
} }
result = result.filter(item => item.code.indexOf(code) === 0); result = result.filter((item) => item.code.indexOf(code) === 0);
} }
if (typeToColumnsPlaceholder[type] && result.length) { if (typeToColumnsPlaceholder[type] && result.length) {
// set columns placeholder // set columns placeholder
const codeFill = type === 'province' ? '' : type === 'city' ? COLUMNSPLACEHOLDERCODE.slice(2, 4) : COLUMNSPLACEHOLDERCODE.slice(4, 6); const codeFill =
type === 'province'
? ''
: type === 'city'
? COLUMNSPLACEHOLDERCODE.slice(2, 4)
: COLUMNSPLACEHOLDERCODE.slice(4, 6);
result.unshift({ result.unshift({
code: `${code}${codeFill}`, code: `${code}${codeFill}`,
name: typeToColumnsPlaceholder[type] name: typeToColumnsPlaceholder[type],
}); });
} }
return result; return result;
...@@ -145,11 +152,9 @@ VantComponent({ ...@@ -145,11 +152,9 @@ VantComponent({
if (!code) { if (!code) {
if (this.data.columnsPlaceholder.length) { if (this.data.columnsPlaceholder.length) {
code = COLUMNSPLACEHOLDERCODE; code = COLUMNSPLACEHOLDERCODE;
} } else if (Object.keys(county)[0]) {
else if (Object.keys(county)[0]) {
code = Object.keys(county)[0]; code = Object.keys(county)[0];
} } else {
else {
code = ''; code = '';
} }
} }
...@@ -165,19 +170,27 @@ VantComponent({ ...@@ -165,19 +170,27 @@ VantComponent({
if (city.length && code.slice(2, 4) === '00') { if (city.length && code.slice(2, 4) === '00') {
[{ code }] = city; [{ code }] = city;
} }
stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false)); stack.push(
picker.setColumnValues(
2,
this.getList('county', code.slice(0, 4)),
false
)
);
return Promise.all(stack) return Promise.all(stack)
.catch(() => { }) .catch(() => {})
.then(() => picker.setIndexes([ .then(() =>
picker.setIndexes([
this.getIndex('province', code), this.getIndex('province', code),
this.getIndex('city', code), this.getIndex('city', code),
this.getIndex('county', code) this.getIndex('county', code),
])) ])
.catch(() => { }); )
.catch(() => {});
}, },
getValues() { getValues() {
const picker = this.getPicker(); const picker = this.getPicker();
return picker ? picker.getValues().filter(value => !!value) : []; return picker ? picker.getValues().filter((value) => !!value) : [];
}, },
getDetail() { getDetail() {
const values = this.getValues(); const values = this.getValues();
...@@ -186,7 +199,7 @@ VantComponent({ ...@@ -186,7 +199,7 @@ VantComponent({
country: '', country: '',
province: '', province: '',
city: '', city: '',
county: '' county: '',
}; };
if (!values.length) { if (!values.length) {
return area; return area;
...@@ -196,17 +209,16 @@ VantComponent({ ...@@ -196,17 +209,16 @@ VantComponent({
if (area.code[0] === '9') { if (area.code[0] === '9') {
area.country = names[1] || ''; area.country = names[1] || '';
area.province = names[2] || ''; area.province = names[2] || '';
} } else {
else {
area.province = names[0] || ''; area.province = names[0] || '';
area.city = names[1] || ''; area.city = names[1] || '';
area.county = names[2] || ''; area.county = names[2] || '';
} }
return area; return area;
}, },
reset() { reset(code) {
this.code = ''; this.code = code || '';
return this.setValues(); return this.setValues();
} },
} },
}); });
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'badge',
type: 'descendant',
linked(target) {
this.badges.push(target);
this.setActive(this.data.active);
},
unlinked(target) {
this.badges = this.badges.filter(item => item !== target);
this.setActive(this.data.active);
}
},
props: {
active: {
type: Number,
value: 0,
observer: 'setActive'
}
},
beforeCreate() {
this.badges = [];
this.currentActive = -1;
},
methods: {
setActive(active) {
const { badges, currentActive } = this;
if (!badges.length) {
return Promise.resolve();
}
this.currentActive = active;
const stack = [];
if (currentActive !== active && badges[currentActive]) {
stack.push(badges[currentActive].setActive(false));
}
if (badges[active]) {
stack.push(badges[active].setActive(true));
}
return Promise.all(stack);
}
}
});
<view class="van-badge-group van-hairline--top-bottom custom-class">
<slot />
</view>
@import '../common/index.wxss';.van-badge-group{width:85px}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
relation: {
type: 'ancestor',
name: 'badge-group',
linked(target) {
this.parent = target;
}
},
props: {
info: null,
title: String
},
methods: {
onClick() {
const { parent } = this;
if (!parent) {
return;
}
const index = parent.badges.indexOf(this);
parent.setActive(index).then(() => {
this.$emit('click', index);
parent.$emit('change', index);
});
},
setActive(active) {
return this.set({ active });
}
}
});
@import '../common/index.wxss';.van-badge{display:block;padding:20px 12px 20px 9px;overflow:hidden;font-size:14px;line-height:1.4;color:#7d7e80;word-break:break-all;background-color:#f8f8f8;border-left:3px solid transparent;box-sizing:border-box;-webkit-user-select:none;user-select:none}.van-badge--hover{background-color:#f2f3f5}.van-badge:after{border-bottom-width:1px}.van-badge--active{font-weight:700;color:#333;border-color:#f44}.van-badge--active:after{border-right-width:1px}.van-badge--active,.van-badge--active.van-badge--hover{background-color:#fff}.van-badge__text{position:relative}
\ No newline at end of file
...@@ -4,9 +4,15 @@ import { openType } from '../mixins/open-type'; ...@@ -4,9 +4,15 @@ import { openType } from '../mixins/open-type';
VantComponent({ VantComponent({
mixins: [button, openType], mixins: [button, openType],
classes: ['hover-class', 'loading-class'], classes: ['hover-class', 'loading-class'],
data: {
baseStyle: '',
},
props: { props: {
icon: String, icon: String,
color: String, classPrefix: {
type: String,
value: 'van-icon',
},
plain: Boolean, plain: Boolean,
block: Boolean, block: Boolean,
round: Boolean, round: Boolean,
...@@ -15,24 +21,53 @@ VantComponent({ ...@@ -15,24 +21,53 @@ VantComponent({
hairline: Boolean, hairline: Boolean,
disabled: Boolean, disabled: Boolean,
loadingText: String, loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular',
},
type: { type: {
type: String, type: String,
value: 'default' value: 'default',
}, },
dataset: null,
size: { size: {
type: String, type: String,
value: 'normal' value: 'normal',
}, },
loadingSize: { loadingSize: {
type: String, type: String,
value: '20px' value: '20px',
},
color: {
type: String,
observer(color) {
let style = '';
if (color) {
style += `color: ${this.data.plain ? color : 'white'};`;
if (!this.data.plain) {
// Use background instead of backgroundColor to make linear-gradient work
style += `background: ${color};`;
}
// hide border when color is linear-gradient
if (color.indexOf('gradient') !== -1) {
style += 'border: 0;';
} else {
style += `border-color: ${color};`;
} }
}
if (style !== this.data.baseStyle) {
this.setData({ baseStyle: style });
}
},
},
}, },
methods: { methods: {
onClick() { onClick() {
if (!this.data.disabled && !this.data.loading) { if (!this.data.loading) {
this.$emit('click'); this.$emit('click');
} }
} },
} noop() {},
},
}); });
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
<button <button
id="{{ id }}" id="{{ id }}"
data-detail="{{ dataset }}"
class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}" class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
open-type="{{ openType }}"
hover-class="van-button--active hover-class" hover-class="van-button--active hover-class"
style="{{ color ? 'border-color: ' + color + ';' + (plain ? 'color: ' + color : 'color: #fff; background-color: ' + color) : '' }}"
lang="{{ lang }}" lang="{{ lang }}"
style="{{ baseStyle }} {{ customStyle }}"
open-type="{{ disabled ? '' : openType }}"
business-id="{{ businessId }}" business-id="{{ businessId }}"
session-from="{{ sessionFrom }}" session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}" send-message-title="{{ sendMessageTitle }}"
...@@ -15,7 +16,7 @@ ...@@ -15,7 +16,7 @@
show-message-card="{{ showMessageCard }}" show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}" app-parameter="{{ appParameter }}"
aria-label="{{ ariaLabel }}" aria-label="{{ ariaLabel }}"
bindtap="onClick" bindtap="{{ !disabled ? 'onClick' : 'noop' }}"
bindgetuserinfo="bindGetUserInfo" bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact" bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber" bindgetphonenumber="bindGetPhoneNumber"
...@@ -27,12 +28,10 @@ ...@@ -27,12 +28,10 @@
<van-loading <van-loading
custom-class="loading-class" custom-class="loading-class"
size="{{ loadingSize }}" size="{{ loadingSize }}"
color="{{ type === 'default' ? '#c9c9c9' : '' }}" type="{{ loadingType }}"
color="{{ loadingColor(type,color,plain) }}"
/> />
<view <view wx:if="{{ loadingText }}" class="van-button__loading-text">
wx:if="{{ loadingText }}"
class="van-button__loading-text"
>
{{ loadingText }} {{ loadingText }}
</view> </view>
</block> </block>
...@@ -41,6 +40,7 @@ ...@@ -41,6 +40,7 @@
wx:if="{{ icon }}" wx:if="{{ icon }}"
size="1.2em" size="1.2em"
name="{{ icon }}" name="{{ icon }}"
class-prefix="{{ classPrefix }}"
class="van-button__icon" class="van-button__icon"
custom-style="line-height: inherit;" custom-style="line-height: inherit;"
/> />
...@@ -49,3 +49,19 @@ ...@@ -49,3 +49,19 @@
</view> </view>
</block> </block>
</button> </button>
<wxs module="loadingColor">
function get(type, color,plain) {
if(plain) {
return color ? color: '#c9c9c9';
}
if(type === 'default') {
return '#c9c9c9';
}
return 'white';
}
module.exports = get;
</wxs>
@import '../common/index.wxss';.van-button{position:relative;display:inline-block;height:44px;padding:0;font-size:16px;line-height:42px;text-align:center;vertical-align:middle;box-sizing:border-box;border-radius:2px;-webkit-appearance:none;-webkit-text-size-adjust:100%}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;background-color:#000;border:inherit;border-color:#000;border-radius:inherit;content:" ";opacity:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#333;background-color:#fff;border:1px solid #eee}.van-button--primary{color:#fff;background-color:#07c160;border:1px solid #07c160}.van-button--info{color:#fff;background-color:#1989fa;border:1px solid #1989fa}.van-button--danger{color:#fff;background-color:#f44;border:1px solid #f44}.van-button--warning{color:#fff;background-color:#ff976a;border:1px solid #ff976a}.van-button--plain{background-color:#fff}.van-button--plain.van-button--primary{color:#07c160}.van-button--plain.van-button--info{color:#1989fa}.van-button--plain.van-button--danger{color:#f44}.van-button--plain.van-button--warning{color:#ff976a}.van-button--large{width:100%;height:50px;line-height:48px}.van-button--normal{padding:0 15px;font-size:14px}.van-button--small{height:30px;min-width:60px;padding:0 8px;font-size:12px;line-height:28px}.van-button--mini{display:inline-block;width:50px;height:22px;font-size:10px;line-height:20px}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:block;width:100%}.van-button--round{border-radius:10em}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5}.van-button__text{display:inline}.van-button__loading-text{margin-left:5px;display:inline-block;vertical-align:middle}.van-button__icon{min-width:1em;line-height:inherit!important;vertical-align:top}.van-button__icon+.van-button__text:not(:empty){display:inline-block;margin-left:5px;vertical-align:top}.van-button--hairline{border-width:0;padding-top:1px}.van-button--hairline:after{border-width:1px;border-color:inherit;border-radius:4px}.van-button--hairline.van-button--round:after{border-radius:10em}.van-button--hairline.van-button--square:after{border-radius:0} @import '../common/index.wxss';.van-button{position:relative;display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;padding:0;text-align:center;vertical-align:middle;-webkit-appearance:none;-webkit-text-size-adjust:100%;height:44px;height:var(--button-default-height,44px);line-height:20px;line-height:var(--button-line-height,20px);font-size:16px;font-size:var(--button-default-font-size,16px);transition:opacity .2s;transition:opacity var(--animation-duration-fast,.2s);border-radius:2px;border-radius:var(--button-border-radius,2px)}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;border:inherit;border-radius:inherit;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);opacity:0;content:" ";background-color:#000;background-color:var(--black,#000);border-color:#000;border-color:var(--black,#000)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#323233;color:var(--button-default-color,#323233);background:#fff;background:var(--button-default-background-color,#fff);border:1px solid #ebedf0;border:var(--button-border-width,1px) solid var(--button-default-border-color,#ebedf0)}.van-button--primary{color:#fff;color:var(--button-primary-color,#fff);background:#07c160;background:var(--button-primary-background-color,#07c160);border:1px solid #07c160;border:var(--button-border-width,1px) solid var(--button-primary-border-color,#07c160)}.van-button--info{color:#fff;color:var(--button-info-color,#fff);background:#1989fa;background:var(--button-info-background-color,#1989fa);border:1px solid #1989fa;border:var(--button-border-width,1px) solid var(--button-info-border-color,#1989fa)}.van-button--danger{color:#fff;color:var(--button-danger-color,#fff);background:#ee0a24;background:var(--button-danger-background-color,#ee0a24);border:1px solid #ee0a24;border:var(--button-border-width,1px) solid var(--button-danger-border-color,#ee0a24)}.van-button--warning{color:#fff;color:var(--button-warning-color,#fff);background:#ff976a;background:var(--button-warning-background-color,#ff976a);border:1px solid #ff976a;border:var(--button-border-width,1px) solid var(--button-warning-border-color,#ff976a)}.van-button--plain{background:#fff;background:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:#07c160;color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:#1989fa;color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:#ee0a24;color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:#ff976a;color:var(--button-warning-background-color,#ff976a)}.van-button--large{width:100%;height:50px;height:var(--button-large-height,50px)}.van-button--normal{padding:0 15px;font-size:14px;font-size:var(--button-normal-font-size,14px)}.van-button--small{min-width:60px;min-width:var(--button-small-min-width,60px);height:30px;height:var(--button-small-height,30px);padding:0 8px;padding:0 var(--padding-xs,8px);font-size:12px;font-size:var(--button-small-font-size,12px)}.van-button--mini{display:inline-block;min-width:50px;min-width:var(--button-mini-min-width,50px);height:22px;height:var(--button-mini-height,22px);font-size:10px;font-size:var(--button-mini-font-size,10px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:-webkit-flex;display:flex;width:100%}.van-button--round{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5;opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{min-width:1em;line-height:inherit!important;vertical-align:top}.van-button--hairline{padding-top:1px;border-width:0}.van-button--hairline:after{border-color:inherit;border-width:1px;border-radius:4px;border-radius:calc(var(--button-border-radius, 2px)*2)}.van-button--hairline.van-button--round:after{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0}
\ No newline at end of file \ No newline at end of file
<wxs src="./index.wxs" module="computed"></wxs>
<template name="calendar">
<view class="van-calendar">
<header
title="{{ title }}"
showTitle="{{ showTitle }}"
subtitle="{{ subtitle }}"
showSubtitle="{{ showSubtitle }}"
>
<slot name="title" slot="title"></slot>
</header>
<scroll-view class="van-calendar__body" scroll-y scroll-into-view="{{ scrollIntoView }}">
<month
wx:for="{{ computed.getMonths(minDate, maxDate) }}"
wx:key="index"
id="month{{ index }}"
class="month"
data-date="{{ item }}"
date="{{ item }}"
type="{{ type }}"
color="{{ color }}"
minDate="{{ minDate }}"
maxDate="{{ maxDate }}"
showMark="{{ showMark }}"
formatter="{{ formatter }}"
rowHeight="{{ rowHeight }}"
currentDate="{{ currentDate }}"
showSubtitle="{{ showSubtitle }}"
allowSameDay="{{ allowSameDay }}"
showMonthTitle="{{ index !== 0 || !showSubtitle }}"
bind:click="onClickDay"
/>
</scroll-view>
<view class="van-calendar__footer {{ safeAreaInsetBottom ? 'van-calendar__footer--safe-area-inset-bottom' : '' }}">
<slot name="footer"></slot>
</view>
<view class="van-calendar__footer {{ safeAreaInsetBottom ? 'van-calendar__footer--safe-area-inset-bottom' : '' }}">
<van-button
wx:if="{{ showConfirm }}"
round
block
type="danger"
color="{{ color }}"
custom-class="van-calendar__confirm"
disabled="{{ computed.getButtonDisabled(type, currentDate) }}"
nativeType="text"
bind:click="onConfirm"
>
{{ computed.getButtonDisabled(type, currentDate) ? confirmDisabledText : confirmText }}
</van-button>
</view>
</view>
</template>
import { VantComponent } from '../../../common/component';
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
subtitle: String,
showTitle: Boolean,
showSubtitle: Boolean,
},
data: {
weekdays: ['', '', '', '', '', '', ''],
},
methods: {},
});
<view class="van-calendar__header">
<block wx:if="{{ showTitle }}">
<view class="van-calendar__header-title"><slot name="title"></slot></view>
<view class="van-calendar__header-title">{{ title }}</view>
</block>
<view wx:if="{{ showSubtitle }}" class="van-calendar__header-subtitle">
{{ subtitle }}
</view>
<view class="van-calendar__weekdays">
<view wx:for="{{ weekdays }}" wx:key="index" class="van-calendar__weekday">
{{ item }}
</view>
</view>
</view>
@import '../../../common/index.wxss';.van-calendar__header{-webkit-flex-shrink:0;flex-shrink:0;box-shadow:0 2px 10px rgba(125,126,128,.16);box-shadow:var(--calendar-header-box-shadow,0 2px 10px rgba(125,126,128,.16))}.van-calendar__header-subtitle,.van-calendar__header-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:-webkit-flex;display:flex}.van-calendar__weekday{-webkit-flex:1;flex:1;text-align:center;font-size:12px;font-size:var(--calendar-weekdays-font-size,12px);line-height:30px;line-height:var(--calendar-weekdays-height,30px)}
\ No newline at end of file
import { VantComponent } from '../../../common/component';
import {
getMonthEndDay,
compareDay,
getPrevDay,
getNextDay,
} from '../../utils';
VantComponent({
props: {
date: {
type: null,
observer: 'setDays',
},
type: {
type: String,
observer: 'setDays',
},
color: String,
minDate: {
type: null,
observer: 'setDays',
},
maxDate: {
type: null,
observer: 'setDays',
},
showMark: Boolean,
rowHeight: [Number, String],
formatter: {
type: null,
observer: 'setDays',
},
currentDate: {
type: [null, Array],
observer: 'setDays',
},
allowSameDay: Boolean,
showSubtitle: Boolean,
showMonthTitle: Boolean,
},
data: {
visible: true,
days: [],
},
methods: {
onClick(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.days[index];
if (item.type !== 'disabled') {
this.$emit('click', item);
}
},
setDays() {
const days = [];
const startDate = new Date(this.data.date);
const year = startDate.getFullYear();
const month = startDate.getMonth();
const totalDay = getMonthEndDay(
startDate.getFullYear(),
startDate.getMonth() + 1
);
for (let day = 1; day <= totalDay; day++) {
const date = new Date(year, month, day);
const type = this.getDayType(date);
let config = {
date,
type,
text: day,
bottomInfo: this.getBottomInfo(type),
};
if (this.data.formatter) {
config = this.data.formatter(config);
}
days.push(config);
}
this.setData({ days });
},
getMultipleDayType(day) {
const { currentDate } = this.data;
if (!Array.isArray(currentDate)) {
return '';
}
const isSelected = (date) =>
currentDate.some((item) => compareDay(item, date) === 0);
if (isSelected(day)) {
const prevDay = getPrevDay(day);
const nextDay = getNextDay(day);
const prevSelected = isSelected(prevDay);
const nextSelected = isSelected(nextDay);
if (prevSelected && nextSelected) {
return 'multiple-middle';
}
if (prevSelected) {
return 'end';
}
return nextSelected ? 'start' : 'multiple-selected';
}
return '';
},
getRangeDayType(day) {
const { currentDate, allowSameDay } = this.data;
if (!Array.isArray(currentDate)) {
return;
}
const [startDay, endDay] = currentDate;
if (!startDay) {
return;
}
const compareToStart = compareDay(day, startDay);
if (!endDay) {
return compareToStart === 0 ? 'start' : '';
}
const compareToEnd = compareDay(day, endDay);
if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
return 'start-end';
}
if (compareToStart === 0) {
return 'start';
}
if (compareToEnd === 0) {
return 'end';
}
if (compareToStart > 0 && compareToEnd < 0) {
return 'middle';
}
},
getDayType(day) {
const { type, minDate, maxDate, currentDate } = this.data;
if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
return 'disabled';
}
if (type === 'single') {
return compareDay(day, currentDate) === 0 ? 'selected' : '';
}
if (type === 'multiple') {
return this.getMultipleDayType(day);
}
/* istanbul ignore else */
if (type === 'range') {
return this.getRangeDayType(day);
}
},
getBottomInfo(type) {
if (this.data.type === 'range') {
if (type === 'start') {
return '开始';
}
if (type === 'end') {
return '结束';
}
if (type === 'start-end') {
return '开始/结束';
}
}
},
},
});
<wxs src="./index.wxs" module="computed"></wxs>
<wxs src="../../../wxs/utils.wxs" module="utils" />
<view class="van-calendar__month" style="{{ computed.getMonthStyle(visible, date, rowHeight) }}">
<view wx:if="{{ showMonthTitle }}" class="van-calendar__month-title">
{{ computed.formatMonthTitle(date) }}
</view>
<view wx:if="{{ visible }}" class="van-calendar__days">
<view wx:if="{{ showMark }}" class="van-calendar__month-mark">
{{ computed.getMark(date) }}
</view>
<view
wx:for="{{ days }}"
wx:key="index"
style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color) }}"
class="{{ utils.bem('calendar__day', [item.type]) }} {{ item.className }}"
data-index="{{ index }}"
bindtap="onClick"
>
<view wx:if="{{ item.type === 'selected' }}" class="van-calendar__selected-day" style="background: {{ color }}">
<view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
{{ item.text }}
<view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
{{ item.bottomInfo }}
</view>
</view>
<view wx:else>
<view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
{{ item.text }}
<view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
{{ item.bottomInfo }}
</view>
</view>
</view>
</view>
</view>
/* eslint-disable */
var utils = require('../../utils.wxs');
function getMark(date) {
return getDate(date).getMonth() + 1;
}
var ROW_HEIGHT = 64;
function getDayStyle(type, index, date, rowHeight, color) {
var style = [];
var offset = getDate(date).getDay();
if (index === 0) {
style.push(['margin-left', (100 * offset) / 7 + '%']);
}
if (rowHeight !== ROW_HEIGHT) {
style.push(['height', rowHeight + 'px']);
}
if (color) {
if (
type === 'start' ||
type === 'end' ||
type === 'multiple-selected' ||
type === 'multiple-middle'
) {
style.push(['background', color]);
} else if (type === 'middle') {
style.push(['color', color]);
}
}
return style
.map(function(item) {
return item.join(':');
})
.join(';');
}
function formatMonthTitle(date) {
date = getDate(date);
return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
}
function getMonthStyle(visible, date, rowHeight) {
if (!visible) {
date = getDate(date);
var totalDay = utils.getMonthEndDay(
date.getFullYear(),
date.getMonth() + 1
);
var offset = getDate(date).getDay();
var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
return 'padding-bottom:' + padding + 'px';
}
}
module.exports = {
getMark: getMark,
getDayStyle: getDayStyle,
formatMonthTitle: formatMonthTitle,
getMonthStyle: getMonthStyle
};
@import '../../../common/index.wxss';.van-calendar{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;height:100%;background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__month-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);font-size:14px;font-size:var(--calendar-month-title-font-size,14px);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__days{position:relative;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-user-select:none;user-select:none}.van-calendar__month-mark{position:absolute;top:50%;left:50%;z-index:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);pointer-events:none;color:rgba(242,243,245,.8);color:var(--calendar-month-mark-color,rgba(242,243,245,.8));font-size:160px;font-size:var(--calendar-month-mark-font-size,160px)}.van-calendar__day,.van-calendar__selected-day{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;text-align:center}.van-calendar__day{position:relative;width:14.285%;height:64px;height:var(--calendar-day-height,64px);font-size:16px;font-size:var(--calendar-day-font-size,16px)}.van-calendar__day--end,.van-calendar__day--multiple-middle,.van-calendar__day--multiple-selected,.van-calendar__day--start,.van-calendar__day--start-end{color:#fff;color:var(--calendar-range-edge-color,#fff);background-color:#ee0a24;background-color:var(--calendar-range-edge-background-color,#ee0a24)}.van-calendar__day--start{border-radius:4px 0 0 4px;border-radius:var(--border-radius-md,4px) 0 0 var(--border-radius-md,4px)}.van-calendar__day--end{border-radius:0 4px 4px 0;border-radius:0 var(--border-radius-md,4px) var(--border-radius-md,4px) 0}.van-calendar__day--multiple-selected,.van-calendar__day--start-end{border-radius:4px;border-radius:var(--border-radius-md,4px)}.van-calendar__day--middle{color:#ee0a24;color:var(--calendar-range-middle-color,#ee0a24)}.van-calendar__day--middle:after{position:absolute;top:0;right:0;bottom:0;left:0;background-color:currentColor;content:"";opacity:.1;opacity:var(--calendar-range-middle-background-opacity,.1)}.van-calendar__day--disabled{cursor:default;color:#c8c9cc;color:var(--calendar-day-disabled-color,#c8c9cc)}.van-calendar__bottom-info,.van-calendar__top-info{position:absolute;right:0;left:0;font-size:10px;font-size:var(--calendar-info-font-size,10px);line-height:14px;line-height:var(--calendar-info-line-height,14px)}@media (max-width:350px){.van-calendar__bottom-info,.van-calendar__top-info{font-size:9px}}.van-calendar__top-info{top:6px}.van-calendar__bottom-info{bottom:6px}.van-calendar__selected-day{width:54px;width:var(--calendar-selected-day-size,54px);height:54px;height:var(--calendar-selected-day-size,54px);color:#fff;color:var(--calendar-selected-day-color,#fff);background-color:#ee0a24;background-color:var(--calendar-selected-day-background-color,#ee0a24);border-radius:4px;border-radius:var(--border-radius-md,4px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import {
ROW_HEIGHT,
getNextDay,
compareDay,
copyDates,
calcDateNum,
formatMonthTitle,
compareMonth,
getMonths,
getDayByOffset,
} from './utils';
import Toast from '../toast/toast';
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
color: String,
show: {
type: Boolean,
observer(val) {
if (val) {
this.initRect();
this.scrollIntoView();
}
},
},
formatter: null,
confirmText: {
type: String,
value: '确定',
},
rangePrompt: String,
defaultDate: {
type: [Number, Array],
observer(val) {
this.setData({ currentDate: val });
this.scrollIntoView();
},
},
allowSameDay: Boolean,
confirmDisabledText: String,
type: {
type: String,
value: 'single',
observer: 'reset',
},
minDate: {
type: null,
value: Date.now(),
},
maxDate: {
type: null,
value: new Date(
new Date().getFullYear(),
new Date().getMonth() + 6,
new Date().getDate()
).getTime(),
},
position: {
type: String,
value: 'bottom',
},
rowHeight: {
type: [Number, String],
value: ROW_HEIGHT,
},
round: {
type: Boolean,
value: true,
},
poppable: {
type: Boolean,
value: true,
},
showMark: {
type: Boolean,
value: true,
},
showTitle: {
type: Boolean,
value: true,
},
showConfirm: {
type: Boolean,
value: true,
},
showSubtitle: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
maxRange: {
type: [Number, String],
value: null,
},
},
data: {
subtitle: '',
currentDate: null,
scrollIntoView: '',
},
created() {
this.setData({
currentDate: this.getInitialDate(),
});
},
mounted() {
if (this.data.show || !this.data.poppable) {
this.initRect();
this.scrollIntoView();
}
},
methods: {
reset() {
this.setData({ currentDate: this.getInitialDate() });
this.scrollIntoView();
},
initRect() {
if (this.contentObserver != null) {
this.contentObserver.disconnect();
}
const contentObserver = this.createIntersectionObserver({
thresholds: [0, 0.1, 0.9, 1],
observeAll: true,
});
this.contentObserver = contentObserver;
contentObserver.relativeTo('.van-calendar__body');
contentObserver.observe('.month', (res) => {
if (res.boundingClientRect.top <= res.relativeRect.top) {
// @ts-ignore
this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
}
});
},
getInitialDate() {
const { type, defaultDate, minDate } = this.data;
if (type === 'range') {
const [startDay, endDay] = defaultDate || [];
return [
startDay || minDate,
endDay || getNextDay(new Date(minDate)).getTime(),
];
}
if (type === 'multiple') {
return [defaultDate || minDate];
}
return defaultDate || minDate;
},
scrollIntoView() {
setTimeout(() => {
const {
currentDate,
type,
show,
poppable,
minDate,
maxDate,
} = this.data;
const targetDate = type === 'single' ? currentDate : currentDate[0];
const displayed = show || !poppable;
if (!targetDate || !displayed) {
return;
}
const months = getMonths(minDate, maxDate);
months.some((month, index) => {
if (compareMonth(month, targetDate) === 0) {
this.setData({ scrollIntoView: `month${index}` });
return true;
}
return false;
});
}, 100);
},
onOpen() {
this.$emit('open');
},
onOpened() {
this.$emit('opened');
},
onClose() {
this.$emit('close');
},
onClosed() {
this.$emit('closed');
},
onClickDay(event) {
const { date } = event.detail;
const { type, currentDate, allowSameDay } = this.data;
if (type === 'range') {
const [startDay, endDay] = currentDate;
if (startDay && !endDay) {
const compareToStart = compareDay(date, startDay);
if (compareToStart === 1) {
this.select([startDay, date], true);
} else if (compareToStart === -1) {
this.select([date, null]);
} else if (allowSameDay) {
this.select([date, date]);
}
} else {
this.select([date, null]);
}
} else if (type === 'multiple') {
let selectedIndex;
const selected = currentDate.some((dateItem, index) => {
const equal = compareDay(dateItem, date) === 0;
if (equal) {
selectedIndex = index;
}
return equal;
});
if (selected) {
const cancelDate = currentDate.splice(selectedIndex, 1);
this.setData({ currentDate });
this.unselect(cancelDate);
} else {
this.select([...currentDate, date]);
}
} else {
this.select(date, true);
}
},
unselect(dateArray) {
const date = dateArray[0];
if (date) {
this.$emit('unselect', copyDates(date));
}
},
select(date, complete) {
if (complete && this.data.type === 'range') {
const valid = this.checkRange(date);
if (!valid) {
// auto selected to max range if showConfirm
if (this.data.showConfirm) {
this.emit([
date[0],
getDayByOffset(date[0], this.data.maxRange - 1),
]);
} else {
this.emit(date);
}
return;
}
}
this.emit(date);
if (complete && !this.data.showConfirm) {
this.onConfirm();
}
},
emit(date) {
const getTime = (date) => (date instanceof Date ? date.getTime() : date);
this.setData({
currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
});
this.$emit('select', copyDates(date));
},
checkRange(date) {
const { maxRange, rangePrompt } = this.data;
if (maxRange && calcDateNum(date) > maxRange) {
Toast({
context: this,
message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
});
return false;
}
return true;
},
onConfirm() {
if (this.data.type === 'range' && !this.checkRange()) {
return;
}
wx.nextTick(() => {
this.$emit('confirm', copyDates(this.data.currentDate));
});
},
},
});
{
"component": true,
"usingComponents": {
"header": "./components/header/index",
"month": "./components/month/index",
"van-button": "../button/index",
"van-popup": "../popup/index"
}
}
<wxs src="./index.wxs" module="computed" />
<import src="./calendar.wxml" />
<van-popup
wx:if="{{ poppable }}"
custom-class="van-calendar__popup--{{ position }}"
close-icon-class="van-calendar__close-icon"
show="{{ show }}"
round="{{ round }}"
position="{{ position }}"
closeable="{{ showTitle || showSubtitle }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:enter="onOpen"
bind:close="onClose"
bind:after-enter="onOpened"
bind:after-leave="onClosed"
>
<template
is="calendar"
data="{{ title, subtitle, showTitle, showSubtitle, minDate, maxDate, type, color, showMark, formatter, rowHeight, currentDate, safeAreaInsetBottom, showConfirm, confirmDisabledText, confirmText, scrollIntoView, allowSameDay }}"
/>
</van-popup>
<template
wx:else
is="calendar"
data="{{ title, subtitle, showTitle, showSubtitle, minDate, maxDate, type, color, showMark, formatter, rowHeight, currentDate, safeAreaInsetBottom, showConfirm, confirmDisabledText, confirmText, scrollIntoView, allowSameDay }}"
/>
<van-toast id="van-toast" />
/* eslint-disable */
var utils = require('./utils.wxs');
function getMonths(minDate, maxDate) {
var months = [];
var cursor = getDate(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
return months;
}
function getButtonDisabled(type, currentDate) {
if (currentDate == null) {
return true;
}
if (type === 'range') {
return !currentDate[0] || !currentDate[1];
}
if (type === 'multiple') {
return !currentDate.length;
}
return !currentDate;
}
module.exports = {
getMonths: getMonths,
getButtonDisabled: getButtonDisabled
};
@import '../common/index.wxss';.van-calendar{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;height:100%;height:var(--calendar-height,100%);background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:80%;height:var(--calendar-popup-height,80%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-flex:1;flex:1;overflow:auto;-webkit-overflow-scrolling:touch}.van-calendar__footer{-webkit-flex-shrink:0;flex-shrink:0;padding:0 16px;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:36px!important;height:var(--calendar-confirm-button-height,36px)!important;margin:7px 0!important;margin:var(--calendar-confirm-button-margin,7px 0)!important;line-height:34px!important;line-height:var(--calendar-confirm-button-line-height,34px)!important}
\ No newline at end of file
export declare const ROW_HEIGHT = 64;
export declare function formatMonthTitle(date: Date): string;
export declare function compareMonth(
date1: Date | number,
date2: Date | number
): 0 | 1 | -1;
export declare function compareDay(
day1: Date | number,
day2: Date | number
): 0 | 1 | -1;
export declare function getDayByOffset(date: Date, offset: number): Date;
export declare function getPrevDay(date: Date): Date;
export declare function getNextDay(date: Date): Date;
export declare function calcDateNum(date: [Date, Date]): number;
export declare function copyDates(dates: Date | Date[]): Date | Date[];
export declare function getMonthEndDay(year: number, month: number): number;
export declare function getMonths(minDate: number, maxDate: number): any[];
export const ROW_HEIGHT = 64;
export function formatMonthTitle(date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
return `${date.getFullYear()}${date.getMonth() + 1}月`;
}
export function compareMonth(date1, date2) {
if (!(date1 instanceof Date)) {
date1 = new Date(date1);
}
if (!(date2 instanceof Date)) {
date2 = new Date(date2);
}
const year1 = date1.getFullYear();
const year2 = date2.getFullYear();
const month1 = date1.getMonth();
const month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
export function compareDay(day1, day2) {
if (!(day1 instanceof Date)) {
day1 = new Date(day1);
}
if (!(day2 instanceof Date)) {
day2 = new Date(day2);
}
const compareMonthResult = compareMonth(day1, day2);
if (compareMonthResult === 0) {
const date1 = day1.getDate();
const date2 = day2.getDate();
return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
}
return compareMonthResult;
}
export function getDayByOffset(date, offset) {
date = new Date(date);
date.setDate(date.getDate() + offset);
return date;
}
export function getPrevDay(date) {
return getDayByOffset(date, -1);
}
export function getNextDay(date) {
return getDayByOffset(date, 1);
}
export function calcDateNum(date) {
const day1 = new Date(date[0]).getTime();
const day2 = new Date(date[1]).getTime();
return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
}
export function copyDates(dates) {
if (Array.isArray(dates)) {
return dates.map((date) => {
if (date === null) {
return date;
}
return new Date(date);
});
}
return new Date(dates);
}
export function getMonthEndDay(year, month) {
return 32 - new Date(year, month - 1, 32).getDate();
}
export function getMonths(minDate, maxDate) {
const months = [];
const cursor = new Date(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (compareMonth(cursor, maxDate) !== 1);
return months;
}
/* eslint-disable */
function getMonthEndDay(year, month) {
return 32 - getDate(year, month - 1, 32).getDate();
}
function compareMonth(date1, date2) {
date1 = getDate(date1);
date2 = getDate(date2);
var year1 = date1.getFullYear();
var year2 = date2.getFullYear();
var month1 = date1.getMonth();
var month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
module.exports = {
getMonthEndDay: getMonthEndDay,
compareMonth: compareMonth
};
...@@ -16,23 +16,34 @@ VantComponent({ ...@@ -16,23 +16,34 @@ VantComponent({
desc: String, desc: String,
thumb: String, thumb: String,
title: String, title: String,
price: String, price: {
type: String,
observer: 'updatePrice',
},
centered: Boolean, centered: Boolean,
lazyLoad: Boolean, lazyLoad: Boolean,
thumbLink: String, thumbLink: String,
originPrice: String, originPrice: String,
thumbMode: { thumbMode: {
type: String, type: String,
value: 'aspectFit' value: 'aspectFit',
}, },
currency: { currency: {
type: String, type: String,
value: '¥' value: '¥',
} },
}, },
methods: { methods: {
updatePrice() {
const { price } = this.data;
const priceArr = price.toString().split('.');
this.setData({
integerStr: priceArr[0],
decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
});
},
onClickThumb() { onClickThumb() {
this.jumpLink('thumbLink'); this.jumpLink('thumbLink');
} },
} },
}); });
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
</van-tag> </van-tag>
</view> </view>
<view class="van-card__content"> <view class="van-card__content {{ utils.bem('card__content', { center: centered }) }}">
<view>
<view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view> <view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
<slot wx:else name="title" /> <slot wx:else name="title" />
...@@ -29,11 +30,15 @@ ...@@ -29,11 +30,15 @@
<slot wx:else name="desc" /> <slot wx:else name="desc" />
<slot name="tags" /> <slot name="tags" />
</view>
<view class="van-card__bottom"> <view class="van-card__bottom">
<view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }} {{ price }}</view> <slot name="price-top" />
<view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }}<text class="van-card__price-integer">{{ integerStr }}</text><text class="van-card__price-decimal">{{ decimalStr }}</text></view>
<slot wx:else name="price" />
<view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view> <view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
<view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view> <view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
<slot wx:else name="num" />
<slot name="bottom" /> <slot name="bottom" />
</view> </view>
</view> </view>
......
@import '../common/index.wxss';.van-card{position:relative;padding:5px 15px;font-size:12px;color:#333;background-color:#fafafa;box-sizing:border-box}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;width:90px;height:90px;margin-right:10px;-webkit-flex:none;flex:none}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%}.van-card__content{position:relative;min-width:0;-webkit-flex:1;flex:1}.van-card__desc,.van-card__title{word-break:break-all}.van-card__title{font-weight:700;line-height:16px}.van-card__desc{color:#7d7e80}.van-card__bottom,.van-card__desc{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#f44}.van-card__origin-price{display:inline-block;margin-left:5px;font-size:10px;color:#7d7e80;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{position:absolute;top:2px;left:0}.van-card__footer{width:100%;text-align:right;-webkit-flex:none;flex:none} @import '../common/index.wxss';.van-card{position:relative;box-sizing:border-box;padding:8px 16px;padding:var(--card-padding,8px 16px);font-size:12px;font-size:var(--card-font-size,12px);color:#323233;color:var(--card-text-color,#323233);background-color:#fafafa;background-color:var(--card-background-color,#fafafa)}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;-webkit-flex:none;flex:none;width:88px;width:var(--card-thumb-size,88px);height:88px;height:var(--card-thumb-size,88px);margin-right:8px;margin-right:var(--padding-xs,8px)}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%;border-radius:8px;border-radius:var(--border-radius-lg,8px)}.van-card__content{position:relative;display:-webkit-flex;display:flex;-webkit-flex:1;flex:1;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:space-between;justify-content:space-between;min-width:0;min-height:88px;min-height:var(--card-thumb-size,88px)}.van-card__content--center{-webkit-justify-content:center;justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:16px;line-height:var(--card-title-line-height,16px)}.van-card__desc{line-height:20px;line-height:var(--card-desc-line-height,20px);color:#646566;color:var(--card-desc-color,#646566)}.van-card__bottom{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#ee0a24;color:var(--card-price-color,#ee0a24);font-size:12px;font-size:var(--card-price-font-size,12px)}.van-card__price-integer{font-size:16px;font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif;font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{display:inline-block;margin-left:5px;text-decoration:line-through;font-size:10px;font-size:var(--card-origin-price-font-size,10px);color:#646566;color:var(--card-origin-price-color,#646566)}.van-card__num{float:right}.van-card__tag{position:absolute;top:2px;left:0}.van-card__footer{-webkit-flex:none;flex:none;width:100%;text-align:right}
\ No newline at end of file \ No newline at end of file
...@@ -4,7 +4,7 @@ VantComponent({ ...@@ -4,7 +4,7 @@ VantComponent({
title: String, title: String,
border: { border: {
type: Boolean, type: Boolean,
value: true value: true,
} },
} },
}); });
@import '../common/index.wxss';.van-cell-group__title{font-size:14px;padding:15px 15px 5px;color:#999;line-height:16px} @import '../common/index.wxss';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}
\ No newline at end of file \ No newline at end of file
...@@ -6,7 +6,7 @@ VantComponent({ ...@@ -6,7 +6,7 @@ VantComponent({
'label-class', 'label-class',
'value-class', 'value-class',
'right-icon-class', 'right-icon-class',
'hover-class' 'hover-class',
], ],
mixins: [link], mixins: [link],
props: { props: {
...@@ -25,13 +25,13 @@ VantComponent({ ...@@ -25,13 +25,13 @@ VantComponent({
useLabelSlot: Boolean, useLabelSlot: Boolean,
border: { border: {
type: Boolean, type: Boolean,
value: true value: true,
} },
}, },
methods: { methods: {
onClick(event) { onClick(event) {
this.$emit('click', event.detail); this.$emit('click', event.detail);
this.jumpLink(); this.jumpLink();
} },
} },
}); });
@import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;width:100%;padding:10px 15px;font-size:14px;line-height:24px;color:#333;background-color:#fff;box-sizing:border-box}.van-cell:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:auto;left:15px;right:0;bottom:0;-webkit-transform:scaleY(.5);transform:scaleY(.5);border-bottom:1px solid #eee}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff}.van-cell__label{margin-top:3px;font-size:12px;line-height:18px;color:#999}.van-cell__value{overflow:hidden;color:#999;text-align:right;vertical-align:middle}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;height:24px;font-size:16px;-webkit-align-items:center;align-items:center}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#999}.van-cell__left-icon{line-height:24px;vertical-align:middle}.van-cell__right-icon{line-height:24px}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;left:7px;font-size:14px;color:#f44;content:"*"}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-bottom:12px}.van-cell--large .van-cell__title{font-size:16px}.van-cell--large .van-cell__label{font-size:14px} @import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:10px 16px;padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);font-size:14px;font-size:var(--cell-font-size,14px);line-height:24px;line-height:var(--cell-line-height,24px);color:#323233;color:var(--cell-text-color,#323233);background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:auto;right:0;bottom:0;left:16px;border-bottom:1px solid #ebedf0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell__label{margin-top:3px;margin-top:var(--cell-label-margin-top,3px);font-size:12px;font-size:var(--cell-label-font-size,12px);line-height:18px;line-height:var(--cell-label-line-height,18px);color:#969799;color:var(--cell-label-color,#969799)}.van-cell__value{overflow:hidden;text-align:right;vertical-align:middle;color:#969799;color:var(--cell-value-color,#969799)}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:24px;height:var(--cell-line-height,24px);font-size:16px;font-size:var(--cell-icon-size,16px)}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#969799;color:var(--cell-right-icon-color,#969799)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:24px;line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5;background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;content:"*";left:8px;left:var(--padding-xs,8px);font-size:14px;font-size:var(--cell-font-size,14px);color:#ee0a24;color:var(--cell-required-color,#ee0a24)}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-top:var(--cell-large-vertical-padding,12px);padding-bottom:12px;padding-bottom:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:16px;font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__value{font-size:16px;font-size:var(--cell-large-value-font-size,16px)}.van-cell--large .van-cell__label{font-size:14px;font-size:var(--cell-large-label-font-size,14px)}
\ No newline at end of file \ No newline at end of file
...@@ -4,25 +4,21 @@ VantComponent({ ...@@ -4,25 +4,21 @@ VantComponent({
relation: { relation: {
name: 'checkbox', name: 'checkbox',
type: 'descendant', type: 'descendant',
current: 'checkbox-group',
linked(target) { linked(target) {
this.children = this.children || [];
this.children.push(target);
this.updateChild(target); this.updateChild(target);
}, },
unlinked(target) {
this.children = this.children.filter((child) => child !== target);
}
}, },
props: { props: {
max: Number, max: Number,
value: { value: {
type: Array, type: Array,
observer: 'updateChildren' observer: 'updateChildren',
}, },
disabled: { disabled: {
type: Boolean, type: Boolean,
observer: 'updateChildren' observer: 'updateChildren',
} },
}, },
methods: { methods: {
updateChildren() { updateChildren() {
...@@ -30,10 +26,10 @@ VantComponent({ ...@@ -30,10 +26,10 @@ VantComponent({
}, },
updateChild(child) { updateChild(child) {
const { value, disabled } = this.data; const { value, disabled } = this.data;
child.set({ child.setData({
value: value.indexOf(child.data.name) !== -1, value: value.indexOf(child.data.name) !== -1,
disabled: disabled || child.data.disabled parentDisabled: disabled,
}); });
} },
} },
}); });
...@@ -8,12 +8,7 @@ VantComponent({ ...@@ -8,12 +8,7 @@ VantComponent({
relation: { relation: {
name: 'checkbox-group', name: 'checkbox-group',
type: 'ancestor', type: 'ancestor',
linked(target) { current: 'checkbox',
this.parent = target;
},
unlinked() {
this.parent = null;
}
}, },
classes: ['icon-class', 'label-class'], classes: ['icon-class', 'label-class'],
props: { props: {
...@@ -25,27 +20,33 @@ VantComponent({ ...@@ -25,27 +20,33 @@ VantComponent({
labelDisabled: Boolean, labelDisabled: Boolean,
shape: { shape: {
type: String, type: String,
value: 'round' value: 'round',
} },
iconSize: {
type: null,
value: 20,
},
},
data: {
parentDisabled: false,
}, },
methods: { methods: {
emitChange(value) { emitChange(value) {
if (this.parent) { if (this.parent) {
this.setParentValue(this.parent, value); this.setParentValue(this.parent, value);
} } else {
else {
emit(this, value); emit(this, value);
} }
}, },
toggle() { toggle() {
const { disabled, value } = this.data; const { parentDisabled, disabled, value } = this.data;
if (!disabled) { if (!disabled && !parentDisabled) {
this.emitChange(!value); this.emitChange(!value);
} }
}, },
onClickLabel() { onClickLabel() {
const { labelDisabled, disabled, value } = this.data; const { labelDisabled, parentDisabled, disabled, value } = this.data;
if (!disabled && !labelDisabled) { if (!disabled && !labelDisabled && !parentDisabled) {
this.emitChange(!value); this.emitChange(!value);
} }
}, },
...@@ -61,14 +62,13 @@ VantComponent({ ...@@ -61,14 +62,13 @@ VantComponent({
parentValue.push(name); parentValue.push(name);
emit(parent, parentValue); emit(parent, parentValue);
} }
} } else {
else {
const index = parentValue.indexOf(name); const index = parentValue.indexOf(name);
if (index !== -1) { if (index !== -1) {
parentValue.splice(index, 1); parentValue.splice(index, 1);
emit(parent, parentValue); emit(parent, parentValue);
} }
} }
} },
} },
}); });
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="van-checkbox custom-class"> <view class="van-checkbox custom-class">
<view class="van-checkbox__icon-wrap" bindtap="toggle"> <view class="van-checkbox__icon-wrap" bindtap="toggle">
...@@ -6,13 +7,14 @@ ...@@ -6,13 +7,14 @@
<van-icon <van-icon
wx:else wx:else
name="success" name="success"
class="{{ utils.bem('checkbox__icon', [shape, { disabled, checked: value }]) }}" size="0.8em"
style="{{ checkedColor && value && !disabled ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}" class="{{ utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }]) }}"
style="{{ computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) }}"
custom-class="icon-class" custom-class="icon-class"
custom-style="line-height: 20px;" custom-style="line-height: 1.25em;"
/> />
</view> </view>
<view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled }]) }}" bindtap="onClickLabel"> <view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}" bindtap="onClickLabel">
<slot /> <slot />
</view> </view>
</view> </view>
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) {
var styles = [['font-size', utils.addUnit(iconSize)]];
if (checkedColor && value && !disabled && !parentDisabled) {
styles.push(['border-color', checkedColor]);
styles.push(['background-color', checkedColor]);
}
return styles
.map(function(item) {
return item.join(':');
})
.join(';');
}
module.exports = {
iconStyle: iconStyle
};
@import '../common/index.wxss';.van-checkbox{display:-webkit-flex;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:block;width:20px;height:20px;font-size:14px;color:transparent;text-align:center;border:1px solid #e5e5e5;box-sizing:border-box;transition:.2s}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;background-color:#1989fa;border-color:#1989fa}.van-checkbox__icon--disabled{background-color:#eee;border-color:#c9c9c9}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c9c9c9}.van-checkbox__label{margin-left:10px;color:#333;word-break:break-all}.van-checkbox__label--left{float:left;margin:0 10px 0 0}.van-checkbox__label--disabled{color:#c9c9c9}.van-checkbox__label:empty{margin:0} @import '../common/index.wxss';.van-checkbox{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px;line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;font-size:20px;font-size:var(--checkbox-size,20px);border:1px solid #c8c9cc;border:1px solid var(--checkbox-border-color,#c8c9cc);transition-duration:.2s;transition-duration:var(--checkbox-transition-duration,.2s)}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--checkbox-checked-icon-color,#1989fa)}.van-checkbox__icon--disabled{background-color:#ebedf0;background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c8c9cc;color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;margin-left:10px;margin-left:var(--checkbox-label-margin,10px);color:#323233;color:var(--checkbox-label-color,#323233)}.van-checkbox__label--left{float:left;margin:0 10px 0 0;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:#c8c9cc;color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component';
import { isObj } from '../common/utils';
import { BLUE, WHITE } from '../common/color';
function format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
const PERIMETER = 2 * Math.PI;
const BEGIN_ANGLE = -Math.PI / 2;
const STEP = 1;
VantComponent({
props: {
text: String,
lineCap: {
type: String,
value: 'round',
},
value: {
type: Number,
value: 0,
observer: 'reRender',
},
speed: {
type: Number,
value: 50,
},
size: {
type: Number,
value: 100,
},
fill: String,
layerColor: {
type: String,
value: WHITE,
},
color: {
type: [String, Object],
value: BLUE,
observer: 'setHoverColor',
},
type: {
type: String,
value: '',
},
strokeWidth: {
type: Number,
value: 4,
},
clockwise: {
type: Boolean,
value: true,
},
},
data: {
hoverColor: BLUE,
},
methods: {
getContext() {
if (!this.ctx) {
this.ctx = wx.createCanvasContext('van-circle', this);
}
return this.ctx;
},
setHoverColor() {
const { color, size, type } = this.data;
const context = type ? this.getContext(type) : this.getContext();
let hoverColor = color;
if (isObj(color)) {
const LinearColor = context.createLinearGradient(size, 0, 0, 0);
Object.keys(color)
.sort((a, b) => parseFloat(a) - parseFloat(b))
.map((key) =>
LinearColor.addColorStop(parseFloat(key) / 100, color[key])
);
hoverColor = LinearColor;
}
this.setData({ hoverColor });
},
presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
const { strokeWidth, lineCap, clockwise, size } = this.data;
const position = size / 2;
const radius = position - strokeWidth / 2;
context.setStrokeStyle(strokeStyle);
context.setLineWidth(strokeWidth);
context.setLineCap(lineCap);
context.beginPath();
context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
context.stroke();
if (fill) {
context.setFillStyle(fill);
context.fill();
}
},
renderLayerCircle(context) {
const { layerColor, fill } = this.data;
this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
},
renderHoverCircle(context, formatValue) {
const { clockwise, hoverColor } = this.data;
// 结束角度
const progress = PERIMETER * (formatValue / 100);
const endAngle = clockwise
? BEGIN_ANGLE + progress
: 3 * Math.PI - (BEGIN_ANGLE + progress);
this.presetCanvas(context, hoverColor, BEGIN_ANGLE, endAngle);
},
drawCircle(currentValue) {
const { size, type } = this.data;
const context = type ? this.getContext(type) : this.getContext();
context.clearRect(0, 0, size, size);
this.renderLayerCircle(context);
const formatValue = format(currentValue);
if (formatValue !== 0) {
this.renderHoverCircle(context, formatValue);
}
context.draw();
},
reRender() {
// tofector 动画暂时没有想到好的解决方案
const { value, speed } = this.data;
if (speed <= 0 || speed > 1000) {
this.drawCircle(value);
return;
}
this.clearInterval();
this.currentValue = this.currentValue || 0;
this.interval = setInterval(() => {
if (this.currentValue !== value) {
if (this.currentValue < value) {
this.currentValue += STEP;
} else {
this.currentValue -= STEP;
}
this.drawCircle(this.currentValue);
} else {
this.clearInterval();
}
}, 1000 / speed);
},
clearInterval() {
if (this.interval) {
clearInterval(this.interval);
this.interval = null;
}
},
},
created() {
const { value } = this.data;
this.currentValue = value;
this.drawCircle(value);
},
destroyed() {
this.ctx = null;
this.clearInterval();
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-circle">
<canvas class="van-circle__canvas" style="width: {{ utils.addUnit(size) }};height:{{ utils.addUnit(size) }}" canvas-id="van-circle"></canvas>
<view wx:if="{{ !text }}" class="van-circle__text">
<slot></slot>
</view>
<cover-view wx:else class="van-circle__text">{{ text }}</cover-view>
</view>
\ No newline at end of file
@import '../common/index.wxss';.van-circle{position:relative;display:inline-block;text-align:center}.van-circle__text{position:absolute;top:50%;left:0;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#323233;color:var(--circle-text-color,#323233)}
\ No newline at end of file
...@@ -2,22 +2,25 @@ import { VantComponent } from '../common/component'; ...@@ -2,22 +2,25 @@ import { VantComponent } from '../common/component';
VantComponent({ VantComponent({
relation: { relation: {
name: 'row', name: 'row',
type: 'ancestor' type: 'ancestor',
current: 'col',
}, },
props: { props: {
span: Number, span: Number,
offset: Number offset: Number,
}, },
data: { data: {
style: '' viewStyle: '',
}, },
methods: { methods: {
setGutter(gutter) { setGutter(gutter) {
const padding = `${gutter / 2}px`; const padding = `${gutter / 2}px`;
const style = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : ''; const viewStyle = gutter
if (style !== this.data.style) { ? `padding-left: ${padding}; padding-right: ${padding};`
this.set({ style }); : '';
} if (viewStyle !== this.data.viewStyle) {
} this.setData({ viewStyle });
} }
},
},
}); });
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<view <view
class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}" class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
style="{{ style }}" style="{{ viewStyle }}"
> >
<slot /> <slot />
</view> </view>
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
const nextTick = () => new Promise(resolve => setTimeout(resolve, 20)); const nextTick = () => new Promise((resolve) => setTimeout(resolve, 20));
VantComponent({ VantComponent({
classes: ['title-class', 'content-class'], classes: ['title-class', 'content-class'],
relation: { relation: {
name: 'collapse', name: 'collapse',
type: 'ancestor', type: 'ancestor',
linked(parent) { current: 'collapse-item',
this.parent = parent;
}
}, },
props: { props: {
name: null, name: null,
...@@ -19,17 +17,17 @@ VantComponent({ ...@@ -19,17 +17,17 @@ VantComponent({
clickable: Boolean, clickable: Boolean,
border: { border: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
isLink: { isLink: {
type: Boolean, type: Boolean,
value: true value: true,
} },
}, },
data: { data: {
contentHeight: 0, contentHeight: 0,
expanded: false, expanded: false,
transition: false transition: false,
}, },
mounted() { mounted() {
this.updateExpanded() this.updateExpanded()
...@@ -39,7 +37,7 @@ VantComponent({ ...@@ -39,7 +37,7 @@ VantComponent({
if (this.data.expanded) { if (this.data.expanded) {
data.contentHeight = 'auto'; data.contentHeight = 'auto';
} }
this.set(data); this.setData(data);
}); });
}, },
methods: { methods: {
...@@ -68,7 +66,7 @@ VantComponent({ ...@@ -68,7 +66,7 @@ VantComponent({
.then((height) => { .then((height) => {
if (expanded) { if (expanded) {
return this.set({ return this.set({
contentHeight: height ? `${height}px` : 'auto' contentHeight: height ? `${height}px` : 'auto',
}); });
} }
return this.set({ contentHeight: `${height}px` }) return this.set({ contentHeight: `${height}px` })
...@@ -87,10 +85,10 @@ VantComponent({ ...@@ -87,10 +85,10 @@ VantComponent({
}, },
onTransitionEnd() { onTransitionEnd() {
if (this.data.expanded) { if (this.data.expanded) {
this.set({ this.setData({
contentHeight: 'auto' contentHeight: 'auto',
}); });
} }
} },
} },
}); });
@import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:.3s}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c9c9c9!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__wrapper--transition{transition:height .3s ease-in-out}.van-collapse-item__content{padding:15px;font-size:13px;line-height:1.5;color:#999;background-color:#fff} @import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;transition:-webkit-transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s),-webkit-transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c8c9cc!important;color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important;background-color:var(--white,#fff)!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__wrapper--transition{transition:height .3s ease-in-out}.van-collapse-item__content{padding:15px;padding:var(--collapse-item-content-padding,15px);color:#969799;color:var(--collapse-item-content-text-color,#969799);font-size:13px;font-size:var(--collapse-item-content-font-size,13px);line-height:1.5;line-height:var(--collapse-item-content-line-height,1.5);background-color:#fff;background-color:var(--collapse-item-content-background-color,#fff)}
\ No newline at end of file \ No newline at end of file
...@@ -3,29 +3,21 @@ VantComponent({ ...@@ -3,29 +3,21 @@ VantComponent({
relation: { relation: {
name: 'collapse-item', name: 'collapse-item',
type: 'descendant', type: 'descendant',
linked(child) { current: 'collapse',
this.children.push(child);
},
unlinked(child) {
this.children = this.children.filter((item) => item !== child);
}
}, },
props: { props: {
value: { value: {
type: null, type: null,
observer: 'updateExpanded' observer: 'updateExpanded',
}, },
accordion: { accordion: {
type: Boolean, type: Boolean,
observer: 'updateExpanded' observer: 'updateExpanded',
}, },
border: { border: {
type: Boolean, type: Boolean,
value: true value: true,
}
}, },
beforeCreate() {
this.children = [];
}, },
methods: { methods: {
updateExpanded() { updateExpanded() {
...@@ -35,16 +27,21 @@ VantComponent({ ...@@ -35,16 +27,21 @@ VantComponent({
}, },
switch(name, expanded) { switch(name, expanded) {
const { accordion, value } = this.data; const { accordion, value } = this.data;
const changeItem = name;
if (!accordion) { if (!accordion) {
name = expanded name = expanded
? (value || []).concat(name) ? (value || []).concat(name)
: (value || []).filter((activeName) => activeName !== name); : (value || []).filter((activeName) => activeName !== name);
} } else {
else {
name = expanded ? name : ''; name = expanded ? name : '';
} }
if (expanded) {
this.$emit('open', changeItem);
} else {
this.$emit('close', changeItem);
}
this.$emit('change', name); this.$emit('change', name);
this.$emit('input', name); this.$emit('input', name);
} },
} },
}); });
export declare const RED = "#f44"; export declare const RED = "#ee0a24";
export declare const BLUE = "#1989fa"; export declare const BLUE = "#1989fa";
export declare const WHITE = "#fff";
export declare const GREEN = "#07c160"; export declare const GREEN = "#07c160";
export declare const ORANGE = "#ff976a"; export declare const ORANGE = "#ff976a";
export declare const GRAY = "#323233";
export declare const GRAY_DARK = "#969799";
export const RED = '#f44'; export const RED = '#ee0a24';
export const BLUE = '#1989fa'; export const BLUE = '#1989fa';
export const WHITE = '#fff';
export const GREEN = '#07c160'; export const GREEN = '#07c160';
export const ORANGE = '#ff976a'; export const ORANGE = '#ff976a';
export const GRAY = '#323233';
export const GRAY_DARK = '#969799';
import { VantComponentOptions, CombinedComponentInstance } from '../definitions/index'; import { VantComponentOptions, CombinedComponentInstance } from '../definitions/index';
declare function VantComponent<Data, Props, Methods, Computed>(vantOptions?: VantComponentOptions<Data, Props, Methods, Computed, CombinedComponentInstance<Data, Props, Methods, Computed>>): void; declare function VantComponent<Data, Props, Methods>(vantOptions?: VantComponentOptions<Data, Props, Methods, CombinedComponentInstance<Data, Props, Methods>>): void;
export { VantComponent }; export { VantComponent };
import { basic } from '../mixins/basic'; import { basic } from '../mixins/basic';
import { observe } from '../mixins/observer/index'; const relationFunctions = {
ancestor: {
linked(parent) {
this.parent = parent;
},
unlinked() {
this.parent = null;
},
},
descendant: {
linked(child) {
this.children = this.children || [];
this.children.push(child);
},
unlinked(child) {
this.children = (this.children || []).filter((it) => it !== child);
},
},
};
function mapKeys(source, target, map) { function mapKeys(source, target, map) {
Object.keys(map).forEach(key => { Object.keys(map).forEach((key) => {
if (source[key]) { if (source[key]) {
target[map[key]] = source[key]; target[map[key]] = source[key];
} }
}); });
} }
function makeRelation(options, vantOptions, relation) {
const { type, name, linked, unlinked, linkChanged } = relation;
const { beforeCreate, destroyed } = vantOptions;
if (type === 'descendant') {
options.created = function () {
beforeCreate && beforeCreate.bind(this)();
this.children = this.children || [];
};
options.detached = function () {
this.children = [];
destroyed && destroyed.bind(this)();
};
}
options.relations = Object.assign(options.relations || {}, {
[`../${name}/index`]: {
type,
linked(node) {
relationFunctions[type].linked.bind(this)(node);
linked && linked.bind(this)(node);
},
linkChanged(node) {
linkChanged && linkChanged.bind(this)(node);
},
unlinked(node) {
relationFunctions[type].unlinked.bind(this)(node);
unlinked && unlinked.bind(this)(node);
},
},
});
}
function VantComponent(vantOptions = {}) { function VantComponent(vantOptions = {}) {
const options = {}; const options = {};
mapKeys(vantOptions, options, { mapKeys(vantOptions, options, {
...@@ -19,13 +67,11 @@ function VantComponent(vantOptions = {}) { ...@@ -19,13 +67,11 @@ function VantComponent(vantOptions = {}) {
mounted: 'ready', mounted: 'ready',
relations: 'relations', relations: 'relations',
destroyed: 'detached', destroyed: 'detached',
classes: 'externalClasses' classes: 'externalClasses',
}); });
const { relation } = vantOptions; const { relation } = vantOptions;
if (relation) { if (relation) {
options.relations = Object.assign(options.relations || {}, { makeRelation(options, vantOptions, relation);
[`../${relation.name}/index`]: relation
});
} }
// add default externalClasses // add default externalClasses
options.externalClasses = options.externalClasses || []; options.externalClasses = options.externalClasses || [];
...@@ -37,12 +83,19 @@ function VantComponent(vantOptions = {}) { ...@@ -37,12 +83,19 @@ function VantComponent(vantOptions = {}) {
if (vantOptions.field) { if (vantOptions.field) {
options.behaviors.push('wx://form-field'); options.behaviors.push('wx://form-field');
} }
if (options.properties) {
Object.keys(options.properties).forEach((name) => {
if (Array.isArray(options.properties[name])) {
// miniprogram do not allow multi type
options.properties[name] = null;
}
});
}
// add default options // add default options
options.options = { options.options = {
multipleSlots: true, multipleSlots: true,
addGlobalClass: true addGlobalClass: true,
}; };
observe(vantOptions, options);
Component(options); Component(options);
} }
export { VantComponent }; export { VantComponent };
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{content:"";display:table;clear:both}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px} .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{display:table;clear:both;content:""}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file \ No newline at end of file
.van-clearfix:after{content:"";display:table;clear:both} .van-clearfix:after{display:table;clear:both;content:""}
\ No newline at end of file \ No newline at end of file
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3} .van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
\ No newline at end of file \ No newline at end of file
.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{content:" ";position:absolute;pointer-events:none;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;top:-50%;left:-50%;right:-50%;bottom:-50%;-webkit-transform:scale(.5);transform:scale(.5);border:0 solid #eee}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px} .van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file \ No newline at end of file
...@@ -4,4 +4,5 @@ export declare function isObj(x: any): boolean; ...@@ -4,4 +4,5 @@ export declare function isObj(x: any): boolean;
export declare function isNumber(value: any): boolean; export declare function isNumber(value: any): boolean;
export declare function range(num: number, min: number, max: number): number; export declare function range(num: number, min: number, max: number): number;
export declare function nextTick(fn: Function): void; export declare function nextTick(fn: Function): void;
export declare function getSystemInfoSync(): WechatMiniprogram.GetSystemInfoSuccessCallbackResult; export declare function getSystemInfoSync(): WechatMiniprogram.GetSystemInfoSyncResult;
export declare function addUnit(value?: string | number): string | undefined;
...@@ -6,7 +6,7 @@ export function isObj(x) { ...@@ -6,7 +6,7 @@ export function isObj(x) {
return x !== null && (type === 'object' || type === 'function'); return x !== null && (type === 'object' || type === 'function');
} }
export function isNumber(value) { export function isNumber(value) {
return /^\d+$/.test(value); return /^\d+(\.\d+)?$/.test(value);
} }
export function range(num, min, max) { export function range(num, min, max) {
return Math.min(Math.max(num, min), max); return Math.min(Math.max(num, min), max);
...@@ -23,3 +23,10 @@ export function getSystemInfoSync() { ...@@ -23,3 +23,10 @@ export function getSystemInfoSync() {
} }
return systemInfo; return systemInfo;
} }
export function addUnit(value) {
if (!isDef(value)) {
return undefined;
}
value = String(value);
return isNumber(value) ? `${value}px` : value;
}
export declare function canIUseModel(): boolean;
import { getSystemInfoSync } from './utils';
function compareVersion(v1, v2) {
v1 = v1.split('.');
v2 = v2.split('.');
const len = Math.max(v1.length, v2.length);
while (v1.length < len) {
v1.push('0');
}
while (v2.length < len) {
v2.push('0');
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i], 10);
const num2 = parseInt(v2[i], 10);
if (num1 > num2) {
return 1;
}
if (num1 < num2) {
return -1;
}
}
return 0;
}
export function canIUseModel() {
const system = getSystemInfoSync();
return compareVersion(system.SDKVersion, '2.9.3') >= 0;
}
import { VantComponent } from '../common/component';
import { isSameSecond, parseFormat, parseTimeData } from './utils';
function simpleTick(fn) {
return setTimeout(fn, 30);
}
VantComponent({
props: {
useSlot: Boolean,
millisecond: Boolean,
time: {
type: Number,
observer: 'reset',
},
format: {
type: String,
value: 'HH:mm:ss',
},
autoStart: {
type: Boolean,
value: true,
},
},
data: {
timeData: parseTimeData(0),
formattedTime: '0',
},
destroyed() {
clearTimeout(this.tid);
this.tid = null;
},
methods: {
// 开始
start() {
if (this.counting) {
return;
}
this.counting = true;
this.endTime = Date.now() + this.remain;
this.tick();
},
// 暂停
pause() {
this.counting = false;
clearTimeout(this.tid);
},
// 重置
reset() {
this.pause();
this.remain = this.data.time;
this.setRemain(this.remain);
if (this.data.autoStart) {
this.start();
}
},
tick() {
if (this.data.millisecond) {
this.microTick();
} else {
this.macroTick();
}
},
microTick() {
this.tid = simpleTick(() => {
this.setRemain(this.getRemain());
if (this.remain !== 0) {
this.microTick();
}
});
},
macroTick() {
this.tid = simpleTick(() => {
const remain = this.getRemain();
if (!isSameSecond(remain, this.remain) || remain === 0) {
this.setRemain(remain);
}
if (this.remain !== 0) {
this.macroTick();
}
});
},
getRemain() {
return Math.max(this.endTime - Date.now(), 0);
},
setRemain(remain) {
this.remain = remain;
const timeData = parseTimeData(remain);
if (this.data.useSlot) {
this.$emit('change', timeData);
}
this.setData({
formattedTime: parseFormat(this.data.format, timeData),
});
if (remain === 0) {
this.pause();
this.$emit('finish');
}
},
},
});
<view class="van-count-down">
<slot wx:if="{{ useSlot }}"/>
<block wx:else>{{ formattedTime }}</block>
</view>
@import '../common/index.wxss';.van-count-down{color:#323233;color:var(--count-down-text-color,#323233);font-size:14px;font-size:var(--count-down-font-size,14px);line-height:20px;line-height:var(--count-down-line-height,20px)}
\ No newline at end of file
export declare type TimeData = {
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
};
export declare function parseTimeData(time: number): TimeData;
export declare function parseFormat(format: string, timeData: TimeData): string;
export declare function isSameSecond(time1: number, time2: number): boolean;
function padZero(num, targetLength = 2) {
let str = num + '';
while (str.length < targetLength) {
str = '0' + str;
}
return str;
}
const SECOND = 1000;
const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
export function parseTimeData(time) {
const days = Math.floor(time / DAY);
const hours = Math.floor((time % DAY) / HOUR);
const minutes = Math.floor((time % HOUR) / MINUTE);
const seconds = Math.floor((time % MINUTE) / SECOND);
const milliseconds = Math.floor(time % SECOND);
return {
days,
hours,
minutes,
seconds,
milliseconds,
};
}
export function parseFormat(format, timeData) {
const { days } = timeData;
let { hours, minutes, seconds, milliseconds } = timeData;
if (format.indexOf('DD') === -1) {
hours += days * 24;
} else {
format = format.replace('DD', padZero(days));
}
if (format.indexOf('HH') === -1) {
minutes += hours * 60;
} else {
format = format.replace('HH', padZero(hours));
}
if (format.indexOf('mm') === -1) {
seconds += minutes * 60;
} else {
format = format.replace('mm', padZero(minutes));
}
if (format.indexOf('ss') === -1) {
milliseconds += seconds * 1000;
} else {
format = format.replace('ss', padZero(seconds));
}
return format.replace('SSS', padZero(milliseconds, 3));
}
export function isSameSecond(time1, time2) {
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
}
...@@ -20,8 +20,7 @@ function times(n, iteratee) { ...@@ -20,8 +20,7 @@ function times(n, iteratee) {
return result; return result;
} }
function getTrueValue(formattedValue) { function getTrueValue(formattedValue) {
if (!formattedValue) if (!formattedValue) return;
return;
while (isNaN(parseInt(formattedValue, 10))) { while (isNaN(parseInt(formattedValue, 10))) {
formattedValue = formattedValue.slice(1); formattedValue = formattedValue.slice(1);
} }
...@@ -33,47 +32,59 @@ function getMonthEndDay(year, month) { ...@@ -33,47 +32,59 @@ function getMonthEndDay(year, month) {
const defaultFormatter = (_, value) => value; const defaultFormatter = (_, value) => value;
VantComponent({ VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'], classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign({}, pickerProps, { formatter: { props: Object.assign(Object.assign({}, pickerProps), {
type: Function, value: {
value: defaultFormatter type: null,
}, value: null, type: { observer: 'updateValue',
},
filter: null,
type: {
type: String, type: String,
value: 'datetime' value: 'datetime',
}, showToolbar: { observer: 'updateValue',
},
showToolbar: {
type: Boolean, type: Boolean,
value: true value: true,
}, minDate: { },
formatter: {
type: null,
value: defaultFormatter,
},
minDate: {
type: Number, type: Number,
value: new Date(currentYear - 10, 0, 1).getTime() value: new Date(currentYear - 10, 0, 1).getTime(),
}, maxDate: { observer: 'updateValue',
},
maxDate: {
type: Number, type: Number,
value: new Date(currentYear + 10, 11, 31).getTime() value: new Date(currentYear + 10, 11, 31).getTime(),
}, minHour: { observer: 'updateValue',
},
minHour: {
type: Number, type: Number,
value: 0 value: 0,
}, maxHour: { observer: 'updateValue',
},
maxHour: {
type: Number, type: Number,
value: 23 value: 23,
}, minMinute: { observer: 'updateValue',
},
minMinute: {
type: Number, type: Number,
value: 0 value: 0,
}, maxMinute: { observer: 'updateValue',
},
maxMinute: {
type: Number, type: Number,
value: 59 value: 59,
} }), observer: 'updateValue',
},
}),
data: { data: {
innerValue: Date.now(), innerValue: Date.now(),
columns: [] columns: [],
},
watch: {
value: 'updateValue',
type: 'updateValue',
minDate: 'updateValue',
maxDate: 'updateValue',
minHour: 'updateValue',
maxHour: 'updateValue',
minMinute: 'updateValue',
maxMinute: 'updateValue'
}, },
methods: { methods: {
updateValue() { updateValue() {
...@@ -84,8 +95,7 @@ VantComponent({ ...@@ -84,8 +95,7 @@ VantComponent({
this.updateColumnValue(val).then(() => { this.updateColumnValue(val).then(() => {
this.$emit('input', val); this.$emit('input', val);
}); });
} } else {
else {
this.updateColumns(); this.updateColumns();
} }
}, },
...@@ -94,21 +104,32 @@ VantComponent({ ...@@ -94,21 +104,32 @@ VantComponent({
this.picker = this.selectComponent('.van-datetime-picker'); this.picker = this.selectComponent('.van-datetime-picker');
const { picker } = this; const { picker } = this;
const { setColumnValues } = picker; const { setColumnValues } = picker;
picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]); picker.setColumnValues = (...args) =>
setColumnValues.apply(picker, [...args, false]);
} }
return this.picker; return this.picker;
}, },
updateColumns() { updateColumns() {
const { formatter = defaultFormatter } = this.data; const { formatter = defaultFormatter } = this.data;
const results = this.getOriginColumns().map((column) => ({
values: column.values.map((value) => formatter(column.type, value)),
}));
return this.set({ columns: results });
},
getOriginColumns() {
const { filter } = this.data;
const results = this.getRanges().map(({ type, range }) => { const results = this.getRanges().map(({ type, range }) => {
const values = times(range[1] - range[0] + 1, index => { let values = times(range[1] - range[0] + 1, (index) => {
let value = range[0] + index; let value = range[0] + index;
value = type === 'year' ? `${value}` : padZero(value); value = type === 'year' ? `${value}` : padZero(value);
return formatter(type, value); return value;
}); });
return { values }; if (filter) {
values = filter(type, values);
}
return { type, values };
}); });
return this.set({ columns: results }); return results;
}, },
getRanges() { getRanges() {
const { data } = this; const { data } = this;
...@@ -116,42 +137,52 @@ VantComponent({ ...@@ -116,42 +137,52 @@ VantComponent({
return [ return [
{ {
type: 'hour', type: 'hour',
range: [data.minHour, data.maxHour] range: [data.minHour, data.maxHour],
}, },
{ {
type: 'minute', type: 'minute',
range: [data.minMinute, data.maxMinute] range: [data.minMinute, data.maxMinute],
} },
]; ];
} }
const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary('max', data.innerValue); const {
const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary('min', data.innerValue); maxYear,
maxDate,
maxMonth,
maxHour,
maxMinute,
} = this.getBoundary('max', data.innerValue);
const {
minYear,
minDate,
minMonth,
minHour,
minMinute,
} = this.getBoundary('min', data.innerValue);
const result = [ const result = [
{ {
type: 'year', type: 'year',
range: [minYear, maxYear] range: [minYear, maxYear],
}, },
{ {
type: 'month', type: 'month',
range: [minMonth, maxMonth] range: [minMonth, maxMonth],
}, },
{ {
type: 'day', type: 'day',
range: [minDate, maxDate] range: [minDate, maxDate],
}, },
{ {
type: 'hour', type: 'hour',
range: [minHour, maxHour] range: [minHour, maxHour],
}, },
{ {
type: 'minute', type: 'minute',
range: [minMinute, maxMinute] range: [minMinute, maxMinute],
} },
]; ];
if (data.type === 'date') if (data.type === 'date') result.splice(3, 2);
result.splice(3, 2); if (data.type === 'year-month') result.splice(2, 3);
if (data.type === 'year-month')
result.splice(2, 3);
return result; return result;
}, },
correctValue(value) { correctValue(value) {
...@@ -160,8 +191,7 @@ VantComponent({ ...@@ -160,8 +191,7 @@ VantComponent({
const isDateType = data.type !== 'time'; const isDateType = data.type !== 'time';
if (isDateType && !isValidDate(value)) { if (isDateType && !isValidDate(value)) {
value = data.minDate; value = data.minDate;
} } else if (!isDateType && !value) {
else if (!isDateType && !value) {
const { minHour } = data; const { minHour } = data;
value = `${padZero(minHour)}:00`; value = `${padZero(minHour)}:00`;
} }
...@@ -208,7 +238,7 @@ VantComponent({ ...@@ -208,7 +238,7 @@ VantComponent({
[`${type}Month`]: month, [`${type}Month`]: month,
[`${type}Date`]: date, [`${type}Date`]: date,
[`${type}Hour`]: hour, [`${type}Hour`]: hour,
[`${type}Minute`]: minute [`${type}Minute`]: minute,
}; };
}, },
onCancel() { onCancel() {
...@@ -223,9 +253,9 @@ VantComponent({ ...@@ -223,9 +253,9 @@ VantComponent({
const picker = this.getPicker(); const picker = this.getPicker();
if (data.type === 'time') { if (data.type === 'time') {
const indexes = picker.getIndexes(); const indexes = picker.getIndexes();
value = `${indexes[0] + data.minHour}:${indexes[1] + data.minMinute}`; value = `${+data.columns[0].values[indexes[0]]}:${+data.columns[1]
} .values[indexes[1]]}`;
else { } else {
const values = picker.getValues(); const values = picker.getValues();
const year = getTrueValue(values[0]); const year = getTrueValue(values[0]);
const month = getTrueValue(values[1]); const month = getTrueValue(values[1]);
...@@ -255,33 +285,33 @@ VantComponent({ ...@@ -255,33 +285,33 @@ VantComponent({
const picker = this.getPicker(); const picker = this.getPicker();
if (type === 'time') { if (type === 'time') {
const pair = value.split(':'); const pair = value.split(':');
values = [ values = [formatter('hour', pair[0]), formatter('minute', pair[1])];
formatter('hour', pair[0]), } else {
formatter('minute', pair[1])
];
}
else {
const date = new Date(value); const date = new Date(value);
values = [ values = [
formatter('year', `${date.getFullYear()}`), formatter('year', `${date.getFullYear()}`),
formatter('month', padZero(date.getMonth() + 1)) formatter('month', padZero(date.getMonth() + 1)),
]; ];
if (type === 'date') { if (type === 'date') {
values.push(formatter('day', padZero(date.getDate()))); values.push(formatter('day', padZero(date.getDate())));
} }
if (type === 'datetime') { if (type === 'datetime') {
values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', padZero(date.getMinutes()))); values.push(
formatter('day', padZero(date.getDate())),
formatter('hour', padZero(date.getHours())),
formatter('minute', padZero(date.getMinutes()))
);
} }
} }
return this.set({ innerValue: value }) return this.set({ innerValue: value })
.then(() => this.updateColumns()) .then(() => this.updateColumns())
.then(() => picker.setValues(values)); .then(() => picker.setValues(values));
} },
}, },
created() { created() {
const innerValue = this.correctValue(this.data.value); const innerValue = this.correctValue(this.data.value);
this.updateColumnValue(innerValue).then(() => { this.updateColumnValue(innerValue).then(() => {
this.$emit('input', innerValue); this.$emit('input', innerValue);
}); });
} },
}); });
...@@ -3,22 +3,19 @@ import { Weapp } from './weapp'; ...@@ -3,22 +3,19 @@ import { Weapp } from './weapp';
declare type RecordToAny<T> = { declare type RecordToAny<T> = {
[K in keyof T]: any; [K in keyof T]: any;
}; };
declare type RecordToReturn<T> = { export declare type CombinedComponentInstance<Data, Props, Methods> = Methods & WechatMiniprogram.Component.TrivialInstance & Weapp.FormField & {
[P in keyof T]: T[P] extends (...args: any[]) => any ? ReturnType<T[P]> : T[P]; data: Data & RecordToAny<Props>;
}; };
export declare type CombinedComponentInstance<Data, Props, Methods, Computed> = Methods & WechatMiniprogram.Component.TrivialInstance & Weapp.FormField & { export interface VantComponentOptions<Data, Props, Methods, Instance> {
data: Data & RecordToReturn<Computed> & RecordToAny<Props>;
};
export interface VantComponentOptions<Data, Props, Methods, Computed, Instance> {
data?: Data; data?: Data;
field?: boolean; field?: boolean;
classes?: string[]; classes?: string[];
mixins?: string[]; mixins?: string[];
props?: Props & Weapp.PropertyOption; props?: Props & Weapp.PropertyOption;
watch?: Weapp.WatchOption<Instance>;
computed?: Computed & Weapp.ComputedOption<Instance>;
relation?: Weapp.RelationOption<Instance> & { relation?: Weapp.RelationOption<Instance> & {
type: 'ancestor' | 'descendant';
name: string; name: string;
current: string;
}; };
relations?: { relations?: {
[componentName: string]: Weapp.RelationOption<Instance>; [componentName: string]: Weapp.RelationOption<Instance>;
......
/// <reference types="miniprogram-api-typings" /> /// <reference types="miniprogram-api-typings" />
export declare namespace Weapp { export declare namespace Weapp {
interface FormField { export interface FormField {
data: { data: {
name: string; name: string;
value: any; value: any;
...@@ -13,7 +13,7 @@ export declare namespace Weapp { ...@@ -13,7 +13,7 @@ export declare namespace Weapp {
[key: string]: any; [key: string]: any;
}; };
} }
interface Event { export interface Event {
/** /**
* 代表事件的类型。 * 代表事件的类型。
*/ */
...@@ -57,14 +57,14 @@ export declare namespace Weapp { ...@@ -57,14 +57,14 @@ export declare namespace Weapp {
*/ */
clientY: number; clientY: number;
} }
interface TouchEvent extends Event { export interface TouchEvent extends Event {
touches: Array<Touch>; touches: Array<Touch>;
changedTouches: Array<Touch>; changedTouches: Array<Touch>;
} }
/** /**
* relation定义,miniprogram-api-typings缺少this定义 * relation定义,miniprogram-api-typings缺少this定义
*/ */
interface RelationOption<Instance> { export interface RelationOption<Instance> {
/** 目标组件的相对关系 */ /** 目标组件的相对关系 */
type: 'parent' | 'child' | 'ancestor' | 'descendant'; type: 'parent' | 'child' | 'ancestor' | 'descendant';
/** 关系生命周期函数,当关系被建立在页面节点树中时触发,触发时机在组件attached生命周期之后 */ /** 关系生命周期函数,当关系被建立在页面节点树中时触发,触发时机在组件attached生命周期之后 */
...@@ -80,23 +80,17 @@ export declare namespace Weapp { ...@@ -80,23 +80,17 @@ export declare namespace Weapp {
* obverser定义,miniprogram-api-typings缺少this定义 * obverser定义,miniprogram-api-typings缺少this定义
*/ */
type Observer<Instance, T> = (this: Instance, newVal: T, oldVal: T, changedPath: Array<string | number>) => void; type Observer<Instance, T> = (this: Instance, newVal: T, oldVal: T, changedPath: Array<string | number>) => void;
/**
* watch定义
*/
interface WatchOption<Instance> {
[name: string]: string | Observer<Instance, any>;
}
/** /**
* methods定义,miniprogram-api-typings缺少this定义 * methods定义,miniprogram-api-typings缺少this定义
*/ */
interface MethodOption<Instance> { export interface MethodOption<Instance> {
[name: string]: (this: Instance, ...args: any[]) => any; [name: string]: (this: Instance, ...args: any[]) => any;
} }
interface ComputedOption<Instance> { export interface ComputedOption<Instance> {
[name: string]: (this: Instance) => any; [name: string]: (this: Instance) => any;
} }
type PropertyType = StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | FunctionConstructor | null; type PropertyType = StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | FunctionConstructor | null;
interface PropertyOption { export interface PropertyOption {
[name: string]: PropertyType | PropertyType[] | { [name: string]: PropertyType | PropertyType[] | {
/** 属性类型 */ /** 属性类型 */
type: PropertyType | PropertyType[]; type: PropertyType | PropertyType[];
...@@ -108,4 +102,5 @@ export declare namespace Weapp { ...@@ -108,4 +102,5 @@ export declare namespace Weapp {
optionalTypes?: PropertyType[]; optionalTypes?: PropertyType[];
}; };
} }
export {};
} }
...@@ -4,6 +4,7 @@ declare type DialogOptions = { ...@@ -4,6 +4,7 @@ declare type DialogOptions = {
lang?: string; lang?: string;
show?: boolean; show?: boolean;
title?: string; title?: string;
width?: string | number;
zIndex?: number; zIndex?: number;
context?: WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance; context?: WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
message?: string; message?: string;
...@@ -16,6 +17,7 @@ declare type DialogOptions = { ...@@ -16,6 +17,7 @@ declare type DialogOptions = {
asyncClose?: boolean; asyncClose?: boolean;
businessId?: number; businessId?: number;
sessionFrom?: string; sessionFrom?: string;
overlayStyle?: string;
appParameter?: string; appParameter?: string;
messageAlign?: string; messageAlign?: string;
sendMessageImg?: string; sendMessageImg?: string;
......
...@@ -3,55 +3,61 @@ function getContext() { ...@@ -3,55 +3,61 @@ function getContext() {
const pages = getCurrentPages(); const pages = getCurrentPages();
return pages[pages.length - 1]; return pages[pages.length - 1];
} }
const Dialog = options => { const Dialog = (options) => {
options = Object.assign({}, Dialog.currentOptions, options); options = Object.assign(Object.assign({}, Dialog.currentOptions), options);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const context = options.context || getContext(); const context = options.context || getContext();
const dialog = context.selectComponent(options.selector); const dialog = context.selectComponent(options.selector);
delete options.context; delete options.context;
delete options.selector; delete options.selector;
if (dialog) { if (dialog) {
dialog.set(Object.assign({ onCancel: reject, onConfirm: resolve }, options)); dialog.setData(
Object.assign({ onCancel: reject, onConfirm: resolve }, options)
);
queue.push(dialog); queue.push(dialog);
} } else {
else { console.warn(
console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确'); '未找到 van-dialog 节点,请确认 selector 及 context 是否正确'
);
} }
}); });
}; };
Dialog.defaultOptions = { Dialog.defaultOptions = {
show: true, show: true,
title: '', title: '',
width: null,
message: '', message: '',
zIndex: 100, zIndex: 100,
overlay: true, overlay: true,
selector: '#van-dialog',
className: '', className: '',
customStyle: '',
asyncClose: false, asyncClose: false,
messageAlign: '',
transition: 'scale', transition: 'scale',
selector: '#van-dialog', customStyle: '',
messageAlign: '',
overlayStyle: '',
confirmButtonText: '确认', confirmButtonText: '确认',
cancelButtonText: '取消', cancelButtonText: '取消',
showConfirmButton: true, showConfirmButton: true,
showCancelButton: false, showCancelButton: false,
closeOnClickOverlay: false, closeOnClickOverlay: false,
confirmButtonOpenType: '' confirmButtonOpenType: '',
}; };
Dialog.alert = Dialog; Dialog.alert = Dialog;
Dialog.confirm = options => Dialog(Object.assign({ showCancelButton: true }, options)); Dialog.confirm = (options) =>
Dialog(Object.assign({ showCancelButton: true }, options));
Dialog.close = () => { Dialog.close = () => {
queue.forEach(dialog => { queue.forEach((dialog) => {
dialog.close(); dialog.close();
}); });
queue = []; queue = [];
}; };
Dialog.stopLoading = () => { Dialog.stopLoading = () => {
queue.forEach(dialog => { queue.forEach((dialog) => {
dialog.stopLoading(); dialog.stopLoading();
}); });
}; };
Dialog.setDefaultOptions = options => { Dialog.setDefaultOptions = (options) => {
Object.assign(Dialog.currentOptions, options); Object.assign(Dialog.currentOptions, options);
}; };
Dialog.resetDefaultOptions = () => { Dialog.resetDefaultOptions = () => {
......
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { button } from '../mixins/button'; import { button } from '../mixins/button';
import { openType } from '../mixins/open-type'; import { openType } from '../mixins/open-type';
import { GRAY, BLUE } from '../common/color';
VantComponent({ VantComponent({
mixins: [button, openType], mixins: [button, openType],
props: { props: {
show: Boolean, show: {
type: Boolean,
observer(show) {
!show && this.stopLoading();
},
},
title: String, title: String,
message: String, message: String,
useSlot: Boolean, useSlot: Boolean,
...@@ -12,44 +18,50 @@ VantComponent({ ...@@ -12,44 +18,50 @@ VantComponent({
customStyle: String, customStyle: String,
asyncClose: Boolean, asyncClose: Boolean,
messageAlign: String, messageAlign: String,
overlayStyle: String,
useTitleSlot: Boolean,
showCancelButton: Boolean, showCancelButton: Boolean,
closeOnClickOverlay: Boolean, closeOnClickOverlay: Boolean,
confirmButtonOpenType: String, confirmButtonOpenType: String,
width: null,
zIndex: { zIndex: {
type: Number, type: Number,
value: 2000 value: 2000,
}, },
confirmButtonText: { confirmButtonText: {
type: String, type: String,
value: '确认' value: '确认',
}, },
cancelButtonText: { cancelButtonText: {
type: String, type: String,
value: '取消' value: '取消',
},
confirmButtonColor: {
type: String,
value: BLUE,
},
cancelButtonColor: {
type: String,
value: GRAY,
}, },
showConfirmButton: { showConfirmButton: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
overlay: { overlay: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
transition: { transition: {
type: String, type: String,
value: 'scale' value: 'scale',
} },
}, },
data: { data: {
loading: { loading: {
confirm: false, confirm: false,
cancel: false cancel: false,
}
}, },
watch: {
show(show) {
!show && this.stopLoading();
}
}, },
methods: { methods: {
onConfirm() { onConfirm() {
...@@ -63,23 +75,23 @@ VantComponent({ ...@@ -63,23 +75,23 @@ VantComponent({
}, },
handleAction(action) { handleAction(action) {
if (this.data.asyncClose) { if (this.data.asyncClose) {
this.set({ this.setData({
[`loading.${action}`]: true [`loading.${action}`]: true,
}); });
} }
this.onClose(action); this.onClose(action);
}, },
close() { close() {
this.set({ this.setData({
show: false show: false,
}); });
}, },
stopLoading() { stopLoading() {
this.set({ this.setData({
loading: { loading: {
confirm: false, confirm: false,
cancel: false cancel: false,
} },
}); });
}, },
onClose(action) { onClose(action) {
...@@ -89,10 +101,12 @@ VantComponent({ ...@@ -89,10 +101,12 @@ VantComponent({
this.$emit('close', action); this.$emit('close', action);
// 把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading // 把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
this.$emit(action, { dialog: this }); this.$emit(action, { dialog: this });
const callback = this.data[action === 'confirm' ? 'onConfirm' : 'onCancel']; const callback = this.data[
action === 'confirm' ? 'onConfirm' : 'onCancel'
];
if (callback) { if (callback) {
callback(this); callback(this);
} }
} },
} },
}); });
<wxs src="../wxs/utils.wxs" module="utils" />
<van-popup <van-popup
show="{{ show }}" show="{{ show }}"
z-index="{{ zIndex }}" z-index="{{ zIndex }}"
overlay="{{ overlay }}" overlay="{{ overlay }}"
custom-class="van-dialog {{ className }}"
transition="{{ transition }}" transition="{{ transition }}"
custom-style="{{ customStyle }}" custom-class="van-dialog {{ className }}"
custom-style="width: {{ utils.addUnit(width) }};{{ customStyle }}"
overlay-style="{{ overlayStyle }}"
close-on-click-overlay="{{ closeOnClickOverlay }}" close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClickOverlay" bind:close="onClickOverlay"
> >
<view <view
wx:if="{{ title }}" wx:if="{{ title || useTitleSlot }}"
class="van-dialog__header {{ message || useSlot ? '' : 'van-dialog--isolated' }}" class="van-dialog__header {{ message || useSlot ? '' : 'van-dialog--isolated' }}"
> >
{{ title }} <slot wx:if="{{ useTitleSlot }}" name="title" />
<block wx:elif="{{ title }}">{{ title }}</block>
</view> </view>
<slot wx:if="{{ useSlot }}" /> <slot wx:if="{{ useSlot }}" />
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
wx:elif="{{ message }}" wx:elif="{{ message }}"
class="van-dialog__message {{ title ? 'van-dialog__message--has-title' : '' }} {{ messageAlign ? 'van-dialog__message--' + messageAlign : '' }}" class="van-dialog__message {{ title ? 'van-dialog__message--has-title' : '' }} {{ messageAlign ? 'van-dialog__message--' + messageAlign : '' }}"
> >
<text>{{ message }}</text> <text class="van-dialog__message-text">{{ message }}</text>
</view> </view>
<view class="van-hairline--top van-dialog__footer"> <view class="van-hairline--top van-dialog__footer">
...@@ -30,6 +34,7 @@ ...@@ -30,6 +34,7 @@
loading="{{ loading.cancel }}" loading="{{ loading.cancel }}"
class="van-dialog__button van-hairline--right" class="van-dialog__button van-hairline--right"
custom-class="van-dialog__cancel" custom-class="van-dialog__cancel"
custom-style="color: {{ cancelButtonColor }}"
bind:click="onCancel" bind:click="onCancel"
> >
{{ cancelButtonText }} {{ cancelButtonText }}
...@@ -40,6 +45,7 @@ ...@@ -40,6 +45,7 @@
class="van-dialog__button" class="van-dialog__button"
loading="{{ loading.confirm }}" loading="{{ loading.confirm }}"
custom-class="van-dialog__confirm" custom-class="van-dialog__confirm"
custom-style="color: {{ confirmButtonColor }}"
open-type="{{ confirmButtonOpenType }}" open-type="{{ confirmButtonOpenType }}"
lang="{{ lang }}" lang="{{ lang }}"
......
@import '../common/index.wxss';.van-dialog{top:45%!important;width:85%;overflow:hidden;font-size:16px;background-color:#fff;border-radius:4px}.van-dialog__header{padding-top:25px;font-weight:500;line-height:24px;text-align:center}.van-dialog__header--isolated{padding:25px 0}.van-dialog__message{max-height:60vh;padding:25px;overflow-y:auto;font-size:14px;line-height:20px;text-align:center;-webkit-overflow-scrolling:touch}.van-dialog__message--has-title{padding-top:12px;color:#7d7e80}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:-webkit-flex;display:flex}.van-dialog__button{-webkit-flex:1;flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog__confirm{color:#1989fa!important}.van-dialog-bounce-enter{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9)} @import '../common/index.wxss';.van-dialog{top:45%!important;overflow:hidden;width:320px;width:var(--dialog-width,320px);font-size:16px;font-size:var(--dialog-font-size,16px);border-radius:16px;border-radius:var(--dialog-border-radius,16px);background-color:#fff;background-color:var(--dialog-background-color,#fff)}@media (max-width:321px){.van-dialog{width:90%;width:var(--dialog-small-screen-width,90%)}}.van-dialog__header{text-align:center;padding-top:24px;padding-top:var(--dialog-header-padding-top,24px);font-weight:500;font-weight:var(--dialog-header-font-weight,500);line-height:24px;line-height:var(--dialog-header-line-height,24px)}.van-dialog__header--isolated{padding:24px 0;padding:var(--dialog-header-isolated-padding,24px 0)}.van-dialog__message{overflow-y:auto;text-align:center;-webkit-overflow-scrolling:touch;font-size:14px;font-size:var(--dialog-message-font-size,14px);line-height:20px;line-height:var(--dialog-message-line-height,20px);max-height:60vh;max-height:var(--dialog-message-max-height,60vh);padding:24px;padding:var(--dialog-message-padding,24px)}.van-dialog__message-text{word-wrap:break-word}.van-dialog__message--has-title{padding-top:12px;padding-top:var(--dialog-has-title-message-padding-top,12px);color:#646566;color:var(--dialog-has-title-message-text-color,#646566)}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:-webkit-flex;display:flex}.van-dialog__button{-webkit-flex:1;flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog-bounce-enter{-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7);opacity:0}.van-dialog-bounce-leave-active{-webkit-transform:translate3d(-50%,-50%,0) scale(.9);transform:translate3d(-50%,-50%,0) scale(.9);opacity:0}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
dashed: {
type: Boolean,
value: false,
},
hairline: {
type: Boolean,
value: false,
},
contentPosition: {
type: String,
value: '',
},
fontSize: {
type: Number,
value: '',
},
borderColor: {
type: String,
value: '',
},
textColor: {
type: String,
value: '',
},
customStyle: {
type: String,
value: '',
},
},
});
{
"component": true,
"usingComponents": {}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('divider', [{dashed, hairline}, contentPosition]) }}"
style="{{ borderColor ? 'border-color: ' + borderColor + ';' : '' }}{{ textColor ? 'color: ' + textColor + ';' : '' }} {{ fontSize ? 'font-size: ' + fontSize + 'px;' : '' }} {{ customStyle }}"
>
<slot />
</view>
@import '../common/index.wxss';.van-divider{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;margin:16px 0;margin:var(--divider-margin,16px 0);color:#969799;color:var(--divider-text-color,#969799);font-size:14px;font-size:var(--divider-font-size,14px);line-height:24px;line-height:var(--divider-line-height,24px);border:0 solid #ebedf0;border-color:var(--divider-border-color,#ebedf0)}.van-divider:after,.van-divider:before{display:block;-webkit-flex:1;flex:1;box-sizing:border-box;height:1px;border-color:inherit;border-style:inherit;border-width:1px 0 0}.van-divider:before{content:""}.van-divider--hairline:after,.van-divider--hairline:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-divider--dashed{border-style:dashed}.van-divider--center:before,.van-divider--left:before,.van-divider--right:before{margin-right:16px;margin-right:var(--divider-content-padding,16px)}.van-divider--center:after,.van-divider--left:after,.van-divider--right:after{content:"";margin-left:16px;margin-left:var(--divider-content-padding,16px)}.van-divider--left:before{max-width:10%;max-width:var(--divider-content-left-width,10%)}.van-divider--right:after{max-width:10%;max-width:var(--divider-content-right-width,10%)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: {
name: 'dropdown-menu',
type: 'ancestor',
current: 'dropdown-item',
linked() {
this.updateDataFromParent();
},
},
props: {
value: {
type: null,
observer: 'rerender',
},
title: {
type: String,
observer: 'rerender',
},
disabled: Boolean,
titleClass: {
type: String,
observer: 'rerender',
},
options: {
type: Array,
value: [],
observer: 'rerender',
},
popupStyle: String,
},
data: {
transition: true,
showPopup: false,
showWrapper: false,
displayTitle: '',
},
methods: {
rerender() {
wx.nextTick(() => {
this.parent && this.parent.updateItemListData();
});
},
updateDataFromParent() {
if (this.parent) {
const {
overlay,
duration,
activeColor,
closeOnClickOverlay,
direction,
} = this.parent.data;
this.setData({
overlay,
duration,
activeColor,
closeOnClickOverlay,
direction,
});
}
},
onOpen() {
this.$emit('open');
},
onOpened() {
this.$emit('opened');
},
onClose() {
this.$emit('close');
},
onClosed() {
this.$emit('closed');
this.setData({ showWrapper: false });
},
onOptionTap(event) {
const { option } = event.currentTarget.dataset;
const { value } = option;
const shouldEmitChange = this.data.value !== value;
this.setData({ showPopup: false, value });
this.$emit('close');
this.rerender();
if (shouldEmitChange) {
this.$emit('change', value);
}
},
toggle(show, options = {}) {
const { showPopup } = this.data;
if (typeof show !== 'boolean') {
show = !showPopup;
}
if (show === showPopup) {
return;
}
this.setData({
transition: !options.immediate,
showPopup: show,
});
if (show) {
this.parent.getChildWrapperStyle().then((wrapperStyle) => {
this.setData({ wrapperStyle, showWrapper: true });
this.rerender();
});
} else {
this.rerender();
}
},
},
});
{ {
"component": true, "component": true,
"usingComponents": { "usingComponents": {
"van-popup": "../popup/index",
"van-cell": "../cell/index", "van-cell": "../cell/index",
"van-switch": "../switch/index" "van-icon": "../icon/index"
} }
} }
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ showWrapper }}"
class="{{ utils.bem('dropdown-item', direction) }}"
style="{{ wrapperStyle }}"
>
<van-popup
show="{{ showPopup }}"
custom-style="position: absolute;{{ popupStyle }}"
overlay-style="position: absolute;"
overlay="{{ overlay }}"
position="{{ direction === 'down' ? 'top' : 'bottom' }}"
duration="{{ transition ? duration : 0 }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:enter="onOpen"
bind:leave="onClose"
bind:close="toggle"
bind:after-enter="onOpened"
bind:after-leave="onClosed"
>
<van-cell
wx:for="{{ options }}"
wx:key="value"
data-option="{{ item }}"
class="{{ utils.bem('dropdown-item__option', { active: item.value === value } ) }}"
clickable
icon="{{ item.icon }}"
bind:tap="onOptionTap"
>
<view
slot="title"
class="van-dropdown-item__title"
style="{{ item.value === value ? 'color:' + activeColor : '' }}"
>
{{ item.text }}
</view>
<van-icon
wx:if="{{ item.value === value }}"
name="success"
class="van-dropdown-item__icon"
color="{{ activeColor }}"
/>
</van-cell>
<slot />
</van-popup>
</view>
@import '../common/index.wxss';.van-dropdown-item{position:fixed;right:0;left:0;overflow:hidden}.van-dropdown-item__option{text-align:left}.van-dropdown-item__option--active .van-dropdown-item__icon,.van-dropdown-item__option--active .van-dropdown-item__title{color:#1989fa;color:var(--dropdown-menu-option-active-color,#1989fa)}.van-dropdown-item--up{top:0}.van-dropdown-item--down{bottom:0}.van-dropdown-item__icon{display:block;line-height:inherit}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { addUnit } from '../common/utils';
let ARRAY = [];
VantComponent({
field: true,
relation: {
name: 'dropdown-item',
type: 'descendant',
current: 'dropdown-menu',
linked() {
this.updateItemListData();
},
unlinked() {
this.updateItemListData();
},
},
props: {
activeColor: {
type: String,
observer: 'updateChildrenData',
},
overlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
zIndex: {
type: Number,
value: 10,
},
duration: {
type: Number,
value: 200,
observer: 'updateChildrenData',
},
direction: {
type: String,
value: 'down',
observer: 'updateChildrenData',
},
closeOnClickOverlay: {
type: Boolean,
value: true,
observer: 'updateChildrenData',
},
closeOnClickOutside: {
type: Boolean,
value: true,
},
},
data: {
itemListData: [],
},
beforeCreate() {
const { windowHeight } = wx.getSystemInfoSync();
this.windowHeight = windowHeight;
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter((item) => item !== this);
},
methods: {
updateItemListData() {
this.setData({
itemListData: this.children.map((child) => child.data),
});
},
updateChildrenData() {
this.children.forEach((child) => {
child.updateDataFromParent();
});
},
toggleItem(active) {
this.children.forEach((item, index) => {
const { showPopup } = item.data;
if (index === active) {
item.toggle();
} else if (showPopup) {
item.toggle(false, { immediate: true });
}
});
},
close() {
this.children.forEach((child) => {
child.toggle(false, { immediate: true });
});
},
getChildWrapperStyle() {
const { zIndex, direction } = this.data;
return this.getRect('.van-dropdown-menu').then((rect) => {
const { top = 0, bottom = 0 } = rect;
const offset = direction === 'down' ? bottom : this.windowHeight - top;
let wrapperStyle = `z-index: ${zIndex};`;
if (direction === 'down') {
wrapperStyle += `top: ${addUnit(offset)};`;
} else {
wrapperStyle += `bottom: ${addUnit(offset)};`;
}
return wrapperStyle;
});
},
onTitleTap(event) {
const { index } = event.currentTarget.dataset;
const child = this.children[index];
if (!child.data.disabled) {
ARRAY.forEach((menuItem) => {
if (
menuItem &&
menuItem.data.closeOnClickOutside &&
menuItem !== this
) {
menuItem.close();
}
});
this.toggleItem(index);
}
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="van-dropdown-menu van-dropdown-menu--top-bottom">
<view
wx:for="{{ itemListData }}"
wx:key="index"
data-index="{{ index }}"
class="{{ utils.bem('dropdown-menu__item', { disabled: item.disabled }) }}"
bind:tap="onTitleTap"
>
<view
class="{{ item.titleClass }} {{ utils.bem('dropdown-menu__title', { active: item.showPopup, down: item.showPopup === (direction === 'down') }) }}"
style="{{ item.showPopup ? 'color:' + activeColor : '' }}"
>
<view class="van-ellipsis">
{{ computed.displayTitle(item) }}
</view>
</view>
</view>
<slot />
</view>
/* eslint-disable */
function displayTitle(item) {
if (item.title) {
return item.title;
}
var match = item.options.filter(function(option) {
return option.value === item.value;
});
var displayTitle = match.length ? match[0].text : '';
return displayTitle;
}
module.exports = {
displayTitle: displayTitle
};
@import '../common/index.wxss';.van-dropdown-menu{display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none;height:50px;height:var(--dropdown-menu-height,50px);background-color:#fff;background-color:var(--dropdown-menu-background-color,#fff)}.van-dropdown-menu__item{display:-webkit-flex;display:flex;-webkit-flex:1;flex:1;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;min-width:0}.van-dropdown-menu__item:active{opacity:.7}.van-dropdown-menu__item--disabled:active{opacity:1}.van-dropdown-menu__item--disabled .van-dropdown-menu__title{color:#969799;color:var(--dropdown-menu-title-disabled-text-color,#969799)}.van-dropdown-menu__title{position:relative;box-sizing:border-box;max-width:100%;padding:0 8px;padding:var(--dropdown-menu-title-padding,0 8px);color:#323233;color:var(--dropdown-menu-title-text-color,#323233);font-size:15px;font-size:var(--dropdown-menu-title-font-size,15px);line-height:18px;line-height:var(--dropdown-menu-title-line-height,18px)}.van-dropdown-menu__title:after{position:absolute;top:50%;right:-4px;margin-top:-5px;border-color:transparent transparent currentcolor currentcolor;border-style:solid;border-width:3px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:.8;content:""}.van-dropdown-menu__title--active{color:#1989fa;color:var(--dropdown-menu-title-active-text-color,#1989fa)}.van-dropdown-menu__title--down:after{margin-top:-1px;-webkit-transform:rotate(135deg);transform:rotate(135deg)}
\ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { getSystemInfoSync } from '../common/utils'; import { commonProps, inputProps, textareaProps } from './props';
import { canIUseModel } from '../common/version';
VantComponent({ VantComponent({
field: true, field: true,
classes: ['input-class', 'right-icon-class'], classes: ['input-class', 'right-icon-class'],
props: { props: Object.assign(
Object.assign(
Object.assign(Object.assign({}, commonProps), inputProps),
textareaProps
),
{
size: String, size: String,
icon: String, icon: String,
label: String, label: String,
error: Boolean, error: Boolean,
fixed: Boolean,
focus: Boolean,
center: Boolean, center: Boolean,
isLink: Boolean, isLink: Boolean,
leftIcon: String, leftIcon: String,
rightIcon: String, rightIcon: String,
disabled: Boolean, autosize: [Boolean, Object],
autosize: Boolean, readonly: {
readonly: Boolean, type: Boolean,
observer: 'setShowClear',
},
required: Boolean, required: Boolean,
password: Boolean,
iconClass: String, iconClass: String,
clearable: Boolean, clearable: {
type: Boolean,
observer: 'setShowClear',
},
clickable: Boolean,
inputAlign: String, inputAlign: String,
customStyle: String, customStyle: String,
confirmType: String,
confirmHold: Boolean,
errorMessage: String, errorMessage: String,
placeholder: String, arrowDirection: String,
placeholderStyle: String, showWordLimit: Boolean,
errorMessageAlign: String, errorMessageAlign: String,
selectionEnd: {
type: Number,
value: -1
},
selectionStart: {
type: Number,
value: -1
},
showConfirmBar: {
type: Boolean,
value: true
},
adjustPosition: {
type: Boolean,
value: true
},
cursorSpacing: {
type: Number,
value: 50
},
maxlength: {
type: Number,
value: -1
},
type: {
type: String,
value: 'text'
},
border: { border: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
titleWidth: { titleWidth: {
type: String, type: String,
value: '90px' value: '90px',
}
}, },
}
),
data: { data: {
focused: false, focused: false,
system: getSystemInfoSync().system.split(' ').shift().toLowerCase() innerValue: '',
showClear: false,
},
created() {
this.value = this.data.value;
this.setData({ innerValue: this.value });
}, },
methods: { methods: {
onInput(event) { onInput(event) {
const { value = '' } = event.detail || {}; const { value = '' } = event.detail || {};
this.set({ value }, () => { this.value = value;
this.emitChange(value); this.setShowClear();
}); this.emitChange();
}, },
onFocus(event) { onFocus(event) {
this.set({ focused: true }); this.focused = true;
this.setShowClear();
this.$emit('focus', event.detail); this.$emit('focus', event.detail);
}, },
onBlur(event) { onBlur(event) {
this.set({ focused: false }); this.focused = false;
this.setShowClear();
this.$emit('blur', event.detail); this.$emit('blur', event.detail);
}, },
onClickIcon() { onClickIcon() {
this.$emit('click-icon'); this.$emit('click-icon');
}, },
onClear() { onClear() {
this.set({ value: '' }, () => { this.setData({ innerValue: '' });
this.emitChange(''); this.value = '';
this.setShowClear();
wx.nextTick(() => {
this.emitChange();
this.$emit('clear', ''); this.$emit('clear', '');
}); });
}, },
onConfirm() { onConfirm(event) {
this.$emit('confirm', this.data.value); const { value = '' } = event.detail || {};
}, this.value = value;
emitChange(value) { this.setShowClear();
this.$emit('input', value); this.$emit('confirm', value);
this.$emit('change', value); },
setValue(value) {
this.value = value;
this.setShowClear();
if (value === '') {
this.setData({ innerValue: '' });
} }
this.emitChange();
},
onLineChange(event) {
this.$emit('linechange', event.detail);
},
onKeyboardHeightChange(event) {
this.$emit('keyboardheightchange', event.detail);
},
emitChange() {
if (canIUseModel()) {
this.setData({ value: this.value });
} }
wx.nextTick(() => {
this.$emit('input', this.value);
this.$emit('change', this.value);
});
},
setShowClear() {
const { clearable, readonly } = this.data;
const { focused, value } = this;
this.setData({
showClear: !!clearable && !!focused && !!value && !readonly,
});
},
noop() {},
},
}); });
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<van-cell <van-cell
size="{{ size }}"
icon="{{ leftIcon }}" icon="{{ leftIcon }}"
title="{{ label }}" title="{{ label }}"
center="{{ center }}" center="{{ center }}"
border="{{ border }}" border="{{ border }}"
is-link="{{ isLink }}" is-link="{{ isLink }}"
required="{{ required }}" required="{{ required }}"
custom-style="{{ customStyle }}" clickable="{{ clickable }}"
title-width="{{ titleWidth }}" title-width="{{ titleWidth }}"
custom-style="{{ customStyle }}"
arrow-direction="{{ arrowDirection }}"
custom-class="van-field" custom-class="van-field"
size="{{ size }}"
> >
<slot name="left-icon" slot="icon" /> <slot name="left-icon" slot="icon" />
<slot name="label" slot="title" /> <slot name="label" slot="title" />
<view class="{{ utils.bem('field__body', [type, system]) }}"> <view class="{{ utils.bem('field__body', [type]) }}">
<textarea <textarea
wx:if="{{ type === 'textarea' }}" wx:if="{{ type === 'textarea' }}"
class="input-class {{ utils.bem('field__input', [inputAlign, type, { disabled, error }]) }}" class="input-class {{ utils.bem('field__input', [inputAlign, type, { disabled, error }]) }}"
fixed="{{ fixed }}" fixed="{{ fixed }}"
focus="{{ focus }}" focus="{{ focus }}"
value="{{ value }}" cursor="{{ cursor }}"
value="{{ innerValue }}"
auto-focus="{{ autoFocus }}"
disabled="{{ disabled || readonly }}" disabled="{{ disabled || readonly }}"
maxlength="{{ maxlength }}" maxlength="{{ maxlength }}"
placeholder="{{ placeholder }}" placeholder="{{ placeholder }}"
placeholder-style="{{ placeholderStyle }}" placeholder-style="{{ placeholderStyle }}"
placeholder-class="{{ utils.bem('field__placeholder', { error }) }}" placeholder-class="{{ utils.bem('field__placeholder', { error }) }}"
auto-height="{{ autosize }}" auto-height="{{ !!autosize }}"
style="{{ computed.inputStyle(autosize) }}"
cursor-spacing="{{ cursorSpacing }}" cursor-spacing="{{ cursorSpacing }}"
adjust-position="{{ adjustPosition }}" adjust-position="{{ adjustPosition }}"
show-confirm-bar="{{ showConfirmBar }}" show-confirm-bar="{{ showConfirmBar }}"
hold-keyboard="{{ holdKeyboard }}"
selection-end="{{ selectionEnd }}" selection-end="{{ selectionEnd }}"
selection-start="{{ selectionStart }}" selection-start="{{ selectionStart }}"
disable-default-padding="{{ disableDefaultPadding }}"
bindinput="onInput" bindinput="onInput"
bind:blur="onBlur" bindblur="onBlur"
bind:focus="onFocus" bindfocus="onFocus"
bind:confirm="onConfirm" bindconfirm="onConfirm"
bindlinechange="onLineChange"
bindkeyboardheightchange="onKeyboardHeightChange"
> >
</textarea> </textarea>
<input <input
...@@ -43,7 +53,9 @@ ...@@ -43,7 +53,9 @@
class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}" class="input-class {{ utils.bem('field__input', [inputAlign, { disabled, error }]) }}"
type="{{ type }}" type="{{ type }}"
focus="{{ focus }}" focus="{{ focus }}"
value="{{ value }}" cursor="{{ cursor }}"
value="{{ innerValue }}"
auto-focus="{{ autoFocus }}"
disabled="{{ disabled || readonly }}" disabled="{{ disabled || readonly }}"
maxlength="{{ maxlength }}" maxlength="{{ maxlength }}"
placeholder="{{ placeholder }}" placeholder="{{ placeholder }}"
...@@ -51,27 +63,27 @@ ...@@ -51,27 +63,27 @@
placeholder-class="{{ utils.bem('field__placeholder', { error }) }}" placeholder-class="{{ utils.bem('field__placeholder', { error }) }}"
confirm-type="{{ confirmType }}" confirm-type="{{ confirmType }}"
confirm-hold="{{ confirmHold }}" confirm-hold="{{ confirmHold }}"
hold-keyboard="{{ holdKeyboard }}"
cursor-spacing="{{ cursorSpacing }}" cursor-spacing="{{ cursorSpacing }}"
adjust-position="{{ adjustPosition }}" adjust-position="{{ adjustPosition }}"
selection-end="{{ selectionEnd }}" selection-end="{{ selectionEnd }}"
selection-start="{{ selectionStart }}" selection-start="{{ selectionStart }}"
password="{{ password || type === 'password' }}" password="{{ password || type === 'password' }}"
bindinput="onInput" bindinput="onInput"
bind:blur="onBlur" bindblur="onBlur"
bind:focus="onFocus" bindfocus="onFocus"
bind:confirm="onConfirm" bindconfirm="onConfirm"
bindkeyboardheightchange="onKeyboardHeightChange"
/> />
<van-icon <van-icon
wx:if="{{ clearable && focused && value && !readonly }}" wx:if="{{ showClear }}"
size="16px"
name="clear" name="clear"
class="van-field__clear-root van-field__icon-root" class="van-field__clear-root van-field__icon-root"
bindtouchstart="onClear" catch:touchstart="onClear"
/> />
<view class="van-field__icon-container" bind:tap="onClickIcon"> <view class="van-field__icon-container" bind:tap="onClickIcon">
<van-icon <van-icon
wx:if="{{ rightIcon || icon }}" wx:if="{{ rightIcon || icon }}"
size="16px"
name="{{ rightIcon || icon }}" name="{{ rightIcon || icon }}"
class="van-field__icon-root {{ iconClass }}" class="van-field__icon-root {{ iconClass }}"
custom-class="right-icon-class" custom-class="right-icon-class"
...@@ -83,7 +95,10 @@ ...@@ -83,7 +95,10 @@
<slot name="button" /> <slot name="button" />
</view> </view>
</view> </view>
<view wx:if="{{ errorMessage }}" class="van-field__error-message {{ utils.bem('field__error', [errorMessageAlign, { disabled, error }]) }}"> <view wx:if="{{ showWordLimit && maxlength }}" class="van-field__word-limit">
<view class="{{ utils.bem('field__word-num', { full: value.length >= maxlength }) }}">{{ value.length }}</view>/{{ maxlength }}
</view>
<view wx:if="{{ errorMessage }}" class="{{ utils.bem('field__error-message', [errorMessageAlign, { disabled, error }]) }}">
{{ errorMessage }} {{ errorMessage }}
</view> </view>
</van-cell> </van-cell>
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
function inputStyle(autosize) {
if (autosize && autosize.constructor === 'Object') {
var style = '';
if (autosize.minHeight) {
style += 'min-height:' + utils.addUnit(autosize.minHeight) + ';';
}
if (autosize.maxHeight) {
style += 'max-height:' + utils.addUnit(autosize.maxHeight) + ';';
}
return style;
}
return '';
}
module.exports = {
inputStyle: inputStyle
};
@import '../common/index.wxss';.van-field__body{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center}.van-field__body--textarea{min-height:24px;line-height:1.2em}.van-field__body--textarea.van-field__body--ios{margin-top:-4.5px}.van-field__input{position:relative;display:block;width:100%;height:24px;min-height:24px;padding:0;margin:0;line-height:inherit;color:#333;text-align:left;background-color:initial;border:0;box-sizing:border-box;resize:none}.van-field__input--textarea{height:18px;min-height:18px}.van-field__input--error{color:#f44}.van-field__input--disabled{color:#999;background-color:initial;opacity:1}.van-field__input--center{text-align:center}.van-field__input--right{text-align:right}.van-field__placeholder{position:absolute;top:0;right:0;left:0;color:#999;pointer-events:none}.van-field__placeholder--error{color:#f44}.van-field__icon-root{display:-webkit-flex;display:flex;min-height:24px;-webkit-align-items:center;align-items:center}.van-field__clear-root,.van-field__icon-container{padding:0 10px;margin-right:-10px;line-height:inherit;vertical-align:middle}.van-field__button,.van-field__clear-root,.van-field__icon-container{-webkit-flex-shrink:0;flex-shrink:0}.van-field__clear-root{color:#c9c9c9}.van-field__icon-container{color:#999}.van-field__icon-container:empty{display:none}.van-field__button{padding-left:10px}.van-field__button:empty{display:none}.van-field__error-message{font-size:12px;color:#f44;text-align:left}.van-field__error-message--center{text-align:center}.van-field__error-message--right{text-align:right} @import '../common/index.wxss';.van-field{--cell-icon-size:16px;--cell-icon-size:var(--field-icon-size,16px)}.van-field__body{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center}.van-field__body--textarea{line-height:1.2em}.van-field__body--textarea,.van-field__input{min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__input{position:relative;display:block;box-sizing:border-box;width:100%;margin:0;padding:0;line-height:inherit;text-align:left;background-color:initial;border:0;resize:none;color:#323233;color:var(--field-input-text-color,#323233);height:24px;height:var(--cell-line-height,24px)}.van-field__input--textarea{height:18px;height:var(--field-text-area-min-height,18px);min-height:18px;min-height:var(--field-text-area-min-height,18px)}.van-field__input--error{color:#ee0a24;color:var(--field-input-error-text-color,#ee0a24)}.van-field__input--disabled{background-color:initial;opacity:1;color:#969799;color:var(--field-input-disabled-text-color,#969799)}.van-field__input--center{text-align:center}.van-field__input--right{text-align:right}.van-field__placeholder{position:absolute;top:0;right:0;left:0;pointer-events:none;color:#c8c9cc;color:var(--field-placeholder-text-color,#c8c9cc)}.van-field__placeholder--error{color:#ee0a24;color:var(--field-error-message-color,#ee0a24)}.van-field__icon-root{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;min-height:24px;min-height:var(--cell-line-height,24px)}.van-field__clear-root,.van-field__icon-container{line-height:inherit;vertical-align:middle;padding:0 8px;padding:0 var(--padding-xs,8px);margin-right:-8px;margin-right:-var(--padding-xs,8px)}.van-field__button,.van-field__clear-root,.van-field__icon-container{-webkit-flex-shrink:0;flex-shrink:0}.van-field__clear-root{font-size:16px;font-size:var(--field-clear-icon-size,16px);color:#c8c9cc;color:var(--field-clear-icon-color,#c8c9cc)}.van-field__icon-container{font-size:16px;font-size:var(--field-icon-size,16px);color:#969799;color:var(--field-icon-container-color,#969799)}.van-field__icon-container:empty{display:none}.van-field__button{padding-left:8px;padding-left:var(--padding-xs,8px)}.van-field__button:empty{display:none}.van-field__error-message{text-align:left;font-size:12px;font-size:var(--field-error-message-text-font-size,12px);color:#ee0a24;color:var(--field-error-message-color,#ee0a24)}.van-field__error-message--center{text-align:center}.van-field__error-message--right{text-align:right}.van-field__word-limit{text-align:right;margin-top:4px;margin-top:var(--padding-base,4px);color:#646566;color:var(--field-word-limit-color,#646566);font-size:12px;font-size:var(--field-word-limit-font-size,12px);line-height:16px;line-height:var(--field-word-limit-line-height,16px)}.van-field__word-num{display:inline}.van-field__word-num--full{color:#ee0a24;color:var(--field-word-num-full-color,#ee0a24)}
\ No newline at end of file \ No newline at end of file
export declare const commonProps: {
value: {
type: StringConstructor;
observer(value: string): void;
};
placeholder: StringConstructor;
placeholderStyle: StringConstructor;
placeholderClass: StringConstructor;
disabled: BooleanConstructor;
maxlength: {
type: NumberConstructor;
value: number;
};
cursorSpacing: {
type: NumberConstructor;
value: number;
};
autoFocus: BooleanConstructor;
focus: BooleanConstructor;
cursor: {
type: NumberConstructor;
value: number;
};
selectionStart: {
type: NumberConstructor;
value: number;
};
selectionEnd: {
type: NumberConstructor;
value: number;
};
adjustPosition: {
type: BooleanConstructor;
value: boolean;
};
holdKeyboard: BooleanConstructor;
};
export declare const inputProps: {
type: {
type: StringConstructor;
value: string;
};
password: BooleanConstructor;
confirmType: StringConstructor;
confirmHold: BooleanConstructor;
};
export declare const textareaProps: {
autoHeight: BooleanConstructor;
fixed: BooleanConstructor;
showConfirmBar: {
type: BooleanConstructor;
value: boolean;
};
disableDefaultPadding: {
type: BooleanConstructor;
value: boolean;
};
};
export const commonProps = {
value: {
type: String,
observer(value) {
if (value !== this.value) {
this.setData({ innerValue: value });
this.value = value;
}
},
},
placeholder: String,
placeholderStyle: String,
placeholderClass: String,
disabled: Boolean,
maxlength: {
type: Number,
value: -1,
},
cursorSpacing: {
type: Number,
value: 50,
},
autoFocus: Boolean,
focus: Boolean,
cursor: {
type: Number,
value: -1,
},
selectionStart: {
type: Number,
value: -1,
},
selectionEnd: {
type: Number,
value: -1,
},
adjustPosition: {
type: Boolean,
value: true,
},
holdKeyboard: Boolean,
};
export const inputProps = {
type: {
type: String,
value: 'text',
},
password: Boolean,
confirmType: String,
confirmHold: Boolean,
};
export const textareaProps = {
autoHeight: Boolean,
fixed: Boolean,
showConfirmBar: {
type: Boolean,
value: true,
},
disableDefaultPadding: {
type: Boolean,
value: true,
},
};
...@@ -4,19 +4,38 @@ import { button } from '../mixins/button'; ...@@ -4,19 +4,38 @@ import { button } from '../mixins/button';
import { openType } from '../mixins/open-type'; import { openType } from '../mixins/open-type';
VantComponent({ VantComponent({
mixins: [link, button, openType], mixins: [link, button, openType],
relation: {
type: 'ancestor',
name: 'goods-action',
current: 'goods-action-button',
},
props: { props: {
text: String, text: String,
color: String,
loading: Boolean, loading: Boolean,
disabled: Boolean, disabled: Boolean,
plain: Boolean,
type: { type: {
type: String, type: String,
value: 'danger' value: 'danger',
} },
}, },
methods: { methods: {
onClick(event) { onClick(event) {
this.$emit('click', event.detail); this.$emit('click', event.detail);
this.jumpLink(); this.jumpLink();
},
updateStyle() {
if (this.parent == null) {
return;
} }
} const { children = [] } = this.parent;
const { length } = children;
const index = children.indexOf(this);
this.setData({
isFirst: index === 0,
isLast: index === length - 1,
});
},
},
}); });
<wxs src="../wxs/utils.wxs" module="utils" />
<van-button <van-button
square
id="{{ id }}" id="{{ id }}"
size="large"
lang="{{ lang }}" lang="{{ lang }}"
type="{{ type }}" type="{{ type }}"
color="{{ color }}"
plain="{{ plain }}"
loading="{{ loading }}" loading="{{ loading }}"
disabled="{{ disabled }}" disabled="{{ disabled }}"
open-type="{{ openType }}" open-type="{{ openType }}"
custom-class="custom-class" class="{{ utils.bem('goods-action-button', [type, { first: isFirst, last: isLast, plain: plain }])}}"
custom-class="van-goods-action-button__inner"
business-id="{{ businessId }}" business-id="{{ businessId }}"
session-from="{{ sessionFrom }}" session-from="{{ sessionFrom }}"
app-parameter="{{ appParameter }}" app-parameter="{{ appParameter }}"
...@@ -24,4 +26,5 @@ ...@@ -24,4 +26,5 @@
bindlaunchapp="bindLaunchApp" bindlaunchapp="bindLaunchApp"
> >
{{ text }} {{ text }}
<slot></slot>
</van-button> </van-button>
@import '../common/index.wxss';:host{-webkit-flex:1;flex:1} @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-goods-action-button{--button-warning-background-color:linear-gradient(90deg,#ffd01e,#ff8917);--button-warning-background-color:var(--goods-action-button-warning-color,linear-gradient(90deg,#ffd01e,#ff8917));--button-danger-background-color:linear-gradient(90deg,#ff6034,#ee0a24);--button-danger-background-color:var(--goods-action-button-danger-color,linear-gradient(90deg,#ff6034,#ee0a24));--button-default-height:40px;--button-default-height:var(--goods-action-button-height,40px);--button-line-height:20px;--button-line-height:var(--goods-action-button-line-height,20px);--button-plain-background-color:#fff;--button-plain-background-color:var(--goods-action-button-plain-color,#fff);display:block;--button-border-width:0}.van-goods-action-button--first{margin-left:5px;--button-border-radius:20px 0 0 20px;--button-border-radius:var(--goods-action-button-border-radius,20px) 0 0 var(--goods-action-button-border-radius,20px)}.van-goods-action-button--last{margin-right:5px;--button-border-radius:0 20px 20px 0;--button-border-radius:0 var(--goods-action-button-border-radius,20px) var(--goods-action-button-border-radius,20px) 0}.van-goods-action-button--first.van-goods-action-button--last{--button-border-radius:20px;--button-border-radius:var(--goods-action-button-border-radius,20px)}.van-goods-action-button--plain{--button-border-width:1px}.van-goods-action-button__inner{width:100%;font-weight:500!important;font-weight:var(--font-weight-bold,500)!important}@media (max-width:321px){.van-goods-action-button{font-size:13px}}
\ No newline at end of file \ No newline at end of file
...@@ -7,15 +7,16 @@ VantComponent({ ...@@ -7,15 +7,16 @@ VantComponent({
mixins: [link, button, openType], mixins: [link, button, openType],
props: { props: {
text: String, text: String,
dot: Boolean,
info: String, info: String,
icon: String, icon: String,
disabled: Boolean, disabled: Boolean,
loading: Boolean loading: Boolean,
}, },
methods: { methods: {
onClick(event) { onClick(event) {
this.$emit('click', event.detail); this.$emit('click', event.detail);
this.jumpLink(); this.jumpLink();
} },
} },
}); });
...@@ -22,14 +22,17 @@ ...@@ -22,14 +22,17 @@
bindgetphonenumber="bindGetPhoneNumber" bindgetphonenumber="bindGetPhoneNumber"
bindlaunchapp="bindLaunchApp" bindlaunchapp="bindLaunchApp"
> >
<view class="van-goods-action-icon__content van-hairline--right"> <view class="van-goods-action-icon__content">
<van-icon <van-icon
wx:if="{{ icon }}"
size="20px" size="20px"
name="{{ icon }}" name="{{ icon }}"
dot="{{ dot }}"
info="{{ info }}" info="{{ info }}"
class="van-goods-action-icon__icon" class="van-goods-action-icon__icon"
custom-class="icon-class" custom-class="icon-class"
/> />
<slot name="icon" />
<text class="text-class">{{ text }}</text> <text class="text-class">{{ text }}</text>
</view> </view>
</van-button> </van-button>
@import '../common/index.wxss';.van-goods-action-icon{width:50px!important;border:none!important}.van-goods-action-icon__content{display:-webkit-flex;display:flex;height:100%;font-size:10px;line-height:1;color:#7d7e80;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-goods-action-icon__icon{margin-bottom:4px} @import '../common/index.wxss';.van-goods-action-icon{border:none!important;width:50px!important;width:var(--goods-action-icon-height,50px)!important}.van-goods-action-icon__content{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;height:100%;line-height:1;font-size:10px;font-size:var(--goods-action-icon-font-size,10px);color:#646566;color:var(--goods-action-icon-text-color,#646566)}.van-goods-action-icon__icon{margin-bottom:4px}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({ VantComponent({
mixins: [safeArea()] relation: {
type: 'descendant',
name: 'goods-action-button',
current: 'goods-action',
linked() {
this.updateStyle();
},
unlinked() {
this.updateStyle();
},
linkChanged() {
this.updateStyle();
},
},
props: {
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
methods: {
updateStyle() {
wx.nextTick(() => {
this.children.forEach((child) => {
child.updateStyle();
});
});
},
},
}); });
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class {{ utils.bem('goods-action', { safe: isIPhoneX && safeAreaInsetBottom }) }}"> <view class="custom-class {{ utils.bem('goods-action', { safe: safeAreaInsetBottom }) }}">
<slot /> <slot />
</view> </view>
@import '../common/index.wxss';.van-goods-action{position:fixed;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-goods-action--safe{padding-bottom:34px} @import '../common/index.wxss';.van-goods-action{position:fixed;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;background-color:#fff;background-color:var(--goods-action-background-color,#fff)}.van-goods-action--safe{padding-bottom:env(safe-area-inset-bottom)}
\ No newline at end of file \ No newline at end of file
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
import { addUnit } from '../common/utils';
VantComponent({
relation: {
name: 'grid',
type: 'ancestor',
current: 'grid-item',
},
classes: ['content-class', 'icon-class', 'text-class'],
mixins: [link],
props: {
icon: String,
dot: Boolean,
info: null,
text: String,
useSlot: Boolean,
},
data: {
viewStyle: '',
},
mounted() {
this.updateStyle();
},
methods: {
updateStyle() {
if (!this.parent) {
return;
}
const { data, children } = this.parent;
const { columnNum, border, square, gutter, clickable, center } = data;
const width = `${100 / columnNum}%`;
const styleWrapper = [];
styleWrapper.push(`width: ${width}`);
if (square) {
styleWrapper.push(`padding-top: ${width}`);
}
if (gutter) {
const gutterValue = addUnit(gutter);
styleWrapper.push(`padding-right: ${gutterValue}`);
const index = children.indexOf(this);
if (index >= columnNum) {
styleWrapper.push(`margin-top: ${gutterValue}`);
}
}
let contentStyle = '';
if (square && gutter) {
const gutterValue = addUnit(gutter);
contentStyle = `
right: ${gutterValue};
bottom: ${gutterValue};
height: auto;
`;
}
this.setData({
viewStyle: styleWrapper.join('; '),
contentStyle,
center,
border,
square,
gutter,
clickable,
});
},
onClick() {
this.$emit('click');
this.jumpLink();
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class {{ utils.bem('grid-item', { square }) }}" style="{{ viewStyle }}" bindtap="onClick">
<view
class="content-class {{ utils.bem('grid-item__content', { center, square, clickable, surround: border && gutter }) }} {{ border ? 'van-hairline--surround' : '' }}"
style="{{ contentStyle }}"
>
<block wx:if="{{ useSlot }}">
<slot />
</block>
<block wx:else>
<view class="van-grid-item__icon icon-class">
<van-icon wx:if="{{ icon }}" name="{{ icon }}" dot="{{ dot }}" info="{{ info }}" />
<slot wx:else name="icon"></slot>
</view>
<view class="van-grid-item__text text-class">
<text wx:if="{{ text }}">{{ text }}</text>
<slot wx:else name="text"></slot>
</view>
</block>
</view>
</view>
@import '../common/index.wxss';.van-grid-item{position:relative;float:left;box-sizing:border-box}.van-grid-item--square{height:0}.van-grid-item__content{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;box-sizing:border-box;height:100%;padding:16px 8px;padding:var(--grid-item-content-padding,16px 8px);background-color:#fff;background-color:var(--grid-item-content-background-color,#fff)}.van-grid-item__content:after{z-index:1;border-width:0 1px 1px 0;border-bottom-width:var(--border-width-base,1px);border-right-width:var(--border-width-base,1px);border-top-width:0}.van-grid-item__content--surround:after{border-width:1px;border-width:var(--border-width-base,1px)}.van-grid-item__content--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-grid-item__content--square{position:absolute;top:0;right:0;left:0}.van-grid-item__content--clickable:active{background-color:#f2f3f5;background-color:var(--grid-item-content-active-color,#f2f3f5)}.van-grid-item__icon{font-size:26px;font-size:var(--grid-item-icon-size,26px)}.van-grid-item__text{word-wrap:break-word;color:#646566;color:var(--grid-item-text-color,#646566);font-size:12px;font-size:var(--grid-item-text-font-size,12px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { addUnit } from '../common/utils';
VantComponent({
relation: {
name: 'grid-item',
type: 'descendant',
current: 'grid',
},
props: {
square: {
type: Boolean,
observer: 'updateChildren',
},
gutter: {
type: [Number, String],
value: 0,
observer: 'updateChildren',
},
clickable: {
type: Boolean,
observer: 'updateChildren',
},
columnNum: {
type: Number,
value: 4,
observer: 'updateChildren',
},
center: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
border: {
type: Boolean,
value: true,
observer: 'updateChildren',
},
},
data: {
viewStyle: '',
},
created() {
const { gutter } = this.data;
if (gutter) {
this.setData({
viewStyle: `padding-left: ${addUnit(gutter)}`,
});
}
},
methods: {
updateChildren() {
this.children.forEach((child) => {
child.updateStyle();
});
},
},
});
<view class="van-grid custom-class {{ border && !gutter ? 'van-hairline--top' : '' }}" style="{{ viewStyle }}">
<slot />
</view>
@import '../common/index.wxss';.van-grid{position:relative;box-sizing:border-box;overflow:hidden}
\ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
VantComponent({ VantComponent({
props: { props: {
dot: Boolean,
info: null, info: null,
name: String, size: null,
size: String,
color: String, color: String,
customStyle: String, customStyle: String,
classPrefix: { classPrefix: {
type: String, type: String,
value: 'van-icon' value: 'van-icon',
} },
name: {
type: String,
observer(val) {
this.setData({
isImageName: val.indexOf('/') !== -1,
});
},
},
}, },
methods: { methods: {
onClick() { onClick() {
this.$emit('click'); this.$emit('click');
} },
} },
}); });
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<view <view
class="custom-class {{ classPrefix }} {{ utils.isSrc(name) ? 'van-icon--image' : classPrefix + '-' + name }}" class="custom-class {{ classPrefix }} {{ isImageName ? 'van-icon--image' : classPrefix + '-' + name }}"
style="{{ color ? 'color: ' + color + ';' : '' }}{{ size ? 'font-size: ' + size + ';' : '' }}{{ customStyle }}" style="color: {{ color }};font-size: {{ utils.addUnit(size) }};{{ customStyle }}"
bind:tap="onClick" bind:tap="onClick"
> >
<van-info <van-info
wx:if="{{ info !== null }}" wx:if="{{ info !== null || dot }}"
dot="{{ dot }}"
info="{{ info }}" info="{{ info }}"
custom-class="van-icon__info" custom-class="van-icon__info"
/> />
<image <image
wx:if="{{ utils.isSrc(name) }}" wx:if="{{ isImageName }}"
src="{{ name }}" src="{{ name }}"
mode="aspectFit" mode="aspectFit"
class="van-icon__image" class="van-icon__image"
......
@import '../common/index.wxss';@font-face{font-weight:400;font-family:vant-icon;font-style:normal;font-display:auto;src:url(https://img.yzcdn.cn/vant/vant-icon-d3825a.woff2) format("woff2"),url(https://img.yzcdn.cn/vant/vant-icon-d3825a.woff) format("woff"),url(https://img.yzcdn.cn/vant/vant-icon-d3825a.ttf) format("truetype")}.van-icon{position:relative;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.van-icon,.van-icon:before{display:inline-block}.van-icon-add-o:before{content:"\F000"}.van-icon-add-square:before{content:"\F001"}.van-icon-add:before{content:"\F002"}.van-icon-after-sale:before{content:"\F003"}.van-icon-aim:before{content:"\F004"}.van-icon-alipay:before{content:"\F005"}.van-icon-apps-o:before{content:"\F006"}.van-icon-arrow-down:before{content:"\F007"}.van-icon-arrow-left:before{content:"\F008"}.van-icon-arrow-up:before{content:"\F009"}.van-icon-arrow:before{content:"\F00A"}.van-icon-ascending:before{content:"\F00B"}.van-icon-audio:before{content:"\F00C"}.van-icon-award-o:before{content:"\F00D"}.van-icon-award:before{content:"\F00E"}.van-icon-bag-o:before{content:"\F00F"}.van-icon-bag:before{content:"\F010"}.van-icon-balance-list-o:before{content:"\F011"}.van-icon-balance-list:before{content:"\F012"}.van-icon-balance-o:before{content:"\F013"}.van-icon-balance-pay:before{content:"\F014"}.van-icon-bar-chart-o:before{content:"\F015"}.van-icon-bars:before{content:"\F016"}.van-icon-bell:before{content:"\F017"}.van-icon-bill-o:before{content:"\F018"}.van-icon-bill:before{content:"\F019"}.van-icon-birthday-cake-o:before{content:"\F01A"}.van-icon-bookmark-o:before{content:"\F01B"}.van-icon-bookmark:before{content:"\F01C"}.van-icon-browsing-history-o:before{content:"\F01D"}.van-icon-browsing-history:before{content:"\F01E"}.van-icon-brush-o:before{content:"\F01F"}.van-icon-bulb-o:before{content:"\F020"}.van-icon-bullhorn-o:before{content:"\F021"}.van-icon-calender-o:before{content:"\F022"}.van-icon-card:before{content:"\F023"}.van-icon-cart-circle-o:before{content:"\F024"}.van-icon-cart-circle:before{content:"\F025"}.van-icon-cart-o:before{content:"\F026"}.van-icon-cart:before{content:"\F027"}.van-icon-cash-back-record:before{content:"\F028"}.van-icon-cash-on-deliver:before{content:"\F029"}.van-icon-cashier-o:before{content:"\F02A"}.van-icon-certificate:before{content:"\F02B"}.van-icon-chart-trending-o:before{content:"\F02C"}.van-icon-chat-o:before{content:"\F02D"}.van-icon-chat:before{content:"\F02E"}.van-icon-checked:before{content:"\F02F"}.van-icon-circle:before{content:"\F030"}.van-icon-clear:before{content:"\F031"}.van-icon-clock-o:before{content:"\F032"}.van-icon-clock:before{content:"\F033"}.van-icon-close:before{content:"\F034"}.van-icon-closed-eye:before{content:"\F035"}.van-icon-cluster-o:before{content:"\F036"}.van-icon-cluster:before{content:"\F037"}.van-icon-column:before{content:"\F038"}.van-icon-comment-circle-o:before{content:"\F039"}.van-icon-comment-circle:before{content:"\F03A"}.van-icon-comment-o:before{content:"\F03B"}.van-icon-comment:before{content:"\F03C"}.van-icon-completed:before{content:"\F03D"}.van-icon-contact:before{content:"\F03E"}.van-icon-coupon-o:before{content:"\F03F"}.van-icon-coupon:before{content:"\F040"}.van-icon-credit-pay:before{content:"\F041"}.van-icon-cross:before{content:"\F042"}.van-icon-debit-pay:before{content:"\F043"}.van-icon-delete:before{content:"\F044"}.van-icon-descending:before{content:"\F045"}.van-icon-description:before{content:"\F046"}.van-icon-desktop-o:before{content:"\F047"}.van-icon-diamond-o:before{content:"\F048"}.van-icon-diamond:before{content:"\F049"}.van-icon-discount:before{content:"\F04A"}.van-icon-down:before{content:"\F04B"}.van-icon-ecard-pay:before{content:"\F04C"}.van-icon-edit:before{content:"\F04D"}.van-icon-ellipsis:before{content:"\F04E"}.van-icon-empty:before{content:"\F04F"}.van-icon-envelop-o:before{content:"\F050"}.van-icon-exchange:before{content:"\F051"}.van-icon-expand-o:before{content:"\F052"}.van-icon-expand:before{content:"\F053"}.van-icon-eye-o:before{content:"\F054"}.van-icon-eye:before{content:"\F055"}.van-icon-fail:before{content:"\F056"}.van-icon-failure:before{content:"\F057"}.van-icon-filter-o:before{content:"\F058"}.van-icon-fire-o:before{content:"\F059"}.van-icon-fire:before{content:"\F05A"}.van-icon-flag-o:before{content:"\F05B"}.van-icon-flower-o:before{content:"\F05C"}.van-icon-free-postage:before{content:"\F05D"}.van-icon-friends-o:before{content:"\F05E"}.van-icon-friends:before{content:"\F05F"}.van-icon-gem-o:before{content:"\F060"}.van-icon-gem:before{content:"\F061"}.van-icon-gift-card-o:before{content:"\F062"}.van-icon-gift-card:before{content:"\F063"}.van-icon-gift-o:before{content:"\F064"}.van-icon-gift:before{content:"\F065"}.van-icon-gold-coin-o:before{content:"\F066"}.van-icon-gold-coin:before{content:"\F067"}.van-icon-good-job-o:before{content:"\F068"}.van-icon-good-job:before{content:"\F069"}.van-icon-goods-collect-o:before{content:"\F06A"}.van-icon-goods-collect:before{content:"\F06B"}.van-icon-graphic:before{content:"\F06C"}.van-icon-home-o:before{content:"\F06D"}.van-icon-hot-o:before{content:"\F06E"}.van-icon-hot-sale-o:before{content:"\F06F"}.van-icon-hot-sale:before{content:"\F070"}.van-icon-hot:before{content:"\F071"}.van-icon-hotel-o:before{content:"\F072"}.van-icon-idcard:before{content:"\F073"}.van-icon-info-o:before{content:"\F074"}.van-icon-info:before{content:"\F075"}.van-icon-invition:before{content:"\F076"}.van-icon-label-o:before{content:"\F077"}.van-icon-label:before{content:"\F078"}.van-icon-like-o:before{content:"\F079"}.van-icon-like:before{content:"\F07A"}.van-icon-live:before{content:"\F07B"}.van-icon-location-o:before{content:"\F07C"}.van-icon-location:before{content:"\F07D"}.van-icon-lock:before{content:"\F07E"}.van-icon-logistics:before{content:"\F07F"}.van-icon-manager-o:before{content:"\F080"}.van-icon-manager:before{content:"\F081"}.van-icon-map-marked:before{content:"\F082"}.van-icon-medal-o:before{content:"\F083"}.van-icon-medal:before{content:"\F084"}.van-icon-more-o:before{content:"\F085"}.van-icon-more:before{content:"\F086"}.van-icon-music-o:before{content:"\F087"}.van-icon-music:before{content:"\F088"}.van-icon-new-arrival-o:before{content:"\F089"}.van-icon-new-arrival:before{content:"\F08A"}.van-icon-new-o:before{content:"\F08B"}.van-icon-new:before{content:"\F08C"}.van-icon-newspaper-o:before{content:"\F08D"}.van-icon-notes-o:before{content:"\F08E"}.van-icon-orders-o:before{content:"\F08F"}.van-icon-other-pay:before{content:"\F090"}.van-icon-paid:before{content:"\F091"}.van-icon-passed:before{content:"\F092"}.van-icon-pause-circle-o:before{content:"\F093"}.van-icon-pause-circle:before{content:"\F094"}.van-icon-pause:before{content:"\F095"}.van-icon-peer-pay:before{content:"\F096"}.van-icon-pending-payment:before{content:"\F097"}.van-icon-phone-circle-o:before{content:"\F098"}.van-icon-phone-circle:before{content:"\F099"}.van-icon-phone-o:before{content:"\F09A"}.van-icon-phone:before{content:"\F09B"}.van-icon-photo-o:before{content:"\F09C"}.van-icon-photo:before{content:"\F09D"}.van-icon-photograph:before{content:"\F09E"}.van-icon-play-circle-o:before{content:"\F09F"}.van-icon-play-circle:before{content:"\F0A0"}.van-icon-play:before{content:"\F0A1"}.van-icon-plus:before{content:"\F0A2"}.van-icon-point-gift-o:before{content:"\F0A3"}.van-icon-point-gift:before{content:"\F0A4"}.van-icon-points:before{content:"\F0A5"}.van-icon-printer:before{content:"\F0A6"}.van-icon-qr-invalid:before{content:"\F0A7"}.van-icon-qr:before{content:"\F0A8"}.van-icon-question-o:before{content:"\F0A9"}.van-icon-question:before{content:"\F0AA"}.van-icon-records:before{content:"\F0AB"}.van-icon-refund-o:before{content:"\F0AC"}.van-icon-replay:before{content:"\F0AD"}.van-icon-scan:before{content:"\F0AE"}.van-icon-search:before{content:"\F0AF"}.van-icon-send-gift-o:before{content:"\F0B0"}.van-icon-send-gift:before{content:"\F0B1"}.van-icon-service-o:before{content:"\F0B2"}.van-icon-service:before{content:"\F0B3"}.van-icon-setting-o:before{content:"\F0B4"}.van-icon-setting:before{content:"\F0B5"}.van-icon-share:before{content:"\F0B6"}.van-icon-shop-collect-o:before{content:"\F0B7"}.van-icon-shop-collect:before{content:"\F0B8"}.van-icon-shop-o:before{content:"\F0B9"}.van-icon-shop:before{content:"\F0BA"}.van-icon-shopping-cart-o:before{content:"\F0BB"}.van-icon-shopping-cart:before{content:"\F0BC"}.van-icon-shrink:before{content:"\F0BD"}.van-icon-sign:before{content:"\F0BE"}.van-icon-smile-comment-o:before{content:"\F0BF"}.van-icon-smile-comment:before{content:"\F0C0"}.van-icon-smile-o:before{content:"\F0C1"}.van-icon-smile:before{content:"\F0C2"}.van-icon-star-o:before{content:"\F0C3"}.van-icon-star:before{content:"\F0C4"}.van-icon-stop-circle-o:before{content:"\F0C5"}.van-icon-stop-circle:before{content:"\F0C6"}.van-icon-stop:before{content:"\F0C7"}.van-icon-success:before{content:"\F0C8"}.van-icon-thumb-circle-o:before{content:"\F0C9"}.van-icon-thumb-circle:before{content:"\F0CA"}.van-icon-todo-list-o:before{content:"\F0CB"}.van-icon-todo-list:before{content:"\F0CC"}.van-icon-tosend:before{content:"\F0CD"}.van-icon-tv-o:before{content:"\F0CE"}.van-icon-umbrella-circle:before{content:"\F0CF"}.van-icon-underway-o:before{content:"\F0D0"}.van-icon-underway:before{content:"\F0D1"}.van-icon-upgrade:before{content:"\F0D2"}.van-icon-user-circle-o:before{content:"\F0D3"}.van-icon-user-o:before{content:"\F0D4"}.van-icon-video-o:before{content:"\F0D5"}.van-icon-video:before{content:"\F0D6"}.van-icon-vip-card-o:before{content:"\F0D7"}.van-icon-vip-card:before{content:"\F0D8"}.van-icon-volume-o:before{content:"\F0D9"}.van-icon-volume:before{content:"\F0DA"}.van-icon-wap-home-o:before{content:"\F0DB"}.van-icon-wap-home:before{content:"\F0DC"}.van-icon-wap-nav:before{content:"\F0DD"}.van-icon-warn-o:before{content:"\F0DE"}.van-icon-warning-o:before{content:"\F0DF"}.van-icon-warning:before{content:"\F0E0"}.van-icon-weapp-nav:before{content:"\F0E1"}.van-icon-wechat:before{content:"\F0E2"}.van-icon-youzan-shield:before{content:"\F0E3"}.van-icon--image{width:1em;height:1em}.van-icon__image{width:100%;height:100%}.van-icon__info{z-index:1} @import '../common/index.wxss';@font-face{font-weight:400;font-family:vant-icon;font-style:normal;font-display:auto;src:url(https://img.yzcdn.cn/vant/vant-icon-d3825a.woff2) format("woff2"),url(https://img.yzcdn.cn/vant/vant-icon-d3825a.woff) format("woff"),url(https://img.yzcdn.cn/vant/vant-icon-d3825a.ttf) format("truetype")}.van-icon{position:relative;font:normal normal normal 14px/1 vant-icon;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.van-icon,.van-icon:before{display:inline-block}.van-icon-add-o:before{content:"\F000"}.van-icon-add-square:before{content:"\F001"}.van-icon-add:before{content:"\F002"}.van-icon-after-sale:before{content:"\F003"}.van-icon-aim:before{content:"\F004"}.van-icon-alipay:before{content:"\F005"}.van-icon-apps-o:before{content:"\F006"}.van-icon-arrow-down:before{content:"\F007"}.van-icon-arrow-left:before{content:"\F008"}.van-icon-arrow-up:before{content:"\F009"}.van-icon-arrow:before{content:"\F00A"}.van-icon-ascending:before{content:"\F00B"}.van-icon-audio:before{content:"\F00C"}.van-icon-award-o:before{content:"\F00D"}.van-icon-award:before{content:"\F00E"}.van-icon-bag-o:before{content:"\F00F"}.van-icon-bag:before{content:"\F010"}.van-icon-balance-list-o:before{content:"\F011"}.van-icon-balance-list:before{content:"\F012"}.van-icon-balance-o:before{content:"\F013"}.van-icon-balance-pay:before{content:"\F014"}.van-icon-bar-chart-o:before{content:"\F015"}.van-icon-bars:before{content:"\F016"}.van-icon-bell:before{content:"\F017"}.van-icon-bill-o:before{content:"\F018"}.van-icon-bill:before{content:"\F019"}.van-icon-birthday-cake-o:before{content:"\F01A"}.van-icon-bookmark-o:before{content:"\F01B"}.van-icon-bookmark:before{content:"\F01C"}.van-icon-browsing-history-o:before{content:"\F01D"}.van-icon-browsing-history:before{content:"\F01E"}.van-icon-brush-o:before{content:"\F01F"}.van-icon-bulb-o:before{content:"\F020"}.van-icon-bullhorn-o:before{content:"\F021"}.van-icon-calender-o:before{content:"\F022"}.van-icon-card:before{content:"\F023"}.van-icon-cart-circle-o:before{content:"\F024"}.van-icon-cart-circle:before{content:"\F025"}.van-icon-cart-o:before{content:"\F026"}.van-icon-cart:before{content:"\F027"}.van-icon-cash-back-record:before{content:"\F028"}.van-icon-cash-on-deliver:before{content:"\F029"}.van-icon-cashier-o:before{content:"\F02A"}.van-icon-certificate:before{content:"\F02B"}.van-icon-chart-trending-o:before{content:"\F02C"}.van-icon-chat-o:before{content:"\F02D"}.van-icon-chat:before{content:"\F02E"}.van-icon-checked:before{content:"\F02F"}.van-icon-circle:before{content:"\F030"}.van-icon-clear:before{content:"\F031"}.van-icon-clock-o:before{content:"\F032"}.van-icon-clock:before{content:"\F033"}.van-icon-close:before{content:"\F034"}.van-icon-closed-eye:before{content:"\F035"}.van-icon-cluster-o:before{content:"\F036"}.van-icon-cluster:before{content:"\F037"}.van-icon-column:before{content:"\F038"}.van-icon-comment-circle-o:before{content:"\F039"}.van-icon-comment-circle:before{content:"\F03A"}.van-icon-comment-o:before{content:"\F03B"}.van-icon-comment:before{content:"\F03C"}.van-icon-completed:before{content:"\F03D"}.van-icon-contact:before{content:"\F03E"}.van-icon-coupon-o:before{content:"\F03F"}.van-icon-coupon:before{content:"\F040"}.van-icon-credit-pay:before{content:"\F041"}.van-icon-cross:before{content:"\F042"}.van-icon-debit-pay:before{content:"\F043"}.van-icon-delete:before{content:"\F044"}.van-icon-descending:before{content:"\F045"}.van-icon-description:before{content:"\F046"}.van-icon-desktop-o:before{content:"\F047"}.van-icon-diamond-o:before{content:"\F048"}.van-icon-diamond:before{content:"\F049"}.van-icon-discount:before{content:"\F04A"}.van-icon-down:before{content:"\F04B"}.van-icon-ecard-pay:before{content:"\F04C"}.van-icon-edit:before{content:"\F04D"}.van-icon-ellipsis:before{content:"\F04E"}.van-icon-empty:before{content:"\F04F"}.van-icon-envelop-o:before{content:"\F050"}.van-icon-exchange:before{content:"\F051"}.van-icon-expand-o:before{content:"\F052"}.van-icon-expand:before{content:"\F053"}.van-icon-eye-o:before{content:"\F054"}.van-icon-eye:before{content:"\F055"}.van-icon-fail:before{content:"\F056"}.van-icon-failure:before{content:"\F057"}.van-icon-filter-o:before{content:"\F058"}.van-icon-fire-o:before{content:"\F059"}.van-icon-fire:before{content:"\F05A"}.van-icon-flag-o:before{content:"\F05B"}.van-icon-flower-o:before{content:"\F05C"}.van-icon-free-postage:before{content:"\F05D"}.van-icon-friends-o:before{content:"\F05E"}.van-icon-friends:before{content:"\F05F"}.van-icon-gem-o:before{content:"\F060"}.van-icon-gem:before{content:"\F061"}.van-icon-gift-card-o:before{content:"\F062"}.van-icon-gift-card:before{content:"\F063"}.van-icon-gift-o:before{content:"\F064"}.van-icon-gift:before{content:"\F065"}.van-icon-gold-coin-o:before{content:"\F066"}.van-icon-gold-coin:before{content:"\F067"}.van-icon-good-job-o:before{content:"\F068"}.van-icon-good-job:before{content:"\F069"}.van-icon-goods-collect-o:before{content:"\F06A"}.van-icon-goods-collect:before{content:"\F06B"}.van-icon-graphic:before{content:"\F06C"}.van-icon-home-o:before{content:"\F06D"}.van-icon-hot-o:before{content:"\F06E"}.van-icon-hot-sale-o:before{content:"\F06F"}.van-icon-hot-sale:before{content:"\F070"}.van-icon-hot:before{content:"\F071"}.van-icon-hotel-o:before{content:"\F072"}.van-icon-idcard:before{content:"\F073"}.van-icon-info-o:before{content:"\F074"}.van-icon-info:before{content:"\F075"}.van-icon-invition:before{content:"\F076"}.van-icon-label-o:before{content:"\F077"}.van-icon-label:before{content:"\F078"}.van-icon-like-o:before{content:"\F079"}.van-icon-like:before{content:"\F07A"}.van-icon-live:before{content:"\F07B"}.van-icon-location-o:before{content:"\F07C"}.van-icon-location:before{content:"\F07D"}.van-icon-lock:before{content:"\F07E"}.van-icon-logistics:before{content:"\F07F"}.van-icon-manager-o:before{content:"\F080"}.van-icon-manager:before{content:"\F081"}.van-icon-map-marked:before{content:"\F082"}.van-icon-medal-o:before{content:"\F083"}.van-icon-medal:before{content:"\F084"}.van-icon-more-o:before{content:"\F085"}.van-icon-more:before{content:"\F086"}.van-icon-music-o:before{content:"\F087"}.van-icon-music:before{content:"\F088"}.van-icon-new-arrival-o:before{content:"\F089"}.van-icon-new-arrival:before{content:"\F08A"}.van-icon-new-o:before{content:"\F08B"}.van-icon-new:before{content:"\F08C"}.van-icon-newspaper-o:before{content:"\F08D"}.van-icon-notes-o:before{content:"\F08E"}.van-icon-orders-o:before{content:"\F08F"}.van-icon-other-pay:before{content:"\F090"}.van-icon-paid:before{content:"\F091"}.van-icon-passed:before{content:"\F092"}.van-icon-pause-circle-o:before{content:"\F093"}.van-icon-pause-circle:before{content:"\F094"}.van-icon-pause:before{content:"\F095"}.van-icon-peer-pay:before{content:"\F096"}.van-icon-pending-payment:before{content:"\F097"}.van-icon-phone-circle-o:before{content:"\F098"}.van-icon-phone-circle:before{content:"\F099"}.van-icon-phone-o:before{content:"\F09A"}.van-icon-phone:before{content:"\F09B"}.van-icon-photo-o:before{content:"\F09C"}.van-icon-photo:before{content:"\F09D"}.van-icon-photograph:before{content:"\F09E"}.van-icon-play-circle-o:before{content:"\F09F"}.van-icon-play-circle:before{content:"\F0A0"}.van-icon-play:before{content:"\F0A1"}.van-icon-plus:before{content:"\F0A2"}.van-icon-point-gift-o:before{content:"\F0A3"}.van-icon-point-gift:before{content:"\F0A4"}.van-icon-points:before{content:"\F0A5"}.van-icon-printer:before{content:"\F0A6"}.van-icon-qr-invalid:before{content:"\F0A7"}.van-icon-qr:before{content:"\F0A8"}.van-icon-question-o:before{content:"\F0A9"}.van-icon-question:before{content:"\F0AA"}.van-icon-records:before{content:"\F0AB"}.van-icon-refund-o:before{content:"\F0AC"}.van-icon-replay:before{content:"\F0AD"}.van-icon-scan:before{content:"\F0AE"}.van-icon-search:before{content:"\F0AF"}.van-icon-send-gift-o:before{content:"\F0B0"}.van-icon-send-gift:before{content:"\F0B1"}.van-icon-service-o:before{content:"\F0B2"}.van-icon-service:before{content:"\F0B3"}.van-icon-setting-o:before{content:"\F0B4"}.van-icon-setting:before{content:"\F0B5"}.van-icon-share:before{content:"\F0B6"}.van-icon-shop-collect-o:before{content:"\F0B7"}.van-icon-shop-collect:before{content:"\F0B8"}.van-icon-shop-o:before{content:"\F0B9"}.van-icon-shop:before{content:"\F0BA"}.van-icon-shopping-cart-o:before{content:"\F0BB"}.van-icon-shopping-cart:before{content:"\F0BC"}.van-icon-shrink:before{content:"\F0BD"}.van-icon-sign:before{content:"\F0BE"}.van-icon-smile-comment-o:before{content:"\F0BF"}.van-icon-smile-comment:before{content:"\F0C0"}.van-icon-smile-o:before{content:"\F0C1"}.van-icon-smile:before{content:"\F0C2"}.van-icon-star-o:before{content:"\F0C3"}.van-icon-star:before{content:"\F0C4"}.van-icon-stop-circle-o:before{content:"\F0C5"}.van-icon-stop-circle:before{content:"\F0C6"}.van-icon-stop:before{content:"\F0C7"}.van-icon-success:before{content:"\F0C8"}.van-icon-thumb-circle-o:before{content:"\F0C9"}.van-icon-thumb-circle:before{content:"\F0CA"}.van-icon-todo-list-o:before{content:"\F0CB"}.van-icon-todo-list:before{content:"\F0CC"}.van-icon-tosend:before{content:"\F0CD"}.van-icon-tv-o:before{content:"\F0CE"}.van-icon-umbrella-circle:before{content:"\F0CF"}.van-icon-underway-o:before{content:"\F0D0"}.van-icon-underway:before{content:"\F0D1"}.van-icon-upgrade:before{content:"\F0D2"}.van-icon-user-circle-o:before{content:"\F0D3"}.van-icon-user-o:before{content:"\F0D4"}.van-icon-video-o:before{content:"\F0D5"}.van-icon-video:before{content:"\F0D6"}.van-icon-vip-card-o:before{content:"\F0D7"}.van-icon-vip-card:before{content:"\F0D8"}.van-icon-volume-o:before{content:"\F0D9"}.van-icon-volume:before{content:"\F0DA"}.van-icon-wap-home-o:before{content:"\F0DB"}.van-icon-wap-home:before{content:"\F0DC"}.van-icon-wap-nav:before{content:"\F0DD"}.van-icon-warn-o:before{content:"\F0DE"}.van-icon-warning-o:before{content:"\F0DF"}.van-icon-warning:before{content:"\F0E0"}.van-icon-weapp-nav:before{content:"\F0E1"}.van-icon-wechat:before{content:"\F0E2"}.van-icon-youzan-shield:before{content:"\F0E3"}:host{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-icon--image{width:1em;height:1em}.van-icon__image{width:100%;height:100%}.van-icon__info{z-index:1}
\ No newline at end of file
import { addUnit, isDef } from '../common/utils';
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
const FIT_MODE_MAP = {
none: 'center',
fill: 'scaleToFill',
cover: 'aspectFill',
contain: 'aspectFit',
widthFix: 'widthFix',
heightFix: 'heightFix',
};
VantComponent({
mixins: [button, openType],
classes: ['custom-class', 'loading-class', 'error-class', 'image-class'],
props: {
src: {
type: String,
observer() {
this.setData({
error: false,
loading: true,
});
},
},
round: Boolean,
width: {
type: null,
observer: 'setStyle',
},
height: {
type: null,
observer: 'setStyle',
},
radius: null,
lazyLoad: Boolean,
useErrorSlot: Boolean,
useLoadingSlot: Boolean,
showMenuByLongpress: Boolean,
fit: {
type: String,
value: 'fill',
observer: 'setMode',
},
showError: {
type: Boolean,
value: true,
},
showLoading: {
type: Boolean,
value: true,
},
},
data: {
error: false,
loading: true,
viewStyle: '',
},
mounted() {
this.setMode();
this.setStyle();
},
methods: {
setMode() {
this.setData({
mode: FIT_MODE_MAP[this.data.fit],
});
},
setStyle() {
const { width, height, radius } = this.data;
let style = '';
if (isDef(width)) {
style += `width: ${addUnit(width)};`;
}
if (isDef(height)) {
style += `height: ${addUnit(height)};`;
}
if (isDef(radius)) {
style += 'overflow: hidden;';
style += `border-radius: ${addUnit(radius)};`;
}
this.setData({ viewStyle: style });
},
onLoad(event) {
this.setData({
loading: false,
});
this.$emit('load', event.detail);
},
onError(event) {
this.setData({
loading: false,
error: true,
});
this.$emit('error', event.detail);
},
onClick(event) {
this.$emit('click', event.detail);
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
style="{{ viewStyle }}"
class="custom-class {{ utils.bem('image', { round })}}"
bind:tap="onClick"
>
<image
wx:if="{{ !error }}"
src="{{ src }}"
mode="{{ mode }}"
lazy-load="{{ lazyLoad }}"
class="image-class van-image__img"
show-menu-by-longpress="{{ showMenuByLongpress }}"
bind:load="onLoad"
bind:error="onError"
/>
<view
wx:if="{{ loading && showLoading }}"
class="loading-class van-image__loading"
>
<slot wx:if="{{ useLoadingSlot }}" name="loading" />
<van-icon wx:else name="photo-o" size="22" />
</view>
<view
wx:if="{{ error && showError }}"
class="error-class van-image__error"
>
<slot wx:if="{{ useErrorSlot }}" name="error" />
<van-icon wx:else name="warning-o" size="22" />
</view>
</view>
@import '../common/index.wxss';.van-image{position:relative;display:inline-block}.van-image--round{overflow:hidden;border-radius:50%}.van-image--round .van-image__img{border-radius:inherit}.van-image__error,.van-image__img,.van-image__loading{display:block;width:100%;height:100%}.van-image__error,.van-image__loading{position:absolute;top:0;left:0;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#969799;color:var(--image-placeholder-text-color,#969799);font-size:14px;font-size:var(--image-placeholder-font-size,14px);background-color:#f7f8fa;background-color:var(--image-placeholder-background-color,#f7f8fa)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'index-bar',
type: 'ancestor',
current: 'index-anchor',
},
props: {
useSlot: Boolean,
index: null,
},
data: {
active: false,
wrapperStyle: '',
anchorStyle: '',
},
methods: {
scrollIntoView(scrollTop) {
this.getBoundingClientRect().then((rect) => {
wx.pageScrollTo({
duration: 0,
scrollTop: scrollTop + rect.top - this.parent.data.stickyOffsetTop,
});
});
},
getBoundingClientRect() {
return this.getRect('.van-index-anchor-wrapper');
},
},
});
<view
class="van-index-anchor-wrapper"
style="{{ wrapperStyle }}"
>
<view
class="van-index-anchor {{ active ? 'van-index-anchor--active van-hairline--bottom' : '' }}"
style="{{ anchorStyle }}"
>
<slot wx:if="{{ useSlot }}"/>
<block wx:else>
<text>{{ index }}</text>
</block>
</view>
</view>
@import '../common/index.wxss';.van-index-anchor{padding:0 16px;padding:var(--index-anchor-padding,0 16px);color:#323233;color:var(--index-anchor-text-color,#323233);font-weight:500;font-weight:var(--index-anchor-font-weight,500);font-size:14px;font-size:var(--index-anchor-font-size,14px);line-height:32px;line-height:var(--index-anchor-line-height,32px);background-color:initial;background-color:var(--index-anchor-background-color,transparent)}.van-index-anchor--active{right:0;left:0;color:#07c160;color:var(--index-anchor-active-text-color,#07c160);background-color:#fff;background-color:var(--index-anchor-active-background-color,#fff)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { GREEN } from '../common/color';
import { pageScrollMixin } from '../mixins/page-scroll';
const indexList = () => {
const indexList = [];
const charCodeOfA = 'A'.charCodeAt(0);
for (let i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i));
}
return indexList;
};
VantComponent({
relation: {
name: 'index-anchor',
type: 'descendant',
current: 'index-bar',
linked() {
this.updateData();
},
unlinked() {
this.updateData();
},
},
props: {
sticky: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 1,
},
highlightColor: {
type: String,
value: GREEN,
},
stickyOffsetTop: {
type: Number,
value: 0,
},
indexList: {
type: Array,
value: indexList(),
},
},
mixins: [
pageScrollMixin(function (event) {
this.scrollTop = event.scrollTop || 0;
this.onScroll();
}),
],
data: {
activeAnchorIndex: null,
showSidebar: false,
},
created() {
this.scrollTop = 0;
},
methods: {
updateData() {
wx.nextTick(() => {
if (this.timer != null) {
clearTimeout(this.timer);
}
this.timer = setTimeout(() => {
this.setData({
showSidebar: !!this.children.length,
});
this.setRect().then(() => {
this.onScroll();
});
}, 0);
});
},
setRect() {
return Promise.all([
this.setAnchorsRect(),
this.setListRect(),
this.setSiderbarRect(),
]);
},
setAnchorsRect() {
return Promise.all(
this.children.map((anchor) =>
anchor.getRect('.van-index-anchor-wrapper').then((rect) => {
Object.assign(anchor, {
height: rect.height,
top: rect.top + this.scrollTop,
});
})
)
);
},
setListRect() {
return this.getRect('.van-index-bar').then((rect) => {
Object.assign(this, {
height: rect.height,
top: rect.top + this.scrollTop,
});
});
},
setSiderbarRect() {
return this.getRect('.van-index-bar__sidebar').then((res) => {
this.sidebar = {
height: res.height,
top: res.top,
};
});
},
setDiffData({ target, data }) {
const diffData = {};
Object.keys(data).forEach((key) => {
if (target.data[key] !== data[key]) {
diffData[key] = data[key];
}
});
if (Object.keys(diffData).length) {
target.setData(diffData);
}
},
getAnchorRect(anchor) {
return anchor.getRect('.van-index-anchor-wrapper').then((rect) => ({
height: rect.height,
top: rect.top,
}));
},
getActiveAnchorIndex() {
const { children, scrollTop } = this;
const { sticky, stickyOffsetTop } = this.data;
for (let i = this.children.length - 1; i >= 0; i--) {
const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
const reachTop = sticky ? preAnchorHeight + stickyOffsetTop : 0;
if (reachTop + scrollTop >= children[i].top) {
return i;
}
}
return -1;
},
onScroll() {
const { children = [], scrollTop } = this;
if (!children.length) {
return;
}
const { sticky, stickyOffsetTop, zIndex, highlightColor } = this.data;
const active = this.getActiveAnchorIndex();
this.setDiffData({
target: this,
data: {
activeAnchorIndex: active,
},
});
if (sticky) {
let isActiveAnchorSticky = false;
if (active !== -1) {
isActiveAnchorSticky =
children[active].top <= stickyOffsetTop + scrollTop;
}
children.forEach((item, index) => {
if (index === active) {
let wrapperStyle = '';
let anchorStyle = `
color: ${highlightColor};
`;
if (isActiveAnchorSticky) {
wrapperStyle = `
height: ${children[index].height}px;
`;
anchorStyle = `
position: fixed;
top: ${stickyOffsetTop}px;
z-index: ${zIndex};
color: ${highlightColor};
`;
}
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle,
wrapperStyle,
},
});
} else if (index === active - 1) {
const currentAnchor = children[index];
const currentOffsetTop = currentAnchor.top;
const targetOffsetTop =
index === children.length - 1
? this.top
: children[index + 1].top;
const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
const translateY = parentOffsetHeight - currentAnchor.height;
const anchorStyle = `
position: relative;
transform: translate3d(0, ${translateY}px, 0);
z-index: ${zIndex};
color: ${highlightColor};
`;
this.setDiffData({
target: item,
data: {
active: true,
anchorStyle,
},
});
} else {
this.setDiffData({
target: item,
data: {
active: false,
anchorStyle: '',
wrapperStyle: '',
},
});
}
});
}
},
onClick(event) {
this.scrollToAnchor(event.target.dataset.index);
},
onTouchMove(event) {
const sidebarLength = this.children.length;
const touch = event.touches[0];
const itemHeight = this.sidebar.height / sidebarLength;
let index = Math.floor((touch.clientY - this.sidebar.top) / itemHeight);
if (index < 0) {
index = 0;
} else if (index > sidebarLength - 1) {
index = sidebarLength - 1;
}
this.scrollToAnchor(index);
},
onTouchStop() {
this.scrollToAnchorIndex = null;
},
scrollToAnchor(index) {
if (typeof index !== 'number' || this.scrollToAnchorIndex === index) {
return;
}
this.scrollToAnchorIndex = index;
const anchor = this.children.find(
(item) => item.data.index === this.data.indexList[index]
);
if (anchor) {
anchor.scrollIntoView(this.scrollTop);
this.$emit('select', anchor.data.index);
}
},
},
});
<view class="van-index-bar">
<slot />
<view
wx:if="{{ showSidebar }}"
class="van-index-bar__sidebar"
catch:tap="onClick"
catch:touchmove="onTouchMove"
catch:touchend="onTouchStop"
catch:touchcancel="onTouchStop"
>
<view
wx:for="{{ indexList }}"
wx:key="index"
class="van-index-bar__index"
style="z-index: {{ zIndex + 1 }}; color: {{ activeAnchorIndex === index ? highlightColor : '' }}"
data-index="{{ index }}"
>
{{ item }}
</view>
</view>
</view>
@import '../common/index.wxss';.van-index-bar{position:relative}.van-index-bar__sidebar{position:fixed;top:50%;right:0;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;text-align:center;-webkit-transform:translateY(-50%);transform:translateY(-50%);-webkit-user-select:none;user-select:none}.van-index-bar__index{font-weight:500;padding:0 4px 0 16px;padding:0 var(--padding-base,4px) 0 var(--padding-md,16px);font-size:10px;font-size:var(--index-bar-index-font-size,10px);line-height:14px;line-height:var(--index-bar-index-line-height,14px)}
\ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
VantComponent({ VantComponent({
props: { props: {
dot: Boolean,
info: null, info: null,
customStyle: String customStyle: String,
} },
}); });
<wxs src="../wxs/utils.wxs" module="utils" />
<view <view
wx:if="{{ info !== null && info !== '' }}" wx:if="{{ info !== null && info !== '' || dot }}"
class="custom-class van-info" class="custom-class van-info {{ utils.bem('info', { dot }) }}"
style="{{ customStyle }}" style="{{ customStyle }}"
>{{ info }}</view> >{{ dot ? '' : info }}</view>
@import '../common/index.wxss';.van-info{position:absolute;top:-8px;right:0;min-width:16px;padding:0 3px;font-family:PingFang SC,Helvetica Neue,Arial,sans-serif;font-size:12px;font-weight:500;line-height:14px;color:#fff;text-align:center;white-space:nowrap;background-color:#f44;border:1px solid #fff;border-radius:16px;-webkit-transform:translateX(50%);transform:translateX(50%);box-sizing:border-box;-webkit-transform-origin:100%;transform-origin:100%} @import '../common/index.wxss';.van-info{position:absolute;top:0;right:0;box-sizing:border-box;white-space:nowrap;text-align:center;-webkit-transform:translate(50%,-50%);transform:translate(50%,-50%);-webkit-transform-origin:100%;transform-origin:100%;min-width:16px;min-width:var(--info-size,16px);padding:0 3px;padding:var(--info-padding,0 3px);color:#fff;color:var(--info-color,#fff);font-weight:500;font-weight:var(--info-font-weight,500);font-size:12px;font-size:var(--info-font-size,12px);font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif;font-family:var(--info-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif);line-height:14px;line-height:calc(var(--info-size, 16px) - var(--info-border-width, 1px)*2);background-color:#ee0a24;background-color:var(--info-background-color,#ee0a24);border:1px solid #fff;border:var(--info-border-width,1px) solid var(--white,#fff);border-radius:16px;border-radius:var(--info-size,16px)}.van-info--dot{min-width:0;border-radius:100%;width:8px;width:var(--info-dot-size,8px);height:8px;height:var(--info-dot-size,8px);background-color:#ee0a24;background-color:var(--info-dot-color,#ee0a24)}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
VantComponent({ VantComponent({
props: { props: {
size: { color: String,
type: String, vertical: Boolean,
value: '30px'
},
type: { type: {
type: String, type: String,
value: 'circular' value: 'circular',
},
size: String,
textSize: String,
},
data: {
array12: Array.from({ length: 12 }),
}, },
color: {
type: String,
value: '#c9c9c9'
}
}
}); });
<view <wxs src="../wxs/utils.wxs" module="utils" />
class="van-loading custom-class"
style="width: {{ size }}; height: {{ size }}" <view class="custom-class van-loading {{ vertical ? 'van-loading--vertical' : '' }}">
>
<view <view
class="van-loading__spinner van-loading__spinner--{{ type }}" class="van-loading__spinner van-loading__spinner--{{ type }}"
style="color: {{ color }};" style="color: {{ color }}; width: {{ utils.addUnit(size) }}; height: {{ utils.addUnit(size) }}"
> >
<view <view
wx:if="{{ type === 'spinner' }}" wx:if="{{ type === 'spinner' }}"
wx:for="item in 12" wx:for="{{ array12 }}"
wx:key="index" wx:key="index"
class="van-loading__dot" class="van-loading__dot"
/> />
</view> </view>
<view class="van-loading__text" style="font-size: {{ utils.addUnit(textSize) }};">
<slot />
</view>
</view> </view>
@import '../common/index.wxss';.van-loading{z-index:0;line-height:0;vertical-align:middle}.van-loading,.van-loading__spinner{position:relative;display:inline-block}.van-loading__spinner{z-index:-1;width:100%;height:100%;box-sizing:border-box;-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border-radius:100%;border:1px solid transparent;border-top-color:initial}.van-loading__dot{top:0;left:0;width:100%;height:100%;position:absolute}.van-loading__dot:before{width:2px;height:25%;content:" ";display:block;margin:0 auto;border-radius:40%;background-color:currentColor}.van-loading__dot:first-of-type{opacity:1;-webkit-transform:rotate(30deg);transform:rotate(30deg)}.van-loading__dot:nth-of-type(2){opacity:.9375;-webkit-transform:rotate(60deg);transform:rotate(60deg)}.van-loading__dot:nth-of-type(3){opacity:.875;-webkit-transform:rotate(90deg);transform:rotate(90deg)}.van-loading__dot:nth-of-type(4){opacity:.8125;-webkit-transform:rotate(120deg);transform:rotate(120deg)}.van-loading__dot:nth-of-type(5){opacity:.75;-webkit-transform:rotate(150deg);transform:rotate(150deg)}.van-loading__dot:nth-of-type(6){opacity:.6875;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.van-loading__dot:nth-of-type(7){opacity:.625;-webkit-transform:rotate(210deg);transform:rotate(210deg)}.van-loading__dot:nth-of-type(8){opacity:.5625;-webkit-transform:rotate(240deg);transform:rotate(240deg)}.van-loading__dot:nth-of-type(9){opacity:.5;-webkit-transform:rotate(270deg);transform:rotate(270deg)}.van-loading__dot:nth-of-type(10){opacity:.4375;-webkit-transform:rotate(300deg);transform:rotate(300deg)}.van-loading__dot:nth-of-type(11){opacity:.375;-webkit-transform:rotate(330deg);transform:rotate(330deg)}.van-loading__dot:nth-of-type(12){opacity:.3125;-webkit-transform:rotate(1turn);transform:rotate(1turn)}@-webkit-keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}} @import '../common/index.wxss';:host{font-size:0;line-height:1}.van-loading{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#c8c9cc;color:var(--loading-spinner-color,#c8c9cc)}.van-loading__spinner{position:relative;box-sizing:border-box;width:30px;width:var(--loading-spinner-size,30px);max-width:100%;max-height:100%;height:30px;height:var(--loading-spinner-size,30px);-webkit-animation:van-rotate .8s linear infinite;animation:van-rotate .8s linear infinite;-webkit-animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite;animation:van-rotate var(--loading-spinner-animation-duration,.8s) linear infinite}.van-loading__spinner--spinner{-webkit-animation-timing-function:steps(12);animation-timing-function:steps(12)}.van-loading__spinner--circular{border:1px solid transparent;border-top-color:initial;border-radius:100%}.van-loading__text{margin-left:8px;margin-left:var(--padding-xs,8px);color:#969799;color:var(--loading-text-color,#969799);font-size:14px;font-size:var(--loading-text-font-size,14px);line-height:20px;line-height:var(--loading-text-line-height,20px)}.van-loading__text:empty{display:none}.van-loading--vertical{-webkit-flex-direction:column;flex-direction:column}.van-loading--vertical .van-loading__text{margin:8px 0 0;margin:var(--padding-xs,8px) 0 0}.van-loading__dot{position:absolute;top:0;left:0;width:100%;height:100%}.van-loading__dot:before{display:block;width:2px;height:25%;margin:0 auto;background-color:currentColor;border-radius:40%;content:" "}.van-loading__dot:first-of-type{-webkit-transform:rotate(30deg);transform:rotate(30deg);opacity:1}.van-loading__dot:nth-of-type(2){-webkit-transform:rotate(60deg);transform:rotate(60deg);opacity:.9375}.van-loading__dot:nth-of-type(3){-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:.875}.van-loading__dot:nth-of-type(4){-webkit-transform:rotate(120deg);transform:rotate(120deg);opacity:.8125}.van-loading__dot:nth-of-type(5){-webkit-transform:rotate(150deg);transform:rotate(150deg);opacity:.75}.van-loading__dot:nth-of-type(6){-webkit-transform:rotate(180deg);transform:rotate(180deg);opacity:.6875}.van-loading__dot:nth-of-type(7){-webkit-transform:rotate(210deg);transform:rotate(210deg);opacity:.625}.van-loading__dot:nth-of-type(8){-webkit-transform:rotate(240deg);transform:rotate(240deg);opacity:.5625}.van-loading__dot:nth-of-type(9){-webkit-transform:rotate(270deg);transform:rotate(270deg);opacity:.5}.van-loading__dot:nth-of-type(10){-webkit-transform:rotate(300deg);transform:rotate(300deg);opacity:.4375}.van-loading__dot:nth-of-type(11){-webkit-transform:rotate(330deg);transform:rotate(330deg);opacity:.375}.van-loading__dot:nth-of-type(12){-webkit-transform:rotate(1turn);transform:rotate(1turn);opacity:.3125}@-webkit-keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes van-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
\ No newline at end of file \ No newline at end of file
...@@ -3,11 +3,16 @@ export const basic = Behavior({ ...@@ -3,11 +3,16 @@ export const basic = Behavior({
$emit(...args) { $emit(...args) {
this.triggerEvent(...args); this.triggerEvent(...args);
}, },
set(data, callback) {
this.setData(data, callback);
return new Promise((resolve) => wx.nextTick(resolve));
},
getRect(selector, all) { getRect(selector, all) {
return new Promise(resolve => { return new Promise((resolve) => {
wx.createSelectorQuery() wx.createSelectorQuery()
.in(this)[all ? 'selectAll' : 'select'](selector) .in(this)
.boundingClientRect(rect => { [all ? 'selectAll' : 'select'](selector)
.boundingClientRect((rect) => {
if (all && Array.isArray(rect) && rect.length) { if (all && Array.isArray(rect) && rect.length) {
resolve(rect); resolve(rect);
} }
...@@ -17,6 +22,6 @@ export const basic = Behavior({ ...@@ -17,6 +22,6 @@ export const basic = Behavior({
}) })
.exec(); .exec();
}); });
} },
} },
}); });
...@@ -2,10 +2,7 @@ export const button = Behavior({ ...@@ -2,10 +2,7 @@ export const button = Behavior({
externalClasses: ['hover-class'], externalClasses: ['hover-class'],
properties: { properties: {
id: String, id: String,
lang: { lang: String,
type: String,
value: 'en'
},
businessId: Number, businessId: Number,
sessionFrom: String, sessionFrom: String,
sendMessageTitle: String, sendMessageTitle: String,
...@@ -13,6 +10,6 @@ export const button = Behavior({ ...@@ -13,6 +10,6 @@ export const button = Behavior({
sendMessageImg: String, sendMessageImg: String,
showMessageCard: Boolean, showMessageCard: Boolean,
appParameter: String, appParameter: String,
ariaLabel: String ariaLabel: String,
} },
}); });
...@@ -3,8 +3,8 @@ export const link = Behavior({ ...@@ -3,8 +3,8 @@ export const link = Behavior({
url: String, url: String,
linkType: { linkType: {
type: String, type: String,
value: 'navigateTo' value: 'navigateTo',
} },
}, },
methods: { methods: {
jumpLink(urlKey = 'url') { jumpLink(urlKey = 'url') {
...@@ -12,6 +12,6 @@ export const link = Behavior({ ...@@ -12,6 +12,6 @@ export const link = Behavior({
if (url) { if (url) {
wx[this.data.linkType]({ url }); wx[this.data.linkType]({ url });
} }
} },
} },
}); });
function setAsync(context, data) {
return new Promise(resolve => {
context.setData(data, resolve);
});
}
export const behavior = Behavior({
created() {
if (!this.$options) {
return;
}
const cache = {};
const { computed } = this.$options();
const keys = Object.keys(computed);
this.calcComputed = () => {
const needUpdate = {};
keys.forEach(key => {
const value = computed[key].call(this);
if (cache[key] !== value) {
cache[key] = value;
needUpdate[key] = value;
}
});
return needUpdate;
};
},
attached() {
this.set();
},
methods: {
// set data and set computed data
set(data, callback) {
const stack = [];
if (data) {
stack.push(setAsync(this, data));
}
if (this.calcComputed) {
stack.push(setAsync(this, this.calcComputed()));
}
return Promise.all(stack).then(res => {
if (callback && typeof callback === 'function') {
callback.call(this);
}
return res;
});
}
}
});
export declare function observe(vantOptions: any, options: any): void;
import { behavior } from './behavior';
import { observeProps } from './props';
export function observe(vantOptions, options) {
const { watch, computed } = vantOptions;
options.behaviors.push(behavior);
if (watch) {
const props = options.properties || {};
Object.keys(watch).forEach(key => {
if (key in props) {
let prop = props[key];
if (prop === null || !('type' in prop)) {
prop = { type: prop };
}
prop.observer = watch[key];
props[key] = prop;
}
});
options.properties = props;
}
if (computed) {
options.methods = options.methods || {};
options.methods.$options = () => vantOptions;
if (options.properties) {
observeProps(options.properties);
}
}
}
export declare function observeProps(props: any): void;
export function observeProps(props) {
if (!props) {
return;
}
Object.keys(props).forEach(key => {
let prop = props[key];
if (prop === null || !('type' in prop)) {
prop = { type: prop };
}
let { observer } = prop;
prop.observer = function (...args) {
if (observer) {
if (typeof observer === 'string') {
observer = this[observer];
}
observer.apply(this, args);
}
this.set();
};
props[key] = prop;
});
}
export const openType = Behavior({ export const openType = Behavior({
properties: { properties: {
openType: String openType: String,
}, },
methods: { methods: {
bindGetUserInfo(event) { bindGetUserInfo(event) {
...@@ -21,5 +21,5 @@ export const openType = Behavior({ ...@@ -21,5 +21,5 @@ export const openType = Behavior({
bindOpenSetting(event) { bindOpenSetting(event) {
this.$emit('opensetting', event.detail); this.$emit('opensetting', event.detail);
}, },
} },
}); });
/// <reference types="miniprogram-api-typings" />
declare type IPageScrollOption = WechatMiniprogram.Page.IPageScrollOption;
declare type Scroller = (event: IPageScrollOption) => void;
export declare const pageScrollMixin: (scroller: Scroller) => string;
export {};
function getCurrentPage() {
const pages = getCurrentPages();
return pages[pages.length - 1] || {};
}
function onPageScroll(event) {
const { vanPageScroller = [] } = getCurrentPage();
vanPageScroller.forEach((scroller) => {
if (typeof scroller === 'function') {
scroller(event);
}
});
}
export const pageScrollMixin = (scroller) =>
Behavior({
attached() {
const page = getCurrentPage();
if (Array.isArray(page.vanPageScroller)) {
page.vanPageScroller.push(scroller.bind(this));
} else {
page.vanPageScroller =
typeof page.onPageScroll === 'function'
? [page.onPageScroll.bind(page), scroller.bind(this)]
: [scroller.bind(this)];
}
page.onPageScroll = onPageScroll;
},
detached() {
const page = getCurrentPage();
page.vanPageScroller = (page.vanPageScroller || []).filter(
(item) => item !== scroller
);
},
});
export declare const safeArea: ({ safeAreaInsetBottom, safeAreaInsetTop }?: {
safeAreaInsetBottom?: boolean;
safeAreaInsetTop?: boolean;
}) => string;
let cache = null;
function getSafeArea() {
return new Promise((resolve, reject) => {
if (cache != null) {
resolve(cache);
}
else {
wx.getSystemInfo({
success: ({ model, statusBarHeight }) => {
const deviceType = model.replace(/\s/g, '-');
const iphoneNew = /iphone-x|iPhone11|iPhone12/i.test(deviceType);
cache = {
isIPhoneX: iphoneNew,
statusBarHeight
};
resolve(cache);
},
fail: reject
});
}
});
}
export const safeArea = ({ safeAreaInsetBottom = true, safeAreaInsetTop = false } = {}) => Behavior({
properties: {
safeAreaInsetTop: {
type: Boolean,
value: safeAreaInsetTop
},
safeAreaInsetBottom: {
type: Boolean,
value: safeAreaInsetBottom
}
},
created() {
getSafeArea().then(({ isIPhoneX, statusBarHeight }) => {
this.set({ isIPhoneX, statusBarHeight });
});
}
});
const MIN_DISTANCE = 10;
function getDirection(x, y) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
}
export const touch = Behavior({ export const touch = Behavior({
methods: { methods: {
touchStart(event) { resetTouchStatus() {
const touch = event.touches[0];
this.direction = ''; this.direction = '';
this.deltaX = 0; this.deltaX = 0;
this.deltaY = 0; this.deltaY = 0;
this.offsetX = 0; this.offsetX = 0;
this.offsetY = 0; this.offsetY = 0;
},
touchStart(event) {
this.resetTouchStatus();
const touch = event.touches[0];
this.startX = touch.clientX; this.startX = touch.clientX;
this.startY = touch.clientY; this.startY = touch.clientY;
}, },
...@@ -17,11 +30,7 @@ export const touch = Behavior({ ...@@ -17,11 +30,7 @@ export const touch = Behavior({
this.offsetX = Math.abs(this.deltaX); this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY); this.offsetY = Math.abs(this.deltaY);
this.direction = this.direction =
this.offsetX > this.offsetY this.direction || getDirection(this.offsetX, this.offsetY);
? 'horizontal' },
: this.offsetX < this.offsetY },
? 'vertical'
: '';
}
}
}); });
export declare const transition: (showDefaultValue: boolean) => any; export declare const transition: (showDefaultValue: boolean) => string;
...@@ -3,9 +3,9 @@ const getClassNames = (name) => ({ ...@@ -3,9 +3,9 @@ const getClassNames = (name) => ({
enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`, enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`,
'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`, 'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`,
leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`, leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`,
'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class` 'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class`,
}); });
const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 30)); const nextTick = () => new Promise((resolve) => setTimeout(resolve, 1000 / 30));
export const transition = function (showDefaultValue) { export const transition = function (showDefaultValue) {
return Behavior({ return Behavior({
properties: { properties: {
...@@ -14,86 +14,88 @@ export const transition = function (showDefaultValue) { ...@@ -14,86 +14,88 @@ export const transition = function (showDefaultValue) {
show: { show: {
type: Boolean, type: Boolean,
value: showDefaultValue, value: showDefaultValue,
observer: 'observeShow' observer: 'observeShow',
}, },
// @ts-ignore // @ts-ignore
duration: { duration: {
type: [Number, Object], type: null,
value: 300, value: 300,
observer: 'observeDuration' observer: 'observeDuration',
}, },
name: { name: {
type: String, type: String,
value: 'fade' value: 'fade',
} },
}, },
data: { data: {
type: '', type: '',
inited: false, inited: false,
display: false display: false,
},
attached() {
if (this.data.show) {
this.enter();
}
}, },
methods: { methods: {
observeShow(value) { observeShow(value, old) {
if (value) { if (value === old) {
this.enter(); return;
}
else {
this.leave();
} }
value ? this.enter() : this.leave();
}, },
enter() { enter() {
const { duration, name } = this.data; const { duration, name } = this.data;
const classNames = getClassNames(name); const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.enter : duration; const currentDuration = isObj(duration) ? duration.enter : duration;
this.status = 'enter'; this.status = 'enter';
this.$emit('before-enter');
Promise.resolve() Promise.resolve()
.then(nextTick) .then(nextTick)
.then(() => { .then(() => {
this.checkStatus('enter'); this.checkStatus('enter');
this.set({ this.$emit('enter');
this.setData({
inited: true, inited: true,
display: true, display: true,
classes: classNames.enter, classes: classNames.enter,
currentDuration currentDuration,
}); });
}) })
.then(nextTick) .then(nextTick)
.then(() => { .then(() => {
this.checkStatus('enter'); this.checkStatus('enter');
this.set({ this.transitionEnded = false;
classes: classNames['enter-to'] this.setData({
classes: classNames['enter-to'],
}); });
}) })
.catch(() => { }); .catch(() => {});
}, },
leave() { leave() {
if (!this.data.display) {
return;
}
const { duration, name } = this.data; const { duration, name } = this.data;
const classNames = getClassNames(name); const classNames = getClassNames(name);
const currentDuration = isObj(duration) ? duration.leave : duration; const currentDuration = isObj(duration) ? duration.leave : duration;
this.status = 'leave'; this.status = 'leave';
this.$emit('before-leave');
Promise.resolve() Promise.resolve()
.then(nextTick) .then(nextTick)
.then(() => { .then(() => {
this.checkStatus('leave'); this.checkStatus('leave');
this.set({ this.$emit('leave');
this.setData({
classes: classNames.leave, classes: classNames.leave,
currentDuration currentDuration,
}); });
}) })
.then(() => setTimeout(() => this.onTransitionEnd(), currentDuration))
.then(nextTick) .then(nextTick)
.then(() => { .then(() => {
this.checkStatus('leave'); this.checkStatus('leave');
this.set({ this.transitionEnded = false;
classes: classNames['leave-to'] setTimeout(() => this.onTransitionEnd(), currentDuration);
this.setData({
classes: classNames['leave-to'],
}); });
}) })
.catch(() => { }); .catch(() => {});
}, },
checkStatus(status) { checkStatus(status) {
if (status !== this.status) { if (status !== this.status) {
...@@ -101,11 +103,16 @@ export const transition = function (showDefaultValue) { ...@@ -101,11 +103,16 @@ export const transition = function (showDefaultValue) {
} }
}, },
onTransitionEnd() { onTransitionEnd() {
if (!this.data.show) { if (this.transitionEnded) {
this.set({ display: false }); return;
this.$emit('transitionEnd');
}
} }
this.transitionEnded = true;
this.$emit(`after-${this.status}`);
const { show, display } = this.data;
if (!show && display) {
this.setData({ display: false });
} }
},
},
}); });
}; };
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({ VantComponent({
mixins: [safeArea({ safeAreaInsetTop: true })],
classes: ['title-class'], classes: ['title-class'],
props: { props: {
title: String, title: String,
fixed: Boolean, fixed: {
type: Boolean,
observer: 'setHeight',
},
placeholder: {
type: Boolean,
observer: 'setHeight',
},
leftText: String, leftText: String,
rightText: String, rightText: String,
customStyle: String,
leftArrow: Boolean, leftArrow: Boolean,
border: { border: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
zIndex: { zIndex: {
type: Number, type: Number,
value: 120 value: 1,
} },
safeAreaInsetTop: {
type: Boolean,
value: true,
},
},
data: {
statusBarHeight: 0,
height: 44,
baseStyle: '',
},
created() {
const { statusBarHeight } = wx.getSystemInfoSync();
const { safeAreaInsetTop, zIndex } = this.data;
const paddingTop = safeAreaInsetTop ? statusBarHeight : 0;
const baseStyle = `z-index: ${zIndex};padding-top: ${paddingTop}px;`;
this.setData({
statusBarHeight,
height: 44 + statusBarHeight,
baseStyle,
});
},
mounted() {
this.setHeight();
}, },
methods: { methods: {
onClickLeft() { onClickLeft() {
...@@ -24,6 +53,16 @@ VantComponent({ ...@@ -24,6 +53,16 @@ VantComponent({
}, },
onClickRight() { onClickRight() {
this.$emit('click-right'); this.$emit('click-right');
},
setHeight() {
if (!this.data.fixed || !this.data.placeholder) {
return;
} }
} wx.nextTick(() => {
this.getRect('.van-nav-bar').then((res) => {
this.setData({ height: res.height });
});
});
},
},
}); });
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<view wx:if="{{ fixed && placeholder }}" style="height: {{ height }}px;" />
<view <view
class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}" class="{{ utils.bem('nav-bar', { fixed }) }} custom-class {{ border ? 'van-hairline--bottom' : '' }}"
style="z-index: {{ zIndex }}; {{ safeAreaInsetTop ? 'padding-top: ' + statusBarHeight + 'px;' : '' }}" style="{{ baseStyle }} {{ customStyle }}"
> >
<view class="van-nav-bar__left" bind:tap="onClickLeft"> <view class="van-nav-bar__left" bind:tap="onClickLeft">
<block wx:if="{{ leftArrow || leftText }}"> <block wx:if="{{ leftArrow || leftText }}">
......
@import '../common/index.wxss';.van-nav-bar{position:relative;height:44px;line-height:44px;text-align:center;background-color:#fff;-webkit-user-select:none;user-select:none}.van-nav-bar__text{display:inline-block;padding:0 15px;margin:0 -15px;color:#1989fa;vertical-align:middle}.van-nav-bar__text--hover{background-color:#f2f3f5}.van-nav-bar__arrow{color:#1989fa;vertical-align:middle}.van-nav-bar__arrow+.van-nav-bar__text{padding-left:25px;margin-left:-20px}.van-nav-bar--fixed{position:fixed;top:0;left:0;width:100%}.van-nav-bar__title{max-width:60%;margin:0 auto;font-size:16px;font-weight:500}.van-nav-bar__left,.van-nav-bar__right{position:absolute;bottom:0;font-size:14px}.van-nav-bar__left{left:15px}.van-nav-bar__right{right:15px} @import '../common/index.wxss';.van-nav-bar{position:relative;text-align:center;-webkit-user-select:none;user-select:none;height:44px;height:var(--nav-bar-height,44px);line-height:44px;line-height:var(--nav-bar-height,44px);background-color:#fff;background-color:var(--nav-bar-background-color,#fff)}.van-nav-bar__text{display:inline-block;vertical-align:middle;margin:0 -16px;margin:0 -var(--padding-md,16px);padding:0 16px;padding:0 var(--padding-md,16px);color:#1989fa;color:var(--nav-bar-text-color,#1989fa)}.van-nav-bar__text--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}.van-nav-bar__arrow{vertical-align:middle;font-size:16px;font-size:var(--nav-bar-arrow-size,16px);color:#1989fa;color:var(--nav-bar-text-color,#1989fa)}.van-nav-bar__arrow+.van-nav-bar__text{margin-left:-20px;padding-left:25px}.van-nav-bar--fixed{position:fixed;top:0;left:0;width:100%}.van-nav-bar__title{max-width:60%;margin:0 auto;color:#323233;color:var(--nav-bar-title-text-color,#323233);font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--nav-bar-title-font-size,16px)}.van-nav-bar__left,.van-nav-bar__right{position:absolute;bottom:0;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;font-size:14px;font-size:var(--font-size-md,14px)}.van-nav-bar__left{left:16px;left:var(--padding-md,16px)}.van-nav-bar__right{right:16px;right:var(--padding-md,16px)}
\ No newline at end of file \ No newline at end of file
...@@ -5,58 +5,63 @@ VantComponent({ ...@@ -5,58 +5,63 @@ VantComponent({
props: { props: {
text: { text: {
type: String, type: String,
value: '' value: '',
observer() {
wx.nextTick(() => {
this.init();
});
},
}, },
mode: { mode: {
type: String, type: String,
value: '' value: '',
}, },
url: { url: {
type: String, type: String,
value: '' value: '',
}, },
openType: { openType: {
type: String, type: String,
value: 'navigate' value: 'navigate',
}, },
delay: { delay: {
type: Number, type: Number,
value: 1 value: 1,
}, },
speed: { speed: {
type: Number, type: Number,
value: 50 value: 50,
observer() {
wx.nextTick(() => {
this.init();
});
},
}, },
scrollable: { scrollable: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
leftIcon: { leftIcon: {
type: String, type: String,
value: '' value: '',
}, },
color: { color: {
type: String, type: String,
value: FONT_COLOR value: FONT_COLOR,
}, },
backgroundColor: { backgroundColor: {
type: String, type: String,
value: BG_COLOR value: BG_COLOR,
}, },
wrapable: Boolean wrapable: Boolean,
}, },
data: { data: {
show: true show: true,
},
watch: {
text() {
this.set({}, this.init);
}
}, },
created() { created() {
this.resetAnimation = wx.createAnimation({ this.resetAnimation = wx.createAnimation({
duration: 0, duration: 0,
timingFunction: 'linear' timingFunction: 'linear',
}); });
}, },
destroyed() { destroyed() {
...@@ -66,13 +71,15 @@ VantComponent({ ...@@ -66,13 +71,15 @@ VantComponent({
init() { init() {
Promise.all([ Promise.all([
this.getRect('.van-notice-bar__content'), this.getRect('.van-notice-bar__content'),
this.getRect('.van-notice-bar__wrap') this.getRect('.van-notice-bar__wrap'),
]).then((rects) => { ]).then((rects) => {
const [contentRect, wrapRect] = rects; const [contentRect, wrapRect] = rects;
if (contentRect == null || if (
contentRect == null ||
wrapRect == null || wrapRect == null ||
!contentRect.width || !contentRect.width ||
!wrapRect.width) { !wrapRect.width
) {
return; return;
} }
const { speed, scrollable, delay } = this.data; const { speed, scrollable, delay } = this.data;
...@@ -84,7 +91,7 @@ VantComponent({ ...@@ -84,7 +91,7 @@ VantComponent({
this.animation = wx.createAnimation({ this.animation = wx.createAnimation({
duration, duration,
timingFunction: 'linear', timingFunction: 'linear',
delay delay,
}); });
this.scroll(); this.scroll();
} }
...@@ -93,18 +100,18 @@ VantComponent({ ...@@ -93,18 +100,18 @@ VantComponent({
scroll() { scroll() {
this.timer && clearTimeout(this.timer); this.timer && clearTimeout(this.timer);
this.timer = null; this.timer = null;
this.set({ this.setData({
animationData: this.resetAnimation animationData: this.resetAnimation
.translateX(this.wrapWidth) .translateX(this.wrapWidth)
.step() .step()
.export() .export(),
}); });
setTimeout(() => { setTimeout(() => {
this.set({ this.setData({
animationData: this.animation animationData: this.animation
.translateX(-this.contentWidth) .translateX(-this.contentWidth)
.step() .step()
.export() .export(),
}); });
}, 20); }, 20);
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
...@@ -114,10 +121,10 @@ VantComponent({ ...@@ -114,10 +121,10 @@ VantComponent({
onClickIcon() { onClickIcon() {
this.timer && clearTimeout(this.timer); this.timer && clearTimeout(this.timer);
this.timer = null; this.timer = null;
this.set({ show: false }); this.setData({ show: false });
}, },
onClick(event) { onClick(event) {
this.$emit('click', event); this.$emit('click', event);
} },
} },
}); });
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
name="{{ leftIcon }}" name="{{ leftIcon }}"
class="van-notice-bar__left-icon" class="van-notice-bar__left-icon"
/> />
<slot wx:else name="left-icon" />
<view class="van-notice-bar__wrap"> <view class="van-notice-bar__wrap">
<view class="van-notice-bar__content {{ !scrollable && !wrapable ? 'van-ellipsis' : '' }}" animation="{{ animationData }}"> <view class="van-notice-bar__content {{ !scrollable && !wrapable ? 'van-ellipsis' : '' }}" animation="{{ animationData }}">
...@@ -23,13 +24,14 @@ ...@@ -23,13 +24,14 @@
wx:if="{{ mode === 'closeable' }}" wx:if="{{ mode === 'closeable' }}"
class="van-notice-bar__right-icon" class="van-notice-bar__right-icon"
name="cross" name="cross"
bind:tap="onClickIcon" catch:tap="onClickIcon"
/> />
<navigator <navigator
wx:if="{{ mode === 'link' }}" wx:elif="{{ mode === 'link' }}"
url="{{ url }}" url="{{ url }}"
open-type="{{ openType }}" open-type="{{ openType }}"
> >
<van-icon class="van-notice-bar__right-icon" name="arrow" /> <van-icon class="van-notice-bar__right-icon" name="arrow" />
</navigator> </navigator>
<slot wx:else name="right-icon" />
</view> </view>
@import '../common/index.wxss';.van-notice-bar{display:-webkit-flex;display:flex;height:40px;padding:0 15px;font-size:14px;line-height:24px;-webkit-align-items:center;align-items:center}.van-notice-bar--withicon{position:relative;padding-right:40px}.van-notice-bar--wrapable{height:auto;padding:8px 15px}.van-notice-bar--wrapable .van-notice-bar__wrap{height:auto}.van-notice-bar--wrapable .van-notice-bar__content{position:relative;white-space:normal}.van-notice-bar__left-icon{display:-webkit-flex;display:flex;margin-right:4px;vertical-align:middle;-webkit-align-items:center;align-items:center}.van-notice-bar__right-icon{position:absolute;top:10px;right:15px;font-size:16px}.van-notice-bar__wrap{position:relative;height:24px;overflow:hidden;-webkit-flex:1;flex:1}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%} @import '../common/index.wxss';.van-notice-bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:40px;height:var(--notice-bar-height,40px);padding:0 16px;padding:var(--notice-bar-padding,0 16px);font-size:14px;font-size:var(--notice-bar-font-size,14px);color:#ed6a0c;color:var(--notice-bar-text-color,#ed6a0c);line-height:24px;line-height:var(--notice-bar-line-height,24px);background-color:#fffbe8;background-color:var(--notice-bar-background-color,#fffbe8)}.van-notice-bar--withicon{position:relative;padding-right:40px}.van-notice-bar--wrapable{height:auto;padding:8px 16px;padding:var(--notice-bar-wrapable-padding,8px 16px)}.van-notice-bar--wrapable .van-notice-bar__wrap{height:auto}.van-notice-bar--wrapable .van-notice-bar__content{position:relative;white-space:normal}.van-notice-bar__left-icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;margin-right:4px;vertical-align:middle}.van-notice-bar__left-icon,.van-notice-bar__right-icon{font-size:16px;font-size:var(--notice-bar-icon-size,16px);min-width:22px;min-width:var(--notice-bar-icon-min-width,22px)}.van-notice-bar__right-icon{position:absolute;top:10px;right:15px}.van-notice-bar__wrap{position:relative;-webkit-flex:1;flex:1;overflow:hidden;height:24px;height:var(--notice-bar-line-height,24px)}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { RED } from '../common/color'; import { WHITE } from '../common/color';
import { safeArea } from '../mixins/safe-area';
VantComponent({ VantComponent({
mixins: [safeArea()],
props: { props: {
text: String, message: String,
color: { background: String,
type: {
type: String, type: String,
value: '#fff' value: 'danger',
}, },
backgroundColor: { color: {
type: String, type: String,
value: RED value: WHITE,
}, },
duration: { duration: {
type: Number, type: Number,
value: 3000 value: 3000,
}, },
zIndex: { zIndex: {
type: Number, type: Number,
value: 110 value: 110,
} },
safeAreaInsetTop: {
type: Boolean,
value: false,
},
top: null,
},
data: {
show: false,
},
created() {
const { statusBarHeight } = wx.getSystemInfoSync();
this.setData({ statusBarHeight });
}, },
methods: { methods: {
show() { show() {
const { duration } = this.data; const { duration, onOpened } = this.data;
clearTimeout(this.timer); clearTimeout(this.timer);
this.set({ this.setData({ show: true });
show: true wx.nextTick(onOpened);
});
if (duration > 0 && duration !== Infinity) { if (duration > 0 && duration !== Infinity) {
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
this.hide(); this.hide();
...@@ -36,10 +46,16 @@ VantComponent({ ...@@ -36,10 +46,16 @@ VantComponent({
} }
}, },
hide() { hide() {
const { onClose } = this.data;
clearTimeout(this.timer); clearTimeout(this.timer);
this.set({ this.setData({ show: false });
show: false wx.nextTick(onClose);
}); },
} onTap(event) {
const { onClick } = this.data;
if (onClick) {
onClick(event.detail);
} }
},
},
}); });
<wxs src="../wxs/utils.wxs" module="utils" />
<van-transition <van-transition
name="slide-down" name="slide-down"
show="{{ show }}" show="{{ show }}"
custom-class="van-notify" custom-class="van-notify__container"
custom-style="background-color:{{ backgroundColor }}; color: {{ color }}; z-index: {{ zIndex }};" custom-style="z-index: {{ zIndex }}; top: {{ utils.addUnit(top) }}"
bind:tap="onTap"
> >
<view wx:if="{{ safeAreaInsetTop }}" class="van-notify__safe-top" style="padding-top: {{ statusBarHeight }}px"></view> <view
{{ text }} class="van-notify van-notify--{{ type }}"
style="background:{{ background }};color:{{ color }};"
>
<view
wx:if="{{ safeAreaInsetTop }}"
style="height: {{ statusBarHeight }}px"
/>
<text>{{ message }}</text>
</view>
</van-transition> </van-transition>
@import '../common/index.wxss';.van-notify{position:fixed;top:0;width:100%;padding:6px 15px;font-size:14px;line-height:20px;text-align:center;word-break:break-all;box-sizing:border-box}.van-notify__safe-top{height:44px} @import '../common/index.wxss';.van-notify{text-align:center;word-wrap:break-word;padding:6px 15px;padding:var(--notify-padding,6px 15px);font-size:14px;font-size:var(--notify-font-size,14px);line-height:20px;line-height:var(--notify-line-height,20px)}.van-notify__container{position:fixed;top:0;box-sizing:border-box;width:100%}.van-notify--primary{background-color:#1989fa;background-color:var(--notify-primary-background-color,#1989fa)}.van-notify--success{background-color:#07c160;background-color:var(--notify-success-background-color,#07c160)}.van-notify--danger{background-color:#ee0a24;background-color:var(--notify-danger-background-color,#ee0a24)}.van-notify--warning{background-color:#ff976a;background-color:var(--notify-warning-background-color,#ff976a)}
\ No newline at end of file \ No newline at end of file
interface NotifyOptions { interface NotifyOptions {
text: string; type?: 'primary' | 'success' | 'danger' | 'warning';
color?: string; color?: string;
backgroundColor?: string; zIndex?: number;
top?: number;
message: string;
context?: any;
duration?: number; duration?: number;
selector?: string; selector?: string;
context?: any; background?: string;
safeAreaInsetTop?: boolean; safeAreaInsetTop?: boolean;
zIndex?: number; onClick?: () => void;
onOpened?: () => void;
onClose?: () => void;
}
declare function Notify(options: NotifyOptions | string): any;
declare namespace Notify {
var clear: (options?: NotifyOptions) => void;
} }
export default function Notify(options: NotifyOptions | string): void; export default Notify;
export {};
import { isObj } from '../common/utils'; import { WHITE } from '../common/color';
const defaultOptions = { const defaultOptions = {
selector: '#van-notify', selector: '#van-notify',
duration: 3000 type: 'danger',
message: '',
background: '',
duration: 3000,
zIndex: 110,
top: 0,
color: WHITE,
safeAreaInsetTop: false,
onClick: () => {},
onOpened: () => {},
onClose: () => {},
}; };
function parseOptions(text) { function parseOptions(message) {
return isObj(text) ? text : { text }; return typeof message === 'string' ? { message } : message;
} }
function getContext() { function getContext() {
const pages = getCurrentPages(); const pages = getCurrentPages();
return pages[pages.length - 1]; return pages[pages.length - 1];
} }
export default function Notify(options) { export default function Notify(options) {
options = Object.assign({}, defaultOptions, parseOptions(options)); options = Object.assign(
Object.assign({}, defaultOptions),
parseOptions(options)
);
const context = options.context || getContext(); const context = options.context || getContext();
const notify = context.selectComponent(options.selector); const notify = context.selectComponent(options.selector);
delete options.context; delete options.context;
delete options.selector; delete options.selector;
if (notify) { if (notify) {
notify.set(options); notify.setData(options);
notify.show(); notify.show();
return notify;
} }
else {
console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确'); console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');
}
} }
Notify.clear = function (options) {
options = Object.assign(
Object.assign({}, defaultOptions),
parseOptions(options)
);
const context = options.context || getContext();
const notify = context.selectComponent(options.selector);
if (notify) {
notify.hide();
}
};
...@@ -2,22 +2,21 @@ import { VantComponent } from '../common/component'; ...@@ -2,22 +2,21 @@ import { VantComponent } from '../common/component';
VantComponent({ VantComponent({
props: { props: {
show: Boolean, show: Boolean,
mask: Boolean,
customStyle: String, customStyle: String,
duration: { duration: {
type: [Number, Object], type: null,
value: 300 value: 300,
}, },
zIndex: { zIndex: {
type: Number, type: Number,
value: 1 value: 1,
} },
}, },
methods: { methods: {
onClick() { onClick() {
this.$emit('click'); this.$emit('click');
}, },
// for prevent touchmove // for prevent touchmove
noop() { } noop() {},
} },
}); });
<van-transition <van-transition
show="{{ show }}" show="{{ show }}"
custom-class="van-overlay" custom-class="van-overlay"
custom-style="z-index: {{ zIndex }}; {{ mask ? 'background-color: rgba(0, 0, 0, .7);' : '' }}; {{ customStyle }}" custom-style="z-index: {{ zIndex }}; {{ customStyle }}"
duration="{{ duration }}" duration="{{ duration }}"
bind:tap="onClick" bind:tap="onClick"
catch:touchmove="noop" catch:touchmove="noop"
/> >
<slot></slot>
</van-transition>
@import '../common/index.wxss';.van-overlay{position:fixed;top:0;right:0;bottom:0;left:0} @import '../common/index.wxss';.van-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.7);background-color:var(--overlay-background-color,rgba(0,0,0,.7))}
\ No newline at end of file \ No newline at end of file
...@@ -5,6 +5,6 @@ VantComponent({ ...@@ -5,6 +5,6 @@ VantComponent({
desc: String, desc: String,
title: String, title: String,
status: String, status: String,
useFooterSlot: Boolean useFooterSlot: Boolean,
} },
}); });
@import '../common/index.wxss';.van-panel{background:#fff}.van-panel__header-value{color:#f44}.van-panel__footer{padding:10px 15px} @import '../common/index.wxss';.van-panel{background:#fff;background:var(--panel-background-color,#fff)}.van-panel__header-value{color:#ee0a24;color:var(--panel-header-value-color,#ee0a24)}.van-panel__footer{padding:8px 16px;padding:var(--panel-footer-padding,8px 16px)}
\ No newline at end of file \ No newline at end of file
...@@ -10,12 +10,15 @@ VantComponent({ ...@@ -10,12 +10,15 @@ VantComponent({
visibleItemCount: Number, visibleItemCount: Number,
initialOptions: { initialOptions: {
type: Array, type: Array,
value: [] value: [],
}, },
defaultIndex: { defaultIndex: {
type: Number, type: Number,
value: 0 value: 0,
} observer(value) {
this.setIndex(value);
},
},
}, },
data: { data: {
startY: 0, startY: 0,
...@@ -23,61 +26,48 @@ VantComponent({ ...@@ -23,61 +26,48 @@ VantComponent({
duration: 0, duration: 0,
startOffset: 0, startOffset: 0,
options: [], options: [],
currentIndex: 0 currentIndex: 0,
}, },
created() { created() {
const { defaultIndex, initialOptions } = this.data; const { defaultIndex, initialOptions } = this.data;
this.set({ this.set({
currentIndex: defaultIndex, currentIndex: defaultIndex,
options: initialOptions options: initialOptions,
}).then(() => { }).then(() => {
this.setIndex(defaultIndex); this.setIndex(defaultIndex);
}); });
}, },
computed: { methods: {
count() { getCount() {
return this.data.options.length; return this.data.options.length;
}, },
baseOffset() {
const { data } = this;
return (data.itemHeight * (data.visibleItemCount - 1)) / 2;
},
wrapperStyle() {
const { data } = this;
return [
`transition: ${data.duration}ms`,
`transform: translate3d(0, ${data.offset + data.baseOffset}px, 0)`,
`line-height: ${data.itemHeight}px`
].join('; ');
}
},
watch: {
defaultIndex(value) {
this.setIndex(value);
}
},
methods: {
onTouchStart(event) { onTouchStart(event) {
this.set({ this.setData({
startY: event.touches[0].clientY, startY: event.touches[0].clientY,
startOffset: this.data.offset, startOffset: this.data.offset,
duration: 0 duration: 0,
}); });
}, },
onTouchMove(event) { onTouchMove(event) {
const { data } = this; const { data } = this;
const deltaY = event.touches[0].clientY - data.startY; const deltaY = event.touches[0].clientY - data.startY;
this.set({ this.setData({
offset: range(data.startOffset + deltaY, -(data.count * data.itemHeight), data.itemHeight) offset: range(
data.startOffset + deltaY,
-(this.getCount() * data.itemHeight),
data.itemHeight
),
}); });
}, },
onTouchEnd() { onTouchEnd() {
const { data } = this; const { data } = this;
if (data.offset !== data.startOffset) { if (data.offset !== data.startOffset) {
this.set({ this.setData({ duration: DEFAULT_DURATION });
duration: DEFAULT_DURATION const index = range(
}); Math.round(-data.offset / data.itemHeight),
const index = range(Math.round(-data.offset / data.itemHeight), 0, data.count - 1); 0,
this.getCount() - 1
);
this.setIndex(index, true); this.setIndex(index, true);
} }
}, },
...@@ -87,14 +77,13 @@ VantComponent({ ...@@ -87,14 +77,13 @@ VantComponent({
}, },
adjustIndex(index) { adjustIndex(index) {
const { data } = this; const { data } = this;
index = range(index, 0, data.count); const count = this.getCount();
for (let i = index; i < data.count; i++) { index = range(index, 0, count);
if (!this.isDisabled(data.options[i])) for (let i = index; i < count; i++) {
return i; if (!this.isDisabled(data.options[i])) return i;
} }
for (let i = index - 1; i >= 0; i--) { for (let i = index - 1; i >= 0; i--) {
if (!this.isDisabled(data.options[i])) if (!this.isDisabled(data.options[i])) return i;
return i;
} }
}, },
isDisabled(option) { isDisabled(option) {
...@@ -129,6 +118,6 @@ VantComponent({ ...@@ -129,6 +118,6 @@ VantComponent({
getValue() { getValue() {
const { data } = this; const { data } = this;
return data.options[data.currentIndex]; return data.options[data.currentIndex];
} },
} },
}); });
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
bind:touchend="onTouchEnd" bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd" bind:touchcancel="onTouchEnd"
> >
<view style="{{ wrapperStyle }}"> <view style="transition: transform {{ duration }}ms; line-height: {{ itemHeight }}px; transform: translate3d(0, {{ offset + (itemHeight * (visibleItemCount - 1)) / 2 }}px, 0)">
<view <view
wx:for="{{ options }}" wx:for="{{ options }}"
wx:for-item="option" wx:for-item="option"
......
@import '../common/index.wxss';.van-picker-column{overflow:hidden;font-size:16px;color:#999;text-align:center}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{font-weight:500;color:#333}.van-picker-column__item--disabled{opacity:.3} @import '../common/index.wxss';.van-picker-column{overflow:hidden;text-align:center;color:#000;color:var(--picker-option-text-color,#000);font-size:16px;font-size:var(--picker-option-font-size,16px)}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{font-weight:500;font-weight:var(--font-weight-bold,500);color:#323233;color:var(--picker-option-selected-text-color,#323233)}.van-picker-column__item--disabled{opacity:.3;opacity:var(--picker-option-disabled-opacity,.3)}
\ No newline at end of file \ No newline at end of file
...@@ -2,32 +2,42 @@ import { VantComponent } from '../common/component'; ...@@ -2,32 +2,42 @@ import { VantComponent } from '../common/component';
import { pickerProps } from './shared'; import { pickerProps } from './shared';
VantComponent({ VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'], classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign({}, pickerProps, { valueKey: { props: Object.assign(Object.assign({}, pickerProps), {
valueKey: {
type: String, type: String,
value: 'text' value: 'text',
}, defaultIndex: { },
toolbarPosition: {
type: String,
value: 'top',
},
defaultIndex: {
type: Number, type: Number,
value: 0 value: 0,
}, columns: { },
columns: {
type: Array, type: Array,
value: [], value: [],
observer(columns = []) { observer(columns = []) {
this.simple = columns.length && !columns[0].values; this.simple = columns.length && !columns[0].values;
this.children = this.selectAllComponents('.van-picker__column'); this.children = this.selectAllComponents('.van-picker__column');
if (Array.isArray(this.children) && this.children.length) { if (Array.isArray(this.children) && this.children.length) {
this.setColumns().catch(() => { }); this.setColumns().catch(() => {});
} }
} },
} }), },
}),
beforeCreate() { beforeCreate() {
this.children = []; this.children = [];
}, },
methods: { methods: {
noop() { }, noop() {},
setColumns() { setColumns() {
const { data } = this; const { data } = this;
const columns = this.simple ? [{ values: data.columns }] : data.columns; const columns = this.simple ? [{ values: data.columns }] : data.columns;
const stack = columns.map((column, index) => this.setColumnValues(index, column.values)); const stack = columns.map((column, index) =>
this.setColumnValues(index, column.values)
);
return Promise.all(stack); return Promise.all(stack);
}, },
emit(event) { emit(event) {
...@@ -35,13 +45,12 @@ VantComponent({ ...@@ -35,13 +45,12 @@ VantComponent({
if (this.simple) { if (this.simple) {
this.$emit(type, { this.$emit(type, {
value: this.getColumnValue(0), value: this.getColumnValue(0),
index: this.getColumnIndex(0) index: this.getColumnIndex(0),
}); });
} } else {
else {
this.$emit(type, { this.$emit(type, {
value: this.getValues(), value: this.getValues(),
index: this.getIndexes() index: this.getIndexes(),
}); });
} }
}, },
...@@ -50,14 +59,13 @@ VantComponent({ ...@@ -50,14 +59,13 @@ VantComponent({
this.$emit('change', { this.$emit('change', {
picker: this, picker: this,
value: this.getColumnValue(0), value: this.getColumnValue(0),
index: this.getColumnIndex(0) index: this.getColumnIndex(0),
}); });
} } else {
else {
this.$emit('change', { this.$emit('change', {
picker: this, picker: this,
value: this.getValues(), value: this.getValues(),
index: event.currentTarget.dataset.index index: event.currentTarget.dataset.index,
}); });
} }
}, },
...@@ -100,7 +108,8 @@ VantComponent({ ...@@ -100,7 +108,8 @@ VantComponent({
if (column == null) { if (column == null) {
return Promise.reject(new Error('setColumnValues: 对应列不存在')); return Promise.reject(new Error('setColumnValues: 对应列不存在'));
} }
const isSame = JSON.stringify(column.data.options) === JSON.stringify(options); const isSame =
JSON.stringify(column.data.options) === JSON.stringify(options);
if (isSame) { if (isSame) {
return Promise.resolve(); return Promise.resolve();
} }
...@@ -116,7 +125,9 @@ VantComponent({ ...@@ -116,7 +125,9 @@ VantComponent({
}, },
// set values of all columns // set values of all columns
setValues(values) { setValues(values) {
const stack = values.map((value, index) => this.setColumnValue(index, value)); const stack = values.map((value, index) =>
this.setColumnValue(index, value)
);
return Promise.all(stack); return Promise.all(stack);
}, },
// get indexes of all columns // get indexes of all columns
...@@ -125,8 +136,10 @@ VantComponent({ ...@@ -125,8 +136,10 @@ VantComponent({
}, },
// set indexes of all columns // set indexes of all columns
setIndexes(indexes) { setIndexes(indexes) {
const stack = indexes.map((optionIndex, columnIndex) => this.setColumnIndex(columnIndex, optionIndex)); const stack = indexes.map((optionIndex, columnIndex) =>
this.setColumnIndex(columnIndex, optionIndex)
);
return Promise.all(stack); return Promise.all(stack);
} },
} },
}); });
<import src="./toolbar.wxml" />
<view class="van-picker custom-class"> <view class="van-picker custom-class">
<view <template is="toolbar" wx:if="{{ toolbarPosition === 'top' }}" data="{{ showToolbar, cancelButtonText, title, confirmButtonText }}"></template>
wx:if="{{ showToolbar }}"
class="van-picker__toolbar van-hairline--top-bottom toolbar-class"
>
<view
class="van-picker__cancel"
hover-class="van-picker__cancel--hover"
hover-stay-time="70"
data-type="cancel"
bindtap="emit"
>
{{ cancelButtonText }}
</view>
<view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{ title }}</view>
<view
class="van-picker__confirm"
hover-class="van-picker__confirm--hover"
hover-stay-time="70"
data-type="confirm"
bindtap="emit"
>
{{ confirmButtonText }}
</view>
</view>
<view wx:if="{{ loading }}" class="van-picker__loading"> <view wx:if="{{ loading }}" class="van-picker__loading">
<loading color="#1989fa"/> <loading color="#1989fa"/>
</view> </view>
...@@ -34,7 +13,7 @@ ...@@ -34,7 +13,7 @@
<picker-column <picker-column
class="van-picker__column" class="van-picker__column"
wx:for="{{ isSimple(columns) ? [columns] : columns }}" wx:for="{{ isSimple(columns) ? [columns] : columns }}"
wx:key="{{ index }}" wx:key="index"
data-index="{{ index }}" data-index="{{ index }}"
custom-class="column-class" custom-class="column-class"
value-key="{{ valueKey }}" value-key="{{ valueKey }}"
...@@ -45,11 +24,13 @@ ...@@ -45,11 +24,13 @@
active-class="active-class" active-class="active-class"
bind:change="onChange" bind:change="onChange"
/> />
<view class="van-picker__mask" style="background-size: 100% {{ (itemHeight * visibleItemCount - itemHeight) / 2 }}px" />
<view <view
class="van-picker__frame van-hairline--top-bottom" class="van-picker__frame van-hairline--top-bottom"
style="height: {{ itemHeight }}px" style="height: {{ itemHeight }}px"
/> />
</view> </view>
<template is="toolbar" wx:if="{{ toolbarPosition === 'bottom' }}" data="{{ showToolbar, cancelButtonText, title, confirmButtonText }}"></template>
</view> </view>
<wxs module="isSimple"> <wxs module="isSimple">
......
@import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;background-color:#fff;-webkit-user-select:none;user-select:none}.van-picker__toolbar{display:-webkit-flex;display:flex;height:44px;line-height:44px;-webkit-justify-content:space-between;justify-content:space-between}.van-picker__cancel,.van-picker__confirm{padding:0 15px;font-size:14px;color:#1989fa}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5}.van-picker__title{max-width:50%;font-size:16px;font-weight:500;text-align:center}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;background-color:hsla(0,0%,100%,.9);-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;pointer-events:none;-webkit-transform:translateY(-50%);transform:translateY(-50%)} @import '../common/index.wxss';.van-picker{position:relative;overflow:hidden;-webkit-text-size-adjust:100%;-webkit-user-select:none;user-select:none;background-color:#fff;background-color:var(--picker-background-color,#fff)}.van-picker__toolbar{display:-webkit-flex;display:flex;-webkit-justify-content:space-between;justify-content:space-between;height:44px;height:var(--picker-toolbar-height,44px);line-height:44px;line-height:var(--picker-toolbar-height,44px)}.van-picker__cancel,.van-picker__confirm{padding:0 16px;padding:var(--picker-action-padding,0 16px);font-size:14px;font-size:var(--picker-action-font-size,14px);color:#1989fa;color:var(--picker-action-text-color,#1989fa)}.van-picker__cancel--hover,.van-picker__confirm--hover{background-color:#f2f3f5;background-color:var(--picker-action-active-color,#f2f3f5)}.van-picker__title{max-width:50%;text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--picker-option-font-size,16px)}.van-picker__columns{position:relative;display:-webkit-flex;display:flex}.van-picker__column{-webkit-flex:1 1;flex:1 1;width:0}.van-picker__loading{position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;background-color:hsla(0,0%,100%,.9);background-color:var(--picker-loading-mask-color,hsla(0,0%,100%,.9))}.van-picker__mask{position:absolute;top:0;left:0;z-index:2;width:100%;height:100%;background-image:linear-gradient(180deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4)),linear-gradient(0deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4));background-repeat:no-repeat;background-position:top,bottom;-webkit-backface-visibility:hidden;backface-visibility:hidden;pointer-events:none}.van-picker__frame,.van-picker__loading .van-loading{position:absolute;top:50%;left:0;z-index:1;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);pointer-events:none}
\ No newline at end of file \ No newline at end of file
...@@ -4,18 +4,18 @@ export const pickerProps = { ...@@ -4,18 +4,18 @@ export const pickerProps = {
showToolbar: Boolean, showToolbar: Boolean,
cancelButtonText: { cancelButtonText: {
type: String, type: String,
value: '取消' value: '取消',
}, },
confirmButtonText: { confirmButtonText: {
type: String, type: String,
value: '确认' value: '确认',
}, },
visibleItemCount: { visibleItemCount: {
type: Number, type: Number,
value: 5 value: 5,
}, },
itemHeight: { itemHeight: {
type: Number, type: Number,
value: 44 value: 44,
} },
}; };
<template name="toolbar">
<view
wx:if="{{ showToolbar }}"
class="van-picker__toolbar van-hairline--top-bottom toolbar-class"
>
<view
class="van-picker__cancel"
hover-class="van-picker__cancel--hover"
hover-stay-time="70"
data-type="cancel"
bindtap="emit"
>
{{ cancelButtonText }}
</view>
<view wx:if="{{ title }}" class="van-picker__title van-ellipsis">{{
title
}}</view>
<view
class="van-picker__confirm"
hover-class="van-picker__confirm--hover"
hover-stay-time="70"
data-type="confirm"
bindtap="emit"
>
{{ confirmButtonText }}
</view>
</view>
</template>
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition'; import { transition } from '../mixins/transition';
import { safeArea } from '../mixins/safe-area';
VantComponent({ VantComponent({
classes: [ classes: [
'enter-class', 'enter-class',
...@@ -8,38 +7,60 @@ VantComponent({ ...@@ -8,38 +7,60 @@ VantComponent({
'enter-to-class', 'enter-to-class',
'leave-class', 'leave-class',
'leave-active-class', 'leave-active-class',
'leave-to-class' 'leave-to-class',
'close-icon-class',
], ],
mixins: [transition(false), safeArea()], mixins: [transition(false)],
props: { props: {
round: Boolean,
closeable: Boolean,
customStyle: String,
overlayStyle: String,
transition: { transition: {
type: String, type: String,
observer: 'observeClass' observer: 'observeClass',
}, },
customStyle: String,
overlayStyle: String,
zIndex: { zIndex: {
type: Number, type: Number,
value: 100 value: 100,
}, },
overlay: { overlay: {
type: Boolean, type: Boolean,
value: true value: true,
},
closeIcon: {
type: String,
value: 'cross',
},
closeIconPosition: {
type: String,
value: 'top-right',
}, },
closeOnClickOverlay: { closeOnClickOverlay: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
position: { position: {
type: String, type: String,
value: 'center', value: 'center',
observer: 'observeClass' observer: 'observeClass',
} },
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
safeAreaInsetTop: {
type: Boolean,
value: false,
},
}, },
created() { created() {
this.observeClass(); this.observeClass();
}, },
methods: { methods: {
onClickCloseIcon() {
this.$emit('close');
},
onClickOverlay() { onClickOverlay() {
this.$emit('click-overlay'); this.$emit('click-overlay');
if (this.data.closeOnClickOverlay) { if (this.data.closeOnClickOverlay) {
...@@ -49,12 +70,12 @@ VantComponent({ ...@@ -49,12 +70,12 @@ VantComponent({
observeClass() { observeClass() {
const { transition, position } = this.data; const { transition, position } = this.data;
const updateData = { const updateData = {
name: transition || position name: transition || position,
}; };
if (transition === 'none') { if (transition === 'none') {
updateData.duration = 0; updateData.duration = 0;
} }
this.set(updateData); this.setData(updateData);
} },
} },
}); });
{ {
"component": true, "component": true,
"usingComponents": { "usingComponents": {
"van-icon": "../icon/index",
"van-overlay": "../overlay/index" "van-overlay": "../overlay/index"
} }
} }
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
<van-overlay <van-overlay
wx:if="{{ overlay }}" wx:if="{{ overlay }}"
mask
show="{{ show }}" show="{{ show }}"
z-index="{{ zIndex }}" z-index="{{ zIndex }}"
custom-style="{{ overlayStyle }}" custom-style="{{ overlayStyle }}"
...@@ -11,10 +10,15 @@ ...@@ -11,10 +10,15 @@
/> />
<view <view
wx:if="{{ inited }}" wx:if="{{ inited }}"
class="custom-class {{ classes }} {{ utils.bem('popup', [position, { safe: isIPhoneX && safeAreaInsetBottom }]) }}" class="custom-class {{ classes }} {{ utils.bem('popup', [position, { round, safe: safeAreaInsetBottom, safeTop: safeAreaInsetTop }]) }}"
style="z-index: {{ zIndex }}; -webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }} {{ customStyle }}" style="z-index: {{ zIndex }}; -webkit-transition-duration:{{ currentDuration }}ms; transition-duration:{{ currentDuration }}ms; {{ display ? '' : 'display: none;' }};{{ customStyle }}"
bind:transitionend="onTransitionEnd" bind:transitionend="onTransitionEnd"
> >
<view wx:if="{{ safeAreaInsetTop }}" class="van-popup__safe-top" style="padding-top: {{ statusBarHeight }}px;"></view>
<slot /> <slot />
<van-icon
wx:if="{{ closeable }}"
name="{{ closeIcon }}"
class="close-icon-class van-popup__close-icon van-popup__close-icon--{{ closeIconPosition }}"
bind:tap="onClickCloseIcon"
/>
</view> </view>
@import '../common/index.wxss';.van-popup{position:fixed;top:50%;left:50%;max-height:100%;overflow-y:auto;background-color:#fff;box-sizing:border-box;-webkit-animation:ease both;animation:ease both;-webkit-overflow-scrolling:touch;transition-timing-function:ease}.van-popup--center{-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-popup--top{top:0;right:auto;bottom:auto;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--right{top:50%;right:0;bottom:auto;left:auto;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom{top:auto;right:auto;bottom:0;left:50%;width:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-popup--left{top:50%;right:auto;bottom:auto;left:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--bottom.van-popup--safe{padding-bottom:34px}.van-popup--left .van-popup__safe-top,.van-popup--right .van-popup__safe-top,.van-popup--top .van-popup__safe-top{height:44px}.van-popup--bottom .van-popup__safe-top,.van-popup--center .van-popup__safe-top{padding-top:0!important}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-scale-enter,.van-scale-leave-to{opacity:0;-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7)}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-bottom-enter,.van-bottom-leave-to{-webkit-transform:translate3d(-50%,100%,0);transform:translate3d(-50%,100%,0)}.van-top-enter,.van-top-leave-to{-webkit-transform:translate3d(-50%,-100%,0);transform:translate3d(-50%,-100%,0)}.van-left-enter,.van-left-leave-to{-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)} @import '../common/index.wxss';.van-popup{position:fixed;box-sizing:border-box;max-height:100%;overflow-y:auto;transition-timing-function:ease;-webkit-animation:ease both;animation:ease both;-webkit-overflow-scrolling:touch;background-color:#fff;background-color:var(--popup-background-color,#fff)}.van-popup--center{top:50%;left:50%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-popup--center.van-popup--round{border-radius:20px;border-radius:var(--popup-round-border-radius,20px)}.van-popup--top{top:0;left:0;width:100%}.van-popup--top.van-popup--round{border-radius:0 0 20px 20px;border-radius:0 0 var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px)}.van-popup--right{top:50%;right:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--right.van-popup--round{border-radius:20px 0 0 20px;border-radius:var(--popup-round-border-radius,20px) 0 0 var(--popup-round-border-radius,20px)}.van-popup--bottom{bottom:0;left:0;width:100%}.van-popup--bottom.van-popup--round{border-radius:20px 20px 0 0;border-radius:var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px) 0 0}.van-popup--left{top:50%;left:0;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.van-popup--left.van-popup--round{border-radius:0 20px 20px 0;border-radius:0 var(--popup-round-border-radius,20px) var(--popup-round-border-radius,20px) 0}.van-popup--bottom.van-popup--safe{padding-bottom:env(safe-area-inset-bottom)}.van-popup--safeTop{padding-top:env(safe-area-inset-top)}.van-popup__close-icon{position:absolute;z-index:1;z-index:var(--popup-close-icon-z-index,1);color:#969799;color:var(--popup-close-icon-color,#969799);font-size:18px;font-size:var(--popup-close-icon-size,18px)}.van-popup__close-icon--top-left{top:16px;top:var(--popup-close-icon-margin,16px);left:16px;left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--top-right{top:16px;top:var(--popup-close-icon-margin,16px);right:16px;right:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-left{bottom:16px;bottom:var(--popup-close-icon-margin,16px);left:16px;left:var(--popup-close-icon-margin,16px)}.van-popup__close-icon--bottom-right{right:16px;right:var(--popup-close-icon-margin,16px);bottom:16px;bottom:var(--popup-close-icon-margin,16px)}.van-popup__close-icon:active{opacity:.6}.van-scale-enter-active,.van-scale-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-scale-enter,.van-scale-leave-to{-webkit-transform:translate3d(-50%,-50%,0) scale(.7);transform:translate3d(-50%,-50%,0) scale(.7);opacity:0}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-center-enter-active,.van-center-leave-active{transition-property:opacity}.van-center-enter,.van-center-leave-to{opacity:0}.van-bottom-enter-active,.van-bottom-leave-active,.van-left-enter-active,.van-left-leave-active,.van-right-enter-active,.van-right-leave-active,.van-top-enter-active,.van-top-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-bottom-enter,.van-bottom-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-top-enter,.van-top-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-left-enter,.van-left-leave-to{-webkit-transform:translate3d(-100%,-50%,0);transform:translate3d(-100%,-50%,0)}.van-right-enter,.van-right-leave-to{-webkit-transform:translate3d(100%,-50%,0);transform:translate3d(100%,-50%,0)}
\ No newline at end of file \ No newline at end of file
...@@ -6,17 +6,22 @@ VantComponent({ ...@@ -6,17 +6,22 @@ VantComponent({
percentage: Number, percentage: Number,
pivotText: String, pivotText: String,
pivotColor: String, pivotColor: String,
trackColor: String,
showPivot: { showPivot: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
color: { color: {
type: String, type: String,
value: BLUE value: BLUE,
}, },
textColor: { textColor: {
type: String, type: String,
value: '#fff' value: '#fff',
} },
} strokeWidth: {
type: null,
value: 4,
},
},
}); });
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="getters" /> <wxs src="./index.wxs" module="getters" />
<view class="van-progress custom-class"> <view
class="van-progress custom-class"
style="height: {{ utils.addUnit(strokeWidth) }}; {{ trackColor ? 'background: ' + trackColor : '' }}"
>
<view <view
class="van-progress__portion" class="van-progress__portion"
style="width: {{ percentage }}%; background: {{ inactive ? '#cacaca' : color }}" style="width: {{ percentage }}%; background: {{ inactive ? '#cacaca' : color }}"
......
@import '../common/index.wxss';.van-progress{position:relative;height:4px;background:#e5e5e5;border-radius:4px}.van-progress__portion{position:absolute;left:0;height:100%;border-radius:inherit}.van-progress__pivot{position:absolute;top:50%;right:0;min-width:2em;padding:0 5px;font-size:10px;line-height:1.6;text-align:center;word-break:keep-all;background-color:#e5e5e5;border-radius:1em;-webkit-transform:translateY(-50%);transform:translateY(-50%);box-sizing:border-box} @import '../common/index.wxss';.van-progress{position:relative;height:4px;height:var(--progress-height,4px);border-radius:4px;border-radius:var(--progress-height,4px);background:#ebedf0;background:var(--progress-background-color,#ebedf0)}.van-progress__portion{position:absolute;left:0;height:100%;border-radius:inherit;background:#1989fa;background:var(--progress-color,#1989fa)}.van-progress__pivot{position:absolute;top:50%;right:0;box-sizing:border-box;min-width:2em;text-align:center;word-break:keep-all;border-radius:1em;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#fff;color:var(--progress-pivot-text-color,#fff);padding:0 5px;padding:var(--progress-pivot-padding,0 5px);font-size:10px;font-size:var(--progress-pivot-font-size,10px);line-height:1.6;line-height:var(--progress-pivot-line-height,1.6);background-color:#1989fa;background-color:var(--progress-pivot-background-color,#1989fa)}
\ No newline at end of file \ No newline at end of file
...@@ -4,24 +4,20 @@ VantComponent({ ...@@ -4,24 +4,20 @@ VantComponent({
relation: { relation: {
name: 'radio', name: 'radio',
type: 'descendant', type: 'descendant',
current: 'radio-group',
linked(target) { linked(target) {
this.children = this.children || [];
this.children.push(target);
this.updateChild(target); this.updateChild(target);
}, },
unlinked(target) {
this.children = this.children.filter((child) => child !== target);
}
}, },
props: { props: {
value: { value: {
type: null, type: null,
observer: 'updateChildren' observer: 'updateChildren',
}, },
disabled: { disabled: {
type: Boolean, type: Boolean,
observer: 'updateChildren' observer: 'updateChildren',
} },
}, },
methods: { methods: {
updateChildren() { updateChildren() {
...@@ -29,10 +25,10 @@ VantComponent({ ...@@ -29,10 +25,10 @@ VantComponent({
}, },
updateChild(child) { updateChild(child) {
const { value, disabled } = this.data; const { value, disabled } = this.data;
child.set({ child.setData({
value, value,
disabled: disabled || child.data.disabled disabled: disabled || child.data.disabled,
}); });
} },
} },
}); });
...@@ -4,28 +4,28 @@ VantComponent({ ...@@ -4,28 +4,28 @@ VantComponent({
relation: { relation: {
name: 'radio-group', name: 'radio-group',
type: 'ancestor', type: 'ancestor',
linked(target) { current: 'radio',
this.parent = target;
},
unlinked() {
this.parent = null;
}
}, },
classes: ['icon-class', 'label-class'], classes: ['icon-class', 'label-class'],
props: { props: {
name: null,
value: null, value: null,
disabled: Boolean, disabled: Boolean,
useIconSlot: Boolean, useIconSlot: Boolean,
checkedColor: String, checkedColor: String,
labelPosition: { labelPosition: {
type: String, type: String,
value: 'right' value: 'right',
}, },
labelDisabled: Boolean, labelDisabled: Boolean,
shape: { shape: {
type: String, type: String,
value: 'round' value: 'round',
} },
iconSize: {
type: null,
value: 20,
},
}, },
methods: { methods: {
emitChange(value) { emitChange(value) {
...@@ -33,15 +33,16 @@ VantComponent({ ...@@ -33,15 +33,16 @@ VantComponent({
instance.$emit('input', value); instance.$emit('input', value);
instance.$emit('change', value); instance.$emit('change', value);
}, },
onChange(event) { onChange() {
console.log(event); if (!this.data.disabled) {
this.emitChange(this.data.name); this.emitChange(this.data.name);
}
}, },
onClickLabel() { onClickLabel() {
const { disabled, labelDisabled, name } = this.data; const { disabled, labelDisabled, name } = this.data;
if (!disabled && !labelDisabled) { if (!disabled && !labelDisabled) {
this.emitChange(name); this.emitChange(name);
} }
} },
} },
}); });
...@@ -8,15 +8,15 @@ ...@@ -8,15 +8,15 @@
> >
<slot /> <slot />
</view> </view>
<view class="van-radio__icon-wrap" bindtap="onChange"> <view class="van-radio__icon-wrap" style="font-size: {{ utils.addUnit(iconSize) }};" bindtap="onChange">
<slot wx:if="{{ useIconSlot }}" name="icon" /> <slot wx:if="{{ useIconSlot }}" name="icon" />
<van-icon <van-icon
wx:else wx:else
name="success" name="success"
class="{{ utils.bem('radio__icon', [shape, { disabled, checked: value === name }]) }}" class="{{ utils.bem('radio__icon', [shape, { disabled, checked: value === name }]) }}"
style="{{ checkedColor && !disabled && value === name ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}" style="font-size: {{ utils.addUnit(iconSize) }};{{ checkedColor && !disabled && value === name ? 'border-color:' + checkedColor + '; background-color:' + checkedColor + ';' : '' }}"
custom-class="icon-class" custom-class="icon-class"
custom-style="line-height: 20px;" custom-style="line-height: {{ utils.addUnit(iconSize) }};font-size: .8em;display: block;"
/> />
</view> </view>
<view <view
......
@import '../common/index.wxss';.van-radio{display:-webkit-flex;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-radio__icon-wrap,.van-radio__label{line-height:20px}.van-radio__icon-wrap{-webkit-flex:none;flex:none}.van-radio__icon{display:block;width:20px;height:20px;font-size:14px;color:transparent;text-align:center;border:1px solid #e5e5e5;box-sizing:border-box;transition:.2s}.van-radio__icon--round{border-radius:100%}.van-radio__icon--checked{color:#fff;background-color:#1989fa;border-color:#1989fa}.van-radio__icon--disabled{background-color:#eee;border-color:#c9c9c9}.van-radio__icon--disabled.van-radio__icon--checked{color:#c9c9c9}.van-radio__label{margin-left:10px;color:#333;word-break:break-all}.van-radio__label--left{float:left;margin:0 10px 0 0}.van-radio__label--disabled{color:#c9c9c9}.van-radio__label:empty{margin:0} @import '../common/index.wxss';.van-radio{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-radio__icon-wrap{-webkit-flex:none;flex:none}.van-radio__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;border:1px solid #c8c9cc;border:1px solid var(--radio-border-color,#c8c9cc);font-size:20px;font-size:var(--radio-size,20px);transition-duration:.2s;transition-duration:var(--radio-transition-duration,.2s)}.van-radio__icon--round{border-radius:100%}.van-radio__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--radio-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--radio-checked-icon-color,#1989fa)}.van-radio__icon--disabled{background-color:#ebedf0;background-color:var(--radio-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__icon--disabled.van-radio__icon--checked{color:#c8c9cc;color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__label{word-wrap:break-word;margin-left:10px;margin-left:var(--radio-label-margin,10px);color:#323233;color:var(--radio-label-color,#323233);line-height:20px;line-height:var(--radio-size,20px)}.van-radio__label--left{float:left;margin:0 10px 0 0;margin:0 var(--radio-label-margin,10px) 0 0}.van-radio__label--disabled{color:#c8c9cc;color:var(--radio-disabled-label-color,#c8c9cc)}.van-radio__label:empty{margin:0}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { canIUseModel } from '../common/version';
VantComponent({ VantComponent({
field: true, field: true,
classes: ['icon-class'], classes: ['icon-class'],
props: { props: {
value: Number, value: {
type: Number,
observer(value) {
if (value !== this.data.innerValue) {
this.setData({ innerValue: value });
}
},
},
readonly: Boolean, readonly: Boolean,
disabled: Boolean, disabled: Boolean,
allowHalf: Boolean, allowHalf: Boolean,
size: { size: null,
type: Number,
value: 20
},
icon: { icon: {
type: String, type: String,
value: 'star' value: 'star',
}, },
voidIcon: { voidIcon: {
type: String, type: String,
value: 'star-o' value: 'star-o',
}, },
color: { color: {
type: String, type: String,
value: '#ffd21e' value: '#ffd21e',
}, },
voidColor: { voidColor: {
type: String, type: String,
value: '#c7c7c7' value: '#c7c7c7',
}, },
disabledColor: { disabledColor: {
type: String, type: String,
value: '#bdbdbd' value: '#bdbdbd',
}, },
count: { count: {
type: Number, type: Number,
value: 5 value: 5,
} observer(value) {
this.setData({ innerCountArray: Array.from({ length: value }) });
}, },
data: {
innerValue: 0
}, },
watch: { gutter: null,
value(value) { touchable: {
if (value !== this.data.innerValue) { type: Boolean,
this.set({ innerValue: value }); value: true,
} },
} },
data: {
innerValue: 0,
innerCountArray: Array.from({ length: 5 }),
}, },
methods: { methods: {
onSelect(event) { onSelect(event) {
const { data } = this; const { data } = this;
const { score } = event.currentTarget.dataset; const { score } = event.currentTarget.dataset;
if (!data.disabled && !data.readonly) { if (!data.disabled && !data.readonly) {
this.set({ innerValue: score + 1 }); this.setData({ innerValue: score + 1 });
if (canIUseModel()) {
this.setData({ value: score + 1 });
}
wx.nextTick(() => {
this.$emit('input', score + 1); this.$emit('input', score + 1);
this.$emit('change', score + 1); this.$emit('change', score + 1);
});
} }
}, },
onTouchMove(event) { onTouchMove(event) {
const { clientX, clientY } = event.touches[0]; const { touchable } = this.data;
if (!touchable) return;
const { clientX } = event.touches[0];
this.getRect('.van-rate__icon', true).then((list) => { this.getRect('.van-rate__icon', true).then((list) => {
const target = list const target = list
.sort(item => item.right - item.left) .sort((item) => item.right - item.left)
.find(item => clientX >= item.left && .find((item) => clientX >= item.left && clientX <= item.right);
clientX <= item.right &&
clientY >= item.top &&
clientY <= item.bottom);
if (target != null) { if (target != null) {
this.onSelect(Object.assign({}, event, { currentTarget: target })); this.onSelect(
Object.assign(Object.assign({}, event), { currentTarget: target })
);
} }
}); });
} },
} },
}); });
...@@ -6,13 +6,14 @@ ...@@ -6,13 +6,14 @@
> >
<view <view
class="van-rate__item" class="van-rate__item"
wx:for="{{ count }}" wx:for="{{ innerCountArray }}"
wx:key="index" wx:key="index"
style="font-size: {{ size}}px;" style="padding-right: {{ index !== count - 1 ? utils.addUnit(gutter) : '' }}"
> >
<van-icon <van-icon
name="{{ index + 1 <= innerValue ? icon : voidIcon }}" name="{{ index + 1 <= innerValue ? icon : voidIcon }}"
class="van-rate__icon" class="van-rate__icon"
style="font-size: {{ utils.addUnit(size) }}"
custom-class="icon-class" custom-class="icon-class"
data-score="{{ index }}" data-score="{{ index }}"
color="{{ disabled ? disabledColor : index + 1 <= innerValue ? color : voidColor }}" color="{{ disabled ? disabledColor : index + 1 <= innerValue ? color : voidColor }}"
...@@ -23,6 +24,7 @@ ...@@ -23,6 +24,7 @@
wx:if="{{ allowHalf }}" wx:if="{{ allowHalf }}"
name="{{ index + 0.5 <= innerValue ? icon : voidIcon }}" name="{{ index + 0.5 <= innerValue ? icon : voidIcon }}"
class="{{ utils.bem('rate__icon', ['half']) }}" class="{{ utils.bem('rate__icon', ['half']) }}"
style="font-size: {{ utils.addUnit(size) }}"
custom-class="icon-class" custom-class="icon-class"
data-score="{{ index - 0.5 }}" data-score="{{ index - 0.5 }}"
color="{{ disabled ? disabledColor : index + 0.5 <= innerValue ? color : voidColor }}" color="{{ disabled ? disabledColor : index + 0.5 <= innerValue ? color : voidColor }}"
......
@import '../common/index.wxss';.van-rate{-webkit-user-select:none;user-select:none}.van-rate__item{position:relative;display:inline-block;padding:0 2px}.van-rate__icon{display:block;height:1em}.van-rate__icon--half{position:absolute;top:0;left:2px;width:.5em;overflow:hidden} @import '../common/index.wxss';.van-rate{display:-webkit-inline-flex;display:inline-flex;-webkit-user-select:none;user-select:none}.van-rate__item{position:relative;padding:0 2px;padding:0 var(--rate-horizontal-padding,2px)}.van-rate__icon{display:block;height:1em;font-size:20px;font-size:var(--rate-icon-size,20px)}.van-rate__icon--half{position:absolute;top:0;width:.5em;overflow:hidden;left:2px;left:var(--rate-horizontal-padding,2px)}
\ No newline at end of file \ No newline at end of file
...@@ -3,17 +3,21 @@ VantComponent({ ...@@ -3,17 +3,21 @@ VantComponent({
relation: { relation: {
name: 'col', name: 'col',
type: 'descendant', type: 'descendant',
current: 'row',
linked(target) { linked(target) {
if (this.data.gutter) { if (this.data.gutter) {
target.setGutter(this.data.gutter); target.setGutter(this.data.gutter);
} }
} },
}, },
props: { props: {
gutter: Number gutter: {
type: Number,
observer: 'setGutter',
}, },
watch: { },
gutter: 'setGutter' data: {
viewStyle: '',
}, },
mounted() { mounted() {
if (this.data.gutter) { if (this.data.gutter) {
...@@ -24,13 +28,13 @@ VantComponent({ ...@@ -24,13 +28,13 @@ VantComponent({
setGutter() { setGutter() {
const { gutter } = this.data; const { gutter } = this.data;
const margin = `-${Number(gutter) / 2}px`; const margin = `-${Number(gutter) / 2}px`;
const style = gutter const viewStyle = gutter
? `margin-right: ${margin}; margin-left: ${margin};` ? `margin-right: ${margin}; margin-left: ${margin};`
: ''; : '';
this.set({ style }); this.setData({ viewStyle });
this.getRelationNodes('../col/index').forEach(col => { this.getRelationNodes('../col/index').forEach((col) => {
col.setGutter(this.data.gutter); col.setGutter(this.data.gutter);
}); });
} },
} },
}); });
<view class="custom-class van-row" style="{{ style }}"> <view class="custom-class van-row" style="{{ viewStyle }}">
<slot /> <slot />
</view> </view>
@import '../common/index.wxss';.van-row:after{content:"";display:table;clear:both} @import '../common/index.wxss';.van-row:after{display:table;clear:both;content:""}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { canIUseModel } from '../common/version';
VantComponent({ VantComponent({
field: true, field: true,
classes: ['field-class', 'input-class', 'cancel-class'], classes: ['field-class', 'input-class', 'cancel-class'],
...@@ -11,52 +12,67 @@ VantComponent({ ...@@ -11,52 +12,67 @@ VantComponent({
inputAlign: String, inputAlign: String,
showAction: Boolean, showAction: Boolean,
useActionSlot: Boolean, useActionSlot: Boolean,
useLeftIconSlot: Boolean,
useRightIconSlot: Boolean,
leftIcon: {
type: String,
value: 'search',
},
rightIcon: String,
placeholder: String, placeholder: String,
placeholderStyle: String, placeholderStyle: String,
actionText: {
type: String,
value: '取消',
},
background: { background: {
type: String, type: String,
value: '#ffffff' value: '#ffffff',
}, },
maxlength: { maxlength: {
type: Number, type: Number,
value: -1 value: -1,
}, },
shape: { shape: {
type: String, type: String,
value: 'square' value: 'square',
}, },
clearable: { clearable: {
type: Boolean, type: Boolean,
value: true value: true,
} },
}, },
methods: { methods: {
onChange(event) { onChange(event) {
this.set({ value: event.detail }); if (canIUseModel()) {
this.setData({ value: event.detail });
}
this.$emit('change', event.detail); this.$emit('change', event.detail);
}, },
onCancel() { onCancel() {
/** /**
* 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效 * 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效
* // https://github.com/youzan/vant-weapp/issues/1768 * https://github.com/youzan/@vant/weapp/issues/1768
*/ */
setTimeout(() => { setTimeout(() => {
this.set({ value: '' }); if (canIUseModel()) {
this.setData({ value: '' });
}
this.$emit('cancel'); this.$emit('cancel');
this.$emit('change', ''); this.$emit('change', '');
}, 200); }, 200);
}, },
onSearch() { onSearch(event) {
this.$emit('search', this.data.value); this.$emit('search', event.detail);
}, },
onFocus() { onFocus(event) {
this.$emit('focus'); this.$emit('focus', event.detail);
}, },
onBlur() { onBlur(event) {
this.$emit('blur'); this.$emit('blur', event.detail);
},
onClear(event) {
this.$emit('clear', event.detail);
}, },
onClear() {
this.$emit('clear');
}, },
}
}); });
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
<van-field <van-field
type="search" type="search"
left-icon="search" left-icon="{{ !useLeftIconSlot ? leftIcon : '' }}"
right-icon="{{ !useRightIconSlot ? rightIcon : '' }}"
focus="{{ focus }}" focus="{{ focus }}"
error="{{ error }}" error="{{ error }}"
border="{{ false }}" border="{{ false }}"
...@@ -31,7 +32,10 @@ ...@@ -31,7 +32,10 @@
bind:change="onChange" bind:change="onChange"
bind:confirm="onSearch" bind:confirm="onSearch"
bind:clear="onClear" bind:clear="onClear"
/> >
<slot wx:if="{{ useLeftIconSlot }}" name="left-icon" slot="left-icon" />
<slot wx:if="{{ useRightIconSlot }}" name="right-icon" slot="right-icon" />
</van-field>
</view> </view>
<view <view
...@@ -41,6 +45,6 @@ ...@@ -41,6 +45,6 @@
hover-stay-time="70" hover-stay-time="70"
> >
<slot wx:if="{{ useActionSlot }}" name="action" /> <slot wx:if="{{ useActionSlot }}" name="action" />
<view wx:else bind:tap="onCancel" class="cancel-class">取消</view> <view wx:else bind:tap="onCancel" class="cancel-class">{{ actionText }}</view>
</view> </view>
</view> </view>
@import '../common/index.wxss';.van-search{padding:10px 16px;-webkit-align-items:center;align-items:center;box-sizing:border-box}.van-search,.van-search__content{display:-webkit-flex;display:flex}.van-search__content{padding-left:10px;background-color:#f7f8fa;border-radius:2px;-webkit-flex:1;flex:1}.van-search__content--round{border-radius:17px}.van-search__label{padding:0 5px;font-size:14px;line-height:34px;color:#333}.van-search__field{-webkit-flex:1;flex:1}.van-search__field__left-icon{color:#999}.van-search--withaction{padding-right:0}.van-search__action{padding:0 10px;font-size:14px;line-height:34px;color:#333}.van-search__action--hover{background-color:#f2f3f5} @import '../common/index.wxss';.van-search{-webkit-align-items:center;align-items:center;box-sizing:border-box;padding:10px 12px;padding:var(--search-padding,10px 12px)}.van-search,.van-search__content{display:-webkit-flex;display:flex}.van-search__content{-webkit-flex:1;flex:1;padding-left:8px;padding-left:var(--padding-xs,8px);border-radius:2px;border-radius:var(--border-radius-sm,2px);background-color:#f7f8fa;background-color:var(--search-background-color,#f7f8fa)}.van-search__content--round{border-radius:17px;border-radius:calc(var(--search-input-height, 34px)/2)}.van-search__label{padding:0 5px;padding:var(--search-label-padding,0 5px);font-size:14px;font-size:var(--search-label-font-size,14px);line-height:34px;line-height:var(--search-input-height,34px);color:#323233;color:var(--search-label-color,#323233)}.van-search__field{-webkit-flex:1;flex:1}.van-search__field__left-icon{color:#969799;color:var(--search-left-icon-color,#969799)}.van-search--withaction{padding-right:0}.van-search__action{padding:0 8px;padding:var(--search-action-padding,0 8px);font-size:14px;font-size:var(--search-action-font-size,14px);line-height:34px;line-height:var(--search-input-height,34px);color:#323233;color:var(--search-action-text-color,#323233)}.van-search__action--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
classes: ['active-class', 'disabled-class'],
relation: {
type: 'ancestor',
name: 'sidebar',
current: 'sidebar-item',
},
props: {
dot: Boolean,
info: null,
title: String,
disabled: Boolean,
},
methods: {
onClick() {
const { parent } = this;
if (!parent || this.data.disabled) {
return;
}
const index = parent.children.indexOf(this);
parent.setActive(index).then(() => {
this.$emit('click', index);
parent.$emit('change', index);
});
},
setActive(selected) {
return this.setData({ selected });
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<view <view
class="{{ utils.bem('badge', { active }) }} van-hairline custom-class" class="{{ utils.bem('sidebar-item', { selected, disabled }) }} {{ selected ? 'active-class' : '' }} {{ disabled ? 'disabled-class' : '' }} custom-class"
hover-class="van-badge--hover" hover-class="van-sidebar-item--hover"
hover-stay-time="70" hover-stay-time="70"
bind:tap="onClick" bind:tap="onClick"
> >
<view class="van-badge__text"> <view class="van-sidebar-item__text">
<van-info <van-info
wx:if="{{ info !== null }}" wx:if="{{ info !== null || dot }}"
dot="{{ dot }}"
info="{{ info }}" info="{{ info }}"
custom-style="right: 4px" custom-style="right: 4px"
/> />
{{ title }} <view wx:if="{{ title }}">{{ title }}</view>
<slot wx:else name="title" />
</view> </view>
</view> </view>
@import '../common/index.wxss';.van-sidebar-item{display:block;box-sizing:border-box;overflow:hidden;word-wrap:break-word;border-left:3px solid transparent;-webkit-user-select:none;user-select:none;padding:20px 12px 20px 8px;padding:var(--sidebar-padding,20px 12px 20px 8px);font-size:14px;font-size:var(--sidebar-font-size,14px);line-height:20px;line-height:var(--sidebar-line-height,20px);color:#323233;color:var(--sidebar-text-color,#323233);background-color:#f7f8fa;background-color:var(--sidebar-background-color,#f7f8fa)}.van-sidebar-item__text{position:relative;display:inline-block}.van-sidebar-item--hover:not(.van-sidebar-item--disabled){background-color:#f2f3f5;background-color:var(--sidebar-active-color,#f2f3f5)}.van-sidebar-item:after{border-bottom-width:1px}.van-sidebar-item--selected{color:#323233;color:var(--sidebar-selected-text-color,#323233);font-weight:500;font-weight:var(--sidebar-selected-font-weight,500);border-color:#ee0a24;border-color:var(--sidebar-selected-border-color,#ee0a24)}.van-sidebar-item--selected:after{border-right-width:1px}.van-sidebar-item--selected,.van-sidebar-item--selected.van-sidebar-item--hover{background-color:#fff;background-color:var(--sidebar-selected-background-color,#fff)}.van-sidebar-item--disabled{color:#c8c9cc;color:var(--sidebar-disabled-text-color,#c8c9cc)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'sidebar-item',
type: 'descendant',
current: 'sidebar',
linked() {
this.setActive(this.data.activeKey);
},
unlinked() {
this.setActive(this.data.activeKey);
},
},
props: {
activeKey: {
type: Number,
value: 0,
observer: 'setActive',
},
},
beforeCreate() {
this.currentActive = -1;
},
methods: {
setActive(activeKey) {
const { children, currentActive } = this;
if (!children.length) {
return Promise.resolve();
}
this.currentActive = activeKey;
const stack = [];
if (currentActive !== activeKey && children[currentActive]) {
stack.push(children[currentActive].setActive(false));
}
if (children[activeKey]) {
stack.push(children[activeKey].setActive(true));
}
return Promise.all(stack);
},
},
});
<view class="van-sidebar custom-class">
<slot />
</view>
@import '../common/index.wxss';.van-sidebar{width:85px;width:var(--sidebar-width,85px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
classes: ['avatar-class', 'title-class', 'row-class'],
props: {
row: {
type: Number,
value: 0,
observer(value) {
this.setData({ rowArray: Array.from({ length: value }) });
},
},
title: Boolean,
avatar: Boolean,
loading: {
type: Boolean,
value: true,
},
animate: {
type: Boolean,
value: true,
},
avatarSize: {
type: String,
value: '32px',
},
avatarShape: {
type: String,
value: 'round',
},
titleWidth: {
type: String,
value: '40%',
},
rowWidth: {
type: null,
value: '100%',
observer(val) {
this.setData({ isArray: val instanceof Array });
},
},
},
data: {
isArray: false,
rowArray: [],
},
});
{
"component": true,
"usingComponents": {}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
wx:if="{{ loading }}"
class="custom-class {{ utils.bem('skeleton', [{animate}]) }}"
>
<view
wx:if="{{ avatar }}"
class="avatar-class {{ utils.bem('skeleton__avatar', [avatarShape])}}"
style="{{ 'width:' + avatarSize + ';height:' + avatarSize }}"
/>
<view class="{{ utils.bem('skeleton__content')}}">
<view
wx:if="{{ title }}"
class="title-class {{ utils.bem('skeleton__title') }}"
style="{{ 'width:' + titleWidth }}"
/>
<view
wx:for="{{ rowArray }}"
wx:key="index"
wx:for-index="index"
class="row-class {{ utils.bem('skeleton__row') }}"
style="{{ 'width:' + (isArray ? rowWidth[index] : rowWidth) }}"
/>
</view>
</view>
<view wx:else class="{{ utils.bem('skeleton__content')}}">
<slot />
</view>
@import '../common/index.wxss';.van-skeleton{display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:0 16px;padding:var(--skeleton-padding,0 16px)}.van-skeleton__avatar{-webkit-flex-shrink:0;flex-shrink:0;margin-right:16px;margin-right:var(--padding-md,16px);background-color:#f2f3f5;background-color:var(--skeleton-avatar-background-color,#f2f3f5)}.van-skeleton__avatar--round{border-radius:100%}.van-skeleton__content{-webkit-flex:1;flex:1}.van-skeleton__avatar+.van-skeleton__content{padding-top:8px;padding-top:var(--padding-xs,8px)}.van-skeleton__row,.van-skeleton__title{height:16px;height:var(--skeleton-row-height,16px);background-color:#f2f3f5;background-color:var(--skeleton-row-background-color,#f2f3f5)}.van-skeleton__title{margin:0}.van-skeleton__row:not(:first-child){margin-top:12px;margin-top:var(--skeleton-row-margin-top,12px)}.van-skeleton__title+.van-skeleton__row{margin-top:20px}.van-skeleton--animate{-webkit-animation:van-skeleton-blink 1.2s ease-in-out infinite;animation:van-skeleton-blink 1.2s ease-in-out infinite}@-webkit-keyframes van-skeleton-blink{50%{opacity:.6}}@keyframes van-skeleton-blink{50%{opacity:.6}}
\ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch'; import { touch } from '../mixins/touch';
import { canIUseModel } from '../common/version';
VantComponent({ VantComponent({
mixins: [touch], mixins: [touch],
props: { props: {
...@@ -9,68 +10,75 @@ VantComponent({ ...@@ -9,68 +10,75 @@ VantComponent({
inactiveColor: String, inactiveColor: String,
max: { max: {
type: Number, type: Number,
value: 100 value: 100,
}, },
min: { min: {
type: Number, type: Number,
value: 0 value: 0,
}, },
step: { step: {
type: Number, type: Number,
value: 1 value: 1,
}, },
value: { value: {
type: Number, type: Number,
value: 0 value: 0,
observer: 'updateValue',
}, },
barHeight: { barHeight: {
type: String, type: null,
value: '2px' value: '2px',
}
}, },
watch: {
value(value) {
this.updateValue(value, false);
}
}, },
created() { created() {
this.updateValue(this.data.value); this.updateValue(this.data.value);
}, },
methods: { methods: {
onTouchStart(event) { onTouchStart(event) {
if (this.data.disabled) if (this.data.disabled) return;
return;
this.touchStart(event); this.touchStart(event);
this.startValue = this.format(this.data.value); this.startValue = this.format(this.data.value);
this.dragStatus = 'start';
}, },
onTouchMove(event) { onTouchMove(event) {
if (this.data.disabled) if (this.data.disabled) return;
return; if (this.dragStatus === 'start') {
this.$emit('drag-start');
}
this.touchMove(event); this.touchMove(event);
this.dragStatus = 'draging';
this.getRect('.van-slider').then((rect) => { this.getRect('.van-slider').then((rect) => {
const diff = this.deltaX / rect.width * 100; const diff = (this.deltaX / rect.width) * 100;
this.newValue = this.startValue + diff; this.newValue = this.startValue + diff;
this.updateValue(this.newValue, false, true); this.updateValue(this.newValue, false, true);
}); });
}, },
onTouchEnd() { onTouchEnd() {
if (this.data.disabled) if (this.data.disabled) return;
return; if (this.dragStatus === 'draging') {
this.updateValue(this.newValue, true); this.updateValue(this.newValue, true);
this.$emit('drag-end');
}
}, },
onClick(event) { onClick(event) {
if (this.data.disabled) if (this.data.disabled) return;
return; const { min } = this.data;
this.getRect('.van-slider').then((rect) => { this.getRect('.van-slider').then((rect) => {
const value = (event.detail.x - rect.left) / rect.width * 100; const value =
((event.detail.x - rect.left) / rect.width) * this.getRange() + min;
this.updateValue(value, true); this.updateValue(value, true);
}); });
}, },
updateValue(value, end, drag) { updateValue(value, end, drag) {
value = this.format(value); value = this.format(value);
this.set({ const { min } = this.data;
const width = `${((value - min) * 100) / this.getRange()}%`;
this.setData({
value, value,
barStyle: `width: ${value}%; height: ${this.data.barHeight};` barStyle: `
width: ${width};
${drag ? 'transition: none;' : ''}
`,
}); });
if (drag) { if (drag) {
this.$emit('drag', { value }); this.$emit('drag', { value });
...@@ -78,10 +86,17 @@ VantComponent({ ...@@ -78,10 +86,17 @@ VantComponent({
if (end) { if (end) {
this.$emit('change', value); this.$emit('change', value);
} }
if ((drag || end) && canIUseModel()) {
this.setData({ value });
}
},
getRange() {
const { max, min } = this.data;
return max - min;
}, },
format(value) { format(value) {
const { max, min, step } = this.data; const { max, min, step } = this.data;
return Math.round(Math.max(min, Math.min(value, max)) / step) * step; return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
} },
} },
}); });
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view <view
class="custom-class {{ utils.bem('slider', { disabled }) }}" class="custom-class {{ utils.bem('slider', { disabled }) }}"
...@@ -7,7 +8,7 @@ ...@@ -7,7 +8,7 @@
> >
<view <view
class="van-slider__bar" class="van-slider__bar"
style="{{ barStyle }}; {{ activeColor ? 'background:' + activeColor : '' }}" style="{{ barStyle }};{{ computed.barStyle(barHeight, activeColor) }}"
> >
<view <view
class="van-slider__button-wrapper" class="van-slider__button-wrapper"
......
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
function barStyle(barHeight, activeColor) {
var styles = [['height', utils.addUnit(barHeight)]];
if (activeColor) {
styles.push(['background', activeColor]);
}
return styles
.map(function (item) {
return item.join(':');
})
.join(';');
}
module.exports = {
barStyle: barStyle,
};
@import '../common/index.wxss';.van-slider{position:relative;border-radius:999px;background-color:#e5e5e5}.van-slider__bar{position:relative;border-radius:inherit;background-color:#1989fa}.van-slider__button{width:20px;height:20px;border-radius:50%;background-color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.5)}.van-slider__button-wrapper{position:absolute;top:50%;right:0;-webkit-transform:translate3d(50%,-50%,0);transform:translate3d(50%,-50%,0)}.van-slider__button-wrapper:after{content:"";position:absolute;width:200%;height:200%;top:-50%;left:-50%}.van-slider--disabled{opacity:.3} @import '../common/index.wxss';.van-slider{position:relative;border-radius:999px;border-radius:var(--border-radius-max,999px);background-color:#ebedf0;background-color:var(--slider-inactive-background-color,#ebedf0)}.van-slider:before{position:absolute;right:0;left:0;content:"";top:-8px;top:-var(--padding-xs,8px);bottom:-8px;bottom:-var(--padding-xs,8px)}.van-slider__bar{position:relative;border-radius:inherit;transition:width .2s;transition:width var(--animation-duration-fast,.2s);background-color:#1989fa;background-color:var(--slider-active-background-color,#1989fa)}.van-slider__button{width:24px;height:24px;border-radius:50%;box-shadow:0 1px 2px rgba(0,0,0,.5);background-color:#fff;background-color:var(--slider-button-background-color,#fff)}.van-slider__button-wrapper{position:absolute;top:50%;right:0;-webkit-transform:translate3d(50%,-50%,0);transform:translate3d(50%,-50%,0)}.van-slider--disabled{opacity:.5}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { isDef } from '../common/utils';
const LONG_PRESS_START_TIME = 600;
const LONG_PRESS_INTERVAL = 200;
// add num and avoid float number
function add(num1, num2) {
const cardinal = Math.pow(10, 10);
return Math.round((num1 + num2) * cardinal) / cardinal;
}
function equal(value1, value2) {
return String(value1) === String(value2);
}
VantComponent({ VantComponent({
field: true, field: true,
classes: [ classes: ['input-class', 'plus-class', 'minus-class'],
'input-class',
'plus-class',
'minus-class'
],
props: { props: {
value: null, value: {
integer: Boolean, type: null,
observer(value) {
if (!equal(value, this.data.currentValue)) {
this.setData({ currentValue: this.format(value) });
}
},
},
integer: {
type: Boolean,
observer: 'check',
},
disabled: Boolean, disabled: Boolean,
inputWidth: String, inputWidth: null,
buttonSize: null,
asyncChange: Boolean, asyncChange: Boolean,
disableInput: Boolean, disableInput: Boolean,
decimalLength: {
type: Number,
value: null,
observer: 'check',
},
min: { min: {
type: null, type: null,
value: 1 value: 1,
observer: 'check',
}, },
max: { max: {
type: null, type: null,
value: Number.MAX_SAFE_INTEGER value: Number.MAX_SAFE_INTEGER,
observer: 'check',
}, },
step: { step: {
type: null, type: null,
value: 1 value: 1,
}, },
showPlus: { showPlus: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
showMinus: { showMinus: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
disablePlus: Boolean, disablePlus: Boolean,
disableMinus: Boolean disableMinus: Boolean,
}, longPress: {
computed: { type: Boolean,
minusDisabled() { value: true,
return this.data.disabled || this.data.disableMinus || this.data.value <= this.data.min;
},
plusDisabled() {
return this.data.disabled || this.data.disablePlus || this.data.value >= this.data.max;
}
},
watch: {
value(value) {
if (value === '') {
return;
}
const newValue = this.range(value);
if (typeof newValue === 'number' && +this.data.value !== newValue) {
this.set({ value: newValue });
}
}, },
max: 'check',
min: 'check',
}, },
data: { data: {
focus: false currentValue: '',
}, },
created() { created() {
this.set({ this.setData({
value: this.range(this.data.value) currentValue: this.format(this.data.value),
}); });
}, },
methods: { methods: {
check() { check() {
const newValue = this.range(this.data.value); const val = this.format(this.data.currentValue);
if (typeof newValue === 'number' && +this.data.value !== newValue) { if (!equal(val, this.data.currentValue)) {
this.set({ value: newValue }); this.setData({ currentValue: val });
} }
}, },
isDisabled(type) {
if (type === 'plus') {
return (
this.data.disabled ||
this.data.disablePlus ||
this.data.currentValue >= this.data.max
);
}
return (
this.data.disabled ||
this.data.disableMinus ||
this.data.currentValue <= this.data.min
);
},
onFocus(event) { onFocus(event) {
this.$emit('focus', event.detail); this.$emit('focus', event.detail);
}, },
onBlur(event) { onBlur(event) {
const value = this.range(this.data.value); const value = this.format(event.detail.value);
this.triggerInput(value); this.emitChange(value);
this.$emit('blur', event.detail); this.$emit(
'blur',
Object.assign(Object.assign({}, event.detail), { value })
);
},
// filter illegal characters
filter(value) {
value = String(value).replace(/[^0-9.-]/g, '');
if (this.data.integer && value.indexOf('.') !== -1) {
value = value.split('.')[0];
}
return value;
}, },
// limit value range // limit value range
range(value) { format(value) {
value = String(value).replace(/[^0-9.-]/g, ''); value = this.filter(value);
return Math.max(Math.min(this.data.max, value), this.data.min); // format range
value = value === '' ? 0 : +value;
value = Math.max(Math.min(this.data.max, value), this.data.min);
// format decimal
if (isDef(this.data.decimalLength)) {
value = value.toFixed(this.data.decimalLength);
}
return value;
}, },
onInput(event) { onInput(event) {
const { value = '' } = event.detail || {}; const { value = '' } = event.detail || {};
this.triggerInput(value); // allow input to be empty
if (value === '') {
return;
}
let formatted = this.filter(value);
// limit max decimal length
if (isDef(this.data.decimalLength) && formatted.indexOf('.') !== -1) {
const pair = formatted.split('.');
formatted = `${pair[0]}.${pair[1].slice(0, this.data.decimalLength)}`;
}
this.emitChange(formatted);
}, },
onChange(type) { emitChange(value) {
if (this.data[`${type}Disabled`]) { if (!this.data.asyncChange) {
this.setData({ currentValue: value });
}
this.$emit('change', value);
},
onChange() {
const { type } = this;
if (this.isDisabled(type)) {
this.$emit('overlimit', type); this.$emit('overlimit', type);
return; return;
} }
const diff = type === 'minus' ? -this.data.step : +this.data.step; const diff = type === 'minus' ? -this.data.step : +this.data.step;
const value = Math.round((+this.data.value + diff) * 100) / 100; const value = this.format(add(+this.data.currentValue, diff));
this.triggerInput(this.range(value)); this.emitChange(value);
this.$emit(type); this.$emit(type);
}, },
onMinus() { longPressStep() {
this.onChange('minus'); this.longPressTimer = setTimeout(() => {
this.onChange();
this.longPressStep();
}, LONG_PRESS_INTERVAL);
}, },
onPlus() { onTap(event) {
this.onChange('plus'); const { type } = event.currentTarget.dataset;
this.type = type;
this.onChange();
}, },
triggerInput(value) { onTouchStart(event) {
this.set({ if (!this.data.longPress) {
value: this.data.asyncChange ? this.data.value : value return;
});
this.$emit('change', value);
} }
clearTimeout(this.longPressTimer);
const { type } = event.currentTarget.dataset;
this.type = type;
this.isLongPress = false;
this.longPressTimer = setTimeout(() => {
this.isLongPress = true;
this.onChange();
this.longPressStep();
}, LONG_PRESS_START_TIME);
},
onTouchEnd() {
if (!this.data.longPress) {
return;
} }
clearTimeout(this.longPressTimer);
},
},
}); });
...@@ -2,17 +2,21 @@ ...@@ -2,17 +2,21 @@
<view class="van-stepper custom-class"> <view class="van-stepper custom-class">
<view <view
class="minus-class {{ utils.bem('stepper__minus', { disabled: minusDisabled }) }}" wx:if="{{ showMinus }}"
style="{{ showMinus ? '' : 'display: none;' }}" data-type="minus"
style="width: {{ utils.addUnit(buttonSize) }}; height: {{ utils.addUnit(buttonSize) }}"
class="minus-class {{ utils.bem('stepper__minus', { disabled: disabled || disableMinus || currentValue <= min }) }}"
hover-class="van-stepper__minus--hover" hover-class="van-stepper__minus--hover"
hover-stay-time="70" hover-stay-time="70"
bind:tap="onMinus" bind:tap="onTap"
bind:touchstart="onTouchStart"
bind:touchend="onTouchEnd"
/> />
<input <input
type="{{ integer ? 'number' : 'digit' }}" type="{{ integer ? 'number' : 'digit' }}"
class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}" class="input-class {{ utils.bem('stepper__input', { disabled: disabled || disableInput }) }}"
style="{{ inputWidth ? 'width: ' + inputWidth : '' }}" style="width: {{ utils.addUnit(inputWidth) }}; height: {{ utils.addUnit(buttonSize) }}"
value="{{ value }}" value="{{ currentValue }}"
focus="{{ focus }}" focus="{{ focus }}"
disabled="{{ disabled || disableInput }}" disabled="{{ disabled || disableInput }}"
bindinput="onInput" bindinput="onInput"
...@@ -20,10 +24,14 @@ ...@@ -20,10 +24,14 @@
bind:blur="onBlur" bind:blur="onBlur"
/> />
<view <view
class="plus-class {{ utils.bem('stepper__plus', { disabled: plusDisabled }) }}" wx:if="{{ showPlus }}"
style="{{ showPlus ? '' : 'display: none;' }}" data-type="plus"
style="width: {{ utils.addUnit(buttonSize) }}; height: {{ utils.addUnit(buttonSize) }}"
class="plus-class {{ utils.bem('stepper__plus', { disabled: disabled || disablePlus || currentValue >= max }) }}"
hover-class="van-stepper__plus--hover" hover-class="van-stepper__plus--hover"
hover-stay-time="70" hover-stay-time="70"
bind:tap="onPlus" bind:tap="onTap"
bind:touchstart="onTouchStart"
bind:touchend="onTouchEnd"
/> />
</view> </view>
@import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{position:relative;display:inline-block;width:28px;height:28px;padding:5px;margin:1px;vertical-align:middle;background-color:#f2f3f5;border:0;box-sizing:border-box}.van-stepper__minus:before,.van-stepper__plus:before{width:9px;height:1px}.van-stepper__minus:after,.van-stepper__plus:after{width:1px;height:9px}.van-stepper__minus:after,.van-stepper__minus:before,.van-stepper__plus:after,.van-stepper__plus:before{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;background-color:#333;content:""}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:#e8e8e8}.van-stepper__minus--disabled,.van-stepper__plus--disabled{background-color:#f7f8fa}.van-stepper__minus--disabled:after,.van-stepper__minus--disabled:before,.van-stepper__plus--disabled:after,.van-stepper__plus--disabled:before{background-color:#c9c9c9}.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:#f7f8fa}.van-stepper__minus{border-radius:4px 0 0 4px}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 4px 4px 0}.van-stepper__input{display:inline-block;width:30px;height:26px;padding:1px;margin:1px;font-size:14px;color:#333;text-align:center;vertical-align:middle;background-color:#f2f3f5;border:0;border-width:1px 0;border-radius:0;box-sizing:initial;-webkit-appearance:none}.van-stepper__input--disabled{color:#c9c9c9;background-color:#f2f3f5} @import '../common/index.wxss';.van-stepper{font-size:0}.van-stepper__minus,.van-stepper__plus{position:relative;display:inline-block;box-sizing:border-box;margin:1px;vertical-align:middle;border:0;background-color:#f2f3f5;background-color:var(--stepper-background-color,#f2f3f5);color:#323233;color:var(--stepper-button-icon-color,#323233);width:28px;width:var(--stepper-input-height,28px);height:28px;height:var(--stepper-input-height,28px);padding:4px;padding:var(--padding-base,4px)}.van-stepper__minus:before,.van-stepper__plus:before{width:9px;height:1px}.van-stepper__minus:after,.van-stepper__plus:after{width:1px;height:9px}.van-stepper__minus:after,.van-stepper__minus:before,.van-stepper__plus:after,.van-stepper__plus:before{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;background-color:currentColor;content:""}.van-stepper__minus--hover,.van-stepper__plus--hover{background-color:#e8e8e8;background-color:var(--stepper-active-color,#e8e8e8)}.van-stepper__minus--disabled,.van-stepper__plus--disabled{color:#c8c9cc;color:var(--stepper-button-disabled-icon-color,#c8c9cc)}.van-stepper__minus--disabled,.van-stepper__minus--disabled.van-stepper__minus--hover,.van-stepper__minus--disabled.van-stepper__plus--hover,.van-stepper__plus--disabled,.van-stepper__plus--disabled.van-stepper__minus--hover,.van-stepper__plus--disabled.van-stepper__plus--hover{background-color:#f7f8fa;background-color:var(--stepper-button-disabled-color,#f7f8fa)}.van-stepper__minus{border-radius:4px 0 0 4px;border-radius:var(--stepper-border-radius,4px) 0 0 var(--stepper-border-radius,4px)}.van-stepper__minus:after{display:none}.van-stepper__plus{border-radius:0 4px 4px 0;border-radius:0 var(--stepper-border-radius,4px) var(--stepper-border-radius,4px) 0}.van-stepper__input{display:inline-block;box-sizing:border-box;min-height:0;margin:1px;padding:1px;text-align:center;vertical-align:middle;border:0;border-width:1px 0;border-radius:0;-webkit-appearance:none;font-size:14px;font-size:var(--stepper-input-font-size,14px);color:#323233;color:var(--stepper-input-text-color,#323233);background-color:#f2f3f5;background-color:var(--stepper-background-color,#f2f3f5);width:32px;width:var(--stepper-input-width,32px);height:28px;height:var(--stepper-input-height,28px)}.van-stepper__input--disabled{color:#c8c9cc;color:var(--stepper-input-disabled-text-color,#c8c9cc);background-color:#f2f3f5;background-color:var(--stepper-input-disabled-background-color,#f2f3f5)}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { GREEN } from '../common/color'; import { GREEN, GRAY_DARK } from '../common/color';
VantComponent({ VantComponent({
classes: ['desc-class'],
props: { props: {
icon: String, icon: String,
steps: Array, steps: Array,
active: Number, active: Number,
direction: { direction: {
type: String, type: String,
value: 'horizontal' value: 'horizontal',
}, },
activeColor: { activeColor: {
type: String, type: String,
value: GREEN value: GREEN,
} },
} inactiveColor: {
type: String,
value: GRAY_DARK,
},
activeIcon: {
type: String,
value: 'checked',
},
inactiveIcon: String,
},
methods: {
onClick(event) {
const { index } = event.currentTarget.dataset;
this.$emit('click-step', index);
},
},
}); });
...@@ -5,17 +5,36 @@ ...@@ -5,17 +5,36 @@
<view <view
wx:for="{{ steps }}" wx:for="{{ steps }}"
wx:key="index" wx:key="index"
bindtap="onClick"
data-index="{{ index }}"
class="{{ utils.bem('step', [direction, status(index, active)]) }} van-hairline" class="{{ utils.bem('step', [direction, status(index, active)]) }} van-hairline"
style="{{ status(index, active) === 'inactive' ? 'color: ' + inactiveColor: '' }}"
> >
<view class="van-step__title" style="{{ index === active ? 'color: ' + activeColor : '' }}"> <view class="van-step__title" style="{{ index === active ? 'color: ' + activeColor : '' }}">
<view>{{ item.text }}</view> <view>{{ item.text }}</view>
<view>{{ item.desc }}</view> <view class="desc-class">{{ item.desc }}</view>
</view> </view>
<view class="van-step__circle-container"> <view class="van-step__circle-container">
<view class="van-step__circle" wx:if="{{ index !== active }}" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" /> <block wx:if="{{ index !== active }}">
<van-icon wx:else name="checked" color="{{ activeColor }}" custom-class="van-step__active" /> <van-icon
wx:if="{{ inactiveIcon }}"
color="{{ status(index, active) === 'inactive' ? inactiveColor: activeColor }}"
name="{{ inactiveIcon }}"
custom-class="van-step__icon"
/>
<view
wx:else
class="van-step__circle"
style="{{ 'background-color: ' + (index < active ? activeColor : inactiveColor) }}"
/>
</block>
<van-icon wx:else name="{{ activeIcon }}" color="{{ activeColor }}" custom-class="van-step__icon" />
</view> </view>
<view wx:if="{{ index !== steps.length - 1 }}" class="van-step__line" style="{{ index < active ? 'background-color: ' + activeColor : '' }}" /> <view
wx:if="{{ index !== steps.length - 1 }}"
class="van-step__line" style="{{ 'background-color: ' + (index < active ? activeColor : inactiveColor) }}"
/>
</view> </view>
</view> </view>
</view> </view>
...@@ -28,7 +47,7 @@ function get(index, active) { ...@@ -28,7 +47,7 @@ function get(index, active) {
return 'process'; return 'process';
} }
return ''; return 'inactive';
} }
module.exports = get; module.exports = get;
......
@import '../common/index.wxss';.van-steps{overflow:hidden;background-color:#fff}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{position:relative;display:-webkit-flex;display:flex;overflow:hidden}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{position:relative;-webkit-flex:1;flex:1;font-size:14px;color:#999}.van-step--finish{color:#333}.van-step__circle{width:5px;height:5px;background-color:#999;border-radius:50%}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{-webkit-transform:none;transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{position:absolute;right:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;-webkit-transform:none;transform:none}.van-step--horizontal:last-child .van-step__circle-container{right:0;padding:0 0 0 8px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{position:absolute;bottom:6px;z-index:1;padding:0 8px;background-color:#fff;-webkit-transform:translate3d(-50%,50%,0);transform:translate3d(-50%,50%,0)}.van-step--horizontal .van-step__title{display:inline-block;font-size:12px;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)}.van-step--horizontal .van-step__line{position:absolute;right:0;bottom:6px;left:0;height:1px;background-color:#eee;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal.van-step--process{color:#333}.van-step--horizontal.van-step--process .van-step__active{display:block;font-size:12px;line-height:1}.van-step--vertical{padding:10px 10px 10px 0;font-size:14px;line-height:18px}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{position:absolute;top:0;left:-15px;z-index:1;width:1px;height:20px;background-color:#fff;content:""}.van-step--vertical .van-step__active,.van-step--vertical .van-step__circle,.van-step--vertical .van-step__line{position:absolute;top:19px;left:-14px;z-index:2;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-step--vertical .van-step__active{font-size:12px;line-height:1}.van-step--vertical .van-step__line{z-index:1;width:1px;height:100%;background-color:#eee;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0)} @import '../common/index.wxss';.van-steps{overflow:hidden;background-color:#fff;background-color:var(--steps-background-color,#fff)}.van-steps--horizontal{padding:10px}.van-steps--horizontal .van-step__wrapper{position:relative;display:-webkit-flex;display:flex;overflow:hidden}.van-steps--vertical{padding-left:10px}.van-steps--vertical .van-step__wrapper{padding:0 0 0 20px}.van-step{position:relative;-webkit-flex:1;flex:1;font-size:14px;font-size:var(--step-font-size,14px);color:#969799;color:var(--step-text-color,#969799)}.van-step--finish{color:#323233;color:var(--step-finish-text-color,#323233)}.van-step__circle{border-radius:50%;width:5px;width:var(--step-circle-size,5px);height:5px;height:var(--step-circle-size,5px);background-color:#969799;background-color:var(--step-circle-color,#969799)}.van-step--horizontal{padding-bottom:14px}.van-step--horizontal:first-child .van-step__title{-webkit-transform:none;transform:none}.van-step--horizontal:first-child .van-step__circle-container{padding:0 8px 0 0;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal:last-child{position:absolute;right:0;width:auto}.van-step--horizontal:last-child .van-step__title{text-align:right;-webkit-transform:none;transform:none}.van-step--horizontal:last-child .van-step__circle-container{right:0;padding:0 0 0 8px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0)}.van-step--horizontal .van-step__circle-container{position:absolute;bottom:6px;z-index:1;-webkit-transform:translate3d(-50%,50%,0);transform:translate3d(-50%,50%,0);background-color:#fff;background-color:var(--white,#fff);padding:0 8px;padding:0 var(--padding-xs,8px)}.van-step--horizontal .van-step__title{display:inline-block;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0);font-size:12px;font-size:var(--step-horizontal-title-font-size,12px)}.van-step--horizontal .van-step__line{position:absolute;right:0;bottom:6px;left:0;height:1px;-webkit-transform:translate3d(0,50%,0);transform:translate3d(0,50%,0);background-color:#ebedf0;background-color:var(--step-line-color,#ebedf0)}.van-step--horizontal.van-step--process{color:#323233;color:var(--step-process-text-color,#323233)}.van-step--horizontal.van-step--process .van-step__icon{display:block;line-height:1;font-size:12px;font-size:var(--step-icon-size,12px)}.van-step--vertical{padding:10px 10px 10px 0;line-height:18px}.van-step--vertical:after{border-bottom-width:1px}.van-step--vertical:last-child:after{border-bottom-width:none}.van-step--vertical:first-child:before{position:absolute;top:0;left:-15px;z-index:1;width:1px;height:20px;content:"";background-color:#fff;background-color:var(--white,#fff)}.van-step--vertical .van-step__circle,.van-step--vertical .van-step__icon,.van-step--vertical .van-step__line{position:absolute;top:19px;left:-14px;z-index:2;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.van-step--vertical .van-step__icon{line-height:1;font-size:12px;font-size:var(--step-icon-size,12px)}.van-step--vertical .van-step__line{z-index:1;width:1px;height:100%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0);background-color:#ebedf0;background-color:var(--step-line-color,#ebedf0)}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component';
import { pageScrollMixin } from '../mixins/page-scroll';
const ROOT_ELEMENT = '.van-sticky';
VantComponent({
props: {
zIndex: {
type: Number,
value: 99,
},
offsetTop: {
type: Number,
value: 0,
observer: 'onScroll',
},
disabled: {
type: Boolean,
observer: 'onScroll',
},
container: {
type: null,
observer: 'onScroll',
},
scrollTop: {
type: null,
observer(val) {
this.onScroll({ scrollTop: val });
},
},
},
mixins: [
pageScrollMixin(function (event) {
if (this.data.scrollTop != null) {
return;
}
this.onScroll(event);
}),
],
data: {
height: 0,
fixed: false,
transform: 0,
},
mounted() {
this.onScroll();
},
methods: {
onScroll({ scrollTop } = {}) {
const { container, offsetTop, disabled } = this.data;
if (disabled) {
this.setDataAfterDiff({
fixed: false,
transform: 0,
});
return;
}
this.scrollTop = scrollTop || this.scrollTop;
if (typeof container === 'function') {
Promise.all([this.getRect(ROOT_ELEMENT), this.getContainerRect()]).then(
([root, container]) => {
if (offsetTop + root.height > container.height + container.top) {
this.setDataAfterDiff({
fixed: false,
transform: container.height - root.height,
});
} else if (offsetTop >= root.top) {
this.setDataAfterDiff({
fixed: true,
height: root.height,
transform: 0,
});
} else {
this.setDataAfterDiff({ fixed: false, transform: 0 });
}
}
);
return;
}
this.getRect(ROOT_ELEMENT).then((root) => {
if (offsetTop >= root.top) {
this.setDataAfterDiff({ fixed: true, height: root.height });
this.transform = 0;
} else {
this.setDataAfterDiff({ fixed: false });
}
});
},
setDataAfterDiff(data) {
wx.nextTick(() => {
const diff = Object.keys(data).reduce((prev, key) => {
if (data[key] !== this.data[key]) {
prev[key] = data[key];
}
return prev;
}, {});
this.setData(diff);
this.$emit('scroll', {
scrollTop: this.scrollTop,
isFixed: data.fixed || this.data.fixed,
});
});
},
getContainerRect() {
const nodesRef = this.data.container();
return new Promise((resolve) =>
nodesRef.boundingClientRect(resolve).exec()
);
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="custom-class van-sticky" style="{{ computed.containerStyle({ fixed, height, zIndex }) }}">
<view class="{{ utils.bem('sticky-wrap', { fixed }) }}" style="{{ computed.wrapStyle({ fixed, offsetTop, transform, zIndex }) }}">
<slot />
</view>
</view>
/* eslint-disable */
function wrapStyle(data) {
var style = '';
if (data.transform) {
style += 'transform: translate3d(0, ' + data.transform + 'px, 0);';
}
if (data.fixed) {
style += 'top: ' + data.offsetTop + 'px;';
}
if (data.zIndex) {
style += 'z-index: ' + data.zIndex + ';';
}
return style;
}
function containerStyle(data) {
var style = '';
if (data.fixed) {
style += 'height: ' + data.height + 'px;';
}
if (data.zIndex) {
style += 'z-index: ' + data.zIndex + ';';
}
return style;
}
module.exports = {
wrapStyle: wrapStyle,
containerStyle: containerStyle
};
@import '../common/index.wxss';.van-sticky{position:relative}.van-sticky-wrap--fixed{position:fixed;right:0;left:0}
\ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({ VantComponent({
mixins: [safeArea()], classes: ['bar-class', 'price-class', 'button-class'],
classes: [
'bar-class',
'price-class',
'button-class'
],
props: { props: {
tip: { tip: {
type: null, type: null,
observer: 'updateTip' observer: 'updateTip',
}, },
tipIcon: String, tipIcon: String,
type: Number, type: Number,
price: { price: {
type: null, type: null,
observer: 'updatePrice' observer: 'updatePrice',
}, },
label: String, label: String,
loading: Boolean, loading: Boolean,
...@@ -24,32 +18,40 @@ VantComponent({ ...@@ -24,32 +18,40 @@ VantComponent({
buttonText: String, buttonText: String,
currency: { currency: {
type: String, type: String,
value: '¥' value: '¥',
}, },
buttonType: { buttonType: {
type: String, type: String,
value: 'danger' value: 'danger',
}, },
decimalLength: { decimalLength: {
type: Number, type: Number,
value: 2, value: 2,
observer: 'updatePrice' observer: 'updatePrice',
},
suffixLabel: String,
safeAreaInsetBottom: {
type: Boolean,
value: true,
}, },
suffixLabel: String
}, },
methods: { methods: {
updatePrice() { updatePrice() {
const { price, decimalLength } = this.data; const { price, decimalLength } = this.data;
this.set({ const priceStrArr =
typeof price === 'number' &&
(price / 100).toFixed(decimalLength).split('.');
this.setData({
hasPrice: typeof price === 'number', hasPrice: typeof price === 'number',
priceStr: (price / 100).toFixed(decimalLength) integerStr: priceStrArr && priceStrArr[0],
decimalStr: decimalLength && priceStrArr ? `.${priceStrArr[1]}` : '',
}); });
}, },
updateTip() { updateTip() {
this.set({ hasTip: typeof this.data.tip === 'string' }); this.setData({ hasTip: typeof this.data.tip === 'string' });
}, },
onSubmit(event) { onSubmit(event) {
this.$emit('submit', event.detail); this.$emit('submit', event.detail);
} },
} },
}); });
...@@ -16,27 +16,29 @@ ...@@ -16,27 +16,29 @@
<slot name="tip" /> <slot name="tip" />
</view> </view>
<view class="bar-class {{ utils.bem('submit-bar__bar', { safe: safeAreaInsetBottom && isIPhoneX }) }}"> <view class="bar-class van-submit-bar__bar">
<slot /> <slot />
<view wx:if="{{ hasPrice }}" class="van-submit-bar__text"> <view wx:if="{{ hasPrice }}" class="van-submit-bar__text">
<text>{{ label || '合计:' }}</text> <text>{{ label || '合计:' }}</text>
<text class="van-submit-bar__price price-class"> <text class="van-submit-bar__price price-class">
<text class="van-submit-bar__currency">{{ currency }} </text> <text class="van-submit-bar__currency">{{ currency }} </text>
<text>{{ priceStr }}</text> <text class="van-submit-bar__price-integer">{{ integerStr }}</text><text>{{decimalStr}}</text>
</text> </text>
<text class="van-submit-bar__suffix-label">{{ suffixLabel }}</text> <text class="van-submit-bar__suffix-label">{{ suffixLabel }}</text>
</view> </view>
<van-button <van-button
square round
size="large"
type="{{ buttonType }}" type="{{ buttonType }}"
loading="{{ loading }}" loading="{{ loading }}"
disabled="{{ disabled }}" disabled="{{ disabled }}"
class="van-submit-bar__button" class="van-submit-bar__button"
custom-class="button-class" custom-class="button-class"
custom-style="width: 100%;"
bind:click="onSubmit" bind:click="onSubmit"
> >
{{ loading ? '' : buttonText }} {{ loading ? '' : buttonText }}
</van-button> </van-button>
</view> </view>
<view wx:if="{{ safeAreaInsetBottom }}" class="van-submit-bar__safe" />
</view> </view>
@import '../common/index.wxss';.van-submit-bar{position:fixed;bottom:0;left:0;z-index:100;width:100%;-webkit-user-select:none;user-select:none}.van-submit-bar__tip{padding:10px;font-size:12px;line-height:1.5;color:#f56723;background-color:#fff7cc}.van-submit-bar__tip:empty{display:none}.van-submit-bar__tip-icon{width:12px;height:12px;margin-right:4px;vertical-align:middle}.van-submit-bar__tip-text{display:inline;vertical-align:middle}.van-submit-bar__bar{display:-webkit-flex;display:flex;height:50px;font-size:14px;background-color:#fff;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-end;justify-content:flex-end}.van-submit-bar__bar--safe{padding-bottom:34px}.van-submit-bar__text{padding-right:12px;font-weight:500;color:#333;-webkit-flex:1;flex:1;text-align:right}.van-submit-bar__price{font-size:18px;color:#f44}.van-submit-bar__currency{font-size:14px}.van-submit-bar__suffix-label{margin-left:5px}.van-submit-bar__button{width:110px} @import '../common/index.wxss';.van-submit-bar{position:fixed;bottom:0;left:0;width:100%;-webkit-user-select:none;user-select:none;z-index:100;z-index:var(--submit-bar-z-index,100);background-color:#fff;background-color:var(--submit-bar-background-color,#fff)}.van-submit-bar__tip{padding:10px;padding:var(--submit-bar-tip-padding,10px);color:#f56723;color:var(--submit-bar-tip-color,#f56723);font-size:12px;font-size:var(--submit-bar-tip-font-size,12px);line-height:1.5;line-height:var(--submit-bar-tip-line-height,1.5);background-color:#fff7cc;background-color:var(--submit-bar-tip-background-color,#fff7cc)}.van-submit-bar__tip:empty{display:none}.van-submit-bar__tip-icon{width:12px;height:12px;margin-right:4px;vertical-align:middle;font-size:12px;font-size:var(--submit-bar-tip-icon-size,12px);min-width:18px;min-width:calc(var(--submit-bar-tip-icon-size, 12px)*1.5)}.van-submit-bar__tip-text{display:inline;vertical-align:middle}.van-submit-bar__bar{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-end;justify-content:flex-end;padding:0 16px;padding:var(--submit-bar-padding,0 16px);height:50px;height:var(--submit-bar-height,50px);font-size:14px;font-size:var(--submit-bar-text-font-size,14px);background-color:#fff;background-color:var(--submit-bar-background-color,#fff)}.van-submit-bar__safe{height:constant(safe-area-inset-bottom);height:env(safe-area-inset-bottom)}.van-submit-bar__text{-webkit-flex:1;flex:1;text-align:right;color:#323233;color:var(--submit-bar-text-color,#323233);padding-right:12px;padding-right:var(--padding-sm,12px)}.van-submit-bar__price,.van-submit-bar__text{font-weight:500;font-weight:var(--font-weight-bold,500)}.van-submit-bar__price{color:#ee0a24;color:var(--submit-bar-price-color,#ee0a24);font-size:12px;font-size:var(--submit-bar-price-font-size,12px)}.van-submit-bar__price-integer{font-size:20px;font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif}.van-submit-bar__currency{font-size:12px;font-size:var(--submit-bar-currency-font-size,12px)}.van-submit-bar__suffix-label{margin-left:5px}.van-submit-bar__button{width:110px;width:var(--submit-bar-button-width,110px);font-weight:500;font-weight:var(--font-weight-bold,500);--button-default-height:40px!important;--button-default-height:var(--submit-bar-button-height,40px)!important;--button-line-height:40px!important;--button-line-height:var(--submit-bar-button-height,40px)!important}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch'; import { touch } from '../mixins/touch';
import { range } from '../common/utils';
const THRESHOLD = 0.3; const THRESHOLD = 0.3;
let ARRAY = [];
VantComponent({ VantComponent({
props: { props: {
disabled: Boolean, disabled: Boolean,
leftWidth: { leftWidth: {
type: Number, type: Number,
value: 0 value: 0,
observer(leftWidth = 0) {
if (this.offset > 0) {
this.swipeMove(leftWidth);
}
},
}, },
rightWidth: { rightWidth: {
type: Number, type: Number,
value: 0 value: 0,
observer(rightWidth = 0) {
if (this.offset < 0) {
this.swipeMove(-rightWidth);
}
},
},
asyncClose: Boolean,
name: {
type: [Number, String],
value: '',
}, },
asyncClose: Boolean
}, },
mixins: [touch], mixins: [touch],
data: { data: {
catchMove: false catchMove: false,
}, },
created() { created() {
this.offset = 0; this.offset = 0;
ARRAY.push(this);
},
destroyed() {
ARRAY = ARRAY.filter((item) => item !== this);
}, },
methods: { methods: {
open(position) { open(position) {
const { leftWidth, rightWidth } = this.data; const { leftWidth, rightWidth } = this.data;
const offset = position === 'left' ? leftWidth : -rightWidth; const offset = position === 'left' ? leftWidth : -rightWidth;
this.swipeMove(offset); this.swipeMove(offset);
this.$emit('open', {
position,
name: this.data.name,
});
}, },
close() { close() {
this.swipeMove(0); this.swipeMove(0);
}, },
swipeMove(offset = 0) { swipeMove(offset = 0) {
this.offset = offset; this.offset = range(offset, -this.data.rightWidth, this.data.leftWidth);
const transform = `translate3d(${offset}px, 0, 0)`; const transform = `translate3d(${this.offset}px, 0, 0)`;
const transition = this.draging const transition = this.dragging
? 'none' ? 'none'
: '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'; : 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
this.set({ this.setData({
wrapperStyle: ` wrapperStyle: `
-webkit-transform: ${transform}; -webkit-transform: ${transform};
-webkit-transition: ${transition}; -webkit-transition: ${transition};
transform: ${transform}; transform: ${transform};
transition: ${transition}; transition: ${transition};
` `,
}); });
}, },
swipeLeaveTransition() { swipeLeaveTransition() {
...@@ -50,50 +74,39 @@ VantComponent({ ...@@ -50,50 +74,39 @@ VantComponent({
const { offset } = this; const { offset } = this;
if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) { if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) {
this.open('right'); this.open('right');
} } else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
this.open('left'); this.open('left');
} } else {
else {
this.swipeMove(0); this.swipeMove(0);
} }
this.set({ catchMove: false }); this.setData({ catchMove: false });
}, },
startDrag(event) { startDrag(event) {
if (this.data.disabled) { if (this.data.disabled) {
return; return;
} }
this.draging = true;
this.startOffset = this.offset; this.startOffset = this.offset;
this.firstDirection = '';
this.touchStart(event); this.touchStart(event);
}, },
noop() { }, noop() {},
onDrag(event) { onDrag(event) {
if (this.data.disabled) { if (this.data.disabled) {
return; return;
} }
this.touchMove(event); this.touchMove(event);
if (!this.firstDirection) { if (this.direction !== 'horizontal') {
this.firstDirection = this.direction;
this.set({ catchMove: this.firstDirection === 'horizontal' });
}
if (this.firstDirection === 'vertical') {
return; return;
} }
const { leftWidth, rightWidth } = this.data; this.dragging = true;
const offset = this.startOffset + this.deltaX; ARRAY.filter((item) => item !== this).forEach((item) => item.close());
if ((rightWidth > 0 && -offset > rightWidth) || this.setData({ catchMove: true });
(leftWidth > 0 && offset > leftWidth)) { this.swipeMove(this.startOffset + this.deltaX);
return;
}
this.swipeMove(offset);
}, },
endDrag() { endDrag() {
if (this.data.disabled) { if (this.data.disabled) {
return; return;
} }
this.draging = false; this.dragging = false;
this.swipeLeaveTransition(); this.swipeLeaveTransition();
}, },
onClick(event) { onClick(event) {
...@@ -103,11 +116,14 @@ VantComponent({ ...@@ -103,11 +116,14 @@ VantComponent({
return; return;
} }
if (this.data.asyncClose) { if (this.data.asyncClose) {
this.$emit('close', { position, instance: this }); this.$emit('close', {
} position,
else { instance: this,
name: this.data.name,
});
} else {
this.swipeMove(0); this.swipeMove(0);
} }
} },
} },
}); });
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
bindtouchstart="startDrag" bindtouchstart="startDrag"
catchtouchmove="{{ catchMove ? 'noop' : '' }}" catchtouchmove="{{ catchMove ? 'noop' : '' }}"
capture-bind:touchmove="onDrag" capture-bind:touchmove="onDrag"
catchtouchend="endDrag" bindtouchend="endDrag"
catchtouchcancel="endDrag" bindtouchcancel="endDrag"
> >
<view style="{{ wrapperStyle }}"> <view style="{{ wrapperStyle }}">
<view wx:if="{{ leftWidth }}" class="van-swipe-cell__left" data-key="left" catch:tap="onClick"> <view wx:if="{{ leftWidth }}" class="van-swipe-cell__left" data-key="left" catch:tap="onClick">
......
import { VantComponent } from '../common/component';
VantComponent({
field: true,
props: {
value: null,
icon: String,
title: String,
label: String,
border: Boolean,
checked: Boolean,
loading: Boolean,
disabled: Boolean,
activeColor: String,
inactiveColor: String,
useLabelSlot: Boolean,
size: {
type: String,
value: '24px'
},
activeValue: {
type: null,
value: true
},
inactiveValue: {
type: null,
value: false
}
},
watch: {
checked(value) {
this.set({ value });
}
},
created() {
this.set({ value: this.data.checked });
},
methods: {
onChange(event) {
this.$emit('change', event.detail);
}
}
});
<van-cell
center
title="{{ title }}"
label="{{ label }}"
border="{{ border }}"
icon="{{ icon }}"
custom-class="van-switch-cell"
use-label-slot="{{ useLabelSlot }}"
>
<slot slot="icon" name="icon" />
<slot slot="title" name="title" />
<slot slot="label" name="label" />
<van-switch
size="{{ size }}"
checked="{{ checked }}"
loading="{{ loading }}"
disabled="{{ disabled }}"
active-color="{{ activeColor }}"
inactive-color="{{ inactiveColor }}"
active-value="{{ activeValue }}"
inactive-value="{{ inactiveValue }}"
custom-class="van-switch-cell__switch"
bind:change="onChange"
/>
</van-cell>
@import '../common/index.wxss';.van-switch-cell{padding-top:9px;padding-bottom:9px}.van-switch-cell__switch{vertical-align:middle}
\ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { BLUE, GRAY_DARK } from '../common/color';
VantComponent({ VantComponent({
field: true, field: true,
classes: ['node-class'], classes: ['node-class'],
props: { props: {
checked: null, checked: {
type: null,
observer(value) {
const loadingColor = this.getLoadingColor(value);
this.setData({ value, loadingColor });
},
},
loading: Boolean, loading: Boolean,
disabled: Boolean, disabled: Boolean,
activeColor: String, activeColor: String,
inactiveColor: String, inactiveColor: String,
size: { size: {
type: String, type: String,
value: '30px' value: '30px',
}, },
activeValue: { activeValue: {
type: null, type: null,
value: true value: true,
}, },
inactiveValue: { inactiveValue: {
type: null, type: null,
value: false value: false,
}
}, },
watch: {
checked(value) {
this.set({ value });
}
}, },
created() { created() {
this.set({ value: this.data.checked }); const { checked: value } = this.data;
const loadingColor = this.getLoadingColor(value);
this.setData({ value, loadingColor });
}, },
methods: { methods: {
getLoadingColor(checked) {
const { activeColor, inactiveColor } = this.data;
return checked ? activeColor || BLUE : inactiveColor || GRAY_DARK;
},
onClick() { onClick() {
const { activeValue, inactiveValue } = this.data; const { activeValue, inactiveValue } = this.data;
if (!this.data.disabled && !this.data.loading) { if (!this.data.disabled && !this.data.loading) {
...@@ -38,6 +46,6 @@ VantComponent({ ...@@ -38,6 +46,6 @@ VantComponent({
this.$emit('input', value); this.$emit('input', value);
this.$emit('change', value); this.$emit('change', value);
} }
} },
} },
}); });
...@@ -6,6 +6,6 @@ ...@@ -6,6 +6,6 @@
bind:tap="onClick" bind:tap="onClick"
> >
<view class="van-switch__node node-class"> <view class="van-switch__node node-class">
<van-loading wx:if="{{ loading }}" size="50%" custom-class="van-switch__loading" /> <van-loading wx:if="{{ loading }}" color="{{ loadingColor }}" custom-class="van-switch__loading" />
</view> </view>
</view> </view>
@import '../common/index.wxss';.van-switch{display:inline-block;position:relative;width:2em;border:1px solid rgba(0,0,0,.1);border-radius:1em;box-sizing:initial;transition:background-color .3s}.van-switch,.van-switch__node{height:1em;background-color:#fff}.van-switch__node{top:0;left:0;position:absolute;border-radius:100%;width:1em;z-index:1;transition:.3s;box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05)}.van-switch__loading{top:25%;left:25%;position:absolute!important}.van-switch--on{background-color:#1989fa}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em)}.van-switch--disabled{opacity:.4} @import '../common/index.wxss';.van-switch{position:relative;display:inline-block;box-sizing:initial;width:2em;width:var(--switch-width,2em);height:1em;height:var(--switch-height,1em);background-color:#fff;background-color:var(--switch-background-color,#fff);border:1px solid rgba(0,0,0,.1);border:var(--switch-border,1px solid rgba(0,0,0,.1));border-radius:1em;border-radius:var(--switch-node-size,1em);transition:background-color .3s;transition:background-color var(--switch-transition-duration,.3s)}.van-switch__node{position:absolute;top:0;left:0;border-radius:100%;z-index:1;z-index:var(--switch-node-z-index,1);width:1em;width:var(--switch-node-size,1em);height:1em;height:var(--switch-node-size,1em);background-color:#fff;background-color:var(--switch-node-background-color,#fff);box-shadow:0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05);box-shadow:var(--switch-node-box-shadow,0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05));transition:-webkit-transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:transform .3s cubic-bezier(.3,1.05,.4,1.05),-webkit-transform .3s cubic-bezier(.3,1.05,.4,1.05);transition:-webkit-transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);transition:transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);transition:transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05),-webkit-transform var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05)}.van-switch__loading{position:absolute!important;top:25%;left:25%;width:50%;height:50%}.van-switch--on{background-color:#1989fa;background-color:var(--switch-on-background-color,#1989fa)}.van-switch--on .van-switch__node{-webkit-transform:translateX(1em);transform:translateX(1em);-webkit-transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)));transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)))}.van-switch--disabled{opacity:.4;opacity:var(--switch-disabled-opacity,.4)}
\ No newline at end of file \ No newline at end of file
...@@ -2,34 +2,58 @@ import { VantComponent } from '../common/component'; ...@@ -2,34 +2,58 @@ import { VantComponent } from '../common/component';
VantComponent({ VantComponent({
relation: { relation: {
name: 'tabs', name: 'tabs',
type: 'ancestor' type: 'ancestor',
current: 'tab',
}, },
props: { props: {
dot: Boolean, dot: {
info: null, type: Boolean,
title: String, observer: 'update',
disabled: Boolean, },
titleStyle: String info: {
type: null,
observer: 'update',
},
title: {
type: String,
observer: 'update',
},
disabled: {
type: Boolean,
observer: 'update',
},
titleStyle: {
type: String,
observer: 'update',
},
name: {
type: [Number, String],
value: '',
},
}, },
data: { data: {
width: null,
inited: false,
active: false, active: false,
animated: false
},
watch: {
title: 'update',
disabled: 'update',
dot: 'update',
info: 'update',
titleStyle: 'update'
}, },
methods: { methods: {
update() { getComputedName() {
const parent = this.getRelationNodes('../tabs/index')[0]; if (this.data.name !== '') {
if (parent) { return this.data.name;
parent.updateTabs();
}
} }
return this.index;
},
updateRender(active, parent) {
const { data: parentData } = parent;
this.inited = this.inited || active;
this.setData({
active,
shouldRender: this.inited || !parentData.lazyRender,
shouldShow: active || parentData.animated,
});
},
update() {
if (this.parent) {
this.parent.updateTabs();
} }
},
},
}); });
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<view <view
wx:if="{{ animated || inited }}"
class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}" class="custom-class {{ utils.bem('tab__pane', { active, inactive: !active }) }}"
style="{{ animated || active ? '' : 'display: none;' }} {{ width ? 'width:' + width + 'px;' : '' }}" style="{{ shouldShow ? '' : 'display: none;' }}"
> >
<slot /> <slot wx:if="{{ shouldRender }}" />
</view> </view>
@import '../common/index.wxss';.van-tab__pane{box-sizing:border-box;overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible} @import '../common/index.wxss';:host{-webkit-flex-shrink:0;flex-shrink:0;width:100%}.van-tab__pane,:host{box-sizing:border-box}.van-tab__pane{overflow-y:auto;-webkit-overflow-scrolling:touch}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
\ No newline at end of file \ No newline at end of file
...@@ -2,18 +2,17 @@ import { VantComponent } from '../common/component'; ...@@ -2,18 +2,17 @@ import { VantComponent } from '../common/component';
VantComponent({ VantComponent({
props: { props: {
info: null, info: null,
name: null,
icon: String, icon: String,
dot: Boolean, dot: Boolean,
name: {
type: [String, Number]
}
}, },
relation: { relation: {
name: 'tabbar', name: 'tabbar',
type: 'ancestor' type: 'ancestor',
current: 'tabbar-item',
}, },
data: { data: {
active: false active: false,
}, },
methods: { methods: {
onClick() { onClick() {
...@@ -44,6 +43,6 @@ VantComponent({ ...@@ -44,6 +43,6 @@ VantComponent({
return Object.keys(patch).length > 0 return Object.keys(patch).length > 0
? this.set(patch) ? this.set(patch)
: Promise.resolve(); : Promise.resolve();
} },
} },
}); });
...@@ -5,11 +5,11 @@ ...@@ -5,11 +5,11 @@
style="color: {{ active ? activeColor : inactiveColor }}" style="color: {{ active ? activeColor : inactiveColor }}"
bind:tap="onClick" bind:tap="onClick"
> >
<view class="{{ utils.bem('tabbar-item__icon', { dot }) }}"> <view class="van-tabbar-item__icon">
<van-icon <van-icon
wx:if="{{ icon }}" wx:if="{{ icon }}"
name="{{ icon }}" name="{{ icon }}"
customStyle="display: block" custom-class="van-tabbar-item__icon__inner"
/> />
<block wx:else> <block wx:else>
<slot <slot
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
<slot wx:else name="icon" /> <slot wx:else name="icon" />
</block> </block>
<van-info <van-info
wx:if="{{ info !== null }}" dot="{{ dot }}"
info="{{ info }}" info="{{ info }}"
custom-style="margin-top: 2px" custom-class="van-tabbar-item__info"
/> />
</view> </view>
<view class="van-tabbar-item__text"> <view class="van-tabbar-item__text">
......
@import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-tabbar-item{color:#7d7e80;height:100%;display:-webkit-flex;display:flex;line-height:1;font-size:12px;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center}.van-tabbar-item__icon{font-size:18px;margin-bottom:5px;position:relative}.van-tabbar-item__icon--dot:after{top:0;right:-8px;width:8px;height:8px;content:" ";position:absolute;border-radius:100%;background-color:#f44}.van-tabbar-item__icon image{width:30px;height:18px;display:block}.van-tabbar-item--active{color:#1989fa} @import '../common/index.wxss';:host{-webkit-flex:1;flex:1}.van-tabbar-item{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;height:100%;color:#646566;color:var(--tabbar-item-text-color,#646566);font-size:12px;font-size:var(--tabbar-item-font-size,12px);line-height:1;line-height:var(--tabbar-item-line-height,1)}.van-tabbar-item__icon{position:relative;margin-bottom:5px;margin-bottom:var(--tabbar-item-margin-bottom,5px);font-size:18px;font-size:var(--tabbar-item-icon-size,18px)}.van-tabbar-item__icon__inner{display:block;min-width:1em}.van-tabbar-item--active{color:#1989fa;color:var(--tabbar-item-active-color,#1989fa)}.van-tabbar-item__info{margin-top:2px}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
VantComponent({ VantComponent({
mixins: [safeArea()],
relation: { relation: {
name: 'tabbar-item', name: 'tabbar-item',
type: 'descendant', type: 'descendant',
current: 'tabbar',
linked(target) { linked(target) {
this.children.push(target);
target.parent = this; target.parent = this;
target.updateFromParent(); target.updateFromParent();
}, },
unlinked(target) { unlinked() {
this.children = this.children.filter((item) => item !== target);
this.updateChildren(); this.updateChildren();
} },
}, },
props: { props: {
active: { active: {
type: [Number, String], type: null,
observer: 'updateChildren' observer: 'updateChildren',
}, },
activeColor: { activeColor: {
type: String, type: String,
observer: 'updateChildren' observer: 'updateChildren',
}, },
inactiveColor: { inactiveColor: {
type: String, type: String,
observer: 'updateChildren' observer: 'updateChildren',
}, },
fixed: { fixed: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
border: { border: {
type: Boolean, type: Boolean,
value: true value: true,
}, },
zIndex: { zIndex: {
type: Number, type: Number,
value: 1 value: 1,
} },
safeAreaInsetBottom: {
type: Boolean,
value: true,
}, },
beforeCreate() {
this.children = [];
}, },
methods: { methods: {
updateChildren() { updateChildren() {
...@@ -58,6 +56,6 @@ VantComponent({ ...@@ -58,6 +56,6 @@ VantComponent({
if (active !== this.data.active) { if (active !== this.data.active) {
this.$emit('change', active); this.$emit('change', active);
} }
} },
} },
}); });
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<view <view
class="custom-class {{ border ? 'van-hairline--top-bottom' : '' }} {{ utils.bem('tabbar', { fixed, safe: isIPhoneX && safeAreaInsetBottom }) }}" class="custom-class {{ border ? 'van-hairline--top-bottom' : '' }} {{ utils.bem('tabbar', { fixed, safe: safeAreaInsetBottom }) }}"
style="{{ zIndex ? 'z-index: ' + zIndex : '' }}" style="{{ zIndex ? 'z-index: ' + zIndex : '' }}"
> >
<slot /> <slot />
......
@import '../common/index.wxss';.van-tabbar{display:-webkit-flex;display:flex;width:100%;height:50px;background-color:#fff}.van-tabbar--fixed{position:fixed;bottom:0;left:0}.van-tabbar--safe{padding-bottom:34px} @import '../common/index.wxss';.van-tabbar{display:-webkit-flex;display:flex;width:100%;height:50px;height:var(--tabbar-height,50px);background-color:#fff;background-color:var(--tabbar-background-color,#fff)}.van-tabbar--fixed{position:fixed;bottom:0;left:0}.van-tabbar--safe{padding-bottom:env(safe-area-inset-bottom)}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch'; import { touch } from '../mixins/touch';
import { nextTick } from '../common/utils'; import { isDef, addUnit } from '../common/utils';
VantComponent({ VantComponent({
mixins: [touch], mixins: [touch],
classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'], classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'],
relation: { relation: {
name: 'tab', name: 'tab',
type: 'descendant', type: 'descendant',
linked(child) { current: 'tabs',
this.child.push(child); linked(target) {
this.updateTabs(this.data.tabs.concat(child.data)); target.index = this.children.length - 1;
}, this.updateTabs();
unlinked(child) { },
const index = this.child.indexOf(child); unlinked() {
const { tabs } = this.data; this.children = this.children.map((child, index) => {
tabs.splice(index, 1); child.index = index;
this.child.splice(index, 1); return child;
this.updateTabs(tabs); });
} this.updateTabs();
},
}, },
props: { props: {
color: String, color: {
type: String,
observer: 'setLine',
},
sticky: Boolean, sticky: Boolean,
animated: Boolean, animated: {
type: Boolean,
observer() {
this.children.forEach((child, index) =>
child.updateRender(index === this.data.currentIndex, this)
);
},
},
swipeable: Boolean, swipeable: Boolean,
lineWidth: { lineWidth: {
type: Number, type: [String, Number],
value: -1 value: -1,
observer: 'setLine',
}, },
lineHeight: { lineHeight: {
type: Number, type: [String, Number],
value: -1 value: -1,
observer: 'setLine',
}, },
titleActiveColor: String,
titleInactiveColor: String,
active: { active: {
type: Number, type: [String, Number],
value: 0 value: 0,
observer(name) {
if (name !== this.getCurrentName()) {
this.setCurrentIndexByName(name);
}
},
}, },
type: { type: {
type: String, type: String,
value: 'line' value: 'line',
}, },
border: { border: {
type: Boolean, type: Boolean,
value: true value: true,
},
ellipsis: {
type: Boolean,
value: true,
}, },
duration: { duration: {
type: Number, type: Number,
value: 0.3 value: 0.3,
}, },
zIndex: { zIndex: {
type: Number, type: Number,
value: 1 value: 1,
}, },
swipeThreshold: { swipeThreshold: {
type: Number, type: Number,
value: 4 value: 4,
observer(value) {
this.setData({
scrollable: this.children.length > value || !this.data.ellipsis,
});
},
}, },
offsetTop: { offsetTop: {
type: Number, type: Number,
value: 0 value: 0,
} },
lazyRender: {
type: Boolean,
value: true,
},
}, },
data: { data: {
tabs: [], tabs: [],
...@@ -67,251 +100,185 @@ VantComponent({ ...@@ -67,251 +100,185 @@ VantComponent({
scrollLeft: 0, scrollLeft: 0,
scrollable: false, scrollable: false,
trackStyle: '', trackStyle: '',
wrapStyle: '', currentIndex: null,
position: '' container: null,
},
watch: {
swipeThreshold() {
this.set({
scrollable: this.child.length > this.data.swipeThreshold
});
},
color: 'setLine',
lineWidth: 'setLine',
lineHeight: 'setLine',
active: 'setActiveTab',
animated: 'setTrack',
offsetTop: 'setWrapStyle'
},
beforeCreate() {
this.child = [];
}, },
mounted() { mounted() {
wx.nextTick(() => {
this.setLine(true); this.setLine(true);
this.setTrack();
this.scrollIntoView(); this.scrollIntoView();
this.getRect('.van-tabs__wrap').then((rect) => {
this.navHeight = rect.height;
this.observerContentScroll();
}); });
}, },
destroyed() {
// @ts-ignore
this.createIntersectionObserver().disconnect();
},
methods: { methods: {
updateTabs(tabs) { updateContainer() {
tabs = tabs || this.data.tabs; this.setData({
this.set({ container: () => this.createSelectorQuery().select('.van-tabs'),
tabs,
scrollable: tabs.length > this.data.swipeThreshold
}); });
this.setActiveTab();
}, },
trigger(eventName, index) { updateTabs() {
const { children = [], data } = this;
this.setData({
tabs: children.map((child) => child.data),
scrollable:
this.children.length > data.swipeThreshold || !data.ellipsis,
});
this.setCurrentIndexByName(this.getCurrentName() || data.active);
},
trigger(eventName, child) {
const { currentIndex } = this.data;
const currentChild = child || this.children[currentIndex];
if (!isDef(currentChild)) {
return;
}
this.$emit(eventName, { this.$emit(eventName, {
index, index: currentChild.index,
title: this.data.tabs[index].title name: currentChild.getComputedName(),
title: currentChild.data.title,
}); });
}, },
onTap(event) { onTap(event) {
const { index } = event.currentTarget.dataset; const { index } = event.currentTarget.dataset;
if (this.data.tabs[index].disabled) { const child = this.children[index];
this.trigger('disabled', index); if (child.data.disabled) {
this.trigger('disabled', child);
} else {
this.setCurrentIndex(index);
wx.nextTick(() => {
this.trigger('click');
});
} }
else { },
this.trigger('click', index); // correct the index of active tab
this.setActive(index); setCurrentIndexByName(name) {
const { children = [] } = this;
const matched = children.filter(
(child) => child.getComputedName() === name
);
if (matched.length) {
this.setCurrentIndex(matched[0].index);
} }
}, },
setActive(active) { setCurrentIndex(currentIndex) {
if (active !== this.data.active) { const { data, children = [] } = this;
this.trigger('change', active); if (
this.set({ active }); !isDef(currentIndex) ||
this.setActiveTab(); currentIndex >= children.length ||
currentIndex < 0
) {
return;
}
children.forEach((item, index) => {
const active = index === currentIndex;
if (active !== item.data.active || !item.inited) {
item.updateRender(active, this);
}
});
if (currentIndex === data.currentIndex) {
return;
}
const shouldEmitChange = data.currentIndex !== null;
this.setData({ currentIndex });
wx.nextTick(() => {
this.setLine();
this.scrollIntoView();
this.updateContainer();
this.trigger('input');
if (shouldEmitChange) {
this.trigger('change');
}
});
},
getCurrentName() {
const activeTab = this.children[this.data.currentIndex];
if (activeTab) {
return activeTab.getComputedName();
} }
}, },
setLine(skipTransition) { setLine(skipTransition) {
if (this.data.type !== 'line') { if (this.data.type !== 'line') {
return; return;
} }
const { color, active, duration, lineWidth, lineHeight } = this.data; const {
this.getRect('.van-tab', true).then((rects) => { color,
const rect = rects[active]; duration,
currentIndex,
lineWidth,
lineHeight,
} = this.data;
this.getRect('.van-tab', true).then((rects = []) => {
const rect = rects[currentIndex];
if (rect == null) {
return;
}
const width = lineWidth !== -1 ? lineWidth : rect.width / 2; const width = lineWidth !== -1 ? lineWidth : rect.width / 2;
const height = lineHeight !== -1 ? `height: ${lineHeight}px;` : ''; const height =
lineHeight !== -1
? `height: ${addUnit(lineHeight)}; border-radius: ${addUnit(
lineHeight
)};`
: '';
let left = rects let left = rects
.slice(0, active) .slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0); .reduce((prev, curr) => prev + curr.width, 0);
left += (rect.width - width) / 2; left += (rect.width - width) / 2;
const transition = skipTransition const transition = skipTransition
? '' ? ''
: `transition-duration: ${duration}s; -webkit-transition-duration: ${duration}s;`; : `transition-duration: ${duration}s; -webkit-transition-duration: ${duration}s;`;
this.set({ this.setData({
lineStyle: ` lineStyle: `
${height} ${height}
width: ${width}px; width: ${addUnit(width)};
background-color: ${color}; background-color: ${color};
-webkit-transform: translateX(${left}px); -webkit-transform: translateX(${left}px);
transform: translateX(${left}px); transform: translateX(${left}px);
${transition} ${transition}
` `,
});
});
},
setTrack() {
const { animated, active, duration } = this.data;
if (!animated)
return '';
this.getRect('.van-tabs__content').then((rect) => {
const { width } = rect;
this.set({
trackStyle: `
width: ${width * this.child.length}px;
left: ${-1 * active * width}px;
transition: left ${duration}s;
display: -webkit-box;
display: flex;
`
});
const props = { width, animated };
this.child.forEach((item) => {
item.set(props);
}); });
}); });
}, },
setActiveTab() {
this.child.forEach((item, index) => {
const data = {
active: index === this.data.active
};
if (data.active) {
data.inited = true;
}
if (data.active !== item.data.active) {
item.set(data);
}
});
nextTick(() => {
this.setLine();
this.setTrack();
this.scrollIntoView();
});
},
// scroll active tab into view // scroll active tab into view
scrollIntoView() { scrollIntoView() {
const { active, scrollable } = this.data; const { currentIndex, scrollable } = this.data;
if (!scrollable) { if (!scrollable) {
return; return;
} }
Promise.all([ Promise.all([
this.getRect('.van-tab', true), this.getRect('.van-tab', true),
this.getRect('.van-tabs__nav') this.getRect('.van-tabs__nav'),
]).then(([tabRects, navRect]) => { ]).then(([tabRects, navRect]) => {
const tabRect = tabRects[active]; const tabRect = tabRects[currentIndex];
const offsetLeft = tabRects const offsetLeft = tabRects
.slice(0, active) .slice(0, currentIndex)
.reduce((prev, curr) => prev + curr.width, 0); .reduce((prev, curr) => prev + curr.width, 0);
this.set({ this.setData({
scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2 scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2,
}); });
}); });
}, },
onTouchScroll(event) {
this.$emit('scroll', event.detail);
},
onTouchStart(event) { onTouchStart(event) {
if (!this.data.swipeable) if (!this.data.swipeable) return;
return;
this.touchStart(event); this.touchStart(event);
}, },
onTouchMove(event) { onTouchMove(event) {
if (!this.data.swipeable) if (!this.data.swipeable) return;
return;
this.touchMove(event); this.touchMove(event);
}, },
// watch swipe touch end // watch swipe touch end
onTouchEnd() { onTouchEnd() {
if (!this.data.swipeable) if (!this.data.swipeable) return;
return; const { tabs, currentIndex } = this.data;
const { active, tabs } = this.data;
const { direction, deltaX, offsetX } = this; const { direction, deltaX, offsetX } = this;
const minSwipeDistance = 50; const minSwipeDistance = 50;
if (direction === 'horizontal' && offsetX >= minSwipeDistance) { if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
if (deltaX > 0 && active !== 0) { if (deltaX > 0 && currentIndex !== 0) {
this.setActive(active - 1); this.setCurrentIndex(currentIndex - 1);
} } else if (deltaX < 0 && currentIndex !== tabs.length - 1) {
else if (deltaX < 0 && active !== tabs.length - 1) { this.setCurrentIndex(currentIndex + 1);
this.setActive(active + 1);
} }
} }
}, },
setWrapStyle() {
const { offsetTop, position } = this.data;
let wrapStyle;
switch (position) {
case 'top':
wrapStyle = `
top: ${offsetTop}px;
position: fixed;
`;
break;
case 'bottom':
wrapStyle = `
top: auto;
bottom: 0;
`;
break;
default:
wrapStyle = '';
}
// cut down `set`
if (wrapStyle === this.data.wrapStyle)
return;
this.set({ wrapStyle });
}, },
observerContentScroll() {
if (!this.data.sticky) {
return;
}
const { offsetTop } = this.data;
const { windowHeight } = wx.getSystemInfoSync();
// @ts-ignore
this.createIntersectionObserver().disconnect();
// @ts-ignore
this.createIntersectionObserver()
.relativeToViewport({ top: -(this.navHeight + offsetTop) })
.observe('.van-tabs', (res) => {
const { top } = res.boundingClientRect;
if (top > offsetTop) {
return;
}
const position = res.intersectionRatio > 0 ? 'top' : 'bottom';
this.$emit('scroll', {
scrollTop: top + offsetTop,
isFixed: position === 'top'
});
this.setPosition(position);
});
// @ts-ignore
this.createIntersectionObserver()
.relativeToViewport({ bottom: -(windowHeight - 1 - offsetTop) })
.observe('.van-tabs', (res) => {
const { top, bottom } = res.boundingClientRect;
if (bottom < this.navHeight) {
return;
}
const position = res.intersectionRatio > 0 ? 'top' : '';
this.$emit('scroll', {
scrollTop: top + offsetTop,
isFixed: position === 'top'
});
this.setPosition(position);
});
},
setPosition(position) {
if (position !== this.data.position) {
this.set({ position }).then(() => {
this.setWrapStyle();
});
}
}
}
}); });
{ {
"component": true, "component": true,
"usingComponents": { "usingComponents": {
"van-info": "../info/index" "van-info": "../info/index",
"van-sticky": "../sticky/index"
} }
} }
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="getters" />
<view class="custom-class {{ utils.bem('tabs', [type]) }}"> <view class="custom-class {{ utils.bem('tabs', [type]) }}">
<view style="z-index: {{ zIndex }}; {{ wrapStyle }}" class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}"> <van-sticky
disabled="{{ !sticky }}"
z-index="{{ zIndex }}"
offset-top="{{ offsetTop }}"
container="{{ container }}"
bind:scroll="onTouchScroll"
>
<view class="{{ utils.bem('tabs__wrap', { scrollable }) }} {{ type === 'line' && border ? 'van-hairline--top-bottom' : '' }}">
<slot name="nav-left" /> <slot name="nav-left" />
<scroll-view <scroll-view
scroll-x="{{ scrollable }}" scroll-x="{{ scrollable }}"
scroll-with-animation scroll-with-animation
scroll-left="{{ scrollLeft }}" scroll-left="{{ scrollLeft }}"
class="van-tabs__scroll--{{ type }}" class="{{ utils.bem('tabs__scroll', [type]) }}"
style="{{ color ? 'border-color: ' + color : '' }}" style="{{ color ? 'border-color: ' + color : '' }}"
> >
<view class="{{ utils.bem('tabs__nav', [type]) }} nav-class"> <view class="{{ utils.bem('tabs__nav', [type]) }} nav-class" style="{{ getters.tabCardTypeBorderStyle(color, type) }}">
<view wx:if="{{ type === 'line' }}" class="van-tabs__line" style="{{ lineStyle }}" /> <view wx:if="{{ type === 'line' }}" class="van-tabs__line" style="{{ lineStyle }}" />
<view <view
wx:for="{{ tabs }}" wx:for="{{ tabs }}"
wx:key="index" wx:key="index"
data-index="{{ index }}" data-index="{{ index }}"
class="van-ellipsis tab-class {{ index === active ? 'tab-active-class' : '' }} {{ utils.bem('tab', { active: index === active, disabled: item.disabled }) }}" class="{{ getters.tabClass(index === currentIndex, ellipsis) }} {{ utils.bem('tab', { active: index === currentIndex, disabled: item.disabled, complete: !ellipsis }) }}"
style="{{ color && index !== active && type === 'card' && !item.disabled ? 'color: ' + color : '' }} {{ color && index === active && type === 'card' ? ';background-color:' + color : '' }} {{ color ? ';border-color: ' + color : '' }} {{ scrollable ? ';flex-basis:' + (88 / swipeThreshold) + '%' : '' }}" style="{{ getters.tabStyle(index === currentIndex, ellipsis, color, type, item.disabled, titleActiveColor, titleInactiveColor, swipeThreshold, scrollable) }}"
bind:tap="onTap" bind:tap="onTap"
> >
<view class="van-ellipsis {{ utils.bem('tab__title', { dot: item.dot }) }}" style="{{ item.titleStyle }}"> <view class="{{ ellipsis ? 'van-ellipsis' : '' }}" style="{{ item.titleStyle }}">
{{ item.title }} {{ item.title }}
<van-info <van-info
wx:if="{{ item.info !== null }}" wx:if="{{ item.info !== null || item.dot }}"
info="{{ item.info }}" info="{{ item.info }}"
dot="{{ item.dot }}"
custom-class="van-tab__title__info" custom-class="van-tab__title__info"
/> />
</view> </view>
...@@ -35,6 +44,8 @@ ...@@ -35,6 +44,8 @@
<slot name="nav-right" /> <slot name="nav-right" />
</view> </view>
</van-sticky>
<view <view
class="van-tabs__content" class="van-tabs__content"
bind:touchstart="onTouchStart" bind:touchstart="onTouchStart"
...@@ -42,7 +53,10 @@ ...@@ -42,7 +53,10 @@
bind:touchend="onTouchEnd" bind:touchend="onTouchEnd"
bind:touchcancel="onTouchEnd" bind:touchcancel="onTouchEnd"
> >
<view class="van-tabs__track" style="{{ trackStyle }}"> <view
class="{{ utils.bem('tabs__track', [{ animated }]) }} van-tabs__track"
style="{{ getters.trackStyle({ duration, currentIndex, animated }) }}"
>
<slot /> <slot />
</view> </view>
</view> </view>
......
/* eslint-disable */
function tabClass(active, ellipsis) {
var classes = ['tab-class'];
if (active) {
classes.push('tab-active-class');
}
if (ellipsis) {
classes.push('van-ellipsis');
}
return classes.join(' ');
}
function tabStyle(
active,
ellipsis,
color,
type,
disabled,
activeColor,
inactiveColor,
swipeThreshold,
scrollable
) {
var styles = [];
var isCard = type === 'card';
// card theme color
if (color && isCard) {
styles.push('border-color:' + color);
if (!disabled) {
if (active) {
styles.push('background-color:' + color);
} else {
styles.push('color:' + color);
}
}
}
var titleColor = active ? activeColor : inactiveColor;
if (titleColor) {
styles.push('color:' + titleColor);
}
if (scrollable && ellipsis) {
styles.push('flex-basis:' + 88 / swipeThreshold + '%');
}
return styles.join(';');
}
function tabCardTypeBorderStyle(color, type) {
var isCard = type === 'card';
var styles = [];
if (isCard && color) {
styles.push('border-color:' + color);
}
return styles.join(';');
}
function trackStyle(data) {
if (!data.animated) {
return '';
}
return [
'transform: translate3d(' + -100 * data.currentIndex + '%, 0, 0)',
'-webkit-transition-duration: ' + data.duration + 's',
'transition-duration: ' + data.duration + 's'
].join(';');
}
module.exports.tabClass = tabClass;
module.exports.tabStyle = tabStyle;
module.exports.trackStyle = trackStyle;
module.exports.tabCardTypeBorderStyle = tabCardTypeBorderStyle;
@import '../common/index.wxss';.van-tabs{position:relative;-webkit-tap-highlight-color:transparent}.van-tabs__wrap{position:absolute;top:0;right:0;left:0;display:-webkit-flex;display:flex;background-color:#fff}.van-tabs__wrap--page-top{position:fixed}.van-tabs__wrap--content-bottom{top:auto;bottom:0}.van-tabs__wrap--scrollable .van-tab{-webkit-flex:0 0 22%;flex:0 0 22%}.van-tabs__scroll--card{border:1px solid #f44;border-radius:2px}.van-tabs__nav{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none}.van-tabs__nav--line{height:100%}.van-tabs__nav--card{height:30px}.van-tabs__nav--card .van-tab{line-height:30px;color:#f44;border-right:1px solid #f44}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{color:#fff;background-color:#f44}.van-tabs__line{position:absolute;bottom:0;left:0;z-index:1;height:3px;background-color:#f44;border-radius:3px}.van-tabs--line{padding-top:44px}.van-tabs--line .van-tabs__wrap{height:44px}.van-tabs--card{padding-top:30px;margin:0 15px}.van-tabs--card .van-tabs__wrap{height:30px}.van-tabs__content{overflow:hidden}.van-tab,.van-tabs__track{position:relative}.van-tab{min-width:0;padding:0 5px;font-size:14px;line-height:44px;color:#7d7e80;text-align:center;cursor:pointer;box-sizing:border-box;-webkit-flex:1;flex:1}.van-tab--active{font-weight:500;color:#333}.van-tab--disabled{color:#c9c9c9}.van-tab__title--dot:after{display:inline-block;width:8px;height:8px;vertical-align:middle;background-color:#f44;border-radius:100%;content:""}.van-tab__title__info{position:relative!important;top:-1px!important;display:inline-block;-webkit-transform:translateX(0)!important;transform:translateX(0)!important} @import '../common/index.wxss';.van-tabs{position:relative;-webkit-tap-highlight-color:transparent}.van-tabs__wrap{display:-webkit-flex;display:flex;overflow:hidden}.van-tabs__wrap--scrollable .van-tab{-webkit-flex:0 0 22%;flex:0 0 22%}.van-tabs__scroll{background-color:#fff;background-color:var(--tabs-nav-background-color,#fff)}.van-tabs__scroll--line{box-sizing:initial;height:calc(100% + 15px)}.van-tabs__scroll--card{margin:0 16px;margin:0 var(--padding-md,16px)}.van-tabs__scroll::-webkit-scrollbar{display:none}.van-tabs__nav{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none}.van-tabs__nav--card{box-sizing:border-box;height:30px;height:var(--tabs-card-height,30px);border:1px solid #ee0a24;border:var(--border-width-base,1px) solid var(--tabs-default-color,#ee0a24);border-radius:2px;border-radius:var(--border-radius-sm,2px)}.van-tabs__nav--card .van-tab{color:#ee0a24;color:var(--tabs-default-color,#ee0a24);line-height:28px;line-height:calc(var(--tabs-card-height, 30px) - 2*var(--border-width-base, 1px));border-right:1px solid #ee0a24;border-right:var(--border-width-base,1px) solid var(--tabs-default-color,#ee0a24)}.van-tabs__nav--card .van-tab:last-child{border-right:none}.van-tabs__nav--card .van-tab.van-tab--active{color:#fff;color:var(--white,#fff);background-color:#ee0a24;background-color:var(--tabs-default-color,#ee0a24)}.van-tabs__nav--card .van-tab--disabled{color:#c8c9cc;color:var(--tab-disabled-text-color,#c8c9cc)}.van-tabs__line{position:absolute;bottom:0;left:0;z-index:1;height:3px;height:var(--tabs-bottom-bar-height,3px);border-radius:3px;border-radius:var(--tabs-bottom-bar-height,3px);background-color:#ee0a24;background-color:var(--tabs-bottom-bar-color,#ee0a24)}.van-tabs__track{position:relative;width:100%;height:100%}.van-tabs__track--animated{display:-webkit-flex;display:flex;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-tabs__content{overflow:hidden}.van-tabs--line .van-tabs__wrap{height:44px;height:var(--tabs-line-height,44px)}.van-tabs--card .van-tabs__wrap{height:30px;height:var(--tabs-card-height,30px)}.van-tab{position:relative;-webkit-flex:1;flex:1;box-sizing:border-box;min-width:0;padding:0 5px;text-align:center;cursor:pointer;color:#646566;color:var(--tab-text-color,#646566);font-size:14px;font-size:var(--tab-font-size,14px);line-height:44px;line-height:var(--tabs-line-height,44px)}.van-tab--active{font-weight:500;font-weight:var(--font-weight-bold,500);color:#323233;color:var(--tab-active-text-color,#323233)}.van-tab--disabled{color:#c8c9cc;color:var(--tab-disabled-text-color,#c8c9cc)}.van-tab--complete{-webkit-flex:1 0 auto!important;flex:1 0 auto!important}.van-tab__title__info{position:relative!important;top:-1px!important;display:inline-block;-webkit-transform:translateX(0)!important;transform:translateX(0)!important}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { RED, BLUE, GREEN, ORANGE } from '../common/color';
const DEFAULT_COLOR = '#999';
const COLOR_MAP = {
danger: RED,
primary: BLUE,
success: GREEN,
warning: ORANGE
};
VantComponent({ VantComponent({
props: { props: {
size: String, size: String,
type: String,
mark: Boolean, mark: Boolean,
color: String, color: String,
plain: Boolean, plain: Boolean,
round: Boolean, round: Boolean,
textColor: String textColor: String,
type: {
type: String,
value: 'default',
},
closeable: Boolean,
},
methods: {
onClose() {
this.$emit('close');
},
}, },
computed: {
style() {
const color = this.data.color || COLOR_MAP[this.data.type] || DEFAULT_COLOR;
const key = this.data.plain ? 'color' : 'background-color';
const style = { [key]: color };
if (this.data.textColor) {
style.color = this.data.textColor;
}
return Object.keys(style).map(key => `${key}: ${style[key]}`).join(';');
}
}
}); });
{ {
"component": true "component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
} }
<wxs src="../wxs/utils.wxs" module="utils" /> <wxs src="../wxs/utils.wxs" module="utils" />
<view <view
class="custom-class {{ utils.bem('tag', [size, { mark, plain, round }]) }} {{ plain ? 'van-hairline--surround' : '' }}" class="custom-class {{ utils.bem('tag', [type, size, { mark, plain, round }]) }} {{ plain ? 'van-hairline--surround' : '' }}"
style="{{ style }}" style="{{ color && !plain ? 'background-color: ' + color + ';' : '' }}{{ textColor || (color && plain) ? 'color: ' + (textColor || color) : '' }}"
> >
<slot /> <slot />
<van-icon
wx:if="{{ closeable }}"
name="cross"
custom-class="van-tag__close"
bind:click="onClose"
/>
</view> </view>
@import '../common/index.wxss';.van-tag{color:#fff;font-size:10px;padding:.2em .5em;line-height:normal;border-radius:.2em;display:inline-block}.van-tag:after{border-color:currentColor;border-radius:.4em}.van-tag--mark{padding-right:.6em;border-radius:0 .8em .8em 0}.van-tag--mark:after{border-radius:0 1.6em 1.6em 0}.van-tag--round{border-radius:.8em}.van-tag--round:after{border-radius:1.6em}.van-tag--medium{font-size:12px}.van-tag--large{font-size:14px} @import '../common/index.wxss';.van-tag{display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;line-height:normal;padding:.2em .5em;padding:var(--tag-padding,.2em .5em);color:#fff;color:var(--tag-text-color,#fff);font-size:10px;font-size:var(--tag-font-size,10px);border-radius:.2em;border-radius:var(--tag-border-radius,.2em)}.van-tag:after{border-color:currentColor;border-radius:.2em * 2;border-radius:var(--tag-border-radius,.2em) * 2}.van-tag--default{background-color:#969799;background-color:var(--tag-default-color,#969799)}.van-tag--default.van-tag--plain{color:#969799;color:var(--tag-default-color,#969799)}.van-tag--danger{background-color:#ee0a24;background-color:var(--tag-dander-color,#ee0a24)}.van-tag--danger.van-tag--plain{color:#ee0a24;color:var(--tag-dander-color,#ee0a24)}.van-tag--primary{background-color:#1989fa;background-color:var(--tag-primary-color,#1989fa)}.van-tag--primary.van-tag--plain{color:#1989fa;color:var(--tag-primary-color,#1989fa)}.van-tag--success{background-color:#07c160;background-color:var(--tag-success-color,#07c160)}.van-tag--success.van-tag--plain{color:#07c160;color:var(--tag-success-color,#07c160)}.van-tag--warning{background-color:#ff976a;background-color:var(--tag-warning-color,#ff976a)}.van-tag--warning.van-tag--plain{color:#ff976a;color:var(--tag-warning-color,#ff976a)}.van-tag--plain{background-color:#fff;background-color:var(--tag-plain-background-color,#fff)}.van-tag--mark{padding-right:.7em}.van-tag--mark,.van-tag--mark:after{border-radius:0 999px 999px 0;border-radius:0 var(--tag-round-border-radius,999px) var(--tag-round-border-radius,999px) 0}.van-tag--round,.van-tag--round:after{border-radius:999px;border-radius:var(--tag-round-border-radius,999px)}.van-tag--medium{font-size:12px;font-size:var(--tag-medium-font-size,12px)}.van-tag--large{font-size:14px;font-size:var(--tag-large-font-size,14px)}.van-tag__close{margin-left:2px}
\ No newline at end of file \ No newline at end of file
...@@ -7,23 +7,23 @@ VantComponent({ ...@@ -7,23 +7,23 @@ VantComponent({
forbidClick: Boolean, forbidClick: Boolean,
zIndex: { zIndex: {
type: Number, type: Number,
value: 1000 value: 1000,
}, },
type: { type: {
type: String, type: String,
value: 'text' value: 'text',
}, },
loadingType: { loadingType: {
type: String, type: String,
value: 'circular' value: 'circular',
}, },
position: { position: {
type: String, type: String,
value: 'middle' value: 'middle',
} },
}, },
methods: { methods: {
// for prevent touchmove // for prevent touchmove
noop() { } noop() {},
} },
}); });
<van-overlay <van-overlay
wx:if="{{ mask || forbidClick }}" wx:if="{{ mask || forbidClick }}"
show="{{ show }}" show="{{ show }}"
mask="{{ mask }}"
z-index="{{ zIndex }}" z-index="{{ zIndex }}"
custom-style="{{ mask ? '' : 'background-color: transparent;' }}"
/> />
<van-transition <van-transition
show="{{ show }}" show="{{ show }}"
......
@import '../common/index.wxss';.van-toast{display:-webkit-flex;display:flex;color:#fff;font-size:14px;line-height:20px;border-radius:4px;word-break:break-all;-webkit-align-items:center;align-items:center;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:center;justify-content:center;box-sizing:initial;background-color:rgba(51,51,51,.88);white-space:pre-wrap}.van-toast__container{position:fixed;top:50%;left:50%;max-width:70%;width:-webkit-fit-content;width:fit-content;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.van-toast--text{padding:8px 12px;min-width:96px}.van-toast--icon{width:90px;padding:15px;min-height:90px}.van-toast--icon .van-toast__icon{font-size:48px}.van-toast--icon .van-toast__text{padding-top:5px}.van-toast__loading{margin:10px 0}.van-toast--top{-webkit-transform:translateY(-30vh);transform:translateY(-30vh)}.van-toast--bottom{-webkit-transform:translateY(30vh);transform:translateY(30vh)} @import '../common/index.wxss';.van-toast{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:initial;color:#fff;color:var(--toast-text-color,#fff);font-size:14px;font-size:var(--toast-font-size,14px);line-height:20px;line-height:var(--toast-line-height,20px);white-space:pre-wrap;word-wrap:break-word;background-color:rgba(50,50,51,.88);background-color:var(--toast-background-color,rgba(50,50,51,.88));border-radius:4px;border-radius:var(--toast-border-radius,4px)}.van-toast__container{position:fixed;top:50%;left:50%;width:-webkit-fit-content;width:fit-content;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);max-width:70%;max-width:var(--toast-max-width,70%)}.van-toast--text{min-width:96px;min-width:var(--toast-text-min-width,96px);padding:8px 12px;padding:var(--toast-text-padding,8px 12px)}.van-toast--icon{width:90px;width:var(--toast-default-width,90px);min-height:90px;min-height:var(--toast-default-min-height,90px);padding:16px;padding:var(--toast-default-padding,16px)}.van-toast--icon .van-toast__icon{font-size:48px;font-size:var(--toast-icon-size,48px)}.van-toast--icon .van-toast__text{padding-top:8px}.van-toast__loading{margin:10px 0}.van-toast--top{-webkit-transform:translateY(-30vh);transform:translateY(-30vh)}.van-toast--bottom{-webkit-transform:translateY(30vh);transform:translateY(30vh)}
\ No newline at end of file \ No newline at end of file
...@@ -5,11 +5,11 @@ const defaultOptions = { ...@@ -5,11 +5,11 @@ const defaultOptions = {
message: '', message: '',
show: true, show: true,
zIndex: 1000, zIndex: 1000,
duration: 3000, duration: 2000,
position: 'middle', position: 'middle',
forbidClick: false, forbidClick: false,
loadingType: 'circular', loadingType: 'circular',
selector: '#van-toast' selector: '#van-toast',
}; };
let queue = []; let queue = [];
let currentOptions = Object.assign({}, defaultOptions); let currentOptions = Object.assign({}, defaultOptions);
...@@ -21,7 +21,10 @@ function getContext() { ...@@ -21,7 +21,10 @@ function getContext() {
return pages[pages.length - 1]; return pages[pages.length - 1];
} }
function Toast(toastOptions) { function Toast(toastOptions) {
const options = Object.assign({}, currentOptions, parseOptions(toastOptions)); const options = Object.assign(
Object.assign({}, currentOptions),
parseOptions(toastOptions)
);
const context = options.context || getContext(); const context = options.context || getContext();
const toast = context.selectComponent(options.selector); const toast = context.selectComponent(options.selector);
if (!toast) { if (!toast) {
...@@ -31,28 +34,29 @@ function Toast(toastOptions) { ...@@ -31,28 +34,29 @@ function Toast(toastOptions) {
delete options.context; delete options.context;
delete options.selector; delete options.selector;
toast.clear = () => { toast.clear = () => {
toast.set({ show: false }); toast.setData({ show: false });
if (options.onClose) { if (options.onClose) {
options.onClose(); options.onClose();
} }
}; };
queue.push(toast); queue.push(toast);
toast.set(options); toast.setData(options);
clearTimeout(toast.timer); clearTimeout(toast.timer);
if (options.duration > 0) { if (options.duration > 0) {
toast.timer = setTimeout(() => { toast.timer = setTimeout(() => {
toast.clear(); toast.clear();
queue = queue.filter(item => item !== toast); queue = queue.filter((item) => item !== toast);
}, options.duration); }, options.duration);
} }
return toast; return toast;
} }
const createMethod = (type) => (options) => Toast(Object.assign({ type }, parseOptions(options))); const createMethod = (type) => (options) =>
Toast(Object.assign({ type }, parseOptions(options)));
Toast.loading = createMethod('loading'); Toast.loading = createMethod('loading');
Toast.success = createMethod('success'); Toast.success = createMethod('success');
Toast.fail = createMethod('fail'); Toast.fail = createMethod('fail');
Toast.clear = () => { Toast.clear = () => {
queue.forEach(toast => { queue.forEach((toast) => {
toast.clear(); toast.clear();
}); });
queue = []; queue = [];
......
...@@ -7,7 +7,7 @@ VantComponent({ ...@@ -7,7 +7,7 @@ VantComponent({
'enter-to-class', 'enter-to-class',
'leave-class', 'leave-class',
'leave-active-class', 'leave-active-class',
'leave-to-class' 'leave-to-class',
], ],
mixins: [transition(true)] mixins: [transition(true)],
}); });
@import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-fade-up-enter,.van-fade-up-leave-to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-fade-down-enter,.van-fade-down-leave-to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-fade-left-enter,.van-fade-left-leave-to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-fade-right-enter,.van-fade-right-leave-to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-slide-up-enter,.van-slide-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)} @import '../common/index.wxss';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.van-fade-up-enter,.van-fade-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);opacity:0}.van-fade-down-enter,.van-fade-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);opacity:0}.van-fade-left-enter,.van-fade-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);opacity:0}.van-fade-right-enter,.van-fade-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);opacity:0}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.van-slide-up-enter,.van-slide-up-leave-to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
const ITEM_HEIGHT = 44;
VantComponent({ VantComponent({
classes: [ classes: [
'main-item-class', 'main-item-class',
...@@ -7,50 +6,49 @@ VantComponent({ ...@@ -7,50 +6,49 @@ VantComponent({
'main-active-class', 'main-active-class',
'content-active-class', 'content-active-class',
'main-disabled-class', 'main-disabled-class',
'content-disabled-class' 'content-disabled-class',
], ],
props: { props: {
items: Array, items: {
type: Array,
observer: 'updateSubItems',
},
activeId: null,
mainActiveIndex: { mainActiveIndex: {
type: Number, type: Number,
value: 0 value: 0,
observer: 'updateSubItems',
}, },
activeId: { height: {
type: [Number, String, Array] type: [Number, String],
value: 300,
}, },
maxHeight: { max: {
type: Number, type: Number,
value: 300 value: Infinity,
} },
}, },
data: { data: {
subItems: [], subItems: [],
mainHeight: 0,
itemHeight: 0
},
watch: {
items() {
this.updateSubItems().then(() => {
this.updateMainHeight();
});
},
maxHeight() {
this.updateItemHeight(this.data.subItems);
this.updateMainHeight();
},
mainActiveIndex: 'updateSubItems'
}, },
methods: { methods: {
// 当一个子项被选择时 // 当一个子项被选择时
onSelectItem(event) { onSelectItem(event) {
const { item } = event.currentTarget.dataset; const { item } = event.currentTarget.dataset;
if (!item.disabled) { const isArray = Array.isArray(this.data.activeId);
// 判断有没有超出右侧选择的最大数
const isOverMax = isArray && this.data.activeId.length >= this.data.max;
// 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件
const isSelected = isArray
? this.data.activeId.indexOf(item.id) > -1
: this.data.activeId === item.id;
if (!item.disabled && (!isOverMax || isSelected)) {
this.$emit('click-item', item); this.$emit('click-item', item);
} }
}, },
// 当一个导航被点击时 // 当一个导航被点击时
onClickNav(event) { onClickNav(event) {
const { index } = event.currentTarget.dataset; const index = event.detail;
const item = this.data.items[index]; const item = this.data.items[index];
if (!item.disabled) { if (!item.disabled) {
this.$emit('click-nav', { index }); this.$emit('click-nav', { index });
...@@ -60,19 +58,7 @@ VantComponent({ ...@@ -60,19 +58,7 @@ VantComponent({
updateSubItems() { updateSubItems() {
const { items, mainActiveIndex } = this.data; const { items, mainActiveIndex } = this.data;
const { children = [] } = items[mainActiveIndex] || {}; const { children = [] } = items[mainActiveIndex] || {};
this.updateItemHeight(children);
return this.set({ subItems: children }); return this.set({ subItems: children });
}, },
// 更新组件整体高度,根据最大高度和当前组件需要展示的高度来决定
updateMainHeight() {
const { items = [], subItems = [] } = this.data;
const maxHeight = Math.max(items.length * ITEM_HEIGHT, subItems.length * ITEM_HEIGHT);
this.set({ mainHeight: Math.min(maxHeight, this.data.maxHeight) });
}, },
// 更新子项列表高度,根据可展示的最大高度和当前子项列表的高度决定
updateItemHeight(subItems) {
const itemHeight = Math.min(subItems.length * ITEM_HEIGHT, this.data.maxHeight);
return this.set({ itemHeight });
}
}
}); });
{ {
"component": true, "component": true,
"usingComponents": { "usingComponents": {
"van-icon": "../icon/index" "van-icon": "../icon/index",
"van-sidebar": "../sidebar/index",
"van-sidebar-item": "../sidebar-item/index"
} }
} }
...@@ -3,28 +3,27 @@ ...@@ -3,28 +3,27 @@
<view <view
class="van-tree-select" class="van-tree-select"
style="height: {{ mainHeight }}px" style="height: {{ utils.addUnit(height) }}"
> >
<scroll-view scroll-y class="van-tree-select__nav"> <scroll-view scroll-y class="van-tree-select__nav">
<view <van-sidebar active-key="{{ mainActiveIndex }}" bind:change="onClickNav" custom-class="van-tree-select__nav__inner">
<van-sidebar-item
wx:for="{{ items }}" wx:for="{{ items }}"
wx:key="index" wx:key="index"
class="van-ellipsis main-item-class {{ utils.bem('tree-select__nitem', { active: mainActiveIndex === index, disabled: item.disabled }) }} {{ mainActiveIndex === index ? 'main-active-class' : '' }} {{ item.disabled ? 'main-disabled-class' : '' }}" custom-class="main-item-class"
data-index="{{ index }}" active-class="main-active-class"
bind:tap="onClickNav" disabled-class="main-disabled-class"
> title="{{ item.text }}"
{{ item.text }} disabled="{{ item.disabled }}"
</view> />
</van-sidebar>
</scroll-view> </scroll-view>
<scroll-view <scroll-view scroll-y class="van-tree-select__content">
scroll-y <slot name="content" />
class="van-tree-select__content"
style="height: {{ itemHeight }}px"
>
<view <view
wx:for="{{ subItems }}" wx:for="{{ subItems }}"
wx:key="id" wx:key="id"
class="van-ellipsis van-hairline--bottom content-item-class {{ utils.bem('tree-select__item', { active: wxs.isActive(activeId, item.id), disabled: item.disabled }) }} {{ wxs.isActive(activeId, item.id) ? 'content-active-class' : '' }} {{ item.disabled ? 'content-disabled-class' : '' }}" class="van-ellipsis content-item-class {{ utils.bem('tree-select__item', { active: wxs.isActive(activeId, item.id), disabled: item.disabled }) }} {{ wxs.isActive(activeId, item.id) ? 'content-active-class' : '' }} {{ item.disabled ? 'content-disabled-class' : '' }}"
data-item="{{ item }}" data-item="{{ item }}"
bind:tap="onSelectItem" bind:tap="onSelectItem"
> >
......
@import '../common/index.wxss';.van-tree-select{position:relative;font-size:14px;-webkit-user-select:none;user-select:none}.van-tree-select__nav{position:absolute;top:0;bottom:0;left:0;width:35%;min-width:120px;background-color:#fafafa}.van-tree-select__nitem{position:relative;padding:0 9px 0 15px;line-height:44px}.van-tree-select__nitem--active:after{position:absolute;top:0;bottom:0;left:0;width:3.6px;background-color:#f44;content:""}.van-tree-select__nitem--active{font-weight:700;background-color:#fff}.van-tree-select__nitem--disabled{color:#999}.van-tree-select__content{width:65%;padding-left:15px;margin-left:35%;background-color:#fff;box-sizing:border-box}.van-tree-select__item{position:relative;font-weight:700;line-height:44px}.van-tree-select__item--active{color:#f44}.van-tree-select__item--disabled{color:#999}.van-tree-select__selected{position:absolute;top:0;right:15px;bottom:0;height:24px;margin:auto 0;line-height:24px} @import '../common/index.wxss';.van-tree-select{position:relative;display:-webkit-flex;display:flex;-webkit-user-select:none;user-select:none;font-size:14px;font-size:var(--tree-select-font-size,14px)}.van-tree-select__nav{-webkit-flex:1;flex:1;background-color:#f7f8fa;background-color:var(--tree-select-nav-background-color,#f7f8fa);--sidebar-padding:12px 8px 12px 12px}.van-tree-select__nav__inner{width:100%!important;height:100%}.van-tree-select__content{-webkit-flex:2;flex:2;background-color:#fff;background-color:var(--tree-select-content-background-color,#fff)}.van-tree-select__item{position:relative;font-weight:700;padding:0 32px 0 16px;padding:0 32px 0 var(--padding-md,16px);line-height:44px;line-height:var(--tree-select-item-height,44px)}.van-tree-select__item--active{color:#ee0a24;color:var(--tree-select-item-active-color,#ee0a24)}.van-tree-select__item--disabled{color:#c8c9cc;color:var(--tree-select-item-disabled-color,#c8c9cc)}.van-tree-select__selected{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);right:16px;right:var(--padding-md,16px)}
\ No newline at end of file \ No newline at end of file
import { VantComponent } from '../common/component';
import { isImageFile, isVideo, chooseFile, isPromise } from './utils';
import { chooseImageProps, chooseVideoProps } from './shared';
VantComponent({
props: Object.assign(
Object.assign(
{
disabled: Boolean,
multiple: Boolean,
uploadText: String,
useBeforeRead: Boolean,
afterRead: null,
beforeRead: null,
previewSize: {
type: null,
value: 90,
},
name: {
type: [Number, String],
value: '',
},
accept: {
type: String,
value: 'image',
},
fileList: {
type: Array,
value: [],
observer: 'formatFileList',
},
maxSize: {
type: Number,
value: Number.MAX_VALUE,
},
maxCount: {
type: Number,
value: 100,
},
deletable: {
type: Boolean,
value: true,
},
showUpload: {
type: Boolean,
value: true,
},
previewImage: {
type: Boolean,
value: true,
},
previewFullImage: {
type: Boolean,
value: true,
},
imageFit: {
type: String,
value: 'scaleToFill',
},
uploadIcon: {
type: String,
value: 'photograph',
},
},
chooseImageProps
),
chooseVideoProps
),
data: {
lists: [],
isInCount: true,
},
methods: {
formatFileList() {
const { fileList = [], maxCount } = this.data;
const lists = fileList.map((item) =>
Object.assign(Object.assign({}, item), {
isImage:
typeof item.isImage === 'undefined'
? isImageFile(item)
: item.isImage,
})
);
this.setData({ lists, isInCount: lists.length < maxCount });
},
getDetail(index) {
return {
name: this.data.name,
index: index == null ? this.data.fileList.length : index,
};
},
startUpload() {
const { maxCount, multiple, accept, lists, disabled } = this.data;
if (disabled) return;
chooseFile(
Object.assign(Object.assign({}, this.data), {
maxCount: maxCount - lists.length,
})
)
.then((res) => {
let file = null;
if (isVideo(res, accept)) {
file = Object.assign({ path: res.tempFilePath }, res);
} else {
file = multiple ? res.tempFiles : res.tempFiles[0];
}
this.onBeforeRead(file);
})
.catch((error) => {
this.$emit('error', error);
});
},
onBeforeRead(file) {
const { beforeRead, useBeforeRead } = this.data;
let res = true;
if (typeof beforeRead === 'function') {
res = beforeRead(file, this.getDetail());
}
if (useBeforeRead) {
res = new Promise((resolve, reject) => {
this.$emit(
'before-read',
Object.assign(Object.assign({ file }, this.getDetail()), {
callback: (ok) => {
ok ? resolve() : reject();
},
})
);
});
}
if (!res) {
return;
}
if (isPromise(res)) {
res.then((data) => this.onAfterRead(data || file));
} else {
this.onAfterRead(file);
}
},
onAfterRead(file) {
const { maxSize } = this.data;
const oversize = Array.isArray(file)
? file.some((item) => item.size > maxSize)
: file.size > maxSize;
if (oversize) {
this.$emit('oversize', Object.assign({ file }, this.getDetail()));
return;
}
if (typeof this.data.afterRead === 'function') {
this.data.afterRead(file, this.getDetail());
}
this.$emit('after-read', Object.assign({ file }, this.getDetail()));
},
deleteItem(event) {
const { index } = event.currentTarget.dataset;
this.$emit(
'delete',
Object.assign(Object.assign({}, this.getDetail(index)), {
file: this.data.fileList[index],
})
);
},
onPreviewImage(event) {
if (!this.data.previewFullImage) return;
const { index } = event.currentTarget.dataset;
const { lists } = this.data;
const item = lists[index];
wx.previewImage({
urls: lists
.filter((item) => item.isImage)
.map((item) => item.url || item.path),
current: item.url || item.path,
fail() {
wx.showToast({ title: '预览图片失败', icon: 'none' });
},
});
},
onClickPreview(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.lists[index];
this.$emit(
'click-preview',
Object.assign(Object.assign({}, item), this.getDetail(index))
);
},
},
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-uploader">
<view class="van-uploader__wrapper">
<!-- 预览样式 -->
<view
wx:if="{{ previewImage }}"
wx:for="{{ lists }}"
wx:key="index"
class="van-uploader__preview"
data-index="{{ index }}"
bindtap="onClickPreview"
>
<image
wx:if="{{ item.isImage }}"
mode="{{ imageFit }}"
src="{{ item.url || item.path }}"
alt="{{ item.name || ('图片' + index) }}"
class="van-uploader__preview-image"
style="width: {{ utils.addUnit(previewSize) }}; height: {{ utils.addUnit(previewSize) }};"
data-index="{{ index }}"
bind:tap="onPreviewImage"
/>
<view
wx:else
class="van-uploader__file"
style="width: {{ utils.addUnit(previewSize) }}; height: {{ utils.addUnit(previewSize) }};"
>
<van-icon name="description" class="van-uploader__file-icon" />
<view class="van-uploader__file-name van-ellipsis">{{ item.name || item.url || item.path }}</view>
</view>
<view
wx:if="{{ item.status === 'uploading' || item.status === 'failed' }}"
class="van-uploader__mask"
>
<van-icon wx:if="{{ item.status === 'failed' }}" name="warning-o" class="van-uploader__mask-icon" />
<van-loading wx:else class="van-uploader__loading" />
<text wx:if="{{ item.message }}" class="van-uploader__upload-text">{{ item.message }}</text>
</view>
<van-icon
wx:if="{{ deletable }}"
name="clear"
class="van-uploader__preview-delete"
data-index="{{ index }}"
bind:tap="deleteItem"
/>
</view>
<!-- 上传样式 -->
<block wx:if="{{ isInCount }}">
<view class="van-uploader__slot" bind:tap="startUpload">
<slot />
</view>
<!-- 默认上传样式 -->
<view
wx:if="{{ showUpload }}"
class="van-uploader__upload {{ disabled ? 'van-uploader__upload--disabled': ''}}"
style="width: {{ utils.addUnit(previewSize) }}; height: {{ utils.addUnit(previewSize) }};"
bind:tap="startUpload"
>
<van-icon name="{{ uploadIcon }}" class="van-uploader__upload-icon" />
<text wx:if="{{ uploadText }}" class="van-uploader__upload-text">{{ uploadText }}</text>
</view>
</block>
</view>
</view>
@import '../common/index.wxss';.van-uploader{position:relative;display:inline-block}.van-uploader__wrapper{display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}.van-uploader__slot:empty{display:none}.van-uploader__slot:not(:empty)+.van-uploader__upload{display:none!important}.van-uploader__upload{position:relative;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:80px;height:80px;margin:0 8px 8px 0;background-color:#f7f8fa;border-radius:8px}.van-uploader__upload:active{background-color:#f2f3f5}.van-uploader__upload-icon{color:#dcdee0;font-size:24px}.van-uploader__upload-text{margin-top:8px;color:#969799;font-size:12px}.van-uploader__upload--disabled{opacity:.5;opacity:var(--uploader-disabled-opacity,.5)}.van-uploader__preview{position:relative;margin:0 8px 8px 0;cursor:pointer}.van-uploader__preview-image{display:block;width:80px;height:80px;overflow:hidden;border-radius:8px}.van-uploader__preview-delete{position:absolute;top:-8px;right:-8px;color:#969799;font-size:18px;background-color:#fff;border-radius:100%}.van-uploader__file{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;width:80px;height:80px;background-color:#f7f8fa;border-radius:8px}.van-uploader__file-icon{color:#646566;font-size:20px}.van-uploader__file-name{box-sizing:border-box;width:100%;margin-top:8px;padding:0 4px;color:#646566;font-size:12px;text-align:center}.van-uploader__mask{position:absolute;top:0;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;color:#fff;background-color:rgba(50,50,51,.88);border-radius:8px}.van-uploader__mask-icon{font-size:22px}.van-uploader__mask-message{margin-top:6px;padding:0 4px;font-size:12px;line-height:14px}.van-uploader__loading{width:22px;height:22px;color:#fff}
\ No newline at end of file
export declare const chooseImageProps: {
sizeType: {
type: ArrayConstructor;
value: string[];
};
capture: {
type: ArrayConstructor;
value: string[];
};
};
export declare const chooseVideoProps: {
capture: {
type: ArrayConstructor;
value: string[];
};
compressed: {
type: BooleanConstructor;
value: boolean;
};
maxDuration: {
type: NumberConstructor;
value: number;
};
camera: {
type: StringConstructor;
value: string;
};
};
// props for choose image
export const chooseImageProps = {
sizeType: {
type: Array,
value: ['original', 'compressed'],
},
capture: {
type: Array,
value: ['album', 'camera'],
},
};
// props for choose video
export const chooseVideoProps = {
capture: {
type: Array,
value: ['album', 'camera'],
},
compressed: {
type: Boolean,
value: true,
},
maxDuration: {
type: Number,
value: 60,
},
camera: {
type: String,
value: 'back',
},
};
/// <reference types="miniprogram-api-typings" />
interface File {
path: string;
url: string;
size: number;
name: string;
type: string;
time: number;
image: boolean;
}
export declare function isImageFile(item: File): boolean;
export declare function isVideo(
res: any,
accept: string
): res is WechatMiniprogram.ChooseVideoSuccessCallbackResult;
export declare function chooseFile({
accept,
multiple,
capture,
compressed,
maxDuration,
sizeType,
camera,
maxCount,
}: {
accept: any;
multiple: any;
capture: any;
compressed: any;
maxDuration: any;
sizeType: any;
camera: any;
maxCount: any;
}): Promise<
| WechatMiniprogram.ChooseImageSuccessCallbackResult
| WechatMiniprogram.ChooseMediaSuccessCallbackResult
| WechatMiniprogram.ChooseVideoSuccessCallbackResult
| WechatMiniprogram.ChooseMessageFileSuccessCallbackResult
>;
export declare function isFunction(val: unknown): val is Function;
export declare function isObject(val: any): val is Record<any, any>;
export declare function isPromise<T = any>(val: unknown): val is Promise<T>;
export {};
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
function isImageUrl(url) {
return IMAGE_REGEXP.test(url);
}
export function isImageFile(item) {
if (item.type) {
return item.type.indexOf('image') === 0;
}
if (item.path) {
return isImageUrl(item.path);
}
if (item.url) {
return isImageUrl(item.url);
}
return false;
}
export function isVideo(res, accept) {
return accept === 'video';
}
export function chooseFile({
accept,
multiple,
capture,
compressed,
maxDuration,
sizeType,
camera,
maxCount,
}) {
switch (accept) {
case 'image':
return new Promise((resolve, reject) => {
wx.chooseImage({
count: multiple ? Math.min(maxCount, 9) : 1,
sourceType: capture,
sizeType,
success: resolve,
fail: reject,
});
});
case 'media':
return new Promise((resolve, reject) => {
wx.chooseMedia({
count: multiple ? Math.min(maxCount, 9) : 1,
sourceType: capture,
maxDuration,
sizeType,
camera,
success: resolve,
fail: reject,
});
});
case 'video':
return new Promise((resolve, reject) => {
wx.chooseVideo({
sourceType: capture,
compressed,
maxDuration,
camera,
success: resolve,
fail: reject,
});
});
default:
return new Promise((resolve, reject) => {
wx.chooseMessageFile({
count: multiple ? maxCount : 1,
type: 'file',
success: resolve,
fail: reject,
});
});
}
}
export function isFunction(val) {
return typeof val === 'function';
}
export function isObject(val) {
return val !== null && typeof val === 'object';
}
export function isPromise(val) {
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
}
/* eslint-disable */
var REGEXP = getRegExp('^\d+(\.\d+)?$');
function addUnit(value) {
if (value == null) {
return undefined;
}
return REGEXP.test('' + value) ? value + 'px' : value;
}
module.exports = {
addUnit: addUnit
};
/* eslint-disable */
var bem = require('./bem.wxs').bem; var bem = require('./bem.wxs').bem;
var memoize = require('./memoize.wxs').memoize; var memoize = require('./memoize.wxs').memoize;
var addUnit = require('./add-unit.wxs').addUnit;
function isSrc(url) {
return url.indexOf('http') === 0 || url.indexOf('data:image') === 0 || url.indexOf('//') === 0;
}
module.exports = { module.exports = {
bem: memoize(bem), bem: memoize(bem),
isSrc: isSrc, memoize: memoize,
memoize: memoize addUnit: addUnit
}; };
<style lang="less">
</style>
<template>
<view>我的抽奖</view>
</template>
<script>
import wepy from '@wepy/core';
wepy.page({
});
</script>
<style lang="less">
</style>
<template>
<view>问题反馈</view>
</template>
<script>
import wepy from '@wepy/core';
wepy.page({
});
</script>
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
} }
.userInfo{ .userInfo{
position: fixed; position: fixed;
z-index: 9; z-index: 10;
top:100rpx; top:100rpx;
left: 30rpx; left: 30rpx;
} }
...@@ -170,22 +170,21 @@ ...@@ -170,22 +170,21 @@
<view class="video-wrapper"> <view class="video-wrapper">
<van-dialog id="van-dialog" /> <van-dialog id="van-dialog" />
<view id="myvideo"> <view id="myvideo">
<van-notify id="van-notify" />
<video-list :videoList.sync="videoList" :total="total" bindchange="changeVideo"> <video-list :videoList.sync="videoList" :total="total" bindchange="changeVideo">
</video-list> </video-list>
</view> </view>
<view class="userInfo" style="{{userImgStyle}}"> <view class="userInfo" style="{{userImgStyle}}" @tap="showMenu(!showMenus)">
<image src="{{userInfo.avatarUrl}}" mode="cover" class="userimage"></image> <image src="{{userInfo.avatarUrl}}" mode="cover" class="userimage"></image>
</view> </view>
<view> <view>
<video-gold type="gold" :des="goldNum" :gold="sign"></video-gold> <video-gold type="gold" :des="goldNum" :gold="sign"></video-gold>
<video-sign type="sign" des="签到" :sign="sign" @sign-in="signIn"></video-sign> <video-sign type="sign" des="签到" :sign="sign" @sign-in="signIn"></video-sign>
<video-lottery type="lottery" des="抽奖" @tap="getAwards"></video-lottery> <video-lottery type="lottery" des="抽奖" @tap="getAwards"></video-lottery>
<video-share type="share"></video-share> <video-share type="share" des="分享"></video-share>
</view> </view>
<view class="content"> <view class="content">
<view class="leftcont"> <view class="leftcont">
<button bindtap="toTest">点击去领奖</button>
<swiper class="list-wrapper" vertical="true" circular="true" display-multiple-items="2" autoplay="true" interval="1500"> <swiper class="list-wrapper" vertical="true" circular="true" display-multiple-items="2" autoplay="true" interval="1500">
<swiper-item wx:for="{{adlist}}" wx:key="index" catch:touchmove> <swiper-item wx:for="{{adlist}}" wx:key="index" catch:touchmove>
<view class="imgwrap"> <view class="imgwrap">
...@@ -231,19 +230,22 @@ ...@@ -231,19 +230,22 @@
<button open-type="getUserInfo" bindgetuserinfo="getUserInfo">授权并进入</button> <button open-type="getUserInfo" bindgetuserinfo="getUserInfo">授权并进入</button>
</view> </view>
</view> </view>
<network v-if="!isConnected"></network> <network v-if="isConnected === false"></network>
<!-- <star-animation></star-animation> --> <open-animation :isWin="true"></open-animation>
<star-animation1 v-if="sign && showAnimation"></star-animation1> <popup @showMenu="showMenu" :showMenus="showMenus"></popup>
<open-animation></open-animation> <!-- <shared-popup></shared-popup> -->
</view> </view>
</template> </template>
<script> <script>
let touchDotX = 0, touchDotY = 0; let touchDotX = 0, touchDotY = 0;
let timeout = null;
let timeout1 = null;
import store from '../store'; import store from '../store';
import { mapState, mapActions } from '@wepy/x'; import { mapState, mapActions } from '@wepy/x';
import wepy from '@wepy/core'; import wepy from '@wepy/core';
import Dialog from '../components/vant/dialog/dialog'; import Dialog from '../components/vant/dialog/dialog';
import Notify from '../components/vant/notify/notify';
wepy.page({ wepy.page({
store, store,
hooks: { hooks: {
...@@ -251,22 +253,25 @@ ...@@ -251,22 +253,25 @@
}, },
data: { data: {
list:[], //商品list list: [], // 商品list
adlist:[], adlist: [],
current:5, //商品列表初次展示第几个 current: 5, // 商品列表初次展示第几个
// userInfo: {}, // userInfo: {},
swiperItem:2, swiperItem: 2,
videoList:[], videoList: [],
length: 4, length: 4,
circular:false, // 商品是否无限循环 circular: false, // 商品是否无限循环
topPage:0, topPage: 0,
lastPage:0, lastPage: 0,
currentIndex:5, //商品当前滑动到第几个 currentIndex: 5, // 商品当前滑动到第几个
authmodal:false, authmodal: false,
sign: false, sign: false,
showAnimation: false, showAnimation: false,
userImgStyle:'', userImgStyle: '',
goldNum:2500, goldStyle: '',
goldNum: 50000,
awards: false,
showMenus: false
}, },
computed: { computed: {
...@@ -275,36 +280,36 @@ ...@@ -275,36 +280,36 @@
methods: { methods: {
...mapActions([ 'setIsConnected', 'setUserInfo' ]), ...mapActions([ 'setIsConnected', 'setUserInfo' ]),
moveSwiper(e){ moveSwiper(e) {
if(e.$wx.detail.source == 'touch') { if (e.$wx.detail.source == 'touch') {
let current = e.$wx.detail.current; let current = e.$wx.detail.current;
this.currentIndex = current; this.currentIndex = current;
} }
}, },
swipermoveDone(e){ swipermoveDone(e) {
if(e.$wx.detail.source == 'touch') { if (e.$wx.detail.source == 'touch') {
let current = e.$wx.detail.current; let current = e.$wx.detail.current;
let totalPage = 3; let totalPage = 3;
let nextlist=[ let nextlist = [
{value:11,text: '白色条纹马克杯,马克吐温同款11', imgsrc:'/static/images/test1.jpg', price:'¥9.89',people:2200,sku:'100004549235'}, {value: 11, text: '白色条纹马克杯,马克吐温同款11', imgsrc: '/static/images/test1.jpg', price: '¥9.89', people: 2200, sku: '100004549235'},
{value:12,text: '白色条纹马克杯,马克吐温同款12', imgsrc:'/static/images/test2.png', price:'¥19.20',people:'2200',sku:'100004549235'}, {value: 12, text: '白色条纹马克杯,马克吐温同款12', imgsrc: '/static/images/test2.png', price: '¥19.20', people: '2200', sku: '100004549235'},
{value:13,text: '白色条纹马克杯,马克吐温同款13', imgsrc:'/static/images/peo1.jpg', price:'¥39.08',people:2200,sku:'100004549235'}, {value: 13, text: '白色条纹马克杯,马克吐温同款13', imgsrc: '/static/images/peo1.jpg', price: '¥39.08', people: 2200, sku: '100004549235'},
{value:14,text: '白色条纹马克杯,马克吐温同款14', imgsrc:'/static/images/peo2.jpg', price:'¥599.20',people:2200,sku:'100004549235'}, {value: 14, text: '白色条纹马克杯,马克吐温同款14', imgsrc: '/static/images/peo2.jpg', price: '¥599.20', people: 2200, sku: '100004549235'},
{value:15,text: '白色条纹马克杯,马克吐温同款15', imgsrc:'/static/images/peo3.jpg', price:'¥2399.01',people:2200,sku:'100004549235'}, {value: 15, text: '白色条纹马克杯,马克吐温同款15', imgsrc: '/static/images/peo3.jpg', price: '¥2399.01', people: 2200, sku: '100004549235'}
]; ];
let that = this; let that = this;
function debounce(func,wait) { function debounce(func, wait) {
let timeout; let timeout;
return function () { return function () {
if (timeout) clearTimeout(timeout); if (timeout) clearTimeout(timeout);
let callNow = !timeout; let callNow = !timeout;
timeout = setTimeout(func, wait) timeout = setTimeout(func, wait);
if (callNow) func(); if (callNow) func();
};
} }
} /* if(current <= 2) {
/*if(current <= 2) {
debounce(setTimeout(function(){ debounce(setTimeout(function(){
that.topPage +=1; that.topPage +=1;
if(that.lastPage+that.topPage >= totalPage) { if(that.lastPage+that.topPage >= totalPage) {
...@@ -315,35 +320,35 @@ ...@@ -315,35 +320,35 @@
// that.current = current+1; // that.current = current+1;
// that.currentIndex = current+1; // that.currentIndex = current+1;
},1000),500); },1000),500);
}*/ } */
if(current >= this.list.length-3) { if (current >= this.list.length - 3) {
debounce(setTimeout(function(){ debounce(setTimeout(function() {
that.lastPage +=1; that.lastPage += 1;
if(that.lastPage+that.topPage >= totalPage) { if (that.lastPage + that.topPage >= totalPage) {
that.circular = true; that.circular = true;
return; return;
} }
that.list = [ ...that.list,...nextlist]; that.list = [ ...that.list, ...nextlist];
},1000),500) }, 1000), 500);
} }
} }
}, },
toViewPage(e) { toViewPage(e) {
let item = e.$wx.currentTarget.dataset.item let item = e.$wx.currentTarget.dataset.item;
// console.log(sku,12) // console.log(sku,12)
//解决长按触发tap事件的bug // 解决长按触发tap事件的bug
wx.navigateToMiniProgram({ wx.navigateToMiniProgram({
appId: 'wx91d27dbf599dff74', appId: 'wx91d27dbf599dff74',
path: 'pages/item/detail/detail?sku='+item.sku, // 跳转小程序的路径 path: 'pages/item/detail/detail?sku=' + item.sku, // 跳转小程序的路径
// 有效值 develop(开发版),trial(体验版),release(正式版) // 有效值 develop(开发版),trial(体验版),release(正式版)
envVersion: 'release', envVersion: 'release',
success(res) { success(res) {
console.log('跳转成功'); console.log('跳转成功');
} }
}) });
/* wx.navigateTo({ /* wx.navigateTo({
url: '/pages/auth' url: '/pages/auth'
});*/ }); */
}, },
touchStart (event) { touchStart (event) {
touchDotX = event.touches[0].pageX; // 获取触摸时的原点 touchDotX = event.touches[0].pageX; // 获取触摸时的原点
...@@ -367,7 +372,7 @@ ...@@ -367,7 +372,7 @@
// 手指离开屏幕时记录的坐标 // 手指离开屏幕时记录的坐标
let touchMoveX = event.changedTouches[0].pageX; let touchMoveX = event.changedTouches[0].pageX;
let touchMoveY = event.changedTouches[0].pageY; let touchMoveY = event.changedTouches[0].pageY;
let current = event.currentTarget.dataset let current = event.currentTarget.dataset;
// 起始点的坐标(x0,y0)和手指离开时的坐标(x1,y1)之差 // 起始点的坐标(x0,y0)和手指离开时的坐标(x1,y1)之差
let tmX = touchMoveX - touchDotX; let tmX = touchMoveX - touchDotX;
let tmY = touchMoveY - touchDotY; let tmY = touchMoveY - touchDotY;
...@@ -395,7 +400,7 @@ ...@@ -395,7 +400,7 @@
} }
}, },
getUserInfo (e) { getUserInfo (e) {
if(e.$wx.detail.userInfo) { if (e.$wx.detail.userInfo) {
this.setUserInfo(e.$wx.detail.userInfo); this.setUserInfo(e.$wx.detail.userInfo);
this.authmodal = false; this.authmodal = false;
} }
...@@ -403,11 +408,11 @@ ...@@ -403,11 +408,11 @@
changeVideo(e) { changeVideo(e) {
this.setIsConnected(); this.setIsConnected();
console.log(this.length, e.activeId); console.log(this.length, e.activeId);
if (this.length - e.activeId === 1) { // if (this.length - e.activeId === 1) {
this.videoList = [{id: e.activeId + 2, url: 'https://ip1707952229.mobgslb.tbcache.com/youku/6974c3708c0337150e1743b1c/03000801005EA2A6C8FB4C2003E8807282A547-8207-4F52-9663-969096765248.mp4?sid=158960247500010009412_00_Bac09720260d484f23ac2ccebe5206930&sign=b76f4099e108fc306d3db993d1bec0a8&ctype=50&ali_redirect_domain=vali.cp31.ott.cibntv.net&ali_redirect_ex_ftag=5898cd25832bbff232de6d9fa668e8ddf8bacc5fef3f2e7b&ali_redirect_ex_tmining_ts=1589602477&ali_redirect_ex_tmining_expire=3600&ali_redirect_ex_hot=111'}]; // this.videoList = [{id: e.activeId + 2, url: 'https://ip1707952229.mobgslb.tbcache.com/youku/6974c3708c0337150e1743b1c/03000801005EA2A6C8FB4C2003E8807282A547-8207-4F52-9663-969096765248.mp4?sid=158960247500010009412_00_Bac09720260d484f23ac2ccebe5206930&sign=b76f4099e108fc306d3db993d1bec0a8&ctype=50&ali_redirect_domain=vali.cp31.ott.cibntv.net&ali_redirect_ex_ftag=5898cd25832bbff232de6d9fa668e8ddf8bacc5fef3f2e7b&ali_redirect_ex_tmining_ts=1589602477&ali_redirect_ex_tmining_expire=3600&ali_redirect_ex_hot=111'}];
this.length += 1; // this.length += 1;
console.log('add video'); // console.log('add video');
} // }
}, },
deleteAnimation (current) { deleteAnimation (current) {
if (current && current.itemid != undefined) { if (current && current.itemid != undefined) {
...@@ -421,12 +426,12 @@ ...@@ -421,12 +426,12 @@
}); });
this.list = list; this.list = list;
let that = this; let that = this;
//如果剩下4个就不让他循环了,这时候就一屏显示出来了 // 如果剩下4个就不让他循环了,这时候就一屏显示出来了
if(list.length <= 4) { if (list.length <= 4) {
this.circular = false; this.circular = false;
} }
if(current.itemid >= list.length -1) { if (current.itemid >= list.length - 1) {
this.current = this.currentIndex -1; this.current = this.currentIndex - 1;
} }
setTimeout(function() { setTimeout(function() {
let newlist = that.list.filter((item, index) => index != current.itemid); let newlist = that.list.filter((item, index) => index != current.itemid);
...@@ -462,19 +467,26 @@ ...@@ -462,19 +467,26 @@
timeout = null; timeout = null;
timeout1 = null; timeout1 = null;
} else { } else {
const innerAudioContext = wx.createInnerAudioContext();
innerAudioContext.autoplay = true;
innerAudioContext.src = '/static/audio/supermarie.mp3';
innerAudioContext.onPlay(() => {
console.log('开始播放');
});
innerAudioContext.onError((res) => {
console.log(res.errMsg);
console.log(res.errCode);
});
timeout = setTimeout(() => { timeout = setTimeout(() => {
that.showAnimation = that.sign; that.showAnimation = that.sign;
timeout1 = setTimeout(() => { timeout1 = setTimeout(() => {
const num = [1, 2, 4, 501, 2501, 5001]; const num = [1, 2, 4, 501, 2501, 5001];
that.goldNum = num[Math.floor(Math.random() * 6)]; that.goldNum = 1;
}, 1000); }, 600);
}, 1300); }, 1100);
} }
} else { } else {
Dialog.alert({ Notify({ backgroundColor: '#ff976a', text: '签到必须同意推送授权', safeAreaInsetTop: true });
title: '订阅通知',
message: '签到必须同意推送提醒!'
});
} }
} }
}, },
...@@ -494,31 +506,29 @@ ...@@ -494,31 +506,29 @@
imageUrl: '', imageUrl: '',
success: function(res) { success: function(res) {
let shareId = res.shareTickets[0]; let shareId = res.shareTickets[0];
console.log('shareId', shareId) console.log('shareId', shareId);
// 转发成功 // 转发成功
console.log(res) console.log(res);
}, },
fail: function(res) { fail: function(res) {
// 转发失败 // 转发失败
console.log(res) console.log(res);
}
} }
};
}, },
getAwards: function() { getAwards: function() {
wx.navigateTo({ wx.navigateTo({
url: '/pages/raffle?id=1&progress=70&chance=1/780&corn=50000&imgsrc=/static/images/test2.png&goods=Nintendo Switch任天堂游戏机任天堂游戏机' url: '/pages/raffle?id=1&progress=70&chance=1/780&corn=50000&imgsrc=/static/images/test2.png&goods=Nintendo Switch任天堂游戏机任天堂游戏机'
}); });
// this.awards = !this.awards; // this.awards = !this.awards;
}, }
toTest() {
wx.navigateTo({url:'/pages/myraffles'})
},
}, },
created () { created () {
let self = this; let self = this;
let statusHeight = this.$app.$options.globalData.statusBarHeight || ''; let statusHeight = this.$app.$options.globalData.statusBarHeight || '';
statusHeight && (this.userImgStyle = 'top:'+statusHeight+'px') statusHeight && (this.userImgStyle = 'top:' + statusHeight + 'px');
console.log(this.userImgStyle);
if (store.state.userInfo) { if (store.state.userInfo) {
this.userInfo = store.state.userInfo; this.userInfo = store.state.userInfo;
} else { } else {
...@@ -530,16 +540,16 @@ ...@@ -530,16 +540,16 @@
}); });
} }
this.list = [ this.list = [
{value: 1, text: '白色条纹马克杯,马克吐温同款1', imgsrc:'/static/images/test1.jpg', price:'¥399.00',people:2200,sku:'100004549235'}, {value: 1, text: '白色条纹马克杯,马克吐温同款1', imgsrc: '/static/images/test1.jpg', price: '¥399.00', people: 2200, sku: '100004549235'},
{value: 2, text: '白色条纹马克杯,马克吐温同款2', imgsrc:'/static/images/test2.png', price:'¥1399.22',people:2200,sku:'2004203'}, {value: 2, text: '白色条纹马克杯,马克吐温同款2', imgsrc: '/static/images/test2.png', price: '¥1399.22', people: 2200, sku: '2004203'},
{value: 3, text: '白色条纹马克杯,马克吐温同款3', imgsrc:'/static/images/peo1.jpg', price:'¥199.22',people:2200,sku:'17818909707'}, {value: 3, text: '白色条纹马克杯,马克吐温同款3', imgsrc: '/static/images/peo1.jpg', price: '¥199.22', people: 2200, sku: '17818909707'},
{value: 4, text: '白色条纹马克杯,马克吐温同款4', imgsrc:'/static/images/peo2.jpg', price:'¥134.12',people:2200,sku:'67704484242'}, {value: 4, text: '白色条纹马克杯,马克吐温同款4', imgsrc: '/static/images/peo2.jpg', price: '¥134.12', people: 2200, sku: '67704484242'},
{value: 5, text: '白色条纹马克杯,马克吐温同款5', imgsrc:'/static/images/peo3.jpg', price:'¥194.22',people:2200,sku:'100004549235'}, {value: 5, text: '白色条纹马克杯,马克吐温同款5', imgsrc: '/static/images/peo3.jpg', price: '¥194.22', people: 2200, sku: '100004549235'},
{value: 6, text: '白色条纹马克杯,马克吐温同款6', imgsrc:'/static/images/peo1.jpg', price:'¥292.22',people:2200,sku:'100004549235'}, {value: 6, text: '白色条纹马克杯,马克吐温同款6', imgsrc: '/static/images/peo1.jpg', price: '¥292.22', people: 2200, sku: '100004549235'},
{value: 7, text: '白色条纹马克杯,马克吐温同款7', imgsrc:'/static/images/test1.jpg', price:'¥1399.92',people:2200,sku:'100004549235'}, {value: 7, text: '白色条纹马克杯,马克吐温同款7', imgsrc: '/static/images/test1.jpg', price: '¥1399.92', people: 2200, sku: '100004549235'},
{value: 8, text: '白色条纹马克杯,马克吐温同款8', imgsrc:'/static/images/test2.png', price:'¥1399.98',people:2200,sku:'100004549235'}, {value: 8, text: '白色条纹马克杯,马克吐温同款8', imgsrc: '/static/images/test2.png', price: '¥1399.98', people: 2200, sku: '100004549235'},
{value: 9, text: '白色条纹马克杯,马克吐温同款9', imgsrc:'/static/images/peo3.jpg', price:'¥1399.78',people:2200,sku:'100004549235'}, {value: 9, text: '白色条纹马克杯,马克吐温同款9', imgsrc: '/static/images/peo3.jpg', price: '¥1399.78', people: 2200, sku: '100004549235'},
{value: 10, text: '白色条纹马克杯,马克吐温同款10', imgsrc:'/static/images/peo2.jpg', price:'¥1399.67',people:2200,sku:'100004549235'} {value: 10, text: '白色条纹马克杯,马克吐温同款10', imgsrc: '/static/images/peo2.jpg', price: '¥1399.67', people: 2200, sku: '100004549235'}
]; ];
let urls = [ let urls = [
// 'https://www.apple.com/105/media/us/iphone-x/2017/01df5b43-28e4-4848-bf20-490c34a926a7/films/feature/iphone-x-feature-tpl-cc-us-20170912_1920x1080h.mp4', // 'https://www.apple.com/105/media/us/iphone-x/2017/01df5b43-28e4-4848-bf20-490c34a926a7/films/feature/iphone-x-feature-tpl-cc-us-20170912_1920x1080h.mp4',
...@@ -571,8 +581,8 @@ ...@@ -571,8 +581,8 @@
{imgsrc: '/static/images/test1.jpg', text: '小8刚刚参与了抽奖'} {imgsrc: '/static/images/test1.jpg', text: '小8刚刚参与了抽奖'}
]; ];
// console.log(this.$app.$options.globalData.info,111) // console.log(this.$app.$options.globalData.info,111)
//如果已经存在store里就不用再获取用户信息了 // 如果已经存在store里就不用再获取用户信息了
if(this.userInfo) return; if (this.userInfo) return;
wx.getSetting({ wx.getSetting({
success: res => { success: res => {
if (res.authSetting['scope.userInfo']) { if (res.authSetting['scope.userInfo']) {
...@@ -580,7 +590,7 @@ ...@@ -580,7 +590,7 @@
wx.getUserInfo({ wx.getUserInfo({
success: res => { success: res => {
// 可以将 res 发送给后台解码出 unionId // 可以将 res 发送给后台解码出 unionId
if(res.userInfo) { if (res.userInfo) {
that.setUserInfo(res.userInfo); that.setUserInfo(res.userInfo);
// that.userInfo = res.userInfo; // that.userInfo = res.userInfo;
} }
...@@ -588,22 +598,22 @@ ...@@ -588,22 +598,22 @@
// 所以此处加入 callback 以防止这种情况 // 所以此处加入 callback 以防止这种情况
if (that.userInfoReadyCallback) { if (that.userInfoReadyCallback) {
that.userInfoReadyCallback(res => { that.userInfoReadyCallback(res => {
that.setUserInfo(res.userInfo||{}); that.setUserInfo(res.userInfo || {});
// that.userInfo = res.userInfo||{}; // that.userInfo = res.userInfo||{};
}) });
} }
} }
}) });
}else{ } else {
that.authmodal = true; that.authmodal = true;
} }
} }
}); });
}, },
onShow() { onShow() {
//从其他小程序回来可以在当前生命周期检测到,但是这个方法,自己的小程序页面返回也会进入 // 从其他小程序回来可以在当前生命周期检测到,但是这个方法,自己的小程序页面返回也会进入
console.log('页面show!!') console.log('页面show!!');
}, }
}); });
</script> </script>
<config> <config>
...@@ -619,9 +629,10 @@ ...@@ -619,9 +629,10 @@
'video-share': '~@/components/custom/sign', 'video-share': '~@/components/custom/sign',
'video-lottery': '~@/components/custom/sign', 'video-lottery': '~@/components/custom/sign',
'network': '~@/components/custom/network', 'network': '~@/components/custom/network',
'star-animation': '~@/components/custom/starAnimation',
'star-animation1': '~@/components/custom/starAnimation1',
'open-animation': '~@/components/custom/openAnimation', 'open-animation': '~@/components/custom/openAnimation',
'popup': '~@/components/custom/popup',
'van-notify': '~@/components/vant/notify/index',
'shared-popup': '~@/components/custom/sharedPopup'
}, },
navigationStyle: "custom", navigationStyle: "custom",
"navigateToMiniProgramAppIdList":[ "navigateToMiniProgramAppIdList":[
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
</view> </view>
</view> </view>
<van-popup show="{{ showAddress }}" position="bottom" bind:close="onClose"> <van-popup show="{{ showAddress }}" position="bottom" bind:close="onClose">
<van-area area-list="{{ areaList }}" value="110101" bind:confirm="getaddress" bind:cancel="onClose"/> <van-area area-list="{{ areaList }}" value="110101" bind:confirm="getaddress" bind:cancel="onClose" title="请选择地区"/>
</van-popup> </van-popup>
<view class="footerheight"></view> <view class="footerheight"></view>
<view class="footer"> <view class="footer">
......
...@@ -140,14 +140,14 @@ ...@@ -140,14 +140,14 @@
import Notify from '../components/vant/notify/notify'; import Notify from '../components/vant/notify/notify';
wepy.page({ wepy.page({
data: { data: {
progress:0, progress: 0,
progressStyle:'', progressStyle: '',
isCheck:false, isCheck: false,
id:null, id: null,
corn:'', corn: '',
goods:'', goods: '',
chance:'', chance: '',
goodsimg:'', goodsimg: ''
}, },
methods: { methods: {
check() { check() {
...@@ -179,32 +179,32 @@ ...@@ -179,32 +179,32 @@
let imgsrc = '/static/images/selected.png'; let imgsrc = '/static/images/selected.png';
if(this.isCheck) { if(this.isCheck) {
imgsrc = '/static/images/selected.png'; imgsrc = '/static/images/selected.png';
}else { } else {
imgsrc = '/static/images/selectno.png'; imgsrc = '/static/images/selectno.png';
} }
return imgsrc return imgsrc;
}, },
opentype() { opentype() {
if(this.isCheck) { if (this.isCheck) {
return 'getPhoneNumber' return 'getPhoneNumber';
}else { } else {
return '' return '';
} }
} }
}, },
onLoad (query) { onLoad (query) {
console.log(query); console.log(query);
let {id,corn,goods,chance,imgsrc,progress} = query; let {id, corn, goods, chance, imgsrc, progress} = query;
if(progress) { if (progress) {
this.progress = progress; this.progress = progress;
this.progressStyle = 'width:'+progress+'%'; this.progressStyle = 'width:' + progress + '%';
} }
this.id = id; this.id = id;
this.corn = corn; this.corn = corn;
this.goods = goods; this.goods = goods;
this.chance = chance; this.chance = chance;
this.goodsimg = imgsrc; this.goodsimg = imgsrc;
}, }
}); });
</script> </script>
<config> <config>
......
...@@ -2,7 +2,9 @@ import Vuex from '@wepy/x'; ...@@ -2,7 +2,9 @@ import Vuex from '@wepy/x';
export default new Vuex.Store({ export default new Vuex.Store({
state: { state: {
userInfo: null, userInfo: {
avatarUrl: '/static/images/user@2x.png'
},
isConnected: true isConnected: true
}, },
mutations: { mutations: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment