first commit

master
tangyi 2022-04-11 09:11:15 +08:00
commit a72b414409
83 changed files with 16369 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/vendor
/node_modules
/public/storage
/unpackage
/.hbuilderx
Homestead.yaml
Homestead.json
.env
.idea

53
App.vue Normal file
View File

@ -0,0 +1,53 @@
<script>
export default {
globalData:{
projectname:'', //
lat:'', //
lng:'' ,//
hostapi:'' //
},
// show
onLaunch: function() {
//
// #ifdef APP-PLUS
this.globalData.hostapi = '';
// #endif
// #ifdef MP-WEIXIN
this.globalData.hostapi = '';
// #endif
// #ifdef H5
this.globalData.hostapi = '';
// this.globalData.hostapi = '/web';
// #endif
},
onShow: function() {
// if(uni.getStorageSync('token')){
// // token
// this.$toolAll.tools.refreshToken();
// }
},
onHide: function() {
}
};
</script>
<style>
/*每个页面公共css */
/* 阿里巴巴矢量图标库 start */
@import url("./commons/icon-font.css");
/* 阿里巴巴矢量图标库 end */
/* 项目基础样式 start */
@import url("./commons/base.css");
/* 项目基础样式 end */
/* 项目页面样式 start */
@import url("./commons/flying-monkey.css");
/* 项目页面样式 end */
/* 动画样式 start */
@import url("./commons/animate.min.css");
/* 动画样式 end */
page {background-color: #f7f7f7;}
</style>

12
commons/animate.min.css vendored Normal file

File diff suppressed because one or more lines are too long

416
commons/base.css Normal file
View File

@ -0,0 +1,416 @@
/* @media screen and (height:812px){
}
@media screen and (height:844px){
}
@media screen and (height:896px){
}
@media screen and (min-height:926px){
}
*/
.bottoc{margin-top: 6rpx;color: #414141;}
.opc{opacity: 0.7;}
.width100{width: 100%;}
.width55{width: 55%;}
.width50{width: 50%;}
.width49{width: 49%;}
.width48_5{width: 48.5%;}
.width48{width: 48%;}
.width47{width: 47%;}
.width46{width: 46%;}
.width45{width: 45%;}
.width33{width: 33%;}
.width32{width: 32%;}
.width31{width: 31%;}
.width30{width: 30%;}
.width29{width: 29%;}
.width28{width: 28%;}
.width27{width: 27%;}
.width26{width: 26%;}
.width25{width: 25%;}
.posAll{position: fixed;top: 0;left: 0;right: 0;bottom: 0;background-color: rgba(0,0,0,.45);z-index: 12;}
.posir{position: relative;}
.posia{position: absolute;}
.poszy{position: fixed;left: 0;right: 0;z-index: 3;}
.posiszy{position: fixed;left: 0;right: 0;z-index: 5;}
.posixzy{position: fixed;left: 0;right: 0;z-index: 2;bottom: 0;}
.posia-op{position: absolute;top: 0;right: 0;left: 0;bottom: 0;opacity: 0;}
.syxzo{top: 0;left: 0;right: 0;bottom: 0;opacity: 0;}
.position-sticky{position: sticky;top: 40px;z-index: 2;}
.dis{display: flex;}
.disac{display: flex;align-items: center;}
.disja{display: flex;justify-content: space-around;}
.disjb{display: flex;justify-content: space-between;}
.disje{display: flex;justify-content: flex-end;}
.disjbac{display: flex;justify-content: space-between;align-items: center;}
.disjcac{display: flex;justify-content: center;align-items: center;}
.fc{flex-direction: column;}
.fw{flex-wrap: wrap;}
.fe{justify-content: flex-end;}
.flexs{flex-shrink: 0;}
.wh42{width: 42rpx;height: 42rpx;}
.wh44{width: 44rpx;height: 44rpx;}
button:after{content: none!important;}
.borbot{border-bottom: 2rpx solid #E6E6E6;}
.borbot:last-child{border-bottom: none;}
.bbot{border-bottom: 2rpx solid #EEEEEE;}
.borbot-df{border: 2rpx solid #DFDFDF;}
.borbot-cc{border: 2rpx solid #CCCCCC;}
.bleft {border-left: 1rpx solid #EEEEEE;}
/* 行高 */
.line-h30{line-height: 30rpx;}
.line-h32{line-height: 32rpx;}
.line-h34{line-height: 34rpx;}
.line-h36{line-height: 36rpx;}
.line-h38{line-height: 38rpx;}
.line-h40{line-height: 40rpx;}
.line-h42{line-height: 42rpx;}
.line-h44{line-height: 44rpx;}
.line-h46{line-height: 46rpx;}
.line-h48{line-height: 48rpx;}
.line-h50{line-height: 50rpx;}
.line-h52{line-height: 52rpx;}
.line-h54{line-height: 54rpx;}
.line-h56{line-height: 56rpx;}
.line-h58{line-height: 58rpx;}
.line-h60{line-height: 60rpx;}
.line-h62{line-height: 62rpx;}
.line-h64{line-height: 64rpx;}
.line-h66{line-height: 66rpx;}
.line-h68{line-height: 60rpx;}
.line-h70{line-height: 70rpx;}
.line-h72{line-height: 72rpx;}
.line-h74{line-height: 74rpx;}
.clips1{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 1;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips2{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips3{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 3;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips4{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 4;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips5{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 5;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips6{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 6;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips7{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 7;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips8{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 8;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips9{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 9;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips10{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 10;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
/* 字体大小 */
.fs16{
font-size: 32rpx;
}
.app-content{
padding-bottom: 150rpx;
}
.fon20{font-size: 20rpx;}
.fon22{font-size: 22rpx;}
.fon24{font-size: 24rpx;}
.fon25{font-size: 25rpx;}
.fon26{font-size: 26rpx;}
.fon27{font-size: 27rpx;}
.fon28{font-size: 28rpx;}
.fon30{font-size: 30rpx;}
.fon32{font-size: 32rpx;}
.fon34{font-size: 34rpx;}
.fon36{font-size: 36rpx;}
.fon38{font-size: 38rpx;}
.fon40{font-size: 40rpx;}
.fon42{font-size: 42rpx;}
.fon44{font-size: 44rpx;}
.fon46{font-size: 46rpx;}
.fon48{font-size: 48rpx;}
.fon50{font-size: 50rpx;}
.fon52{font-size: 52rpx;}
.fon54{font-size: 54rpx;}
.fon56{font-size: 56rpx;}
.fon58{font-size: 58rpx;}
.fon60{font-size: 60rpx;}
.fon62{font-size: 62rpx;}
.fon64{font-size: 64rpx;}
.fon66{font-size: 66rpx;}
.fon68{font-size: 68rpx;}
.fon70{font-size: 70rpx;}
.fon72{font-size: 72rpx;}
/* 字体颜色 */
.cF37A61{
color: #F37A61 ;
}
.colf{color: #FFFFFF;}
.colf6{color: #f6f6f6;}
.colb{color: #000000;}
.colc{color: #CCCCCC;}
.col3{color: #333333;}
.col34{color: #343434;}
.col6{color: #666666;}
.colf8{color: #F85050;}
.col9{color: #999999;}
.pcol{color: #3875F6;}
.col2c{color: #2C2C2C;}
.col80{color: #808080;}
.col7D{color: #7D7D7D;}
.colB3{color: #B3B3B3;}
.col5b{color: #5B5B5B;}
.colpeili{color: #868695;}
/* 字体位置 */
.tright{text-align: right;}
.tcenter{text-align: center;}
/* 文字空两格 */
.tindent{text-indent: 2em;}
/* 元素缩小 */
.scal13{transform: scale(1.3);}
.scal12{transform: scale(1.2);}
.scal11{transform: scale(1.1);}
.scal10{transform: scale(1);}
.scal09{transform: scale(.9);}
.scal08{transform: scale(.8);}
.scal07{transform: scale(.7);}
.scal06{transform: scale(.6);}
.scal05{transform: scale(.5);}
/* 行间距 */
.linh40{line-height: 40rpx;}
.linh50{line-height: 50rpx;}
.linh60{line-height: 60rpx;}
.linh70{line-height: 70rpx;}
/* 粗体 */
.bold{font-weight: bold;}
.bold400{font-weight: 400;}
.bold500{font-weight: 500;}
/* 背景颜色 */
.pbackc{background-color: #3875F6;}
.bacf{background-color: #FFFFFF;}
.bac0{background-color: #000000;}
.bcdb{background-color: #DBDBDB;}
.bcf8{background: #F85050;}
.bacf5{background: #F5F5F5;}
.bacf6{background-color: #f6f6f6;}
/* 圆角 */
.radius10{border-radius: 10rpx;}
.radius15{border-radius: 15rpx;}
.radius20{border-radius: 20rpx;}
.radius30{border-radius: 30rpx;}
.radius35{border-radius: 35rpx;}
.radius40{border-radius: 40rpx;}
.radius45{border-radius: 45rpx;}
.radius_50{border-radius: 50%;}
.radius_100{border-radius: 100%;}
/* 上下左右---外边距 */
.mar10{margin: 10rpx;}
.mar20{margin: 20rpx;}
.mar25{margin: 25rpx;}
.mar30{margin: 30rpx;}
.mar32{margin: 32rpx;}
.mar36{margin: 36rpx;}
.mar40{margin: 40rpx;}
.mar50{margin: 50rpx;}
/* 上下---外边距 */
.mar-sx10{margin-top: 10rpx;margin-bottom: 10rpx;}
.mar-sx20{margin-top: 20rpx;margin-bottom: 20rpx;}
.mar-sx25{margin-top: 25rpx;margin-bottom: 25rpx;}
.mar-sx30{margin-top: 30rpx;margin-bottom: 30rpx;}
.mar-sx32{margin-top: 32rpx;margin-bottom: 32rpx;}
.mar-sx36{margin-top: 36rpx;margin-bottom: 36rpx;}
.mar-sx40{margin-top: 40rpx;margin-bottom: 40rpx;}
.mar-sx50{margin-top: 50rpx;margin-bottom: 50rpx;}
/* 左右---外边距 */
.mar-zy10{margin-left: 10rpx;margin-right: 10rpx;}
.mar-zy20{margin-left: 20rpx;margin-right: 20rpx;}
.mar-zy25{margin-left: 25rpx;margin-right: 25rpx;}
.mar-zy30{margin-left: 30rpx;margin-right: 30rpx;}
.mar-zy32{margin-left: 32rpx;margin-right: 32rpx;}
.mar-zy36{margin-left: 36rpx;margin-right: 36rpx;}
.mar-zy40{margin-left: 40rpx;margin-right: 40rpx;}
.mar-zy50{margin-left: 50rpx;margin-right: 50rpx;}
.mar-zy85{margin-left: 85rpx;margin-right: 85rpx;}
/* 上---外边距 */
.mar-s10{margin-top: 10rpx;}
.mar-s20{margin-top: 20rpx;}
.mar-s25{margin-top: 25rpx;}
.mar-s30{margin-top: 30rpx;}
.mar-s32{margin-top: 32rpx;}
.mar-s36{margin-top: 36rpx;}
.mar-s40{margin-top: 40rpx;}
.mar-s50{margin-top: 50rpx;}
.mar-s60{margin-top: 60rpx;}
.mar-s70{margin-top: 70rpx;}
.mar-s80{margin-top: 80rpx;}
.mar-s90{margin-top: 90rpx;}
.mar-s100{margin-top: 100rpx;}
.mar-s120{margin-top: 120rpx;}
.mar-s140{margin-top: 140rpx;}
.mar-s160{margin-top: 160rpx;}
.mar-s180{margin-top: 180rpx;}
/* 下---外边距 */
.mar-x10{margin-bottom: 10rpx;}
.mar-x20{margin-bottom: 20rpx;}
.mar-x25{margin-bottom: 25rpx;}
.mar-x30{margin-bottom: 30rpx;}
.mar-x32{margin-bottom: 32rpx;}
.mar-x36{margin-bottom: 36rpx;}
.mar-x40{margin-bottom: 40rpx;}
.mar-x50{margin-bottom: 50rpx;}
.mar-x60{margin-bottom: 60rpx;}
.mar-x70{margin-bottom: 70rpx;}
.mar-x80{margin-bottom: 80rpx;}
.mar-x90{margin-bottom: 90rpx;}
.mar-x100{margin-bottom: 100rpx;}
.mar-x120{margin-bottom: 120rpx;}
.mar-x140{margin-bottom: 140rpx;}
.mar-x160{margin-bottom: 160rpx;}
.mar-x180{margin-bottom: 180rpx;}
/* 左---外边距 */
.mar-z10{margin-left: 10rpx;}
.mar-z20{margin-left: 20rpx;}
.mar-z25{margin-left: 25rpx;}
.mar-z30{margin-left: 30rpx;}
.mar-z32{margin-left: 32rpx;}
.mar-z36{margin-left: 36rpx;}
.mar-z40{margin-left: 40rpx;}
.mar-z50{margin-left: 50rpx;}
.mar-z60{margin-left: 60rpx;}
.mar-z70{margin-left: 70rpx;}
.mar-z80{margin-left: 80rpx;}
.mar-z90{margin-left: 90rpx;}
.mar-z100{margin-left: 100rpx;}
.mar-z110{margin-left: 110rpx;}
.mar-z120{margin-left: 120rpx;}
/* 右---外边距 */
.mar-y10{margin-right: 10rpx;}
.mar-y20{margin-right: 20rpx;}
.mar-y25{margin-right: 25rpx;}
.mar-y30{margin-right: 30rpx;}
.mar-y32{margin-right: 32rpx;}
.mar-y36{margin-right: 36rpx;}
.mar-y40{margin-right: 40rpx;}
.mar-y50{margin-right: 50rpx;}
.mar-y60{margin-right: 60rpx;}
.mar-y70{margin-right: 70rpx;}
.mar-y80{margin-right: 80rpx;}
.mar-y90{margin-right: 90rpx;}
.mar-y100{margin-right: 100rpx;}
.mar-y110{margin-right: 110rpx;}
.mar-y120{margin-right: 120rpx;}
/* 上下左右---内边距 */
.pad10{padding: 10rpx;}
.pad20{padding: 20rpx;}
.pad25{padding: 25rpx;}
.pad30{padding: 30rpx;}
.pad32{padding: 32rpx;}
.pad36{padding: 36rpx;}
.pad40{padding: 40rpx;}
.pad50{padding: 50rpx;}
/* 上下---内边距 */
.pad-sx6{padding-top: 6rpx;padding-bottom: 6rpx;}
.pad-sx10{padding-top: 10rpx;padding-bottom: 10rpx;}
.pad-sx20{padding-top: 20rpx;padding-bottom: 20rpx;}
.pad-sx25{padding-top: 25rpx;padding-bottom: 25rpx;}
.pad-sx30{padding-top: 30rpx;padding-bottom: 30rpx;}
.pad-sx32{padding-top: 32rpx;padding-bottom: 32rpx;}
.pad-sx36{padding-top: 36rpx;padding-bottom: 36rpx;}
.pad-sx40{padding-top: 40rpx;padding-bottom: 40rpx;}
.pad-sx50{padding-top: 50rpx;padding-bottom: 50rpx;}
/* 左右---内边距 */
.pad-zy10{padding-left: 10rpx;padding-right: 10rpx;}
.pad-zy20{padding-left: 20rpx;padding-right: 20rpx;}
.pad-zy25{padding-left: 25rpx;padding-right: 25rpx;}
.pad-zy30{padding-left: 30rpx;padding-right: 30rpx;}
.pad-zy32{padding-left: 32rpx;padding-right: 32rpx;}
.pad-zy36{padding-left: 36rpx;padding-right: 36rpx;}
.pad-zy40{padding-left: 40rpx;padding-right: 40rpx;}
.pad-zy50{padding-left: 50rpx;padding-right: 50rpx;}
/* 上---内边距 */
.pad-s10{padding-top: 10rpx;}
.pad-s20{padding-top: 20rpx;}
.pad-s25{padding-top: 25rpx;}
.pad-s30{padding-top: 30rpx;}
.pad-s32{padding-top: 32rpx;}
.pad-s36{padding-top: 36rpx;}
.pad-s40{padding-top: 40rpx;}
.pad-s50{padding-top: 50rpx;}
.pad-s120{padding-top: 120rpx;}
.pad-s140{padding-top: 140rpx;}
.pad-s160{padding-top: 160rpx;}
.pad-s180{padding-top: 180rpx;}
/* 下---内边距 */
.pad-x10{padding-bottom: 10rpx;}
.pad-x20{padding-bottom: 20rpx;}
.pad-x25{padding-bottom: 25rpx;}
.pad-x30{padding-bottom: 30rpx;}
.pad-x32{padding-bottom: 32rpx;}
.pad-x36{padding-bottom: 36rpx;}
.pad-x40{padding-bottom: 40rpx;}
.pad-x50{padding-bottom: 50rpx;}
.pad-x120{padding-bottom: 120rpx;}
.pad-x140{padding-bottom: 140rpx;}
.pad-x160{padding-bottom: 160rpx;}
.pad-x180{padding-bottom: 180rpx;}
.pad-x260{padding-bottom: 260rpx;}
/* 左---内边距 */
.pad-z10{padding-left: 10rpx;}
.pad-z20{padding-left: 20rpx;}
.pad-z25{padding-left: 25rpx;}
.pad-z30{padding-left: 30rpx;}
.pad-z32{padding-left: 32rpx;}
.pad-z36{padding-left: 36rpx;}
.pad-z40{padding-left: 40rpx;}
.pad-z50{padding-left: 50rpx;}
/* 右---内边距 */
.pad-y10{padding-right: 10rpx;}
.pad-y20{padding-right: 20rpx;}
.pad-y25{padding-right: 25rpx;}
.pad-y30{padding-right: 30rpx;}
.pad-y32{padding-right: 32rpx;}
.pad-y36{padding-right: 36rpx;}
.pad-y40{padding-right: 40rpx;}
.pad-y50{padding-right: 50rpx;}
.pad-sx27-zy20{padding: 27rpx 20rpx;}
scroll-view ::-webkit-scrollbar {
display: none !important;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}

381
commons/flying-monkey.css Normal file
View File

@ -0,0 +1,381 @@
/* 注册页面 */
.register-close {width: 26rpx;height: 25rpx;}
.register-title {color: #03affb;}
.register-phone-img{
width: 0;
height: 0;
border-left: 8rpx solid transparent;
border-top: 10rpx solid #000;
border-right: 8rpx solid transparent;
margin: 0 20rpx 0 10rpx;
}
.clear-input {
width: 100%;
border: none;
border-bottom: 1rpx solid #d9d9d9;
font-weight: 400;
font-size: 24rpx;
box-sizing: border-box;
height: 66rpx;
padding-right: 60rpx;
}
.obtain-code {
flex-shrink: 0;
border: 1rpx solid #03affb;
color: #03affb;
width: 170rpx;
height: 45rpx;
display: flex;justify-content: center;align-items: center;
border-radius: 24rpx;
padding: 4rpx 0rpx;
margin-left: 20rpx;
}
.obtainIng {
background-color: #03affb;
color: #FFFFFF;
}
.placeholderColor {color: #bfbfbf;}
.register-radio {transform: scale(0.5);margin-left: -10rpx;margin-right: -10rpx;}
uni-radio .uni-radio-input {border: 1rpx solid #444444;}
.register-agree-policy {color: #03affb;}
.register-btn {width: 422rpx;height: 76rpx;display: flex;justify-content: center;align-items: center; margin: 0 auto;border-radius: 76rpx;margin-top: 60rpx; background-color: #03affb;color: #FFFFFF;}
.clear-box {
position: absolute;right: 0;
top: 50%;
transform: translateY(-50%);
z-index: 1;
}
.clear-close {
position: relative;
display: flex;justify-content: center;align-items: center;
width: 40rpx;height: 40rpx;
border-radius: 100%;
background-color: rgba(0,0,0,.3);
}
.clear-close span {
position: absolute;
width: 0;
border: 2rpx solid #FFFFFF;
height: 20rpx;
border-radius: 2rpx;
}
.clear-close span:first-child {transform: rotate(45deg);}
.clear-close span:last-child {transform: rotate(-45deg);}
/* panding全局 */
.padding{
padding: 0 27rpx;
}
/* 按钮全局 */
.submit-button {
width: 686rpx;
border-radius: 50rpx;
height: 90rpx;
background-color: #02A2ea !important;
display: flex;justify-content: center;align-items: center;
color: #FFFFFF !important;
font-size: 30rpx;
}
/* 登录 */
.login-img {
width: 100%;
}
.login-box {
position: absolute;
left: 0;
right: 0;
top: 46%;
padding: 0 50rpx;
}
.login-input-box {
position: relative;
display: flex;
align-items: center;
border: 1rpx solid #cbcccb;
border-radius: 10rpx;
padding: 20rpx;
margin-bottom: 40rpx;
}
.login-code-btn {
position: absolute;
right: 20rpx;
top: 50%;
z-index: 2;
transform: translateY(-50%);
background-color: #03affb;
color: #FFFFFF;
padding: 10rpx 20rpx;
border-radius: 10rpx;
}
.login-input-box input {
border-left: 1rpx solid #EEEEEE;
margin-left: 20rpx;
padding-left: 20rpx;
}
.login-btn {
height: 80rpx;
display: flex;justify-content: center;align-items: center;
background-color: #03affb;
border-radius: 10rpx;
color: #FFFFFF;
}
/* 忘记密码 */
.forget-title{color: #787a81;}
.forget-input-box{
border-bottom: 1rpx solid #EEEEEE;
padding: 20rpx 0;
margin-bottom: 30rpx;
}
.forget-obtain-code {
position: absolute;
right: 0rpx;
top: 0rpx;
z-index: 2;
background-color: #03affb;
color: #FFFFFF;
padding: 10rpx 20rpx;
border-radius: 10rpx;
}
.forget-btn {
width: 422rpx;
height: 75rpx;
display: flex;justify-content: center;align-items: center;
background-color: #03affb;
color: #FFFFFF;
border-radius: 75rpx;
margin: 0 auto;
box-shadow: 0rpx 10rpx 30rpx rgba(3, 175, 251,0.3);
margin-top: 80rpx;
}
/* 首页 */
.home-message-box {line-height: 60rpx;}
.home-message-box image {
width: 30rpx;
height: 35rpx;
}
.home-message-box view {
position: absolute;
left: 14rpx;
top: -16rpx;
width: 40rpx;
height: 40rpx;
display: flex;justify-content: center;align-items: center;
border-radius: 100%;
font-size: 22rpx;
background-color: #e93030;
color: #FFFFFF;
transform: scale(.8);
}
.project-notice-box {
position: relative;
z-index: 1;
background-color: #FFFFFF;
margin: 20rpx 0;
border-radius: 10rpx;
box-shadow: 6rpx 6rpx 20rpx rgba(0, 162, 234, 0.3);
margin-top: -70rpx;
padding: 20rpx 0;
}
.home-fun-box {
background-color: #FFFFFF;
padding: 30rpx;
margin-bottom: 20rpx;
}
.fun-title::before {
content: '';
display: block;
width: 7rpx;
height: 30rpx;
background: linear-gradient(to top, #FFFFFF 0%, #03affb 40%, #03affb 100%);
border-radius: 26%;
margin-right: 10rpx;
}
.home-solution {
background-color: #FFFFFF;
}
.solution-title {
bottom: 0rpx;
left: -40rpx;
right: -40rpx;
padding: 6rpx;
background-color: rgba(255,255,255,0.6);
transform: scale(.6);
text-align: center;
}
.engineer-num {
position: absolute;
top: -16rpx;
right: -12rpx;
font-size: 24rpx;
background-color: #f03232;
width: 36rpx;
height: 36rpx;
display: flex;justify-content: center;align-items: center;
border-radius: 100%;
color: #FFFFFF;
transform: scale(.8);
}
/* 我的页面 */
.my-exit-btn{
height: 88rpx;
display: flex;justify-content: center;align-items: center;
border-radius: 88rpx;
background-color: #03affb;
color: #FFFFFF;
margin-top: 40rpx;
}
/* 个人信息页面 */
.gender-box {margin-right: 80rpx;color: #333333;}
.gender-box view{
position: relative;
width: 20rpx;
height: 20rpx;
border: 4rpx solid #818181;
border-radius: 100%;
margin-right: 10rpx;
}
.gender-box view::before {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
content: '';
display: block;
width: 14rpx;
height: 14rpx;
background-color: #818181;
border-radius: 100%;
}
.gender-active view{
border: 4rpx solid #d81e06!important;
}
.gender-active view::before {
background-color: #d81e06!important;
}
.person-btn {
margin: 0 40rpx;
height: 88rpx;
display: flex;justify-content: center;align-items: center;
border-radius: 88rpx;
background-color: #03affb;
color: #FFFFFF;
margin-top: 40rpx;
}
/* 电子证件 */
.electronic-head{
background-color: #03affb;
padding-top: 80rpx;
}
/* 服务范围 */
.service-range-status {
background-color: #cdcdcd;
color: #242323;
/* padding: 6rpx 20rpx; */
border-radius: 6rpx;
}
.service-range-activeStatus {
background-color: #03affb;
color: #FFFFFF;
}
/* 我要评价 */
.evaluate-addimg {
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.evaluate-addimg::before,.evaluate-addimg::after{
content: '';
display: block;
width: 2rpx;
background-color: #959595;
height: 60rpx;
}
.evaluate-addimg::before{
transform: rotate(90deg);
}
/* 我的账户 */
.account-active {
position: relative;
color: #03affb;
}
.account-active::after{
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0;
content: '';
display: block;
width: 60%;
height: 4rpx;
background-color: #03affb;
}
.account-btn {
border: 1rpx solid #00a2e9;
color: #00a2e9;
border-radius: 16rpx;
padding: 8rpx 10rpx;
}
.account-detailed {
position: relative;
display: flex;
align-items: center;
font-size: 29rpx;
font-weight: bold;
padding-left: 20rpx;
}
.account-detailed::before {
position: absolute;
left: 0;
top: 4rpx;
bottom: 4rpx;
content: '';
display: block;
width: 4rpx;
background-color: #03affb;
}
.account-detailed-item view:nth-child(1) {
width: 16%;
}
.account-detailed-item view:nth-child(2) {
width: 40%;
text-align: center;
}
.account-detailed-item view:nth-child(3) {
width: 16%;
text-align: center;
}
.account-detailed-item view:nth-child(4) {
width: 22%;
text-align: center;
}
.unsettled-btn {
font-size: 30rpx;
color: #03affb;
border: 1rpx solid #03affb;
border-radius: 6rpx;
padding: 6rpx 20rpx;
margin-top: 10rpx;
}
/* 消息中心 */
.message-circle::before {
content: '';
display: flex;
width: 24rpx;
height: 24rpx;
background-color: #6f91ff;
border-radius: 100%;
margin-right: 20rpx;
}
.activity-message::before {
background-color: #6f91ff;
}
.audit-failed::before {
background-color: #f15d5d;
}
.system-notification::before {
background-color: #2cfc3b;
}

123
commons/icon-font.css Normal file
View File

@ -0,0 +1,123 @@
@font-face {
font-family: "iconfont"; /* Project id 3180711 */
src: url('https://at.alicdn.com/t/font_3180711_7fx7wl7itar.woff2?t=1647479558213') format('woff2'),
url('https://at.alicdn.com/t/font_3180711_7fx7wl7itar.woff?t=1647479558213') format('woff'),
url('https://at.alicdn.com/t/font_3180711_7fx7wl7itar.ttf?t=1647479558213') format('truetype');
}
.icon {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-sandian:before {
content: "\e769";
}
.icon-nothing-collection:before {
content: "\e610";
}
.icon-nothing-more:before {
content: "\e624";
}
.icon-nothing-data:before {
content: "\e60c";
}
.icon-address-check:before {
content: "\e6c2";
}
.icon-address-unchecked:before {
content: "\e623";
}
.icon-navigate-now:before {
content: "\e640";
}
.icon-send-goods:before {
content: "\e601";
}
.icon-payment:before {
content: "\e602";
}
.icon-finish:before {
content: "\e63f";
}
.icon-take:before {
content: "\e649";
}
.icon-refund:before {
content: "\e613";
}
.icon-customer-black:before {
content: "\ec2e";
}
.icon-customer:before {
content: "\e628";
}
.icon-check:before {
content: "\e61e";
}
.icon-del-white:before {
content: "\e61f";
}
.icon-screen:before {
content: "\e60b";
}
.icon-search:before {
content: "\e653";
}
.icon-caidan-mo:before {
content: "\e73e";
}
.icon-renwu-mo:before {
content: "\e73f";
}
.icon-shopp-cart:before {
content: "\e73d";
}
.icon-caidan-active:before {
content: "\e608";
}
.icon-renwu-acitve:before {
content: "\e67c";
}
.icon-home-mo:before {
content: "\e673";
}
.icon-home-active:before {
content: "\e674";
}
.icon-return:before {
content: "\e600";
}
.icon-next:before {
content: "\e60e";
}

View File

@ -0,0 +1,162 @@
<template>
<view class="circle-progress"
:style="{width: widthPx + 'px',height: widthPx + 'px',backgroundColor: bgColor}">
<!-- 有的不支持canvas-id属性必须用id属性 -->
<canvas v-if="canvasId" class="canvas-bg" :canvas-id="canvasId" :id="canvasId"
:style="{width: widthPx + 'px',height: widthPx + 'px'}"></canvas>
<canvas v-if="elId" class="canvas" :canvas-id="elId" :id="elId"
:style="{width: widthPx + 'px',height: widthPx + 'px'}"></canvas>
<slot></slot>
</view>
</template>
<script>
export default {
name: 'circle-progress',
props: {
//
percent: {
type: Number,
default: 0,
// 0100
validator: val => {
return val >= 0 && val <= 100;
}
},
//
inactiveColor: {
type: String,
default: '#ececec'
},
//
activeColor: {
type: String,
default: '#009dff'
},
// 线rpx
borderWidth: {
type: [Number, String],
default: 14
},
// rpx
width: {
type: [Number, String],
default: 200
},
// ms
duration: {
type: [Number, String],
default: 1500
},
//
bgColor: {
type: String,
default: '#ffffff'
}
},
data() {
return {
canvasId: this.randomId(), //
elId: this.randomId(),
widthPx: uni.upx2px(this.width), // px
borderWidthPx: uni.upx2px(this.borderWidth), // px
startAngle: -Math.PI / 2, // canvas312
progressContext: null, // canvas
newPercent: 0, //
oldPercent: 0 //
};
},
watch: {
percent(nVal, oVal = 0) {
if (nVal > 100) nVal = 100;
if (nVal < 0) oVal = 0;
this.newPercent = nVal;
this.oldPercent = oVal;
setTimeout(() => {
this.drawCircleByProgress(oVal);
}, 50);
}
},
created() {
// 使
this.newPercent = this.percent;
this.oldPercent = 0;
},
mounted() {
this.drawProgressBg();
this.drawCircleByProgress(this.oldPercent);
},
methods: {
//progressID
randomId() {
return 'progressId' + parseInt(Math.random() * 1000000)
},
drawProgressBg() {
let ctx = uni.createCanvasContext(this.canvasId, this);
ctx.setLineWidth(this.borderWidthPx); //
ctx.setStrokeStyle(this.inactiveColor); // 线
ctx.beginPath(); //
let radius = this.widthPx / 2;
ctx.arc(radius, radius, radius - this.borderWidthPx, 0, 2 * Math.PI, false);
ctx.stroke(); //
ctx.draw();
},
drawCircleByProgress(progress) {
let ctx = this.progressContext;
if (!ctx) {
ctx = uni.createCanvasContext(this.elId, this);
this.progressContext = ctx;
}
//
ctx.setLineCap('round');
// 线
ctx.setLineWidth(this.borderWidthPx);
ctx.setStrokeStyle(this.activeColor);
//
let time = Math.floor(this.duration / 200);
let endAngle = ((2 * Math.PI) / 100) * progress + this.startAngle;
ctx.beginPath();
// canvas
let radius = this.widthPx / 2;
ctx.arc(radius, radius, radius - this.borderWidthPx, this.startAngle, endAngle, false);
ctx.stroke();
ctx.draw();
//
//
// if (this.newPercent > this.oldPercent) {
// progress++;
// if (progress > this.newPercent) return;
// } else {
// //
// progress--;
// if (progress < this.newPercent) return;
// }
//
progress = this.newPercent;
setTimeout(() => {
//
this.drawCircleByProgress(progress);
// }, time);
}, 0);
}
}
};
</script>
<style scoped>
.circle-progress {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.canvas-bg {
position: absolute;
}
.canvas {
position: absolute;
}
</style>

107
components/city/city.css Normal file
View File

@ -0,0 +1,107 @@
.lotus-address-picker {
font-size: 26rpx;
padding-top: 30rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
line-height: normal;
padding-right: 30rpx;
box-sizing: border-box;
}
.lotus-address-picker-box {
/*display: -webkit-box;
display: -webkit-flex;*/
display: flex;
align-items: center;
justify-content: center;
justify-content: flex-start;
padding-top: 10rpx;
padding-bottom: 10rpx;
}
.lotus-address-picker-box-item {
height: 600upx;
overflow-y: auto;
width: 33.333%;
padding-left: 20rpx;
padding-right: 20rpx;
box-sizing: border-box;
}
.lotus-address-picker2 {
color: #03affb;
position: relative;
}
.lotus-address-picker2:after {
content: '';
position: absolute;
right: 0;
top: 65%;
transform: translateY(-35%) rotate(-45deg);
width: 20rpx;
height: 10rpx;
border-left-width: 4rpx;
border-bottom-width: 4rpx;
border-left-style: solid;
border-bottom-style: solid;
border-left-color: #03affb;
border-bottom-color: #03affb;
}
.lotus-address-mask {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 999;
background: rgba(0, 0, 0, 0.5);
}
.lotus-address-box {
background: #fff;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: auto;
}
.lotus-address-action {
font-size: 30rpx;
/*display: -webkit-box;
display: -webkit-flex;*/
display: flex;
align-items: center;
justify-content: center;
justify-content: space-between;
padding: 25rpx 30rpx;
position: relative;
}
.lotus-address-action:after {
content: " ";
position: absolute;
left: 0;
top: 0;
right: 0;
height: 1px;
border-top: 1px solid #eee;
color: #eee;
transform-origin: 0 0;
transform: scaleY(0.5);
}
.lotus-address-action:before {
content: " ";
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
border-bottom: 1px solid #eee;
color: #eee;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
.lotus-address-action-cancel {
color: #969696;
}
.lotus-address-action-affirm {
color: #03affb;
}

1
components/city/city.js Normal file

File diff suppressed because one or more lines are too long

233
components/city/city.vue Normal file
View File

@ -0,0 +1,233 @@
<template>
<!--地址picker-->
<view :status="checkStatus" v-if="lotusAddressData.visible" class="lotus-address-mask">
<view :class="lotusAddressData.visible?'lotus-address-box':'lotus-address-box lotus-address-box-out'">
<view class="lotus-address-action">
<text @tap="cancelPicker" class="lotus-address-action-cancel">取消</text>
<text @tap="chosedVal" class="lotus-address-action-affirm">确认</text>
</view>
<view class="lotus-address-picker-box">
<!---->
<scroll-view scroll-y :scroll-into-view="'pid'+pChoseIndex" class="lotus-address-picker-box-item">
<view @tap="clickPicker(0,pIndex,pItem);" :id="'pid'+pIndex" :class="pIndex === pChoseIndex?'lotus-address-picker lotus-address-picker2':'lotus-address-picker'" v-for="(pItem,pIndex) in province" :key="pIndex">{{pItem}}</view>
</scroll-view>
<!---->
<scroll-view scroll-y :scroll-into-view="'cid'+cChoseIndex" class="lotus-address-picker-box-item">
<view @tap="clickPicker(1,cIndex,cItem);" :id="'cid'+cIndex" :class="cIndex === cChoseIndex?'lotus-address-picker lotus-address-picker2':'lotus-address-picker'" v-for="(cItem,cIndex) in city" :key="cIndex">{{cItem}}</view>
</scroll-view>
<!---->
<scroll-view scroll-y :scroll-into-view="'tid'+tChoseIndex" class="lotus-address-picker-box-item">
<view @tap="clickPicker(2,tIndex,tItem);" :id="'tid'+tIndex" :class="tIndex === tChoseIndex?'lotus-address-picker lotus-address-picker2':'lotus-address-picker'" v-for="(tItem,tIndex) in town" :key="tIndex">{{tItem}}</view>
</scroll-view>
<!--区END-->
</view>
</view>
</view>
<!--地址picker END-->
</template>
<script>
import {lotusAddressJson} from "./city.js";
export default {
props:['lotusAddressData'],
data() {
return {
visible: false,
province:[],
city:[],
town:[],
provinceName:'',
cityName:'',
townName:'',
type:0,//01
pChoseIndex:-1,
cChoseIndex:-1,
tChoseIndex:-1
};
},
methods:{
//
cancelPicker(){
const provinceCode = this.getTarId(this.provinceName);
const cityCode = this.getTarId(this.cityName);
const townCode = this.getTarId(this.townName);
this.visible = false;
this.$emit("choseVal",{
province:this.provinceName,
provinceCode,
city:this.cityName,
cityCode,
town:this.townName,
townCode,
isChose:0,
visible:false
});
},
//
chosedVal() {
this.type = 1;
const provinceCode = this.getTarId(this.provinceName);
const cityCode = this.getTarId(this.cityName);
const townCode = this.getTarId(this.townName);
this.visible = false;
let isChose = 0;
// isChose = 1
if((this.provinceName&&this.cityName)||(this.provinceName&&this.cityName&&this.townName)){
isChose = 1;
}
this.$emit("choseVal",{
province:this.provinceName,
provinceCode,
city:this.cityName,
cityCode,
town:this.townName,
townCode,
isChose,
visible:false
});
},
//value
getTarId(name,type){
let id = 0;
lotusAddressJson.map((item,index)=>{
if(item.name === name){
id = item.value;
}
});
return id;
},
//
getCityArr(parentId){
let city = [];
lotusAddressJson.map((item,index)=>{
if(item.parent === parentId){
city.push(item.name);
}
});
return city;
},
//
getTownArr(parentId){
let town = [];
lotusAddressJson.map((item,index)=>{
if(index>34&&item.parent === parentId){
town.push(item.name);
}
});
return town;
},
//
initFn(){
if(!this.province.length){
lotusAddressJson.map((item,index)=>{
if(index<=34){
this.province.push(item.name);
}
});
}
//
const p = this._props.lotusAddressData.provinceName;
const c = this._props.lotusAddressData.cityName;
const t = this._props.lotusAddressData.townName;
//
if(p){
this.pChoseIndex = this.getTarIndex(this.province,p);
}
//
if(p&&c){
const pid = this.getTarId(p);
this.city = this.getCityArr(pid);
this.cChoseIndex = this.getTarIndex(this.city,c);
}
//
if(p&&c&&t){
const cid= this.getTarId(c);
this.town = this.getTownArr(cid);
this.tChoseIndex = this.getTarIndex(this.town,t);
}
//
if(!p&&!c&&!t){
this.pChoseIndex = -1;
this.cChoseIndex = -1;
this.tChoseIndex = -1;
this.city = [];
this.town = [];
}
},
//
getChosedData(){
const pid = this.getTarId(this.provinceName,'province');
this.city = this.getCityArr(pid);
const cid= this.getTarId(this.cityName,'city');
this.town = this.getTownArr(cid);
//index
if(this.provinceName){
this.pChoseIndex = this.getTarIndex(this.province,this.provinceName);
}
if(this.cityName){
this.cChoseIndex = this.getTarIndex(this.city,this.cityName);
}
if(this.townName){
this.tChoseIndex = this.getTarIndex(this.town,this.townName);
}
},
//
clickPicker(type,index,name){
//
if(type === 0){
this.pChoseIndex = index;
this.provinceName = name;
this.cChoseIndex = -1;
this.tChoseIndex = -1;
this.cityName = '';
this.townName = '';
}
//
if(type ===1){
this.cChoseIndex = index;
this.cityName = name;
this.tChoseIndex = -1;
this.townName = '';
}
//
if(type === 2){
this.tChoseIndex = index;
this.townName = name;
}
//
this.getChosedData();
},
//index
getTarIndex(arr,tarName){
let cIndex = 0;
arr.map((item,index)=>{
if(item === tarName){
cIndex = index;
}
});
return cIndex;
}
},
computed:{
checkStatus(){
let t = null;
const _this = this;
if(!_this.visible){
_this.visible = _this._props.lotusAddressData.visible;
//
_this.provinceName = _this._props.lotusAddressData.provinceName;
_this.cityName = _this._props.lotusAddressData.cityName;
_this.townName = _this._props.lotusAddressData.townName;
//
_this.initFn();
t = _this.visible;
}
return t;
}
}
}
</script>
<style lang="less">
@import "./city.css";
</style>

View File

@ -0,0 +1,568 @@
<template>
<view class="cmd-progress cmd-progress-default" :class="setStatusClass">
<block v-if="type == 'circle' || type == 'dashboard'">
<view class="cmd-progress cmd-progress-default" :class="setStatusClass">
<view class="cmd-progress-inner" :style="setCircleStyle">
<!-- 绘制圈 start -->
<!-- #ifdef H5 -->
<svg viewBox="0 0 100 100" class="cmd-progress-circle">
<path :d="setCirclePath" stroke="#f3f3f3" :stroke-linecap="strokeShape" :stroke-width="strokeWidth"
fill-opacity="0" class="cmd-progress-circle-trail" :style="setCircleTrailStyle"></path>
<path :d="setCirclePath" :stroke-linecap="strokeShape" :stroke-width="strokeWidth" fill-opacity="0" class="cmd-progress-circle-path"
:style="setCirclePathStyle"></path>
</svg>
<!-- #endif -->
<!-- #ifndef H5 -->
<text :style="setCircle"></text>
<!-- #endif -->
<!-- 绘制圈 end -->
<!-- 状态文本 start -->
<block v-if="showInfo">
<text class="cmd-progress-text" :title="setFormat" :style="{color: strokeColor}">
<block v-if="status != 'success' && status != 'exception' && setProgress < 100">{{setFormat}}</block>
<!-- #ifdef H5 -->
<svg v-if="status == 'exception'" viewBox="64 64 896 896" data-icon="close" width="1em" height="1em" fill="currentColor"
aria-hidden="true">
<path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path>
</svg>
<!-- <svg v-if="status == 'success' || setProgress == 100" viewBox="64 64 896 896" data-icon="check" width="1em"
height="1em" fill="currentColor" aria-hidden="true" :style="{'color': strokeColor ? strokeColor : ''}">
<path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"></path>
</svg> -->
<text v-if="status == 'exception' || status == 'success' || setProgress == 100">{{setFormat}}</text>
<!-- #endif -->
<!-- #ifndef H5 -->
<!-- <text v-if="status == 'exception' || status == 'success' || setProgress == 100" :style="setCircleIcon"></text> -->
<text v-if="status == 'exception' || status == 'success' || setProgress == 100">{{setFormat}}</text>
<!-- #endif -->
</text>
</block>
<!-- 状态文本 end -->
</view>
</view>
</block>
<block v-if="type == 'line'">
<!-- 进度条 start -->
<view class="cmd-progress-outer">
<view class="cmd-progress-inner" :style="{'border-radius': strokeShape == 'square' ? 0 : '100px'}">
<view class="cmd-progress-bg" :style="setLineStyle"></view>
<view v-if="successPercent" class="cmd-progress-success-bg" :style="setLineSuccessStyle"></view>
</view>
</view>
<!-- 进度条 end -->
<!-- 进度条是否显示信息 start -->
<block v-if="showInfo">
<text class="cmd-progress-text" :title="setFormat">
<block v-if="status != 'success' && status != 'exception' && setProgress < 100">{{setFormat}}</block>
<!-- #ifdef H5 -->
<svg v-if="status == 'exception'" viewBox="64 64 896 896" data-icon="close-circle" width="1em" height="1em"
fill="currentColor" aria-hidden="true">
<path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path>
</svg>
<svg v-if="status == 'success' || setProgress == 100" viewBox="64 64 896 896" data-icon="check-circle" width="1em"
height="1em" fill="currentColor" aria-hidden="true" :style="{'color': strokeColor ? strokeColor : ''}">
<path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 0 1-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path>
</svg>
<!-- #endif -->
<!-- #ifndef H5 -->
<!-- <text v-if="status == 'exception' || status == 'success' || setProgress == 100" :style="setLineStatusIcon"></text> -->
<text v-if="status == 'exception' || status == 'success' || setProgress == 100">{{setFormat}}</text>
<!-- #endif -->
</text>
</block>
<!-- 进度条是否显示信息 end -->
</block>
</view>
</template>
<script>
/**
* 进度条组件
* @description 显示一个操作完成的百分比时为用户显示该操作的当前进度和状态
* @tutorial https://ext.dcloud.net.cn/plugin?id=259
* @property {String} type 进度类型 - 线型line圆圈形circle仪表盘dashboard默认线型line
* @property {Number} percent 进度百分比值 - 显示范围0-100 可能数比较大就需要自己转成百分比的值
* @property {Number} success-percent 进度已完成的百分几 - 仅支持进度线型line
* @property {String} status 进度状态 - 涌动active仅支持线型line正常normal完成success失败exception默认正常normal
* @property {Boolean} show-info 进度状态信息 - 是否显示进度数值或状态图标默认true
* @property {Number} stroke-width 进度线条的宽度 - 建议在条线的宽度范围1-50与进度条显示宽度有关默认8
* @property {String} stroke-color 进度线条的颜色 - 渐变色仅支持线型line
* @property {String} stroke-shape 进度线条两端的形状 - round方块直角square默认圆round
* @property {Number} width 进度画布宽度 - 仅支持圆圈形circle仪表盘dashboard默认80
* @property {String} gap-degree 进度圆形缺口角度 - 可取值 0 ~ 360,仅支持圆圈形circle仪表盘dashboard
* @property {String} gap-position 进度圆形缺口位置 - 可取值'top', 'bottom', 'left', 'right',仅支持圆圈形circle仪表盘dashboard
* @example <cmd-progress :percent="30"></cmd-progress>
*/
export default {
name: 'cmd-progress',
props: {
/**
* 类型默认line可选 line circle dashboard
*/
type: {
validator: val => {
return ['line', 'circle', 'dashboard'].includes(val);
},
default: 'line'
},
/**
* 百分比
*/
percent: {
type: Number,
default: 0
},
/**
* 已完成的分段百分仅支持类型line
*/
successPercent: {
type: Number,
default: 0
},
/**
* 是否显示进度数值或状态图标
*/
showInfo: {
type: Boolean,
default: true
},
/**
* 进度状态可选normal success exception active仅支持类型line
*/
status: {
validator: val => {
return ['normal', 'success', 'exception', 'active'].includes(val);
},
default: 'normal'
},
/**
* 条线的宽度1-50与width有关
*/
strokeWidth: {
type: Number,
default: 6
},
/**
* 条线的颜色渐变色仅支持类型line
*/
strokeColor: {
type: String,
default: ''
},
/**
* 线圈底色
*/
circleStrokeColor:{
type:String,
default:''
},
/**
* 条线两端的形状 可选'round', 'square'
*/
strokeShape: {
validator: val => {
return ['round', 'square'].includes(val);
},
default: 'round'
},
/**
* 圆形进度条画布宽度,支持类型circle dashboard
*/
width: {
type: Number,
default: 80
},
/**
* 圆形进度条缺口角度可取值 0 ~ 360,支持类型circle dashboard
*/
gapDegree: {
type: Number,
default: 0
},
/**
* 圆形进度条缺口位置,可取值'top', 'bottom', 'left', 'right' ,支持类型circle dashboard
*/
gapPosition: {
validator: val => {
return ['top', 'bottom', 'left', 'right'].includes(val);
},
default: 'top'
}
},
computed: {
/**
* 如果需要自定义格式就在这改
*/
setFormat() {
return `${this.setProgress}%`;
},
/**
* 设置显示进度值禁止小于0和超过100
*/
setProgress() {
let percent = this.percent;
if (!this.percent || this.percent < 0) {
percent = 0;
} else if (this.percent >= 100) {
percent = 100;
}
return percent;
},
/**
* 进度圈svg大小
*/
setCircleStyle() {
return `width: ${this.width}px;
height: ${this.width}px;
fontSize: ${this.width * 0.15 + 6}px;`
},
/**
* 圈底色
*/
setCircleTrailStyle() {
const radius = 50 - this.strokeWidth / 2;
const len = Math.PI * 2 * radius;
const gapDeg = this.gapDegree || (this.type === 'dashboard' && 75);
return `stroke-dasharray: ${len - (gapDeg||0)}px, ${len}px;
stroke-dashoffset: -${(gapDeg||0) / 2}px;
stroke: ${this.circleStrokeColor};
transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s;`
},
/**
* 圈进度
*/
setCirclePathStyle() {
const radius = 50 - this.strokeWidth / 2;
const len = Math.PI * 2 * radius;
const gapDeg = this.gapDegree || (this.type === 'dashboard' && 75);
return `stroke: ${this.strokeColor};
stroke-dasharray: ${(this.setProgress / 100) * (len - (gapDeg||0))}px, ${len}px;
stroke-dashoffset: -${(gapDeg||0) / 2}px;
transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s, stroke-width 0.06s ease 0.3s;`
},
/**
* 绘制圈
*/
setCirclePath() {
const radius = 50 - this.strokeWidth / 2;
let beginPositionX = 0;
let beginPositionY = -radius;
let endPositionX = 0;
let endPositionY = -2 * radius;
const gapPos = (this.type === 'dashboard' && 'bottom') || this.gapPosition || 'top';
switch (gapPos) {
case 'left':
beginPositionX = -radius;
beginPositionY = 0;
endPositionX = 2 * radius;
endPositionY = 0;
break;
case 'right':
beginPositionX = radius;
beginPositionY = 0;
endPositionX = -2 * radius;
endPositionY = 0;
break;
case 'bottom':
beginPositionY = radius;
endPositionY = 2 * radius;
break;
default:
break;
}
return `M 50,50 m ${beginPositionX},${beginPositionY} a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY} a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`;
},
// #ifndef H5
/**
* 非H5端绘制进度圈svg转base URL
*/
setCircle() {
const radius = 50 - this.strokeWidth / 2;
const len = Math.PI * 2 * radius;
const gapDeg = this.gapDegree || (this.type === 'dashboard' && 75);
let currentColor = '#108ee9'
//
if (this.status == 'exception') {
currentColor = '#f5222d'
}
//
if (this.status == 'success' || this.setProgress >= 100 || this.strokeColor) {
currentColor = this.strokeColor || '#52c41a'
}
let svgToBase =
`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' class='cmd-progress-circle'%3E%3Cpath d='${this.setCirclePath}' stroke='%23f3f3f3' stroke-linecap='${this.strokeShape}' stroke-width='${this.strokeWidth}' fill-opacity='0' class='cmd-progress-circle-trail' style='stroke-dasharray: ${len - (gapDeg||0)}px, ${len}px;stroke-dashoffset: -${(gapDeg||0) / 2}px;transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s;'%3E%3C/path%3E%3Cpath d='${this.setCirclePath}' stroke-linecap='${this.strokeShape}' stroke-width='${this.strokeWidth}' fill-opacity='0' class='cmd-progress-circle-path' style='stroke: ${escape(currentColor)};stroke-dasharray: ${(this.setProgress / 100) * (len - (gapDeg||0))}px, ${len}px;stroke-dashoffset: -${(gapDeg||0) / 2}px;transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s, stroke-width 0.06s ease 0.3s;'%3E%3C/path%3E%3C/svg%3E`
return `background-image: url("${svgToBase}");
background-size: cover;
display: inline-block;
${this.setCircleStyle}`;
},
/**
* 设置进度圈状态图标
*/
setCircleIcon() {
let currentColor = '#108ee9'
let svgToBase = ''
//
if (this.status == 'exception') {
currentColor = '#f5222d'
svgToBase =
`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896' data-icon='close' width='1em' height='1em' fill='${escape(currentColor)}' aria-hidden='true'%3E %3Cpath d='M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z'%3E%3C/path%3E %3C/svg%3E`;
}
//
if (this.status == 'success' || this.setProgress >= 100) {
currentColor = this.strokeColor || '#52c41a'
// svgToBase = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896' data-icon='check' width='1em' height='1em' fill='${escape(currentColor)}' aria-hidden='true'%3E %3Cpath d='M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z'%3E%3C/path%3E %3C/svg%3E`;
}
return `background-image: url("${svgToBase}");
background-size: cover;
display: inline-block;
width: 1em;
height: 1em;`;
},
// #endif
/**
* 设置进度条样式
*/
setLineStyle() {
return `width: ${this.setProgress}%;
height: ${this.strokeWidth}px;
background: ${this.strokeColor};
border-radius: ${this.strokeShape === 'square' ? 0 : '100px'};`;
},
/**
* 设置已完成分段进度
*/
setLineSuccessStyle() {
let successPercent = this.successPercent;
if (!this.successPercent || this.successPercent < 0 || this.setProgress < this.successPercent) {
successPercent = 0;
} else if (this.successPercent >= 100) {
successPercent = 100;
}
return `width: ${successPercent}%;
height: ${this.strokeWidth}px;
border-radius: ${this.strokeShape === 'square' ? 0 : '100px'};`;
},
// #ifndef H5
/**
* 设置进度条状态图标
*/
setLineStatusIcon() {
let currentColor = '#108ee9'
let svgToBase = ''
//
if (this.status == 'exception') {
currentColor = '#f5222d'
svgToBase =
`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896' data-icon='close-circle' width='1em' height='1em' fill='${escape(currentColor)}' aria-hidden='true'%3E %3Cpath d='M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z'%3E%3C/path%3E %3C/svg%3E`;
}
//
if (this.status == 'success' || this.setProgress >= 100) {
currentColor = this.strokeColor || '#52c41a'
svgToBase =
`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896' data-icon='check-circle' width='1em' height='1em' fill='${escape(currentColor)}' aria-hidden='true'%3E %3Cpath d='M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 0 1-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z'%3E%3C/path%3E %3C/svg%3E`;
}
return `background-image: url("${svgToBase}");
background-size: cover;
display: inline-block;
width: 1em;
height: 1em;`;
},
// #endif
/**
* 状态样式
*/
setStatusClass() {
let statusClass = [];
//
if (this.status == 'exception') {
statusClass.push('cmd-progress-status-exception')
}
//
if (this.status == 'success' || this.setProgress >= 100) {
statusClass.push('cmd-progress-status-success')
}
//
if (this.status == 'active') {
statusClass.push('cmd-progress-status-active')
}
//
if (this.showInfo) {
statusClass.push('cmd-progress-show-info')
}
//
if (this.type === 'line') {
statusClass.push('cmd-progress-line')
}
//
if (this.type === 'circle' || this.type === 'dashboard') {
statusClass.push('cmd-progress-circle')
}
statusClass.push('cmd-progress-status-normal')
return statusClass;
}
}
}
</script>
<style>
.cmd-progress {
box-sizing: border-box;
margin: 0;
padding: 0;
list-style: none;
display: inline-block;
}
.cmd-progress-line {
width: 100%;
font-size: 28upx;
position: relative;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.cmd-progress-outer {
display: inline-block;
width: 100%;
margin-right: 0;
padding-right: 0;
}
.cmd-progress-show-info .cmd-progress-outer {
flex: 1;
}
.cmd-progress-inner {
display: inline-block;
width: 100%;
background-color: #f5f5f5;
border-radius: 200upx;
vertical-align: middle;
position: relative;
}
.cmd-progress-circle-trail {
stroke: #f5f5f5;
}
.cmd-progress-circle-path {
stroke: #1890ff;
animation: appear 0.3s;
}
.cmd-progress-success-bg,
.cmd-progress-bg {
background-color: #1890ff;
transition: all 0.4s cubic-bezier(0.08, 0.82, 0.17, 1) 0s;
position: relative;
}
.cmd-progress-success-bg {
background-color: #52c41a;
position: absolute;
top: 0;
left: 0;
}
.cmd-progress-text {
word-break: normal;
width: 60upx;
text-align: left;
margin-left: 16upx;
vertical-align: middle;
display: inline-block;
white-space: nowrap;
color: rgba(0, 0, 0, 0.45);
line-height: 1;
}
.cmd-progress-status-active .cmd-progress-bg:before {
content: "";
opacity: 0;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #fff;
border-radius: 20upx;
-webkit-animation: cmd-progress-active 2.4s cubic-bezier(0.23, 1, 0.32, 1) infinite;
animation: cmd-progress-active 2.4s cubic-bezier(0.23, 1, 0.32, 1) infinite;
}
.cmd-progress-status-exception .cmd-progress-bg {
background-color: #f5222d;
}
.cmd-progress-status-exception .cmd-progress-text {
color: #f5222d;
}
.cmd-progress-status-exception .cmd-progress-circle-path {
stroke: #f5222d;
}
.cmd-progress-status-success .cmd-progress-bg {
background-color: #52c41a;
}
.cmd-progress-status-success .cmd-progress-text {
color: #52c41a;
}
.cmd-progress-status-success .cmd-progress-circle-path {
stroke: #52c41a;
}
.cmd-progress-circle .cmd-progress-inner {
position: relative;
line-height: 1;
background-color: transparent;
}
.cmd-progress-circle .cmd-progress-text {
display: block;
position: absolute;
width: 100%;
text-align: center;
line-height: 1;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
left: 0;
margin: 0;
color: rgba(0, 0, 0, 0.65);
white-space: normal;
}
.cmd-progress-circle .cmd-progress-status-exception .cmd-progress-text {
color: #f5222d;
}
.cmd-progress-circle .cmd-progress-status-success .cmd-progress-text {
color: #52c41a;
}
@keyframes cmd-progress-active {
0% {
opacity: 0.1;
width: 0;
}
20% {
opacity: 0.5;
width: 0;
}
100% {
opacity: 0;
width: 100%;
}
}
</style>

View File

@ -0,0 +1,65 @@
<template>
<view>
<view class="pad-zy30" :style="{paddingTop:statusBarHeight + 'px',paddingBottom: '70px'}">
<slot name="content"></slot>
</view>
</view>
</template>
<script>
export default {
name:"container-subgroup-two",
props:{
ifLoading:{
type:Boolean,
default:true
}
},
data() {
return {
statusBarHeight:uni.getSystemInfoSync().statusBarHeight + 50,
loading:true,
exist:''
};
},
//
beforeCreate(){
},
//
created(){
},
//
beforeMount(){
},
//
mounted(){
setTimeout(()=>{
this.loading = false;
},500)
},
//
beforeUpdate(){
},
//
updated(){
},
//
beforeDestroy(){
},
//
destroyed(){
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,85 @@
<template>
<view>
<view v-if="loading && ifLoading" class="container-loading">
<view class="loading-box">
<span></span>
<span></span>
<span></span>
<span></span>
</view>
</view>
<view v-else class="pad-zy20" style="padding-bottom: 70px;">
<slot name="content"></slot>
</view>
</view>
</template>
<script>
export default {
name:"container-subgroup",
props:{
ifLoading:{
type:Boolean,
default:true
}
},
data() {
return {
statusBarHeight:uni.getStorageSync('statusBar') + 50,
loading:true,
exist:''
};
},
//
beforeCreate(){
this.exist = uni.getStorageSync('token');
this.exist ? this.loading = false : this.loading = true;
},
//
created(){
},
//
beforeMount(){
},
//
mounted(){
setTimeout(()=>{
this.loading = false;
},500)
},
//
beforeUpdate(){
},
//
updated(){
},
//
beforeDestroy(){
},
//
destroyed(){
}
}
</script>
<style scoped>
.container-loading {position: fixed;top: 0;left: 0;bottom: 0;right: 0;display: flex;justify-content: center;align-items: center;}
.container-loading .loading-box {width: 80rpx;display: flex;flex-wrap: wrap;animation: rotate 3s linear infinite;}
@keyframes rotate{
to{transform: rotateZ(360deg);}
}
.container-loading .loading-box span {width: 32rpx;height: 32rpx;background-color: #000000;margin: 4rpx;animation: scale 1.5s linear infinite;}
@keyframes scale{
50%{transform: scale(1);}
}
.container-loading .loading-box span:nth-child(1){border-radius: 50% 50% 0 50%;transform-origin: bottom right;}
.container-loading .loading-box span:nth-child(2){border-radius: 50% 50% 50% 0;transform-origin: bottom left;animation-delay: .5s;}
.container-loading .loading-box span:nth-child(3){border-radius: 50% 0 50% 50%;transform-origin: top right;animation-delay: 1.5s;}
.container-loading .loading-box span:nth-child(4){border-radius: 0 50% 50% 50%;transform-origin: top left;animation-delay: 1s;}
</style>

View File

@ -0,0 +1,295 @@
<template>
<view class="datetime-picker">
<view class="mask" :class="{ show: open }" @touchmove.stop.prevent catchtouchmove="true"></view>
<view class="wrap" :class="{ show: open }">
<view class="picker-header" @touchmove.stop.prevent catchtouchmove="true">
<view class="btn-picker cancel" @click="open = false">取消</view>
<view class="btn-picker submit" @click="_onSubmit"></view>
</view>
<view class="picker-body">
<picker-view :value="value" @change="_onChange">
<picker-view-column>
<view class="column-item" v-for="item in years" :key="item">
{{ item + "年" }}
</view>
</picker-view-column>
<picker-view-column>
<view class="column-item" v-for="item in months" :key="item">
{{ formatNum(item) + "月" }}
</view>
</picker-view-column>
<picker-view-column>
<view class="column-item" v-for="item in days" :key="item">
{{ formatNum(item) + "日" }}
</view>
</picker-view-column>
<picker-view-column>
<view class="column-item" v-for="item in hours" :key="item">
{{ formatNum(item) + "时" }}
</view>
</picker-view-column>
<picker-view-column>
<view class="column-item" v-for="item in minutes" :key="item">
{{ formatNum(item) + "分" }}
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "buuug7-simple-datetime-picker",
props: {
startYear: {
type: Number,
default: 2000,
},
endYear: {
type: Number,
default: 2030,
},
},
data() {
return {
open: false,
years: [],
months: [],
days: [],
hours: [],
minutes: [],
currentDate: new Date(),
year: "",
month: "",
day: "",
hour: "",
minute: "",
value: [0, 0, 0, 0, 0],
};
},
mounted() {
this.init();
},
watch: {
month() {
this.initDays();
},
},
methods: {
init() {
this.initYears();
this.initMonths();
this.initDays();
this.initHours();
this.initMinutes();
this.setSelectValue();
},
initYears() {
const years = [];
for (let year = this.startYear; year <= this.endYear; year++) {
years.push(year);
if (this.currentDate.getFullYear() === year) {
this.$set(this.value, 0, year - this.startYear);
}
}
this.years = years;
},
initMonths() {
const months = [];
for (let month = 1; month <= 12; month++) {
months.push(month);
if (this.currentDate.getMonth() + 1 === month) {
this.$set(this.value, 1, month - 1);
}
}
this.months = months;
},
initDays() {
const value = this.value;
const selectedYear = this.years[value[0]];
const selectedMonth = this.months[value[1]];
const days = [];
const totalDays = new Date(selectedYear, selectedMonth, 0).getDate();
for (let day = 1; day <= totalDays; day++) {
days.push(day);
if (this.currentDate.getDate() === day) {
this.$set(value, 2, day - 1);
}
}
this.days = days;
},
initHours() {
const hours = [];
for (let hour = 0; hour <= 23; hour++) {
hours.push(hour);
if (this.currentDate.getHours() === hour) {
this.$set(this.value, 3, hour);
}
}
this.hours = hours;
},
initMinutes() {
const minutes = [];
for (let minute = 0; minute < 60; minute++) {
minutes.push(minute);
if (this.currentDate.getMinutes() === minute) {
this.$set(this.value, 4, minute);
}
}
this.minutes = minutes;
},
show() {
this.open = true;
},
hide() {
this.open = false;
},
_onChange(e) {
this.value = e.detail.value;
this.setSelectValue();
},
setSelectValue() {
const v = this.value;
this.year = this.years[v[0]];
this.month = this.months[v[1]];
this.day = this.days[v[2]];
this.hour = this.hours[v[3]];
this.minute = this.minutes[v[4]];
},
_onSubmit() {
const {
year,
month,
day,
hour,
minute,
formatNum
} = this;
const result = {
year: formatNum(year),
month: formatNum(month),
day: formatNum(day),
hour: formatNum(hour),
minute: formatNum(minute),
};
this.$emit("submit", result);
this.hide();
},
formatNum(num) {
return num < 10 ? "0" + num : num + "";
},
},
};
</script>
<style lang="scss">
$transition: all 0.3s ease;
$primary: #488ee9;
.datetime-picker {
position: relative;
z-index: 999;
picker-view {
height: 100%;
}
.mask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.6);
visibility: hidden;
opacity: 0;
transition: $transition;
&.show {
visibility: visible;
opacity: 1;
}
}
.wrap {
z-index: 1001;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: $transition;
transform: translateY(100%);
&.show {
transform: translateY(0);
}
}
.picker-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 8px 8px;
background-color: darken(#fff, 2%);
background-color: #fff;
}
.picker-body {
width: 100%;
height: 420rpx;
overflow: hidden;
background-color: #fff;
}
.column-item {
text-overflow: ellipsis;
white-space: nowrap;
display: flex;
justify-content: center;
align-items: center;
}
.btn-picker {
position: relative;
display: inline-block;
padding-left: 10px;
padding-right: 10px;
box-sizing: border-box;
text-align: center;
text-decoration: none;
line-height: 2;
-webkit-tap-highlight-color: transparent;
overflow: hidden;
background-color: #eee;
font-size: 14px;
// border-radius: 2px;
color: #000;
cursor: pointer;
}
.btn-picker.submit {
background-color: $primary;
color: #fff;
}
}
</style>

View File

@ -0,0 +1,133 @@
<template>
<view @click="toggle" class="evan-switch" :class="{'evan-switch--disabled':disabled}" :style="{width:2*size+'px',height:switchHeight,borderRadius:size+'px',backgroundColor:currentValue===activeValue?activeColor:inactiveColor}">
<view class="evan-switch__circle" :style="{width:size+'px',height:size+'px',transform:currentValue===activeValue?`translateX(${size}px)`:`translateX(0)`}"></view>
</view>
</template>
<script>
export default {
name: 'EvanSwitch',
props: {
value: {
type: [String, Number, Boolean],
default: false
},
activeColor: {
type: String,
default: '#108ee9'
},
inactiveColor: {
type: String,
default: '#fff'
},
size: {
type: Number,
default: 30
},
disabled: {
type: Boolean,
default: false
},
activeValue: {
type: [String, Number, Boolean],
default: true
},
inactiveValue: {
type: [String, Number, Boolean],
default: false
},
beforeChange: {
type: Function,
default: null
},
extraData: null,
contextLevel: {
type: Number,
default: 1
}
},
computed: {
switchHeight() {
// #ifdef APP-NVUE
return this.size + 2 + 'px'
// #endif
// #ifndef APP-NVUE
return this.size + 'px'
// #endif
}
},
watch: {
value: {
immediate: true,
handler(value) {
this.currentValue = value
}
}
},
data() {
return {
currentValue: false
}
},
methods: {
toggle() {
if (!this.disabled) {
if (this.beforeChange && typeof this.beforeChange === 'function') {
let context = this
for (let i = 0; i < this.contextLevel; i++) {
context = context.$options.parent
}
const result = this.beforeChange(this.currentValue === this.activeValue ? this.inactiveValue : this.activeValue,
this.extraData, context)
if (typeof result === 'object') {
result.then(() => {
this.toggleValue()
}).catch(() => {})
} else if (typeof result === 'boolean' && result) {
this.toggleValue()
}
} else {
this.toggleValue()
}
}
},
toggleValue() {
this.currentValue = this.currentValue === this.activeValue ? this.inactiveValue : this.activeValue
this.$emit('input', this.currentValue)
this.$emit('change', this.currentValue)
}
}
}
</script>
<style lang="scss" scoped>
.evan-switch {
position: relative;
border-width: 1px;
border-color: rgba(0, 0, 0, 0.1);
border-style: solid;
transition: background-color 0.3s;
/* #ifndef APP-NVUE */
box-sizing: content-box;
/* #endif */
}
.evan-switch--disabled {
opacity: 0.3;
}
.evan-switch__circle {
position: absolute;
left: 0;
top: 0;
background-color: #fff;
border-radius: 50%;
/* #ifndef APP-NVUE */
box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
/* #endif */
/* #ifdef APP-NVUE */
box-shadow: 1px 0 0px 0 rgba(0, 0, 0, 0.05);
/* #endif */
transition: transform 0.3s;
}
</style>

View File

@ -0,0 +1,68 @@
<template>
<view class="tab">
<view class="foot-tab">
<view class="li" v-for="(item,index) in tabList">
<image src="" class="icon" ></image>
<view class="text">
{{item.title}}
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
tabList:[
{
title:"首页"
},
{
title:"发起抽奖"
},
{
title:"我的"
}
]
}
},
methods: {
}
}
</script>
<style>
.tab{
width: 100%;
background-color: #FFFFFF;position: fixed;
bottom: 0rpx;
left: 0rpx;
height: 108rpx;
box-shadow: 0px -4rpx 12rpx 12rpx rgba(0, 0, 0, 0.07);
}
.foot-tab{
display: flex;
width: 100%;
height: 100%;
justify-content: space-between;
color: rgba(16, 16, 16, 100);
align-items: center;
padding: 0 50rpx;
box-sizing: border-box;
font-size: 24rpx;
text-align: center;
font-family: PingFangSC-regular;
color: #101010;
}
.foot-tab .icon{
width: 48rpx;
height: 48rpx;
margin: auto;
background-color: rgba(227, 227, 227, 100);
}
</style>

View File

@ -0,0 +1,85 @@
<template>
<view>
<view @tap="chooseItem(index)" v-for="(item,index) in list" :key="index"
class="item-box display-between-center">
<view class="display-between-center">
<view class="display-center-center left-box">
<image v-if="item.leftImg!=''"
:style="{width:[26,38,40,33][index]+'rpx',height:[36,38,40,31][index]+'rpx'}"
:src="item.leftImg" mode="widthFix" lazy-load></image>
</view>
<view class="item-title">{{item.title}}</view>
</view>
<view class="display-between-center">
<view class="item-content">{{item.content}}</view>
<i class='icon icon-next' style="font-size: 28rpx;color: #8c8c9b;"></i>
</view>
</view>
</view>
</template>
<script>
export default {
name:"function-list",
props:{
list:{
type:Array,
default:()=>{
return [
{
leftImg:'/static/public/icon-address.png',
title:'收货地址',
num:0,
content:'',
rightImg:'',
url:''
},
{
leftImg:'/static/public/icon-distribution.png',
title:'分销中心',
num:0,
content:'百万奖金等你来拿',
rightImg:'',
url:''
},
{
leftImg:'/static/public/icon-duty.png',
title:'免责声明',
num:0,
content:'',
rightImg:'',
url:''
},
{
leftImg:'/static/public/icon-aboutus.png',
title:'关于我们',
num:0,
content:'',
rightImg:'',
url:''
}
]
}
}
},
data() {
return {};
},
methods:{
chooseItem(index){
uni.navigateTo({
url: this.list[index].url
})
}
}
}
</script>
<style scoped>
.display-between-center {display: flex;justify-content: space-between;align-items: center;}
.display-center-center {display: flex;justify-content: center;align-items: center;}
.item-box{padding: 30rpx 0;}
.left-box{width: 40rpx;height: 40rpx;margin-right: 20rpx;}
.item-title {font-size: 30rpx;color: #000000;}
.item-content {font-size: 24rpx;color: #8c8c9b;margin-right: 10rpx;}
</style>

View File

@ -0,0 +1,75 @@
<template>
<view id="main-img">
<!-- <view class="mar-x40" v-for="(item,index) in list" :key="index"> -->
<!-- 活动商品 start -->
<view v-for="(item,index) in activityList" :key="index" class="mar-x50">
<h1 class="fon36 bold">{{item.name}}</h1>
<view class="colpeili fon26 mar-s20 mar-x40 clips1">{{item.subtitle}}</view>
<view class="posir" @tap="goDetail(item.id)">
<image class="radius30 animated fadeIn" :src="item.cover" mode="aspectFill" lazy-load style="height: 425rpx;width: 100%;" :style="{height:activityHeight + 'px'}"></image>
<view v-if="item.tag!=''" class="posia fon24 colf pad-zy10 pad-s10 pad-x20 activity-img"></view>
</view>
</view>
<!-- 活动商品 end -->
<!-- 子商品 start -->
<view class="disjbac fw">
<view @tap="goDetail(item.id)" class="width47 mar-x50 posir" v-for="(item,index) in list" :key="index">
<image :src="item.cover" mode="aspectFill" lazy-load style="width: 100%;height: 312rpx;border-radius: 30rpx;"></image>
<view class="clips2 fon30 col0 linh50" style="height: 100rpx;">{{item.name}}</view>
<view class="fon30 colpeili">{{item.price}}</view>
<view v-if="item.tag!=''" class="posia fon24 colf pad-zy10 pad-s10 pad-x20 activity-img"></view>
</view>
</view>
<!-- 子商品 end -->
<!-- </view> -->
</view>
</template>
<script>
export default {
name:"list-one",
props:{
list:{
type:Array,
default:()=>{
return []
}
},
activityList:{
type:Array,
default:()=>{
return []
}
}
},
data() {
return {
check:uni.getStorageSync('is_active'),
activityHeight:''
};
},
mounted() {
uni.createSelectorQuery().in(this).select('#main-img').boundingClientRect().exec(rect => {
this.activityHeight = rect[0].width;
console.log(this.activityHeight,55);
});
},
methods:{
goDetail(id){//
if(this.check){
uni.navigateTo({
url:`/pagesB/shopDetail/shopDetail?id=${id}`
})
} else {
uni.navigateTo({
url:`/pages/login/login`
})
}
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,163 @@
<template>
<scroll-view scroll-y @scrolltolower="scrollBottomEv" :style="{height: scrollHeight +'px'}">
<view class="disjbac fw">
<view @tap="goDetail(item.id)" class="width48_5 mar-x50 posir" v-for="(item,index) in dataList" :key="index">
<image class="animated fadeIn" :src="item.imgSrc" mode="aspectFill" style="width: 100%;height: 312rpx;border-radius: 30rpx;"></image>
<view class="clips2 fon30 col0 linh50" style="height: 100rpx;">{{item.title}}</view>
<view class="fon30 colpeili">{{item.price}}</view>
<view v-if="item.isActivity" class="posia fon24 colf pad-zy10 pad-s10 pad-x20 activity-img"></view>
</view>
</view>
<!-- 暂无更多数据 -->
<pitera v-if="showpitera"></pitera>
</scroll-view>
</template>
<script>
//
import pitera from '@/components/nothing/pitera.vue';
export default {
name:"list-two",
components:{
pitera
},
props:{
//
scrollCate:{
type:Number,
default:1
},
//
pageSource: {
type:Number,
default:1
}
},
data() {
return {
scrollHeight:uni.getStorageSync('scrollHeight'),
//
dataList:[
{
id:1,
imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',
title:'于亿年宝藏中臻选1的宝',
price:'2,000',
isActivity:true,
},
{
id:1,
imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',
title:'于亿年宝藏中臻选1的宝石级钻石每年开采数级钻石每年开采数',
price:'2,000',
isActivity:false,
},
{
id:1,
imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',
title:'于亿年宝藏中臻选',
price:'2,000',
isActivity:false,
},
{
id:1,
imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',
title:'于亿年宝藏中臻选',
price:'2,000',
isActivity:true,
},
{
id:1,
imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',
title:'于亿年宝藏中臻选',
price:'2,000',
isActivity:false,
},
{
id:1,
imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',
title:'于亿年宝藏中臻选1的宝石级钻石每年开采数',
price:'2,000',
isActivity:false,
},
{
id:1,
imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',
title:'于亿年宝藏中臻选1的宝石级钻石每年开采数的宝石级钻石每年开采数',
price:'2,000',
isActivity:false,
},
{
id:1,
imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',
title:'于亿年宝藏中臻选',
price:'2,000',
isActivity:false,
},
{
id:1,
imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',
title:'于亿年宝藏中臻选1的宝石级钻石每年开采数的宝石级钻石每年开采数',
price:'2,000',
isActivity:false,
}
],
page:1, //
size:10, //
total:0, //
showpitera:true, //
};
},
mounted() {
switch (this.scrollCate){
case 1:
this.scrollHeight = uni.getStorageSync('scrollHeight-one'); // App.vue
break;
case 2:
this.scrollHeight = uni.getStorageSync('scrollHeight-two'); // App.vue
break;
case 3:
this.scrollHeight = uni.getStorageSync('scrollHeight-three'); // App.vue
break;
case 4:
this.scrollHeight = uni.getStorageSync('scrollHeight-four'); // App.vue
break;
}
switch (this.pageSource){
case 1:
this.checkList();
break;
}
},
methods:{
checkList(){
console.log('列表事件')
},
//
scrollBottomEv(){
console.log('触底了',55)
//
if(this.total!=this.dataList.length){
// +1
this.page++
switch (this.pageSource){
case 1:
// this.checkList();//
break;
}
} else {
//
this.pitera = true;
}
},
goDetail(id){//
uni.navigateTo({
url:`/pagesB/shopDetail/shopDetail?id=${id}`
})
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,61 @@
<template>
<text :style="{ color: color, 'font-size': size + 'rpx' }" :class="{isTheme:isTheme}" class="lw-icons"
@click="_onClick">{{icons[icon]}}</text>
</template>
<script>
import icons from './icons.js';
// #ifdef APP-NVUE
var domModule = weex.requireModule('dom');
domModule.addRule('fontFace', {
'fontFamily': 'iconfont',
'src': 'url(\'https://at.alicdn.com/t/font_2294175_vq7ymlkpbtm.ttf\')',
});
// #endif
export default {
name: 'UniIcons',
props: {
icon: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 50
},
isTheme: {
type: Boolean,
default: false
}
},
data() {
return {
icons: icons
}
},
methods: {
_onClick() {
this.$emit('click')
}
}
}
</script>
<style lang="scss" scoped>
/* #ifndef APP-NVUE */
@font-face {
font-family: iconfont;
src: url('https://at.alicdn.com/t/font_2294175_vq7ymlkpbtm.ttf')
}
/* #endif */
.lw-icons {
font-family: iconfont;
text-decoration: none;
text-align: center;
}
</style>

View File

@ -0,0 +1,6 @@
export default {
'aixin':'\ue8ab',
'rules':'\ue909',
'sound':'\ue8ea',
'arrowright':'\uee02'
}

View File

@ -0,0 +1,372 @@
<template>
<view>
<view class="contentBox" v-if="list.length" @click="toEmit()"
:style="'color:' + color + ';background-color:' + backgroundColor + ';height:' + height+'rpx;'">
<view v-if="showIcon" class="supBox">
<lwIcon :size="32" :color="iconColor" icon="sound"></lwIcon>
</view>
<view v-if="list.length > 1" class="content">
<view v-for="(item, index) in list" :key="index" @tap.stop="dangGao(index)">
<view class="loopItemBase" :class="index==0&&firstIn?'fistInClass':''"
:animation="realAnimation(index)" v-if="aindexArr.includes(index)"
:style="'line-height:'+height+'rpx;'">
{{ item }}
</view>
</view>
</view>
<view v-if="list.length == 1" class="content">
<view :style="'line-height:'+height+'rpx;'" @tap.stop="dangGao(0)" class="loopItemBaseShow">{{ list[0] }}</view>
</view>
<view v-if="showMore" class="offBox">
<lwIcon :size="32" :color="moreColor" icon="arrowright"></lwIcon>
</view>
</view>
</view>
</template>
<script>
/*
lw-notice公告上下轮询组件组件内依赖了自有的字体图标组件可自行替换为uni或自身项目的图标组件
color:字体颜色
backgroundColor:背景色
list:要循环的列表数据
height:组件高度
showScale:是否有缩放动画
runTime:间隔切换时间
showIcon:是否显示头部小喇叭
iconColor:小喇叭的颜色
showMore:是否显示尾部更多
moreColor:显示更多的颜色
*/
import lwIcon from './iconFont.vue'
export default {
components: {
lwIcon
},
props: {
color: {
type: String,
default: '#666666'
},
backgroundColor: {
type: String,
default: '#f5f5f5'
},
list: {
type: Array,
default: function(){
return []
}
},
height: {
type: Number,
default: 40
},
showScale: {
type: Boolean,
default: false
},
runTime: {
type: Number,
default: 4000
},
showIcon: {
type: Boolean,
default: false
},
showMore: {
type: Boolean,
default: false
},
iconColor: {
type: String,
default: '#aaaaaa'
},
moreColor: {
type: String,
default: '#aaaaaa'
}
},
data() {
return {
//
firstIn: true,
//
aindexArr: [],
//
animation: null,
//
animationData: null,
//
animationDataTwo: null,
//
indexLinkAnimationObj: {},
setTimerOne: null,
setTimerTwo: null,
setTimerThree: null,
setTimerFour: null,
setTimerFive: null
};
},
beforeDestroy() {
this.resetPage()
},
computed: {
//
realAnimation() {
return function(value) {
if (this.indexLinkAnimationObj[value]) {
return this[this.indexLinkAnimationObj[value]]
} else {
return {}
}
}
}
},
methods: {
// 3000
// 1.a 1 1 0ms
// 2.b 2 2 200ms
// 3.a 1 1 300ms
// 4.c 1 1 400ms
// 5.b 2 2 500ms
// 6.a 2 2 600ms
// 7.c 1 1 700ms
// 8.b 1 1 800ms
// 9.a 2 2 900ms
// 10.c 2 2 1000ms
initPage() {
this.resetPage();
if (this.list && this.list.length) {
if (this.list.length > 1) {
this.aindexArr.push(0);
this.animation = uni.createAnimation({
timingFunction: 'linear',
})
// #ifdef H5
this.animationDataH5 = this.animation.translateY(-100).step({
duration: 10000
}).export()
// #endif
this.runAnimation(0, true);
}
}
},
//
resetPage() {
//
clearTimeout(this.setTimerOne);
clearTimeout(this.setTimerTwo);
clearTimeout(this.setTimerThree);
clearTimeout(this.setTimerFour);
clearTimeout(this.setTimerFive);
//
this.aindexArr = [];
this.animation = null;
this.animationData = null;
this.animationDataTwo = null;
this.indexLinkAnimationObj = {};
},
// ()
runAnimation(value, firstIn) {
let that = this;
if (!firstIn) {
that.aindexArr.push(value);
}
//
let lockText = that.createAni(firstIn);
// 50(dom)
that.setTimerOne = setTimeout(() => {
//
that.indexLinkAnimationObj[value] = lockText;
// console.log('')
// console.log(that.indexLinkAnimationObj)
//
let unitRunTime = (that.runTime - 50) / 6;
let waitTime = firstIn ? unitRunTime * 4 : unitRunTime * 5;
let waitTimeTwo = firstIn ? (that.runTime - unitRunTime) : that.runTime;
// #ifdef H5
waitTimeTwo = firstIn ? (that.runTime - (1.5 * unitRunTime)) : that.runTime;
//H5
if (firstIn) {
that.aindexArr.splice(0, 1);
that.aindexArr.push(0);
}
// #endif
//
that.setTimerTwo = setTimeout(() => {
let Index = value == that.list.length - 1 ? 0 : value + 1;
that.runAnimation(Index)
}, waitTime)
//
that.setTimerThree = setTimeout(() => {
let index = that.aindexArr.indexOf(value);
that.aindexArr.splice(index, 1)
that.firstIn = false;
delete that.indexLinkAnimationObj[value]
}, waitTimeTwo)
}, 50)
},
//
createAni(firstIn) {
let that = this;
let unitRunTime = (that.runTime - 50) / 6;
let delayTime = unitRunTime * 4;
let durationTime = unitRunTime;
let dispairTime = unitRunTime;
// #ifdef H5
delayTime = unitRunTime * 3.5;
dispairTime = unitRunTime * 1.5;
// #endif
let showTransformHeight = -uni.upx2px(that.height);
let hideTransformHeight = showTransformHeight * 2;
//
if (that.showScale) {
if (firstIn) {
// that.animation.translateY(1).scale(1,1).step({ duration: 5 });
that.animation.translateY(showTransformHeight).scale(0.5, 0.5).step({
delay: delayTime,
duration: dispairTime
});
} else {
that.animation.translateY(showTransformHeight).scale(1, 1).step({
duration: durationTime
});
that.animation.translateY(hideTransformHeight).scale(0.5, 0.5).step({
delay: delayTime,
duration: dispairTime
});
}
} else {
if (firstIn) {
// that.animation.translateY(1).step({ duration: 5 });
that.animation.translateY(showTransformHeight).step({
delay: delayTime,
duration: dispairTime
});
} else {
that.animation.translateY(showTransformHeight).step({
duration: durationTime
});
that.animation.translateY(hideTransformHeight).step({
delay: delayTime,
duration: dispairTime
});
}
}
//
if (!that.animationData) {
that.animationData = that.animation.export()
that.setTimerFour = setTimeout(() => {
clearTimeout(that.setTimerFour)
that.animationData = false;
}, that.runTime)
return 'animationData'
} else {
that.animationDataTwo = that.animation.export()
that.setTimerFive = setTimeout(() => {
clearTimeout(that.setTimerFive)
that.animationDataTwo = false;
}, that.runTime)
return 'animationDataTwo'
}
},
//
toEmit() {
let that = this
if (that.list.length == 1) {
that.$emit('itemClick', that.list[0])
} else {
that.$emit('itemClick', that.list[that.aindexArr[0]])
}
},
dangGao(index){
let that = this
if (that.list.length != 0) {
that.$emit('dangGao', index)
}
}
},
created() {
},
mounted() {
// list
// setTimeout()
this.initPage()
},
watch: {
list(value) {
this.initPage()
}
}
};
</script>
<style lang="scss" scoped>
.contentBox {
width: 100%;
display: flex;
// padding: 0 20rpx;
align-items: center;
box-sizing: border-box;
font-size: 24rpx;
.supBox {
width: 50rpx;
display: flex;
justify-content: flex-start;
}
.offBox {
width: 50rpx;
display: flex;
justify-content: flex-end;
}
.content {
width: 100%;
flex-grow: 1;
height: 100%;
display: flex;
overflow: hidden;
position: relative;
align-items: center;
box-sizing: border-box;
justify-content: center;
.loopItemBase {
left: 0;
top: 100%;
width: 100%;
height: 100%;
overflow: hidden;
font-size: 28rpx;
text-align: left;
position: absolute;
white-space: nowrap;
align-items: center;
text-overflow: ellipsis;
&.fistInClass {
top: 0;
}
}
.loopItemBaseShow {
position: absolute;
top: 0;
left: 0;
width: 100%;
// height: 100%;
overflow: hidden;
font-size: 28rpx;
text-align: left;
white-space: nowrap;
align-items: center;
text-overflow: ellipsis;
}
}
}
</style>

View File

@ -0,0 +1,41 @@
<template>
<view class="nothing">
<view class="nothing-box">
<image v-if="imgSrc!=''" class="nothing-img" :src="imgSrc" mode="aspectFill" lazy-load></image>
<i class="iconImg icon"
:class="['icon-nothing-more','icon-nothing-data','icon-nothing-collection'][currentType]"></i>
<view v-if="currentType!=1" class="nothing-con">{{content}}</view>
</view>
</view>
</template>
<script>
export default {
name:"nothing-page",
props:{
imgSrc:{ //
type:String,
default:''
},
content:{ //
type:String,
default:'暂无内容'
},
currentType:{ // icon
type:String,
default: '0'
}
},
data() {
return {};
}
}
</script>
<style scoped>
.nothing{position: fixed;top: 0;bottom: 0;left: 0;right: 0;display: flex;justify-content: center;align-items: center;z-index: -1;}
.nothing-box{display: flex;justify-content: center;flex-direction: column;align-items: center;}
.nothing-box .nothing-img{width: 470rpx;height: 270rpx;}
.iconImg {font-size: 280rpx;color: #999999;}
.nothing-con{font-size: 24rpx;font-family: PingFang SC;font-weight: 500;color: #999999;}
</style>

View File

@ -0,0 +1,54 @@
<template>
<view :style="{
color: textColor,
fontSize: textFontSize,
fontWeight: `${ ifBold ? 'bold' : 0 }`,
textAlign: `${ ifCenter ? 'center' : 'left' }`,
padding: paddingStr
}">{{textStr}}</view>
</template>
<script>
export default {
name:"pitera",
props:{
//
textStr: {
type:String,
default:'-- NO MORE --'
},
//
textColor: {
type:String,
default:'#999999'
},
//
textFontSize: {
type: String,
default: '24rpx'
},
//
ifBold: {
type:Boolean,
default:false
},
//
ifCenter: {
type:Boolean,
default: true
},
//
paddingStr: {
type:String,
default:'20rpx'
}
},
data() {
return {};
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,100 @@
<template>
<view>
<view @tap="lianK"
:style="{
background: backgroundColor,
right:nright+'rpx',
bottom:nbottom+'rpx',
boxShadow: `0rpx 0rpx 30rpx rgba(0,0,0,${shadowNum})`,
borderRadius: radiusNum,
width: widthHeight,
height: widthHeight}"
class="customer-box">
<i class="icon" :style="{color:iconColor}" :class="['icon-customer','icon-customer-black'][iconNum]" style="font-size: 70rpx;"></i>
<!-- <image class="posia" src="/static/public/btnKF.png" style="width: 50rpx;height: 50rpx;top: 20rpx;" mode=""></image> -->
<view v-if="showText" class="fon20" style="margin-top: -20rpx;">线</view>
<button class="fon24 posia-op" open-type="contact"></button>
</view>
</view>
</template>
<script>
export default {
name:"public-customer",
props:{
//
widthHeight:{
type:String,
default:'110rpx'
},
//
backgroundColor:{
type:String,
default:'#000000'
},
// 0~1
shadowNum:{
type:Number,
default:0.55
},
//
radiusNum:{
type:String,
default: '26rpx'
},
//
nright:{
type:Number,
default:20
},
nbottom:{//
type:Number,
default:260
},
// 线
showText:{
type:Boolean,
default:true
},
//
iconNum:{
type:Number,
default:0
},
//
iconColor:{
type:String,
default:'#FFFFFF'
},
nid:{//id
type:String,
default:'0'
}
},
data() {
return {
publicColor:uni.getStorageSync('publicColor'),
};
},
methods:{
lianK(){
this.$requst.post('user/rand-bind-service').then(res=>{})
this.$requst.post('user/record',{type:'other',action:'ask',id:this.nid}).then(res=>{},error=>{})
let maiOjb = {
e:5,//
t:new Date().getTime()//
}
this.$toolAll.tools.maiDian(maiOjb)
}
}
}
</script>
<style scoped>
.customer-box {
position: fixed;z-index: 2;
display: flex;justify-content: center;align-items: center;flex-wrap: wrap;
box-sizing: border-box;
color: #FFFFFF;
}
</style>

143
components/rate.vue Normal file
View File

@ -0,0 +1,143 @@
<template>
<view class="htz-rate-main">
<template v-for="(item,index) in count">
<image @tap="checkItem((index+1))" class="htz-rate-image" :key="index"
:style="{'width':size+'rpx','height':size+'rpx','padding-right':gutter+'rpx'}"
:src="checkedVal<(index+1)?defImgSrc:selImgSrc"></image>
</template>
</view>
</template>
<script>
export default {
name: 'htz-rate',
props: {
curentClick:{//
type:Number,
default:0
},
value: { //
type: Number,
default: 0,
},
count: { //
type: Number,
default: 5,
},
size: { //
type: Number,
default: 42,
},
gutter: { //
type: Number,
default: 15,
},
type: { //
type: Number,
default: 0,
},
disHref: { //
type: String,
default: '',
},
checkedHref: { //
type: String,
default: '',
},
readonly: { //
type: Boolean,
default: false,
},
},
data() {
return {
ImgData: ['/static/rate/rate1_0.png', '/static/rate/rate1_1.png'],
defImgSrc: '',
selImgSrc: '',
checkedVal: 0,
}
},
mounted: function() {
this.$nextTick(function() {
this.checkedVal = this.value;
if (this.disHref != '') {
this.defImgSrc = this.disHref;
this.selImgSrc = this.checkedHref;
} else {
//if (this.type != undefined) {
this.defImgSrc = this.ImgData[this.type];
this.selImgSrc = this.ImgData[this.type].replace('_0', '_1');
//}
}
});
},
watch: {
value(val, oldVal) {
this.checkedVal = this.value;
},
},
methods: {
checkItem(index) {
if (!this.readonly) {
this.checkedVal = index;
this.$emit('input', [index,this.curentClick]);
this.$emit('change', [index,this.curentClick]);
}
},
}
}
</script>
<style>
.htz-rate-main {
display: inline-flex;
}
.htz-rate-image {
vertical-align: middle;
}
.htz-image-upload-list {
display: flex;
flex-wrap: wrap;
}
.htz-image-upload-Item {
width: 160rpx;
height: 160rpx;
margin: 13rpx;
border-radius: 10rpx;
position: relative;
}
.htz-image-upload-Item image {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.htz-image-upload-Item-add {
font-size: 105rpx;
/* line-height: 160rpx; */
text-align: center;
border: 1px dashed #d9d9d9;
color: #d9d9d9;
}
.htz-image-upload-Item-del {
background-color: #f5222d;
font-size: 24rpx;
position: absolute;
width: 35rpx;
height: 35rpx;
line-height: 35rpx;
text-align: center;
top: 0;
right: 0;
z-index: 100;
color: #fff;
}
</style>

42
components/shareAll.vue Normal file
View File

@ -0,0 +1,42 @@
<template>
<view>
<view v-if="showShare" @tap="closeShare" style="position: fixed;top: 0;right: 0;left: 0;bottom: 0;background-color: rgba(0,0,0,.5);z-index: 10;">
</view>
<view v-if="showShare" style="display: flex;flex-direction: column;justify-content: space-around;
position: fixed;bottom: 0;left: 0;right: 0;z-index: 100; background-color: #FFFFFF;padding: 40rpx;">
<view class="posir" v-for="(item,index) in cateArr" :key="index" style="display: flex;justify-content: center;align-items: center;flex-direction: column;width: 25%;">
<image style="width: 100rpx;height: 100rpx;margin-bottom: 10rpx;" :src="item.src" mode=""></image>
<view class="fon28 color33">{{item.title}}</view>
<button data-name="shareBtn" open-type="share" plain="true" class="posia" style="top: 0;left: 0;right: 0;bottom: 0;opacity: 0;">分享</button>
</view>
</view>
</view>
</template>
<script>
export default {
name:'shareAll',
props:{
showShare:{
type:Boolean,
default:false
}
},
data() {
return {
cateArr:[
{src:'/static/img/share/weix.png',title:'微信好友'},
]
};
},
methods:{
closeShare(){
this.$emit('closeShare')
}
}
}
</script>
<style>
</style>

200
components/status-nav.vue Normal file
View File

@ -0,0 +1,200 @@
<template>
<view :style="{height: statusBarHeight+navBarHeight+'px'}">
<view class="status-box statusHNH" >
<!-- 网络电量栏 start -->
<view :style="{height: statusBarHeight+'px',background: backgroudColor}"></view>
<!-- 网络电量栏 end -->
<!-- 头部状态栏 start -->
<view class="status-nav"
:style="{background: backgroudColor,height: navBarHeight+'px'}">
<!-- 返回键 -->
<view class="return-box" @tap="backEv" v-if="ifReturn"
:style="{height: navBarHeight+'px'}">
<slot name="leftContent">
<i class="icon icon-return" style="font-size: 32rpx;"
:style="{color: returnColor}"></i>
</slot>
</view>
<!-- 标题 -->
<view class="tab-title" v-if="ifTitle && ifNet"
:style="{
fontWeight:fontWeight,
color: titleColor,
justifyContent: ifCenter ? 'center' : '',
padding: ifCenter ? '0px' : `${ifReturn ? '0 38' : '0 15'}px`}">
<view class="title-box" :class="['','clips1','clips2'][clipNumber]" :style="{maxWidth: ifCenter ? '360rpx' : '70%'}">{{navBarTitle}}</view>
</view>
<view class="tab-title" v-if="!ifNet"
:style="{
color: titleColor,
justifyContent: ifCenter ? 'center' : '',
padding: ifCenter ? '0px' : `${ifReturn ? '0 38' : '0 15'}px`}">
<view class="title-box" :class="['','clips1','clips2'][clipNumber]" :style="{maxWidth: ifCenter ? '360rpx' : '70%'}">{{netText}}<text @tap="refreshEv" style="color: #3875F6;margin-left: 20rpx;">刷新</text></view>
</view>
</view>
<!-- 头部状态栏 end -->
</view>
</view>
</template>
<script>
export default {
name:'status-nav',
props:{
//
backgroudColor:{
type:String,
default:'#FFFFFF'
},
//
navBarHeight: {
type:Number,
default:40
},
//
ifReturn:{
type:Boolean,
default:true
},
//
returnColor: {
type:String,
default:'#000'
},
//
ifTitle:{
type:Boolean,
default:true
},
//
navBarTitle: {
type:String,
default:''
},
//
clipNumber: {
type:Number,
default:1
},
//
titleColor:{
type:String,
default:'#333333'
},
//
fontWeight:{
type:String,
default:'300'
},
//
ifCenter: {
type:Boolean,
default: true
},
//
fromWhere: {
type:Number,
default:0
}
},
data(){
return {
statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
ifNet:true ,//
netText:'当前无网络',
netTimer:null
}
},
mounted() {
//
this.$toolAll.tools.networkStatus();
// +
// const query = wx.createSelectorQuery().in(this)
// query.select('.statusHNH').boundingClientRect((rect) => {
// uni.setStorageSync('statusHNH',rect.height)
// }).exec();
//
this.$toolAll.tools.obtainUrl();
this.$toolAll.tools.obtainUrlParam();
setTimeout(()=>{
this.ifNet = uni.getStorageSync('isNet');
},500)
},
methods:{
//
refreshEv(){
this.netText = '正在刷新...';
let outTime = 0;//
this.netTimer = setInterval(()=>{
outTime++;
this.$toolAll.tools.networkStatus();
if(uni.getStorageSync('isNet')) {
clearInterval(this.netTimer);
this.ifNet = true;
}
if(outTime==10) {
clearInterval(this.netTimer);
this.netText = '刷新失败';
outTime = 0;
}
},1000)
},
//
backEv(){
if(uni.getStorageSync('outside')*1==2){
this.fromWhere = uni.getStorageSync('outside')*1;
}
switch (this.fromWhere){
case 1:
case 2:
uni.navigateTo({
url:'/pages/tabbar/pagehome/pagehome'
})
uni.setStorageSync('outside',0)
break;
case 0:
uni.navigateBack({
delta:1
})
break;
default:
break;
}
}
}
}
</script>
<style scoped>
.clips1{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 1;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips2{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.status-box{
position: fixed;top: 0;left: 0;right: 0;z-index: 10;
}
.status-nav{
width: 100%;
position: relative;
display: flex;
align-items: center;
}
.return-box {
display: flex;justify-content: center;align-items: center;flex-shrink: 0;
position: absolute;
padding: 0rpx 10rpx;
}
.return-box i {font-size: 56rpx;}
.tab-title{
width: 100%;
font-size: 32rpx;
display: flex;
font-weight: bold;
}
.tab-title .title-box{margin-top: -4rpx;}
</style>

View File

@ -0,0 +1,191 @@
<template>
<view class="status-box statusHNH">
<!-- 网络电量栏 start -->
<view :style="{height: statusBarHeight+'px',background: backgroudColor}"></view>
<!-- 网络电量栏 end -->
<!-- 头部状态栏 start -->
<view class="status-nav"
:style="{background: backgroudColor,height: navBarHeight+'px'}">
<!-- 返回键 -->
<slot name="leftContent">
<view class="return-box" @tap="backEv" v-if="ifReturn"
:style="{height: navBarHeight+'px'}">
</view>
</slot>
<!-- 标题 -->
<view class="tab-title" v-if="ifTitle && ifNet"
:style="{
color: titleColor,
justifyContent: ifCenter ? 'center' : '',
padding: ifCenter ? '0px' : `${ifReturn ? '0 38' : '0 15'}px`}">
<view class="title-box" :class="['','clips1','clips2'][clipNumber]" :style="{maxWidth: ifCenter ? '360rpx' : '70%'}">
<slot name="centerContent">{{navBarTitle}}</slot>
</view>
</view>
<!-- 右边功能 -->
<view class="right-box">
<slot name="rightContent"></slot>
</view>
</view>
<!-- 头部状态栏 end -->
</view>
</template>
<script>
export default {
name:'status-nav',
props:{
//
backgroudColor:{
type:String,
default:'#FFFFFF'
},
//
navBarHeight: {
type:Number,
default:50
},
//
ifReturn:{
type:Boolean,
default:true
},
//
returnColor: {
type:String,
default:'#000'
},
//
ifTitle:{
type:Boolean,
default:true
},
//
navBarTitle: {
type:String,
default:''
},
//
clipNumber: {
type:Number,
default:1
},
//
titleColor:{
type:String,
default:'#333333'
},
//
ifCenter: {
type:Boolean,
default: true
},
//
fromWhere: {
type:Number,
default:0
}
},
data(){
return {
statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
ifNet:true ,//
netText:'当前无网络',
netTimer:null
}
},
mounted() {
//
this.$toolAll.tools.networkStatus();
// +
// const query = wx.createSelectorQuery().in(this)
// query.select('.statusHNH').boundingClientRect((rect) => {
// uni.setStorageSync('statusHNH',rect.height)
// }).exec();
//
this.$toolAll.tools.obtainUrl();
this.$toolAll.tools.obtainUrlParam();
setTimeout(()=>{
this.ifNet = uni.getStorageSync('isNet');
},500)
},
methods:{
//
refreshEv(){
this.netText = '正在刷新...';
let outTime = 0;//
this.netTimer = setInterval(()=>{
outTime++;
this.$toolAll.tools.networkStatus();
if(uni.getStorageSync('isNet')) {
clearInterval(this.netTimer);
this.ifNet = true;
}
if(outTime==10) {
clearInterval(this.netTimer);
this.netText = '刷新失败';
outTime = 0;
}
},1000)
},
//
backEv(){
if(uni.getStorageSync('outside')*1==2){
this.fromWhere = uni.getStorageSync('outside')*1;
}
switch (this.fromWhere){
case 1:
case 2:
uni.navigateTo({
url:'/pages/tabbar/pagehome/pagehome'
})
uni.setStorageSync('outside',0)
break;
case 0:
uni.navigateBack({
delta:1
})
break;
default:
break;
}
}
}
}
</script>
<style scoped>
.clips1{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 1;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.clips2{display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;overflow: hidden;text-overflow: ellipsis;word-wrap: break-word;word-break:break-all;}
.status-box{
position: fixed;top: 0;left: 0;right: 0;z-index: 10;
}
.status-nav{
width: 100%;
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
height: 50px;
line-height: 50px;
padding: 0 30rpx;
box-sizing: border-box;
}
.return-box {
display: flex;justify-content: center;align-items: center;flex-shrink: 0;
position: absolute;
padding: 0rpx 10rpx;
}
.return-box i {font-size: 56rpx;}
.tab-title{
width: 100%;
font-size: 38rpx;
display: flex;
}
.tab-title .title-box{margin-top: -4rpx;}
.right-box {flex-shrink: 0;font-size: 30rpx;}
</style>

View File

@ -0,0 +1,172 @@
<template>
<view class="tabBlock" v-if="list.length > 0">
<scroll-view scroll-x="true" scroll-with-animation :scroll-left="tabsScrollLeft" @scroll="scroll">
<view class="tab" id="tab_list">
<!-- 循环体 -->
<view v-for="(item, index) in list" :key="index"
:class="['tab__item', {'tab__item--active': currentIndex === index}]"
:style="{color: (currentIndex === index ? `${itemColor}`: '')}" id="tab_item"
@click="select(item, index)">
<!-- 标题 -->
<!-- <view><slot name="title" :title="item.title"></slot></view> -->
<!-- 标题 -->
<view v-if="!showTitleSlot">{{item.title}}</view>
</view>
</view>
<!-- 下划线 -->
<view class="tab__line"
:style="{background: lineColor, width: lineStyle.width, transform: lineStyle.transform,transitionDuration: lineStyle.transitionDuration}">
</view>
</scroll-view>
</view>
</template>
<script>
export default {
props: {
value: [Number, String],
list: { //
type: Array,
default: () => {
return [
{title:'标题一'},
{title:'标题二'},
{title:'标题三'},
{title:'标题四'},
{title:'标题五'},
{title:'标题六'},
{title:'标题七'},
{title:'标题八'},
{title:'标题九'},
]
}
},
itemColor: String, // tab
lineColor: String, // 线
lineAnimated: { // 线
type: Boolean,
default: true
}
},
data() {
return {
currentIndex: 0,
lineStyle: {},
scrollLeft: 0,
tabsScrollLeft: 0,
duration: 0.3
}
},
computed: {
showTitleSlot() {
return this.$scopedSlots.title
}
},
watch: {
list() {
this.setTabList()
},
value() {
this.currentIndex = this.value
this.setTabList()
}
},
mounted() {
this.currentIndex = this.value
this.setTabList()
if (!this.lineAnimated) {
this.duration = 0
}
console.log(this.$scopedSlots)
},
methods: {
select(item, index) {
this.$emit('input', index)
},
setTabList() {
this.$nextTick(() => {
if (this.list.length > 0) {
this.setLine()
this.scrollIntoView()
}
})
},
setLine() {
let lineWidth = 0,
lineLeft = 0
this.getElementData(`#tab_item`, (data) => {
let el = data[this.currentIndex]
this.$emit('tabheight',el.height)
lineWidth = el.width / 2
// lineLeft = el.width * (this.currentIndex + 0.5) // item
lineLeft = el.width / 2 + (-data[0].left) + el.left
this.lineStyle = {
width: `${lineWidth}px`,
transform: `translateX(${lineLeft}px) translateX(-50%)`,
transitionDuration: `${this.duration}s`
};
})
},
scrollIntoView() { // item
let lineLeft = 0;
this.getElementData('#tab_list', (data) => {
let list = data[0]
this.getElementData(`#tab_item`, (data) => {
let el = data[this.currentIndex]
// lineLeft = el.width * (this.currentIndex + 0.5) - list.width / 2 - this.scrollLeft
lineLeft = el.width / 2 + (-list.left) + el.left - list.width / 2 - this.scrollLeft
this.tabsScrollLeft = this.scrollLeft + lineLeft
})
})
},
getElementData(el, callback) {
uni.createSelectorQuery().in(this).selectAll(el).boundingClientRect().exec((data) => {
callback(data[0]);
});
},
scroll(e) {
this.scrollLeft = e.detail.scrollLeft;
}
}
}
</script>
<style lang="scss">
.tabBlock {
position: relative;
background: #fff;
.tab {
position: relative;
display: flex;
font-size: 28rpx;
padding-bottom: 15rpx;
white-space: nowrap;
&__item {
// flex: 1;
width: 20%;
flex-shrink: 0;
text-align: center;
line-height: 90rpx;
color: #868695;
&--active {
color: $uni-color-primary;
font-weight: bold;
}
&-title {
margin: 0 40rpx;
}
}
}
.tab__line {
display: block;
height: 6rpx;
position: absolute;
bottom: 20rpx;
left: 0;
z-index: 1;
border-radius: 6rpx;
position: relative;
background: $uni-color-primary;
}
}
</style>

View File

@ -0,0 +1,132 @@
<template>
<view class="banner-box">
<swiper :current="bcurrent" @change="changeBanner" :style="{height: newHeight+'px'}" :autoplay="isplay" :circular="true" :interval="3000" :duration="500">
<swiper-item v-for="(item,index) in bannerList" :key="index">
<view @tap="chooseImg(index,item.url)" class="img-box">
<image :style="{borderRadius:newRadius+'px',height:newHeight+'px'}" class="img animated fadeIn" :src="item.imgSrc" mode="aspectFill"></image>
<image @tap.stop="playVideo(index)" v-if="item.isVideo && isVedio" class="posia animated bounceIn" style="width: 126rpx;height: 126rpx;z-index: 1;" src="/static/public/video.png" mode=""></image>
</view>
</swiper-item>
</swiper>
<!-- 指示点 -->
<view v-if="isDot" class="dot-box" :style="{bottom:newBottom+'px'}">
<view :class="bcurrent==indexd ? 'dotActive' : 'dotMo'"
v-for="(itemd,indexd) in bannerList.length" :key="indexd"
@tap="chooseDot(indexd)"></view>
</view>
</view>
</template>
<script>
export default {
name:"swiper-pu",
props:{
isplay:{
type:Boolean,
default:false
},
isDot:{//
type:Boolean,
default:true
},
bannerList:{//
type:Array,
default:function(){
return [
{imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',url:'',isVideo:false,poster:''},
{imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',url:'',isVideo:false,poster:''},
{imgSrc:'https://s6.jpg.cm/2022/02/14/L4oDhy.jpg',url:'',isVideo:false,poster:''},
]
}
},
newHeight:{//swiper
type:String,
default:'200'
},
newBottom:{//
type:String,
default:'18'
},
newRadius:{//
type:String,
default:'0'
},
browseP:{
type:Boolean,
default:false
}
},
data() {
return {
bcurrent: 0, //
isShowVideo:false, //
autoplay:false, //
isVedio:uni.getStorageSync('is_vedio') //
};
},
methods:{
//
chooseImg(index,url){
// console.log('banner',index);
this.bcurrent = index
if(this.browseP){
let imgList = []
this.bannerList.forEach(item=>{
let nurl = ''
let obj = {}
if(this.isVedio) {
item.url=='' ? nurl = item.imgSrc : nurl = item.url
obj = {
url:nurl,
type:item.isVideo?'video':'image',
poster:item.poster
}
} else {
nurl = item.imgSrc
obj = {
url:nurl,
type:'image',
poster:item.poster
}
}
imgList.push(obj)
})
//
uni.previewMedia({
current:this.bcurrent,
sources:imgList
})
} else {
//
uni.navigateTo({
url:`/${url}`
})
}
},
//
changeBanner(e){
this.bcurrent = e.detail.current//
// console.log(this.bcurrent);
},
//
chooseDot(index){
this.bcurrent = index;
},
playVideo(index){
// console.log('');
uni.navigateTo({
url:`/pagesB/video/playVideo?src=${this.bannerList[index].url}&posterSrc=${this.bannerList[index].poster}`
})
}
}
}
</script>
<style scoped>
.banner-box{position: relative;}
.img-box{position: relative;display: flex;justify-content: center;align-items: center;}
.img{width:100%;vertical-align: bottom;}
.dot-box{position: absolute;bottom: 36rpx;display: flex;justify-content: center;width: 100%;}
.dotActive{width: 20rpx;height: 20rpx;margin-right: 10rpx;border-radius: 20rpx; background-color: rgba(255, 255, 255, 1);}
.dotMo{width: 20rpx;height: 20rpx;margin-right: 10rpx;border-radius: 100%;background-color: rgba(191, 191, 191, 0.8);}
</style>

201
jsFile/base64-src.js Normal file
View File

@ -0,0 +1,201 @@
function getLocalFilePath(path) {
if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf(
'_downloads') === 0) {
return path
}
if (path.indexOf('file://') === 0) {
return path
}
if (path.indexOf('/storage/emulated/0/') === 0) {
return path
}
if (path.indexOf('/') === 0) {
var localFilePath = plus.io.convertAbsoluteFileSystem(path)
if (localFilePath !== path) {
return localFilePath
} else {
path = path.substr(1)
}
}
return '_www/' + path
}
function dataUrlToBase64(str) {
var array = str.split(',')
return array[array.length - 1]
}
var index = 0
function getNewFileId() {
return Date.now() + String(index++)
}
function biggerThan(v1, v2) {
var v1Array = v1.split('.')
var v2Array = v2.split('.')
var update = false
for (var index = 0; index < v2Array.length; index++) {
var diff = v1Array[index] - v2Array[index]
if (diff !== 0) {
update = diff > 0
break
}
}
return update
}
// 图片路径转base64
export function pathToBase64(path) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
if (typeof FileReader === 'function') {
var xhr = new XMLHttpRequest()
xhr.open('GET', path, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (this.status === 200) {
let fileReader = new FileReader()
fileReader.onload = function(e) {
resolve(e.target.result)
}
fileReader.onerror = reject
fileReader.readAsDataURL(this.response)
}
}
xhr.onerror = reject
xhr.send()
return
}
var canvas = document.createElement('canvas')
var c2x = canvas.getContext('2d')
var img = new Image
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
canvas.height = canvas.width = 0
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
entry.file(function(file) {
var fileReader = new plus.io.FileReader()
fileReader.onload = function(data) {
resolve(data.target.result)
}
fileReader.onerror = function(error) {
reject(error)
}
fileReader.readAsDataURL(file)
}, function(error) {
reject(error)
})
}, function(error) {
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: function(res) {
resolve('data:image/png;base64,' + res.data)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
// base64转图片路径
export function base64ToPath(base64) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
base64 = base64.split(',')
var type = base64[0].match(/:(.*?);/)[1]
var str = atob(base64[1])
var n = str.length
var array = new Uint8Array(n)
while (n--) {
array[n] = str.charCodeAt(n)
}
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], {
type: type
})))
}
var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
if (extName) {
extName = extName[1]
} else {
reject(new Error('base64 error'))
}
var fileName = getNewFileId() + '.' + extName
if (typeof plus === 'object') {
var basePath = '_doc'
var dirPath = 'uniapp_temp'
var filePath = basePath + '/' + dirPath + '/' + fileName
if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime
.innerVersion)) {
plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
entry.getDirectory(dirPath, {
create: true,
exclusive: false,
}, function(entry) {
entry.getFile(fileName, {
create: true,
exclusive: false,
}, function(entry) {
entry.createWriter(function(writer) {
writer.onwrite = function() {
resolve(filePath)
}
writer.onerror = reject
writer.seek(0)
writer.writeAsBinary(dataUrlToBase64(base64))
}, reject)
}, reject)
}, reject)
}, reject)
return
}
var bitmap = new plus.nativeObj.Bitmap(fileName)
bitmap.loadBase64Data(base64, function() {
bitmap.save(filePath, {}, function() {
bitmap.clear()
resolve(filePath)
}, function(error) {
bitmap.clear()
reject(error)
})
}, function(error) {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
var filePath = wx.env.USER_DATA_PATH + '/' + fileName
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: dataUrlToBase64(base64),
encoding: 'base64',
success: function() {
resolve(filePath)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}

4
jsFile/public-api.js Normal file
View File

@ -0,0 +1,4 @@
import request from './requst.js';
export function uploadImg(data) {
return request.upload("/universal/api.upload/upload", data);
}

2606
jsFile/qrcode.js Normal file

File diff suppressed because it is too large Load Diff

166
jsFile/requst.js Normal file
View File

@ -0,0 +1,166 @@
// 判断当前环境
const ENV = process.env.NODE_ENV;
console.log(ENV,'当前环境'); // development开发环境 test测试环境 production生产环境
// 配置全局域名
// #ifdef APP-PLUS
const hostapi = 'https://7and5.cn';
// #endif
// #ifdef MP-WEIXIN
const hostapi = 'https://7and5.cn';
// #endif
// #ifdef H5
// const hostapi = '/web';
const hostapi = 'https://7and5.cn';
// #endif
// 清理所有缓存并前往授权页
const goLogin = () => {
uni.clearStorageSync();
uni.navigateTo({
url: '/pages/login/login'
})
}
// 请求错误处理
const checkError = (e) => {
// console.error("----接口错误----", e)
if (e.data) {
if (e.data.code) {
switch (Number(e.data.code)) {
case 4003:
// 参数错误
console.log('4003参数错误');
break;
case 4004:
// 记录不存在
console.log('4004记录不存在');
break;
case 5001:
// xxx错误
console.log('5001xxx错误');
break;
case 5050:
// 服务器错误,请稍后重试
console.log('5050服务器错误请稍后重试');
break;
case 5051:
// 未知错误
console.log('5051未知错误');
break;
case 6001:
// token验证失败或已失效
console.log('6001token验证失败或已失效');
goLogin();
break;
}
}
}
}
// 封装request的(GET、POST)请求
const request = (method, url, options) => {
let methods = '';
let headers = {};
switch (method) {
case 'get':
methods = 'GET'
headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer '+uni.getStorageSync('token') || '',
'token':uni.getStorageSync('token') || ''
}
break;
case 'post':
methods = 'POST'
headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer '+uni.getStorageSync('token') || '',
'token':uni.getStorageSync('token') || ''
}
break;
case 'postForm':
methods = 'POST'
headers = {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Authorization': 'Bearer '+uni.getStorageSync('token') || '',
'token':uni.getStorageSync('token') || ''
}
break;
}
let params = {};
if(options!=undefined) params = options;
// params.token = uni.getStorageSync('token');
return new Promise((resolve, reject) => {
uni.request({
url: `${hostapi}${url}`,
method: methods,
data: params,
header: headers,
// sslVerify:false,//验证 ssl 证书 仅App安卓端支持
// withCredentials:true,//跨域请求时是否携带凭证cookies仅H5支持
success: res => {
console.log(`${url}返的结果===>`,res);
if (res.statusCode == 200) {
// 接口调用成功
resolve(res.data);
} else {
// 接口返回错误信息
checkError(res);
}
},
fail: e => {
// 接口请求错误
checkError(e, reject);
},
complete: rest => {
// 是否成功,都会执行
console.log(rest,100);
}
})
})
}
// 上传文件 封装请求
const uploadFile = (url, options) => {
let tempData = options || {}
return new Promise((resolve, reject) => {
uni.uploadFile({
url: `${hostapi}${url}`,
filePath: tempData.path,
name: 'file',
fileType:'image',
formData: tempData,
// sslVerify:false,//验证 ssl 证书 仅App安卓端支持
// withCredentials:true,//跨域请求时是否携带凭证cookies仅H5支持
header: {
// 'Content-Type': 'multipart/form-data;charset=UTF-8',
// 'Authorization': 'Bearer '+uni.getStorageSync('token') || '',
token:uni.getStorageSync('token') || ''
},
success: res => {
if (res.statusCode == 200) {
let temp = JSON.parse(res.data)
if (temp.code == 1) {
resolve(temp)
}
}
}
});
})
}
export default {
get: (url, options) => {
return request('get', url, options)
},
// JOSN格式
post: (url, options) => {
return request('post', url, options)
},
// form-data格式
postForm: (url, options) => {
return request('postForm', url, options)
},
// 上传
upload: (url, options) => {
return uploadFile(url, options)
}
}

11
jsFile/share.js Normal file
View File

@ -0,0 +1,11 @@
export default {
onShareAppMessage(res) { //发送给朋友
return {
title: '', // 默认是小程序的名称(可以写slogan等)
path: uni.getStorageSync('url') // 默认是当前页面,必须是以‘/’开头的完整路径
}
},
onShareTimeline(res) {//分享到朋友圈
return {}
},
}

664
jsFile/tools.js Normal file
View File

@ -0,0 +1,664 @@
const app = getApp();
const tools = {
timer:'',
timerNot:'',
// 埋点倒计时
daoTime(){
let daoTime = uni.getStorageSync('daoTime')
if(daoTime==''){//初次判断倒计时是否为空
uni.setStorageSync('daoTime',60)//设置倒计时
daoTime = uni.getStorageSync('daoTime')
this.timer = setInterval(()=>{
uni.setStorageSync('daoTime',daoTime--)//设置倒计时
// console.log('埋点倒计时初次:',daoTime);
// console.log('埋点长度初次:',uni.getStorageSync('maiList').length);
if(uni.getStorageSync('daoTime')<=0 || uni.getStorageSync('maiList').length==5){
uni.removeStorageSync('daoTime')//清空倒计时
clearInterval(this.timer)//关闭倒计时
// console.log('上/报,埋点');
// reportBuriedPoint(uni.getStorageSync('maiList'))//上报事件
uni.removeStorageSync('maiList')//清空上报参数
this.daoTime()//重新倒计时
}
},1000)
} else {//继续当前倒计时倒计
this.timer = setInterval(()=>{
uni.setStorageSync('daoTime',daoTime--)//设置倒计时
// console.log('埋点倒计时:',daoTime);
// console.log('埋点长度:',uni.getStorageSync('maiList').length);
if(uni.getStorageSync('daoTime')<=0 || uni.getStorageSync('maiList').length==5){
uni.removeStorageSync('daoTime')//清空倒计时
clearInterval(this.timer)//关闭倒计时
// console.log('上报,埋点');
// reportBuriedPoint(uni.getStorageSync('maiList'))//上报事件
uni.removeStorageSync('maiList')//清空上报参数
this.daoTime()//重新倒计时
}
},1000)
}
},
closeTimer(){
clearInterval(this.timer)//关闭倒计时
console.log('倒计时清空了');
clearInterval(this.timerNot)//关闭倒计时
},
maiDian(data){//埋点事件
let maiList = uni.getStorageSync('maiList')
// console.log(maiList);
if(maiList==''){
maiList = [data]
} else maiList.push(data)
uni.setStorageSync('maiList',maiList)
},
weekDate(){//获取未来七天星期几,几号
let date = new Date()
let year = date.getFullYear()
let month = date.getMonth()+1
let day = date.getDate()
let nth = date.getDay()//星期几
// console.log(year,month,day);
let xingq = ['周一','周二','周三','周四','周五','周六','周日']
},
// 手机号验证
isPhone:function(phone){
// 手机号正则表达式
let reg_tel = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
// if(!reg_tel.test(phone)){
// return true
// }
// return false
return !reg_tel.test(phone);
},
// 电子邮箱验证
isEmail(email){
let reg_email = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
return !reg_email.test(email);
},
// 身份证验证
isIdentity(identity) {
let reg_identity = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
return !reg_identity.test(identity);
},
// 手机号中间四位用"****"带替
hideMPhone(phone){
return `${phone.substr(0, 3)}****${phone.substr(7)}`
},
// 手机号中间加字符
phoneAddChat(phone,startNum=3,endNum=7,character=' '){
let phoneStr = phone;
phoneStr = phoneStr.replace(/\s*/g, "");
var phoneArr = [];
for(var i = 0; i < phoneStr.length; i++){
if (i==startNum||i==endNum){
phoneArr.push(`${character}` + phoneStr.charAt(i));
} else {
phoneArr.push(phoneStr.charAt(i));
}
}
phone = phoneArr.join("");
return phone;
},
// 昵称从第一个字开始,后面的都用"*"代替
hideName(name,num){
return `${name.substr(0, 1)}****${name.substr(name.length-1)}`
},
// 金额转换各三位数使用英文","隔开
changeNum(num){
if (num) {
// 针对整数部分进行格式化处理,这是此方法的核心,也是稍难理解的一个地方,逆向的来思考或者采用简单的事例来实现就容易多了
/*
也可以这样想象现在有一串数字字符串在你面前如果让你给他家千分位的逗号的话你是怎么来思考和操作的?
字符串长度为0/1/2/3时都不用添加
字符串长度大于3的时候从右往左数有三位字符就加一个逗号然后继续往前数直到不到往前数少于三位字符为止
*/
num = num+''; // 数字转换为字符串,数字是没有.length属性的
for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++) {
num = num.substring(0, num.length - (4 * i + 3)) + ',' + num.substring(num.length - (4 * i + 3))
}
// 将数据(符号、整数部分、小数部分)整体组合返回
return num;
}
},
// 整数添加.00,小数就不添加
addXiaoShu(num){
console.log(num,120);
let str = num.toString();
if(str.length > 9){
str = str*1;
str = str.toFixed(2);
str = str+'';
}
return str.includes('.') ? str : str = num + '.00';
},
// type:+加、-减、*乘、/除
// len:小数后保留几位
operationEv(num1,num2,type,len=0){
// 将数字转化成字符串
num1 = num1.toString();
num2 = num2.toString();
// 获取小数点的位置
var index1 = num1.indexOf(".");
var index2 = num2.indexOf(".");
// 如果小数点存在,那么就再获取各自的小数位数
var ws1 = 0;
var ws2 = 0;
if(index1 != -1){
ws1 = num1.split(".")[1].length;
}
if(index2 != -1){
ws2 = num2.split(".")[1].length;
}
// 看谁的小数位数大,谁的小数位数小
var bigger = (ws1 > ws2) ? ws1 : ws2;
var smaller = (ws1 < ws2) ? ws1 : ws2;
// 计算得到需要补齐的0的个数
var zerosCount = bigger - smaller;
// 好了,现在不管三七二十,全部去除小数点
num1 = num1.replace(".","");
num2 = num2.replace(".","");
// 比较num1和num2谁大比较方法就是看谁是smaller是smaller的一方就补0
if(ws1 == smaller){
for (var i = 0; i < zerosCount; i++) {
num1 += "0";
}
} else {
for (var i = 0; i < zerosCount; i++) {
num2 += "0";
}
}
// 开始计算
var sum = "";
if(type=="+"){
// 加
sum = parseInt(num1) + parseInt(num2);
}
if(type=="-"){
// 减
sum = parseInt(num1) - parseInt(num2);
}
if(type=="*"){
// 乘
sum = parseInt(num1) * parseInt(num2);
}
if(type=="/"){
// 除
sum = parseInt(num1) / parseInt(num2);
}
// 根据较大的小数位数计算倍数
var beishu = 1;
for (var i = 0; i < bigger; i++) {
beishu = beishu*10;
}
sum = sum/beishu;
if(type=="*"){
switch (bigger){
case 1:
sum = sum / 10;
break;
case 2:
sum = sum / 100;
break;
case 3:
sum = sum / 1000;
break;
}
}
if(type=="/"){
switch (bigger){
case 1:
sum = sum * 10;
break;
case 2:
sum = sum * 100;
break;
case 3:
sum = sum * 1000;
break;
}
}
len!=0 ? sum = sum.toFixed(len) : '';
return sum;
},
// 时间戳===>日期
timestampToTime(timestamp) {
var date = timestamp.toString().length==13 ? new Date(timestamp*1) : new Date(timestamp * 1000);//时间戳为10位需*1000时间戳为13位的话不需乘1000
var Y = date.getFullYear();
var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1);
var D = date.getDate() < 10 ? '0'+date.getDate() : date.getDate();
var h = date.getHours() < 10 ? '0'+date.getHours() : date.getHours();
var m = date.getMinutes() < 10 ? '0'+date.getMinutes() : date.getMinutes();
var s = date.getSeconds() < 10 ? '0'+date.getSeconds() : date.getSeconds();
return Y + '-' + M + '-' + D + ' ' + h + ':' + m + ':' +s;
},
// 日期===>时间戳
timeToTimestamp(time){
var date = new Date(time);
var timestamp = date.getTime();//精确到毫秒
return timestamp
// var date = new Date('2014-04-23 18:55:49:123');
// 有三种方式获取
// var time1 = date.getTime();//精确到毫秒
// var time2 = date.valueOf();//精确到毫秒
// var time3 = Date.parse(date);//只能精确到秒毫秒用000替代
// console.log(time1);//1398250549123
// console.log(time2);//1398250549123
// console.log(time3);//1398250549000
},
// 返回当前时间
returnCurrentTime(format,type) {
let date = new Date();
let year = date.getFullYear(); // 年
let month = date.getMonth() + 1; // 月
let day = date.getDate(); // 日
let time = date.getHours(); // 时
let minu = date.getSeconds(); // 分
let second = date.getMinutes(); // 秒
let newTime = '';
switch (type){
case 0:
newTime = `${year}${format}${month < 10? '0' + month : month}${format}${day < 10 ? '0' + day : day} ${time < 10 ? '0' + time : time}:${minu < 10 ? '0' + minu : minu}`; // 2022-03-31 16:05
break;
case 1:
newTime = `${year}${format}${month < 10? '0' + month : month}${format}${day < 10 ? '0' + day : day} ${time < 10 ? '0' + time : time}:${minu < 10 ? '0' + minu : minu}:${second < 10 ? '0' + second : second}`; // 2022-03-31 16:10:07
break;
}
return newTime;
},
// 返回时间xx天xx小时xx分钟
returnTimeFormat(startTime,endTime){
console.log(startTime,endTime);
let newTimeFormat = '';
let currentTimestamp = this.timeToTimestamp(endTime) - this.timeToTimestamp(startTime);
return this.returnTimestampToTime(currentTimestamp);
},
// 返回时间戳转时、分对象
returnTimestampToTime(timestamp){
let timeStr = '';
var day = parseInt((timestamp % (1000 * 60 * 60 * 24 * 12)) / (1000 * 60 * 60 * 24));
var hours = parseInt((timestamp % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var seconds = parseInt((timestamp % (1000 * 60 * 60)) / (1000 * 60));
day = day < 10 ? ('0' + day) : day;
hours = hours < 10 ? ('0' + hours) : hours;
seconds = seconds < 10 ? ('0' + seconds) : seconds;
if(day*1==0) {
if(hours*1==0) {
seconds*1==0 ? timeStr = 0 : timeStr = `${seconds}分钟`;
} else {
timeStr = `${hours}小时${seconds}分钟`;
}
} else {
timeStr = `${day}${hours}小时${seconds}分钟`;
}
return timeStr;
},
// 时间戳转时分秒 00 : 00 : 00
formatDuring: function(mss) {
// let dangTime = Math.round(new Date()/1000)//获取当前时间戳
var hours = parseInt((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var seconds = parseInt((mss % (1000 * 60 * 60)) / (1000 * 60));
var minutes = (mss % (1000 * 60)) / 1000;
hours = hours < 10 ? ('0' + hours) : hours;
seconds = seconds < 10 ? ('0' + seconds) : seconds;
minutes = minutes < 10 ? ('0' + minutes) : minutes;
return hours + ' : ' + seconds + ' : ' + minutes;
},
// 随机数生成
randomStr(){
var strData = "";
//如果觉得12个数太少也可以多放点将i<4修改即可
for(var i=0;i<4;i++){
var num = random(0,9); //数字
var upper = String.fromCharCode(random(65,90)); //大写字母
var lower = String.fromCharCode(random(97,122)); //小写字母
strData = strData+num+upper+lower; //将所有结果放进strData中
}
var str = "";
for (var i = 0; i < 4; i++) {
str += strData[random(0,strData.length-1)]; //在strData里面随机抽取四个数
}
return str;
},
// 金额输入框验证
checkPrice(number,zong){
let reg = /^[0-9]*$/;//数字正则表达式
let newObj = {}
zong = parseInt(zong).toString()//取小数点左边的整数
if(!reg.test(number)){//不是数字时
newObj = {
len:zong.length,//动态设置长度
val:zong//动态设置值正整数的总金额
}
} else {//是数字时
newObj = {
len:zong.length,
val:number//动态设置当前输入的值
}
if(number*1 > zong*1){//输入的金额大于总金额
newObj.val = zong//赋值总金额
}
}
return newObj
},
// 提示方法
showToast: function(msg, icon,time) {
// 弹框图标none默认无图标、loading、success
var newIncon = 'none';
if (icon) {newIncon = icon;}
// 弹框显示时间默认2秒
var newTime = 2000
if (time) {newTime = time;}
return uni.showToast({
title: msg,
icon: newIncon,
duration:newTime
})
},
// 富文本
escape2Html(str) {
var arrEntities = { 'lt': '<', 'gt': '>', 'nbsp': ' ', 'amp': '&', 'quot': '"' };
return str.replace(/&(lt|gt|nbsp|amp|quot|src);/ig, function (all, t) {
return arrEntities[t];
})
.replace('<section', '<div')
.replace(/\<img/g, '<img @tap="pre" style="max-width:100%!important;height:auto" ')
.replace(/src=\"/g,'src="https://oss.hmzfyy.cn');
},
// 检查网络状态
networkStatus(){
uni.getNetworkType({
success: (res)=> {
console.log('当前网络状态:',res.networkType);//none当前无网络连接
if(res.networkType=='none'){
uni.setStorageSync('isNet',false)
} else {
uni.setStorageSync('isNet',true);
// 微信小程序原生API性能优化
// #ifdef MP-WEIXIN
// 连网下,检测小程序是否有更新
this.checkUpdate();
// #endif
}
}
});
},
// app、小程序的检测版本并更新
checkUpdate(){
// 检测app
// #ifdef APP-PLUS
// #endif
//检测小程序
// #ifdef MP-WEIXIN
var self = this;
// 获取小程序更新机制兼容
if (wx.canIUse('getUpdateManager')) {
const updateManager = wx.getUpdateManager();//1. 检查小程序是否有新版本发布
updateManager.onCheckForUpdate(function(res) {// 请求完新版本信息的回调
if (res.hasUpdate) {
//检测到新版本,需要更新,给出提示
wx.showModal({
title: '更新提示',
content: '检测到新版本,是否下载新版本并重启小程序?',
success: function(res) {
if (res.confirm) {
//2. 用户确定下载更新小程序,小程序下载及更新静默进行
self.downLoadAndUpdate(updateManager)
// 清除所有缓存
uni.clearStorage();
uni.clearStorageSync();
} else if (res.cancel) {
//用户点击取消按钮的处理,如果需要强制更新,则给出二次弹窗,如果不需要,则这里的代码都可以删掉了
wx.showModal({
title: '温馨提示~',
content: '本次版本更新涉及到新的功能添加,旧版本无法正常访问的哦~',
showCancel:false,//隐藏取消按钮
confirmText:"确定更新",//只保留确定更新按钮
success: function(res) {
if (res.confirm) {
//下载新版本,并重新应用
self.downLoadAndUpdate(updateManager)
}
}
})
}
}
})
}
})
} else { // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
// #endif
},
/**
* 下载小程序新版本并重启应用
* */
downLoadAndUpdate(updateManager){
var self = this;
wx.showLoading(); //静默下载更新小程序新版本
updateManager.onUpdateReady(function () {
wx.hideLoading(); //新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate();
// 清除缓存
uni.clearStorageSync();
uni.clearStorage();
})
updateManager.onUpdateFailed(function () { // 新的版本下载失败
wx.showModal({
title: '已经有新版本了哟~',
content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~',
})
})
},
// 文本复制
clickCopy(data){
uni.setClipboardData({
data: data,
success: ()=> {
uni.showToast({title: '复制成功',duration: 2000,icon: 'none'});
}
});
},
dayTime(endTime,startTime=''){//开启倒计时
let totalSecond = '';
// 本地倒计时
// if(startTime=='') totalSecond = Math.floor((new Date(endTime).getTime() - new Date().getTime())/1000);
// 解决苹果手机问题
let date = endTime;
date = endTime.replace(/-/g,'/')
// 服务器倒计时
if(startTime!='') totalSecond = Math.floor((new Date(date).getTime() - startTime)/1000);
// 总秒数
let second = totalSecond;
// 天数
let day = Math.floor(second / 3600 / 24);
let dayStr = day.toString();
if(dayStr.length == 1) dayStr = '0' + dayStr;
// 小时
let hr = Math.floor((second - day * 3600 * 24) / 3600);
let hrStr = hr.toString();
if(hrStr.length == 1) hrStr = '0' + hrStr;
// 分钟
let min = Math.floor((second - day * 3600 * 24 - hr * 3600) / 60);
let minStr = min.toString();
if(minStr.length == 1) minStr = '0' + minStr;
// 秒
let sec = second - day * 3600 * 24 - hr * 3600 - min * 60;
let secStr = sec.toString();
if(secStr.length == 1) secStr = '0' + secStr;
let newTime = '';
if(dayStr==0) {
newTime = hrStr +'时'+ minStr +'分'+ secStr +'秒';
} else {
newTime = dayStr +'天'+ hrStr +'时'+ minStr +'分'+ secStr +'秒';
}
return newTime;
},
// 刷新token
refreshToken(){
console.log('进入检测token是否过期');
var date = new Date();
var timestamp = date.getTime();//精确到毫秒
// 如果过期时间 减 10分钟 小于当前时间刷新token
if((uni.getStorageSync('expire')*1000 - 600000) < timestamp) {
uni.login({
provider: 'weixin',
success: (res)=> {
if (res.code) {
var params = {code:res.code}
uni.request({
url: `${app.globalData.hostapi}/api/user/login`,
method: 'post',
data: params,
header: {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer '+uni.getStorageSync('token') || ''
},
success: res => {
if(res.data.data.token!=''){
uni.setStorageSync('token',res.data.data.token)//缓存token
uni.setStorageSync('openid',res.data.data.openid)//缓存Openid
uni.setStorageSync('expire',res.data.data.expire)//缓存失效时间(时间戳格式)
uni.setStorageSync('is_active',res.data.data.is_active)//是否第一次授权
uni.setStorageSync('phone_active',res.data.data.phone_active)//是否绑定手机号
uni.setStorageSync('userId',res.data.data.account_id)//用户id
uni.setStorageSync('invite_code',res.data.data.invite_code)//邀请码
}
}
})
}
},
});
}
},
// 判断是否授权,没授权,前往登录页面授权
authTimer:null,
judgeAuth(){
let auth = false;
clearTimeout(this.authTimer);
if(!uni.getStorageSync('token')) {
this.showToast('请登录');
this.authTimer = setTimeout(()=>{
uni.navigateTo({url:'/pages/login/login'});
},2000)
} else {
auth = true;
}
return auth;
},
// 判断当前环境、清空日志、设置全局域名
currentContext(){
// #ifdef APP-PLUS
if(uni.getSystemInfoSync().platform != "devtools"){//devtools开发版 值域为ios、android、mac3.1.10+、windows3.1.10+、linux3.1.10+
// console.log = () =>{}
}
// #endif
// 微信小程序原生API性能优化
// #ifdef MP-WEIXIN
let hInfo = wx.getAccountInfoSync();
// console.log(hInfo.envVersion);//develop:开发版 trial体验版 release正式版
// if(hInfo.miniProgram.envVersion == "develop"){
if(hInfo.miniProgram.envVersion == "develop" || hInfo.miniProgram.envVersion == "trial"){
} else {
// 清除所有输出日志
console.log = () =>{};
// 开启埋点倒计时
this.daoTime();//开启埋点倒计时
}
// #endif
},
// 禁止小程序使用分享
disableShareEv(){
// #ifdef MP-WEIXIN
wx.hideShareMenu({
menus: ['shareAppMessage', 'shareTimeline']
})
// #endif
},
// 获取当前页面url不带参数
obtainUrl(){
let pages = getCurrentPages();
let route = pages[pages.length - 1].route;
uni.setStorageSync('url',`/${route}?invite_code=${uni.getStorageSync('invite_code')}`);
console.log(`${route}`,'tools.js当前页面路径不带参数')
},
// 获取当前页面url带参数
obtainUrlParam(){
let pages = getCurrentPages();
let routeParam = pages[pages.length - 1].$page.fullPath;
uni.setStorageSync('urlParam',`${routeParam}?invite_code=${uni.getStorageSync('invite_code')}`);
console.log(uni.getStorageSync('urlParam'),'tools.js当前页面路径带参数')
},
// 去这里
goFlag:true,
goThere(){
if(this.flag){
this.flag = false;
// #ifdef MP-WEIXIN
wx.getLocation({//获取当前经纬度
type: 'wgs84', //返回可以用于wx.openLocation的经纬度官方提示bug: iOS 6.3.30 type 参数不生效,只会返回 wgs84 类型的坐标信息
success: (res)=> {
wx.openLocation({//​使用微信内置地图查看位置。
latitude: 30.656693,//要去的纬度-地址
longitude: 104.136425,//要去的经度-地址
name: '大向天诚有限责任公司',
address: '四川省成都市成华区双店路B口',
fail:err=>{
this.showToast('地址信息错误');
}
})
}
})
// #endif
setTimeout(()=>{
this.flag = true;
},2000)
} else {
this.showToast('请勿多次点击');
}
},
// 拨打电话
countCustomer(phone){
const res = uni.getSystemInfoSync();
if(res.platform=='ios'){
uni.makePhoneCall({
phoneNumber:phone*1,
success: () => {},
fail: () => {}
})
} else {
uni.showActionSheet({
itemList:[phone,'立即呼叫'],
itemColor:'#3875F6',
success: (res) => {
if(res.tapIndex==1){
uni.makePhoneCall({
phoneNumber:phone
})
}
}
})
}
},
}
export default {
tools
}

26
main.js Normal file
View File

@ -0,0 +1,26 @@
import Vue from 'vue';
import App from './App';
import content from './components/containers/container-subgroup-two.vue';//引入无内容组件
Vue.component('content',content);//全局注册无内容组件
import nothingPage from './components/nothing/nothing-page.vue';//引入无内容组件
Vue.component('nothing-page',nothingPage);//全局注册无内容组件
import share from './jsFile/share.js';// 全局注册分享事件
Vue.mixin(share);
// 常用工具
import tools from '@/jsFile/tools.js';
Vue.prototype.$toolAll = tools;
// 响应数据
import requst from '@/jsFile/requst.js';
Vue.prototype.$requst = requst;
App.mpType = 'app';
const app = new Vue({
...App
})
app.$mount()

127
manifest.json Normal file
View File

@ -0,0 +1,127 @@
{
"name" : "抽奖",
"appid" : "__UNI__492E85A",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
"app-plus" : {
"usingComponents" : true,
"compilerVersion" : 3,
/* 5+App */
"modules" : {
"Payment" : {},
"Share" : {},
"Maps" : {},
"Geolocation" : {}
},
/* */
"distribute" : {
/* */
"android" : {
/* android */
"permissions" : [
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
"ios" : {},
/* ios */
"sdkConfigs" : {
"maps" : {
"amap" : {
"appkey_ios" : "",
"appkey_android" : "57d6437544bb36bd3b5f4efb5b06ddbf"
}
},
"payment" : {
"weixin" : {
"__platform__" : [ "ios", "android" ],
"appid" : "wx2654bc27c419ada6",
"UniversalLinks" : ""
}
},
"push" : {},
"geolocation" : {
"baidu" : {
"__platform__" : [ "ios", "android" ],
"appkey_ios" : "",
"appkey_android" : "mDcZsWM7gGKb7MC1bC8Mo33FScjYEr0I"
},
"amap" : {
"__platform__" : [ "ios", "android" ],
"appkey_ios" : "",
"appkey_android" : "57d6437544bb36bd3b5f4efb5b06ddbf"
}
},
"share" : {
"weixin" : {
"appid" : "wx2654bc27c419ada6",
"UniversalLinks" : ""
}
},
"ad" : {}
}
},
"splashscreen" : {
"alwaysShowBeforeRender" : false,
"waiting" : false
}
},
/* SDK */
"quickapp" : {},
/* */
"mp-weixin" : {
/* */
"appid" : "wx372ffc194d87c693",
"setting" : {
"urlCheck" : true,
"es6" : true
},
"usingComponents" : true,
"permission" : {
"scope.userLocation" : {
"desc" : "您的位置信息将用于小程序位置接口的效果展示"
}
}
},
"h5" : {
"sdkConfigs" : {
"maps" : {
"qqmap" : {
"key" : "TMWBZ-XA3CD-HA74Y-PNUS4-SAV6Q-X7FXH"
}
}
},
"devServer" : {
"https" : false,
"proxy" : {
"/web" : {
"target" : "https://7and5.cn",
"changeOrigin" : true,
"secure" : false,
"pathRewrite" : {
"^/web" : ""
}
}
}
}
},
"mp-baidu" : {
"appid" : "24346353"
}
}

11
package.json Normal file
View File

@ -0,0 +1,11 @@
{
"id": "zhuge-swiper",
"name": "轮播视频和图片",
"version": "1.0.1",
"description": "自动轮播视频和图片组件。播放视频时停止轮播手动滑动swiper时视频停止播放",
"keywords": [
"vue",
"swiper",
"zhuge"
]
}

71
pages.json Normal file
View File

@ -0,0 +1,71 @@
{
"pages": [ {
"path" : "pages/index/index",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
],
"subPackages": [{ //A
"root": "pagesA",
"pages": [{
"path": "test/test",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}]
},
{ //B
"root": "pagesB",
"pages": [{
"path" : "signin/signin",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
,{
"path" : "integralMall/integralMall",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
]
}
],
"preloadRule": {
"pages/index/index": {
"network": "all",
"packages": ["pagesA"]
}
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#FFFFFF", //
"backgroundColor": "#FFFFFF", //
"navigationStyle": "custom", //
"app-plus": {
"titleNView": false, //APPH5
"bounce": "none",
"scrollIndicator": "none"
}
},
"condition": { //
"current": 0, //(list )
"list": [{
"name": "", //
"path": "", //
"query": "" //onLoad
}]
}
}

547
pages/index/index.vue Normal file
View File

@ -0,0 +1,547 @@
<template>
<view class="app-content">
<statusNav fontWeight="800" titleColor="rgba(255, 255, 255, 100)" backgroudColor="#F37A61" navBarTitle="抽奖"
:ifReturn="ifReturn"></statusNav>
<view class="head">
<view class="li">
<view class="text">
<text class="num">0</text> 积分
</view>
<view class="button">
去兑换>
</view>
</view>
<view class="li">
<view class="text">
<text class="num">0.00</text>
</view>
<view class="button">
去提现>
</view>
</view>
</view>
<view class="function-list">
<view class="li" v-for="(item,index) in dataFunction">
<image src="" class="icon" mode=""></image>
<view class="text">
{{item.title}}
</view>
</view>
</view>
<view class="main">
<view class="title-content">
<view class="title">
每日福利
</view>
<view class="text">
<text>我要上首页</text>
<view class="bor">
</view>
<text>分享</text>
</view>
</view>
<view class="welfare-content">
<view class="img-content">
<image src="" class="img" mode="aspectFill"></image>
<view class="icon">
</view>
</view>
<view class="text-content">
<view class="name">
奖品现金红包666元独宠一人 x1份
</view>
<view class="date">
开奖时间2021年10月27日<text class="fs16 bold cF37A61">22</text><text
class="fs16 bold cF37A61">30</text>
</view>
<view class="text">
抽奖商城 <text class="bold">赞助</text>
</view>
<view class="button">
免费参与
</view>
</view>
</view>
<view class="title-content">
<view class="title">
精选福利
</view>
</view>
<view class="choiceness-content">
<view class="li" v-for="(item,index) in dataChoiceness">
<view class="img-content">
<image src="" class="img" mode="aspectFill"></image>
<view class="text">
抽奖商城<text class="bold">赞助</text>
</view>
<view class="icon">
</view>
</view>
<view class="text-content">
<view class="clips2 name">
{{item.title}}<text class="on">x1份</text>
</view>
<view class="date">
开奖时间10/27 <text class="cF37A61 bold"> 22:30</text>
</view>
<view class="button" :class="item.state==0?'btn':''">
<text v-if="item.state==0"></text>
<text v-else> </text>
</view>
</view>
</view>
</view>
<view class="title-content">
<view class="title">
自助福利
</view>
</view>
<view class="self-help">
<view class="li">
<image src="" class="img" mode=""></image>
<view class="text-content">
<view class="name">
奖品兰蔻口红196<text class="on">x1份</text>
</view>
<view class="date">
开奖时间2021年10月27日<text class="ml fs16 bold cF37A61">22</text><text
class="fs16 bold cF37A61">30</text>
</view>
<view class="button">
免费参与
</view>
</view>
</view>
<view class="li">
<image src="" class="img" mode=""></image>
<view class="text-content">
<view class="name">
奖品兰蔻口红196<text class="on">x1份</text>
</view>
<view class="date">
开奖时间2021年10月27日<text class="ml fs16 bold cF37A61">22</text><text
class="fs16 bold cF37A61">30</text>
</view>
<view class="button">
免费参与
</view>
</view>
</view>
</view>
</view>
<footTabOne></footTabOne>
</view>
</template>
<script>
import footTabOne from "../../components/foot-tabs/foot-tab-one.vue"
import statusNav from '../../components/status-nav.vue';
export default {
components: {
footTabOne,
statusNav
},
data() {
return {
ifReturn: false,
dataFunction: [{
src: "",
title: "天天签到"
},
{
src: "",
title: "积分商城"
},
{
src: "",
title: "惊喜盲盒"
},
],
dataChoiceness: [{
title: "奖品现金红包666元独宠一人",
state: 1,
},
{
title: "奖品现金红包666元独宠一人",
state: 1,
},
{
title: "奖品现金红包666元独宠一人",
state: 1,
},
{
title: "奖品现金红包666元独宠一人",
state: 0,
},
]
}
},
onLoad() {
uni.navigateTo({
url:"/pagesB/integralMall/integralMall"
})
},
methods: {
}
}
</script>
<style>
.head {
width: 100%;
height: 382rpx;
background-color: #F37A61;
padding: 0 44rpx;
display: flex;
position: relative;
box-sizing: border-box;
padding-top: 38rpx;
justify-content: space-between;
}
.head .li .text {
color: rgba(255, 255, 255, 100);
font-size: 28rpx;
font-family: PingFangSC-regular;
}
.head .li .text .num {
color: rgba(255, 255, 255, 100);
font-size: 48rpx;
font-family: PingFangSC-regular;
}
.head .li {
text-align: center;
display: inline-block;
}
.head .li .button {
margin-top: 42rpx;
width: 214rpx;
background-color: #FFFFFF;
height: 66rpx;
color: rgba(243, 122, 97, 100);
line-height: 66rpx;
border-radius: 60rpx;
text-align: center;
}
.function-list {
width: 702rpx;
margin: auto;
margin-top: -142rpx;
position: relative;
background-color: #FFFFFF;
z-index: 2;
height: 182rpx;
border-radius: 20rpx;
text-align: center;
box-shadow: 0px 6rpx 18rpx 0px rgba(0, 0, 0, 0.09);
padding: 0 60rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
color: rgba(16, 16, 16, 100);
font-size: 28rpx;
font-family: PingFangSC-regular;
}
.function-list .li .icon {
width: 72rpx;
height: 72rpx;
background-color: rgba(227, 227, 227, 100);
text-align: center;
margin-bottom: 30rpx;
}
.main {
padding: 0 25rpx;
}
.main .title-content {
display: flex;
margin-top: 40rpx;
align-items: flex-end;
justify-content: space-between;
}
.main .title-content .title {
color: rgba(16, 16, 16, 100);
font-size: 36rpx;
font-family: PingFangSC-regular;
}
.main .title-content .text {
color: rgba(176, 176, 176, 100);
font-size: 24rpx;
display: flex;
align-items: center;
font-family: PingFangSC-regular;
}
.main .title-content .text .bor {
border-left: 4rpx solid rgba(176, 176, 176, 100);
width: 2rpx;
height: 25rpx;
margin: 0 23rpx;
}
.welfare-content {
box-shadow: 0px 0px 6rpx 0px rgba(0, 0, 0, 0.1);
margin-top: 26rpx;
border-radius: 20rpx 20rpx 20rpx 20rpx;
overflow: hidden;
position: relative;
}
.welfare-content .img-content {
width: 100%;
position: relative;
height: 350rpx;
border-radius: 20rpx 20rpx 0rpx 0px;
}
.welfare-content .img-content .img {
width: 100%;
height: 100%;
border-radius: 20rpx 20rpx 0rpx 0px;
background-color: rgba(227, 227, 227, 100);
}
.welfare-content .img-content .icon {
position: absolute;
right: 30rpx;
top: 30rpx;
width: 58rpx;
height: 58rpx;
line-height: 58rpx;
color: #FFFFFF;
font-size: 28rpx;
border-radius: 50%;
background-color: rgba(243, 122, 97, 100);
text-align: center;
}
.welfare-content .text-content {
padding: 20rpx;
position: relative;
}
.welfare-content .text-content .name {
color: rgba(16, 16, 16, 100);
font-size: 28rpx;
font-family: PingFangSC-regular;
}
.welfare-content .text-content .date {
color: rgba(16, 16, 16, 100);
font-size: 24rpx;
font-family: PingFangSC-regular;
margin: 20rpx 0rpx;
}
.welfare-content .text-content .text {
color: rgba(243, 122, 97, 100);
font-size: 28rpx;
font-family: PingFangSC-regular;
}
.welfare-content .text-content .button {
width: 160rpx;
height: 58rpx;
position: absolute;
right: 20rpx;
top: 70rpx;
border-radius: 8rpx;
background-color: rgba(243, 122, 97, 100);
text-align: center;
color: #FFFFFF;
line-height: 58rpx;
font-size: 28rpx;
}
.choiceness-content {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.choiceness-content .li {
width: 340rpx;
height: 560rpx;
background-color: #FFFFFF;
border-radius: 20rpx;
margin-top: 22rpx;
box-shadow: 0px 0px 12rpx 0px rgba(0, 0, 0, 0.1);
}
.choiceness-content .li .img-content {
position: relative;
width: 100%;
background-color: rgba(227, 227, 227, 100);
height: 310rpx;
overflow: hidden;
border-radius: 20rpx 20rpx 0px 0px;
}
.choiceness-content .li .img-content .text {
width: 166rpx;
height: 44rpx;
background-color: rgba(78, 180, 255, 100);
color: rgba(255, 255, 255, 100);
font-size: 28rpx;
position: absolute;
left: 0rpx;
font-size: 24rpx;
line-height: 44rpx;
top: 0rpx;
text-align: center;
font-family: Arial;
}
.choiceness-content .li .img-content .icon {
position: absolute;
right: 10rpx;
top: 10rpx;
width: 58rpx;
height: 58rpx;
line-height: 58rpx;
color: #FFFFFF;
font-size: 28rpx;
border-radius: 50%;
background-color: rgba(243, 122, 97, 100);
text-align: center;
}
.choiceness-content .li .img-content .img {
width: 100%;
height: 100%;
}
.choiceness-content .text-content {
padding: 14rpx 22rpx 0rpx 14rpx;
}
.choiceness-content .text-content .name {
color: rgba(16, 16, 16, 100);
font-size: 28rpx;
line-height: 46rpx;
text-align: left;
font-family: PingFangSC-regular;
}
.choiceness-content .text-content .name .on {
color: rgba(227, 227, 227, 100);
margin-left: 10rpx;
}
.choiceness-content .text-content .date {
color: rgba(16, 16, 16, 100);
font-size: 24rpx;
line-height: 50rpx;
text-align: left;
font-family: PingFangSC-regular;
}
.choiceness-content .text-content .date .bold {
font-size: 28rpx;
margin-left: 10rpx;
}
.choiceness-content .text-content .button {
width: 100%;
height: 58rpx;
border-radius: 8rpx;
background-color: rgba(243, 122, 97, 100);
text-align: center;
color: #FFFFFF;
line-height: 58rpx;
margin-top: 16rpx;
;
font-size: 28rpx;
}
.choiceness-content .text-content .btn {
background-color: rgba(185, 185, 185, 100);
}
.self-help {
width: 100%;
border-radius: 20rpx;
margin-top: 20rpx;
padding: 20rpx;
padding-right: 36rpx;
box-sizing: border-box;
box-shadow: 0px 0px 12rpx 0px rgba(0, 0, 0, 0.1);
}
.self-help .li {
padding-bottom: 20rpx;
border-bottom: 2rpx solid rgba(187, 187, 187, 100);
display: flex;
margin-bottom: 20rpx;
}
.self-help .li:last-child{
border: none;
padding-bottom: 0rpx;
margin-bottom: 0rpx;
}
.self-help .li .img {
width: 182rpx;
height: 182rpx;
margin-right: 12rpx;
background-color: rgba(227, 227, 227, 100);
border-radius: 8rpx;
}
.self-help .li .name {
color: rgba(16, 16, 16, 100);
font-size: 28rpx;
line-height: 46rpx;
text-align: left;
font-family: PingFangSC-regular;
}
.self-help .li .name .on {
color: rgba(227, 227, 227, 100);
margin-left: 10rpx;
}
.self-help .li .date {
color: rgba(16, 16, 16, 100);
font-size: 24rpx;
line-height: 50rpx;
text-align: left;
font-family: PingFangSC-regular;
}
.self-help .li .date .ml{
margin-left: 10rpx;
}
.self-help .li .button {
width: 438rpx;
height: 58rpx;
border-radius: 8rpx;
background-color: rgba(243, 122, 97, 100);
text-align: center;
color: #FFFFFF;
line-height: 58rpx;
margin-top: 16rpx;
font-size: 28rpx;
}
</style>

22
pagesA/test/test.vue Normal file
View File

@ -0,0 +1,22 @@
<template>
<view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,150 @@
<template>
<view>
<statusNav returnColor="#141414" fontWeight="800" titleColor="#141414" backgroudColor="#fff" navBarTitle="积分商城">
</statusNav>
<view class="head" :style="{top: statusBarHeight+40+'px'}">
<input type="text" class="input" value="" placeholder="搜索" placeholder-class="input-placeholder" />
<view class="nav">
<view class="li" @click="navIndexFun(index)" :class="navIndex==index?'on':''" v-for="(item,index) in navList">
{{item.title}}
</view>
</view>
</view>
<view class="mall">
<view class="li" v-for="(item,index) in 6">
<image src="" class="img" mode=""></image>
<view class="name">
现金红包666元独宠一人
</view>
<view class="num">
30.00+20积分
</view>
</view>
</view>
</view>
</template>
<script>
import footTabOne from "../../components/foot-tabs/foot-tab-one.vue"
import statusNav from '../../components/status-nav.vue';
export default {
components: {
footTabOne,
statusNav
},
data() {
return {
navIndex:0,
statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
navList:[
{
title:"热门推荐",
},
{
title:"生活用品"
},
{
title:"美妆护肤"
},
{
title:"生鲜食品"
},
{
title:"母婴"
},
{
title:"母婴"
},
]
}
},
methods: {
navIndexFun(index){
this.navIndex=index
}
}
}
</script>
<style>
.head {
width: 100%;
height: 208rpx;
padding-top: 36rpx;
background-color: #FFFFFF;
box-sizing: border-box;
position: fixed;
top: 0rpx;
left: 0rpx;
}
.head .input {
width: 692rpx;
margin: auto;
height: 36px;
line-height: 20px;
margin-top: ;
border-radius: 5px;
background-color: rgba(236, 236, 236, 100);
text-align: center;
}
.input-placeholder {
text-align: center;
color: rgba(185, 185, 185, 100);
font-size: 28rpx;
}
.head .nav{
display: flex;
padding-left: 30rpx;
overflow: auto;
}
.head .nav .li{
padding: 30rpx 0rpx;
margin-right: 54rpx;
color: rgba(113, 113, 113, 100);
border-bottom: 8rpx solid #FFFFFF;
font-size: 28rpx;
position: relative;
white-space: nowrap;
}
.head .nav .on{
color: rgba(243, 122, 97, 100);
border-bottom: 8rpx solid #F37A61;
}
.mall{
padding: 20rpx 25rpx 0rpx;
margin-top: 208rpx;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.mall .li{
width: 340rpx;
height: 440rpx;
border-radius: 20rpx;
margin-bottom: 22rpx;
box-shadow: 0px 0px 12rpx 0px rgba(0, 0, 0, 0.1);
}
.mall .li .img{
background-color: rgba(236, 236, 236, 100);
width: 100%;
height: 310rpx;
border-radius: 20rpx 20rpx 0px 0px;
}
.mall .li .name{
color: rgba(16, 16, 16, 100);
font-size: 28rpx;
padding: 14rpx 14rpx;
font-family: PingFangSC-regular;
}
.mall .li .num{
color: rgba(243, 122, 97, 100);
font-size: 28rpx;
padding: 0 14rpx;
font-weight: normal;
}
</style>

561
pagesB/signin/signin.vue Normal file
View File

@ -0,0 +1,561 @@
<template>
<view>
<statusNav returnColor="#ffffff" fontWeight="800" titleColor="rgba(255, 255, 255, 100)" backgroudColor="#F37A61"
navBarTitle="天天签到">
</statusNav>
<view class="head">
<view class="integral">
当前积分
</view>
<view class="num">
<text class="bold">3000</text>积分
</view>
<view class="text">
每日签到领取积分连续签到领大礼~
</view>
<view class="button">
兑换商城
</view>
</view>
<view class="signin-content">
<view class="text">
已连续签到<text class="cF37A61 bold">3</text>
</view>
<view class="icon-content">
<view class="li" v-for="(item,index) in signinData">
<view class="icon" :class="item.state?'on':''">
<image src="" v-if="item.state" mode=""></image>
</view>
<view class="icon-text">
{{item.title}}
</view>
</view>
</view>
<view class="button" @click="signinFun()">
立即签到
</view>
</view>
<view class="conversion">
<view class="title">
兑换红包
</view>
<view class="conversion-content">
<view class="li" v-for="(item,index) in 4" @click="redPacketFun()">
<image src="" class="img" mode=""></image>
<view class="text">
限量3000个
</view>
</view>
</view>
</view>
<view class="welfare">
<view class="title">
福利任务
</view>
<view class="welfare-content">
<view class="li" v-for="(item,index) in welfareData">
<view class="left">
<view class="text">
{{item.title}} <text class="ml" v-if="item.num>0">{{item.num}}/3</text>
</view>
<view class="num">
<image src="" class="icon" mode=""></image>
<view class="">
积分+40
</view>
</view>
</view>
<view class="button" :class="item.state?'on':''">
<text v-if="item.state"></text>
<text v-else>+40</text>
</view>
</view>
</view>
</view>
<view class="welfare time-limit">
<view class="title">
限时任务
</view>
<view class="welfare-content">
<view class="li" v-for="(item,index) in welfareData">
<view class="left">
<view class="text">
{{item.title}} <text class="ml" v-if="item.num>0">{{item.num}}/3</text>
</view>
<view class="num">
<image src="" class="icon" mode=""></image>
<view class="">
积分+40
</view>
</view>
</view>
<view class="right">
<view class="button" :class="item.state?'on':''">
<text v-if="item.state"></text>
<text v-else>+40</text>
</view>
<view class="date">
剩余时间20小时30分
</view>
</view>
</view>
</view>
</view>
<view class="make" v-if="isSignin">
<view class="make-content">
<view class="title">
恭喜签到成功
</view>
<view class="signin-make">
<view class="text">
+50积分
</view>
<view class="button" @click="signinFun()">
明天提醒我
</view>
</view>
</view>
<view class="make-close" @click="signinFun()">
<!-- <image src="" class="make-close-img" mode=""></image> -->
</view>
</view>
<view class="make" v-if="isRedPacket">
<view class="make-content">
<view class="title">
恭喜签到成功
</view>
<view class="PacketFun-make">
+0.3
</view>
</view>
<view class="make-close" @click="redPacketFun()">
<!-- <image src="" class="make-close-img" mode=""></image> -->
</view>
</view>
</view>
</template>
<script>
import footTabOne from "../../components/foot-tabs/foot-tab-one.vue"
import statusNav from '../../components/status-nav.vue';
export default {
components: {
footTabOne,
statusNav
},
data() {
return {
isRedPacket:false,
isSignin: false,
signinData: [{
title: "第1天",
state: true
},
{
title: "第2天",
state: false
},
{
title: "第3天",
state: false
},
{
title: "第4天",
state: false
},
{
title: "第5天",
state: false
},
{
title: "第6天",
state: false
},
{
title: "第7天",
state: false
},
],
welfareData: [{
title: "邀请好友注册",
state: false,
num: 0,
},
{
title: "参与抽奖",
state: true,
num: 2,
},
]
}
},
methods: {
signinFun() {
this.isSignin=!this.isSignin
},
redPacketFun() {
this.isRedPacket=!this.isRedPacket
},
}
}
</script>
<style>
.head {
width: 100%;
height: 360rpx;
line-height: 40rpx;
padding: 0 22rpx 0 26rpx;
background-color: rgba(243, 122, 97, 100);
}
.head .integral {
color: rgba(227, 227, 227, 100);
font-size: 28rpx;
position: relative;
font-family: PingFangSC-regular;
}
.head .num {
color: rgba(255, 255, 255, 100);
font-size: 28rpx;
margin-top: 16rpx;
font-family: PingFangSC-regular;
}
.head .num .bold {
font-size: 44rpx;
line-height: 60rpx;
}
.head .text {
font-size: 28rpx;
margin-top: 12rpx;
color: #E3E3E3;
}
.head .button {
width: 184rpx;
height: 72rpx;
position: absolute;
right: 22rpx;
top: 245rpx;
border-radius: 60rpx;
background-color: rgba(255, 221, 221, 100);
text-align: center;
line-height: 72rpx;
color: rgba(243, 122, 97, 100);
font-size: 28rpx;
}
.signin-content {
width: 702rpx;
height: 368rpx;
border-radius: 20rpx;
background-color: #FFFFFF;
margin: auto;
padding: 20rpx;
box-sizing: border-box;
box-sizing: border-box;
margin-top: -138rpx;
box-shadow: 0rpx 4rpx 12rpx 0rpx rgba(0, 0, 0, 0.08);
}
.signin-content .text {
font-size: 28rpx;
}
.signin-content .text .bold {
font-size: 32rpx;
}
.icon-content {
display: flex;
margin-top: 36rpx;
justify-content: space-between;
color: rgba(208, 208, 208, 100);
font-size: 24rpx;
text-align: center;
}
.icon-content .li .icon {
width: 60rpx;
border-radius: 50%;
margin-bottom: 16rpx;
height: 60rpx;
background-color: rgba(227, 227, 227, 100);
}
.icon-content .li .on {
background-color: rgba(249, 197, 29, 100);
}
.signin-content .button {
width: 602rpx;
height: 84rpx;
line-height: 84rpx;
border-radius: 60rpx;
color: rgba(255, 255, 255, 100);
font-size: 32rpx;
margin: auto;
margin-top: 54rpx;
background-color: rgba(249, 197, 29, 100);
text-align: center;
}
.conversion {
padding: 20rpx 26rpx;
width: 702rpx;
box-sizing: border-box;
background-color: #FFFFFF;
height: 378rpx;
margin: auto;
margin-top: 20rpx;
border-radius: 20rpx;
box-shadow: 0rpx 4rpx 12rpx 0rpx rgba(0, 0, 0, 0.08);
}
.conversion .title {
color: rgba(16, 16, 16, 100);
font-size: 32rpx;
font-family: PingFangSC-regular;
padding-bottom: 16rpx;
border-bottom: 2rpx solid rgba(227, 227, 227, 100);
}
.conversion-content {
display: flex;
margin-top: 30rpx;
justify-content: space-between;
}
.conversion-content .li .img {
width: 122rpx;
height: 196rpx;
border-radius: 20rpx;
background-color: rgba(227, 227, 227, 100);
}
.conversion-content .li .text {
color: rgba(16, 16, 16, 100);
font-size: 24rpx;
text-align: center;
margin-top: 16rpx;
font-family: PingFangSC-regular;
}
.welfare {
padding: 20rpx 26rpx 28rpx;
width: 702rpx;
box-sizing: border-box;
background-color: #FFFFFF;
margin: auto;
margin-top: 20rpx;
border-radius: 20rpx;
box-shadow: 0rpx 4rpx 12rpx 0rpx rgba(0, 0, 0, 0.08);
}
.welfare .title {
color: rgba(16, 16, 16, 100);
font-size: 32rpx;
font-family: PingFangSC-regular;
padding-bottom: 16rpx;
border-bottom: 2rpx solid rgba(227, 227, 227, 100);
}
.welfare-content .li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 0rpx;
border-bottom: 2rpx solid rgba(227, 227, 227, 100)
}
.welfare-content .li .text {
font-size: 28rpx;
text-align: left;
margin-bottom: 18rpx;
font-family: PingFangSC-regular;
}
.welfare-content .li .text .ml {
margin-left: 20rpx;
}
.welfare-content .li .num {
display: flex;
color: rgba(16, 16, 16, 100);
font-size: 24rpx;
align-items: center;
}
.welfare-content .li .num .icon {
width: 28rpx;
height: 28rpx;
margin-right: 10rpx;
background-color: rgba(208, 208, 208, 100);
text-align: center;
}
.welfare-content .li .button {
width: 164rpx;
height: 64rpx;
border-radius: 60rpx;
color: rgba(255, 255, 255, 100);
line-height: 64rpx;
font-size: 28rpx;
background-color: rgba(243, 122, 97, 100);
text-align: center;
}
.time-limit .li .right .date {
color: rgba(243, 122, 97, 100);
font-size: 24rpx;
}
.time-limit .li .right {
text-align: right;
}
.time-limit .li .button {
width: 164rpx;
display: inline-block;
height: 56rpx;
margin-bottom: 22rpx;
border-radius: 60rpx;
color: rgba(255, 255, 255, 100);
line-height: 56rpx;
font-size: 28rpx;
background-color: rgba(243, 122, 97, 100);
text-align: center;
}
.time-limit .li .text {
margin-bottom: 30rpx;
}
.welfare-content .li .on {
background-color: rgba(243, 188, 97, 100);
}
.make {
width: 100%;
height: 100%;
position: fixed;
z-index: 100;
left: 0rpx;
top: 0rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.54);
}
.make-close {
width: 84rpx;
height: 84rpx;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.6);
text-align: center;
margin-top: 48rpx;
border: 2rpx solid rgba(255, 255, 255, 100);
}
.make-content .title {
width: 524rpx;
height: 168rpx;
font-size: 36rpx;
color: #FFFFFF;
padding-top: 74rpx;
position: relative;
box-sizing: border-box;
border-radius: 20rpx 20rpx 0px 0px;
background-color: rgba(243, 122, 97, 100);
text-align: center;
}
.make-content .title::after {
position: absolute;
content: "";
left: 76rpx;
top: -36rpx;
width: 46rpx;
height: 106rpx;
line-height: 20px;
border-radius: 12px;
background-color: rgba(249, 70, 70, 100);
text-align: center;
}
.make-content .title::before {
position: absolute;
content: "";
right: 76rpx;
top: -36rpx;
width: 46rpx;
height: 106rpx;
line-height: 20px;
border-radius: 12px;
background-color: rgba(249, 70, 70, 100);
text-align: center;
}
.signin-make {
width: 100%;
height: 374rpx;
border-radius: 0px 0px 20rpx 20rpx;
background-color: #FFFFFF;
}
.signin-make .text {
color: rgba(243, 122, 97, 100);
font-size: 40rpx;
padding-top: 74rpx;
box-sizing: border-box;
text-align: center;
font-family: PingFangSC-medium;
}
.signin-make .button {
width: 387rpx;
margin: auto;
height: 84rpx;
color: rgba(255, 255, 255, 100);
font-size: 28rpx;
margin-top: 90rpx;
line-height: 84rpx;
border-radius: 20rpx;
background-color: rgba(243, 122, 97, 100);
text-align: center;
}
.PacketFun-make{
width: 100%;
height: 280rpx;
border-radius: 0px 0px 20rpx 20rpx;
background-color: #FFFFFF;
color: rgba(243, 122, 97, 100);
font-size: 96rpx;
text-align: center;
line-height: 280rpx;
}
</style>

77
project.config.json Normal file
View File

@ -0,0 +1,77 @@
{
"description": "项目配置文件",
"packOptions": {
"ignore": []
},
"setting": {
"urlCheck": true,
"es6": true,
"enhance": true,
"postcss": true,
"preloadBackgroundData": false,
"minified": true,
"newFeature": false,
"coverView": true,
"nodeModules": false,
"autoAudits": false,
"showShadowRootInWxmlPanel": true,
"scopeDataCheck": false,
"uglifyFileName": false,
"checkInvalidKey": true,
"checkSiteMap": true,
"uploadWithSourceMap": true,
"compileHotReLoad": false,
"lazyloadPlaceholderEnable": false,
"useMultiFrameRuntime": true,
"useApiHook": true,
"useApiHostProcess": true,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"useIsolateContext": false,
"userConfirmedBundleSwitch": false,
"packNpmManually": false,
"packNpmRelationList": [],
"minifyWXSS": true,
"disableUseStrict": false,
"minifyWXML": true,
"showES6CompileOption": false,
"useCompilerPlugins": false,
"ignoreUploadUnusedFiles": true
},
"compileType": "miniprogram",
"libVersion": "2.22.0",
"appid": "wx987dc41899f719e8",
"projectname": "%E4%BD%A9%E4%B8%BD%E5%95%86%E5%9F%8E",
"debugOptions": {
"hidedInDevtools": []
},
"scripts": {},
"staticServerOptions": {
"baseURL": "",
"servePath": ""
},
"isGameTourist": false,
"condition": {
"search": {
"list": []
},
"conversation": {
"list": []
},
"game": {
"list": []
},
"plugin": {
"list": []
},
"gamePlugin": {
"list": []
},
"miniprogram": {
"list": []
}
}
}

19
readme.md Normal file
View File

@ -0,0 +1,19 @@
<!-- 暂无更多组件参数的使用
组件一
<nothing-page
:imgSrc="图片路径可相对、可绝对、可网络"
:currentType="0,1,2,..."
:content="'-- NO MORE --'"></nothing-page>
组件二
<pitera
:textColor="'#999999'"
:textStr="'-- NO MORE --'"
:textFontSize="'24rpx'"
:ifBold="false"
:ifCenter="true"
:paddingStr="'20rpx'"></pitera>
-->

76
uni.scss Normal file
View File

@ -0,0 +1,76 @@
/**
* uni-app
*
* uni-app https://ext.dcloud.net.cn使
* 使scss使 import 便App
*
*/
/**
* App使
*
* 使scss scss 使 import
*/
/* 颜色变量 */
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//
$uni-text-color-inverse:#fff;//
$uni-text-color-grey:#999;//
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
/* 背景颜色 */
$uni-bg-color:#ffffff;
$uni-bg-color-grey:#f8f8f8;
$uni-bg-color-hover:#f1f1f1;//
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//
/* 边框颜色 */
$uni-border-color:#c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm:24upx;
$uni-font-size-base:28upx;
$uni-font-size-lg:32upx;
/* 图片尺寸 */
$uni-img-size-sm:40upx;
$uni-img-size-base:52upx;
$uni-img-size-lg:80upx;
/* Border Radius */
$uni-border-radius-sm: 4upx;
$uni-border-radius-base: 6upx;
$uni-border-radius-lg: 12upx;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 10px;
$uni-spacing-row-base: 20upx;
$uni-spacing-row-lg: 30upx;
/* 垂直间距 */
$uni-spacing-col-sm: 8upx;
$uni-spacing-col-base: 16upx;
$uni-spacing-col-lg: 24upx;
/* 透明度 */
$uni-opacity-disabled: 0.3; //
/* 文章场景相关 */
$uni-color-title: #2C405A; //
$uni-font-size-title:40upx;
$uni-color-subtitle: #555555; //
$uni-font-size-subtitle:36upx;
$uni-color-paragraph: #3F536E; //
$uni-font-size-paragraph:30upx;

View File

@ -0,0 +1,85 @@
## 2.2.22021-12-10
- 修复 clear-icon 属性在小程序平台不生效的 bug
## 2.2.12021-12-10
- 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的 bug
## 2.2.02021-11-19
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
## 2.1.52021-11-09
- 新增 提供组件设计资源,组件样式调整
## 2.1.42021-09-10
- 修复 hide-second 在移动端的 bug
- 修复 单选赋默认值时,赋值日期未高亮的 bug
- 修复 赋默认值时,移动端未正确显示时间的 bug
## 2.1.32021-09-09
- 新增 hide-second 属性,支持只使用时分,隐藏秒
## 2.1.22021-09-03
- 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次
- 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法
- 优化 调整字号大小,美化日历界面
- 修复 因国际化导致的 placeholder 失效的 bug
## 2.1.12021-08-24
- 新增 支持国际化
- 优化 范围选择器在 pc 端过宽的问题
## 2.1.02021-08-09
- 新增 适配 vue3
## 2.0.192021-08-09
- 新增 支持作为 uni-forms 子组件相关功能
- 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的 bug
## 2.0.182021-08-05
- 修复 type 属性动态赋值无效的 bug
- 修复 ‘确认’按钮被 tabbar 遮盖 bug
- 修复 组件未赋值时范围选左、右日历相同的 bug
## 2.0.172021-08-04
- 修复 范围选未正确显示当前值的 bug
- 修复 h5 平台(移动端)报错 'cale' of undefined 的 bug
## 2.0.162021-07-21
- 新增 return-type 属性支持返回 date 日期对象
## 2.0.152021-07-14
- 修复 单选日期类型,初始赋值后不在当前日历的 bug
- 新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效)
- 优化 移动端移除显示框的清空按钮,无实际用途
## 2.0.142021-07-14
- 修复 组件赋值为空,界面未更新的 bug
- 修复 start 和 end 不能动态赋值的 bug
- 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的 bug
## 2.0.132021-07-08
- 修复 范围选择不能动态赋值的 bug
## 2.0.122021-07-08
- 修复 范围选择的初始时间在一个月内时造成无法选择的bug
## 2.0.112021-07-08
- 优化 弹出层在超出视窗边缘定位不准确的问题
## 2.0.102021-07-08
- 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的 bug
- 优化 弹出层在超出视窗边缘被遮盖的问题
## 2.0.92021-07-07
- 新增 maskClick 事件
- 修复 特殊情况日历 rpx 布局错误的 bugrpx -> px
- 修复 范围选择时清空返回值不合理的bug['', ''] -> []
## 2.0.82021-07-07
- 新增 日期时间显示框支持插槽
## 2.0.72021-07-01
- 优化 添加 uni-icons 依赖
## 2.0.62021-05-22
- 修复 图标在小程序上不显示的 bug
- 优化 重命名引用组件,避免潜在组件命名冲突
## 2.0.52021-05-20
- 优化 代码目录扁平化
## 2.0.42021-05-12
- 新增 组件示例地址
## 2.0.32021-05-10
- 修复 ios 下不识别 '-' 日期格式的 bug
- 优化 pc 下弹出层添加边框和阴影
## 2.0.22021-05-08
- 修复 在 admin 中获取弹出层定位错误的bug
## 2.0.12021-05-08
- 修复 type 属性向下兼容,默认值从 date 变更为 datetime
## 2.0.02021-04-30
- 支持日历形式的日期+时间的范围选择
> 注意此版本不向后兼容不再支持单独时间选择type=time及相关的 hide-second 属性(时间选可使用内置组件 picker
## 1.0.62021-03-18
- 新增 hide-second 属性,时间支持仅选择时、分
- 修复 选择跟显示的日期不一样的 bug
- 修复 chang事件触发2次的 bug
- 修复 分、秒 end 范围错误的 bug
- 优化 更好的 nvue 适配

View File

@ -0,0 +1,185 @@
<template>
<view class="uni-calendar-item__weeks-box" :class="{
'uni-calendar-item--disable':weeks.disable,
'uni-calendar-item--before-checked-x':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked-x':weeks.afterMultiple,
}" @click="choiceDate(weeks)" @mouseenter="handleMousemove(weeks)">
<view class="uni-calendar-item__weeks-box-item" :class="{
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && (calendar.userChecked || !checkHover),
'uni-calendar-item--checked-range-text': checkHover,
'uni-calendar-item--before-checked':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked':weeks.afterMultiple,
'uni-calendar-item--disable':weeks.disable,
}">
<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
<text class="uni-calendar-item__weeks-box-text uni-calendar-item__weeks-box-text-disable uni-calendar-item--checked-text">{{weeks.date}}</text>
</view>
<view :class="{'uni-calendar-item--isDay': weeks.isDay}"></view>
</view>
</template>
<script>
export default {
props: {
weeks: {
type: Object,
default () {
return {}
}
},
calendar: {
type: Object,
default: () => {
return {}
}
},
selected: {
type: Array,
default: () => {
return []
}
},
lunar: {
type: Boolean,
default: false
},
checkHover: {
type: Boolean,
default: false
}
},
methods: {
choiceDate(weeks) {
this.$emit('change', weeks)
},
handleMousemove(weeks) {
this.$emit('handleMouse', weeks)
}
}
}
</script>
<style lang="scss" scoped>
.uni-calendar-item__weeks-box {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
margin: 1px 0;
position: relative;
}
.uni-calendar-item__weeks-box-text {
font-size: 14px;
// font-family: Lato-Bold, Lato;
font-weight: bold;
color: #455997;
}
.uni-calendar-item__weeks-lunar-text {
font-size: 12px;
color: #333;
}
.uni-calendar-item__weeks-box-item {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
width: 40px;
height: 40px;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-calendar-item__weeks-box-circle {
position: absolute;
top: 5px;
right: 5px;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: #dd524d;
}
.uni-calendar-item__weeks-box .uni-calendar-item--disable {
// background-color: rgba(249, 249, 249, $uni-opacity-disabled);
cursor: default;
}
.uni-calendar-item--disable .uni-calendar-item__weeks-box-text-disable {
color: #D1D1D1;
}
.uni-calendar-item--isDay {
position: absolute;
top: 10px;
right: 17%;
background-color: #dd524d;
width:6px;
height: 6px;
border-radius: 50%;
}
.uni-calendar-item--extra {
color: #dd524d;
opacity: 0.8;
}
.uni-calendar-item__weeks-box .uni-calendar-item--checked {
background-color: #007aff;
border-radius: 50%;
box-sizing: border-box;
border: 3px solid #fff;
}
.uni-calendar-item--checked .uni-calendar-item--checked-text {
color: #fff;
}
.uni-calendar-item--multiple .uni-calendar-item--checked-range-text {
color: #333;
}
.uni-calendar-item--multiple {
background-color: #F6F7FC;
// color: #fff;
}
.uni-calendar-item--multiple .uni-calendar-item--before-checked,
.uni-calendar-item--multiple .uni-calendar-item--after-checked {
background-color: #409eff;
border-radius: 50%;
box-sizing: border-box;
border: 3px solid #F6F7FC;
}
.uni-calendar-item--before-checked .uni-calendar-item--checked-text,
.uni-calendar-item--after-checked .uni-calendar-item--checked-text {
color: #fff;
}
.uni-calendar-item--before-checked-x {
border-top-left-radius: 50px;
border-bottom-left-radius: 50px;
box-sizing: border-box;
background-color: #F6F7FC;
}
.uni-calendar-item--after-checked-x {
border-top-right-radius: 50px;
border-bottom-right-radius: 50px;
background-color: #F6F7FC;
}
</style>

View File

@ -0,0 +1,898 @@
<template>
<view class="uni-calendar" @mouseleave="leaveCale">
<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}"
@click="clean"></view>
<view v-if="insert || show" class="uni-calendar__content"
:class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow, 'uni-calendar__content-mobile': aniMaskShow}">
<view class="uni-calendar__header" :class="{'uni-calendar__header-mobile' :!insert}">
<view v-if="left" class="uni-calendar__header-btn-box" @click.stop="pre">
<view class="uni-calendar__header-btn uni-calendar--left"></view>
</view>
<picker mode="date" :value="date" fields="month" @change="bindDateChange">
<text
class="uni-calendar__header-text">{{ (nowDate.year||'') + ' 年 ' + ( nowDate.month||'') +' 月'}}</text>
</picker>
<view v-if="right" class="uni-calendar__header-btn-box" @click.stop="next">
<view class="uni-calendar__header-btn uni-calendar--right"></view>
</view>
<view v-if="!insert" class="dialog-close" @click="clean">
<view class="dialog-close-plus" data-id="close"></view>
<view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
</view>
<!-- <text class="uni-calendar__backtoday" @click="backtoday"></text> -->
</view>
<view class="uni-calendar__box">
<view v-if="showMonth" class="uni-calendar__box-bg">
<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
</view>
<view class="uni-calendar__weeks" style="padding-bottom: 7px;">
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{monText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{THUText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{SATText}}</text>
</view>
</view>
<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar"
:selected="selected" :lunar="lunar" :checkHover="range" @change="choiceDate"
@handleMouse="handleMouse">
</calendar-item>
</view>
</view>
</view>
<view v-if="!insert && !range && typeHasTime" class="uni-date-changed uni-calendar--fixed-top"
style="padding: 0 80px;">
<view class="uni-date-changed--time-date">{{tempSingleDate ? tempSingleDate : selectDateText}}</view>
<time-picker type="time" :start="reactStartTime" :end="reactEndTime" v-model="time"
:disabled="!tempSingleDate" :border="false" :hide-second="hideSecond" class="time-picker-style">
</time-picker>
</view>
<view v-if="!insert && range && typeHasTime" class="uni-date-changed uni-calendar--fixed-top">
<view class="uni-date-changed--time-start">
<view class="uni-date-changed--time-date">{{tempRange.before ? tempRange.before : startDateText}}
</view>
<time-picker type="time" :start="reactStartTime" v-model="timeRange.startTime" :border="false"
:hide-second="hideSecond" :disabled="!tempRange.before" class="time-picker-style">
</time-picker>
</view>
<uni-icons type="arrowthinright" color="#999" style="line-height: 50px;"></uni-icons>
<view class="uni-date-changed--time-end">
<view class="uni-date-changed--time-date">{{tempRange.after ? tempRange.after : endDateText}}</view>
<time-picker type="time" :end="reactEndTime" v-model="timeRange.endTime" :border="false"
:hide-second="hideSecond" :disabled="!tempRange.after" class="time-picker-style">
</time-picker>
</view>
</view>
<view v-if="!insert" class="uni-date-changed uni-date-btn--ok">
<!-- <view class="uni-calendar__header-btn-box">
<text class="uni-calendar__button-text uni-calendar--fixed-width">{{okText}}</text>
</view> -->
<view class="uni-datetime-picker--btn" @click="confirm"></view>
</view>
</view>
</view>
</template>
<script>
import Calendar from './util.js';
import calendarItem from './calendar-item.vue'
import timePicker from './time-picker.vue'
import {
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from './i18n/index.js'
const {
t
} = initVueI18n(messages)
/**
* Calendar 日历
* @description 日历组件可以查看日期选择任意范围内的日期打点操作常用场景如酒店日期预订火车机票选择购买日期上下班打卡等
* @tutorial https://ext.dcloud.net.cn/plugin?id=56
* @property {String} date 自定义当前时间默认为今天
* @property {Boolean} lunar 显示农历
* @property {String} startDate 日期选择范围-开始日期
* @property {String} endDate 日期选择范围-结束日期
* @property {Boolean} range 范围选择
* @property {Boolean} insert = [true|false] 插入模式,默认为false
* @value true 弹窗模式
* @value false 插入模式
* @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
* @property {Array} selected 打点期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
* @property {Boolean} showMonth 是否选择月份为背景
* @event {Function} change 日期改变`insert :ture` 时生效
* @event {Function} confirm 确认选择`insert :false` 时生效
* @event {Function} monthSwitch 切换月份时触发
* @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
*/
export default {
components: {
calendarItem,
timePicker
},
props: {
date: {
type: String,
default: ''
},
defTime: {
type: [String, Object],
default: ''
},
selectableTimes: {
type: [Object],
default () {
return {}
}
},
selected: {
type: Array,
default () {
return []
}
},
lunar: {
type: Boolean,
default: false
},
startDate: {
type: String,
default: ''
},
endDate: {
type: String,
default: ''
},
range: {
type: Boolean,
default: false
},
typeHasTime: {
type: Boolean,
default: false
},
insert: {
type: Boolean,
default: true
},
showMonth: {
type: Boolean,
default: true
},
clearDate: {
type: Boolean,
default: true
},
left: {
type: Boolean,
default: true
},
right: {
type: Boolean,
default: true
},
checkHover: {
type: Boolean,
default: true
},
hideSecond: {
type: [Boolean],
default: false
},
pleStatus: {
type: Object,
default () {
return {
before: '',
after: '',
data: [],
fulldate: ''
}
}
}
},
data() {
return {
show: false,
weeks: [],
calendar: {},
nowDate: '',
aniMaskShow: false,
firstEnter: true,
time: '',
timeRange: {
startTime: '',
endTime: ''
},
tempSingleDate: '',
tempRange: {
before: '',
after: ''
}
}
},
watch: {
date: {
immediate: true,
handler(newVal, oldVal) {
if (!this.range) {
this.tempSingleDate = newVal
setTimeout(() => {
this.init(newVal)
}, 100)
}
}
},
defTime: {
immediate: true,
handler(newVal, oldVal) {
if (!this.range) {
this.time = newVal
} else {
// console.log('-----', newVal);
this.timeRange.startTime = newVal.start
this.timeRange.endTime = newVal.end
}
}
},
startDate(val) {
this.cale.resetSatrtDate(val)
this.cale.setDate(this.nowDate.fullDate)
this.weeks = this.cale.weeks
},
endDate(val) {
this.cale.resetEndDate(val)
this.cale.setDate(this.nowDate.fullDate)
this.weeks = this.cale.weeks
},
selected(newVal) {
this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
this.weeks = this.cale.weeks
},
pleStatus: {
immediate: true,
handler(newVal, oldVal) {
const {
before,
after,
fulldate,
which
} = newVal
this.tempRange.before = before
this.tempRange.after = after
setTimeout(() => {
if (fulldate) {
this.cale.setHoverMultiple(fulldate)
if (before && after) {
this.cale.lastHover = true
if (this.rangeWithinMonth(after, before)) return
this.setDate(before)
} else {
this.cale.setMultiple(fulldate)
this.setDate(this.nowDate.fullDate)
this.calendar.fullDate = ''
this.cale.lastHover = false
}
} else {
this.cale.setDefaultMultiple(before, after)
if (which === 'left') {
this.setDate(before)
this.weeks = this.cale.weeks
} else {
this.setDate(after)
this.weeks = this.cale.weeks
}
this.cale.lastHover = true
}
}, 16)
}
}
},
computed: {
reactStartTime() {
const activeDate = this.range ? this.tempRange.before : this.calendar.fullDate
const res = activeDate === this.startDate ? this.selectableTimes.start : ''
return res
},
reactEndTime() {
const activeDate = this.range ? this.tempRange.after : this.calendar.fullDate
const res = activeDate === this.endDate ? this.selectableTimes.end : ''
return res
},
/**
* for i18n
*/
selectDateText() {
return t("uni-datetime-picker.selectDate")
},
startDateText() {
return this.startPlaceholder || t("uni-datetime-picker.startDate")
},
endDateText() {
return this.endPlaceholder || t("uni-datetime-picker.endDate")
},
okText() {
return t("uni-datetime-picker.ok")
},
monText() {
return t("uni-calender.MON")
},
TUEText() {
return t("uni-calender.TUE")
},
WEDText() {
return t("uni-calender.WED")
},
THUText() {
return t("uni-calender.THU")
},
FRIText() {
return t("uni-calender.FRI")
},
SATText() {
return t("uni-calender.SAT")
},
SUNText() {
return t("uni-calender.SUN")
},
},
created() {
//
this.cale = new Calendar({
// date: new Date(),
selected: this.selected,
startDate: this.startDate,
endDate: this.endDate,
range: this.range,
// multipleStatus: this.pleStatus
})
//
// this.cale.setDate(this.date)
this.init(this.date)
// this.setDay
},
methods: {
leaveCale() {
this.firstEnter = true
},
handleMouse(weeks) {
if (weeks.disable) return
if (this.cale.lastHover) return
let {
before,
after
} = this.cale.multipleStatus
if (!before) return
this.calendar = weeks
//
this.cale.setHoverMultiple(this.calendar.fullDate)
this.weeks = this.cale.weeks
// hover
if (this.firstEnter) {
this.$emit('firstEnterCale', this.cale.multipleStatus)
this.firstEnter = false
}
},
rangeWithinMonth(A, B) {
const [yearA, monthA] = A.split('-')
const [yearB, monthB] = B.split('-')
return yearA === yearB && monthA === monthB
},
// 穿
clean() {
this.close()
},
clearCalender() {
if (this.range) {
this.timeRange.startTime = ''
this.timeRange.endTime = ''
this.tempRange.before = ''
this.tempRange.after = ''
this.cale.multipleStatus.before = ''
this.cale.multipleStatus.after = ''
this.cale.multipleStatus.data = []
this.cale.lastHover = false
} else {
this.time = ''
this.tempSingleDate = ''
}
this.calendar.fullDate = ''
this.setDate()
},
bindDateChange(e) {
const value = e.detail.value + '-1'
this.init(value)
},
/**
* 初始化日期显示
* @param {Object} date
*/
init(date) {
this.cale.setDate(date)
this.weeks = this.cale.weeks
this.nowDate = this.calendar = this.cale.getInfo(date)
},
// choiceDate(weeks) {
// if (weeks.disable) return
// this.calendar = weeks
// //
// this.cale.setMultiple(this.calendar.fullDate, true)
// this.weeks = this.cale.weeks
// this.tempSingleDate = this.calendar.fullDate
// this.tempRange.before = this.cale.multipleStatus.before
// this.tempRange.after = this.cale.multipleStatus.after
// this.change()
// },
/**
* 打开日历弹窗
*/
open() {
//
if (this.clearDate && !this.insert) {
this.cale.cleanMultipleStatus()
// this.cale.setDate(this.date)
this.init(this.date)
}
this.show = true
this.$nextTick(() => {
setTimeout(() => {
this.aniMaskShow = true
}, 50)
})
},
/**
* 关闭日历弹窗
*/
close() {
this.aniMaskShow = false
this.$nextTick(() => {
setTimeout(() => {
this.show = false
this.$emit('close')
}, 300)
})
},
/**
* 确认按钮
*/
confirm() {
this.setEmit('confirm')
this.close()
},
/**
* 变化触发
*/
change() {
if (!this.insert) return
this.setEmit('change')
},
/**
* 选择月份触发
*/
monthSwitch() {
let {
year,
month
} = this.nowDate
this.$emit('monthSwitch', {
year,
month: Number(month)
})
},
/**
* 派发事件
* @param {Object} name
*/
setEmit(name) {
let {
year,
month,
date,
fullDate,
lunar,
extraInfo
} = this.calendar
this.$emit(name, {
range: this.cale.multipleStatus,
year,
month,
date,
time: this.time,
timeRange: this.timeRange,
fulldate: fullDate,
lunar,
extraInfo: extraInfo || {}
})
},
/**
* 选择天触发
* @param {Object} weeks
*/
choiceDate(weeks) {
if (weeks.disable) return
this.calendar = weeks
this.calendar.userChecked = true
//
this.cale.setMultiple(this.calendar.fullDate, true)
this.weeks = this.cale.weeks
this.tempSingleDate = this.calendar.fullDate
this.tempRange.before = this.cale.multipleStatus.before
this.tempRange.after = this.cale.multipleStatus.after
this.change()
},
/**
* 回到今天
*/
backtoday() {
let date = this.cale.getDate(new Date()).fullDate
// this.cale.setDate(date)
this.init(date)
this.change()
},
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
//
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
//
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
if (startDate <= endDate) {
return true
} else {
return false
}
},
/**
* 上个月
*/
pre() {
const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
this.setDate(preDate)
this.monthSwitch()
},
/**
* 下个月
*/
next() {
const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
this.setDate(nextDate)
this.monthSwitch()
},
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.cale.setDate(date)
this.weeks = this.cale.weeks
this.nowDate = this.cale.getInfo(date)
}
}
}
</script>
<style lang="scss" scoped>
.uni-calendar {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.uni-calendar__mask {
position: fixed;
bottom: 0;
top: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.4);
transition-property: opacity;
transition-duration: 0.3s;
opacity: 0;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-calendar--mask-show {
opacity: 1
}
.uni-calendar--fixed {
position: fixed;
bottom: calc(var(--window-bottom));
left: 0;
right: 0;
transition-property: transform;
transition-duration: 0.3s;
transform: translateY(460px);
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-calendar--ani-show {
transform: translateY(0);
}
.uni-calendar__content {
background-color: #fff;
}
.uni-calendar__content-mobile {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
box-shadow: 0px 0px 5px 3px rgba(0, 0, 0, 0.1);
}
.uni-calendar__header {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
height: 50px;
}
.uni-calendar__header-mobile {
padding: 10px;
padding-bottom: 0;
}
.uni-calendar--fixed-top {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
border-top-color: rgba(0, 0, 0, 0.4);
border-top-style: solid;
border-top-width: 1px;
}
.uni-calendar--fixed-width {
width: 50px;
}
.uni-calendar__backtoday {
position: absolute;
right: 0;
top: 25rpx;
padding: 0 5px;
padding-left: 10px;
height: 25px;
line-height: 25px;
font-size: 12px;
border-top-left-radius: 25px;
border-bottom-left-radius: 25px;
color: #fff;
background-color: #f1f1f1;
}
.uni-calendar__header-text {
text-align: center;
width: 100px;
font-size: 15px;
color: #666;
}
.uni-calendar__button-text {
text-align: center;
width: 100px;
font-size: 14px;
color: #007aff;
/* #ifndef APP-NVUE */
letter-spacing: 3px;
/* #endif */
}
.uni-calendar__header-btn-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
}
.uni-calendar__header-btn {
width: 9px;
height: 9px;
border-left-color: #808080;
border-left-style: solid;
border-left-width: 1px;
border-top-color: #555555;
border-top-style: solid;
border-top-width: 1px;
}
.uni-calendar--left {
transform: rotate(-45deg);
}
.uni-calendar--right {
transform: rotate(135deg);
}
.uni-calendar__weeks {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-calendar__weeks-item {
flex: 1;
}
.uni-calendar__weeks-day {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
height: 40px;
border-bottom-color: #F5F5F5;
border-bottom-style: solid;
border-bottom-width: 1px;
}
.uni-calendar__weeks-day-text {
font-size: 12px;
color: #B2B2B2;
}
.uni-calendar__box {
position: relative;
// padding: 0 10px;
padding-bottom: 7px;
}
.uni-calendar__box-bg {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.uni-calendar__box-bg-text {
font-size: 200px;
font-weight: bold;
color: #999;
opacity: 0.1;
text-align: center;
/* #ifndef APP-NVUE */
line-height: 1;
/* #endif */
}
.uni-date-changed {
padding: 0 10px;
// line-height: 50px;
text-align: center;
color: #333;
border-top-color: #DCDCDC;
;
border-top-style: solid;
border-top-width: 1px;
flex: 1;
}
.uni-date-btn--ok {
padding: 20px 15px;
}
.uni-date-changed--time-start {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
}
.uni-date-changed--time-end {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
}
.uni-date-changed--time-date {
color: #999;
line-height: 50px;
margin-right: 5px;
// opacity: 0.6;
}
.time-picker-style {
// width: 62px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center
}
.mr-10 {
margin-right: 10px;
}
.dialog-close {
position: absolute;
top: 0;
right: 0;
bottom: 0;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
padding: 0 25px;
margin-top: 10px;
}
.dialog-close-plus {
width: 16px;
height: 2px;
background-color: #737987;
border-radius: 2px;
transform: rotate(45deg);
}
.dialog-close-rotate {
position: absolute;
transform: rotate(-45deg);
}
.uni-datetime-picker--btn {
border-radius: 100px;
height: 40px;
line-height: 40px;
background-color: #007aff;
color: #fff;
font-size: 16px;
letter-spacing: 5px;
}
/* #ifndef APP-NVUE */
.uni-datetime-picker--btn:active {
opacity: 0.7;
}
/* #endif */
</style>

View File

@ -0,0 +1,19 @@
{
"uni-datetime-picker.selectDate": "select date",
"uni-datetime-picker.selectTime": "select time",
"uni-datetime-picker.selectDateTime": "select datetime",
"uni-datetime-picker.startDate": "start date",
"uni-datetime-picker.endDate": "end date",
"uni-datetime-picker.startTime": "start time",
"uni-datetime-picker.endTime": "end time",
"uni-datetime-picker.ok": "ok",
"uni-datetime-picker.clear": "clear",
"uni-datetime-picker.cancel": "cancel",
"uni-calender.MON": "MON",
"uni-calender.TUE": "TUE",
"uni-calender.WED": "WED",
"uni-calender.THU": "THU",
"uni-calender.FRI": "FRI",
"uni-calender.SAT": "SAT",
"uni-calender.SUN": "SUN"
}

View File

@ -0,0 +1,8 @@
import en from './en.json'
import zhHans from './zh-Hans.json'
import zhHant from './zh-Hant.json'
export default {
en,
'zh-Hans': zhHans,
'zh-Hant': zhHant
}

View File

@ -0,0 +1,19 @@
{
"uni-datetime-picker.selectDate": "选择日期",
"uni-datetime-picker.selectTime": "选择时间",
"uni-datetime-picker.selectDateTime": "选择日期时间",
"uni-datetime-picker.startDate": "开始日期",
"uni-datetime-picker.endDate": "结束日期",
"uni-datetime-picker.startTime": "开始时间",
"uni-datetime-picker.endTime": "结束时间",
"uni-datetime-picker.ok": "确定",
"uni-datetime-picker.clear": "清除",
"uni-datetime-picker.cancel": "取消",
"uni-calender.SUN": "日",
"uni-calender.MON": "一",
"uni-calender.TUE": "二",
"uni-calender.WED": "三",
"uni-calender.THU": "四",
"uni-calender.FRI": "五",
"uni-calender.SAT": "六"
}

View File

@ -0,0 +1,19 @@
{
"uni-datetime-picker.selectDate": "選擇日期",
"uni-datetime-picker.selectTime": "選擇時間",
"uni-datetime-picker.selectDateTime": "選擇日期時間",
"uni-datetime-picker.startDate": "開始日期",
"uni-datetime-picker.endDate": "結束日期",
"uni-datetime-picker.startTime": "開始时间",
"uni-datetime-picker.endTime": "結束时间",
"uni-datetime-picker.ok": "確定",
"uni-datetime-picker.clear": "清除",
"uni-datetime-picker.cancel": "取消",
"uni-calender.SUN": "日",
"uni-calender.MON": "一",
"uni-calender.TUE": "二",
"uni-calender.WED": "三",
"uni-calender.THU": "四",
"uni-calender.FRI": "五",
"uni-calender.SAT": "六"
}

View File

@ -0,0 +1,45 @@
// #ifdef H5
export default {
name: 'Keypress',
props: {
disable: {
type: Boolean,
default: false
}
},
mounted () {
const keyNames = {
esc: ['Esc', 'Escape'],
tab: 'Tab',
enter: 'Enter',
space: [' ', 'Spacebar'],
up: ['Up', 'ArrowUp'],
left: ['Left', 'ArrowLeft'],
right: ['Right', 'ArrowRight'],
down: ['Down', 'ArrowDown'],
delete: ['Backspace', 'Delete', 'Del']
}
const listener = ($event) => {
if (this.disable) {
return
}
const keyName = Object.keys(keyNames).find(key => {
const keyName = $event.key
const value = keyNames[key]
return value === keyName || (Array.isArray(value) && value.includes(keyName))
})
if (keyName) {
// 避免和其他按键事件冲突
setTimeout(() => {
this.$emit(keyName, {})
}, 0)
}
}
document.addEventListener('keyup', listener)
this.$once('hook:beforeDestroy', () => {
document.removeEventListener('keyup', listener)
})
},
render: () => {}
}
// #endif

View File

@ -0,0 +1,927 @@
<template>
<view class="uni-datetime-picker">
<view @click="initTimePicker">
<slot>
<view class="uni-datetime-picker-timebox-pointer"
:class="{'uni-datetime-picker-disabled': disabled, 'uni-datetime-picker-timebox': border}">
<text class="uni-datetime-picker-text">{{time}}</text>
<view v-if="!time" class="uni-datetime-picker-time">
<text class="uni-datetime-picker-text">{{selectTimeText}}</text>
</view>
</view>
</slot>
</view>
<view v-if="visible" id="mask" class="uni-datetime-picker-mask" @click="tiggerTimePicker"></view>
<view v-if="visible" class="uni-datetime-picker-popup" :class="[dateShow && timeShow ? '' : 'fix-nvue-height']"
:style="fixNvueBug">
<view class="uni-title">
<text class="uni-datetime-picker-text">{{selectTimeText}}</text>
</view>
<view v-if="dateShow" class="uni-datetime-picker__container-box">
<picker-view class="uni-datetime-picker-view" :indicator-style="indicatorStyle" :value="ymd"
@change="bindDateChange">
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in years" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in months" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in days" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
</picker-view>
<!-- 兼容 nvue 不支持伪类 -->
<text class="uni-datetime-picker-sign sign-left">-</text>
<text class="uni-datetime-picker-sign sign-right">-</text>
</view>
<view v-if="timeShow" class="uni-datetime-picker__container-box">
<picker-view class="uni-datetime-picker-view" :class="[hideSecond ? 'time-hide-second' : '']"
:indicator-style="indicatorStyle" :value="hms" @change="bindTimeChange">
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in hours" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in minutes" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
<picker-view-column v-if="!hideSecond">
<view class="uni-datetime-picker-item" v-for="(item,index) in seconds" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
</picker-view>
<!-- 兼容 nvue 不支持伪类 -->
<text class="uni-datetime-picker-sign" :class="[hideSecond ? 'sign-center' : 'sign-left']">:</text>
<text v-if="!hideSecond" class="uni-datetime-picker-sign sign-right">:</text>
</view>
<view class="uni-datetime-picker-btn">
<view @click="clearTime">
<text class="uni-datetime-picker-btn-text">{{clearText}}</text>
</view>
<view class="uni-datetime-picker-btn-group">
<view class="uni-datetime-picker-cancel" @click="tiggerTimePicker">
<text class="uni-datetime-picker-btn-text">{{cancelText}}</text>
</view>
<view @click="setTime">
<text class="uni-datetime-picker-btn-text">{{okText}}</text>
</view>
</view>
</view>
</view>
<!-- #ifdef H5 -->
<!-- <keypress v-if="visible" @esc="tiggerTimePicker" @enter="setTime" /> -->
<!-- #endif -->
</view>
</template>
<script>
// #ifdef H5
import keypress from './keypress'
// #endif
import {
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from './i18n/index.js'
const { t } = initVueI18n(messages)
/**
* DatetimePicker 时间选择器
* @description 可以同时选择日期和时间的选择器
* @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
* @property {String} type = [datetime | date | time] 显示模式
* @property {Boolean} multiple = [true|false] 是否多选
* @property {String|Number} value 默认值
* @property {String|Number} start 起始日期或时间
* @property {String|Number} end 起始日期或时间
* @property {String} return-type = [timestamp | string]
* @event {Function} change 选中发生变化触发
*/
export default {
name: 'UniDatetimePicker',
components: {
// #ifdef H5
keypress
// #endif
},
data() {
return {
indicatorStyle: `height: 50px;`,
visible: false,
fixNvueBug: {},
dateShow: true,
timeShow: true,
title: '日期和时间',
//
time: '',
//
year: 1920,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0,
//
startYear: 1920,
startMonth: 1,
startDay: 1,
startHour: 0,
startMinute: 0,
startSecond: 0,
//
endYear: 2120,
endMonth: 12,
endDay: 31,
endHour: 23,
endMinute: 59,
endSecond: 59,
}
},
props: {
type: {
type: String,
default: 'datetime'
},
value: {
type: [String, Number],
default: ''
},
modelValue: {
type: [String, Number],
default: ''
},
start: {
type: [Number, String],
default: ''
},
end: {
type: [Number, String],
default: ''
},
returnType: {
type: String,
default: 'string'
},
disabled: {
type: [Boolean, String],
default: false
},
border: {
type: [Boolean, String],
default: true
},
hideSecond: {
type: [Boolean, String],
default: false
}
},
watch: {
value: {
handler(newVal, oldVal) {
if (newVal) {
this.parseValue(this.fixIosDateFormat(newVal)) // iOSsafari
this.initTime(false)
} else {
this.time = ''
this.parseValue(Date.now())
}
},
immediate: true
},
type: {
handler(newValue) {
if (newValue === 'date') {
this.dateShow = true
this.timeShow = false
this.title = '日期'
} else if (newValue === 'time') {
this.dateShow = false
this.timeShow = true
this.title = '时间'
} else {
this.dateShow = true
this.timeShow = true
this.title = '日期和时间'
}
},
immediate: true
},
start: {
handler(newVal) {
this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'start') // iOSsafari
},
immediate: true
},
end: {
handler(newVal) {
this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'end') // iOSsafari
},
immediate: true
},
//
months(newVal) {
this.checkValue('month', this.month, newVal)
},
days(newVal) {
this.checkValue('day', this.day, newVal)
},
hours(newVal) {
this.checkValue('hour', this.hour, newVal)
},
minutes(newVal) {
this.checkValue('minute', this.minute, newVal)
},
seconds(newVal) {
this.checkValue('second', this.second, newVal)
}
},
computed: {
//
years() {
return this.getCurrentRange('year')
},
months() {
return this.getCurrentRange('month')
},
days() {
return this.getCurrentRange('day')
},
hours() {
return this.getCurrentRange('hour')
},
minutes() {
return this.getCurrentRange('minute')
},
seconds() {
return this.getCurrentRange('second')
},
// picker
ymd() {
return [this.year - this.minYear, this.month - this.minMonth, this.day - this.minDay]
},
hms() {
return [this.hour - this.minHour, this.minute - this.minMinute, this.second - this.minSecond]
},
// date start
currentDateIsStart() {
return this.year === this.startYear && this.month === this.startMonth && this.day === this.startDay
},
// date end
currentDateIsEnd() {
return this.year === this.endYear && this.month === this.endMonth && this.day === this.endDay
},
//
minYear() {
return this.startYear
},
maxYear() {
return this.endYear
},
minMonth() {
if (this.year === this.startYear) {
return this.startMonth
} else {
return 1
}
},
maxMonth() {
if (this.year === this.endYear) {
return this.endMonth
} else {
return 12
}
},
minDay() {
if (this.year === this.startYear && this.month === this.startMonth) {
return this.startDay
} else {
return 1
}
},
maxDay() {
if (this.year === this.endYear && this.month === this.endMonth) {
return this.endDay
} else {
return this.daysInMonth(this.year, this.month)
}
},
minHour() {
if (this.type === 'datetime') {
if (this.currentDateIsStart) {
return this.startHour
} else {
return 0
}
}
if (this.type === 'time') {
return this.startHour
}
},
maxHour() {
if (this.type === 'datetime') {
if (this.currentDateIsEnd) {
return this.endHour
} else {
return 23
}
}
if (this.type === 'time') {
return this.endHour
}
},
minMinute() {
if (this.type === 'datetime') {
if (this.currentDateIsStart && this.hour === this.startHour) {
return this.startMinute
} else {
return 0
}
}
if (this.type === 'time') {
if (this.hour === this.startHour) {
return this.startMinute
} else {
return 0
}
}
},
maxMinute() {
if (this.type === 'datetime') {
if (this.currentDateIsEnd && this.hour === this.endHour) {
return this.endMinute
} else {
return 59
}
}
if (this.type === 'time') {
if (this.hour === this.endHour) {
return this.endMinute
} else {
return 59
}
}
},
minSecond() {
if (this.type === 'datetime') {
if (this.currentDateIsStart && this.hour === this.startHour && this.minute === this.startMinute) {
return this.startSecond
} else {
return 0
}
}
if (this.type === 'time') {
if (this.hour === this.startHour && this.minute === this.startMinute) {
return this.startSecond
} else {
return 0
}
}
},
maxSecond() {
if (this.type === 'datetime') {
if (this.currentDateIsEnd && this.hour === this.endHour && this.minute === this.endMinute) {
return this.endSecond
} else {
return 59
}
}
if (this.type === 'time') {
if (this.hour === this.endHour && this.minute === this.endMinute) {
return this.endSecond
} else {
return 59
}
}
},
/**
* for i18n
*/
selectTimeText() {
return t("uni-datetime-picker.selectTime")
},
okText() {
return t("uni-datetime-picker.ok")
},
clearText() {
return t("uni-datetime-picker.clear")
},
cancelText() {
return t("uni-datetime-picker.cancel")
}
},
mounted() {
// #ifdef APP-NVUE
const res = uni.getSystemInfoSync();
this.fixNvueBug = {
top: res.windowHeight / 2,
left: res.windowWidth / 2
}
// #endif
},
methods: {
/**
* @param {Object} item
* 小于 10 在前面加个 0
*/
lessThanTen(item) {
return item < 10 ? '0' + item : item
},
/**
* 解析时分秒字符串例如00:00:00
* @param {String} timeString
*/
parseTimeType(timeString) {
if (timeString) {
let timeArr = timeString.split(':')
this.hour = Number(timeArr[0])
this.minute = Number(timeArr[1])
this.second = Number(timeArr[2])
}
},
/**
* 解析选择器初始值类型可以是字符串时间戳例如2000-10-02'08:30:00' 1610695109000
* @param {String | Number} datetime
*/
initPickerValue(datetime) {
let defaultValue = null
if (datetime) {
defaultValue = this.compareValueWithStartAndEnd(datetime, this.start, this.end)
} else {
defaultValue = Date.now()
defaultValue = this.compareValueWithStartAndEnd(defaultValue, this.start, this.end)
}
this.parseValue(defaultValue)
},
/**
* 初始值规则
* - 用户设置初始值 value
* - 设置了起始时间 start终止时间 end start < value < end初始值为 value 否则初始值为 start
* - 只设置了起始时间 start start < value初始值为 value否则初始值为 start
* - 只设置了终止时间 end value < end初始值为 value否则初始值为 end
* - 无起始终止时间则初始值为 value
* - 无初始值 value则初始值为当前本地时间 Date.now()
* @param {Object} value
* @param {Object} dateBase
*/
compareValueWithStartAndEnd(value, start, end) {
let winner = null
value = this.superTimeStamp(value)
start = this.superTimeStamp(start)
end = this.superTimeStamp(end)
if (start && end) {
if (value < start) {
winner = new Date(start)
} else if (value > end) {
winner = new Date(end)
} else {
winner = new Date(value)
}
} else if (start && !end) {
winner = start <= value ? new Date(value) : new Date(start)
} else if (!start && end) {
winner = value <= end ? new Date(value) : new Date(end)
} else {
winner = new Date(value)
}
return winner
},
/**
* 转换为可比较的时间戳接受日期时分秒时间戳
* @param {Object} value
*/
superTimeStamp(value) {
let dateBase = ''
if (this.type === 'time' && value && typeof value === 'string') {
const now = new Date()
const year = now.getFullYear()
const month = now.getMonth() + 1
const day = now.getDate()
dateBase = year + '/' + month + '/' + day + ' '
}
if (Number(value) && typeof value !== NaN) {
value = parseInt(value)
dateBase = 0
}
return this.createTimeStamp(dateBase + value)
},
/**
* 解析默认值 value字符串时间戳
* @param {Object} defaultTime
*/
parseValue(value) {
if (!value) {
return
}
if (this.type === 'time' && typeof value === "string") {
this.parseTimeType(value)
} else {
let defaultDate = null
defaultDate = new Date(value)
if (this.type !== 'time') {
this.year = defaultDate.getFullYear()
this.month = defaultDate.getMonth() + 1
this.day = defaultDate.getDate()
}
if (this.type !== 'date') {
this.hour = defaultDate.getHours()
this.minute = defaultDate.getMinutes()
this.second = defaultDate.getSeconds()
}
}
if (this.hideSecond) {
this.second = 0
}
},
/**
* 解析可选择时间范围 startend年月日字符串时间戳
* @param {Object} defaultTime
*/
parseDatetimeRange(point, pointType) {
//
if (!point) {
if (pointType === 'start') {
this.startYear = 1920
this.startMonth = 1
this.startDay = 1
this.startHour = 0
this.startMinute = 0
this.startSecond = 0
}
if (pointType === 'end') {
this.endYear = 2120
this.endMonth = 12
this.endDay = 31
this.endHour = 23
this.endMinute = 59
this.endSecond = 59
}
return
}
if (this.type === 'time') {
const pointArr = point.split(':')
this[pointType + 'Hour'] = Number(pointArr[0])
this[pointType + 'Minute'] = Number(pointArr[1])
this[pointType + 'Second'] = Number(pointArr[2])
} else {
if (!point) {
pointType === 'start' ? this.startYear = this.year - 60 : this.endYear = this.year + 60
return
}
if (Number(point) && Number(point) !== NaN) {
point = parseInt(point)
}
// datetime end ,
const hasTime = /[0-9]:[0-9]/
if (this.type === 'datetime' && pointType === 'end' && typeof point === 'string' && !hasTime.test(
point)) {
point = point + ' 23:59:59'
}
const pointDate = new Date(point)
this[pointType + 'Year'] = pointDate.getFullYear()
this[pointType + 'Month'] = pointDate.getMonth() + 1
this[pointType + 'Day'] = pointDate.getDate()
if (this.type === 'datetime') {
this[pointType + 'Hour'] = pointDate.getHours()
this[pointType + 'Minute'] = pointDate.getMinutes()
this[pointType + 'Second'] = pointDate.getSeconds()
}
}
},
//
getCurrentRange(value) {
const range = []
for (let i = this['min' + this.capitalize(value)]; i <= this['max' + this.capitalize(value)]; i++) {
range.push(i)
}
return range
},
//
capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
},
//
checkValue(name, value, values) {
if (values.indexOf(value) === -1) {
this[name] = values[0]
}
},
//
daysInMonth(year, month) { // Use 1 for January, 2 for February, etc.
return new Date(year, month, 0).getDate();
},
// iOSsafari
fixIosDateFormat(value) {
if (typeof value === 'string') {
value = value.replace(/-/g, '/')
}
return value
},
/**
* 生成时间戳
* @param {Object} time
*/
createTimeStamp(time) {
if (!time) return
if (typeof time === "number") {
return time
} else {
time = time.replace(/-/g, '/')
if (this.type === 'date') {
time = time + ' ' + '00:00:00'
}
return Date.parse(time)
}
},
/**
* 生成日期或时间的字符串
*/
createDomSting() {
const yymmdd = this.year +
'-' +
this.lessThanTen(this.month) +
'-' +
this.lessThanTen(this.day)
let hhmmss = this.lessThanTen(this.hour) +
':' +
this.lessThanTen(this.minute)
if (!this.hideSecond) {
hhmmss = hhmmss + ':' + this.lessThanTen(this.second)
}
if (this.type === 'date') {
return yymmdd
} else if (this.type === 'time') {
return hhmmss
} else {
return yymmdd + ' ' + hhmmss
}
},
/**
* 初始化返回值并抛出 change 事件
*/
initTime(emit = true) {
this.time = this.createDomSting()
if (!emit) return
if (this.returnType === 'timestamp' && this.type !== 'time') {
this.$emit('change', this.createTimeStamp(this.time))
this.$emit('input', this.createTimeStamp(this.time))
this.$emit('update:modelValue', this.createTimeStamp(this.time))
} else {
this.$emit('change', this.time)
this.$emit('input', this.time)
this.$emit('update:modelValue', this.time)
}
},
/**
* 用户选择日期或时间更新 data
* @param {Object} e
*/
bindDateChange(e) {
const val = e.detail.value
this.year = this.years[val[0]]
this.month = this.months[val[1]]
this.day = this.days[val[2]]
},
bindTimeChange(e) {
const val = e.detail.value
this.hour = this.hours[val[0]]
this.minute = this.minutes[val[1]]
this.second = this.seconds[val[2]]
},
/**
* 初始化弹出层
*/
initTimePicker() {
if (this.disabled) return
const value = this.fixIosDateFormat(this.value)
this.initPickerValue(value)
this.visible = !this.visible
},
/**
* 触发或关闭弹框
*/
tiggerTimePicker(e) {
this.visible = !this.visible
},
/**
* 用户点击清空按钮清空当前值
*/
clearTime() {
this.time = ''
this.$emit('change', this.time)
this.$emit('input', this.time)
this.$emit('update:modelValue', this.time)
this.tiggerTimePicker()
},
/**
* 用户点击确定按钮
*/
setTime() {
this.initTime()
this.tiggerTimePicker()
}
}
}
</script>
<style>
.uni-datetime-picker {
/* #ifndef APP-NVUE */
/* width: 100%; */
/* #endif */
}
.uni-datetime-picker-view {
height: 130px;
width: 270px;
/* #ifndef APP-NVUE */
cursor: pointer;
/* #endif */
}
.uni-datetime-picker-item {
height: 50px;
line-height: 50px;
text-align: center;
font-size: 14px;
}
.uni-datetime-picker-btn {
margin-top: 60px;
/* #ifndef APP-NVUE */
display: flex;
cursor: pointer;
/* #endif */
flex-direction: row;
justify-content: space-between;
}
.uni-datetime-picker-btn-text {
font-size: 14px;
color: #007AFF;
}
.uni-datetime-picker-btn-group {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-datetime-picker-cancel {
margin-right: 30px;
}
.uni-datetime-picker-mask {
position: fixed;
bottom: 0px;
top: 0px;
left: 0px;
right: 0px;
background-color: rgba(0, 0, 0, 0.4);
transition-duration: 0.3s;
z-index: 998;
}
.uni-datetime-picker-popup {
border-radius: 8px;
padding: 30px;
width: 270px;
/* #ifdef APP-NVUE */
height: 500px;
/* #endif */
/* #ifdef APP-NVUE */
width: 330px;
/* #endif */
background-color: #fff;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transition-duration: 0.3s;
z-index: 999;
}
.fix-nvue-height {
/* #ifdef APP-NVUE */
height: 330px;
/* #endif */
}
.uni-datetime-picker-time {
color: grey;
}
.uni-datetime-picker-column {
height: 50px;
}
.uni-datetime-picker-timebox {
border: 1px solid #E5E5E5;
border-radius: 5px;
padding: 7px 10px;
/* #ifndef APP-NVUE */
box-sizing: border-box;
cursor: pointer;
/* #endif */
}
.uni-datetime-picker-timebox-pointer {
/* #ifndef APP-NVUE */
cursor: pointer;
/* #endif */
}
.uni-datetime-picker-disabled {
opacity: 0.4;
/* #ifdef H5 */
cursor: not-allowed !important;
/* #endif */
}
.uni-datetime-picker-text {
font-size: 14px;
}
.uni-datetime-picker-sign {
position: absolute;
top: 53px;
/* 减掉 10px 的元素高度兼容nvue */
color: #999;
/* #ifdef APP-NVUE */
font-size: 16px;
/* #endif */
}
.sign-left {
left: 86px;
}
.sign-right {
right: 86px;
}
.sign-center {
left: 135px;
}
.uni-datetime-picker__container-box {
position: relative;
display: flex;
align-items: center;
justify-content: center;
margin-top: 40px;
}
.time-hide-second {
width: 180px;
}
</style>

View File

@ -0,0 +1,981 @@
<template>
<view class="uni-date">
<view class="uni-date-editor" @click="show">
<slot>
<view class="uni-date-editor--x" :class="{'uni-date-editor--x__disabled': disabled,
'uni-date-x--border': border}">
<view v-if="!isRange" class="uni-date-x uni-date-single">
<uni-icons type="calendar" color="#e1e1e1" size="22"></uni-icons>
<input class="uni-date__x-input" type="text" v-model="singleVal"
:placeholder="singlePlaceholderText" :disabled="true" />
</view>
<view v-else class="uni-date-x uni-date-range">
<uni-icons type="calendar" color="#e1e1e1" size="22"></uni-icons>
<input class="uni-date__x-input t-c" type="text" v-model="range.startDate"
:placeholder="startPlaceholderText" :disabled="true" />
<slot>
<view class="">{{rangeSeparator}}</view>
</slot>
<input class="uni-date__x-input t-c" type="text" v-model="range.endDate"
:placeholder="endPlaceholderText" :disabled="true" />
</view>
<view v-if="showClearIcon" class="uni-date__icon-clear" @click.stop="clear">
<uni-icons type="clear" color="#e1e1e1" size="18"></uni-icons>
</view>
</view>
</slot>
</view>
<view v-show="popup" class="uni-date-mask" @click="close"></view>
<view v-if="!isPhone" ref="datePicker" v-show="popup" class="uni-date-picker__container">
<view v-if="!isRange" class="uni-date-single--x" :style="popover">
<view class="uni-popper__arrow"></view>
<view v-if="hasTime" class="uni-date-changed popup-x-header">
<input class="uni-date__input t-c" type="text" v-model="tempSingleDate"
:placeholder="selectDateText" />
<time-picker type="time" v-model="time" :border="false" :disabled="!tempSingleDate"
:start="reactStartTime" :end="reactEndTime" :hideSecond="hideSecond" style="width: 100%;">
<input class="uni-date__input t-c" type="text" v-model="time" :placeholder="selectTimeText"
:disabled="!tempSingleDate" />
</time-picker>
</view>
<calendar ref="pcSingle" :showMonth="false"
:start-date="caleRange.startDate" :end-date="caleRange.endDate" :date="defSingleDate"
@change="singleChange" style="padding: 0 8px;" />
<view v-if="hasTime" class="popup-x-footer">
<!-- <text class="">此刻</text> -->
<text class="confirm" @click="confirmSingleChange">{{okText}}</text>
</view>
<view class="uni-date-popper__arrow"></view>
</view>
<view v-else class="uni-date-range--x" :style="popover">
<view class="uni-popper__arrow"></view>
<view v-if="hasTime" class="popup-x-header uni-date-changed">
<view class="popup-x-header--datetime">
<input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.startDate"
:placeholder="startDateText" />
<time-picker type="time" v-model="tempRange.startTime" :start="reactStartTime" :border="false"
:disabled="!tempRange.startDate" :hideSecond="hideSecond">
<input class="uni-date__input uni-date-range__input" type="text"
v-model="tempRange.startTime" :placeholder="startTimeText"
:disabled="!tempRange.startDate" />
</time-picker>
</view>
<uni-icons type="arrowthinright" color="#999" style="line-height: 40px;"></uni-icons>
<view class="popup-x-header--datetime">
<input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endDate"
:placeholder="endDateText" />
<time-picker type="time" v-model="tempRange.endTime" :end="reactEndTime" :border="false"
:disabled="!tempRange.endDate" :hideSecond="hideSecond">
<input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endTime"
:placeholder="endTimeText" :disabled="!tempRange.endDate" />
</time-picker>
</view>
</view>
<view class="popup-x-body">
<calendar ref="left" :showMonth="false"
:start-date="caleRange.startDate" :end-date="caleRange.endDate" :range="true"
@change="leftChange" :pleStatus="endMultipleStatus" @firstEnterCale="updateRightCale"
@monthSwitch="leftMonthSwitch" style="padding: 0 8px;" />
<calendar ref="right" :showMonth="false"
:start-date="caleRange.startDate" :end-date="caleRange.endDate" :range="true"
@change="rightChange" :pleStatus="startMultipleStatus" @firstEnterCale="updateLeftCale"
@monthSwitch="rightMonthSwitch" style="padding: 0 8px;border-left: 1px solid #F1F1F1;" />
</view>
<view v-if="hasTime" class="popup-x-footer">
<text class="" @click="clear">{{clearText}}</text>
<text class="confirm" @click="confirmRangeChange">{{okText}}</text>
</view>
</view>
</view>
<calendar v-show="isPhone" ref="mobile" :clearDate="false" :date="defSingleDate" :defTime="reactMobDefTime"
:start-date="caleRange.startDate" :end-date="caleRange.endDate" :selectableTimes="mobSelectableTime"
:pleStatus="endMultipleStatus" :showMonth="false" :range="isRange" :typeHasTime="hasTime" :insert="false"
:hideSecond="hideSecond" @confirm="mobileChange" />
</view>
</template>
<script>
/**
* DatetimePicker 时间选择器
* @description 同时支持 PC 和移动端使用日历选择日期和日期范围
* @tutorial https://ext.dcloud.net.cn/plugin?id=3962
* @property {String} type 选择器类型
* @property {String|Number|Array|Date} value 绑定值
* @property {String} placeholder 单选择时的占位内容
* @property {String} start 起始时间
* @property {String} end 终止时间
* @property {String} start-placeholder 范围选择时开始日期的占位内容
* @property {String} end-placeholder 范围选择时结束日期的占位内容
* @property {String} range-separator 选择范围时的分隔符
* @property {Boolean} border = [true|false] 是否有边框
* @property {Boolean} disabled = [true|false] 是否禁用
* @property {Boolean} clearIcon = [true|false] 是否显示清除按钮仅PC端适用
* @event {Function} change 确定日期时触发的事件
* @event {Function} show 打开弹出层
* @event {Function} close 关闭弹出层
* @event {Function} clear 清除上次选中的状态和值
**/
import calendar from './calendar.vue'
import timePicker from './time-picker.vue'
import {
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from './i18n/index.js'
const {
t
} = initVueI18n(messages)
export default {
name: 'UniDatetimePicker',
components: {
calendar,
timePicker
},
data() {
return {
isRange: false,
hasTime: false,
mobileRange: false,
//
singleVal: '',
tempSingleDate: '',
defSingleDate: '',
time: '',
//
caleRange: {
startDate: '',
startTime: '',
endDate: '',
endTime: ''
},
range: {
startDate: '',
// startTime: '',
endDate: '',
// endTime: ''
},
tempRange: {
startDate: '',
startTime: '',
endDate: '',
endTime: ''
},
//
startMultipleStatus: {
before: '',
after: '',
data: [],
fulldate: ''
},
endMultipleStatus: {
before: '',
after: '',
data: [],
fulldate: ''
},
visible: false,
popup: false,
popover: null,
isEmitValue: false,
isPhone: false,
isFirstShow: true,
}
},
props: {
type: {
type: String,
default: 'datetime'
},
value: {
type: [String, Number, Array, Date],
default: ''
},
modelValue: {
type: [String, Number, Array, Date],
default: ''
},
start: {
type: [Number, String],
default: ''
},
end: {
type: [Number, String],
default: ''
},
returnType: {
type: String,
default: 'string'
},
placeholder: {
type: String,
default: ''
},
startPlaceholder: {
type: String,
default: ''
},
endPlaceholder: {
type: String,
default: ''
},
rangeSeparator: {
type: String,
default: '-'
},
border: {
type: [Boolean],
default: true
},
disabled: {
type: [Boolean],
default: false
},
clearIcon: {
type: [Boolean],
default: true
},
hideSecond: {
type: [Boolean],
default: false
}
},
watch: {
type: {
immediate: true,
handler(newVal, oldVal) {
if (newVal.indexOf('time') !== -1) {
this.hasTime = true
} else {
this.hasTime = false
}
if (newVal.indexOf('range') !== -1) {
this.isRange = true
} else {
this.isRange = false
}
}
},
value: {
immediate: true,
handler(newVal, oldVal) {
if (this.isEmitValue) {
this.isEmitValue = false
return
}
this.initPicker(newVal)
}
},
start: {
immediate: true,
handler(newVal, oldVal) {
if (!newVal) return
const {
defDate,
defTime
} = this.parseDate(newVal)
this.caleRange.startDate = defDate
if (this.hasTime) {
this.caleRange.startTime = defTime
}
}
},
end: {
immediate: true,
handler(newVal, oldVal) {
if (!newVal) return
const {
defDate,
defTime
} = this.parseDate(newVal)
this.caleRange.endDate = defDate
if (this.hasTime) {
this.caleRange.endTime = defTime
}
}
},
},
computed: {
reactStartTime() {
const activeDate = this.isRange ? this.tempRange.startDate : this.tempSingleDate
const res = activeDate === this.caleRange.startDate ? this.caleRange.startTime : ''
return res
},
reactEndTime() {
const activeDate = this.isRange ? this.tempRange.endDate : this.tempSingleDate
const res = activeDate === this.caleRange.endDate ? this.caleRange.endTime : ''
return res
},
reactMobDefTime() {
const times = {
start: this.tempRange.startTime,
end: this.tempRange.endTime
}
return this.isRange ? times : this.time
},
mobSelectableTime() {
return {
start: this.caleRange.startTime,
end: this.caleRange.endTime
}
},
datePopupWidth() {
// todo
return this.isRange ? 653 : 301
},
/**
* for i18n
*/
singlePlaceholderText() {
return this.placeholder || (this.type === 'date' ? this.selectDateText : t(
"uni-datetime-picker.selectDateTime"))
},
startPlaceholderText() {
return this.startPlaceholder || this.startDateText
},
endPlaceholderText() {
return this.endPlaceholder || this.endDateText
},
selectDateText() {
return t("uni-datetime-picker.selectDate")
},
selectTimeText() {
return t("uni-datetime-picker.selectTime")
},
startDateText() {
return this.startPlaceholder || t("uni-datetime-picker.startDate")
},
startTimeText() {
return t("uni-datetime-picker.startTime")
},
endDateText() {
return this.endPlaceholder || t("uni-datetime-picker.endDate")
},
endTimeText() {
return t("uni-datetime-picker.endTime")
},
okText() {
return t("uni-datetime-picker.ok")
},
clearText() {
return t("uni-datetime-picker.clear")
},
showClearIcon() {
const { clearIcon, disabled, singleVal, range } = this
const bool = clearIcon && !disabled && (singleVal || (range.startDate && range.endDate))
return bool
}
},
created() {
this.form = this.getForm('uniForms')
this.formItem = this.getForm('uniFormsItem')
// if (this.formItem) {
// if (this.formItem.name) {
// this.rename = this.formItem.name
// this.form.inputChildrens.push(this)
// }
// }
},
mounted() {
this.platform()
},
methods: {
/**
* 获取父元素实例
*/
getForm(name = 'uniForms') {
let parent = this.$parent;
let parentName = parent.$options.name;
while (parentName !== name) {
parent = parent.$parent;
if (!parent) return false
parentName = parent.$options.name;
}
return parent;
},
initPicker(newVal) {
if (!newVal || Array.isArray(newVal) && !newVal.length) {
this.$nextTick(() => {
this.clear(false)
})
return
}
if (!Array.isArray(newVal) && !this.isRange) {
const {
defDate,
defTime
} = this.parseDate(newVal)
this.singleVal = defDate
this.tempSingleDate = defDate
this.defSingleDate = defDate
if (this.hasTime) {
this.singleVal = defDate + ' ' + defTime
this.time = defTime
}
} else {
const [before, after] = newVal
if (!before && !after) return
const defBefore = this.parseDate(before)
const defAfter = this.parseDate(after)
const startDate = defBefore.defDate
const endDate = defAfter.defDate
this.range.startDate = this.tempRange.startDate = startDate
this.range.endDate = this.tempRange.endDate = endDate
if (this.hasTime) {
this.range.startDate = defBefore.defDate + ' ' + defBefore.defTime
this.range.endDate = defAfter.defDate + ' ' + defAfter.defTime
this.tempRange.startTime = defBefore.defTime
this.tempRange.endTime = defAfter.defTime
}
const defaultRange = {
before: defBefore.defDate,
after: defAfter.defDate
}
this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, defaultRange, {
which: 'right'
})
this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, defaultRange, {
which: 'left'
})
}
},
updateLeftCale(e) {
const left = this.$refs.left
//
left.cale.setHoverMultiple(e.after)
left.setDate(this.$refs.left.nowDate.fullDate)
},
updateRightCale(e) {
const right = this.$refs.right
//
right.cale.setHoverMultiple(e.after)
right.setDate(this.$refs.right.nowDate.fullDate)
},
platform() {
const systemInfo = uni.getSystemInfoSync()
this.isPhone = systemInfo.windowWidth <= 500
this.windowWidth = systemInfo.windowWidth
},
show(event) {
if (this.disabled) {
return
}
this.platform()
if (this.isPhone) {
this.$refs.mobile.open()
return
}
this.popover = {
top: '10px'
}
const dateEditor = uni.createSelectorQuery().in(this).select(".uni-date-editor")
dateEditor.boundingClientRect(rect => {
if (this.windowWidth - rect.left < this.datePopupWidth) {
this.popover.right = 0
}
}).exec()
setTimeout(() => {
this.popup = !this.popup
if (!this.isPhone && this.isRange && this.isFirstShow) {
this.isFirstShow = false
const {
startDate,
endDate
} = this.range
if (startDate && endDate) {
if (this.diffDate(startDate, endDate) < 30) {
this.$refs.right.next()
}
} else {
this.$refs.right.next()
this.$refs.right.cale.lastHover = false
}
}
}, 50)
},
close() {
setTimeout(() => {
this.popup = false
this.$emit('maskClick', this.value)
}, 20)
},
setEmit(value) {
if (this.returnType === "timestamp" || this.returnType === "date") {
if (!Array.isArray(value)) {
if (!this.hasTime) {
value = value + ' ' + '00:00:00'
}
value = this.createTimestamp(value)
if (this.returnType === "date") {
value = new Date(value)
}
} else {
if (!this.hasTime) {
value[0] = value[0] + ' ' + '00:00:00'
value[1] = value[1] + ' ' + '00:00:00'
}
value[0] = this.createTimestamp(value[0])
value[1] = this.createTimestamp(value[1])
if (this.returnType === "date") {
value[0] = new Date(value[0])
value[1] = new Date(value[1])
}
}
}
this.formItem && this.formItem.setValue(value)
this.$emit('change', value)
this.$emit('input', value)
this.$emit('update:modelValue', value)
this.isEmitValue = true
},
createTimestamp(date) {
date = this.fixIosDateFormat(date)
return Date.parse(new Date(date))
},
singleChange(e) {
this.tempSingleDate = e.fulldate
if (this.hasTime) return
this.confirmSingleChange()
},
confirmSingleChange() {
if (!this.tempSingleDate) {
this.popup = false
return
}
if (this.hasTime) {
this.singleVal = this.tempSingleDate + ' ' + (this.time ? this.time : '00:00:00')
} else {
this.singleVal = this.tempSingleDate
}
this.setEmit(this.singleVal)
this.popup = false
},
leftChange(e) {
const {
before,
after
} = e.range
this.rangeChange(before, after)
const obj = {
before: e.range.before,
after: e.range.after,
data: e.range.data,
fulldate: e.fulldate
}
this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, obj)
},
rightChange(e) {
const {
before,
after
} = e.range
this.rangeChange(before, after)
const obj = {
before: e.range.before,
after: e.range.after,
data: e.range.data,
fulldate: e.fulldate
}
this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, obj)
},
mobileChange(e) {
if (this.isRange) {
const {
before,
after
} = e.range
this.handleStartAndEnd(before, after, true)
if (this.hasTime) {
const {
startTime,
endTime
} = e.timeRange
this.tempRange.startTime = startTime
this.tempRange.endTime = endTime
}
this.confirmRangeChange()
} else {
if (this.hasTime) {
this.singleVal = e.fulldate + ' ' + e.time
} else {
this.singleVal = e.fulldate
}
this.setEmit(this.singleVal)
}
this.$refs.mobile.close()
},
rangeChange(before, after) {
if (!(before && after)) return
this.handleStartAndEnd(before, after, true)
if (this.hasTime) return
this.confirmRangeChange()
},
confirmRangeChange() {
if (!this.tempRange.startDate && !this.tempRange.endDate) {
this.popup = false
return
}
let start, end
if (!this.hasTime) {
start = this.range.startDate = this.tempRange.startDate
end = this.range.endDate = this.tempRange.endDate
} else {
start = this.range.startDate = this.tempRange.startDate + ' ' +
(this.tempRange.startTime ? this.tempRange.startTime : '00:00:00')
end = this.range.endDate = this.tempRange.endDate + ' ' +
(this.tempRange.endTime ? this.tempRange.endTime : '00:00:00')
}
const displayRange = [start, end]
this.setEmit(displayRange)
this.popup = false
},
handleStartAndEnd(before, after, temp = false) {
if (!(before && after)) return
const type = temp ? 'tempRange' : 'range'
if (this.dateCompare(before, after)) {
this[type].startDate = before
this[type].endDate = after
} else {
this[type].startDate = after
this[type].endDate = before
}
},
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
//
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
//
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
if (startDate <= endDate) {
return true
} else {
return false
}
},
/**
* 比较时间差
*/
diffDate(startDate, endDate) {
//
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
//
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
const diff = (endDate - startDate) / (24 * 60 * 60 * 1000)
return Math.abs(diff)
},
clear(needEmit = true) {
if (!this.isRange) {
this.singleVal = ''
this.tempSingleDate = ''
this.time = ''
if (this.isPhone) {
this.$refs.mobile && this.$refs.mobile.clearCalender()
} else {
this.$refs.pcSingle && this.$refs.pcSingle.clearCalender()
}
if (needEmit) {
this.formItem && this.formItem.setValue('')
this.$emit('change', '')
this.$emit('input', '')
this.$emit('update:modelValue', '')
}
} else {
this.range.startDate = ''
this.range.endDate = ''
this.tempRange.startDate = ''
this.tempRange.startTime = ''
this.tempRange.endDate = ''
this.tempRange.endTime = ''
if (this.isPhone) {
this.$refs.mobile && this.$refs.mobile.clearCalender()
} else {
this.$refs.left && this.$refs.left.clearCalender()
this.$refs.right && this.$refs.right.clearCalender()
this.$refs.right && this.$refs.right.next()
}
if (needEmit) {
this.formItem && this.formItem.setValue([])
this.$emit('change', [])
this.$emit('input', [])
this.$emit('update:modelValue', [])
}
}
},
parseDate(date) {
date = this.fixIosDateFormat(date)
const defVal = new Date(date)
const year = defVal.getFullYear()
const month = defVal.getMonth() + 1
const day = defVal.getDate()
const hour = defVal.getHours()
const minute = defVal.getMinutes()
const second = defVal.getSeconds()
const defDate = year + '-' + this.lessTen(month) + '-' + this.lessTen(day)
const defTime = this.lessTen(hour) + ':' + this.lessTen(minute) + (this.hideSecond ? '' : (':' + this
.lessTen(second)))
return {
defDate,
defTime
}
},
lessTen(item) {
return item < 10 ? '0' + item : item
},
// iOSsafari
fixIosDateFormat(value) {
if (typeof value === 'string') {
value = value.replace(/-/g, '/')
}
return value
},
leftMonthSwitch(e) {
// console.log('leftMonthSwitch :', e)
},
rightMonthSwitch(e) {
// console.log('rightMonthSwitch :', e)
}
}
}
</script>
<style>
.uni-date-x {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 10px;
border-radius: 4px;
background-color: #fff;
color: #666;
font-size: 14px;
}
.uni-date-x--border {
box-sizing: border-box;
border-radius: 4px;
border: 1px solid #dcdfe6;
}
.uni-date-editor--x {
position: relative;
}
.uni-date-editor--x .uni-date__icon-clear {
position: absolute;
top: 0;
right: 0;
display: inline-block;
box-sizing: border-box;
border: 9px solid transparent;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-date__x-input {
padding: 0 8px;
height: 40px;
width: 100%;
line-height: 40px;
font-size: 14px;
}
.t-c {
text-align: center;
}
.uni-date__input {
height: 40px;
width: 100%;
line-height: 40px;
font-size: 14px;
}
.uni-date-range__input {
text-align: center;
max-width: 142px;
}
.uni-date-picker__container {
position: relative;
/* position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
box-sizing: border-box;
z-index: 996;
font-size: 14px; */
}
.uni-date-mask {
position: fixed;
bottom: 0px;
top: 0px;
left: 0px;
right: 0px;
background-color: rgba(0, 0, 0, 0);
transition-duration: 0.3s;
z-index: 996;
}
.uni-date-single--x {
/* padding: 0 8px; */
background-color: #fff;
position: absolute;
top: 0;
z-index: 999;
border: 1px solid #EBEEF5;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 4px;
}
.uni-date-range--x {
/* padding: 0 8px; */
background-color: #fff;
position: absolute;
top: 0;
z-index: 999;
border: 1px solid #EBEEF5;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 4px;
}
.uni-date-editor--x__disabled {
opacity: 0.4;
cursor: default;
}
.uni-date-editor--logo {
width: 16px;
height: 16px;
vertical-align: middle;
}
/* 添加时间 */
.popup-x-header {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
/* justify-content: space-between; */
}
.popup-x-header--datetime {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
flex: 1;
}
.popup-x-body {
display: flex;
}
.popup-x-footer {
padding: 0 15px;
border-top-color: #F1F1F1;
border-top-style: solid;
border-top-width: 1px;
/* background-color: #fff; */
line-height: 40px;
text-align: right;
color: #666;
}
.popup-x-footer text:hover {
color: #007aff;
cursor: pointer;
opacity: 0.8;
}
.popup-x-footer .confirm {
margin-left: 20px;
color: #007aff;
}
.uni-date-changed {
/* background-color: #fff; */
text-align: center;
color: #333;
border-bottom-color: #F1F1F1;
border-bottom-style: solid;
border-bottom-width: 1px;
/* padding: 0 50px; */
}
.uni-date-changed--time text {
/* padding: 0 20px; */
height: 50px;
line-height: 50px;
}
.uni-date-changed .uni-date-changed--time {
/* display: flex; */
flex: 1;
}
.uni-date-changed--time-date {
color: #333;
opacity: 0.6;
}
.mr-50 {
margin-right: 50px;
}
/* picker 弹出层通用的指示小三角, todo扩展至上下左右方向定位 */
.uni-popper__arrow,
.uni-popper__arrow::after {
position: absolute;
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 6px;
}
.uni-popper__arrow {
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
top: -6px;
left: 10%;
margin-right: 3px;
border-top-width: 0;
border-bottom-color: #EBEEF5;
}
.uni-popper__arrow::after {
content: " ";
top: 1px;
margin-left: -6px;
border-top-width: 0;
border-bottom-color: #fff;
}
</style>

View File

@ -0,0 +1,410 @@
class Calendar {
constructor({
date,
selected,
startDate,
endDate,
range,
// multipleStatus
} = {}) {
// 当前日期
this.date = this.getDate(new Date()) // 当前初入日期
// 打点信息
this.selected = selected || [];
// 范围开始
this.startDate = startDate
// 范围结束
this.endDate = endDate
this.range = range
// 多选状态
this.cleanMultipleStatus()
// 每周日期
this.weeks = {}
// this._getWeek(this.date.fullDate)
// this.multipleStatus = multipleStatus
this.lastHover = false
}
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.selectDate = this.getDate(date)
this._getWeek(this.selectDate.fullDate)
}
/**
* 清理多选状态
*/
cleanMultipleStatus() {
this.multipleStatus = {
before: '',
after: '',
data: []
}
}
/**
* 重置开始日期
*/
resetSatrtDate(startDate) {
// 范围开始
this.startDate = startDate
}
/**
* 重置结束日期
*/
resetEndDate(endDate) {
// 范围结束
this.endDate = endDate
}
/**
* 获取任意时间
*/
getDate(date, AddDayCount = 0, str = 'day') {
if (!date) {
date = new Date()
}
if (typeof date !== 'object') {
date = date.replace(/-/g, '/')
}
const dd = new Date(date)
switch (str) {
case 'day':
dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
break
case 'month':
if (dd.getDate() === 31) {
dd.setDate(dd.getDate() + AddDayCount)
} else {
dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
}
break
case 'year':
dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
break
}
const y = dd.getFullYear()
const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期不足10补0
const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号不足10补0
return {
fullDate: y + '-' + m + '-' + d,
year: y,
month: m,
date: d,
day: dd.getDay()
}
}
/**
* 获取上月剩余天数
*/
_getLastMonthDays(firstDay, full) {
let dateArr = []
for (let i = firstDay; i > 0; i--) {
const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
dateArr.push({
date: beforeDate,
month: full.month - 1,
disable: true
})
}
return dateArr
}
/**
* 获取本月天数
*/
_currentMonthDys(dateData, full) {
let dateArr = []
let fullDate = this.date.fullDate
for (let i = 1; i <= dateData; i++) {
let isinfo = false
let nowDate = full.year + '-' + (full.month < 10 ?
full.month : full.month) + '-' + (i < 10 ?
'0' + i : i)
// 是否今天
let isDay = fullDate === nowDate
// 获取打点信息
let info = this.selected && this.selected.find((item) => {
if (this.dateEqual(nowDate, item.date)) {
return item
}
})
// 日期禁用
let disableBefore = true
let disableAfter = true
if (this.startDate) {
// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
disableBefore = this.dateCompare(this.startDate, nowDate)
}
if (this.endDate) {
// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
disableAfter = this.dateCompare(nowDate, this.endDate)
}
let multiples = this.multipleStatus.data
let checked = false
let multiplesStatus = -1
if (this.range) {
if (multiples) {
multiplesStatus = multiples.findIndex((item) => {
return this.dateEqual(item, nowDate)
})
}
if (multiplesStatus !== -1) {
checked = true
}
}
let data = {
fullDate: nowDate,
year: full.year,
date: i,
multiple: this.range ? checked : false,
beforeMultiple: this.isLogicBefore(nowDate, this.multipleStatus.before, this.multipleStatus.after),
afterMultiple: this.isLogicAfter(nowDate, this.multipleStatus.before, this.multipleStatus.after),
month: full.month,
disable: !(disableBefore && disableAfter),
isDay,
userChecked: false
}
if (info) {
data.extraInfo = info
}
dateArr.push(data)
}
return dateArr
}
/**
* 获取下月天数
*/
_getNextMonthDays(surplus, full) {
let dateArr = []
for (let i = 1; i < surplus + 1; i++) {
dateArr.push({
date: i,
month: Number(full.month) + 1,
disable: true
})
}
return dateArr
}
/**
* 获取当前日期详情
* @param {Object} date
*/
getInfo(date) {
if (!date) {
date = new Date()
}
const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
return dateInfo
}
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
// 计算截止时间
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
if (startDate <= endDate) {
return true
} else {
return false
}
}
/**
* 比较时间是否相等
*/
dateEqual(before, after) {
// 计算截止时间
before = new Date(before.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
after = new Date(after.replace('-', '/').replace('-', '/'))
if (before.getTime() - after.getTime() === 0) {
return true
} else {
return false
}
}
/**
* 比较真实起始日期
*/
isLogicBefore(currentDay, before, after) {
let logicBefore = before
if (before && after) {
logicBefore = this.dateCompare(before, after) ? before : after
}
return this.dateEqual(logicBefore, currentDay)
}
isLogicAfter(currentDay, before, after) {
let logicAfter = after
if (before && after) {
logicAfter = this.dateCompare(before, after) ? after : before
}
return this.dateEqual(logicAfter, currentDay)
}
/**
* 获取日期范围内所有日期
* @param {Object} begin
* @param {Object} end
*/
geDateAll(begin, end) {
var arr = []
var ab = begin.split('-')
var ae = end.split('-')
var db = new Date()
db.setFullYear(ab[0], ab[1] - 1, ab[2])
var de = new Date()
de.setFullYear(ae[0], ae[1] - 1, ae[2])
var unixDb = db.getTime() - 24 * 60 * 60 * 1000
var unixDe = de.getTime() - 24 * 60 * 60 * 1000
for (var k = unixDb; k <= unixDe;) {
k = k + 24 * 60 * 60 * 1000
arr.push(this.getDate(new Date(parseInt(k))).fullDate)
}
return arr
}
/**
* 获取多选状态
*/
setMultiple(fullDate) {
let {
before,
after
} = this.multipleStatus
if (!this.range) return
if (before && after) {
if (!this.lastHover) {
this.lastHover = true
return
}
this.multipleStatus.before = fullDate
this.multipleStatus.after = ''
this.multipleStatus.data = []
this.multipleStatus.fulldate = ''
this.lastHover = false
} else {
if (!before) {
this.multipleStatus.before = fullDate
this.lastHover = false
} else {
this.multipleStatus.after = fullDate
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
.after);
} else {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
.before);
}
this.lastHover = true
}
}
this._getWeek(fullDate)
}
/**
* 鼠标 hover 更新多选状态
*/
setHoverMultiple(fullDate) {
let {
before,
after
} = this.multipleStatus
if (!this.range) return
if (this.lastHover) return
if (!before) {
this.multipleStatus.before = fullDate
} else {
this.multipleStatus.after = fullDate
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
} else {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
}
}
this._getWeek(fullDate)
}
/**
* 更新默认值多选状态
*/
setDefaultMultiple(before, after) {
this.multipleStatus.before = before
this.multipleStatus.after = after
if (before && after) {
if (this.dateCompare(before, after)) {
this.multipleStatus.data = this.geDateAll(before, after);
this._getWeek(after)
} else {
this.multipleStatus.data = this.geDateAll(after, before);
this._getWeek(before)
}
}
}
/**
* 获取每周数据
* @param {Object} dateData
*/
_getWeek(dateData) {
const {
fullDate,
year,
month,
date,
day
} = this.getDate(dateData)
let firstDay = new Date(year, month - 1, 1).getDay()
let currentDay = new Date(year, month, 0).getDate()
let dates = {
lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
nextMonthDays: [], // 下个月开始几天
weeks: []
}
let canlender = []
const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
let weeks = {}
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
for (let i = 0; i < canlender.length; i++) {
if (i % 7 === 0) {
weeks[parseInt(i / 7)] = new Array(7)
}
weeks[parseInt(i / 7)][i % 7] = canlender[i]
}
this.canlender = canlender
this.weeks = weeks
}
//静态方法
// static init(date) {
// if (!this.instance) {
// this.instance = new Calendar(date);
// }
// return this.instance;
// }
}
export default Calendar

View File

@ -0,0 +1,90 @@
{
"id": "uni-datetime-picker",
"displayName": "uni-datetime-picker 日期选择器",
"version": "2.2.2",
"description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择",
"keywords": [
"uni-datetime-picker",
"uni-ui",
"uniui",
"日期时间选择器",
"日期时间"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [
"uni-scss",
"uni-icons"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@ -0,0 +1,21 @@
> `重要通知:组件升级更新 2.0.0 后,支持日期+时间范围选择,组件 ui 将使用日历选择日期ui 变化较大,同时支持 PC 和 移动端。此版本不向后兼容不再支持单独的时间选择type=time及相关的 hide-second 属性(时间选可使用内置组件 picker。若仍需使用旧版本可在插件市场下载*非uni_modules版本*,旧版本将不再维护`
## DatetimePicker 时间选择器
> **组件名uni-datetime-picker**
> 代码块: `uDatetimePicker`
该组件的优势是,支持**时间戳**输入和输出(起始时间、终止时间也支持时间戳),可**同时选择**日期和时间。
若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。
**_点击 picker 默认值规则_**
- 若设置初始值 value, 会显示在 picker 显示框中
- 若无初始值 value则初始值 value 为当前本地时间 Date.now() 但不会显示在 picker 显示框中
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@ -0,0 +1,22 @@
## 1.3.52022-01-24
- 优化 size 属性可以传入不带单位的字符串数值
## 1.3.42022-01-24
- 优化 size 支持其他单位
## 1.3.32022-01-17
- 修复 nvue 有些图标不显示的bug兼容老版本图标
## 1.3.22021-12-01
- 优化 示例可复制图标名称
## 1.3.12021-11-23
- 优化 兼容旧组件 type 值
## 1.3.02021-11-19
- 新增 更多图标
- 优化 自定义图标使用方式
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons)
## 1.1.72021-11-08
## 1.2.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.1.52021-05-12
- 新增 组件示例地址
## 1.1.42021-02-05
- 调整为uni_modules目录规范

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,96 @@
<template>
<!-- #ifdef APP-NVUE -->
<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" @click="_onClick">{{unicode}}</text>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick"></text>
<!-- #endif -->
</template>
<script>
import icons from './icons.js';
const getVal = (val) => {
const reg = /^[0-9]*$/g
return (typeof val === 'number' || reg.test(val) )? val + 'px' : val;
}
// #ifdef APP-NVUE
var domModule = weex.requireModule('dom');
import iconUrl from './uniicons.ttf'
domModule.addRule('fontFace', {
'fontFamily': "uniicons",
'src': "url('"+iconUrl+"')"
});
// #endif
/**
* Icons 图标
* @description 用于展示 icons 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number} size 图标大小
* @property {String} type 图标图案参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export default {
name: 'UniIcons',
emits:['click'],
props: {
type: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 16
},
customPrefix:{
type: String,
default: ''
}
},
data() {
return {
icons: icons.glyphs
}
},
computed:{
unicode(){
let code = this.icons.find(v=>v.font_class === this.type)
if(code){
return unescape(`%u${code.unicode}`)
}
return ''
},
iconSize(){
return getVal(this.size)
}
},
methods: {
_onClick() {
this.$emit('click')
}
}
}
</script>
<style lang="scss">
/* #ifndef APP-NVUE */
@import './uniicons.css';
@font-face {
font-family: uniicons;
src: url('./uniicons.ttf') format('truetype');
}
/* #endif */
.uni-icons {
font-family: uniicons;
text-decoration: none;
text-align: center;
}
</style>

View File

@ -0,0 +1,663 @@
.uniui-color:before {
content: "\e6cf";
}
.uniui-wallet:before {
content: "\e6b1";
}
.uniui-settings-filled:before {
content: "\e6ce";
}
.uniui-auth-filled:before {
content: "\e6cc";
}
.uniui-shop-filled:before {
content: "\e6cd";
}
.uniui-staff-filled:before {
content: "\e6cb";
}
.uniui-vip-filled:before {
content: "\e6c6";
}
.uniui-plus-filled:before {
content: "\e6c7";
}
.uniui-folder-add-filled:before {
content: "\e6c8";
}
.uniui-color-filled:before {
content: "\e6c9";
}
.uniui-tune-filled:before {
content: "\e6ca";
}
.uniui-calendar-filled:before {
content: "\e6c0";
}
.uniui-notification-filled:before {
content: "\e6c1";
}
.uniui-wallet-filled:before {
content: "\e6c2";
}
.uniui-medal-filled:before {
content: "\e6c3";
}
.uniui-gift-filled:before {
content: "\e6c4";
}
.uniui-fire-filled:before {
content: "\e6c5";
}
.uniui-refreshempty:before {
content: "\e6bf";
}
.uniui-location-filled:before {
content: "\e6af";
}
.uniui-person-filled:before {
content: "\e69d";
}
.uniui-personadd-filled:before {
content: "\e698";
}
.uniui-back:before {
content: "\e6b9";
}
.uniui-forward:before {
content: "\e6ba";
}
.uniui-arrow-right:before {
content: "\e6bb";
}
.uniui-arrowthinright:before {
content: "\e6bb";
}
.uniui-arrow-left:before {
content: "\e6bc";
}
.uniui-arrowthinleft:before {
content: "\e6bc";
}
.uniui-arrow-up:before {
content: "\e6bd";
}
.uniui-arrowthinup:before {
content: "\e6bd";
}
.uniui-arrow-down:before {
content: "\e6be";
}
.uniui-arrowthindown:before {
content: "\e6be";
}
.uniui-bottom:before {
content: "\e6b8";
}
.uniui-arrowdown:before {
content: "\e6b8";
}
.uniui-right:before {
content: "\e6b5";
}
.uniui-arrowright:before {
content: "\e6b5";
}
.uniui-top:before {
content: "\e6b6";
}
.uniui-arrowup:before {
content: "\e6b6";
}
.uniui-left:before {
content: "\e6b7";
}
.uniui-arrowleft:before {
content: "\e6b7";
}
.uniui-eye:before {
content: "\e651";
}
.uniui-eye-filled:before {
content: "\e66a";
}
.uniui-eye-slash:before {
content: "\e6b3";
}
.uniui-eye-slash-filled:before {
content: "\e6b4";
}
.uniui-info-filled:before {
content: "\e649";
}
.uniui-reload:before {
content: "\e6b2";
}
.uniui-micoff-filled:before {
content: "\e6b0";
}
.uniui-map-pin-ellipse:before {
content: "\e6ac";
}
.uniui-map-pin:before {
content: "\e6ad";
}
.uniui-location:before {
content: "\e6ae";
}
.uniui-starhalf:before {
content: "\e683";
}
.uniui-star:before {
content: "\e688";
}
.uniui-star-filled:before {
content: "\e68f";
}
.uniui-calendar:before {
content: "\e6a0";
}
.uniui-fire:before {
content: "\e6a1";
}
.uniui-medal:before {
content: "\e6a2";
}
.uniui-font:before {
content: "\e6a3";
}
.uniui-gift:before {
content: "\e6a4";
}
.uniui-link:before {
content: "\e6a5";
}
.uniui-notification:before {
content: "\e6a6";
}
.uniui-staff:before {
content: "\e6a7";
}
.uniui-vip:before {
content: "\e6a8";
}
.uniui-folder-add:before {
content: "\e6a9";
}
.uniui-tune:before {
content: "\e6aa";
}
.uniui-auth:before {
content: "\e6ab";
}
.uniui-person:before {
content: "\e699";
}
.uniui-email-filled:before {
content: "\e69a";
}
.uniui-phone-filled:before {
content: "\e69b";
}
.uniui-phone:before {
content: "\e69c";
}
.uniui-email:before {
content: "\e69e";
}
.uniui-personadd:before {
content: "\e69f";
}
.uniui-chatboxes-filled:before {
content: "\e692";
}
.uniui-contact:before {
content: "\e693";
}
.uniui-chatbubble-filled:before {
content: "\e694";
}
.uniui-contact-filled:before {
content: "\e695";
}
.uniui-chatboxes:before {
content: "\e696";
}
.uniui-chatbubble:before {
content: "\e697";
}
.uniui-upload-filled:before {
content: "\e68e";
}
.uniui-upload:before {
content: "\e690";
}
.uniui-weixin:before {
content: "\e691";
}
.uniui-compose:before {
content: "\e67f";
}
.uniui-qq:before {
content: "\e680";
}
.uniui-download-filled:before {
content: "\e681";
}
.uniui-pyq:before {
content: "\e682";
}
.uniui-sound:before {
content: "\e684";
}
.uniui-trash-filled:before {
content: "\e685";
}
.uniui-sound-filled:before {
content: "\e686";
}
.uniui-trash:before {
content: "\e687";
}
.uniui-videocam-filled:before {
content: "\e689";
}
.uniui-spinner-cycle:before {
content: "\e68a";
}
.uniui-weibo:before {
content: "\e68b";
}
.uniui-videocam:before {
content: "\e68c";
}
.uniui-download:before {
content: "\e68d";
}
.uniui-help:before {
content: "\e679";
}
.uniui-navigate-filled:before {
content: "\e67a";
}
.uniui-plusempty:before {
content: "\e67b";
}
.uniui-smallcircle:before {
content: "\e67c";
}
.uniui-minus-filled:before {
content: "\e67d";
}
.uniui-micoff:before {
content: "\e67e";
}
.uniui-closeempty:before {
content: "\e66c";
}
.uniui-clear:before {
content: "\e66d";
}
.uniui-navigate:before {
content: "\e66e";
}
.uniui-minus:before {
content: "\e66f";
}
.uniui-image:before {
content: "\e670";
}
.uniui-mic:before {
content: "\e671";
}
.uniui-paperplane:before {
content: "\e672";
}
.uniui-close:before {
content: "\e673";
}
.uniui-help-filled:before {
content: "\e674";
}
.uniui-paperplane-filled:before {
content: "\e675";
}
.uniui-plus:before {
content: "\e676";
}
.uniui-mic-filled:before {
content: "\e677";
}
.uniui-image-filled:before {
content: "\e678";
}
.uniui-locked-filled:before {
content: "\e668";
}
.uniui-info:before {
content: "\e669";
}
.uniui-locked:before {
content: "\e66b";
}
.uniui-camera-filled:before {
content: "\e658";
}
.uniui-chat-filled:before {
content: "\e659";
}
.uniui-camera:before {
content: "\e65a";
}
.uniui-circle:before {
content: "\e65b";
}
.uniui-checkmarkempty:before {
content: "\e65c";
}
.uniui-chat:before {
content: "\e65d";
}
.uniui-circle-filled:before {
content: "\e65e";
}
.uniui-flag:before {
content: "\e65f";
}
.uniui-flag-filled:before {
content: "\e660";
}
.uniui-gear-filled:before {
content: "\e661";
}
.uniui-home:before {
content: "\e662";
}
.uniui-home-filled:before {
content: "\e663";
}
.uniui-gear:before {
content: "\e664";
}
.uniui-smallcircle-filled:before {
content: "\e665";
}
.uniui-map-filled:before {
content: "\e666";
}
.uniui-map:before {
content: "\e667";
}
.uniui-refresh-filled:before {
content: "\e656";
}
.uniui-refresh:before {
content: "\e657";
}
.uniui-cloud-upload:before {
content: "\e645";
}
.uniui-cloud-download-filled:before {
content: "\e646";
}
.uniui-cloud-download:before {
content: "\e647";
}
.uniui-cloud-upload-filled:before {
content: "\e648";
}
.uniui-redo:before {
content: "\e64a";
}
.uniui-images-filled:before {
content: "\e64b";
}
.uniui-undo-filled:before {
content: "\e64c";
}
.uniui-more:before {
content: "\e64d";
}
.uniui-more-filled:before {
content: "\e64e";
}
.uniui-undo:before {
content: "\e64f";
}
.uniui-images:before {
content: "\e650";
}
.uniui-paperclip:before {
content: "\e652";
}
.uniui-settings:before {
content: "\e653";
}
.uniui-search:before {
content: "\e654";
}
.uniui-redo-filled:before {
content: "\e655";
}
.uniui-list:before {
content: "\e644";
}
.uniui-mail-open-filled:before {
content: "\e63a";
}
.uniui-hand-down-filled:before {
content: "\e63c";
}
.uniui-hand-down:before {
content: "\e63d";
}
.uniui-hand-up-filled:before {
content: "\e63e";
}
.uniui-hand-up:before {
content: "\e63f";
}
.uniui-heart-filled:before {
content: "\e641";
}
.uniui-mail-open:before {
content: "\e643";
}
.uniui-heart:before {
content: "\e639";
}
.uniui-loop:before {
content: "\e633";
}
.uniui-pulldown:before {
content: "\e632";
}
.uniui-scan:before {
content: "\e62a";
}
.uniui-bars:before {
content: "\e627";
}
.uniui-cart-filled:before {
content: "\e629";
}
.uniui-checkbox:before {
content: "\e62b";
}
.uniui-checkbox-filled:before {
content: "\e62c";
}
.uniui-shop:before {
content: "\e62f";
}
.uniui-headphones:before {
content: "\e630";
}
.uniui-cart:before {
content: "\e631";
}

View File

@ -0,0 +1,86 @@
{
"id": "uni-icons",
"displayName": "uni-icons 图标",
"version": "1.3.5",
"description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
"keywords": [
"uni-ui",
"uniui",
"icon",
"图标"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.2.14"
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": ["uni-scss"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@ -0,0 +1,8 @@
## Icons 图标
> **组件名uni-icons**
> 代码块: `uIcons`
用于展示 icons 图标 。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@ -0,0 +1,8 @@
## 1.0.32022-01-21
- 优化 组件示例
## 1.0.22021-11-22
- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题
## 1.0.12021-11-22
- 修复 vue3中scss语法兼容问题
## 1.0.02021-11-18
- init

View File

@ -0,0 +1 @@
@import './styles/index.scss';

View File

@ -0,0 +1,82 @@
{
"id": "uni-scss",
"displayName": "uni-scss 辅助样式",
"version": "1.0.3",
"description": "uni-sass是uni-ui提供的一套全局样式 通过一些简单的类名和sass变量实现简单的页面布局操作比如颜色、边距、圆角等。",
"keywords": [
"uni-scss",
"uni-ui",
"辅助样式"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"JS SDK",
"通用 SDK"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "n",
"联盟": "n"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@ -0,0 +1,4 @@
`uni-sass``uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@ -0,0 +1,7 @@
@import './setting/_variables.scss';
@import './setting/_border.scss';
@import './setting/_color.scss';
@import './setting/_space.scss';
@import './setting/_radius.scss';
@import './setting/_text.scss';
@import './setting/_styles.scss';

View File

@ -0,0 +1,3 @@
.uni-border {
border: 1px $uni-border-1 solid;
}

View File

@ -0,0 +1,66 @@
// TODO class 使 使
// @mixin get-styles($k,$c) {
// @if $k == size or $k == weight{
// font-#{$k}:#{$c}
// }@else{
// #{$k}:#{$c}
// }
// }
$uni-ui-color:(
//
primary: $uni-primary,
primary-disable: $uni-primary-disable,
primary-light: $uni-primary-light,
//
success: $uni-success,
success-disable: $uni-success-disable,
success-light: $uni-success-light,
warning: $uni-warning,
warning-disable: $uni-warning-disable,
warning-light: $uni-warning-light,
error: $uni-error,
error-disable: $uni-error-disable,
error-light: $uni-error-light,
info: $uni-info,
info-disable: $uni-info-disable,
info-light: $uni-info-light,
//
main-color: $uni-main-color,
base-color: $uni-base-color,
secondary-color: $uni-secondary-color,
extra-color: $uni-extra-color,
//
bg-color: $uni-bg-color,
//
border-1: $uni-border-1,
border-2: $uni-border-2,
border-3: $uni-border-3,
border-4: $uni-border-4,
//
black:$uni-black,
//
white:$uni-white,
//
transparent:$uni-transparent
) !default;
@each $key, $child in $uni-ui-color {
.uni-#{"" + $key} {
color: $child;
}
.uni-#{"" + $key}-bg {
background-color: $child;
}
}
.uni-shadow-sm {
box-shadow: $uni-shadow-sm;
}
.uni-shadow-base {
box-shadow: $uni-shadow-base;
}
.uni-shadow-lg {
box-shadow: $uni-shadow-lg;
}
.uni-mask {
background-color:$uni-mask;
}

View File

@ -0,0 +1,55 @@
@mixin radius($r,$d:null ,$important: false){
$radius-value:map-get($uni-radius, $r) if($important, !important, null);
// Key exists within the $uni-radius variable
@if (map-has-key($uni-radius, $r) and $d){
@if $d == t {
border-top-left-radius:$radius-value;
border-top-right-radius:$radius-value;
}@else if $d == r {
border-top-right-radius:$radius-value;
border-bottom-right-radius:$radius-value;
}@else if $d == b {
border-bottom-left-radius:$radius-value;
border-bottom-right-radius:$radius-value;
}@else if $d == l {
border-top-left-radius:$radius-value;
border-bottom-left-radius:$radius-value;
}@else if $d == tl {
border-top-left-radius:$radius-value;
}@else if $d == tr {
border-top-right-radius:$radius-value;
}@else if $d == br {
border-bottom-right-radius:$radius-value;
}@else if $d == bl {
border-bottom-left-radius:$radius-value;
}
}@else{
border-radius:$radius-value;
}
}
@each $key, $child in $uni-radius {
@if($key){
.uni-radius-#{"" + $key} {
@include radius($key)
}
}@else{
.uni-radius {
@include radius($key)
}
}
}
@each $direction in t, r, b, l,tl, tr, br, bl {
@each $key, $child in $uni-radius {
@if($key){
.uni-radius-#{"" + $direction}-#{"" + $key} {
@include radius($key,$direction,false)
}
}@else{
.uni-radius-#{$direction} {
@include radius($key,$direction,false)
}
}
}
}

View File

@ -0,0 +1,56 @@
@mixin fn($space,$direction,$size,$n) {
@if $n {
#{$space}-#{$direction}: #{$size*$uni-space-root}px
} @else {
#{$space}-#{$direction}: #{-$size*$uni-space-root}px
}
}
@mixin get-styles($direction,$i,$space,$n){
@if $direction == t {
@include fn($space, top,$i,$n);
}
@if $direction == r {
@include fn($space, right,$i,$n);
}
@if $direction == b {
@include fn($space, bottom,$i,$n);
}
@if $direction == l {
@include fn($space, left,$i,$n);
}
@if $direction == x {
@include fn($space, left,$i,$n);
@include fn($space, right,$i,$n);
}
@if $direction == y {
@include fn($space, top,$i,$n);
@include fn($space, bottom,$i,$n);
}
@if $direction == a {
@if $n {
#{$space}:#{$i*$uni-space-root}px;
} @else {
#{$space}:#{-$i*$uni-space-root}px;
}
}
}
@each $orientation in m,p {
$space: margin;
@if $orientation == m {
$space: margin;
} @else {
$space: padding;
}
@for $i from 0 through 16 {
@each $direction in t, r, b, l, x, y, a {
.uni-#{$orientation}#{$direction}-#{$i} {
@include get-styles($direction,$i,$space,true);
}
.uni-#{$orientation}#{$direction}-n#{$i} {
@include get-styles($direction,$i,$space,false);
}
}
}
}

View File

@ -0,0 +1,167 @@
/* #ifndef APP-NVUE */
$-color-white:#fff;
$-color-black:#000;
@mixin base-style($color) {
color: #fff;
background-color: $color;
border-color: mix($-color-black, $color, 8%);
&:not([hover-class]):active {
background: mix($-color-black, $color, 10%);
border-color: mix($-color-black, $color, 20%);
color: $-color-white;
outline: none;
}
}
@mixin is-color($color) {
@include base-style($color);
&[loading] {
@include base-style($color);
&::before {
margin-right:5px;
}
}
&[disabled] {
&,
&[loading],
&:not([hover-class]):active {
color: $-color-white;
border-color: mix(darken($color,10%), $-color-white);
background-color: mix($color, $-color-white);
}
}
}
@mixin base-plain-style($color) {
color:$color;
background-color: mix($-color-white, $color, 90%);
border-color: mix($-color-white, $color, 70%);
&:not([hover-class]):active {
background: mix($-color-white, $color, 80%);
color: $color;
outline: none;
border-color: mix($-color-white, $color, 50%);
}
}
@mixin is-plain($color){
&[plain] {
@include base-plain-style($color);
&[loading] {
@include base-plain-style($color);
&::before {
margin-right:5px;
}
}
&[disabled] {
&,
&:active {
color: mix($-color-white, $color, 40%);
background-color: mix($-color-white, $color, 90%);
border-color: mix($-color-white, $color, 80%);
}
}
}
}
.uni-btn {
margin: 5px;
color: #393939;
border:1px solid #ccc;
font-size: 16px;
font-weight: 200;
background-color: #F9F9F9;
// TODO
overflow: visible;
&::after{
border: none;
}
&:not([type]),&[type=default] {
color: #999;
&[loading] {
background: none;
&::before {
margin-right:5px;
}
}
&[disabled]{
color: mix($-color-white, #999, 60%);
&,
&[loading],
&:active {
color: mix($-color-white, #999, 60%);
background-color: mix($-color-white,$-color-black , 98%);
border-color: mix($-color-white, #999, 85%);
}
}
&[plain] {
color: #999;
background: none;
border-color: $uni-border-1;
&:not([hover-class]):active {
background: none;
color: mix($-color-white, $-color-black, 80%);
border-color: mix($-color-white, $-color-black, 90%);
outline: none;
}
&[disabled]{
&,
&[loading],
&:active {
background: none;
color: mix($-color-white, #999, 60%);
border-color: mix($-color-white, #999, 85%);
}
}
}
}
&:not([hover-class]):active {
color: mix($-color-white, $-color-black, 50%);
}
&[size=mini] {
font-size: 16px;
font-weight: 200;
border-radius: 8px;
}
&.uni-btn-small {
font-size: 14px;
}
&.uni-btn-mini {
font-size: 12px;
}
&.uni-btn-radius {
border-radius: 999px;
}
&[type=primary] {
@include is-color($uni-primary);
@include is-plain($uni-primary)
}
&[type=success] {
@include is-color($uni-success);
@include is-plain($uni-success)
}
&[type=error] {
@include is-color($uni-error);
@include is-plain($uni-error)
}
&[type=warning] {
@include is-color($uni-warning);
@include is-plain($uni-warning)
}
&[type=info] {
@include is-color($uni-info);
@include is-plain($uni-info)
}
}
/* #endif */

View File

@ -0,0 +1,24 @@
@mixin get-styles($k,$c) {
@if $k == size or $k == weight{
font-#{$k}:#{$c}
}@else{
#{$k}:#{$c}
}
}
@each $key, $child in $uni-headings {
/* #ifndef APP-NVUE */
.uni-#{$key} {
@each $k, $c in $child {
@include get-styles($k,$c)
}
}
/* #endif */
/* #ifdef APP-NVUE */
.container .uni-#{$key} {
@each $k, $c in $child {
@include get-styles($k,$c)
}
}
/* #endif */
}

View File

@ -0,0 +1,146 @@
// @use "sass:math";
@import '../tools/functions.scss';
//
$uni-space-root: 2 !default;
//
$uni-radius-root:5px !default;
$uni-radius: () !default;
//
$uni-radius: map-deep-merge(
(
0: 0,
// TODO sm
// 'sm': math.div($uni-radius-root, 2),
null: $uni-radius-root,
'lg': $uni-radius-root * 2,
'xl': $uni-radius-root * 6,
'pill': 9999px,
'circle': 50%
),
$uni-radius
);
//
$body-font-family: 'Roboto', sans-serif !default;
//
$heading-font-family: $body-font-family !default;
$uni-headings: () !default;
$letterSpacing: -0.01562em;
$uni-headings: map-deep-merge(
(
'h1': (
size: 32px,
weight: 300,
line-height: 50px,
// letter-spacing:-0.01562em
),
'h2': (
size: 28px,
weight: 300,
line-height: 40px,
// letter-spacing: -0.00833em
),
'h3': (
size: 24px,
weight: 400,
line-height: 32px,
// letter-spacing: normal
),
'h4': (
size: 20px,
weight: 400,
line-height: 30px,
// letter-spacing: 0.00735em
),
'h5': (
size: 16px,
weight: 400,
line-height: 24px,
// letter-spacing: normal
),
'h6': (
size: 14px,
weight: 500,
line-height: 18px,
// letter-spacing: 0.0125em
),
'subtitle': (
size: 12px,
weight: 400,
line-height: 20px,
// letter-spacing: 0.00937em
),
'body': (
font-size: 14px,
font-weight: 400,
line-height: 22px,
// letter-spacing: 0.03125em
),
'caption': (
'size': 12px,
'weight': 400,
'line-height': 20px,
// 'letter-spacing': 0.03333em,
// 'text-transform': false
)
),
$uni-headings
);
//
$uni-primary: #2979ff !default;
$uni-primary-disable:lighten($uni-primary,20%) !default;
$uni-primary-light: lighten($uni-primary,25%) !default;
//
// 使
$uni-success: #18bc37 !default;
$uni-success-disable:lighten($uni-success,20%) !default;
$uni-success-light: lighten($uni-success,25%) !default;
$uni-warning: #f3a73f !default;
$uni-warning-disable:lighten($uni-warning,20%) !default;
$uni-warning-light: lighten($uni-warning,25%) !default;
$uni-error: #e43d33 !default;
$uni-error-disable:lighten($uni-error,20%) !default;
$uni-error-light: lighten($uni-error,25%) !default;
$uni-info: #8f939c !default;
$uni-info-disable:lighten($uni-info,20%) !default;
$uni-info-light: lighten($uni-info,25%) !default;
//
//
$uni-main-color: #3a3a3a !default; //
$uni-base-color: #6a6a6a !default; //
$uni-secondary-color: #909399 !default; //
$uni-extra-color: #c7c7c7 !default; //
//
$uni-border-1: #F0F0F0 !default;
$uni-border-2: #EDEDED !default;
$uni-border-3: #DCDCDC !default;
$uni-border-4: #B9B9B9 !default;
//
$uni-black: #000000 !default;
$uni-white: #ffffff !default;
$uni-transparent: rgba($color: #000000, $alpha: 0) !default;
//
$uni-bg-color: #f7f7f7 !default;
/* 水平间距 */
$uni-spacing-sm: 8px !default;
$uni-spacing-base: 15px !default;
$uni-spacing-lg: 30px !default;
//
$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default;
$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default;
//
$uni-mask: rgba($color: #000000, $alpha: 0.4) !default;

View File

@ -0,0 +1,19 @@
// map
@function map-deep-merge($parent-map, $child-map){
$result: $parent-map;
@each $key, $child in $child-map {
$parent-has-key: map-has-key($result, $key);
$parent-value: map-get($result, $key);
$parent-type: type-of($parent-value);
$child-type: type-of($child);
$parent-is-map: $parent-type == map;
$child-is-map: $child-type == map;
@if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){
$result: map-merge($result, ( $key: $child ));
}@else {
$result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) ));
}
}
@return $result;
};

View File

@ -0,0 +1,31 @@
//
$uni-space-root: 2;
//
$uni-radius-root:5px;
//
$uni-primary: #2979ff;
//
$uni-success: #4cd964;
//
$uni-warning: #f0ad4e;
//
$uni-error: #dd524d;
//
$uni-info: #909399;
//
$uni-main-color: #303133;
$uni-base-color: #606266;
$uni-secondary-color: #909399;
$uni-extra-color: #C0C4CC;
//
$uni-bg-color: #f5f5f5;
//
$uni-border-1: #DCDFE6;
$uni-border-2: #E4E7ED;
$uni-border-3: #EBEEF5;
$uni-border-4: #F2F6FC;
//
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);

View File

@ -0,0 +1,62 @@
@import './styles/setting/_variables.scss';
//
$uni-space-root: 2;
//
$uni-radius-root:5px;
//
$uni-primary: #2979ff;
$uni-primary-disable:mix(#fff,$uni-primary,50%);
$uni-primary-light: mix(#fff,$uni-primary,80%);
//
// 使
$uni-success: #18bc37;
$uni-success-disable:mix(#fff,$uni-success,50%);
$uni-success-light: mix(#fff,$uni-success,80%);
$uni-warning: #f3a73f;
$uni-warning-disable:mix(#fff,$uni-warning,50%);
$uni-warning-light: mix(#fff,$uni-warning,80%);
$uni-error: #e43d33;
$uni-error-disable:mix(#fff,$uni-error,50%);
$uni-error-light: mix(#fff,$uni-error,80%);
$uni-info: #8f939c;
$uni-info-disable:mix(#fff,$uni-info,50%);
$uni-info-light: mix(#fff,$uni-info,80%);
//
//
$uni-main-color: #3a3a3a; //
$uni-base-color: #6a6a6a; //
$uni-secondary-color: #909399; //
$uni-extra-color: #c7c7c7; //
//
$uni-border-1: #F0F0F0;
$uni-border-2: #EDEDED;
$uni-border-3: #DCDCDC;
$uni-border-4: #B9B9B9;
//
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);
//
$uni-bg-color: #f7f7f7;
/* 水平间距 */
$uni-spacing-sm: 8px;
$uni-spacing-base: 15px;
$uni-spacing-lg: 30px;
//
$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5);
$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5);
//
$uni-mask: rgba($color: #000000, $alpha: 0.4);