Commit ed38b1a6 authored by 郝聪敏's avatar 郝聪敏

替换vant版本;新增分享、抽奖弹窗

parent 36b4ed06
......@@ -6248,11 +6248,6 @@
"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": {
"version": "1.10.0",
"resolved": "http://npmprivate.quantgroups.com/verror/-/verror-1.10.0.tgz",
......
......@@ -18,8 +18,7 @@
"license": "MIT",
"dependencies": {
"@wepy/core": "^2.0.0-alpha.16",
"@wepy/x": "^2.0.2",
"vant-weapp": "^0.5.28"
"@wepy/x": "^2.0.2"
},
"devDependencies": {
"@wepy/cli": "^2.0.0-alpha.28",
......
......@@ -5,7 +5,7 @@
</style>
<script>
import wepy from '@wepy/core';
import eventHub from './common/eventHub';
import http from './common/wxRequest';
import vuex from '@wepy/x';
wepy.use(vuex);
......@@ -18,13 +18,25 @@ wepy.app({
statusBarHeight: ''
},
onLaunch() {
// this.$options.globalData.info = '333';
let that = this;
wx.getSystemInfo({
success: function (res) {
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({
success () {
console.log('已登录');
......@@ -56,7 +68,10 @@ wepy.app({
{
pages: [
'pages/index',
'pages/raffle'
'pages/raffle',
'pages/awards',
'pages/help',
'pages/feedback'
],
window: {
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');
if (!isConnected) {
wx.showToast({
......@@ -11,20 +19,49 @@ const wxRequest = async (params = {}, url) => {
});
return;
}
// tip.loading()
let data = params.query || {};
const header = params.header || {};
let res = await wepy.request({
const promise = new Promise((resolve, reject) => {
wepy.request({
url: url,
method: params.method || 'GET',
data: data,
header: header
data: options.data,
method: options.method,
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()
console.log('wxRequest', res);
return res;
});
return promise;
};
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 = {
wxRequest
post: post,
get: get,
request
};
This diff is collapsed.
<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>
<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">
<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>
......@@ -10,7 +11,7 @@
<div v-if="type === 'gold'" class="gold">
<div class="add-gold" v-if="addGold">
<image class="add-gold-image" :src="addGoldUrl"></image>
<span class="add-gold-num">+1</span>
<span class="add-gold-num">+10</span>
</div>
<div class="show-gold" @tap="showAnimation">
<div class="sunshine" v-if="addsunshine"></div>
......@@ -24,6 +25,7 @@
<button open-type="share" plain="true" class="share-button">
<image class="share-image" :src="shareUrl"></image>
</button>
<span class="title">{{des}}</span>
</div>
<div v-if="type === 'lottery'" class="lottery">
<image class="lottery-image" :src="lotteryUrl"></image>
......@@ -60,7 +62,9 @@
signNotCompletedUrl: '/static/images/sign@2x.png',
signCompletedUrl: '/static/images/sign-completed@2x-70_70px.png',
shareUrl: '/static/images/share@2x.png',
lotteryUrl: '/static/images/lottery@2x.png'
lotteryUrl: '/static/images/lottery@2x.png',
containerStyle: '',
flyAnimation: false
},
props: {
title: '',
......@@ -125,14 +129,16 @@
},
sign(v) {
this.signComplete = false;
this.flyAnimation = false;
console.log(v, this.signComplete);
if (!v) {
timeout = null;
} else {
timeout = setTimeout(() => {
this.signComplete = true;
this.flyAnimation = true;
console.log('signComplete');
}, 1300);
}, 1100);
}
}
},
......@@ -149,7 +155,9 @@
}
},
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>
......@@ -158,8 +166,8 @@
.lottery {
position: absolute;
top: 513rpx;
right: 30rpx;
top: 469rpx;
right: 32rpx;
.lottery-image {
display: flex;
width: 78rpx;
......@@ -176,8 +184,8 @@
.share {
position: absolute;
top: 679rpx;
right: 33rpx;
top: 635rpx;
right: 32rpx;
.share-button {
width: 78rpx;
height: 70rpx;
......@@ -188,11 +196,18 @@
height: 70rpx;
}
}
.title {
width: 100%;
text-align: center;
display: block;
color: #fff;
font-size: 22rpx;
}
}
.sign {
position: absolute;
top: 356rpx;
top: 312rpx;
right: 32rpx;
width: 78rpx;
height: 78rpx;
......@@ -213,7 +228,7 @@
animation: jump 1.2s infinite ease;
}
.fly {
animation: fly1 1.2s forwards linear;
animation: fly1 1s forwards linear;
}
.sign-shine {
overflow: hidden;
......@@ -247,7 +262,7 @@
top: 65rpx;
border-radius: 50%;
z-index: -1;
animation: swift 1.2s infinite ease;
animation: swift 1s infinite ease;
}
.title {
......@@ -318,8 +333,8 @@
.gold {
position: absolute;
top: 270rpx;
left: 39rpx;
top: 130rpx;
left: 40rpx;
.add-gold{
position: absolute;
display: flex;
......@@ -329,19 +344,21 @@
// transform: translateY(-50rpx);
animation:addGold .6s ease-in forwards;
.add-gold-image {
width: 35rpx;
height: 35rpx;
width: 20rpx;
height: 20rpx;
vertical-align: middle;
animation:addGoldRotate .6s linear infinite;
}
.add-gold-num {
color: #fff;
font-size: 24rpx;
font-size: 16rpx;
vertical-align: middle;
}
}
@keyframes addGold {
0% { transform: translateY(-90rpx);}
99% { transform: translateY(-30rpx);opacity: 1;}
0% { transform: translateY(-45rpx);}
99% { transform: translateY(-20rpx);opacity: 1;}
100% { opacity: 0; }
}
......@@ -401,7 +418,8 @@
<config>
{
usingComponents: {
'van-icon': '~@/components/vant/icon/index'
'van-icon': '~@/components/vant/icon/index',
'star-animation': '~@/components/custom/starAnimation'
}
}
</config>
<template>
<div class="loading-container">
<!-- <div class="loading-container"> -->
<!-- <van-loading size="24px" vertical>加载中...</van-loading> -->
<div class="loader">
<div class="face">
<div class="circle"></div>
</div>
</div>
<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 {
// .loading-container {
// position: absolute;
// width: 100%;
// height: 100%;
// display: flex;
// justify-content: center;
// align-items: center;
// z-index: 1;
.meteor {
position: absolute;
width: 100%;
height: 100%;
background: grey;
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
.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;
top: 153rpx;
left: 94rpx;
width: calc(100% - 170rpx);;
height: 0;
// border: 2rpx solid #000;
z-index: 10;
transform: rotateZ(-2deg)
}
.circle {
.star {
position: absolute;
width: 50%;
height: 0.1em;
top: 50%;
left: 50%;
background-color: transparent;
transform: rotate(var(--deg));
transform-origin: left;
&::before {
left: -3rpx;
// bottom: -220rpx;
top: -4rpx;
// left: -43%;
height: 10rpx;
width: 150rpx;
background: linear-gradient(-45deg,rgba(255,255,255,0),yellow);
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;
top: -0.5em;
right: -0.5em;
content: '';
width: 1em;
height: 1em;
background-color: currentColor;
border-radius: 50%;
box-shadow: 0 0 2em,
0 0 4em,
0 0 6em,
0 0 8em,
0 0 10em,
0 0 0.5em rgba(255, 255, 0, 0.1);
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 .6s ease-in-out forwards;
}
@keyframes animate {
to {
transform: rotate(1turn);
.star:before {
transform: rotateZ(-2deg);
// 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.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>
<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>
import { VantComponent } from '../common/component';
import { safeArea } from '../mixins/safe-area';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [safeArea()],
mixins: [button, openType],
props: {
show: Boolean,
title: String,
cancelText: String,
customStyle: String,
overlayStyle: String,
description: String,
round: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 100
value: 100,
},
actions: {
type: Array,
value: []
value: [],
},
overlay: {
type: Boolean,
value: true
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true
}
value: true,
},
closeOnClickAction: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
methods: {
onSelect(event) {
......@@ -31,6 +43,9 @@ VantComponent({
const item = this.data.actions[index];
if (item && !item.disabled && !item.loading) {
this.$emit('select', item);
if (this.data.closeOnClickAction) {
this.onClose();
}
}
},
onCancel() {
......@@ -38,6 +53,10 @@ VantComponent({
},
onClose() {
this.$emit('close');
}
}
},
onClickOverlay() {
this.$emit('click-overlay');
this.onClose();
},
},
});
......@@ -3,14 +3,13 @@
<van-popup
show="{{ show }}"
position="bottom"
round="{{ round }}"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
custom-style="{{ customStyle }}"
overlay-style="{{ overlayStyle }}"
custom-class="van-action-sheet"
safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClose"
bind:close="onClickOverlay"
>
<view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
{{ title }}
......@@ -20,22 +19,39 @@
bind:click="onClose"
/>
</view>
<view wx:if="{{ description }}" class="van-action-sheet__description">
{{ description }}
</view>
<view wx:if="{{ actions && actions.length }}">
<!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
<button
wx:for="{{ actions }}"
wx:key="index"
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 || '' }}"
hover-class="van-action-sheet__item--hover"
data-index="{{ index }}"
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 }}">
{{ item.name }}
<text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
</block>
<van-loading wx:else size="20px" />
<van-loading wx:else custom-class="van-action-sheet__loading" size="20px" />
</button>
</view>
<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}
\ No newline at end of file
@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
......@@ -3,13 +3,29 @@ import { pickerProps } from '../picker/shared';
const COLUMNSPLACEHOLDERCODE = '000000';
VantComponent({
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,
value: {}
}, columnsNum: {
type: [String, Number],
value: 3
}, columnsPlaceholder: {
value: {},
observer: 'setValues',
},
columnsNum: {
type: null,
value: 3,
observer(value) {
this.setData({
displayColumns: this.data.columns.slice(0, +value),
});
},
},
columnsPlaceholder: {
type: Array,
observer(val) {
this.setData({
......@@ -17,26 +33,15 @@ VantComponent({
province: val[0] || '',
city: val[1] || '',
county: val[2] || '',
}
},
});
}
} }),
},
},
}),
data: {
columns: [{ values: [] }, { values: [] }, { values: [] }],
displayColumns: [{ values: [] }, { values: [] }, { values: [] }],
typeToColumnsPlaceholder: {}
},
watch: {
value(value) {
this.code = value;
this.setValues();
},
areaList: 'setValues',
columnsNum(value) {
this.set({
displayColumns: this.data.columns.slice(0, +value)
});
}
typeToColumnsPlaceholder: {},
},
mounted() {
setTimeout(() => {
......@@ -69,8 +74,7 @@ VantComponent({
const { columnsPlaceholder } = this.data;
return values.map((value, index) => {
// save undefined value
if (!value)
return value;
if (!value) return value;
value = JSON.parse(JSON.stringify(value));
if (!value.code || value.name === columnsPlaceholder[index]) {
value.code = '';
......@@ -82,13 +86,11 @@ VantComponent({
onChange(event) {
const { index, picker, value } = event.detail;
this.code = value[index].code;
let getValues = picker.getValues();
getValues = this.parseOutputValues(getValues);
this.setValues().then(() => {
this.$emit('change', {
picker,
values: getValues,
index
values: this.parseOutputValues(picker.getValues()),
index,
});
});
},
......@@ -103,23 +105,28 @@ VantComponent({
return result;
}
const list = this.getConfig(type);
result = Object.keys(list).map(code => ({
result = Object.keys(list).map((code) => ({
code,
name: list[code]
name: list[code],
}));
if (code) {
// oversea code
if (code[0] === '9' && type === 'city') {
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) {
// 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({
code: `${code}${codeFill}`,
name: typeToColumnsPlaceholder[type]
name: typeToColumnsPlaceholder[type],
});
}
return result;
......@@ -145,11 +152,9 @@ VantComponent({
if (!code) {
if (this.data.columnsPlaceholder.length) {
code = COLUMNSPLACEHOLDERCODE;
}
else if (Object.keys(county)[0]) {
} else if (Object.keys(county)[0]) {
code = Object.keys(county)[0];
}
else {
} else {
code = '';
}
}
......@@ -165,19 +170,27 @@ VantComponent({
if (city.length && code.slice(2, 4) === '00') {
[{ 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)
.catch(() => { })
.then(() => picker.setIndexes([
.catch(() => {})
.then(() =>
picker.setIndexes([
this.getIndex('province', code),
this.getIndex('city', code),
this.getIndex('county', code)
]))
.catch(() => { });
this.getIndex('county', code),
])
)
.catch(() => {});
},
getValues() {
const picker = this.getPicker();
return picker ? picker.getValues().filter(value => !!value) : [];
return picker ? picker.getValues().filter((value) => !!value) : [];
},
getDetail() {
const values = this.getValues();
......@@ -186,7 +199,7 @@ VantComponent({
country: '',
province: '',
city: '',
county: ''
county: '',
};
if (!values.length) {
return area;
......@@ -196,17 +209,16 @@ VantComponent({
if (area.code[0] === '9') {
area.country = names[1] || '';
area.province = names[2] || '';
}
else {
} else {
area.province = names[0] || '';
area.city = names[1] || '';
area.county = names[2] || '';
}
return area;
},
reset() {
this.code = '';
reset(code) {
this.code = code || '';
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';
VantComponent({
mixins: [button, openType],
classes: ['hover-class', 'loading-class'],
data: {
baseStyle: '',
},
props: {
icon: String,
color: String,
classPrefix: {
type: String,
value: 'van-icon',
},
plain: Boolean,
block: Boolean,
round: Boolean,
......@@ -15,24 +21,53 @@ VantComponent({
hairline: Boolean,
disabled: Boolean,
loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular',
},
type: {
type: String,
value: 'default'
value: 'default',
},
dataset: null,
size: {
type: String,
value: 'normal'
value: 'normal',
},
loadingSize: {
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: {
onClick() {
if (!this.data.disabled && !this.data.loading) {
if (!this.data.loading) {
this.$emit('click');
}
}
}
},
noop() {},
},
});
......@@ -2,11 +2,12 @@
<button
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' : '' }}"
open-type="{{ openType }}"
hover-class="van-button--active hover-class"
style="{{ color ? 'border-color: ' + color + ';' + (plain ? 'color: ' + color : 'color: #fff; background-color: ' + color) : '' }}"
lang="{{ lang }}"
style="{{ baseStyle }} {{ customStyle }}"
open-type="{{ disabled ? '' : openType }}"
business-id="{{ businessId }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
......@@ -15,7 +16,7 @@
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
aria-label="{{ ariaLabel }}"
bindtap="onClick"
bindtap="{{ !disabled ? 'onClick' : 'noop' }}"
bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber"
......@@ -27,12 +28,10 @@
<van-loading
custom-class="loading-class"
size="{{ loadingSize }}"
color="{{ type === 'default' ? '#c9c9c9' : '' }}"
type="{{ loadingType }}"
color="{{ loadingColor(type,color,plain) }}"
/>
<view
wx:if="{{ loadingText }}"
class="van-button__loading-text"
>
<view wx:if="{{ loadingText }}" class="van-button__loading-text">
{{ loadingText }}
</view>
</block>
......@@ -41,6 +40,7 @@
wx:if="{{ icon }}"
size="1.2em"
name="{{ icon }}"
class-prefix="{{ classPrefix }}"
class="van-button__icon"
custom-style="line-height: inherit;"
/>
......@@ -49,3 +49,19 @@
</view>
</block>
</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}
\ No newline at end of file
@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
<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({
desc: String,
thumb: String,
title: String,
price: String,
price: {
type: String,
observer: 'updatePrice',
},
centered: Boolean,
lazyLoad: Boolean,
thumbLink: String,
originPrice: String,
thumbMode: {
type: String,
value: 'aspectFit'
value: 'aspectFit',
},
currency: {
type: String,
value: '¥'
}
value: '¥',
},
},
methods: {
updatePrice() {
const { price } = this.data;
const priceArr = price.toString().split('.');
this.setData({
integerStr: priceArr[0],
decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
});
},
onClickThumb() {
this.jumpLink('thumbLink');
}
}
},
},
});
......@@ -21,7 +21,8 @@
</van-tag>
</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>
<slot wx:else name="title" />
......@@ -29,11 +30,15 @@
<slot wx:else name="desc" />
<slot name="tags" />
</view>
<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="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
<slot wx:else name="num" />
<slot name="bottom" />
</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}
\ No newline at end of file
@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
......@@ -4,7 +4,7 @@ VantComponent({
title: String,
border: {
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}
\ No newline at end of file
@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
......@@ -6,7 +6,7 @@ VantComponent({
'label-class',
'value-class',
'right-icon-class',
'hover-class'
'hover-class',
],
mixins: [link],
props: {
......@@ -25,13 +25,13 @@ VantComponent({
useLabelSlot: Boolean,
border: {
type: Boolean,
value: true
}
value: true,
},
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
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}
\ No newline at end of file
@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
......@@ -4,25 +4,21 @@ VantComponent({
relation: {
name: 'checkbox',
type: 'descendant',
current: 'checkbox-group',
linked(target) {
this.children = this.children || [];
this.children.push(target);
this.updateChild(target);
},
unlinked(target) {
this.children = this.children.filter((child) => child !== target);
}
},
props: {
max: Number,
value: {
type: Array,
observer: 'updateChildren'
observer: 'updateChildren',
},
disabled: {
type: Boolean,
observer: 'updateChildren'
}
observer: 'updateChildren',
},
},
methods: {
updateChildren() {
......@@ -30,10 +26,10 @@ VantComponent({
},
updateChild(child) {
const { value, disabled } = this.data;
child.set({
child.setData({
value: value.indexOf(child.data.name) !== -1,
disabled: disabled || child.data.disabled
parentDisabled: disabled,
});
}
}
},
},
});
......@@ -8,12 +8,7 @@ VantComponent({
relation: {
name: 'checkbox-group',
type: 'ancestor',
linked(target) {
this.parent = target;
},
unlinked() {
this.parent = null;
}
current: 'checkbox',
},
classes: ['icon-class', 'label-class'],
props: {
......@@ -25,27 +20,33 @@ VantComponent({
labelDisabled: Boolean,
shape: {
type: String,
value: 'round'
}
value: 'round',
},
iconSize: {
type: null,
value: 20,
},
},
data: {
parentDisabled: false,
},
methods: {
emitChange(value) {
if (this.parent) {
this.setParentValue(this.parent, value);
}
else {
} else {
emit(this, value);
}
},
toggle() {
const { disabled, value } = this.data;
if (!disabled) {
const { parentDisabled, disabled, value } = this.data;
if (!disabled && !parentDisabled) {
this.emitChange(!value);
}
},
onClickLabel() {
const { labelDisabled, disabled, value } = this.data;
if (!disabled && !labelDisabled) {
const { labelDisabled, parentDisabled, disabled, value } = this.data;
if (!disabled && !labelDisabled && !parentDisabled) {
this.emitChange(!value);
}
},
......@@ -61,14 +62,13 @@ VantComponent({
parentValue.push(name);
emit(parent, parentValue);
}
}
else {
} else {
const index = parentValue.indexOf(name);
if (index !== -1) {
parentValue.splice(index, 1);
emit(parent, parentValue);
}
}
}
}
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="van-checkbox custom-class">
<view class="van-checkbox__icon-wrap" bindtap="toggle">
......@@ -6,13 +7,14 @@
<van-icon
wx:else
name="success"
class="{{ utils.bem('checkbox__icon', [shape, { disabled, checked: value }]) }}"
style="{{ checkedColor && value && !disabled ? 'border-color:' + checkedColor + '; background-color:' + checkedColor : '' }}"
size="0.8em"
class="{{ utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }]) }}"
style="{{ computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) }}"
custom-class="icon-class"
custom-style="line-height: 20px;"
custom-style="line-height: 1.25em;"
/>
</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 />
</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}
\ No newline at end of file
@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
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';
VantComponent({
relation: {
name: 'row',
type: 'ancestor'
type: 'ancestor',
current: 'col',
},
props: {
span: Number,
offset: Number
offset: Number,
},
data: {
style: ''
viewStyle: '',
},
methods: {
setGutter(gutter) {
const padding = `${gutter / 2}px`;
const style = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : '';
if (style !== this.data.style) {
this.set({ style });
}
}
const viewStyle = gutter
? `padding-left: ${padding}; padding-right: ${padding};`
: '';
if (viewStyle !== this.data.viewStyle) {
this.setData({ viewStyle });
}
},
},
});
......@@ -2,7 +2,7 @@
<view
class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
style="{{ style }}"
style="{{ viewStyle }}"
>
<slot />
</view>
import { VantComponent } from '../common/component';
const nextTick = () => new Promise(resolve => setTimeout(resolve, 20));
const nextTick = () => new Promise((resolve) => setTimeout(resolve, 20));
VantComponent({
classes: ['title-class', 'content-class'],
relation: {
name: 'collapse',
type: 'ancestor',
linked(parent) {
this.parent = parent;
}
current: 'collapse-item',
},
props: {
name: null,
......@@ -19,17 +17,17 @@ VantComponent({
clickable: Boolean,
border: {
type: Boolean,
value: true
value: true,
},
isLink: {
type: Boolean,
value: true
}
value: true,
},
},
data: {
contentHeight: 0,
expanded: false,
transition: false
transition: false,
},
mounted() {
this.updateExpanded()
......@@ -39,7 +37,7 @@ VantComponent({
if (this.data.expanded) {
data.contentHeight = 'auto';
}
this.set(data);
this.setData(data);
});
},
methods: {
......@@ -68,7 +66,7 @@ VantComponent({
.then((height) => {
if (expanded) {
return this.set({
contentHeight: height ? `${height}px` : 'auto'
contentHeight: height ? `${height}px` : 'auto',
});
}
return this.set({ contentHeight: `${height}px` })
......@@ -87,10 +85,10 @@ VantComponent({
},
onTransitionEnd() {
if (this.data.expanded) {
this.set({
contentHeight: 'auto'
this.setData({
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}
\ No newline at end of file
@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
......@@ -3,29 +3,21 @@ VantComponent({
relation: {
name: 'collapse-item',
type: 'descendant',
linked(child) {
this.children.push(child);
},
unlinked(child) {
this.children = this.children.filter((item) => item !== child);
}
current: 'collapse',
},
props: {
value: {
type: null,
observer: 'updateExpanded'
observer: 'updateExpanded',
},
accordion: {
type: Boolean,
observer: 'updateExpanded'
observer: 'updateExpanded',
},
border: {
type: Boolean,
value: true
}
value: true,
},
beforeCreate() {
this.children = [];
},
methods: {
updateExpanded() {
......@@ -35,16 +27,21 @@ VantComponent({
},
switch(name, expanded) {
const { accordion, value } = this.data;
const changeItem = name;
if (!accordion) {
name = expanded
? (value || []).concat(name)
: (value || []).filter((activeName) => activeName !== name);
}
else {
} else {
name = expanded ? name : '';
}
if (expanded) {
this.$emit('open', changeItem);
} else {
this.$emit('close', changeItem);
}
this.$emit('change', name);
this.$emit('input', name);
}
}
},
},
});
export declare const RED = "#f44";
export declare const RED = "#ee0a24";
export declare const BLUE = "#1989fa";
export declare const WHITE = "#fff";
export declare const GREEN = "#07c160";
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 WHITE = '#fff';
export const GREEN = '#07c160';
export const ORANGE = '#ff976a';
export const GRAY = '#323233';
export const GRAY_DARK = '#969799';
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 };
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) {
Object.keys(map).forEach(key => {
Object.keys(map).forEach((key) => {
if (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 = {}) {
const options = {};
mapKeys(vantOptions, options, {
......@@ -19,13 +67,11 @@ function VantComponent(vantOptions = {}) {
mounted: 'ready',
relations: 'relations',
destroyed: 'detached',
classes: 'externalClasses'
classes: 'externalClasses',
});
const { relation } = vantOptions;
if (relation) {
options.relations = Object.assign(options.relations || {}, {
[`../${relation.name}/index`]: relation
});
makeRelation(options, vantOptions, relation);
}
// add default externalClasses
options.externalClasses = options.externalClasses || [];
......@@ -37,12 +83,19 @@ function VantComponent(vantOptions = {}) {
if (vantOptions.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
options.options = {
multipleSlots: true,
addGlobalClass: true
addGlobalClass: true,
};
observe(vantOptions, options);
Component(options);
}
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}
\ 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{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
.van-clearfix:after{content:"";display:table;clear:both}
\ No newline at end of file
.van-clearfix:after{display:table;clear:both;content:""}
\ 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}
\ 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{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
.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}
\ 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{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
......@@ -4,4 +4,5 @@ export declare function isObj(x: any): boolean;
export declare function isNumber(value: any): boolean;
export declare function range(num: number, min: number, max: number): number;
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) {
return x !== null && (type === 'object' || type === 'function');
}
export function isNumber(value) {
return /^\d+$/.test(value);
return /^\d+(\.\d+)?$/.test(value);
}
export function range(num, min, max) {
return Math.min(Math.max(num, min), max);
......@@ -23,3 +23,10 @@ export function getSystemInfoSync() {
}
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) {
return result;
}
function getTrueValue(formattedValue) {
if (!formattedValue)
return;
if (!formattedValue) return;
while (isNaN(parseInt(formattedValue, 10))) {
formattedValue = formattedValue.slice(1);
}
......@@ -33,47 +32,59 @@ function getMonthEndDay(year, month) {
const defaultFormatter = (_, value) => value;
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign({}, pickerProps, { formatter: {
type: Function,
value: defaultFormatter
}, value: null, type: {
props: Object.assign(Object.assign({}, pickerProps), {
value: {
type: null,
observer: 'updateValue',
},
filter: null,
type: {
type: String,
value: 'datetime'
}, showToolbar: {
value: 'datetime',
observer: 'updateValue',
},
showToolbar: {
type: Boolean,
value: true
}, minDate: {
value: true,
},
formatter: {
type: null,
value: defaultFormatter,
},
minDate: {
type: Number,
value: new Date(currentYear - 10, 0, 1).getTime()
}, maxDate: {
value: new Date(currentYear - 10, 0, 1).getTime(),
observer: 'updateValue',
},
maxDate: {
type: Number,
value: new Date(currentYear + 10, 11, 31).getTime()
}, minHour: {
value: new Date(currentYear + 10, 11, 31).getTime(),
observer: 'updateValue',
},
minHour: {
type: Number,
value: 0
}, maxHour: {
value: 0,
observer: 'updateValue',
},
maxHour: {
type: Number,
value: 23
}, minMinute: {
value: 23,
observer: 'updateValue',
},
minMinute: {
type: Number,
value: 0
}, maxMinute: {
value: 0,
observer: 'updateValue',
},
maxMinute: {
type: Number,
value: 59
} }),
value: 59,
observer: 'updateValue',
},
}),
data: {
innerValue: Date.now(),
columns: []
},
watch: {
value: 'updateValue',
type: 'updateValue',
minDate: 'updateValue',
maxDate: 'updateValue',
minHour: 'updateValue',
maxHour: 'updateValue',
minMinute: 'updateValue',
maxMinute: 'updateValue'
columns: [],
},
methods: {
updateValue() {
......@@ -84,8 +95,7 @@ VantComponent({
this.updateColumnValue(val).then(() => {
this.$emit('input', val);
});
}
else {
} else {
this.updateColumns();
}
},
......@@ -94,21 +104,32 @@ VantComponent({
this.picker = this.selectComponent('.van-datetime-picker');
const { picker } = this;
const { setColumnValues } = picker;
picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
picker.setColumnValues = (...args) =>
setColumnValues.apply(picker, [...args, false]);
}
return this.picker;
},
updateColumns() {
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 values = times(range[1] - range[0] + 1, index => {
let values = times(range[1] - range[0] + 1, (index) => {
let value = range[0] + index;
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() {
const { data } = this;
......@@ -116,42 +137,52 @@ VantComponent({
return [
{
type: 'hour',
range: [data.minHour, data.maxHour]
range: [data.minHour, data.maxHour],
},
{
type: 'minute',
range: [data.minMinute, data.maxMinute]
}
range: [data.minMinute, data.maxMinute],
},
];
}
const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary('max', data.innerValue);
const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary('min', data.innerValue);
const {
maxYear,
maxDate,
maxMonth,
maxHour,
maxMinute,
} = this.getBoundary('max', data.innerValue);
const {
minYear,
minDate,
minMonth,
minHour,
minMinute,
} = this.getBoundary('min', data.innerValue);
const result = [
{
type: 'year',
range: [minYear, maxYear]
range: [minYear, maxYear],
},
{
type: 'month',
range: [minMonth, maxMonth]
range: [minMonth, maxMonth],
},
{
type: 'day',
range: [minDate, maxDate]
range: [minDate, maxDate],
},
{
type: 'hour',
range: [minHour, maxHour]
range: [minHour, maxHour],
},
{
type: 'minute',
range: [minMinute, maxMinute]
}
range: [minMinute, maxMinute],
},
];
if (data.type === 'date')
result.splice(3, 2);
if (data.type === 'year-month')
result.splice(2, 3);
if (data.type === 'date') result.splice(3, 2);
if (data.type === 'year-month') result.splice(2, 3);
return result;
},
correctValue(value) {
......@@ -160,8 +191,7 @@ VantComponent({
const isDateType = data.type !== 'time';
if (isDateType && !isValidDate(value)) {
value = data.minDate;
}
else if (!isDateType && !value) {
} else if (!isDateType && !value) {
const { minHour } = data;
value = `${padZero(minHour)}:00`;
}
......@@ -208,7 +238,7 @@ VantComponent({
[`${type}Month`]: month,
[`${type}Date`]: date,
[`${type}Hour`]: hour,
[`${type}Minute`]: minute
[`${type}Minute`]: minute,
};
},
onCancel() {
......@@ -223,9 +253,9 @@ VantComponent({
const picker = this.getPicker();
if (data.type === 'time') {
const indexes = picker.getIndexes();
value = `${indexes[0] + data.minHour}:${indexes[1] + data.minMinute}`;
}
else {
value = `${+data.columns[0].values[indexes[0]]}:${+data.columns[1]
.values[indexes[1]]}`;
} else {
const values = picker.getValues();
const year = getTrueValue(values[0]);
const month = getTrueValue(values[1]);
......@@ -255,33 +285,33 @@ VantComponent({
const picker = this.getPicker();
if (type === 'time') {
const pair = value.split(':');
values = [
formatter('hour', pair[0]),
formatter('minute', pair[1])
];
}
else {
values = [formatter('hour', pair[0]), formatter('minute', pair[1])];
} else {
const date = new Date(value);
values = [
formatter('year', `${date.getFullYear()}`),
formatter('month', padZero(date.getMonth() + 1))
formatter('month', padZero(date.getMonth() + 1)),
];
if (type === 'date') {
values.push(formatter('day', padZero(date.getDate())));
}
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 })
.then(() => this.updateColumns())
.then(() => picker.setValues(values));
}
},
},
created() {
const innerValue = this.correctValue(this.data.value);
this.updateColumnValue(innerValue).then(() => {
this.$emit('input', innerValue);
});
}
},
});
......@@ -3,22 +3,19 @@ import { Weapp } from './weapp';
declare type RecordToAny<T> = {
[K in keyof T]: any;
};
declare type RecordToReturn<T> = {
[P in keyof T]: T[P] extends (...args: any[]) => any ? ReturnType<T[P]> : T[P];
export declare type CombinedComponentInstance<Data, Props, Methods> = Methods & WechatMiniprogram.Component.TrivialInstance & Weapp.FormField & {
data: Data & RecordToAny<Props>;
};
export declare type CombinedComponentInstance<Data, Props, Methods, Computed> = Methods & WechatMiniprogram.Component.TrivialInstance & Weapp.FormField & {
data: Data & RecordToReturn<Computed> & RecordToAny<Props>;
};
export interface VantComponentOptions<Data, Props, Methods, Computed, Instance> {
export interface VantComponentOptions<Data, Props, Methods, Instance> {
data?: Data;
field?: boolean;
classes?: string[];
mixins?: string[];
props?: Props & Weapp.PropertyOption;
watch?: Weapp.WatchOption<Instance>;
computed?: Computed & Weapp.ComputedOption<Instance>;
relation?: Weapp.RelationOption<Instance> & {
type: 'ancestor' | 'descendant';
name: string;
current: string;
};
relations?: {
[componentName: string]: Weapp.RelationOption<Instance>;
......
/// <reference types="miniprogram-api-typings" />
export declare namespace Weapp {
interface FormField {
export interface FormField {
data: {
name: string;
value: any;
......@@ -13,7 +13,7 @@ export declare namespace Weapp {
[key: string]: any;
};
}
interface Event {
export interface Event {
/**
* 代表事件的类型。
*/
......@@ -57,14 +57,14 @@ export declare namespace Weapp {
*/
clientY: number;
}
interface TouchEvent extends Event {
export interface TouchEvent extends Event {
touches: Array<Touch>;
changedTouches: Array<Touch>;
}
/**
* relation定义,miniprogram-api-typings缺少this定义
*/
interface RelationOption<Instance> {
export interface RelationOption<Instance> {
/** 目标组件的相对关系 */
type: 'parent' | 'child' | 'ancestor' | 'descendant';
/** 关系生命周期函数,当关系被建立在页面节点树中时触发,触发时机在组件attached生命周期之后 */
......@@ -80,23 +80,17 @@ export declare namespace Weapp {
* obverser定义,miniprogram-api-typings缺少this定义
*/
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定义
*/
interface MethodOption<Instance> {
export interface MethodOption<Instance> {
[name: string]: (this: Instance, ...args: any[]) => any;
}
interface ComputedOption<Instance> {
export interface ComputedOption<Instance> {
[name: string]: (this: Instance) => any;
}
type PropertyType = StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | FunctionConstructor | null;
interface PropertyOption {
export interface PropertyOption {
[name: string]: PropertyType | PropertyType[] | {
/** 属性类型 */
type: PropertyType | PropertyType[];
......@@ -108,4 +102,5 @@ export declare namespace Weapp {
optionalTypes?: PropertyType[];
};
}
export {};
}
......@@ -4,6 +4,7 @@ declare type DialogOptions = {
lang?: string;
show?: boolean;
title?: string;
width?: string | number;
zIndex?: number;
context?: WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
message?: string;
......@@ -16,6 +17,7 @@ declare type DialogOptions = {
asyncClose?: boolean;
businessId?: number;
sessionFrom?: string;
overlayStyle?: string;
appParameter?: string;
messageAlign?: string;
sendMessageImg?: string;
......
......@@ -3,55 +3,61 @@ function getContext() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
const Dialog = options => {
options = Object.assign({}, Dialog.currentOptions, options);
const Dialog = (options) => {
options = Object.assign(Object.assign({}, Dialog.currentOptions), options);
return new Promise((resolve, reject) => {
const context = options.context || getContext();
const dialog = context.selectComponent(options.selector);
delete options.context;
delete options.selector;
if (dialog) {
dialog.set(Object.assign({ onCancel: reject, onConfirm: resolve }, options));
dialog.setData(
Object.assign({ onCancel: reject, onConfirm: resolve }, options)
);
queue.push(dialog);
}
else {
console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确');
} else {
console.warn(
'未找到 van-dialog 节点,请确认 selector 及 context 是否正确'
);
}
});
};
Dialog.defaultOptions = {
show: true,
title: '',
width: null,
message: '',
zIndex: 100,
overlay: true,
selector: '#van-dialog',
className: '',
customStyle: '',
asyncClose: false,
messageAlign: '',
transition: 'scale',
selector: '#van-dialog',
customStyle: '',
messageAlign: '',
overlayStyle: '',
confirmButtonText: '确认',
cancelButtonText: '取消',
showConfirmButton: true,
showCancelButton: false,
closeOnClickOverlay: false,
confirmButtonOpenType: ''
confirmButtonOpenType: '',
};
Dialog.alert = Dialog;
Dialog.confirm = options => Dialog(Object.assign({ showCancelButton: true }, options));
Dialog.confirm = (options) =>
Dialog(Object.assign({ showCancelButton: true }, options));
Dialog.close = () => {
queue.forEach(dialog => {
queue.forEach((dialog) => {
dialog.close();
});
queue = [];
};
Dialog.stopLoading = () => {
queue.forEach(dialog => {
queue.forEach((dialog) => {
dialog.stopLoading();
});
};
Dialog.setDefaultOptions = options => {
Dialog.setDefaultOptions = (options) => {
Object.assign(Dialog.currentOptions, options);
};
Dialog.resetDefaultOptions = () => {
......
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
import { GRAY, BLUE } from '../common/color';
VantComponent({
mixins: [button, openType],
props: {
show: Boolean,
show: {
type: Boolean,
observer(show) {
!show && this.stopLoading();
},
},
title: String,
message: String,
useSlot: Boolean,
......@@ -12,44 +18,50 @@ VantComponent({
customStyle: String,
asyncClose: Boolean,
messageAlign: String,
overlayStyle: String,
useTitleSlot: Boolean,
showCancelButton: Boolean,
closeOnClickOverlay: Boolean,
confirmButtonOpenType: String,
width: null,
zIndex: {
type: Number,
value: 2000
value: 2000,
},
confirmButtonText: {
type: String,
value: '确认'
value: '确认',
},
cancelButtonText: {
type: String,
value: '取消'
value: '取消',
},
confirmButtonColor: {
type: String,
value: BLUE,
},
cancelButtonColor: {
type: String,
value: GRAY,
},
showConfirmButton: {
type: Boolean,
value: true
value: true,
},
overlay: {
type: Boolean,
value: true
value: true,
},
transition: {
type: String,
value: 'scale'
}
value: 'scale',
},
},
data: {
loading: {
confirm: false,
cancel: false
}
cancel: false,
},
watch: {
show(show) {
!show && this.stopLoading();
}
},
methods: {
onConfirm() {
......@@ -63,23 +75,23 @@ VantComponent({
},
handleAction(action) {
if (this.data.asyncClose) {
this.set({
[`loading.${action}`]: true
this.setData({
[`loading.${action}`]: true,
});
}
this.onClose(action);
},
close() {
this.set({
show: false
this.setData({
show: false,
});
},
stopLoading() {
this.set({
this.setData({
loading: {
confirm: false,
cancel: false
}
cancel: false,
},
});
},
onClose(action) {
......@@ -89,10 +101,12 @@ VantComponent({
this.$emit('close', action);
// 把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
this.$emit(action, { dialog: this });
const callback = this.data[action === 'confirm' ? 'onConfirm' : 'onCancel'];
const callback = this.data[
action === 'confirm' ? 'onConfirm' : 'onCancel'
];
if (callback) {
callback(this);
}
}
}
},
},
});
<wxs src="../wxs/utils.wxs" module="utils" />
<van-popup
show="{{ show }}"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
custom-class="van-dialog {{ className }}"
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 }}"
bind:close="onClickOverlay"
>
<view
wx:if="{{ title }}"
wx:if="{{ title || useTitleSlot }}"
class="van-dialog__header {{ message || useSlot ? '' : 'van-dialog--isolated' }}"
>
{{ title }}
<slot wx:if="{{ useTitleSlot }}" name="title" />
<block wx:elif="{{ title }}">{{ title }}</block>
</view>
<slot wx:if="{{ useSlot }}" />
......@@ -20,7 +24,7 @@
wx:elif="{{ message }}"
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 class="van-hairline--top van-dialog__footer">
......@@ -30,6 +34,7 @@
loading="{{ loading.cancel }}"
class="van-dialog__button van-hairline--right"
custom-class="van-dialog__cancel"
custom-style="color: {{ cancelButtonColor }}"
bind:click="onCancel"
>
{{ cancelButtonText }}
......@@ -40,6 +45,7 @@
class="van-dialog__button"
loading="{{ loading.confirm }}"
custom-class="van-dialog__confirm"
custom-style="color: {{ confirmButtonColor }}"
open-type="{{ confirmButtonOpenType }}"
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)}
\ No newline at end of file
@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
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>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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