Browse Source

新增自定义渠道机能

master
JC96821 4 years ago
parent
commit
1c2d2d0e88
  1. 4
      App.vue
  2. 180
      components/banner-ui/banner-ui.vue
  3. 230
      components/imt-audio/imt-audio.vue
  4. 214
      components/input-ui/audio-ui.vue
  5. 83
      components/input-ui/text-ui.vue
  6. 98
      components/input-ui/title-ui.vue
  7. 398
      components/input-ui/video-ui.vue
  8. 643
      components/ksp-image-cutter/ksp-image-cutter.vue
  9. 101
      components/share-ui/share-ui.vue
  10. 3
      main.js
  11. 21
      node_modules/uview-ui/LICENSE
  12. 102
      node_modules/uview-ui/README.md
  13. 172
      node_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue
  14. 219
      node_modules/uview-ui/components/u-alert-tips/u-alert-tips.vue
  15. 289
      node_modules/uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue
  16. 1265
      node_modules/uview-ui/components/u-avatar-cropper/weCropper.js
  17. 133
      node_modules/uview-ui/components/u-avatar/u-avatar.vue
  18. 147
      node_modules/uview-ui/components/u-back-top/u-back-top.vue
  19. 213
      node_modules/uview-ui/components/u-badge/u-badge.vue
  20. 567
      node_modules/uview-ui/components/u-button/u-button.vue
  21. 641
      node_modules/uview-ui/components/u-calendar/u-calendar.vue
  22. 254
      node_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue
  23. 291
      node_modules/uview-ui/components/u-card/u-card.vue
  24. 69
      node_modules/uview-ui/components/u-cell-group/u-cell-group.vue
  25. 300
      node_modules/uview-ui/components/u-cell-item/u-cell-item.vue
  26. 122
      node_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue
  27. 275
      node_modules/uview-ui/components/u-checkbox/u-checkbox.vue
  28. 215
      node_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue
  29. 128
      node_modules/uview-ui/components/u-col/u-col.vue
  30. 206
      node_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue
  31. 104
      node_modules/uview-ui/components/u-collapse/u-collapse.vue
  32. 233
      node_modules/uview-ui/components/u-column-notice/u-column-notice.vue
  33. 307
      node_modules/uview-ui/components/u-count-down/u-count-down.vue
  34. 239
      node_modules/uview-ui/components/u-count-to/u-count-to.vue
  35. 151
      node_modules/uview-ui/components/u-divider/u-divider.vue
  36. 242
      node_modules/uview-ui/components/u-dropdown-list/u-dropdown-list.vue
  37. 193
      node_modules/uview-ui/components/u-empty/u-empty.vue
  38. 366
      node_modules/uview-ui/components/u-field/u-field.vue
  39. 396
      node_modules/uview-ui/components/u-form-item/u-form-item.vue
  40. 149
      node_modules/uview-ui/components/u-form/u-form.vue
  41. 52
      node_modules/uview-ui/components/u-full-screen/u-full-screen.vue
  42. 54
      node_modules/uview-ui/components/u-gap/u-gap.vue
  43. 113
      node_modules/uview-ui/components/u-grid-item/u-grid-item.vue
  44. 95
      node_modules/uview-ui/components/u-grid/u-grid.vue
  45. 238
      node_modules/uview-ui/components/u-icon/u-icon.vue
  46. 215
      node_modules/uview-ui/components/u-image/u-image.vue
  47. 81
      node_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue
  48. 318
      node_modules/uview-ui/components/u-index-list/u-index-list.vue
  49. 351
      node_modules/uview-ui/components/u-input/u-input.vue
  50. 205
      node_modules/uview-ui/components/u-keyboard/u-keyboard.vue
  51. 227
      node_modules/uview-ui/components/u-lazy-load/u-lazy-load.vue
  52. 141
      node_modules/uview-ui/components/u-line-progress/u-line-progress.vue
  53. 84
      node_modules/uview-ui/components/u-line/u-line.vue
  54. 89
      node_modules/uview-ui/components/u-link/u-link.vue
  55. 101
      node_modules/uview-ui/components/u-loading/u-loading.vue
  56. 198
      node_modules/uview-ui/components/u-loadmore/u-loadmore.vue
  57. 122
      node_modules/uview-ui/components/u-mask/u-mask.vue
  58. 304
      node_modules/uview-ui/components/u-message-input/u-message-input.vue
  59. 295
      node_modules/uview-ui/components/u-modal/u-modal.vue
  60. 295
      node_modules/uview-ui/components/u-navbar/u-navbar.vue
  61. 233
      node_modules/uview-ui/components/u-no-network/u-no-network.vue
  62. 272
      node_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue
  63. 321
      node_modules/uview-ui/components/u-number-box/u-number-box.vue
  64. 158
      node_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue
  65. 653
      node_modules/uview-ui/components/u-picker/u-picker.vue
  66. 439
      node_modules/uview-ui/components/u-popup/u-popup.vue
  67. 86
      node_modules/uview-ui/components/u-radio-group/u-radio-group.vue
  68. 229
      node_modules/uview-ui/components/u-radio/u-radio.vue
  69. 214
      node_modules/uview-ui/components/u-rate/u-rate.vue
  70. 161
      node_modules/uview-ui/components/u-read-more/u-read-more.vue
  71. 267
      node_modules/uview-ui/components/u-row-notice/u-row-notice.vue
  72. 84
      node_modules/uview-ui/components/u-row/u-row.vue
  73. 334
      node_modules/uview-ui/components/u-search/u-search.vue
  74. 131
      node_modules/uview-ui/components/u-section/u-section.vue
  75. 406
      node_modules/uview-ui/components/u-select/u-select.vue
  76. 167
      node_modules/uview-ui/components/u-skeleton/u-skeleton.vue
  77. 254
      node_modules/uview-ui/components/u-slider/u-slider.vue
  78. 200
      node_modules/uview-ui/components/u-steps/u-steps.vue
  79. 152
      node_modules/uview-ui/components/u-sticky/u-sticky.vue
  80. 356
      node_modules/uview-ui/components/u-subsection/u-subsection.vue
  81. 253
      node_modules/uview-ui/components/u-swipe-action/u-swipe-action.vue
  82. 317
      node_modules/uview-ui/components/u-swiper/u-swiper.vue
  83. 160
      node_modules/uview-ui/components/u-switch/u-switch.vue
  84. 246
      node_modules/uview-ui/components/u-tabbar/u-tabbar.vue
  85. 96
      node_modules/uview-ui/components/u-table/u-table.vue
  86. 475
      node_modules/uview-ui/components/u-tabs-swiper/u-tabs-swiper.vue
  87. 337
      node_modules/uview-ui/components/u-tabs/u-tabs.vue
  88. 292
      node_modules/uview-ui/components/u-tag/u-tag.vue
  89. 115
      node_modules/uview-ui/components/u-td/u-td.vue
  90. 58
      node_modules/uview-ui/components/u-th/u-th.vue
  91. 83
      node_modules/uview-ui/components/u-time-line-item/u-time-line-item.vue
  92. 43
      node_modules/uview-ui/components/u-time-line/u-time-line.vue
  93. 222
      node_modules/uview-ui/components/u-toast/u-toast.vue
  94. 121
      node_modules/uview-ui/components/u-top-tips/u-top-tips.vue
  95. 36
      node_modules/uview-ui/components/u-tr/u-tr.vue
  96. 580
      node_modules/uview-ui/components/u-upload/u-upload.vue
  97. 164
      node_modules/uview-ui/components/u-verification-code/u-verification-code.vue
  98. 180
      node_modules/uview-ui/components/u-waterfall/u-waterfall.vue
  99. 883
      node_modules/uview-ui/iconfont.css
  100. 125
      node_modules/uview-ui/index.js

4
App.vue

@ -33,6 +33,6 @@ export default {
};
</script>
<style>
/*每个页面公共css */
<style lang="scss">
@import "uview-ui/index.scss";
</style>

180
components/banner-ui/banner-ui.vue

@ -0,0 +1,180 @@
<template>
<view class="banner-container">
<swiper v-if="showBanner" class="swiper" indicator-dots="true" :autoplay="autoplay" :interval="interval" :duration="duration" circular="true">
<swiper-item v-for="(item, index) in imgList" :key="index" class="swiper-item">
<view v-if="!item.bannerShowSrc" class="empty-item" @tap="chooseImg(index)"><view class="add-plus"></view></view>
<image v-if="item.bannerShowSrc" :src="item.bannerShowSrc" class="banner-img"></image>
<image v-if="item.bannerShowSrc" src="@/static/icon/close.png" class="delete-icon" @tap="deleteImg(index)"></image>
</swiper-item>
</swiper>
<!-- 图片裁剪 -->
<cutter-ui v-if="isCutter" @ok="onok" @cancel="oncancle" :url="currentSrc" :fixed="true" :width="autoLength(650)" :height="autoLength(244)"></cutter-ui>
</view>
</template>
<script>
import upload from '@/util/upload.js'
import cutterUi from '@/components/ksp-image-cutter/ksp-image-cutter.vue'
const system = uni.getSystemInfoSync()
export default {
name: 'bannerUi',
components:{ cutterUi },
props:{
imgCount: Number,
interval: Number,
duration: Number,
initData: Array
},
data(){
return{
autoplay: true,
imgList: [],
currentSrc: '',
currentIndex: -1,
showBanner: false,
isChange: false,
isCutter: false
}
},
watch:{
imgList:{
deep: true,
handler(e){
if(this.isChange){
this.$emit('change', e)
}
}
}
},
computed:{
autoLength:function(){
return function(e){
return e * system.pixelRatio
}
}
},
created() {
this.isChange = false
if(this.initData.length > 0){
this.imgList = this.initData
if(this.imgList.length < this.imgCount){
for(let i=this.imgList.length; i<this.imgCount; i++){
this.imgList.push({bannerShowSrc: '', bannerSrc: ''})
}
}
this.showBanner = true
}else{
for(let i=0; i<this.imgCount; i++){
this.imgList.push({bannerShowSrc: '', bannerSrc: ''})
}
this.showBanner = true
}
},
methods:{
//
chooseImg(index){
this.autoplay = false
let that = this
uni.chooseImage({
count: 1,
sizeType: ['original'],
sourceType: ['album'],
success(resp) {
that.isCutter = true
that.currentSrc = resp.tempFilePaths[0]
that.currentIndex = index
}
})
},
//
onok(e){
upload.upload(1, [e.path]).then(resp=>{
this.isChange = true
this.imgList[this.currentIndex].bannerShowSrc = e.path
this.imgList[this.currentIndex].bannerSrc = resp[0]
this.currentIndex = -1
this.currentSrc = ''
this.autoplay = true
this.isCutter = false
})
},
//
oncancle(e){
this.currentSrc = ''
this.isCutter = false
},
//
deleteImg(index){
this.isChange = true
this.showBanner = false
this.imgList[index].bannerShowSrc = ''
this.imgList[index].bannerSrc = ''
this.showBanner = true
}
}
}
</script>
<style lang="scss" scoped>
.banner-container{
width: 670rpx;
height: 251rpx;
position: relative;
margin-top: 30rpx;
swiper{
height: 100%;
}
.swiper-item{
width: 100%;
height: 100%;
position: relative;
.banner-img{
width: 100%;
height: 100%;
}
.empty-item:active{
background-color: $loading-grey-color;
}
.empty-item{
width: 100%;
height: 100%;
background-color: $loading-color;
transition: background-color .3s;
display: flex;
justify-content: center;
align-items: center;
.add-plus{
position: relative;
}
.add-plus::before{
content: "";
width: 150rpx;
height: 6rpx;
background-color: #fff;
position: absolute;
left: -75rpx;
top: 0;
}
.add-plus::after{
content: "";
width: 120rpx;
height: 6rpx;
background-color: #fff;
transform: rotate(90deg);
position: absolute;
left: -60rpx;
top: 0;
}
}
.delete-icon{
width: 80rpx;
height: 80rpx;
transform: rotate(180deg);
position: absolute;
left: -1rpx;
top: -1rpx;
z-index: 9;
}
}
}
</style>

230
components/imt-audio/imt-audio.vue

@ -0,0 +1,230 @@
<template>
<view class="imt-audio">
<view class="audio-wrapper">
<view class="audio-number">{{currentTime}}</view>
<slider class="audio-slider" :activeColor="color" block-size="16" :value="current" :max="duration" @changing="seek=true,current=$event.detail.value"
@change="change"></slider>
<view class="audio-number">{{durationTime}}</view>
</view>
<view class="audio-control-wrapper" :style="{color:color}">
<view class="audio-control audio-control-prev" v-if="control" :style="{borderColor:color}" @click="prev">&#xe601;</view>
<view v-if="loading" class="audioLoading"></view>
<image v-if="!loading" v-bind:class="controlStyle" class="audio-control" src="../../static/icon/music.png" @click="operation"></image>
<view class="audio-control audio-control-next" v-if="control" :style="{borderColor:color}" @click="next">&#xe601;</view>
</view>
</view>
</template>
<script>
export default {
props: {
src: String, //
autoplay: Boolean, //
duration: Number, //s
control: {
type:Boolean,
default:true
}, ///
continue:Boolean,//@next
color: {
type:String,
default:'#169af3'
} //
},
data() {
return {
audio: '', //
currentTime: '', //
durationTime: '', //
current: '', //slider
loading: false, //
paused: true, //
seek: false, //
isPlay: false,
controlStyle: ['audio-control']
}
},
watch: {
isPlay(e){
if(e){
this.controlStyle = ['audio-control', 'control-play']
}else{
this.controlStyle = ['audio-control']
}
},
//
src(e) {
this.audio.src = e
this.current = 0
this.audio.play()
this.loading = true
},
//
duration(e) {
this.durationTime = this.format(e)
},
//
current(e) {
this.currentTime = this.format(e)
}
},
destroyed(){
this.audio.destroy()
},
created() {
this.audio = uni.createInnerAudioContext()
this.audio.src = this.src
this.current = 0
this.durationTime = this.format(this.duration)
this.audio.obeyMuteSwitch = false
this.audio.autoplay = this.autoplay
//
this.audio.onTimeUpdate(() => {
if (!this.seek) {
this.current = this.audio.currentTime
}
})
//
this.audio.onPlay(() => {
this.paused = false
this.loading = false
})
//
this.audio.onPause(() => {
this.paused = true
})
//
this.audio.onEnded(() => {
if (this.continue) {
this.next()
} else {
this.isPlay = false
this.paused = true
this.current = 0
}
})
//
this.audio.onSeeked(() => {
this.seek = false
})
},
methods: {
//prev
prev() {
this.$emit('prev')
},
//next
next() {
this.$emit('next')
},
//
format(num) {
return '0'.repeat(2 - String(Math.floor(num / 60)).length) + Math.floor(num / 60) + ':' + '0'.repeat(2 - String(
Math.floor(num % 60)).length) + Math.floor(num % 60)
},
///
operation() {
if (this.audio.paused) {
this.isPlay = true
this.audio.play()
this.loading = true
} else {
this.isPlay = false
this.audio.pause()
}
},
//
change(e) {
this.audio.seek(e.detail.value)
}
},
}
</script>
<style>
@font-face {
font-family: 'icon';
src: url('//at.alicdn.com/t/font_1104838_fxzimc34xw.eot');
src: url('//at.alicdn.com/t/font_1104838_fxzimc34xw.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_1104838_fxzimc34xw.woff2') format('woff2'),
url('//at.alicdn.com/t/font_1104838_fxzimc34xw.woff') format('woff'),
url('//at.alicdn.com/t/font_1104838_fxzimc34xw.ttf') format('truetype'),
url('//at.alicdn.com/t/font_1104838_fxzimc34xw.svg#iconfont') format('svg');
}
.imt-audio {
padding: 30upx;
border-radius: 20upx;
background-color: #f9f9f9;
}
.audio-wrapper {
display: flex;
align-items: center;
}
.audio-number {
font-size: 24upx;
line-height: 1;
color: #333;
}
.audio-slider {
flex: 1;
margin: 0 30upx;
}
.audio-control-wrapper {
margin-top: 20upx;
display: flex;
justify-content: center;
align-items: center;
font-family: "icon" !important;
height: 100rpx;
}
.audio-control {
font-size: 32upx;
line-height: 1;
width: 90rpx;
height: 90rpx;
border-radius: 50%;
}
.control-play{
animation: 5s control-roate linear infinite;
}
@keyframes control-roate{
from{transform: rotate(0);}
to{transform: rotate(360deg);}
}
.audio-control-switch {
font-size: 40upx;
margin: 0 80upx;
}
.audio-control-next {
transform: rotate(180deg);
}
.audioLoading {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background-color: transparent;
border-top: 5rpx solid #1296db;
border-right: 5rpx solid transparent;
border-bottom: 5rpx solid #1296db;
border-left: 5rpx solid transparent;
animation: 2s loading linear infinite;
}
@keyframes loading {
0%{
transform: rotate(0);
}
100%{
transform: rotate(360deg);
}
}
</style>

214
components/input-ui/audio-ui.vue

@ -0,0 +1,214 @@
<template>
<view class="audio-content">
<view class="play-area" @tap="changeStatus">
<view v-if="isPlay" class="pause-btn"></view>
<view v-else class="play-btn" ></view>
</view>
<view class="opt-area" @tap="chooseAudio">
<span v-if="audioName">{{subText(audioName, 50)}}</span>
<span v-else>请选择音乐</span>
</view>
<image v-if="audioName" src="@/static/icon/close.png" class="del-icon" @tap.stop="deleteAudio"></image>
</view>
</template>
<script>
import upload from '@/util/upload.js'
import imtAudio from '@/components/imt-audio/imt-audio.vue'
export default {
name: 'audiooUi',
components: { imtAudio },
props:{
initData: Object,
maxDuration: Number
},
data(){
return{
isPlay: false,
audioName: '',
audio: '',
duration: 0,
//onCanPlay
isChoose: false,
uploadSrc: ''
}
},
watch:{
isPlay(e){
//
if(e){
this.audio.play()
}
//
else{
this.audio.stop()
}
}
},
computed:{
subText:function(){
return function(e, len){
return e.length > len?`${e.substring(0, len)}...`:e
}
},
formatDate:function(){
return function(e){
let year = e.getFullYear()
let month = e.getMonth() + 1
let date = e.getDate()
let hour = e.getHours()
let minute = e.getMinutes()
let second = e.getSeconds()
return `${year}-${month}-${date} ${hour<10?'0'+hour:hour}:${minute<10?'0'+minute:minute}:${second<10?'0'+second:second}`
}
}
},
created() {
this.audio = uni.createInnerAudioContext()
if(this.initData){
this.audioName = this.initData.audioSrc
this.audio.src = this.initData.audioPlaySrc
this.uploadSrc = this.initData.audioSrc
}
this.audio.onEnded(()=>{
this.isPlay = false
})
this.audio.onCanplay(()=>{
if(this.isChoose){
this.audio.duration
setTimeout(()=>{
this.duration = this.audio.duration
if(this.duration > this.maxDuration){
uni.showToast({
icon: 'none',
title: `请选择长度不超过${this.maxDuration}秒的音频`
})
}else{
upload.upload(4, [this.audio.src]).then(res=>{
this.audioName = this.formatDate(new Date())
this.$emit('confirm', {name: this.audioName, upload: res[0]})
})
}
}, 500)
this.isChoose = false
}
})
},
destroyed() {
this.audio.destroy()
},
methods: {
changeStatus(){
if(this.audio.src){
this.isPlay = !this.isPlay
}
},
//
chooseAudio(){
let that = this
that.isChoose = true
//
wx.chooseMessageFile({
count: 1,
type: 'file',
extension: ['mp3'],
success:function(resp){
that.audio.src = resp.tempFiles[0].path
}
})
},
//
deleteAudio(){
this.audio.stop()
this.audio.src = ''
this.audioName = ''
this.isPlay = false
this.$emit('confirm', {name: '', src: ''})
}
}
};
</script>
<style lang="scss" scoped>
.audio-content{
width: 670rpx;
height: 150rpx;
border: 1rpx solid $loading-color;
border-top-left-radius: 100rpx;
border-bottom-left-radius: 100rpx;
position: relative;
.play-area{
width: 24%;
height: 100%;
background-color: $loading-color;
display: flex;
justify-content: center;
align-items: center;
border-top-left-radius: 100rpx;
border-bottom-left-radius: 100rpx;
.play-btn{
width: 50%;
height: 50%;
border-radius: 50%;
border: 3rpx solid #fff;
opacity: 0.8;
position: relative;
}
.play-btn::before{
content: "";
width: 0;
height: 0;
border-top: 20rpx solid transparent;
border-right: 30rpx solid transparent;
border-bottom: 20rpx solid transparent;
border-left: 30rpx solid #fff;
position: absolute;
left: 35%;
top: 25%;
}
.pause-btn{
width: 50%;
height: 50%;
border-radius: 50%;
border: 3rpx solid #fff;
opacity: 0.8;
position: relative;
}
.pause-btn::before{
content: "";
width: 30rpx;
height: 30rpx;
background-color: #fff;
position: absolute;
left: 30%;
top: 32%;
}
}
.opt-area{
width: 70%;
height: 87%;
background-color: transparent;
padding: 10rpx 30rpx 10rpx 10rpx;
font-size: 28rpx;
color: $loading-grey-color;
word-break: break-all;
position: absolute;
left: 24%;
top: 0;
transition: background-color .3s, color .3s;
}
.opt-area:active{
background-color: $loading-grey-color;
color: #fff;
}
.del-icon{
width: 60rpx;
height: 60rpx;
transform: rotate(-90deg);
position: absolute;
right: -2rpx;
top: -2rpx;
z-index: 1;
}
}
</style>

83
components/input-ui/text-ui.vue

@ -0,0 +1,83 @@
<template>
<view class="container">
<view v-if="!showInput" class="text-area" :class="{'has-val':textVal}" @tap="showInput = true">
<span v-if="!textVal">{{placeholder}}</span>
<span v-else class="content">{{textVal}}</span>
</view>
<textarea @confirm="confirm" v-if="showInput" auto-height="true" maxlength="300" focus="true" v-model="textVal"></textarea>
</view>
</template>
<script>
export default {
name: 'inputUi',
props:{
placeholder: String
},
data(){
return{
showInput: false,
textVal: ''
}
},
methods: {
confirm(e){
this.$emit('confirm', e.detail.value)
this.showInput = false
}
}
};
</script>
<style lang="scss" scoped>
.container{
width: 100%;
min-height: 150rpx;
display: flex;
justify-content: center;
align-items: center;
.text-area:active{
background-color: $loading-grey-color;
}
.text-area{
width: 700rpx;
min-height: 150rpx;
font-size: 40rpx;
font-weight: 500;
letter-spacing: 2rpx;
background-color: $loading-color;
border: 3rpx dashed $loading-grey-color;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
transition: background-color .3s;
&.has-val{
background-color: transparent;
border: none;
}
.content{
font-size: 30rpx;
color: #6b6b6b;
font-weight: 500;
border: none;
}
}
textarea{
width: 700rpx;
height: 150rpx;
font-size: 30rpx;
padding: 10rpx;
letter-spacing: 5rpx;
}
textarea::before{
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 5rpx;
background-color: $loading-color;
}
}
</style>

98
components/input-ui/title-ui.vue

@ -0,0 +1,98 @@
<template>
<view class="container">
<span v-if="isMust" style="color: red;">*</span>
<textarea :class="{'is-shake':isErr}" v-model="inputVal" auto-height="false" :maxlength="maxLength" :placeholder="placeholder" @confirm="complete" @blur="checkInput"></textarea>
<view v-if="isButton" class="input-btn" @tap="complete">确认</view>
</view>
</template>
<script>
export default {
name: 'titleUi',
props: {
mark: String,
//
isCheck: {default: false, type: Boolean},
//
isMust: { default: false, type: Boolean },
//
isButton: { default: true, type: Boolean },
//
maxLength: Number,
//
placeholder: String
},
data(){
return{
inputVal: '',
isErr: false
}
},
watch:{
isCheck(e){
if(e){
this.checkInput()
}
}
},
methods: {
complete(){
this.$emit('confirm', this.inputVal)
},
checkInput(){
if(!this.inputVal){
this.isErr = true
this.$emit('check', false, this.mark)
}else{
this.isErr = false
this.$emit('confirm', this.inputVal)
this.$emit('check', true, this.mark)
}
}
}
};
</script>
<style lang="scss" scoped>
.container{
span{
margin-right: 10rpx;
display: inline-block;
}
textarea{
display: inline-block;
font-size: 35rpx;
width: 650rpx;
padding: 10rpx;
border-bottom: 1rpx solid $loading-grey-color;
}
.input-btn:active{
background-color: transparent;
color: $phone-color;
}
.input-btn{
display: inline-block;
font-size: 30rpx;
width: 60rpx;
padding: 10rpx 30rpx;
color: #fff;
border-radius: 10rpx;
margin-left: 20rpx;
background-color: $phone-color;
border: 1rpx solid $phone-color;
transition: background-color .3s, color .3s;
}
.is-shake{
animation: shake 1s;
border-bottom: 1rpx solid red;
}
@keyframes shake{
0%{transform: translateX(0);}
25%{transform: translateX(50rpx);}
50%{transform: translateX(-50rpx);}
75%{transform: translateX(50rpx);}
100%{transform: translateX(0);}
}
}
</style>

398
components/input-ui/video-ui.vue

@ -0,0 +1,398 @@
<template>
<view class="container">
<!-- 编辑 -->
<view v-if="!isComplete" class="video-area">
<view v-for="(item, index) in videoList" :key="index">
<view class="video-title-area">
<view class="video-title">{{item.title}}</view>
<button @tap="confirm(item)">选择此视频</button>
</view>
<view class="video-card">
<view class="img-border" @tap="playVideo(item)">
<view class="banner-container">
<view class="header-scroll">{{danmuValue || '视频片头祝福语'}}</view>
</view>
<image :src="item.picUrl" class="cover-img"></image>
<view class="cover">
<view class="play-btn"></view>
</view>
</view>
<view v-if="item.desc" class="desc-area">{{item.desc}}</view>
</view>
</view>
</view>
<!-- 预览 -->
<view class="preview-area" v-if="controls" @tap="controls = false">
<view class="cover"></view>
<view class="video-conrtent">
<view class="close"><view class="close-icon" @tap.stop="controls = false"></view></view>
<video class="video" :src="playSrc" autoplay="false"></video>
</view>
</view>
<!-- 选择完成 -->
<view v-if="isComplete" class="view-area">
<view class="video-content">
<image src="@/static/icon/close.png" class="del-icon" @tap="deleteVideo"></image>
<view class="banner-container">
<view class="header-scroll">{{danmuValue || '视频片头祝福语'}}</view>
</view>
<video id="videoContext" :src="viewSrc" @error="videoErrorCallback"></video>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'videoUi',
props: {
videoList: Array,
initData: Object,
scrollVal: String
},
data(){
return{
//
videoContext: '',
//
controls: false,
//
playSrc: '',
//
viewSrc: '',
//
isComplete: false,
videoTitle: '',
danmuValue: '',
isActice: false
}
},
watch:{
isComplete(e){
//
if(e && !this.videoContext){
this.$nextTick(function(){
this.videoContext = uni.createVideoContext('videoContext')
})
}
},
scrollVal(e){
//
this.danmuValue = e
}
},
created() {
//
if(this.initData){
this.viewSrc = this.initData.videoSrc
this.danmuValue = this.initData.title
this.isComplete = true
}
},
methods: {
//
playVideo(e){
this.playSrc = e.videoSrc
this.controls = true
},
//
deleteVideo(){
this.isComplete = false
this.viewSrc = ''
this.$emit('confirm', '')
},
//
confirm(e){
this.viewSrc = e.videoSrc
this.isComplete = true
this.$emit('confirm', e.videoSrc)
},
//
videoErrorCallback(e){
uni.showModal({
content: e.target.errMsg,
showCancel: false
})
},
//
cancelText(){
this.isActice = false
}
}
}
</script>
<style lang="scss" scoped>
@keyframes fade-in{
from{ opacity: 0; }
to{ opacity: 1; }
}
.container{
width: 100%;
margin-top: 30rpx;
animation: fade-in .5s;
.video-area{
width: 100%;
animation: fade-in .5s;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
.video-title-area{
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 0;
.video-title{
font-size: 35rpx;
font-weight: bold;
}
button{
height: 50rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 30rpx;
padding: 0 20rpx;
border: 1rpx solid $phone-color;
transition: background-color .3s, color .3s;
}
button:active{
background-color: $phone-color;
color: #fff;
}
}
.video-card{
width: 90vw;
margin-bottom: 30rpx;
overflow: hidden;
display: flex;
justify-content: flex-start;
align-items: center;
position: relative;
.img-border{
width: 100%;
position: relative;
.cover-img{
width: 100%;
}
.banner-container{
width: 100%;
height: 50rpx;
letter-spacing: 5rpx;
background-color: $phone-color;
opacity: 0.8;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
z-index: 2;
@keyframes header-scroll{
from{transform: translateX(100%)}
to{transform: translateX(-100%)}
}
.header-scroll{
width: 100%;
padding: 10rpx;
font-size: 30rpx;
color: #fff;
white-space: nowrap;
animation: header-scroll 10s linear infinite;
}
}
.cover{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #000;
opacity: 0.3;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
.play-btn{
width: 0;
height: 0;
border-top: 50rpx solid transparent;
border-right: 80rpx solid transparent;
border-bottom: 50rpx solid transparent;
border-left: 80rpx solid #fff;
position: relative;
left: 40rpx;
}
}
}
.desc-area{
width: 90%;
padding: 10rpx;
color: #fff;
font-size: 25rpx;
background: linear-gradient(90deg, #1f1f1f, transparent);
opacity: 0.8;
position: absolute;
bottom: 0;
left: 0;
}
}
}
.preview-area{
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: 9;
.cover{
width: 100%;
height: 100%;
background-color: #000;
opacity: 0.5;
position: absolute;
left: 0;
top: 0;
}
.video-conrtent{
width: 100%;
.close{
width: 100%;
height: 60rpx;
display: flex;
justify-content: flex-end;
.close-icon{
position: relative;
width: 60rpx;
height: 60rpx;
}
.close-icon::before{
content: "";
width: 0;
height: 60rpx;
border-right: 3rpx solid #fff;
transform: rotate(-45deg);
position: absolute;
right: 0;
left: 50%;
}
.close-icon::after{
content: "";
width: 0;
height: 60rpx;
border-right: 3rpx solid #fff;
transform: rotate(45deg);
position: absolute;
right: 0;
left: 50%;
}
}
.video{
width: 100%;
position: relative;
}
}
}
.view-area{
width: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
animation: fade-in .5s;
position: relative;
.video-content{
width: 90%;
position: relative;
.del-icon{
width: 80rpx;
height: 80rpx;
transform: rotate(180deg);
position: absolute;
left: -1rpx;
top: -1rpx;
z-index: 1;
}
.banner-container{
width: 100%;
height: 50rpx;
letter-spacing: 5rpx;
background-color: $phone-color;
opacity: 0.8;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
@keyframes header-scroll{
from{transform: translateX(100%)}
to{transform: translateX(-100%)}
}
.header-scroll{
width: 100%;
padding: 10rpx;
font-size: 30rpx;
color: #fff;
white-space: nowrap;
animation: header-scroll 10s linear infinite;
}
}
video{
width: 100%;
}
}
.video-title-editor{
width: 90%;
padding: 10rpx;
display: flex;
justify-content: flex-end;
.input-btn{
padding: 10rpx 30rpx;
color: #fff;
font-size: 25rpx;
border-radius: 10rpx;
background-color: $phone-color;
border: 1rpx solid $phone-color;
display: flex;
justify-content: flex-start;
align-items: center;
span{
width: 15rpx;
height: 15rpx;
border-top: 3rpx solid #fff;
border-right: 3rpx solid #fff;
border-bottom: 3rpx solid transparent;
border-left: 3rpx solid transparent;
transform: rotate(45deg);
position: relative;
top: 3rpx;
left: 10rpx;
transition: transform .3s;
}
}
.is-active span{
transform: rotate(135deg);
}
}
.editor-container{
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
z-index: 999;
.editor{
position: absolute;
width: 100%;
height: 100%;
}
}
}
}
</style>

643
components/ksp-image-cutter/ksp-image-cutter.vue

@ -0,0 +1,643 @@
<template>
<view v-show="url" class="ksp-image-cutter">
<view class="target-canvas">
<canvas :style="{width: target.width + 'px', height: target.height + 'px'}" canvas-id="target"></canvas>
</view>
<view class="body">
<image v-if="url" class="image" @load="imageLoad" :style="{left: image.left + 'px', top: image.top + 'px', width: image.width + 'px', height: image.height + 'px'}" :src="url"></image>
<view v-if="mask.show" class="mask"></view>
<view @touchstart="touchStart($event, 'plank')" @touchmove="touchMove" @touchend="touchEnd" @touchcancel="touchCancel" class="plank">
<view class="frame" @touchstart="touchStart($event, 'frame')" @touchstart.stop.prevent="touchHandle" :style="{left: frame.left + 'px', top: frame.top + 'px', width: frame.width + 'px', height: frame.height + 'px'}">
<canvas v-if="mask.show" class="canvas" :style="{width: frame.width + 'px', height: frame.height + 'px'}" canvas-id="canvas"></canvas>
<view class="rect"></view>
<view @touchstart="touchStart($event, 'left')" @touchstart.stop.prevent="touchHandle" class="frame-left"></view>
<view @touchstart="touchStart($event, 'right')" @touchstart.stop.prevent="touchHandle" class="frame-right"></view>
<view @touchstart="touchStart($event, 'top')" @touchstart.stop.prevent="touchHandle" class="frame-top"></view>
<view @touchstart="touchStart($event, 'bottom')" @touchstart.stop.prevent="touchHandle" class="frame-bottom"></view>
<view @touchstart="touchStart($event, 'left-top')" @touchstart.stop.prevent="touchHandle" class="frame-left-top"></view>
<view @touchstart="touchStart($event, 'left-bottom')" @touchstart.stop.prevent="touchHandle" class="frame-left-bottom"></view>
<view @touchstart="touchStart($event, 'right-top')" @touchstart.stop.prevent="touchHandle" class="frame-right-top"></view>
<view @touchstart="touchStart($event, 'right-bottom')" @touchstart.stop.prevent="touchHandle" class="frame-right-bottom"></view>
</view>
</view>
</view>
<view class="toolbar">
<button @tap="oncancle" class="btn-cancel">返回</button>
<button @tap="onok" class="btn-ok">确定</button>
</view>
</view>
</template>
<script>
export default {
props: {
url: {
type: String,
default: ""
},
fixed: {
type: Boolean,
default: false
},
width: {
type: Number,
default: 200
},
height: {
type: Number,
default: 200
},
maxWidth: {
type: Number,
default: 1024
},
maxHeight: {
type: Number,
default: 1024
},
blob: {
type: Boolean,
default: true
}
},
data() {
return {
mask: {
show: false
},
frame: {
left: 50,
top: 50,
width: this.width,
height: this.height
},
image: {
left: 20,
top: 20,
width: 300,
height: 400
},
real: {
width: 100,
height: 100
},
target: {
width: this.width,
height: this.height
},
touches: [],
type: "",
start: {
frame: {
left: 0,
top: 0,
width: 0,
height: 0
},
image: {
left: 0,
top: 0,
width: 0,
height: 0
},
},
timeoutId: -1,
context: null
};
},
mounted() {
//#ifdef H5
this.$el.addEventListener("touchmove", (ev) => {
ev.preventDefault();
});
// #endif
this.context = uni.createCanvasContext("canvas", this);
this.targetContext = uni.createCanvasContext("target", this);
},
methods: {
imageLoad(ev) {
this.mask.show = true;
this.real.width = ev.detail.width;
this.real.height = ev.detail.height;
this.image.width = ev.detail.width;
this.image.height = ev.detail.height;
this.frame.width = this.width;
this.frame.height = this.height;
if (!this.fixed) {
this.frame.width = this.image.width;
this.frame.height = this.image.height;
}
var query = uni.createSelectorQuery().in(this);
query.select(".body").boundingClientRect((data) => {
var bw = data.width;
var bh = data.height;
var fw = this.frame.width;
var fh = this.frame.height;
var tw = bw * 0.8;
var th = bh * 0.8;
var sx = tw / fw;
var sy = th / fh;
var scale = sx;
if (sx < sy) {
scale = sy;
}
tw = fw * scale;
th = fh * scale;
var tx = (bw - tw) / 2;
var ty = (bh - th) / 2;
this.frame.width = tw;
this.frame.height = th;
this.frame.left = tx;
this.frame.top = ty;
var iw = this.image.width;
var ih = this.image.height;
sx = tw / iw;
sy = th / ih;
scale = sx;
if (sx < sy) {
scale = sy;
}
this.image.width = iw * scale;
this.image.height = ih * scale;
this.image.left = (bw - this.image.width) / 2;
this.image.top = (bh - this.image.height) / 2;
setTimeout(() => {
this.trimImage();
}, 100);
}).exec();
},
touchHandle() {},
touchStart(ev, type) {
this.stopTime();
this.mask.show = false;
if (this.touches.length == 0) {
this.type = type;
this.start.frame.left = this.frame.left;
this.start.frame.top = this.frame.top;
this.start.frame.width = this.frame.width;
this.start.frame.height = this.frame.height;
this.start.image.left = this.image.left;
this.start.image.top = this.image.top;
this.start.image.width = this.image.width;
this.start.image.height = this.image.height;
}
var touches = ev.changedTouches;
for(var i = 0; i < touches.length; i++) {
var touch = touches[i];
// this.touches[touch.identifier] = touch;
this.touches.push(touch);
}
},
touchMove(ev) {
this.stopTime();
ev.preventDefault();
var touches = ev.touches;
if (this.touches.length == 1) {
if (this.type == "plank" || this.type == "frame" || this.fixed) {
this.moveImage(this.touches[0], touches[0]);
} else {
this.scaleFrame(this.touches[0], touches[0], this.type);
}
} else if (this.touches.length == 2 && touches.length == 2) {
var ta = this.touches[0];
var tb = this.touches[1];
var tc = touches[0];
var td = touches[1];
if (ta.identifier != tc.identifier) {
var temp = tc;
tc = td;
td = temp;
}
this.scaleImage(ta, tb, tc, td);
}
},
touchEnd(ev) {
this.type = "";
this.touches = [];
this.startTime();
},
touchCancel(ev) {
this.type = "";
this.touches = [];
this.startTime();
},
startTime() {
this.stopTime();
this.timeoutId = setTimeout(() => {
this.trimImage();
}, 800);
},
stopTime() {
if (this.timeoutId >= 0) {
clearTimeout(this.timeoutId);
this.timeoutId = -1;
}
},
trimImage() {
this.mask.show = true;
var query = uni.createSelectorQuery().in(this);
query.select(".body").boundingClientRect((data) => {
var bw = data.width;
var bh = data.height;
var fw = this.frame.width;
var fh = this.frame.height;
var tw = bw * 0.8;
var th = bh * 0.8;
var sx = tw / fw;
var sy = th / fh;
var scale = sx;
if (sx > sy) {
scale = sy;
}
tw = fw * scale;
th = fh * scale;
var tx = (bw - tw) / 2;
var ty = (bh - th) / 2;
var ax = tx - this.frame.left + (this.frame.left - this.image.left) * (1 - scale);
var ay = ty - this.frame.top + (this.frame.top - this.image.top) * (1 - scale);
this.frame.width = tw;
this.frame.height = th;
this.frame.left = tx;
this.frame.top = ty;
this.image.width *= scale;
this.image.height *= scale;
this.image.left += ax;
this.image.top += ay;
}).exec();
setTimeout(() => {
var scale = this.image.width / this.real.width;
var x = (this.frame.left - this.image.left) / scale;
var y = (this.frame.top - this.image.top) / scale;
var width = this.frame.width / scale;
var height = this.frame.height / scale;
this.context.drawImage(this.url, x, y, width, height, 0, 0, this.frame.width, this.frame.height);
this.context.draw(false);
}, 100);
},
moveImage(ta, tb) {
var ax = tb.clientX - ta.clientX;
var ay = tb.clientY - ta.clientY;
this.image.left = this.start.image.left + ax;
this.image.top = this.start.image.top + ay;
if (this.image.left > this.frame.left) {
this.image.left = this.frame.left;
}
if (this.image.top > this.frame.top) {
this.image.top = this.frame.top;
}
if (this.image.left + this.image.width < this.frame.left + this.frame.width) {
this.image.left = this.frame.left + this.frame.width - this.image.width;
}
if (this.image.top + this.image.height < this.frame.top + this.frame.height) {
this.image.top = this.frame.top + this.frame.height - this.image.height;
}
},
scaleImage(ta, tb, tc, td) {
var x1 = ta.clientX;
var y1 = ta.clientY;
var x2 = tb.clientX;
var y2 = tb.clientY;
var x3 = tc.clientX;
var y3 = tc.clientY;
var x4 = td.clientX;
var y4 = td.clientY;
var ol = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
var el = Math.sqrt((x3 - x4) * (x3 - x4) + (y3 - y4) * (y3 - y4));
var ocx = (x1 + x2) / 2;
var ocy = (y1 + y2) / 2;
var ecx = (x3 + x4) / 2;
var ecy = (y3 + y4) / 2;
var ax = ecx - ocx;
var ay = ecy - ocy;
var scale = el / ol;
if (this.start.image.width * scale < this.frame.width) {
scale = this.frame.width / this.start.image.width;
}
if (this.start.image.height * scale < this.frame.height) {
scale = this.frame.height / this.start.image.height;
}
if (this.start.image.width * scale < this.frame.width) {
scale = this.frame.width / this.start.image.width;
}
this.image.left = this.start.image.left + ax - (ocx - this.start.image.left) * (scale - 1);
this.image.top = this.start.image.top + ay - (ocy - this.start.image.top) * (scale - 1);
this.image.width = this.start.image.width * scale;
this.image.height = this.start.image.height * scale;
if (this.image.left > this.frame.left) {
this.image.left = this.frame.left;
}
if (this.image.top > this.frame.top) {
this.image.top = this.frame.top;
}
if (this.image.left + this.image.width < this.frame.left + this.frame.width) {
this.image.left = this.frame.left + this.frame.width - this.image.width;
}
if (this.image.top + this.image.height < this.frame.top + this.frame.height) {
this.image.top = this.frame.top + this.frame.height - this.image.height;
}
},
scaleFrame(ta, tb, type) {
var ax = tb.clientX - ta.clientX;
var ay = tb.clientY - ta.clientY;
var x1 = this.start.frame.left;
var y1 = this.start.frame.top;
var x2 = this.start.frame.left + this.start.frame.width;
var y2 = this.start.frame.top + this.start.frame.height;
if (type == "left") {
x1 += ax;
} else if (type == "right") {
x2 += ax;
} else if (type == "top") {
y1 += ay;
} else if (type == "bottom") {
y2 += ay;
} else if (type == "left-top") {
x1 += ax;
y1 += ay;
} else if (type == "left-bottom") {
x1 += ax;
y2 += ay;
} else if (type == "right-top") {
x2 += ax;
y1 += ay;
} else if (type == "right-bottom") {
x2 += ax;
y2 += ay;
}
if (x1 < this.image.left) {
x1 = this.image.left;
}
if (y1 < this.image.top) {
y1 = this.image.top;
}
if (x2 > this.image.left + this.image.width) {
x2 = this.image.left + this.image.width;
}
if (y2 > this.image.top + this.image.height) {
y2 = this.image.top + this.image.height;
}
this.frame.left = x1;
this.frame.top = y1;
this.frame.width = x2 - x1;
this.frame.height = y2 - y1;
},
parseBlob(base64) {
var arr = base64.split(',');
var mime = arr[0].match(/:(.*?);/)[1];
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
for(var i = 0; i < n; i++) {
u8arr[i] = bstr.charCodeAt(i);
}
var url = URL || webkitURL;
return url.createObjectURL(new Blob([u8arr], {type: mime}));
},
onok() {
var scale = this.image.width / this.real.width;
var x = (this.frame.left - this.image.left) / scale;
var y = (this.frame.top - this.image.top) / scale;
var width = this.frame.width / scale;
var height = this.frame.height / scale;
var tw = width;
var th = height;
if (this.fixed) {
tw = this.width / 2;
th = this.height / 2;
} else {
if (tw > this.maxWidth / 2) {
var sc = this.maxWidth / 2 / tw;
tw = tw * sc;
th = th * sc;
}
if (th > this.maxHeight / 2) {
var sc = this.maxHeight / 2 / th;
th = th * sc;
tw = tw * sc;
}
}
this.target.width = tw;
this.target.height = th;
uni.showLoading({
title: "正在裁剪"
});
setTimeout(() => {
this.targetContext.drawImage(this.url, x, y, width, height, 0, 0, tw, th);
this.targetContext.draw(false, () => {
uni.canvasToTempFilePath({
canvasId: "target",
success: (res) => {
var path = res.tempFilePath;
// #ifdef H5
if (this.blob) {
path = this.parseBlob(path);
}
// #endif
this.$emit("ok", {
path: path
});
},
fail: (ev) => {
console.log(ev);
},
complete: () => {
uni.hideLoading();
}
}, this);
});
}, 100);
},
oncancle() {
this.$emit("cancel");
}
}
}
</script>
<style scoped>
.ksp-image-cutter {
position: fixed;
width: 100vw;
height: 100vh;
top: 0;
left: 0;
bottom: 0;
z-index: 1000;
}
.target-canvas{
width: 0;
height: 0;
overflow: hidden;
}
.toolbar {
position: absolute;
width: 100%;
height: 100upx;
left: 0upx;
bottom: 0upx;
box-sizing: border-box;
border-bottom: 1px solid #C0C0C0;
background: #F8F8F8;
}
.btn-cancel {
position: absolute;
left: 100upx;
top: 12upx;
font-size: 30upx;
line-height: 30upx;
padding: 20upx;
color: #333333;
}
.btn-ok {
position: absolute;
right: 100upx;
top: 12upx;
font-size: 30upx;
line-height: 30upx;
padding: 20upx;
color: #333333;
}
.body {
position: absolute;
left: 0upx;
right: 0upx;
top: 0upx;
bottom: 100upx;
background: black;
overflow: hidden;
}
.mask {
position: absolute;
left: 0upx;
right: 0upx;
top: 0upx;
bottom: 0upx;
background: black;
opacity: 0.4;
}
.plank {
position: absolute;
left: 0upx;
right: 0upx;
top: 0upx;
bottom: 0upx;
}
.image {
position: absolute;
}
.frame {
position: absolute;
}
.canvas {
position: absolute;
display: block;
left: 0px;
top: 0px;
}
.rect {
position: absolute;
left: -2px;
top: -2px;
width: 100%;
height: 100%;
border: 2px solid white;
}
.line-one {
position: absolute;
width: 100%;
height: 1px;
background: white;
left: 0;
top: 33.3%;
}
.line-two {
position: absolute;
width: 100%;
height: 1px;
background: white;
left: 0;
top: 66.7%;
}
.line-three {
position: absolute;
width: 1px;
height: 100%;
background: white;
top: 0;
left: 33.3%;
}
.line-four {
position: absolute;
width: 1px;
height: 100%;
background: white;
top: 0;
left: 66.7%;
}
.frame-left {
position: absolute;
height: 100%;
width: 8px;
left: -4px;
top: 0;
}
.frame-right {
position: absolute;
height: 100%;
width: 8px;
right: -4px;
top: 0;
}
.frame-top {
position: absolute;
width: 100%;
height: 8px;
top: -4px;
left: 0;
}
.frame-bottom {
position: absolute;
width: 100%;
height: 8px;
bottom: -4px;
left: 0;
}
.frame-left-top {
position: absolute;
width: 20px;
height: 20px;
left: -6px;
top: -6px;
border-left: 4px solid red;
border-top: 4px solid red;
}
.frame-left-bottom {
position: absolute;
width: 20px;
height: 20px;
left: -6px;
bottom: -6px;
border-left: 4px solid red;
border-bottom: 4px solid red;
}
.frame-right-top {
position: absolute;
width: 20px;
height: 20px;
right: -6px;
top: -6px;
border-right: 4px solid red;
border-top: 4px solid red;
}
.frame-right-bottom {
position: absolute;
width: 20px;
height: 20px;
right: -6px;
bottom: -6px;
border-right: 4px solid red;
border-bottom: 4px solid red;
}
</style>

101
components/share-ui/share-ui.vue

@ -0,0 +1,101 @@
<template>
<cover-view class="container">
<cover-view class="cover" @tap="cancel"></cover-view>
<cover-view class="share-area">
<cover-view class="img-area">
<cover-image src="@/static/icon/success.png" class="img"></cover-image>
<cover-view class="text">{{shareTitle}}</cover-view>
</cover-view>
<cover-view class="opt-area">
<button @tap="back">预览</button>
<!-- <button open-type="share">分享</button> -->
</cover-view>
</cover-view>
</cover-view>
</template>
<script>
export default {
name: 'shareUi',
props: { shareTitle: String },
data(){
return{
}
},
methods: {
cancel(){
this.$emit('cancel')
},
back(){
this.$emit('back')
}
}
};
</script>
<style lang="scss" scoped>
.container{
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
.cover{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: $phone-color;
opacity: 0.5;
}
@keyframes show-in{
from{
transform: scale(0);
}
to{
transform: scale(1);
}
}
.share-area{
width: 400rpx;
height: 400rpx;
background-color: #fff;
border-radius: 10rpx;
z-index: 999;
animation: show-in .5s;
.img-area{
width: 100%;
height: 70%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.img{
width: 150rpx;
height: 150rpx;
}
.text{
font-size: 30rpx;
margin-top: 20rpx;
}
}
.opt-area{
width: 100%;
display: flex;
justify-content: space-around;
button{
width: 150rpx;
height: 80rpx;
font-size: 30rpx;
border: 1rpx solid $phone-color;
}
}
}
}
</style>

3
main.js

@ -19,7 +19,8 @@ if (wechat.isWechat()) {
}
// #endif
import uView from 'uview-ui'
Vue.use(uView)
App.mpType = 'app'

21
node_modules/uview-ui/LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 www.uviewui.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

102
node_modules/uview-ui/README.md

@ -0,0 +1,102 @@
<p align="center">
<img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
</p>
<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView</h3>
<h3 align="center">多平台快速开发的UI框架</h3>
## 说明
uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
## 特性
- 兼容安卓,iOS,微信小程序,H5,QQ小程序,百度小程序,支付宝小程序,头条小程序
- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用
- 众多贴心的JS利器,让您飞镖在手,召之即来,百步穿杨
- 众多的常用页面和布局,让您专注逻辑,事半功倍
- 详尽的文档支持,现代化的演示效果
- 按需引入,精简打包体积
## 安装
```bash
# npm方式安装
npm i uview-ui
```
## 快速上手
1. `main.js`引入uView库
```js
// main.js
import uView from 'uview-ui';
Vue.use(uView);
```
2. `App.vue`引入基础样式(注意style标签需声明scss属性支持)
```css
/* App.vue */
<style lang="scss">
@import "uview-ui/index.scss";
</style>
```
3. `uni.scss`引入全局scss变量文件
```css
/* uni.scss */
@import "uview-ui/theme.scss";
```
4. `pages.json`配置easycom规则(按需引入)
```js
// pages.json
{
"easycom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
// 此为本身已有的内容
"pages": [
// ......
]
}
```
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 使用方法
配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。
```html
<template>
<u-button>按钮</u-button>
</template>
```
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 链接
- [官方文档](https://uviewui.com/)
- [更新日志](https://uviewui.com/components/changelog.html)
- [升级指南](https://uviewui.com/components/changelog.html)
- [关于我们](https://uviewui.com/cooperation/about.html)
## 预览
您可以通过**微信**扫码,查看最佳的演示效果。
<br>
<br>
<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
<!-- ## 捐赠uView的研发
uView文档和源码全部开源免费,如果您认为uView帮到了您的开发工作,您可以捐赠uView的研发工作,捐赠无门槛,哪怕是一杯可乐也好(相信这比打赏主播更有意义)。
<img src="https://uviewui.com/common/wechat.png" width="220" >
<img style="margin-left: 100px;" src="https://uviewui.com/common/alipay.png" width="220" >
-->
## 版权信息
uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。

172
node_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue

@ -0,0 +1,172 @@
<template>
<u-popup mode="bottom" :border-radius="borderRadius" :popup="false" v-model="value" :maskCloseAble="maskCloseAble"
length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="popupClose" :z-index="uZIndex">
<view class="u-tips u-border-bottom" v-if="tips.text" :style="[tipsStyle]">
{{tips.text}}
</view>
<block v-for="(item, index) in list" :key="index">
<view @touchmove.stop.prevent @tap="itemClick(index)" :style="[itemStyle(index)]" class="u-action-sheet-item" :class="[index < list.length - 1 ? 'u-border-bottom' : '']"
hover-class="u-hover-class" :hover-stay-time="150">
{{item.text}}
</view>
</block>
<view class="u-gab" v-if="cancelBtn">
</view>
<view @touchmove.stop.prevent class="u-actionsheet-cancel u-action-sheet-item" hover-class="u-hover-class"
:hover-stay-time="150" v-if="cancelBtn" @tap="close">{{cancelText}}</view>
</u-popup>
</template>
<script>
/**
* actionSheet 操作菜单
* @description 本组件用于从底部弹出一个操作菜单供用户选择并返回结果本组件功能类似于uni的uni.showActionSheetAPI配置更加灵活所有平台都表现一致
* @tutorial https://www.uviewui.com/components/actionSheet.html
* @property {Array<Object>} list 按钮的文字数组见官方文档示例
* @property {Object} tips 顶部的提示文字见官方文档示例
* @property {String} cancel-text 取消按钮的提示文字
* @property {Boolean} cancel-btn 是否显示底部的取消按钮默认true
* @property {Number String} border-radius 弹出部分顶部左右的圆角值单位rpx默认0
* @property {Boolean} mask-close-able 点击遮罩是否可以关闭默认true
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Number String} z-index z-index值默认1075
* @property {String} cancel-text 取消按钮的提示文字
* @event {Function} click 点击ActionSheet列表项时触发
* @event {Function} close 点击取消按钮时触发
* @example <u-action-sheet :list="list" @click="click" v-model="show"></u-action-sheet>
*/
export default {
name: "u-action-sheet",
props: {
// actionsheet
maskCloseAble: {
type: Boolean,
default: true
},
// rpx
list: {
type: Array,
default () {
//
// return [{
// text: '',
// color: '',
// fontSize: ''
// }]
return [];
}
},
//
tips: {
type: Object,
default () {
return {
text: '',
color: '',
fontSize: '26'
}
}
},
//
cancelBtn: {
type: Boolean,
default: true
},
// iPhoneX
safeAreaInsetBottom: {
type: Boolean,
default: false
},
//
value: {
type: Boolean,
default: false
},
//
borderRadius: {
type: [String, Number],
default: 0
},
// z-index
zIndex: {
type: [String, Number],
default: 0
},
//
cancelText: {
type: String,
default: '取消'
}
},
computed: {
//
tipsStyle() {
let style = {};
if (this.tips.color) style.color = this.tips.color;
if (this.tips.fontSize) style.fontSize = this.tips.fontSize + 'rpx';
return style;
},
//
itemStyle() {
return (index) => {
let style = {};
if (this.list[index].color) style.color = this.list[index].color;
if (this.list[index].fontSize) style.fontSize = this.list[index].fontSize + 'rpx';
return style;
}
},
uZIndex() {
// z-index使
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
methods: {
//
close() {
// inputpropsvalue
// vue
this.popupClose();
this.$emit('close');
},
//
popupClose() {
this.$emit('input', false);
},
// itemif (!this.show) return;
itemClick(index) {
this.$emit('click', index);
this.$emit('input', false);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-tips {
font-size: 26rpx;
text-align: center;
padding: 34rpx 0;
line-height: 1;
color: $u-tips-color;
}
.u-action-sheet-item {
display: flex;
line-height: 1;
justify-content: center;
align-items: center;
font-size: 34rpx;
padding: 34rpx 0;
}
.u-gab {
height: 12rpx;
background-color: rgb(234, 234, 236);
}
.u-actionsheet-cancel {
color: $u-main-color;
}
</style>

219
node_modules/uview-ui/components/u-alert-tips/u-alert-tips.vue

@ -0,0 +1,219 @@
<template>
<view class="u-alert-tips" v-if="show" :class="[
!show ? 'u-close-alert-tips': '',
type ? 'u-alert-tips--bg--' + type + '-light' : '',
type ? 'u-alert-tips--border--' + type + '-disabled' : '',
]" :style="{
backgroundColor: bgColor,
borderColor: borderColor
}">
<view class="u-icon-wrap">
<u-icon v-if="showIcon" :name="$u.type2icon(type)" :size="description ? 40 : 32" class="u-icon" :color="type"></u-icon>
</view>
<view class="u-alert-content" @tap.stop="click">
<view class="u-alert-title" :style="{fontWeight: description ? 500 : 'normal'}">
{{title}}
</view>
<view v-if="description" class="u-alert-desc">
{{description}}
</view>
</view>
<view class="u-icon-wrap">
<u-icon @click="close" v-if="closeAble && !closeText" hoverClass="u-type-error-hover-color" name="close" color="#c0c4cc"
:size="22" class="u-close-icon" :style="{
top: description ? '18rpx' : '24rpx'
}"></u-icon>
</view>
<text v-if="closeAble && closeText" class="u-close-text" :style="{
top: description ? '18rpx' : '24rpx'
}">{{closeText}}</text>
</view>
</template>
<script>
/**
* alertTips 警告提示
* @description 警告提示展现需要关注的信息
* @tutorial https://uviewui.com/components/alertTips.html
* @property {String} title 显示的标题文字
* @property {String} description 辅助性文字颜色比title浅一点字号也小一点可选
* @property {String} type 关闭按钮(默认为叉号icon图标)
* @property {String} close-able 用文字替代关闭图标close-able为true时有效
* @property {Boolean} show-icon 是否显示左边的辅助图标
* @property {Boolean} show 显示或隐藏组件
* @event {Function} click 点击组件时触发
* @event {Function} close 点击关闭按钮时触发
*/
export default {
name: 'u-alert-tips',
props: {
//
title: {
type: String,
default: ''
},
// success/warning/info/error
type: {
type: String,
default: 'warning'
},
//
description: {
type: String,
default: ''
},
//
closeAble: {
type: Boolean,
default: false
},
//
closeText: {
type: String,
default: ''
},
//
showIcon: {
type: Boolean,
default: false
},
// coloricon
color: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: ''
},
//
borderColor: {
type: String,
default: ''
},
//
show: {
type: Boolean,
default: true
}
},
data() {
return {
}
},
methods: {
//
click() {
this.$emit('click');
},
//
close() {
this.$emit('close');
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-alert-tips {
display: flex;
align-items: center;
padding: 16rpx 30rpx;
border-radius: 8rpx;
position: relative;
transition: all 0.3s linear;
border: 1px solid #fff;
&--bg--primary-light {
background-color: $u-type-primary-light;
}
&--bg--info-light {
background-color: $u-type-info-light;
}
&--bg--success-light {
background-color: $u-type-success-light;
}
&--bg--warning-light {
background-color: $u-type-warning-light;
}
&--bg--error-light {
background-color: $u-type-error-light;
}
&--border--primary-disabled {
border-color: $u-type-primary-disabled;
}
&--border--success-disabled {
border-color: $u-type-success-disabled;
}
&--border--error-disabled {
border-color: $u-type-error-disabled;
}
&--border--warning-disabled {
border-color: $u-type-warning-disabled;
}
&--border--info-disabled {
border-color: $u-type-info-disabled;
}
}
.u-close-alert-tips {
opacity: 0;
visibility: hidden;
}
@keyframes myfirst {
from {
height: 100%;
}
to {
height: 0
}
}
.u-icon {
margin-right: 16rpx;
}
.u-alert-title {
font-size: 28rpx;
color: $u-main-color;
}
.u-alert-desc {
font-size: 26rpx;
text-align: left;
color: $u-content-color;
}
.u-close-icon {
position: absolute;
top: 20rpx;
right: 20rpx;
}
.u-close-hover {
color: red;
}
.u-close-text {
font-size: 24rpx;
color: $u-tips-color;
position: absolute;
top: 20rpx;
right: 20rpx;
line-height: 1;
}
</style>

289
node_modules/uview-ui/components/u-avatar-cropper/u-avatar-cropper.vue

@ -0,0 +1,289 @@
<template>
<view class="content">
<view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }">
<canvas
class="cropper"
:disable-scroll="true"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
:style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }"
canvas-id="cropper"
></canvas>
<canvas
class="cropper"
:disable-scroll="true"
:style="{
position: 'fixed',
top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`,
left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`,
width: `${cropperOpt.width * cropperOpt.pixelRatio}px`,
height: `${cropperOpt.height * cropperOpt.pixelRatio}`
}"
canvas-id="targetId"
></canvas>
</view>
<view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }">
<!-- #ifdef H5 -->
<view class="upload" @tap="uploadTap">选择图片</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="upload" @tap="uploadTap">重新选择</view>
<!-- #endif -->
<view class="getCropperImage" @tap="getCropperImage(false)">确定</view>
</view>
</view>
</template>
<script>
import WeCropper from './weCropper.js';
export default {
props: {
// lineWidth-(rpx)color:
// mask-rgba"rgba(0, 0, 0, 0.35)"
boundStyle: {
type: Object,
default() {
return {
lineWidth: 4,
borderColor: 'rgb(245, 245, 245)',
mask: 'rgba(0, 0, 0, 0.35)'
};
}
}
// // rpx
// rectWidth: {
// type: [String, Number],
// default: 400
// },
// // rpx
// rectHeight: {
// type: [String, Number],
// default: 400
// },
// // rpx
// destWidth: {
// type: [String, Number],
// default: 400
// },
// // rpx
// destHeight: {
// type: [String, Number],
// default: 400
// },
// // "png""jpg"
// fileType: {
// type: String,
// default: 'jpg',
// },
// //
// // H5使
// quality: {
// type: [Number, String],
// default: 1
// }
},
data() {
return {
//
bottomNavHeight: 50,
originWidth: 200,
width: 0,
height: 0,
cropperOpt: {
id: 'cropper',
targetId: 'targetCropper',
pixelRatio: 1,
width: 0,
height: 0,
scale: 2.5,
zoom: 8,
cut: {
x: (this.width - this.originWidth) / 2,
y: (this.height - this.originWidth) / 2,
width: this.originWidth,
height: this.originWidth
},
boundStyle: {
lineWidth: uni.upx2px(this.boundStyle.lineWidth),
mask: this.boundStyle.mask,
color: this.boundStyle.borderColor
}
},
//
// px
destWidth: 200,
// px
rectWidth: 200,
// 'png'"jpg"
fileType: 'jpg',
src: '', //
};
},
onLoad(option) {
let rectInfo = uni.getSystemInfoSync();
this.width = rectInfo.windowWidth;
this.height = rectInfo.windowHeight - this.bottomNavHeight;
this.cropperOpt.width = this.width;
this.cropperOpt.height = this.height;
this.cropperOpt.pixelRatio = rectInfo.pixelRatio;
if (option.destWidth) this.destWidth = option.destWidth;
if (option.rectWidth) {
let rectWidth = Number(option.rectWidth);
this.cropperOpt.cut = {
x: (this.width - rectWidth) / 2,
y: (this.height - rectWidth) / 2,
width: rectWidth,
height: rectWidth
};
}
this.rectWidth = option.rectWidth;
if (option.fileType) this.fileType = option.fileType;
//
this.cropper = new WeCropper(this.cropperOpt)
.on('ready', ctx => {
// wecropper is ready for work!
})
.on('beforeImageLoad', ctx => {
// before picture loaded, i can do something
})
.on('imageLoad', ctx => {
// picture loaded
})
.on('beforeDraw', (ctx, instance) => {
// before canvas draw,i can do something
});
// page.json
uni.setNavigationBarColor({
frontColor: '#ffffff',
backgroundColor: '#000000'
});
uni.chooseImage({
count: 1, // 9
sizeType: ['compressed'], //
sourceType: ['album', 'camera'], //
success: res => {
this.src = res.tempFilePaths[0];
// datasrc
this.cropper.pushOrign(this.src);
}
});
},
methods: {
touchStart(e) {
this.cropper.touchStart(e);
},
touchMove(e) {
this.cropper.touchMove(e);
},
touchEnd(e) {
this.cropper.touchEnd(e);
},
getCropperImage(isPre = false) {
console.log(this.src);
if(!this.src) return this.$u.toast('请先选择图片再裁剪');
let cropper_opt = {
destHeight: Number(this.destWidth), // uni.canvasToTempFilePath
destWidth: Number(this.destWidth),
fileType: this.fileType
};
this.cropper.getCropperImage(cropper_opt, (path, err) => {
if (err) {
uni.showModal({
title: '温馨提示',
content: err.message
});
} else {
if (isPre) {
uni.previewImage({
current: '', // http
urls: [path] // http
});
} else {
uni.$emit('uAvatarCropper', path);
this.$u.route({
type: 'back'
});
}
}
});
},
uploadTap() {
const self = this;
uni.chooseImage({
count: 1, // 9
sizeType: ['original', 'compressed'], //
sourceType: ['album', 'camera'], //
success: (res) => {
self.src = res.tempFilePaths[0];
// datasrc
self.cropper.pushOrign(this.src);
}
});
}
}
};
</script>
<style scoped>
@import '../../libs/css/style.components.scss';
.content {
background: rgba(255, 255, 255, 1);
}
.cropper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 11;
}
.cropper-buttons {
background-color: #000000;
color: #eee;
}
.cropper-wrapper {
position: relative;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
background-color: #000;
}
.cropper-buttons {
width: 100vw;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
position: fixed;
bottom: 0;
left: 0;
font-size: 28rpx;
}
.cropper-buttons .upload,
.cropper-buttons .getCropperImage {
width: 50%;
text-align: center;
}
.cropper-buttons .upload {
text-align: left;
padding-left: 50rpx;
}
.cropper-buttons .getCropperImage {
text-align: right;
padding-right: 50rpx;
}
</style>

1265
node_modules/uview-ui/components/u-avatar-cropper/weCropper.js

File diff suppressed because it is too large

133
node_modules/uview-ui/components/u-avatar/u-avatar.vue

File diff suppressed because one or more lines are too long

147
node_modules/uview-ui/components/u-back-top/u-back-top.vue

@ -0,0 +1,147 @@
<template>
<view @tap="backToTop" class="u-back-top" :class="['u-back-top--mode--' + mode]" :style="[{
bottom: bottom + 'rpx',
right: right + 'rpx',
borderRadius: mode == 'circle' ? '10000rpx' : '8rpx',
zIndex: uZIndex,
opacity: opacity
}, customStyle]">
<view class="" v-if="!$slots.default">
<u-icon @click="backToTop" :name="icon" :custom-style="iconStyle"></u-icon>
<view class="u-back-top__tips">
{{tips}}
</view>
</view>
<slot v-else />
</view>
</template>
<script>
export default {
name: 'u-back-top',
props: {
// circle-square-
mode: {
type: String,
default: 'circle'
},
//
icon: {
type: String,
default: 'arrow-upward'
},
//
tips: {
type: String,
default: ''
},
//
duration: {
type: [Number, String],
default: 100
},
//
scrollTop: {
type: [Number, String],
default: 0
},
// rpx
top: {
type: [Number, String],
default: 400
},
// rpx
bottom: {
type: [Number, String],
default: 200
},
// rpx
right: {
type: [Number, String],
default: 40
},
//
zIndex: {
type: [Number, String],
default: '9'
},
//
iconStyle: {
type: Object,
default() {
return {
color: '#909399',
fontSize: '38rpx'
}
}
},
//
customStyle: {
type: Object,
default() {
return {}
}
}
},
watch: {
showBackTop(nVal, oVal) {
//
// v-if
if(nVal) {
this.uZIndex = this.zIndex;
this.opacity = 1;
} else {
this.uZIndex = -1;
this.opacity = 0;
}
}
},
computed: {
showBackTop() {
// scrollToppxtop(rpx)
// px
return this.scrollTop > uni.upx2px(this.top);
},
},
data() {
return {
//
opacity: 0,
// z-index-1
uZIndex: -1
}
},
methods: {
backToTop() {
uni.pageScrollTo({
scrollTop: 0,
duration: this.duration
});
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-back-top {
width: 80rpx;
height: 80rpx;
position: fixed;
z-index: 9;
display: flex;
flex-direction: column;
justify-content: center;
background-color: #E1E1E1;
color: $u-content-color;
align-items: center;
transition: opacity 0.4s;
&__tips {
font-size: 24rpx;
transform: scale(0.8);
line-height: 1;
}
}
</style>

213
node_modules/uview-ui/components/u-badge/u-badge.vue

@ -0,0 +1,213 @@
<template>
<view v-if="show" class="u-badge" :class="[
isDot ? 'u-badge-dot' : '',
size == 'mini' ? 'u-badge-mini' : '',
type ? 'u-badge--bg--' + type : ''
]" :style="[{
top: offset[0] + 'rpx',
right: offset[1] + 'rpx',
fontSize: fontSize + 'rpx',
position: absolute ? 'absolute' : 'static',
color: color,
backgroundColor: bgColor
}, boxStyle]"
>
{{showText}}
</view>
</template>
<script>
/**
* badge 角标
* @description 本组件一般用于展示头像的地方如个人中心或者评论列表页的用户头像展示等场所
* @tutorial https://www.uviewui.com/components/badge.html
* @property {String Number} count 展示的数字大于 overflowCount 时显示为 ${overflowCount}+为0且show-zero为false时隐藏
* @property {Boolean} is-dot 不展示数字只有一个小点默认false
* @property {Boolean} absolute 组件是否绝对定位为true时offset参数才有效默认true
* @property {String Number} overflow-count 展示封顶的数字值默认99
* @property {String} type 使用预设的背景颜色默认error
* @property {Boolean} show-zero 当数值为 0 是否展示 Badge默认false
* @property {String} size Badge的尺寸设为mini会得到小一号的Badge默认default
* @property {Array} offset 设置badge的位置偏移格式为 [x, y]也即设置的为top和right的值单位rpxabsolute为true时有效默认[20, 20]
* @property {String} color 字体颜色默认#ffffff
* @property {String} bgColor 背景颜色优先级比type高如设置type参数会失效
* @property {Boolean} is-center 组件中心点是否和父组件右上角重合优先级比offset高如设置offset参数会失效默认false
* @example <u-badge type="error" count="7"></u-badge>
*/
export default {
name: 'u-badge',
props: {
// primary,warning,success,error,info
type: {
type: String,
default: 'error'
},
// default, mini
size: {
type: String,
default: 'default'
},
//
isDot: {
type: Boolean,
default: false
},
//
count: {
type: [Number, String],
},
//
overflowCount: {
type: Number,
default: 99
},
// 0 Badge
showZero: {
type: Boolean,
default: false
},
//
offset: {
type: Array,
default: () => {
return [20, 20]
}
},
// offset
absolute: {
type: Boolean,
default: true
},
//
fontSize: {
type: [String, Number],
default: '24'
},
//
color: {
type: String,
default: '#ffffff'
},
// badge
bgColor: {
type: String,
default: ''
},
// badgeoffset
isCenter: {
type: Boolean,
default: false
}
},
computed: {
// badge
boxStyle() {
let style = {};
if(this.isCenter) {
style.top = 0;
style.right = 0;
// Y-50%badgebadgeX50%
style.transform = "translateY(-50%) translateX(50%)";
} else {
style.top = this.offset[0] + 'rpx';
style.right = this.offset[1] + 'rpx';
style.transform = "translateY(0) translateX(0)";
}
// miniscal()
if(this.size == 'mini') {
style.transform = style.transform + " scale(0.8)";
}
return style;
},
// isDot
showText() {
if(this.isDot) return '';
else {
if(this.count > this.overflowCount) return `${this.overflowCount}+`;
else return this.count;
}
},
//
show() {
// count0showZerofalse
if(this.count == 0 && this.showZero == false) return false;
else return true;
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-badge {
display: inline-flex;
justify-content: center;
align-items: center;
line-height: 24rpx;
padding: 4rpx 8rpx;
border-radius: 100rpx;
&--bg--primary {
background-color: $u-type-primary;
}
&--bg--error {
background-color: $u-type-error;
}
&--bg--success {
background-color: $u-type-success;
}
&--bg--info {
background-color: $u-type-info;
}
&--bg--warning {
background-color: $u-type-warning;
}
}
.u-badge-dot {
height: 16rpx;
width: 16rpx;
border-radius: 100rpx;
line-height: 1;
}
.u-badge-mini {
transform: scale(0.8);
transform-origin: center center;
}
// .u-primary {
// background: $u-type-primary;
// color: #fff;
// }
// .u-error {
// background: $u-type-error;
// color: #fff;
// }
// .u-warning {
// background: $u-type-warning;
// color: #fff;
// }
// .u-success {
// background: $u-type-success;
// color: #fff;
// }
// .u-black {
// background: #585858;
// color: #fff;
// }
.u-info {
background: $u-type-info;
color: #fff;
}
</style>

567
node_modules/uview-ui/components/u-button/u-button.vue

@ -0,0 +1,567 @@
<template>
<button
id="u-wave-btn"
class="u-btn u-line-1 u-fix-ios-appearance"
:class="[
'u-size-' + size,
plain ? 'u-btn--' + type + '--plain' : '',
loading ? 'u-loading' : '',
shape == 'circle' ? 'u-round-circle' : '',
hairLine ? showHairLineBorder : 'u-btn--bold-border',
'u-btn--' + type,
disabled ? `u-btn--${type}--disabled` : '',
]"
:disabled="disabled"
:form-type="formType"
:open-type="openType"
:app-parameter="appParameter"
:hover-stop-propagation="hoverStopPropagation"
:send-message-title="sendMessageTitle"
send-message-path="sendMessagePath"
:lang="lang"
:data-name="dataName"
:session-from="sessionFrom"
:send-message-img="sendMessageImg"
:show-message-card="showMessageCard"
@getphonenumber="getphonenumber"
@getuserinfo="getuserinfo"
@error="error"
@opensetting="opensetting"
@launchapp="launchapp"
:style="[customStyle]"
@tap.stop="click($event)"
:hover-class="getHoverClass"
:loading="loading"
>
<slot></slot>
<view
v-if="ripple"
class="u-wave-ripple"
:class="[waveActive ? 'u-wave-active' : '']"
:style="{
top: rippleTop + 'px',
left: rippleLeft + 'px',
width: fields.targetWidth + 'px',
height: fields.targetWidth + 'px',
'background-color': rippleBgColor || 'rgba(0, 0, 0, 0.15)'
}"
></view>
</button>
</template>
<script>
/**
* button 按钮
* @description Button 按钮
* @tutorial https://www.uviewui.com/components/button.html
* @property {String} size 按钮的大小
* @property {Boolean} ripple 是否开启点击水波纹效果
* @property {String} ripple-bg-color 水波纹的背景色ripple为true时有效
* @property {String} type 按钮的样式类型
* @property {Boolean} plain 按钮是否镂空背景色透明
* @property {Boolean} disabled 是否禁用
* @property {Boolean} hair-line 是否显示按钮的细边框(默认true)
* @property {Boolean} shape 按钮外观形状见文档说明
* @property {Boolean} loading 按钮名称前是否带 loading 图标(App-nvue 平台 ios 上为雪花Android上为圆圈)
* @property {String} form-type 用于 <form> 组件点击分别会触发 <form> 组件的 submit/reset 事件
* @property {String} open-type 开放能力
* @property {String} hover-class 指定按钮按下去的样式类 hover-class="none" 没有点击态效果(App-nvue 平台暂不支持)
* @property {Number} hover-start-time 按住后多久出现点击态单位毫秒
* @property {Number} hover-stay-time 手指松开后点击态保留时间单位毫秒
* @property {Object} custom-style 对按钮的自定义样式对象形式见文档说明
* @event {Function} click 按钮点击
* @event {Function} getphonenumber open-type="getPhoneNumber"时有效
* @event {Function} getuserinfo 用户点击该按钮时会返回获取到的用户信息从返回参数的detail中获取到的值同uni.getUserInfo
* @event {Function} error 当使用开放能力时发生错误的回调
* @event {Function} opensetting 在打开授权设置页并关闭后回调
* @event {Function} launchapp 打开 APP 成功的回调
* @example <u-button>月落</u-button>
*/
export default {
name: 'u-button',
props: {
//
hairLine: {
type: Boolean,
default: true
},
// defaultprimaryerrorwarningsuccess
type: {
type: String,
default: 'default'
},
// defaultmediummini
size: {
type: String,
default: 'default'
},
// circlesquare
shape: {
type: String,
default: 'square'
},
//
plain: {
type: Boolean,
default: false
},
//
disabled: {
type: Boolean,
default: false
},
//
loading: {
type: Boolean,
default: false
},
// uniappbutton
// https://uniapp.dcloud.io/component/button
openType: {
type: String,
default: ''
},
// <form> <form> submit/reset
// submitreset
formType: {
type: String,
default: ''
},
// APP APP open-type=launchApp
// QQ
appParameter: {
type: String,
default: ''
},
//
hoverStopPropagation: {
type: Boolean,
default: false
},
// zh_CN zh_TW en
lang: {
type: String,
default: 'en'
},
// open-type="contact"
sessionFrom: {
type: String,
default: ''
},
// open-type="contact"
//
sendMessageTitle: {
type: String,
default: ''
},
// open-type="contact"
//
sendMessagePath: {
type: String,
default: ''
},
// open-type="contact"
//
sendMessageImg: {
type: String,
default: ''
},
// true""
// open-type="contact"
showMessageCard: {
type: Boolean,
default: false
},
//
hoverBgColor: {
type: String,
default: ''
},
//
rippleBgColor: {
type: String,
default: ''
},
//
ripple: {
type: Boolean,
default: false
},
//
hoverClass: {
type: String,
default: ''
},
//
customStyle: {
type: Object,
default() {
return {};
}
},
// data-xxxtarget.dataset.name
dataName: {
type: String,
default: ''
}
},
computed: {
// bgColor
getHoverClass() {
// hover-class
if (this.loading || this.disabled || this.ripple || this.hoverClass) return '';
let hoverClass = '';
hoverClass = this.plain ? 'u-' + this.type + '-plain-hover' : 'u-' + this.type + '-hover';
return hoverClass;
},
// 'primary', 'success', 'error', 'warning'
showHairLineBorder() {
if (['primary', 'success', 'error', 'warning'].indexOf(this.type) >= 0 && !this.plain) {
return '';
} else {
return 'u-hairline-border';
}
}
},
data() {
return {
rippleTop: 0, // Y
rippleLeft: 0, // X
fields: {}, //
waveActive: false //
};
},
methods: {
//
click(e) {
// disabledloading
if (this.loading === true || this.disabled === true) return;
//
if (this.ripple) {
//
this.waveActive = false;
this.$nextTick(function() {
this.getWaveQuery(e);
});
}
this.$emit('click');
},
//
getWaveQuery(e) {
this.getElQuery().then(res => {
//
let data = res[0];
//
if (!data.width || !data.width) return;
// (border-radius)
//
data.targetWidth = data.height > data.width ? data.height : data.width;
if (!data.targetWidth) return;
this.fields = data;
let touchesX = '',
touchesY = '';
// #ifdef MP-BAIDU
touchesX = e.changedTouches[0].clientX;
touchesY = e.changedTouches[0].clientY;
// #endif
// #ifdef MP-ALIPAY
touchesX = e.detail.clientX;
touchesY = e.detail.clientY;
// #endif
// #ifndef MP-BAIDU || MP-ALIPAY
touchesX = e.touches[0].clientX;
touchesY = e.touches[0].clientY;
// #endif
// xytouchesYdata.top
// `transform-origin`centerview
//
this.rippleTop = touchesY - data.top - data.targetWidth / 2;
this.rippleLeft = touchesX - data.left - data.targetWidth / 2;
this.$nextTick(() => {
this.waveActive = true;
});
});
},
//
getElQuery() {
return new Promise(resolve => {
let queryInfo = '';
// uniapp
// https://uniapp.dcloud.io/api/ui/nodes-info?id=nodesrefboundingclientrect
queryInfo = uni.createSelectorQuery().in(this);
//#ifdef MP-ALIPAY
queryInfo = uni.createSelectorQuery();
//#endif
queryInfo.select('.u-btn').boundingClientRect();
queryInfo.exec(data => {
resolve(data);
});
});
},
// uniapp
getphonenumber(res) {
this.$emit('getphonenumber', res);
},
getuserinfo(res) {
this.$emit('getuserinfo', res);
},
error(res) {
this.$emit('error', res);
},
opensetting(res) {
this.$emit('opensetting', res);
},
launchapp(res) {
this.$emit('launchapp', res);
}
}
};
</script>
<style scoped lang="scss">
@import '../../libs/css/style.components.scss';
.u-btn::after {
border: none;
}
.u-btn {
position: relative;
border: 0;
//border-radius: 10rpx;
display: inline-block;
overflow: hidden;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0 40rpx;
z-index: 1;
box-sizing: border-box;
transition: all 0.15s;
&--bold-border {
border: 1px solid #ffffff;
}
&--default {
color: $u-content-color;
border-color: #c0c4cc;
background-color: #ffffff;
}
&--primary {
color: #ffffff;
border-color: $u-type-primary;
background-color: $u-type-primary;
}
&--success {
color: #ffffff;
border-color: $u-type-success;
background-color: $u-type-success;
}
&--error {
color: #ffffff;
border-color: $u-type-error;
background-color: $u-type-error;
}
&--warning {
color: #ffffff;
border-color: $u-type-warning;
background-color: $u-type-warning;
}
&--default--disabled {
color: #ffffff;
border-color: #e4e7ed;
background-color: #ffffff;
}
&--primary--disabled {
color: #ffffff!important;
border-color: $u-type-primary-disabled!important;
background-color: $u-type-primary-disabled!important;
}
&--success--disabled {
color: #ffffff!important;
border-color: $u-type-success-disabled!important;
background-color: $u-type-success-disabled!important;
}
&--error--disabled {
color: #ffffff!important;
border-color: $u-type-error-disabled!important;
background-color: $u-type-error-disabled!important;
}
&--warning--disabled {
color: #ffffff!important;
border-color: $u-type-warning-disabled!important;
background-color: $u-type-warning-disabled!important;
}
&--primary--plain {
color: $u-type-primary!important;
border-color: $u-type-primary-disabled!important;
background-color: $u-type-primary-light!important;
}
&--success--plain {
color: $u-type-success!important;
border-color: $u-type-success-disabled!important;
background-color: $u-type-success-light!important;
}
&--error--plain {
color: $u-type-error!important;
border-color: $u-type-error-disabled!important;
background-color: $u-type-error-light!important;
}
&--warning--plain {
color: $u-type-warning!important;
border-color: $u-type-warning-disabled!important;
background-color: $u-type-warning-light!important;
}
}
.u-hairline-border:after {
content: ' ';
position: absolute;
pointer-events: none;
// border-boxscale0.5border-boxborder
box-sizing: border-box;
// (scale())
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
left: 0;
top: 0;
width: 199.8%;
height: 199.7%;
-webkit-transform: scale(0.5, 0.5);
transform: scale(0.5, 0.5);
border: 1px solid currentColor;
z-index: 1;
}
.u-wave-ripple {
z-index: 0;
position: absolute;
border-radius: 100%;
background-clip: padding-box;
pointer-events: none;
user-select: none;
transform: scale(0);
opacity: 1;
transform-origin: center;
}
.u-wave-ripple.u-wave-active {
opacity: 0;
transform: scale(2);
transition: opacity 1s linear, transform 0.4s linear;
}
.u-round-circle {
border-radius: 100rpx;
}
.u-round-circle::after {
border-radius: 100rpx;
}
.u-loading::after {
background-color: hsla(0, 0%, 100%, 0.35);
}
.u-size-default {
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
}
.u-size-medium {
display: inline-flex;
width: auto;
font-size: 26rpx;
height: 70rpx;
line-height: 70rpx;
padding: 0 80rpx;
}
.u-size-mini {
display: inline-flex;
width: auto;
font-size: 22rpx;
padding-top: 1px;
height: 50rpx;
line-height: 50rpx;
padding: 0 20rpx;
}
.u-primary-plain-hover {
color: #ffffff !important;
background: $u-type-primary-dark !important;
}
.u-default-plain-hover {
color: $u-type-primary-dark !important;
background: $u-type-primary-light !important;
}
.u-success-plain-hover {
color: #ffffff !important;
background: $u-type-success-dark !important;
}
.u-warning-plain-hover {
color: #ffffff !important;
background: $u-type-warning-dark !important;
}
.u-error-plain-hover {
color: #ffffff !important;
background: $u-type-error-dark !important;
}
.u-info-plain-hover {
color: #ffffff !important;
background: $u-type-info-dark !important;
}
.u-default-hover {
color: $u-type-primary-dark !important;
border-color: $u-type-primary-dark !important;
background-color: $u-type-primary-light !important;
}
.u-primary-hover {
background: $u-type-primary-dark !important;
color: #fff;
}
.u-success-hover {
background: $u-type-success-dark !important;
color: #fff;
}
.u-info-hover {
background: $u-type-info-dark !important;
color: #fff;
}
.u-warning-hover {
background: $u-type-warning-dark !important;
color: #fff;
}
.u-error-hover {
background: $u-type-error-dark !important;
color: #fff;
}
</style>

641
node_modules/uview-ui/components/u-calendar/u-calendar.vue

@ -0,0 +1,641 @@
<template>
<u-popup closeable :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto"
:safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex" :border-radius="borderRadius" :closeable="closeable">
<view class="u-calendar">
<view class="u-calendar__header">
<view class="u-calendar__header__text" v-if="!$slots['tooltip']">
{{toolTip}}
</view>
<slot v-else name="tooltip" />
</view>
<view class="u-calendar__action u-flex u-row-center">
<view class="u-calendar__action__icon">
<u-icon v-if="changeYear" name="arrow-left-double" :color="yearArrowColor" @click="changeYearHandler(0)"></u-icon>
</view>
<view class="u-calendar__action__icon">
<u-icon v-if="changeMonth" name="arrow-left" :color="monthArrowColor" @click="changeMonthHandler(0)"></u-icon>
</view>
<view class="u-calendar__action__text">{{ showTitle }}</view>
<view class="u-calendar__action__icon">
<u-icon v-if="changeMonth" name="arrow-right" :color="monthArrowColor" @click="changeMonthHandler(1)"></u-icon>
</view>
<view class="u-calendar__action__icon">
<u-icon v-if="changeYear" name="arrow-right-double" :color="yearArrowColor" @click="changeYearHandler(1)"></u-icon>
</view>
</view>
<view class="u-calendar__week-day">
<view class="u-calendar__week-day__text" v-for="(item, index) in weekDayZh" :key="index">{{item}}</view>
</view>
<view class="u-calendar__content">
<!-- 前置空白部分 -->
<block v-for="(item, index) in weekdayArr" :key="index">
<view class="u-calendar__content__item"></view>
</block>
<view class="u-calendar__content__item" :class="{
'u-hover-class':openDisAbled(year,month,index+1),
'u-calendar__content--start-date': (mode == 'range' && startDate==`${year}-${month}-${index+1}`) || mode== 'date',
'u-calendar__content--end-date':(mode== 'range' && endDate==`${year}-${month}-${index+1}`) || mode == 'date'
}" :style="{backgroundColor: getColor(index,1)}" v-for="(item, index) in daysArr" :key="index"
@tap="dateClick(index)">
<view class="u-calendar__content__item__inner" :style="{color: getColor(index,2)}">
<view>{{ index + 1 }}</view>
</view>
<view class="u-calendar__content__item__tips" :style="{color:activeColor}" v-if="mode== 'range' && startDate==`${year}-${month}-${index+1}` && startDate!=endDate">{{startText}}</view>
<view class="u-calendar__content__item__tips" :style="{color:activeColor}" v-if="mode== 'range' && endDate==`${year}-${month}-${index+1}`">{{endText}}</view>
</view>
<view class="u-calendar__content__bg-month">{{month}}</view>
</view>
<view class="u-calendar__bottom">
<view class="u-calendar__bottom__choose">
<text>{{mode == 'date' ? activeDate : startDate}}</text>
<text v-if="endDate">{{endDate}}</text>
</view>
<view class="u-calendar__bottom__btn">
<u-button :type="btnType" shape="circle" size="default" @click="btnFix(false)">确定</u-button>
</view>
</view>
</view>
</u-popup>
</template>
<script>
/**
* calendar 日历
* @description 此组件用于单个选择日期范围选择日期等日历被包裹在底部弹起的容器中
* @tutorial http://uviewui.com/components/calendar.html
* @property {String} mode 选择日期的模式date-为单个日期range-为选择日期范围
* @property {Boolean} v-model 布尔值变量用于控制日历的弹出与收起
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false)
* @property {Boolean} change-year 是否显示顶部的切换年份方向的按钮(默认true)
* @property {Boolean} change-month 是否显示顶部的切换月份方向的按钮(默认true)
* @property {String Number} max-year 可切换的最大年份(默认2050)
* @property {String Number} min-year 最小可选日期(默认1950)
* @property {String Number} min-date 可切换的最小年份(默认1950-01-01)
* @property {String Number} max-date 最大可选日期(默认当前日期)
* @property {String Number} 弹窗顶部左右两边的圆角值单位rpx(默认20)
* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭日历(默认true)
* @property {String} month-arrow-color 月份切换按钮箭头颜色(默认#606266)
* @property {String} year-arrow-color 年份切换按钮箭头颜色(默认#909399)
* @property {String} color 日期字体的默认颜色(默认#303133)
* @property {String} active-bg-color 起始/结束日期按钮的背景色(默认#2979ff)
* @property {String Number} z-index 弹出时的z-index值(默认10075)
* @property {String} active-color 起始/结束日期按钮的字体颜色(默认#ffffff)
* @property {String} range-bg-color 起始/结束日期之间的区域的背景颜色(默认rgba(41,121,255,0.13))
* @property {String} range-color 选择范围内字体颜色(默认#2979ff)
* @property {String} start-text 起始日期底部的提示文字(默认 '开始')
* @property {String} end-text 结束日期底部的提示文字(默认 '结束')
* @property {String} btn-type 底部确定按钮的主题(默认 'primary')
* @property {String} toolTip 顶部提示文字如设置名为tooltip的slot此参数将失效(默认 '选择日期')
* @property {Boolean} closeable 是否显示右上角的关闭图标(默认true)
* @example <u-calendar v-model="show" :mode="mode"></u-calendar>
*/
export default {
name: 'u-calendar',
props: {
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// Picker
maskCloseAble: {
type: Boolean,
default: true
},
//
value: {
type: Boolean,
default: false
},
// z-index
zIndex: {
type: [String, Number],
default: 0
},
//
changeYear: {
type: Boolean,
default: true
},
//
changeMonth: {
type: Boolean,
default: true
},
// date-range-+
mode: {
type: String,
default: 'date'
},
//
maxYear: {
type: [Number, String],
default: 2050
},
//
minYear: {
type: [Number, String],
default: 1950
},
// ()
minDate: {
type: [Number, String],
default: '1950-01-01'
},
/**
* 最大可选日期
* 默认最大值为今天之后的日期不可选
* 2030-12-31
* */
maxDate: {
type: [Number, String],
default: ''
},
//
borderRadius: {
type: [String, Number],
default: 20
},
//
monthArrowColor: {
type: String,
default: '#606266'
},
//
yearArrowColor: {
type: String,
default: '#909399'
},
//
color: {
type: String,
default: '#303133'
},
// |
activeBgColor: {
type: String,
default: '#2979ff'
},
// |
activeColor: {
type: String,
default: '#ffffff'
},
//
rangeBgColor: {
type: String,
default: 'rgba(41,121,255,0.13)'
},
//
rangeColor: {
type: String,
default: '#2979ff'
},
// mode=range
startText: {
type: String,
default: '开始'
},
// mode=range
endText: {
type: String,
default: '结束'
},
//
btnType: {
type: String,
default: 'primary'
},
//
isActiveCurrent: {
type: Boolean,
default: true
},
// mode=date
isChange: {
type: Boolean,
default: false
},
//
closeable: {
type: Boolean,
default: true
},
//
toolTip: {
type: String,
default: '选择日期'
}
},
data() {
return {
// ,1-7
weekday: 1,
weekdayArr:[],
//
days: 0,
daysArr:[],
showTitle: '',
year: 2020,
month: 0,
day: 0,
startYear: 0,
startMonth: 0,
startDay: 0,
endYear: 0,
endMonth: 0,
endDay: 0,
today: '',
activeDate: '',
startDate: '',
endDate: '',
isStart: true,
min: null,
max: null,
weekDayZh: ['日', '一', '二', '三', '四', '五', '六']
};
},
computed: {
dataChange() {
return `${this.mode}-${this.minDate}-${this.maxDate}`;
},
uZIndex() {
// z-index使
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
watch: {
dataChange(val) {
this.init()
}
},
created() {
this.init()
},
methods: {
getColor(index, type) {
let color = type == 1 ? '' : this.color;
let day = index + 1
let date = `${this.year}-${this.month}-${day}`
let timestamp = new Date(date.replace(/\-/g, '/')).getTime();
let start = this.startDate.replace(/\-/g, '/')
let end = this.endDate.replace(/\-/g, '/')
if ((this.isActiveCurrent && this.activeDate == date) || this.startDate == date || this.endDate == date) {
color = type == 1 ? this.activeBgColor : this.activeColor;
} else if (this.endDate && timestamp > new Date(start).getTime() && timestamp < new Date(end).getTime()) {
color = type == 1 ? this.rangeBgColor : this.rangeColor;
}
return color;
},
init() {
let now = new Date();
this.year = now.getFullYear();
this.month = now.getMonth() + 1;
this.day = now.getDate();
this.today = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;
this.activeDate = this.today;
this.min = this.initDate(this.minDate);
this.max = this.initDate(this.maxDate || this.today);
this.startDate = "";
this.startYear = 0;
this.startMonth = 0;
this.startDay = 0;
this.endYear = 0;
this.endMonth = 0;
this.endDay = 0;
this.endDate = "";
this.isStart = true;
this.changeData();
},
//
initDate(date) {
let fdate = date.split('-');
return {
year: Number(fdate[0] || 1920),
month: Number(fdate[1] || 1),
day: Number(fdate[2] || 1)
}
},
openDisAbled: function(year, month, day) {
let bool = true;
let date = `${year}/${month}/${day}`;
// let today = this.today.replace(/\-/g, '/');
let min = `${this.min.year}/${this.min.month}/${this.min.day}`;
let max = `${this.max.year}/${this.max.month}/${this.max.day}`;
let timestamp = new Date(date).getTime();
if (timestamp >= new Date(min).getTime() && timestamp <= new Date(max).getTime()) {
bool = false;
}
return bool;
},
generateArray: function(start, end) {
return Array.from(new Array(end + 1).keys()).slice(start);
},
formatNum: function(num) {
return num < 10 ? '0' + num : num + '';
},
//
getMonthDay(year, month) {
let days = new Date(year, month, 0).getDate();
return days;
},
getWeekday(year, month) {
let date = new Date(`${year}/${month}/01 00:00:00`);
return date.getDay();
},
checkRange(year) {
let overstep = false;
if (year < this.minYear || year > this.maxYear) {
uni.showToast({
title: "日期超出范围啦~",
icon: 'none'
})
overstep = true;
}
return overstep;
},
changeMonthHandler(isAdd) {
if (isAdd) {
let month = this.month + 1;
let year = month > 12 ? this.year + 1 : this.year;
if (!this.checkRange(year)) {
this.month = month > 12 ? 1 : month;
this.year = year;
this.changeData();
}
} else {
let month = this.month - 1;
let year = month < 1 ? this.year - 1 : this.year;
if (!this.checkRange(year)) {
this.month = month < 1 ? 12 : month;
this.year = year;
this.changeData();
}
}
},
changeYearHandler(isAdd) {
let year = isAdd ? this.year + 1 : this.year - 1;
if (!this.checkRange(year)) {
this.year = year;
this.changeData();
}
},
changeData() {
this.days = this.getMonthDay(this.year, this.month);
this.daysArr=this.generateArray(1,this.days)
this.weekday = this.getWeekday(this.year, this.month);
this.weekdayArr=this.generateArray(1,this.weekday)
this.showTitle = `${this.year}${this.month}`;
if (this.isChange && this.mode == 'date') {
this.btnFix(true);
}
},
dateClick: function(day) {
day += 1;
if (!this.openDisAbled(this.year, this.month, day)) {
this.day = day;
let date = `${this.year}-${this.month}-${day}`;
if (this.mode == 'date') {
this.activeDate = date;
} else {
let compare = new Date(date.replace(/\-/g, '/')).getTime() < new Date(this.startDate.replace(/\-/g, '/')).getTime()
if (this.isStart || compare) {
this.startDate = date;
this.startYear = this.year;
this.startMonth = this.month;
this.startDay = this.day;
this.endYear = 0;
this.endMonth = 0;
this.endDay = 0;
this.endDate = "";
this.activeDate = "";
this.isStart = false;
} else {
this.endDate = date;
this.endYear = this.year;
this.endMonth = this.month;
this.endDay = this.day;
this.isStart = true;
}
}
}
},
close() {
// v-modelfalse
this.$emit('input', false);
},
getWeekText(date) {
date = new Date(`${date.replace(/\-/g, '/')} 00:00:00`);
let week = date.getDay();
return '星期' + ['日', '一', '二', '三', '四', '五', '六'][week];
},
btnFix(show) {
if (!show) {
this.close();
}
if (this.mode == 'date') {
let arr = this.activeDate.split('-')
let year = this.isChange ? this.year : Number(arr[0]);
let month = this.isChange ? this.month : Number(arr[1]);
let day = this.isChange ? this.day : Number(arr[2]);
//
let days = this.getMonthDay(year, month);
let result = `${year}-${this.formatNum(month)}-${this.formatNum(day)}`;
let weekText = this.getWeekText(result);
let isToday = false;
if (`${year}-${month}-${day}` == this.today) {
//
isToday = true;
}
this.$emit('change', {
year: year,
month: month,
day: day,
days: days,
result: result,
week: weekText,
isToday: isToday,
// switch: show //
});
} else {
if (!this.startDate || !this.endDate) return;
let startMonth = this.formatNum(this.startMonth);
let startDay = this.formatNum(this.startDay);
let startDate = `${this.startYear}-${startMonth}-${startDay}`;
let startWeek = this.getWeekText(startDate)
let endMonth = this.formatNum(this.endMonth);
let endDay = this.formatNum(this.endDay);
let endDate = `${this.endYear}-${endMonth}-${endDay}`;
let endWeek = this.getWeekText(endDate);
this.$emit('change', {
startYear: this.startYear,
startMonth: this.startMonth,
startDay: this.startDay,
startDate: startDate,
startWeek: startWeek,
endYear: this.endYear,
endMonth: this.endMonth,
endDay: this.endDay,
endDate: endDate,
endWeek: endWeek
});
}
}
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-calendar {
color: $u-content-color;
&__header {
width: 100%;
box-sizing: border-box;
font-size: 30rpx;
background-color: #fff;
color: $u-main-color;
&__text {
margin-top: 30rpx;
padding: 0 60rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
&__action {
padding: 40rpx 0 40rpx 0;
&__icon {
margin: 0 16rpx;
}
&__text {
padding: 0 16rpx;
color: $u-main-color;
font-size: 32rpx;
line-height: 32rpx;
font-weight: bold;
}
}
&__week-day {
display: flex;
align-items: center;
justify-content: center;
padding: 6px 0;
overflow: hidden;
&__text {
flex: 1;
text-align: center;
}
}
&__content {
width: 100%;
display: flex;
flex-wrap: wrap;
padding: 6px 0;
box-sizing: border-box;
background-color: #fff;
position: relative;
&--end-date {
border-top-right-radius: 8rpx;
border-bottom-right-radius: 8rpx;
}
&--start-date {
border-top-left-radius: 8rpx;
border-bottom-left-radius: 8rpx;
}
&__item {
width: 14.2857%;
display: flex;
align-items: center;
justify-content: center;
padding: 6px 0;
overflow: hidden;
position: relative;
z-index: 2;
&__inner {
height: 84rpx;
display: -webkit-box;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
font-size: 32rpx;
position: relative;
border-radius: 50%;
&__desc {
width: 100%;
font-size: 24rpx;
line-height: 24rpx;
transform: scale(0.75);
transform-origin: center center;
position: absolute;
left: 0;
text-align: center;
bottom: 2rpx;
}
}
&__tips {
width: 100%;
font-size: 24rpx;
line-height: 24rpx;
position: absolute;
left: 0;
transform: scale(0.8);
transform-origin: center center;
text-align: center;
bottom: 8rpx;
z-index: 2;
}
}
&__bg-month {
position: absolute;
font-size: 130px;
line-height: 130px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: #e4e7ed;
z-index: 1;
}
}
&__bottom {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: #fff;
padding: 0 40rpx 30rpx;
box-sizing: border-box;
font-size: 24rpx;
color: $u-tips-color;
&__choose {
height: 50rpx;
}
&__btn {
width: 100%;
}
}
}
</style>

254
node_modules/uview-ui/components/u-car-keyboard/u-car-keyboard.vue

@ -0,0 +1,254 @@
<template>
<view class="u-keyboard" @touchmove.stop.prevent>
<view class="u-keyboard-grids">
<block>
<view class="u-keyboard-grids-item" v-for="(group, i) in abc ? EngKeyBoardList : areaList" :key="i">
<view :hover-stay-time="100" @tap="carInputClick(i, j)" hover-class="u-carinput-hover" class="u-keyboard-grids-btn"
v-for="(item, j) in group" :key="j">
{{ item }}
</view>
</view>
<view @touchstart="backspaceClick" @touchend="clearTimer" :hover-stay-time="100" class="u-keyboard-back"
hover-class="u-hover-class">
<u-icon :size="38" name="backspace" :bold="true"></u-icon>
</view>
<view :hover-stay-time="100" class="u-keyboard-change" hover-class="u-carinput-hover" @tap="changeCarInputMode">
<text class="zh" :class="[!abc ? 'active' : 'inactive']"></text>
/
<text class="en" :class="[abc ? 'active' : 'inactive']"></text>
</view>
</block>
</view>
</view>
</template>
<script>
export default {
name: "u-keyboard",
props: {
//
random: {
type: Boolean,
default: false
}
},
data() {
return {
// abc=truebac=false
abc: false
};
},
computed: {
areaList() {
let data = [
'京',
'沪',
'粤',
'津',
'冀',
'豫',
'云',
'辽',
'黑',
'湘',
'皖',
'鲁',
'苏',
'浙',
'赣',
'鄂',
'桂',
'甘',
'晋',
'陕',
'蒙',
'吉',
'闽',
'贵',
'渝',
'川',
'青',
'琼',
'宁',
'挂',
'藏',
'港',
'澳',
'新',
'使',
'学'
];
let tmp = [];
//
if (this.random) data = this.$u.randomArray(data);
//
tmp[0] = data.slice(0, 10);
tmp[1] = data.slice(10, 20);
tmp[2] = data.slice(20, 30);
tmp[3] = data.slice(30, 36);
return tmp;
},
EngKeyBoardList() {
let data = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
0,
'Q',
'W',
'E',
'R',
'T',
'Y',
'U',
'I',
'O',
'P',
'A',
'S',
'D',
'F',
'G',
'H',
'J',
'K',
'L',
'Z',
'X',
'C',
'V',
'B',
'N',
'M'
];
let tmp = [];
if (this.random) data = this.$u.randomArray(data);
tmp[0] = data.slice(0, 10);
tmp[1] = data.slice(10, 20);
tmp[2] = data.slice(20, 30);
tmp[3] = data.slice(30, 36);
return tmp;
}
},
methods: {
//
carInputClick(i, j) {
let value = '';
//
if (this.abc) value = this.EngKeyBoardList[i][j];
else value = this.areaList[i][j];
this.$emit('change', value);
},
// |
changeCarInputMode() {
this.abc = !this.abc;
},
// 退
backspaceClick() {
this.$emit('backspace');
clearInterval(this.timer); //
this.timer = null;
this.timer = setInterval(() => {
this.$emit('backspace');
}, 250);
},
clearTimer() {
clearInterval(this.timer);
this.timer = null;
},
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-keyboard-grids {
background: rgb(215, 215, 217);
padding: 24rpx 0;
position: relative;
}
.u-keyboard-grids-item {
display: flex;
align-items: center;
justify-content: center;
}
.u-keyboard-grids-btn {
text-decoration: none;
width: 62rpx;
flex: 0 0 64rpx;
height: 80rpx;
display: inline-block;
font-size: 36rpx;
text-align: center;
line-height: 80rpx;
background-color: #fff;
margin: 8rpx 5rpx;
border-radius: 8rpx;
box-shadow: 0 2rpx 0rpx #888992;
font-weight: 500;
}
.u-carinput-hover {
background-color: rgb(185, 188, 195) !important;
}
.u-keyboard-back {
position: absolute;
width: 96rpx;
right: 22rpx;
bottom: 32rpx;
height: 80rpx;
background-color: rgb(185, 188, 195);
display: flex;
align-items: center;
border-radius: 8rpx;
justify-content: center;
box-shadow: 0 2rpx 0rpx #888992;
}
.u-keyboard-change {
font-size: 24rpx;
box-shadow: 0 2rpx 0rpx #888992;
position: absolute;
width: 96rpx;
left: 22rpx;
line-height: 1;
bottom: 32rpx;
height: 80rpx;
background-color: #ffffff;
display: flex;
align-items: center;
border-radius: 8rpx;
justify-content: center;
}
.u-keyboard-change .inactive.zh {
transform: scale(0.85) translateY(-10rpx);
}
.u-keyboard-change .inactive.en {
transform: scale(0.85) translateY(10rpx);
}
.u-keyboard-change .active {
color: rgb(237, 112, 64);
font-size: 30rpx;
}
.u-keyboard-change .zh {
transform: translateY(-10rpx);
}
.u-keyboard-change .en {
transform: translateY(10rpx);
}
</style>

291
node_modules/uview-ui/components/u-card/u-card.vue

@ -0,0 +1,291 @@
<template>
<view
class="u-card"
@tap.stop="click"
:class="{ 'u-border': border, 'u-card-full': full, 'u-card--border': borderRadius > 0 }"
:style="{
borderRadius: borderRadius + 'rpx',
margin: margin
}"
>
<view
v-if="showHead"
class="u-card__head"
:style="[{padding: padding + 'rpx'}, headStyle]"
:class="{
'u-border-bottom': headBorderBottom
}"
@tap="headClick"
>
<view v-if="!$slots.head" class="u-flex u-row-between">
<view class="u-card__head--left u-flex u-line-1" v-if="title">
<image
:src="thumb"
class="u-card__head--left__thumb"
mode="aspectfull"
v-if="thumb"
:style="{
height: thumbWidth + 'rpx',
width: thumbWidth + 'rpx',
borderRadius: thumbCircle ? '100rpx' : '6rpx'
}"
></image>
<text
class="u-card__head--left__title u-line-1"
:style="{
fontSize: titleSize + 'rpx',
color: titleColor
}"
>
{{ title }}
</text>
</view>
<view class="u-card__head--right u-line-1" v-if="subTitle">
<text
class="u-card__head__title__text"
:style="{
fontSize: subTitleSize + 'rpx',
color: subTitleColor
}"
>
{{ subTitle }}
</text>
</view>
</view>
<slot name="head" v-else />
</view>
<view @tap="bodyClick" class="u-card__body" :style="[{padding: padding + 'rpx'}, bodyStyle]"><slot name="body" /></view>
<view
v-if="showFoot"
class="u-card__foot"
@tap="footClick"
:style="[{padding: $slots.foot ? padding + 'rpx' : 0}, footStyle]"
:class="{
'u-border-top': footBorderTop
}"
>
<slot name="foot" />
</view>
</view>
</template>
<script>
/**
* card 卡片
* @description 卡片组件一般用于多个列表条目且风格统一的场景
* @tutorial https://www.uviewui.com/components/line.html
* @property {Boolean} full 卡片与屏幕两侧是否留空隙默认false
* @property {String} title 头部左边的标题
* @property {String} title-color 标题颜色默认#303133
* @property {String | Number} title-size 标题字体大小单位rpx默认30
* @property {String} sub-title 头部右边的副标题
* @property {String} sub-title-color 副标题颜色默认#909399
* @property {String | Number} sub-title-size 副标题字体大小默认26
* @property {Boolean} border 是否显示边框默认true
* @property {String | Number} index 用于标识点击了第几个卡片
* @property {String} margin 卡片与屏幕两边和上下元素的间距需带单位"30rpx 20rpx"默认30rpx
* @property {String | Number} border-radius 卡片整体的圆角值单位rpx默认16
* @property {Object} head-style 头部自定义样式对象形式
* @property {Object} body-style 中部自定义样式对象形式
* @property {Object} foot-style 底部自定义样式对象形式
* @property {Boolean} head-border-bottom 是否显示头部的下边框默认true
* @property {Boolean} foot-border-top 是否显示底部的上边框默认true
* @property {Boolean} show-head 是否显示头部默认true
* @property {Boolean} show-head 是否显示尾部默认true
* @property {String} thumb 缩略图路径如设置将显示在标题的左边不建议使用相对路径
* @property {String | Number} thumb-width 缩略图的宽度高等于宽单位rpx默认60
* @property {Boolean} thumb-circle 缩略图是否为圆形默认false
* @event {Function} click 整个卡片任意位置被点击时触发
* @event {Function} head-click 卡片头部被点击时触发
* @event {Function} body-click 卡片主体部分被点击时触发
* @event {Function} foot-click 卡片底部部分被点击时触发
* @example <u-card padding="30" title="card"></u-card>
*/
export default {
name: 'u-card',
props: {
//
full: {
type: Boolean,
default: false
},
//
title: {
type: String,
default: ''
},
//
titleColor: {
type: String,
default: '#303133'
},
// rpx
titleSize: {
type: [Number, String],
default: '30'
},
//
subTitle: {
type: String,
default: ''
},
//
subTitleColor: {
type: String,
default: '#909399'
},
// rpx
subTitleSize: {
type: [Number, String],
default: '26'
},
// full=false()
border: {
type: Boolean,
default: true
},
//
index: {
type: [Number, String, Object],
default: ''
},
// "30rpx 30rpx""20rpx 20rpx 30rpx 30rpx"
margin: {
type: String,
default: '30rpx'
},
// card
borderRadius: {
type: [Number, String],
default: '16'
},
//
headStyle: {
type: Object,
default() {
return {};
}
},
//
bodyStyle: {
type: Object,
default() {
return {};
}
},
//
footStyle: {
type: Object,
default() {
return {};
}
},
//
headBorderBottom: {
type: Boolean,
default: true
},
//
footBorderTop: {
type: Boolean,
default: true
},
//
thumb: {
type: String,
default: ''
},
// rpx
thumbWidth: {
type: [String, Number],
default: '60'
},
//
thumbCircle: {
type: Boolean,
default: false
},
// headbodyfoot
padding: {
type: [String, Number],
default: '30'
},
//
showHead: {
type: Boolean,
default: true
},
//
showFoot: {
type: Boolean,
default: true
}
},
data() {
return {};
},
methods: {
click() {
this.$emit('click', this.index);
},
headClick() {
this.$emit('head-click', this.index);
},
bodyClick() {
this.$emit('body-click', this.index);
},
footClick() {
this.$emit('foot-click', this.index);
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-card {
position: relative;
overflow: hidden;
font-size: 28rpx;
background-color: #ffffff;
box-sizing: border-box;
&-full {
// 0
margin-left: 0 !important;
margin-right: 0 !important;
}
&--border:after {
border-radius: 16rpx;
}
&__head {
&--left {
color: $u-main-color;
&__thumb {
margin-right: 16rpx;
}
&__title {
max-width: 400rpx;
}
}
&--right {
color: $u-tips-color;
margin-left: 6rpx;
}
}
&__body {
color: $u-content-color;
}
&__foot {
color: $u-tips-color;
}
}
</style>

69
node_modules/uview-ui/components/u-cell-group/u-cell-group.vue

@ -0,0 +1,69 @@
<template>
<view class="u-cell-box">
<view class="u-cell-title" v-if="title" :style="[titleStyle]">
{{title}}
</view>
<view class="u-cell-item-box" :class="{'u-border-bottom u-border-top': border}">
<slot />
</view>
</view>
</template>
<script>
/**
* cellGroup 单元格父组件Group
* @description cell单元格一般用于一组列表的情况比如个人中心页设置页等搭配u-cell-item
* @tutorial https://www.uviewui.com/components/cell.html
* @property {String} title 分组标题
* @property {Boolean} border 是否显示外边框默认true
* @property {Object} title-style 分组标题的的样式对象形式{'font-size': '24rpx'} {'fontSize': '24rpx'}
* @example <u-cell-group title="设置喜好">
*/
export default {
name: "u-cell-group",
props: {
//
title: {
type: String,
default: ''
},
// list
border: {
type: Boolean,
default: true
},
//
// {'font-size': '24rpx'} {'fontSize': '24rpx'}
titleStyle: {
type: Object,
default () {
return {};
}
}
},
data() {
return {
index: 0,
}
},
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-cell-box {
width: 100%;
}
.u-cell-title {
padding: 30rpx 32rpx 10rpx 32rpx;
font-size: 30rpx;
text-align: left;
color: $u-tips-color;
}
.u-cell-item-box {
background-color: #FFFFFF;
}
</style>

300
node_modules/uview-ui/components/u-cell-item/u-cell-item.vue

@ -0,0 +1,300 @@
<template>
<view
@tap="click"
class="u-cell"
:class="{ 'u-border-bottom': borderBottom, 'u-border-top': borderTop, 'u-col-center': center, 'u-cell--required': required }"
hover-stay-time="150"
:hover-class="hoverClass"
:style="{
backgroundColor: bgColor
}"
>
<u-icon :size="iconSize" :name="icon" v-if="icon" :custom-style="iconStyle" class="u-cell__left-icon-wrap"></u-icon>
<view class="u-flex" v-else>
<slot name="icon"></slot>
</view>
<view
class="u-cell_title"
:style="[
{
width: titleWidth ? titleWidth + 'rpx' : 'auto'
},
titleStyle
]"
>
<block v-if="title">{{ title }}</block>
<slot name="title" v-else></slot>
<view class="u-cell__label" v-if="label || $slots.label" :style="[labelStyle]">
<block v-if="label">{{ label }}</block>
<slot name="label" v-else></slot>
</view>
</view>
<view class="u-cell__value" :style="[valueStyle]">
<block class="u-cell__value" v-if="value">{{ value }}</block>
<slot v-else></slot>
</view>
<u-icon v-if="arrow" name="arrow-right" :style="[arrowStyle]" class="u-icon-wrap u-cell__right-icon-wrap"></u-icon>
<view class="u-flex" v-if="$slots['right-icon']">
<slot name="right-icon"></slot>
</view>
</view>
</template>
<script>
/**
* cellItem 单元格Item
* @description cell单元格一般用于一组列表的情况比如个人中心页设置页等搭配u-cell-group使用
* @tutorial https://www.uviewui.com/components/cell.html
* @property {String} title 左侧标题
* @property {String} icon 左侧图标名只支持uView内置图标见Icon 图标
* @property {Object} icon-style 左边图标的样式对象形式
* @property {String} value 右侧内容
* @property {String} label 标题下方的描述信息
* @property {Boolean} border-bottom 是否显示cell的下边框默认true
* @property {Boolean} border-top 是否显示cell的上边框默认false
* @property {Boolean} center 是否使内容垂直居中默认false
* @property {String} hover-class 是否开启点击反馈none为无效果默认true
* // @property {Boolean} border-gap border-bottomtrueCelltrue
* @property {Boolean} arrow 是否显示右侧箭头默认true
* @property {Boolean} required 箭头方向可选值默认right
* @property {Boolean} arrow-direction 是否显示左边表示必填的星号默认false
* @property {Object} title-style 标题样式对象形式
* @property {Object} value-style 右侧内容样式对象形式
* @property {Object} label-style 标题下方描述信息的样式对象形式
* @property {String} bg-color 背景颜色默认transparent
* @property {String Number} index 用于在click事件回调中返回标识当前是第几个Item
* @property {String Number} title-width 标题的宽度单位rpx
* @example <u-cell-item icon="integral-fill" title="会员等级" value="新版本"></u-cell-item>
*/
export default {
name: 'u-cell-item',
props: {
// (uView)src
icon: {
type: String,
default: ''
},
//
title: {
type: [String, Number],
default: ''
},
//
value: {
type: [String, Number],
default: ''
},
//
label: {
type: [String, Number],
default: ''
},
//
borderBottom: {
type: Boolean,
default: true
},
//
borderTop: {
type: Boolean,
default: false
},
// cellcell线线
// 1.4.0border-topborder-bottom
// borderGap: {
// type: Boolean,
// default: true
// },
// cellnone
hoverClass: {
type: String,
default: 'u-cell-hover'
},
//
arrow: {
type: Boolean,
default: true
},
//
center: {
type: Boolean,
default: false
},
//
required: {
type: Boolean,
default: false
},
// rpx
titleWidth: {
type: [Number, String],
default: ''
},
// right|up|downright
arrowDirection: {
type: String,
default: 'right'
},
//
titleStyle: {
type: Object,
default() {
return {};
}
},
//
valueStyle: {
type: Object,
default() {
return {};
}
},
//
labelStyle: {
type: Object,
default() {
return {};
}
},
//
bgColor: {
type: String,
default: 'transparent'
},
// cell
index: {
type: [String, Number],
default: ''
},
// 使lable
useLabelSlot: {
type: Boolean,
default: false
},
// rpxicon
iconSize: {
type: [Number, String],
default: 34
},
//
iconStyle: {
type: Object,
default() {
return {}
}
},
},
data() {
return {
};
},
computed: {
arrowStyle() {
let style = {};
if (this.arrowDirection == 'up') style.transform = 'rotate(-90deg)';
else if (this.arrowDirection == 'down') style.transform = 'rotate(90deg)';
else style.transform = 'rotate(0deg)';
return style;
}
},
methods: {
click() {
this.$emit('click', this.index);
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-cell {
position: relative;
display: flex;
box-sizing: border-box;
width: 100%;
padding: 26rpx 32rpx;
font-size: 28rpx;
line-height: 54rpx;
color: $u-content-color;
background-color: #fff;
text-align: left;
}
.u-cell_title {
font-size: 28rpx;
}
.u-cell__left-icon-wrap {
margin-right: 10rpx;
font-size: 32rpx;
}
.u-cell__right-icon-wrap {
margin-left: 10rpx;
color: #969799;
font-size: 28rpx;
}
.u-cell__left-icon-wrap,
.u-cell__right-icon-wrap {
display: flex;
align-items: center;
height: 48rpx;
}
.u-cell-border:after {
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
left: 0;
top: 0;
border-bottom: 1px solid $u-border-color;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
.u-cell-border {
position: relative;
}
.u-cell__label {
margin-top: 6rpx;
font-size: 26rpx;
line-height: 36rpx;
color: $u-tips-color;
word-wrap: break-word;
}
.u-cell__value {
overflow: hidden;
text-align: right;
vertical-align: middle;
color: $u-tips-color;
font-size: 26rpx;
}
.u-cell__title,
.u-cell__value {
flex: 1;
}
.u-cell--required {
overflow: visible;
display: flex;
align-items: center;
}
.u-cell--required:before {
position: absolute;
content: '*';
left: 8px;
margin-top: 4rpx;
font-size: 14px;
color: $u-type-error;
}
</style>

122
node_modules/uview-ui/components/u-checkbox-group/u-checkbox-group.vue

@ -0,0 +1,122 @@
<template>
<view class="u-checkbox-group u-clearfix">
<slot></slot>
</view>
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
/**
* checkboxGroup 开关选择器父组件Group
* @description 复选框组件一般用于需要多个选择的场景该组件功能完整使用方便
* @tutorial https://www.uviewui.com/components/checkbox.html
* @property {String Number} max 最多能选中多少个checkbox默认999
* @property {String Number} size 组件整体的大小单位rpx默认40
* @property {Boolean} disabled 是否禁用所有checkbox默认false
* @property {String Number} icon-size 图标大小单位rpx默认20
* @property {Boolean} label-disabled 是否禁止点击文本操作checkbox(默认false)
* @property {String} width 宽度需带单位
* @property {String} width 宽度需带单位
* @property {String} shape 外观形状shape-方形circle-圆形(默认circle)
* @property {Boolean} wrap 是否每个checkbox都换行默认false
* @property {String} active-color 选中时的颜色应用到所有子Checkbox组件默认#2979ff
* @event {Function} change 任一个checkbox状态发生变化时触发回调为一个对象
* @example <u-checkbox-group></u-checkbox-group>
*/
export default {
name: 'u-checkbox-group',
mixins: [Emitter],
props: {
// checkbox
max: {
type: [Number, String],
default: 999
},
// name
// value: {
// default: Array,
// default() {
// return []
// }
// },
//
disabled: {
type: Boolean,
default: false
},
//
name: {
type: [Boolean, String],
default: ''
},
//
labelDisabled: {
type: Boolean,
default: false
},
// squarecircle
shape: {
type: String,
default: 'square'
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
size: {
type: [String, Number],
default: 34
},
// checkboxu-checkbox-group
width: {
type: String,
default: 'auto'
},
// checkbox
wrap: {
type: Boolean,
default: false
},
// rpx
iconSize: {
type: [String, Number],
default: 20
},
},
data() {
return {
}
},
created() {
// childrendata
this.children = [];
},
methods: {
emitEvent() {
let values = [];
this.children.map(val => {
if(val.value) values.push(val.name);
})
this.$emit('change', values);
// checkbox
this.$nextTick(() => {
// u-form-item
this.dispatch('u-form-item', 'on-form-change', values);
});
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-checkbox-group {
/* #ifndef MP */
display: inline-flex;
flex-wrap: wrap;
/* #endif */
}
</style>

275
node_modules/uview-ui/components/u-checkbox/u-checkbox.vue

@ -0,0 +1,275 @@
<template>
<view class="u-checkbox" :style="[checkboxStyle]">
<view class="u-checkbox__icon-wrap" @tap="toggle" :class="[iconClass]" :style="[iconStyle]">
<u-icon name="checkbox-mark" :size="checkboxIconSize" :color="iconColor"/>
</view>
<view class="u-label-class u-checkbox__label" @tap="onClickLabel" :style="{
fontSize: labelSize + 'rpx'
}">
<slot />
</view>
</view>
</template>
<script>
/**
* checkbox 复选框
* @description 该组件需要搭配checkboxGroup组件使用以便用户进行操作时获得当前复选框组的选中情况
* @tutorial https://www.uviewui.com/components/checkbox.html
* @property {String Number} icon-size 图标大小单位rpx默认20
* @property {String Number} label-size label字体大小单位rpx默认28
* @property {String Number} name checkbox组件的标示符
* @property {String} shape 形状见官网说明默认circle
* @property {Boolean} disabled 是否禁用
* @property {Boolean} label-disabled 是否禁止点击文本操作checkbox
* @property {String} active-color 选中时的颜色如设置CheckboxGroup的active-color将失效
* @event {Function} change 某个checkbox状态发生变化时触发回调为一个对象
* @example <u-checkbox v-model="checked" :disabled="false">天涯</u-checkbox>
*/
export default {
name: "u-checkbox",
props: {
// checkbox
name: {
type: [String, Number],
default: ''
},
// squarecircle
shape: {
type: String,
default: ''
},
//
value: {
type: Boolean,
default: false
},
//
disabled: {
type: [Boolean, String],
default: ''
},
//
labelDisabled: {
type: [Boolean, String],
default: ''
},
// checkboxGroupactiveColor
activeColor: {
type: String,
default: ''
},
// rpx
iconSize: {
type: [String, Number],
default: ''
},
// labelrpx
labelSize: {
type: [String, Number],
default: ''
},
//
size: {
type: [String, Number],
default: ''
},
},
data() {
return {
parentDisabled: false,
newParams: {},
};
},
created() {
// provide/inject使created
this.parent = this.$u.$parent.call(this, 'u-checkbox-group');
// u-checkbox-groupthischildren
this.parent && this.parent.children.push(this);
},
computed: {
// u-checkbox-group
isDisabled() {
return this.disabled !== '' ? this.disabled : this.parent ? this.parent.disabled : false;
},
// label
isLabelDisabled() {
return this.labelDisabled !== '' ? this.labelDisabled : this.parent ? this.parent.labelDisabled : false;
},
// size34rpx
checkboxSize() {
return this.size ? this.size : (this.parent ? this.parent.size : 34);
},
// 20
checkboxIconSize() {
return this.iconSize ? this.iconSize : (this.parent ? this.parent.iconSize : 20);
},
//
elActiveColor() {
return this.activeColor ? this.activeColor : (this.parent ? this.parent.activeColor : 'primary');
},
//
elShape() {
return this.shape ? this.shape : (this.parent ? this.parent.shape : 'square');
},
iconStyle() {
let style = {};
// v-modelfalse
if (this.elActiveColor && this.value && !this.isDisabled) {
style.borderColor = this.elActiveColor;
style.backgroundColor = this.elActiveColor;
}
style.width = this.$u.addUnit(this.checkboxSize);
style.height = this.$u.addUnit(this.checkboxSize);
return style;
},
// checkbox
iconColor() {
return this.value ? '#ffffff' : 'transparent';
},
iconClass() {
let classes = [];
classes.push('u-checkbox__icon-wrap--' + this.elShape);
if (this.value == true) classes.push('u-checkbox__icon-wrap--checked');
if (this.isDisabled) classes.push('u-checkbox__icon-wrap--disabled');
if (this.value && this.isDisabled) classes.push('u-checkbox__icon-wrap--disabled--checked');
// ","
return classes.join(' ');
},
checkboxStyle() {
let style = {};
if(this.parent && this.parent.width) {
style.width = this.parent.width;
// #ifdef MP
// 使float
style.float = 'left';
// #endif
// #ifndef MP
// H5APP使flex
style.flex = `0 0 ${this.parent.width}`;
// #endif
}
if(this.parent && this.parent.wrap) {
style.width = '100%';
// #ifndef MP
// H5APP使flex100%
style.flex = '0 0 100%';
// #endif
}
return style;
}
},
methods: {
onClickLabel() {
if (!this.isLabelDisabled) {
this.setValue();
}
},
toggle() {
if (!this.isDisabled) {
this.setValue();
}
},
emitEvent() {
this.$emit('change', {
value: this.value,
name: this.name
})
// u-checkbox-group
if(this.parent && this.parent.emitEvent) this.parent.emitEvent();
},
// inputinputv-model
setValue() {
//
let checkedNum = 0;
if(this.parent && this.parent.children) {
// valuetrue1()
this.parent.children.map(val => {
if (val.value) checkedNum++;
})
}
//
if (this.value == true) {
this.$emit('input', !this.value);
// this.$emit('input')
this.$nextTick(function() {
this.emitEvent();
})
} else if ((this.parent && checkedNum < this.parent.max) || !this.parent) {
// max
this.$emit('input', !this.value);
// this.$emit('input')
this.$nextTick(function() {
this.emitEvent();
})
}
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-checkbox {
display: inline-flex;
align-items: center;
overflow: hidden;
user-select: none;
line-height: 1.8;
&__icon-wrap {
color: $u-content-color;
flex: none;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 42rpx;
height: 42rpx;
color: transparent;
text-align: center;
transition-property: color, border-color, background-color;
font-size: 20px;
border: 1px solid #c8c9cc;
transition-duration: 0.2s;
&--circle {
border-radius: 100%;
}
&--square {
border-radius: 6rpx;
}
&--checked {
color: #fff;
background-color: $u-type-primary;
border-color: $u-type-primary;
}
&--disabled {
background-color: #ebedf0;
border-color: #c8c9cc;
}
&--disabled--checked {
color: #c8c9cc !important;
}
}
&__label {
word-wrap: break-word;
margin-left: 10rpx;
margin-right: 24rpx;
color: $u-content-color;
font-size: 30rpx;
&--disabled {
color: #c8c9cc;
}
}
}
</style>

215
node_modules/uview-ui/components/u-circle-progress/u-circle-progress.vue

@ -0,0 +1,215 @@
<template>
<view
class="u-circle-progress"
:style="{
width: widthPx + 'px',
height: widthPx + 'px',
backgroundColor: bgColor
}"
>
<canvas
class="u-canvas-bg"
:canvas-id="elBgId"
:style="{
width: widthPx + 'px',
height: widthPx + 'px'
}"
></canvas>
<canvas
class="u-canvas"
:canvas-id="elId"
:style="{
width: widthPx + 'px',
height: widthPx + 'px'
}"
></canvas>
<slot></slot>
</view>
</template>
<script>
/**
* circleProgress 环形进度条
* @description 展示操作或任务的当前进度比如上传文件是一个圆形的进度条注意此组件的percent值只能动态增加不能动态减少
* @tutorial https://www.uviewui.com/components/circleProgress.html
* @property {String Number} percent 圆环进度百分比值为数值类型0-100
* @property {String} inactive-color 圆环的底色默认为灰色(该值无法动态变更)默认#ececec
* @property {String} active-color 圆环激活部分的颜色(该值无法动态变更)默认#19be6b
* @property {String Number} width 整个圆环组件的宽度高度默认等于宽度值单位rpx默认200
* @property {String Number} border-width 圆环的边框宽度单位rpx默认14
* @property {String Number} duration 整个圆环执行一圈的时间单位ms默认呢1500
* @property {String} type 如设置active-color值将会失效
* @property {String} bg-color 整个组件背景颜色默认为白色
* @example <u-circle-progress active-color="#2979ff" :percent="80"></u-circle-progress>
*/
export default {
name: 'u-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: '#19be6b'
},
// 线rpx
borderWidth: {
type: [Number, String],
default: 14
},
// rpx
width: {
type: [Number, String],
default: 200
},
// ms
duration: {
type: [Number, String],
default: 1500
},
//
type: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: '#ffffff'
}
},
data() {
return {
// #ifdef MP-WEIXIN
elBgId: 'uCircleProgressBgId', // 使this.$u.guid()id
elId: 'uCircleProgressElId',
// #endif
// #ifndef MP-WEIXIN
elBgId: this.$u.guid(), // id
elId: this.$u.guid(),
// #endif
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.percent
this.newPercent = nVal;
this.oldPercent = oVal;
setTimeout(() => {
//
//
this.drawCircleByProgress(oVal);
}, 50);
}
},
created() {
// 使
this.newPercent = this.percent;
this.oldPercent = 0;
},
computed: {
// type
circleColor() {
if (['success', 'error', 'info', 'primary', 'warning'].indexOf(this.type) >= 0) return this.$u.color[this.type];
else return this.activeColor;
}
},
mounted() {
// h5this.$nextTick()(HX2.4.7)
setTimeout(() => {
this.drawProgressBg();
this.drawCircleByProgress(this.oldPercent);
}, 50);
},
methods: {
drawProgressBg() {
let ctx = uni.createCanvasContext(this.elBgId, this);
ctx.setLineWidth(this.borderWidthPx); //
ctx.setStrokeStyle(this.inactiveColor); // 线
ctx.beginPath(); //
// (110,110)100
let radius = this.widthPx / 2;
ctx.arc(radius, radius, radius - this.borderWidthPx, 0, 2 * Math.PI, false);
ctx.stroke(); //
ctx.draw();
},
drawCircleByProgress(progress) {
// this.data使
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.circleColor);
// 100
let time = Math.floor(this.duration / 100);
// 2π100
// 312this.startAngle
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;
}
setTimeout(() => {
// time
this.drawCircleByProgress(progress);
}, time);
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-circle-progress {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
}
.u-canvas-bg {
position: absolute;
}
.u-canvas {
position: absolute;
}
</style>

128
node_modules/uview-ui/components/u-col/u-col.vue

@ -0,0 +1,128 @@
<template>
<view class="u-col" :class="[
'u-col-' + span
]" :style="{
padding: `0 ${Number(gutter)/2 + 'rpx'}`,
marginLeft: 100 / 12 * offset + '%',
flex: `0 0 ${100 / 12 * span}%`,
alignItems: uAlignItem,
justifyContent: uJustify
}" @tap.stop.prevent="click">
<slot></slot>
</view>
</template>
<script>
/**
* col 布局单元格
* @description 通过基础的 12 分栏迅速简便地创建布局搭配<u-row>使用
* @tutorial https://www.uviewui.com/components/layout.html
* @property {String Number} span 栅格占据的列数总12等分默认0
* @property {String Number} offset 分栏左边偏移计算方式与span相同默认0
* @example <u-col span="3"><view class="demo-layout bg-purple"></view></u-col>
*/
export default {
name: "u-col",
props: {
// 12
span: {
type: [Number, String],
default: 12
},
// (12)
offset: {
type: [Number, String],
default: 0
},
// `start`(`flex-start`)`end`(`flex-end`)`center``around`(`space-around`)`between`(`space-between`)
justify: {
type: String,
default: 'start'
},
// topcenterbottom
align: {
type: String,
default: 'center'
}
},
inject: ['gutter'],
computed: {
uJustify() {
if (this.justify == 'end' || this.justify == 'start') return 'flex-' + this.justify;
else if (this.justify == 'around' || this.justify == 'between') return 'space-' + this.justify;
else return this.justify;
},
uAlignItem() {
if (this.align == 'top') return 'flex-start';
if (this.align == 'bottom') return 'flex-end';
else return this.align;
}
},
methods: {
click() {
this.$emit('click');
}
}
}
</script>
<style lang="scss">
@import "../../libs/css/style.components.scss";
.u-col {
/* #ifdef MP-WEIXIN */
float: left;
/* #endif */
}
.u-col-0 {
width: 0;
}
.u-col-1 {
width: calc(100%/12);
}
.u-col-2 {
width: calc(100%/12 * 2);
}
.u-col-3 {
width: calc(100%/12 * 3);
}
.u-col-4 {
width: calc(100%/12 * 4);
}
.u-col-5 {
width: calc(100%/12 * 5);
}
.u-col-6 {
width: calc(100%/12 * 6);
}
.u-col-7 {
width: calc(100%/12 * 7);
}
.u-col-8 {
width: calc(100%/12 * 8);
}
.u-col-9 {
width: calc(100%/12 * 9);
}
.u-col-10 {
width: calc(100%/12 * 10);
}
.u-col-11 {
width: calc(100%/12 * 11);
}
.u-col-12 {
width: calc(100%/12 * 12);
}
</style>

206
node_modules/uview-ui/components/u-collapse-item/u-collapse-item.vue

@ -0,0 +1,206 @@
<template>
<view class="u-collapse-item" :style="[itemStyle]">
<view :hover-stay-time="200" class="u-collapse-head" @tap.stop="headClick" :hover-class="hoverClass" :style="[headStyle]">
<block v-if="!$slots['title-all']">
<view v-if="!$slots['title']" class="u-collapse-title u-line-1" :style="[{ textAlign: align ? align : 'left' },
isShow && activeStyle && !arrow ? activeStyle : '']">
{{ title }}
</view>
<slot v-else name="title" />
<view class="u-icon-wrap">
<u-icon v-if="arrow" :color="arrowColor" :class="{ 'u-arrow-down-icon-active': isShow }"
class="u-arrow-down-icon" name="arrow-down"></u-icon>
</view>
</block>
<slot v-else name="title-all" />
</view>
<view class="u-collapse-body" :style="[{
height: isShow ? height + 'px' : '0'
}]">
<view class="u-collapse-content" :id="elId" :style="[bodyStyle]">
<slot></slot>
</view>
</view>
</view>
</template>
<script>
/**
* collapseItem 手风琴Item
* @description 通过折叠面板收纳内容区域搭配u-collapse使用
* @tutorial https://www.uviewui.com/components/collapse.html
* @property {String} title 面板标题
* @property {String Number} index 主要用于事件的回调标识那个Item被点击
* @property {Boolean} disabled 面板是否可以打开或收起默认false
* @property {Boolean} open 设置某个面板的初始状态是否打开默认false
* @property {String Number} name 唯一标识符如不设置默认用当前collapse-item的索引值
* @property {String} align 标题的对齐方式默认left
* @property {Object} active-style 不显示箭头时可以添加当前选择的collapse-item活动样式对象形式
* @event {Function} change 某个item被打开或者收起时触发
* @example <u-collapse-item :title="item.head" v-for="(item, index) in itemList" :key="index">{{item.body}}</u-collapse-item>
*/
export default {
name: "u-collapse-item",
props: {
//
title: {
type: String,
default: ''
},
//
align: {
type: String,
default: 'left'
},
//
disabled: {
type: Boolean,
default: false
},
// collapse
open: {
type: Boolean,
default: false
},
//
name: {
type: [Number, String],
default: ''
},
//
activeStyle: {
type: Object,
default () {
return {}
}
},
//
index: {
type: [String, Number],
default: ''
}
},
inject: ['uCollapse'],
data() {
return {
isShow: false,
elId: this.$u.guid(),
height: 0, // body
headStyle: {}, //
bodyStyle: {}, //
//itemStyle: {}, // item
arrowColor: '', //
hoverClass: '', //
};
},
mounted() {
this.init();
},
watch: {
open(val) {
this.isShow = val;
}
},
computed: {
arrow() {
return this.uCollapse.arrow;
},
itemStyle() {
return this.uCollapse.itemStyle;
}
},
created() {
// u-collapseu-collapse便u-collapse-item
this.isShow = this.open;
this.nameSync = this.name ? this.name : this.uCollapse.childrens.length;
this.uCollapse.childrens.push(this);
//this.itemStyle = this.uCollapse.itemStyle;
this.headStyle = this.uCollapse.headStyle;
this.bodyStyle = this.uCollapse.bodyStyle;
this.arrowColor = this.uCollapse.arrowColor;
this.hoverClass = this.uCollapse.hoverClass;
},
methods: {
//
init() {
this.$nextTick(() => {
this.queryRect();
});
},
// collapsehead
headClick() {
if (this.disabled) return;
if (this.uCollapse.accordion == true) {
this.uCollapse.childrens.map(val => {
// falsethis.isShow = !this.isShow;
if (this != val) {
val.isShow = false;
}
});
}
this.isShow = !this.isShow;
//
this.$emit('change', {
index: this.index,
show: this.isShow
})
//
if (this.isShow) this.uCollapse.onChange();
this.$forceUpdate();
},
//
queryRect() {
// $uGetRectuViewhttps://www.uviewui.com/js/getRect.html
// this.$uGetRectthis.$u.getRect
this.$uGetRect('#' + this.elId).then(res => {
this.height = res.height;
})
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-collapse-head {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
color: $u-main-color;
font-size: 30rpx;
line-height: 1;
padding: 24rpx 0;
text-align: left;
}
.u-collapse-title {
flex: 1;
overflow: hidden;
}
.u-arrow-down-icon {
transition: all 0.3s;
margin-right: 20rpx;
margin-left: 14rpx;
}
.u-arrow-down-icon-active {
transform: rotate(180deg);
transform-origin: center center;
}
.u-collapse-body {
overflow: hidden;
transition: all 0.3s;
}
.u-collapse-content {
overflow: hidden;
font-size: 28rpx;
color: $u-tips-color;
text-align: left;
}
</style>

104
node_modules/uview-ui/components/u-collapse/u-collapse.vue

@ -0,0 +1,104 @@
<template>
<view class="u-collapse">
<slot />
</view>
</template>
<script>
/**
* collapse 手风琴
* @description 通过折叠面板收纳内容区域
* @tutorial https://www.uviewui.com/components/collapse.html
* @property {Boolean} accordion 是否手风琴模式默认true
* @property {Boolean} arrow 是否显示标题右侧的箭头默认true
* @property {String} arrow-color 标题右侧箭头的颜色默认#909399
* @property {Object} head-style 标题自定义样式对象形式
* @property {Object} body-style 主体自定义样式对象形式
* @property {String} hover-class 样式类名按下时有效默认u-hover-class
* @event {Function} change 当前激活面板展开时触发(如果是手风琴模式参数activeNames类型为String否则为Array)
* @example <u-collapse></u-collapse>
*/
export default {
name:"u-collapse",
props: {
//
accordion: {
type: Boolean,
default: true
},
//
headStyle: {
type: Object,
default () {
return {}
}
},
//
bodyStyle: {
type: Object,
default () {
return {}
}
},
// item
itemStyle: {
type: Object,
default () {
return {}
}
},
//
arrow: {
type: Boolean,
default: true
},
//
arrowColor: {
type: String,
default: '#909399'
},
// "none"
hoverClass: {
type: String,
default: 'u-hover-class'
}
},
provide() {
return {
uCollapse: this
}
},
created() {
this.childrens = []
},
data() {
return {
}
},
methods: {
//
init() {
this.childrens.forEach((vm, index) => {
vm.init();
})
},
// collapse itemcollapse item
onChange() {
let activeItem = [];
this.childrens.forEach((vm, index) => {
if (vm.isShow) {
activeItem.push(vm.nameSync);
}
})
// activeItem1
if (this.accordion) activeItem = activeItem.join('');
this.$emit('change', activeItem);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
</style>

233
node_modules/uview-ui/components/u-column-notice/u-column-notice.vue

@ -0,0 +1,233 @@
<template>
<view
class="u-notice-bar"
:style="{
background: computeBgColor,
padding: padding
}"
:class="[
type ? `u-type-${type}-light-bg` : ''
]"
>
<view class="u-icon-wrap">
<u-icon class="u-left-icon" v-if="volumeIcon" name="volume-fill" :size="volumeSize" :color="computeColor"></u-icon>
</view>
<swiper :disable-touch="disableTouch" @change="change" :autoplay="autoplay && playState == 'play'" :vertical="vertical" circular :interval="duration" class="u-swiper">
<swiper-item v-for="(item, index) in list" :key="index" class="u-swiper-item">
<view
class="u-news-item u-line-1"
:style="[textStyle]"
@tap="click(index)"
:class="['u-type-' + type]"
>
{{ item }}
</view>
</swiper-item>
</swiper>
<view class="u-icon-wrap">
<u-icon @click="getMore" class="u-right-icon" v-if="moreIcon" name="arrow-right" :size="26" :color="computeColor"></u-icon>
<u-icon @click="close" class="u-right-icon" v-if="closeIcon" name="close" :size="24" :color="computeColor"></u-icon>
</view>
</view>
</template>
<script>
export default {
props: {
//
list: {
type: Array,
default() {
return [];
}
},
// success|error|primary|info|warning
type: {
type: String,
default: 'warning'
},
//
volumeIcon: {
type: Boolean,
default: true
},
//
moreIcon: {
type: Boolean,
default: false
},
//
closeIcon: {
type: Boolean,
default: false
},
//
autoplay: {
type: Boolean,
default: true
},
// 使
color: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: ''
},
// row-column-
direction: {
type: String,
default: 'row'
},
//
show: {
type: Boolean,
default: true
},
// rpx
fontSize: {
type: [Number, String],
default: 26
},
// ms
duration: {
type: [Number, String],
default: 2000
},
//
volumeSize: {
type: [Number, String],
default: 34
},
// rpx
speed: {
type: Number,
default: 160
},
//
isCircular: {
type: Boolean,
default: true
},
// horizontal-vertical-
mode: {
type: String,
default: 'horizontal'
},
// play-paused-
playState: {
type: String,
default: 'play'
},
//
// HX2.6.11App 2.5.5+H5 2.5.5+
disableTouch: {
type: Boolean,
default: true
},
//
padding: {
type: [Number, String],
default: '18rpx 24rpx'
}
},
computed: {
// uview
computeColor() {
if (this.color) return this.color;
// 使content-color
else if(this.type == 'none') return '#606266';
else return this.type;
},
//
textStyle() {
let style = {};
if (this.color) style.color = this.color;
else if(this.type == 'none') style.color = '#606266';
style.fontSize = this.fontSize + 'rpx';
return style;
},
//
vertical() {
if(this.mode == 'horizontal') return false;
else return true;
},
//
computeBgColor() {
if (this.bgColor) return this.bgColor;
else if(this.type == 'none') return 'transparent';
}
},
data() {
return {
// animation: false
};
},
methods: {
//
click(index) {
this.$emit('click', index);
},
//
close() {
this.$emit('close');
},
//
getMore() {
this.$emit('getMore');
},
change(e) {
let index = e.detail.current;
if(index == this.list.length - 1) {
this.$emit('end');
}
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-notice-bar {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
padding: 18rpx 24rpx;
overflow: hidden;
}
.u-swiper {
font-size: 26rpx;
height: 32rpx;
display: flex;
align-items: center;
flex: 1;
margin-left: 12rpx;
}
.u-swiper-item {
display: flex;
align-items: center;
overflow: hidden;
}
.u-news-item {
overflow: hidden;
}
.u-right-icon {
margin-left: 12rpx;
display: inline-flex;
align-items: center;
}
.u-left-icon {
display: inline-flex;
align-items: center;
}
</style>

307
node_modules/uview-ui/components/u-count-down/u-count-down.vue

@ -0,0 +1,307 @@
<template>
<view class="u-countdown">
<view class="u-countdown-item" :style="[itemStyle]" v-if="showDays && (hideZeroDay || (!hideZeroDay && d != '0'))">
<view class="u-countdown-time" :style="[letterStyle]">
{{ d }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showDays && (hideZeroDay || (!hideZeroDay && d != '0'))"
>
{{ separator == 'colon' ? ':' : '天' }}
</view>
<view class="u-countdown-item" :style="[itemStyle]" v-if="showHours">
<view class="u-countdown-time" :style="{ fontSize: fontSize + 'rpx', color: color}">
{{ h }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showHours"
>
{{ separator == 'colon' ? ':' : '时' }}
</view>
<view class="u-countdown-item" :style="[itemStyle]" v-if="showMinutes">
<view class="u-countdown-time" :style="{ fontSize: fontSize + 'rpx', color: color}">
{{ i }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showMinutes"
>
{{ separator == 'colon' ? ':' : '分' }}
</view>
<view class="u-countdown-item" :style="[itemStyle]" v-if="showSeconds">
<view class="u-countdown-time" :style="{ fontSize: fontSize + 'rpx', color: color}">
{{ s }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showSeconds && separator == 'zh'"
>
</view>
</view>
</template>
<script>
/**
* countDown 倒计时
* @description 该组件一般使用于某个活动的截止时间上通过数字的变化给用户明确的时间感受提示用户进行某一个行为操作
* @tutorial https://www.uviewui.com/components/countDown.html
* @property {String Number} timestamp 倒计时单位为秒
* @property {Boolean} autoplay 是否自动开始倒计时如果为false需手动调用开始方法见官网说明默认true
* @property {String} separator 分隔符colon为英文冒号zh为中文默认colon
* @property {String Number} separator-size 分隔符的字体大小单位rpx默认30
* @property {String} separator-color 分隔符的颜色默认#303133
* @property {String Number} font-size 倒计时字体大小单位rpx默认30
* @property {Boolean} show-border 是否显示倒计时数字的边框默认false
* @property {Boolean} hide-zero-day "天"的部分为0时隐藏该字段 默认true
* @property {String} border-color 数字边框的颜色默认#303133
* @property {String} bg-color 倒计时数字的背景颜色默认#ffffff
* @property {String} color 倒计时数字的颜色默认#303133
* @property {String} height 数字高度值(宽度等同此值)设置边框时看情况是否需要设置此值单位rpx默认auto
* @property {Boolean} show-days 是否显示倒计时的"天"部分默认true
* @property {Boolean} show-hours 是否显示倒计时的"时"部分默认true
* @property {Boolean} show-minutes 是否显示倒计时的"分"部分默认true
* @property {Boolean} show-seconds 是否显示倒计时的"秒"部分默认true
* @event {Function} end 倒计时结束
* @event {Function} change 每秒触发一次回调为当前剩余的倒计秒数
* @example <u-count-down ref="uCountDown" :timestamp="86400" :autoplay="false"></u-count-down>
*/
export default {
name: 'u-count-down',
props: {
//
timestamp: {
type: [Number, String],
default: 0
},
//
autoplay: {
type: Boolean,
default: true
},
// (colon)(zh)false"11:22""1122"
separator: {
type: String,
default: 'colon'
},
// rpx
separatorSize: {
type: [Number, String],
default: 30
},
//
separatorColor: {
type: String,
default: "#303133"
},
//
color: {
type: String,
default: '#303133'
},
// rpx
fontSize: {
type: [Number, String],
default: 30
},
//
bgColor: {
type: String,
default: '#fff'
},
// rpx
height: {
type: [Number, String],
default: 'auto'
},
//
showBorder: {
type: Boolean,
default: false
},
//
borderColor: {
type: String,
default: '#303133'
},
//
showSeconds: {
type: Boolean,
default: true
},
//
showMinutes: {
type: Boolean,
default: true
},
//
showHours: {
type: Boolean,
default: true
},
//
showDays: {
type: Boolean,
default: true
},
// ""0
hideZeroDay: {
type: Boolean,
default: false
}
},
watch: {
//
timestamp(newVal, oldVal) {
//
clearInterval(this.timer);
this.start();
}
},
data() {
return {
d: '00', //
h: '00', //
i: '00', //
s: '00', //
timer: null ,//
seconds: 0, //
};
},
computed: {
// itemitem
itemStyle() {
let style = {};
if(this.height) {
style.height = this.height + 'rpx';
style.width = this.height + 'rpx';
}
if(this.showBorder) {
style.borderStyle = 'solid';
style.borderColor = this.borderColor;
style.borderWidth = '1px';
}
if(this.bgColor) {
style.backgroundColor = this.bgColor;
}
return style;
},
//
letterStyle() {
let style = {};
if(this.fontSize) style.fontSize = this.fontSize + 'rpx';
if(this.color) style.color = this.color;
return style;
}
},
mounted() {
//
this.autoplay && this.timestamp && this.start();
},
methods: {
//
start() {
if (this.timestamp <= 0) return;
this.seconds = Number(this.timestamp);
this.formatTime(this.seconds);
this.timer = setInterval(() => {
this.seconds--;
// change
this.$emit('change', this.seconds);
if (this.seconds < 0) {
return this.end();
}
this.formatTime(this.seconds);
}, 1000);
},
//
formatTime(seconds) {
// 0
seconds <= 0 && this.end();
let [day, hour, minute, second] = [0, 0, 0, 0];
day = Math.floor(seconds / (60 * 60 * 24));
//
// hour()
hour = Math.floor(seconds / (60 * 60)) - day * 24;
// showHour
let showHour = null;
if(this.showDays) {
showHour = hour;
} else {
//
showHour = Math.floor(seconds / (60 * 60));
}
minute = Math.floor(seconds / 60) - hour * 60 - day * 24 * 60;
second = Math.floor(seconds) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
// 10"0"
showHour = showHour < 10 ? '0' + showHour : showHour;
minute = minute < 10 ? '0' + minute : minute;
second = second < 10 ? '0' + second : second;
this.d = day;
this.h = showHour;
this.i = minute;
this.s = second;
},
//
end() {
//
clearInterval(this.timer);
this.timer = null;
this.$emit('end', {});
}
},
beforeDestroy() {
clearInterval(this.timer);
this.timer = null;
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-countdown {
display: inline-flex;
align-items: center;
}
.u-countdown-item {
display: flex;
align-items: center;
justify-content: center;
padding: 2rpx;
border-radius: 6rpx;
white-space: nowrap;
transform: translateZ(0);
}
.u-countdown-time {
margin: 0;
padding: 0;
line-height: 1;
}
.u-countdown-colon {
display: flex;
justify-content: center;
padding: 0 5rpx;
line-height: 1;
align-items: center;
padding-bottom: 4rpx;
}
.u-countdown-scale {
transform: scale(0.9);
transform-origin: center center;
}
</style>

239
node_modules/uview-ui/components/u-count-to/u-count-to.vue

@ -0,0 +1,239 @@
<template>
<view
class="u-count-num"
:style="{
fontSize: fontSize + 'rpx',
fontWeight: bold ? 'bold' : 'normal',
color: color
}"
>
{{ displayValue }}
</view>
</template>
<script>
/**
* countTo 数字滚动
* @description 该组件一般用于需要滚动数字到某一个值的场景目标要求是一个递增的值
* @tutorial https://www.uviewui.com/components/countTo.html
* @property {String Number} start-val 开始值
* @property {String Number} end-val 结束值
* @property {String Number} duration 滚动过程所需的时间单位ms默认2000
* @property {Boolean} autoplay 是否自动开始滚动默认true
* @property {String Number} decimals 要显示的小数位数见官网说明默认0
* @property {Boolean} use-easing 滚动结束时是否缓动结尾见官网说明默认true
* @property {String} separator 千位分隔符见官网说明
* @property {String} color 字体颜色默认#303133
* @property {String Number} font-size 字体大小单位rpx默认50
* @property {Boolean} bold 字体是否加粗默认false
* @event {Function} end 数值滚动到目标值时触发
* @example <u-count-to ref="uCountTo" :end-val="endVal" :autoplay="autoplay"></u-count-to>
*/
export default {
name: 'u-count-to',
props: {
// 0
startVal: {
type: [Number, String],
default: 0
},
//
endVal: {
type: [Number, String],
default: 0,
required: true
},
// ms
duration: {
type: [Number, String],
default: 2000
},
//
autoplay: {
type: Boolean,
default: true
},
//
decimals: {
type: [Number, String],
default: 0
},
// 使
useEasing: {
type: Boolean,
default: true
},
//
decimal: {
type: [Number, String],
default: '.'
},
//
color: {
type: String,
default: '#303133'
},
//
fontSize: {
type: [Number, String],
default: 50
},
//
bold: {
type: Boolean,
default: false
},
// (23,321.05",")
separator: {
type: String,
default: ''
}
},
data() {
return {
localStartVal: this.startVal,
displayValue: this.formatNumber(this.startVal),
printVal: null,
paused: false, //
localDuration: Number(this.duration),
startTime: null, //
timestamp: null, //
remaining: null, //
rAF: null,
lastTime: 0 //
};
},
computed: {
countDown() {
return this.startVal > this.endVal;
}
},
watch: {
startVal() {
this.autoplay && this.start();
},
endVal() {
this.autoplay && this.start();
}
},
mounted() {
this.autoplay && this.start();
},
methods: {
easingFn(t, b, c, d) {
return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b;
},
requestAnimationFrame(callback) {
const currTime = new Date().getTime();
// 使setTimteout60
const timeToCall = Math.max(0, 16 - (currTime - this.lastTime));
const id = setTimeout(() => {
callback(currTime + timeToCall);
}, timeToCall);
this.lastTime = currTime + timeToCall;
return id;
},
cancelAnimationFrame(id) {
clearTimeout(id);
},
//
start() {
this.localStartVal = this.startVal;
this.startTime = null;
this.localDuration = this.duration;
this.paused = false;
this.rAF = this.requestAnimationFrame(this.count);
},
//
reStart() {
if (this.paused) {
this.resume();
this.paused = false;
} else {
this.stop();
this.paused = true;
}
},
//
stop() {
this.cancelAnimationFrame(this.rAF);
},
// ()
resume() {
this.startTime = null;
this.localDuration = this.remaining;
this.localStartVal = this.printVal;
this.requestAnimationFrame(this.count);
},
//
reset() {
this.startTime = null;
this.cancelAnimationFrame(this.rAF);
this.displayValue = this.formatNumber(this.startVal);
},
count(timestamp) {
if (!this.startTime) this.startTime = timestamp;
this.timestamp = timestamp;
const progress = timestamp - this.startTime;
this.remaining = this.localDuration - progress;
if (this.useEasing) {
if (this.countDown) {
this.printVal = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration);
} else {
this.printVal = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration);
}
} else {
if (this.countDown) {
this.printVal = this.localStartVal - (this.localStartVal - this.endVal) * (progress / this.localDuration);
} else {
this.printVal = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration);
}
}
if (this.countDown) {
this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal;
} else {
this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal;
}
this.displayValue = this.formatNumber(this.printVal);
if (progress < this.localDuration) {
this.rAF = this.requestAnimationFrame(this.count);
} else {
this.$emit('end');
}
},
//
isNumber(val) {
return !isNaN(parseFloat(val));
},
formatNumber(num) {
// numNumbertoFixed
num = Number(num);
num = num.toFixed(Number(this.decimals));
num += '';
const x = num.split('.');
let x1 = x[0];
const x2 = x.length > 1 ? this.decimal + x[1] : '';
const rgx = /(\d+)(\d{3})/;
if (this.separator && !this.isNumber(this.separator)) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + this.separator + '$2');
}
}
return x1 + x2;
},
destroyed() {
this.cancelAnimationFrame(this.rAF);
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-count-num {
display: inline-block;
text-align: center;
}
</style>

151
node_modules/uview-ui/components/u-divider/u-divider.vue

@ -0,0 +1,151 @@
<template>
<view class="u-divider" :style="{
height: height == 'auto' ? 'auto' : height + 'rpx',
backgroundColor: bgColor,
marginBottom: marginBottom + 'rpx',
marginTop: marginTop + 'rpx'
}" @tap="click">
<view class="u-divider-line" :class="[type ? 'u-divider-line--bordercolor--' + type : '']" :style="[lineStyle]"></view>
<view v-if="useSlot" class="u-divider-text" :style="{
color: color,
fontSize: fontSize + 'rpx'
}"><slot /></view>
<view class="u-divider-line" :class="[type ? 'u-divider-line--bordercolor--' + type : '']" :style="[lineStyle]"></view>
</view>
</template>
<script>
/**
* divider 分割线
* @description 区隔内容的分割线一般用于页面底部"没有更多"的提示
* @tutorial https://www.uviewui.com/components/divider.html
* @property {String Number} half-width 文字左或右边线条宽度数值或百分比数值时单位为rpx
* @property {String} border-color 线条颜色优先级高于type默认#dcdfe6
* @property {String} color 文字颜色默认#909399
* @property {String Number} fontSize 字体大小单位rpx默认26
* @property {String} bg-color 整个divider的背景颜色默认呢#ffffff
* @property {String Number} height 整个divider的高度单位rpx默认40
* @property {String} type 将线条设置主题色默认primary
* @property {Boolean} useSlot 是否使用slot传入内容如果不传入中间不会有空隙默认true
* @property {String Number} margin-top 与前一个组件的距离单位rpx默认0
* @property {String Number} margin-bottom 与后一个组件的距离单位rpx0
* @event {Function} click divider组件被点击时触发
* @example <u-divider color="#fa3534">长河落日圆</u-divider>
*/
export default {
name: 'u-divider',
props: {
// divider线()rpx
halfWidth: {
type: [Number, String],
default: 150
},
// divider线
borderColor: {
type: String,
default: '#dcdfe6'
},
// primary|info|success|warning|error
type: {
type: String,
default: 'primary'
},
//
color: {
type: String,
default: '#909399'
},
// rpx
fontSize: {
type: [Number, String],
default: 26
},
// divider
bgColor: {
type: String,
default: '#ffffff'
},
// dividerrpx
height: {
type: [Number, String],
default: 'auto'
},
//
marginTop: {
type: [String, Number],
default: 0
},
//
marginBottom: {
type: [String, Number],
default: 0
},
// 使slotslot
useSlot: {
type: Boolean,
default: true
}
},
computed: {
lineStyle() {
let style = {};
if(String(this.halfWidth).indexOf('%') != -1) style.width = this.halfWidth;
else style.width = this.halfWidth + 'rpx';
// borderColortype
if(this.borderColor) style.borderColor = this.borderColor;
return style;
}
},
methods: {
click() {
this.$emit('click');
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-divider {
width: 100%;
position: relative;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
flex-direction: row;
}
.u-divider-line {
border-bottom: 1px solid $u-border-color;
transform: scale(1, 0.5);
transform-origin: center;
&--bordercolor--primary {
border-color: $u-type-primary;
}
&--bordercolor--success {
border-color: $u-type-success;
}
&--bordercolor--error {
border-color: $u-type-primary;
}
&--bordercolor--info {
border-color: $u-type-info;
}
&--bordercolor--warning {
border-color: $u-type-warning;
}
}
.u-divider-text {
white-space: nowrap;
padding: 0 16rpx;
display: inline-flex;
}
</style>

242
node_modules/uview-ui/components/u-dropdown-list/u-dropdown-list.vue

@ -0,0 +1,242 @@
<template>
<view class="dropdown-list-wapper u-flex u-flex-1">
<view
v-for="(drop, index) in dropdownListFromFather"
:key="drop.name"
:show="drop.show"
class="u-selected-class u-dropdown-list"
:style="{ zIndex: zIndex + 1 }"
>
<slot name="selectionbox">
<view
:style="{ height: top + 'rpx' }"
class="drop-item u-flex u-justify-center"
@click="handleDropClick(drop)"
>
<text :style="{ color: drop.show ? activeColor : '#999' }">
{{ getTitle(drop.options) }}
</text>
<view
class="u-animation"
:class="[drop.show ? 'u-animation-show' : '']"
>
<u-icon
v-if="drop.show"
name="arrow-up-fill"
:size="18"
:color="activeColor"
></u-icon>
<u-icon v-else name="arrow-down-fill" :size="18"></u-icon>
</view>
</view>
</slot>
<view
class="u-dropdown-view"
:class="[drop.show ? 'u-dropdownlist-show' : '']"
:style="{
background: bgcolor,
height: drop.show ? 'auto' : 0,
top: top + 'rpx'
}"
>
<slot name="dropdownbox">
<view class="u-selected-list">
<view
class="select-item u-flex u-align-center u-border-bottom u-align-between"
:style="{ color: select.select ? activeColor : '#666666' }"
@tap="handleSelected(select, drop.options)"
v-for="(select, n) in drop.options"
:key="n"
>
<text>{{ select.text }}</text>
<u-icon
v-if="select.select"
class="select-icon"
:color="activeColor"
size="35"
name="checkmark"
></u-icon>
</view>
</view>
</slot>
</view>
</view>
<u-mask
duration="100"
:show="dropdownShow"
@click="closeMask"
:z-index="zIndex"
></u-mask>
</view>
</template>
<script>
const dropdownOption1 = [
{ id: 0, text: '类型', value: '', select: false },
{ id: 1, text: '全场券', value: 1, select: false },
{ id: 2, text: '品类券', value: 2, select: false },
{ id: 3, text: '单品券', value: 3, select: false },
{ id: 4, text: '业务券', value: 4, select: false }
]
const dropdownOption2 = [
{ id: 5, text: '状态', value: '', select: false },
{ id: 6, text: '可使用', value: 1, select: false },
{ id: 7, text: '已过期', value: 2, select: false }
]
const dropdownOption3 = [
{ id: 8, text: '优惠力度', value: '', select: false },
{ id: 9, text: '满100-20', value: 1, select: false },
{ id: 10, text: '满100-50', value: 2, select: false }
]
export default {
props: {
//
dropdownList: {
type: Array,
default: () => [
{ show: false, options: dropdownOption1 },
{ show: false, options: dropdownOption2 },
{ show: false, options: dropdownOption3 }
],
required: true,
validator: value =>
value.every(item => Array.isArray(item.options) && item.options.length)
},
//
bgcolor: {
type: String,
default: 'none'
},
//top rpx
top: {
type: Number,
default: 90
},
//
activeColor: {
type: String,
default: '#e7141a'
},
// maskz-index
zIndex: {
type: [String, Number],
default: 21
}
},
data() {
return {
dropdownShow: false,
dropdownListFromFather: this.dropdownList
}
},
computed: {},
methods: {
getTitle(item = []) {
const obj = item.find(v => v.select) || {}
if (obj.select) {
return obj.text
} else {
if (item[0]) {
item[0].select = true
return item[0].text
}
}
return ''
},
handleDropClick(item) {
if (item.show) {
item.show = false
this.dropdownShow = false
return
}
this.dropdownListFromFather.map(item => {
item.show = false
})
const t = setTimeout(() => {
item.show = true
this.dropdownShow = true
clearTimeout(t)
}, 100)
},
closeMask() {
this.dropdownShow = false
this.dropdownListFromFather.map(item => {
item.show = false
})
},
handleSelected(select, options) {
options.map(item => {
item.select = false
})
select.select = true
this.closeMask()
//
this.$emit('change', select, options)
}
},
watch: {
dropdownList: {
handler(v) {
this.dropdownListFromFather = v
},
deep: true
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.dropdown-list-wapper {
position: relative;
}
.u-dropdown-view {
width: 100%;
overflow: hidden;
position: absolute;
z-index: 9999;
left: 0;
right: 0;
/* opacity: 0; */
visibility: hidden;
transition: height 0.5s ease-in-out;
.u-selected-list {
background-color: #fff;
.select-item {
color: #666666;
font-size: 28rpx;
padding: 30rpx 54rpx 30rpx 30rpx;
margin-left: 30rpx;
}
.select-item.selectActive {
color: #e7141a;
}
}
}
.u-dropdownlist-show {
/* opacity: 1; */
visibility: visible;
}
.u-dropdown-list {
flex: 1;
// z-index: 22;
background: #fff;
position: static;
}
.drop-item {
justify-content: center;
color: #999999;
font-size: 30rpx;
> text {
margin-right: 10rpx;
}
/deep/ {
.uicon {
position: relative;
top: -2rpx;
}
}
}
</style>

193
node_modules/uview-ui/components/u-empty/u-empty.vue

@ -0,0 +1,193 @@
<template>
<view class="u-empty" v-if="show" :style="{
marginTop: marginTop + 'rpx'
}">
<u-icon
:name="src ? src : 'empty-' + mode"
:custom-style="iconStyle"
:label="text ? text : icons[mode]"
label-pos="bottom"
:label-color="color"
:label-size="fontSize"
:size="iconSize"
:color="iconColor"
margin-top="14"
></u-icon>
<view class="u-slot-wrap">
<slot name="bottom"></slot>
</view>
</view>
</template>
<script>
/**
* empty 内容为空
* @description 该组件用于需要加载内容但是加载的第一页数据就为空提示一个"没有内容"的场景 我们精心挑选了十几个场景的图标方便您使用
* @tutorial https://www.uviewui.com/components/empty.html
* @property {String} color 文字颜色默认#c0c4cc
* @property {String} text 文字提示默认无内容
* @property {String} src 自定义图标路径如定义mode参数会失效
* @property {String Number} font-size 提示文字的大小单位rpx默认28
* @property {String} mode 内置的图标见官网说明默认data
* @property {String Number} img-width 图标的宽度单位rpx默认240
* @property {String} img-height 图标的高度单位rpx默认auto
* @property {String Number} margin-top 组件距离上一个元素之间的距离默认0
* @property {Boolean} show 是否显示组件默认true
* @event {Function} click 点击组件时触发
* @event {Function} close 点击关闭按钮时触发
* @example <u-empty text="所谓伊人,在水一方" mode="list"></u-empty>
*/
export default {
name: "u-empty",
props: {
//
src: {
type: String,
default: ''
},
//
text: {
type: String,
default: ''
},
//
color: {
type: String,
default: '#c0c4cc'
},
//
iconColor: {
type: String,
default: '#c0c4cc'
},
//
iconSize: {
type: [String, Number],
default: 120
},
// rpx
fontSize: {
type: [String, Number],
default: 26
},
//
mode: {
type: String,
default: 'data'
},
// rpx
imgWidth: {
type: [String, Number],
default: 120
},
// rpx
imgHeight: {
type: [String, Number],
default: 'auto'
},
//
show: {
type: Boolean,
default: true
},
//
marginTop: {
type: [String, Number],
default: 0
},
iconStyle: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
icons: {
car: '购物车为空',
page: '页面不存在',
search: '没有搜索结果',
address: '没有收货地址',
wifi: '没有WiFi',
order: '订单为空',
coupon: '没有优惠券',
favor: '暂无收藏',
permission: '无权限',
history: '无历史记录',
news: '无新闻列表',
message: '消息列表为空',
list: '列表为空',
data: '数据为空'
},
// icons: [{
// icon: 'car',
// text: ''
// },{
// icon: 'page',
// text: ''
// },{
// icon: 'search',
// text: ''
// },{
// icon: 'address',
// text: ''
// },{
// icon: 'wifi',
// text: 'WiFi'
// },{
// icon: 'order',
// text: ''
// },{
// icon: 'coupon',
// text: ''
// },{
// icon: 'favor',
// text: ''
// },{
// icon: 'permission',
// text: ''
// },{
// icon: 'history',
// text: ''
// },{
// icon: 'news',
// text: ''
// },{
// icon: 'message',
// text: ''
// },{
// icon: 'list',
// text: ''
// },{
// icon: 'data',
// text: ''
// }],
}
}
}
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-empty {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
}
.u-image {
margin-bottom: 20rpx;
}
.u-slot-wrap {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20rpx;
}
</style>

366
node_modules/uview-ui/components/u-field/u-field.vue

@ -0,0 +1,366 @@
<template>
<view class="u-field" :class="{'u-border-top': borderTop, 'u-border-bottom': borderBottom }">
<view class="u-field-inner" :class="[type == 'textarea' ? 'u-textarea-inner' : '', 'u-label-postion-' + labelPosition]">
<view class="u-label" :class="[required ? 'u-required' : '']" :style="{
justifyContent: justifyContent,
flex: labelPosition == 'left' ? `0 0 ${labelWidth}rpx` : '1'
}">
<view class="u-icon-wrap" v-if="icon">
<u-icon size="32" :custom-style="iconStyle" :name="icon" :color="iconColor" class="u-icon"></u-icon>
</view>
<slot name="icon"></slot>
<text class="u-label-text" :class="[this.$slots.icon || icon ? 'u-label-left-gap' : '']">{{ label }}</text>
</view>
<view class="fild-body">
<view class="u-flex-1 u-flex" :style="[inputWrapStyle]">
<textarea v-if="type == 'textarea'" class="u-flex-1 u-textarea-class" :style="[fieldStyle]" :value="value"
:placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" :maxlength="inputMaxlength"
:focus="focus" :autoHeight="autoHeight" :fixed="fixed" @input="onInput" @blur="onBlur" @focus="onFocus" @confirm="onConfirm"
@tap="fieldClick" />
<input
v-else
:style="[fieldStyle]"
:type="type"
class="u-flex-1 u-field__input-wrap"
:value="value"
:password="password || this.type === 'password'"
:placeholder="placeholder"
:placeholderStyle="placeholderStyle"
:disabled="disabled"
:maxlength="inputMaxlength"
:focus="focus"
:confirmType="confirmType"
@focus="onFocus"
@blur="onBlur"
@input="onInput"
@confirm="onConfirm"
@tap="fieldClick"
/>
</view>
<u-icon :size="clearSize" v-if="clearable && value != '' && focused" name="close-circle-fill" color="#c0c4cc" class="u-clear-icon" @touchstart="onClear"/>
<view class="u-button-wrap"><slot name="right" /></view>
<u-icon v-if="rightIcon" @click="rightIconClick" :name="rightIcon" color="#c0c4cc" :style="[rightIconStyle]" size="26" class="u-arror-right" />
</view>
</view>
<view v-if="errorMessage !== false && errorMessage != ''" class="u-error-message" :style="{
paddingLeft: labelWidth + 'rpx'
}">{{ errorMessage }}</view>
</view>
</template>
<script>
/**
* field 输入框
* @description 借助此组件可以实现表单的输入 "text""textarea"类型的此外借助uView的picker和actionSheet组件可以快速实现上拉菜单时间地区选择等 为表单解决方案的利器
* @tutorial https://www.uviewui.com/components/field.html
* @property {String} type 输入框的类型默认text
* @property {String} icon label左边的图标限uView的图标名称
* @property {Object} icon-style 左边图标的样式对象形式
* @property {Boolean} right-icon 输入框右边的图标名称限uView的图标名称默认false
* @property {Boolean} required 是否必填左边您显示红色"*"默认false
* @property {String} label 输入框左边的文字提示
* @property {Boolean} password 是否密码输入方式(用点替换文字)type为text时有效默认false
* @property {Boolean} clearable 是否显示右侧清空内容的图标控件(输入框有内容且获得焦点时才显示)点击可清空输入框内容默认true
* @property {Number String} label-width label的宽度单位rpx默认130
* @property {String} label-align label的文字对齐方式默认left
* @property {Object} field-style 自定义输入框的样式对象形式
* @property {Number | String} clear-size 清除图标的大小单位rpx默认30
* @property {String} input-align 输入框内容对齐方式默认left
* @property {Boolean} border-bottom 是否显示field的下边框默认true
* @property {Boolean} border-top 是否显示field的上边框默认false
* @property {String} icon-color 左边通过icon配置的图标的颜色默认#606266
* @property {Boolean} auto-height 是否自动增高输入区域type为textarea时有效默认true
* @property {String Boolean} error-message 显示的错误提示内容如果为空字符串或者false则不显示错误信息
* @property {String} placeholder 输入框的提示文字
* @property {String} placeholder-style placeholder的样式(内联样式字符串)"color: #ddd"
* @property {Boolean} focus 是否自动获得焦点默认false
* @property {Boolean} fixed 如果type为textarea且在一个"position:fixed"的区域需要指明为true默认false
* @property {Boolean} disabled 是否不可输入默认false
* @property {Number String} maxlength 最大输入长度设置为 -1 的时候不限制最大长度默认140
* @property {String} confirm-type 设置键盘右下角按钮的文字仅在type="text"时生效默认done
* @event {Function} input 输入框内容发生变化时触发
* @event {Function} focus 输入框获得焦点时触发
* @event {Function} blur 输入框失去焦点时触发
* @event {Function} confirm 点击完成按钮时触发
* @event {Function} right-icon-click 通过right-icon生成的图标被点击时触发
* @event {Function} click 输入框被点击或者通过right-icon生成的图标被点击时触发这样设计是考虑到传递右边的图标一般都为需要弹出"picker"等操作时的场景点击倒三角图标理应发出此事件见上方说明
* @example <u-field v-model="mobile" label="手机号" required :error-message="errorMessage"></u-field>
*/
export default {
name:"u-field",
props: {
icon: String,
rightIcon: String,
// arrowDirection: {
// type: String,
// default: 'right'
// },
required: Boolean,
label: String,
password: Boolean,
clearable: {
type: Boolean,
default: true
},
// rpx
labelWidth: {
type: [Number, String],
default: 130
},
// left|center|right
labelAlign: {
type: String,
default: 'left'
},
inputAlign: {
type: String,
default: 'left'
},
iconColor: {
type: String,
default: '#606266'
},
autoHeight: {
type: Boolean,
default: true
},
errorMessage: {
type: [String, Boolean],
default: ''
},
placeholder: String,
placeholderStyle: String,
focus: Boolean,
fixed: Boolean,
value: [Number, String],
type: {
type: String,
default: 'text'
},
disabled: {
type: Boolean,
default: false
},
maxlength: {
type: [Number, String],
default: 140
},
confirmType: {
type: String,
default: 'done'
},
// lable left-top-
labelPosition: {
type: String,
default: 'left'
},
//
fieldStyle: {
type: Object,
default() {
return {}
}
},
//
clearSize: {
type: [Number, String],
default: 30
},
// lable
iconStyle: {
type: Object,
default() {
return {}
}
},
//
borderTop: {
type: Boolean,
default: false
},
//
borderBottom: {
type: Boolean,
default: true
},
},
data() {
return {
focused: false,
itemIndex: 0,
};
},
computed: {
inputWrapStyle() {
let style = {};
style.textAlign = this.inputAlign;
// lableleftinput
if(this.labelPosition == 'left') {
style.margin = `0 8rpx`;
} else {
// labletopinput
style.marginRight = `8rpx`;
}
return style;
},
rightIconStyle() {
let style = {};
if (this.arrowDirection == 'top') style.transform = 'roate(-90deg)';
if (this.arrowDirection == 'bottom') style.transform = 'roate(90deg)';
else style.transform = 'roate(0deg)';
return style;
},
labelStyle() {
let style = {};
if(this.labelAlign == 'left') style.justifyContent = 'flext-start';
if(this.labelAlign == 'center') style.justifyContent = 'center';
if(this.labelAlign == 'right') style.justifyContent = 'flext-end';
return style;
},
// unicomputedstyle.justifyContent = 'center'
justifyContent() {
if(this.labelAlign == 'left') return 'flex-start';
if(this.labelAlign == 'center') return 'center';
if(this.labelAlign == 'right') return 'flex-end';
},
// uniappinputmaxlength
inputMaxlength() {
return Number(this.maxlength)
},
// label
fieldInnerStyle() {
let style = {};
if(this.labelPosition == 'left') {
style.flexDirection = 'row';
} else {
style.flexDirection = 'column';
}
return style;
}
},
methods: {
onInput(event) {
this.$emit('input', event.target.value);
},
onFocus(event) {
this.focused = true;
this.$emit('focus', event);
},
onBlur(event) {
this.focused = false;
this.$emit('blur', event);
},
onConfirm(e) {
this.$emit('confirm', e.detail.value);
},
onClear(event) {
this.$emit('input', '');
},
rightIconClick() {
this.$emit('right-icon-click');
this.$emit('click');
},
fieldClick() {
this.$emit('click');
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-field {
font-size: 28rpx;
padding: 20rpx 28rpx;
text-align: left;
position: relative;
color: $u-main-color;
}
.u-field-inner {
display: flex;
align-items: center;
}
.u-textarea-inner {
align-items: flex-start;
}
.u-textarea-class {
min-height: 96rpx;
width: auto;
font-size: 28rpx;
}
.fild-body {
display: flex;
flex: 1;
align-items: center;
}
.u-arror-right {
margin-left: 8rpx;
}
.u-label-text {
display: inline-block;
}
.u-label-left-gap {
margin-left: 6rpx;
}
.u-label-postion-top {
flex-direction: column;
align-items: flex-start;
}
.u-label {
width: 130rpx;
flex: 1 1 130rpx;
text-align: left;
position: relative;
display: flex;
align-items: center;
}
.u-required::before {
content: '*';
position: absolute;
left: -16rpx;
font-size: 14px;
color: $u-type-error;
height: 9px;
line-height: 1;
}
.u-field__input-wrap {
position: relative;
overflow: hidden;
font-size: 28rpx;
height: 48rpx;
flex: 1;
width: auto;
}
.u-clear-icon {
display: flex;
align-items: center;
}
.u-error-message {
color: $u-type-error;
font-size: 26rpx;
text-align: left;
}
.placeholder-style {
color: rgb(150, 151, 153);
}
.u-input-class {
font-size: 28rpx;
}
</style>

396
node_modules/uview-ui/components/u-form-item/u-form-item.vue

@ -0,0 +1,396 @@
<template>
<view class="u-form-item" :class="{'u-border-bottom': elBorderBottom, 'u-form-item__border-bottom--error': validateState === 'error' && showError('border-bottom')}">
<view class="u-form-item__body" :style="{
flexDirection: elLabelPosition == 'left' ? 'row' : 'column'
}">
<view class="u-form-item--left" :style="{
width: elLabelPosition == 'left' ? $u.addUnit(elLabelWidth) : '100%',
flex: `0 0 ${elLabelPosition == 'left' ? $u.addUnit(elLabelWidth) : '100%'}`,
marginBottom: elLabelPosition == 'left' ? 0 : '10rpx',
}">
<!-- 为了块对齐 -->
<view class="u-form-item--left__content">
<!-- nvue不支持伪元素before -->
<text v-if="required" class="u-form-item--left__content--required">*</text>
<view class="u-form-item--left__content__icon" v-if="leftIcon">
<u-icon :name="leftIcon" :custom-style="leftIconStyle"></u-icon>
</view>
<view class="u-form-item--left__content__label" :style="[elLabelStyle, {
'justify-content': elLabelAlign == 'left' ? 'flex-start' : elLabelAlign == 'center' ? 'center' : 'flex-end'
}]">
{{label}}
</view>
</view>
</view>
<view class="u-form-item--right u-flex">
<view class="u-form-item--right__content">
<view class="u-form-item--right__content__slot ">
<slot />
</view>
<view class="u-form-item--right__content__icon u-flex" v-if="$slots.right || rightIcon">
<u-icon :custom-style="rightIconStyle" v-if="rightIcon" :name="rightIcon"></u-icon>
<slot name="right" />
</view>
</view>
</view>
</view>
<view class="u-form-item__message" v-if="validateState === 'error' && showError('message')" :style="{
paddingLeft: elLabelPosition == 'left' ? $u.addUnit(elLabelWidth) : '0',
}">{{validateMessage}}</view>
</view>
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
import schema from '../../libs/util/async-validator';
//
schema.warning = function(){};
/**
* form-item 表单item
* @description 此组件一般用于表单场景可以配置Input输入框Select弹出框进行表单验证等
* @tutorial http://uviewui.com/components/form.html
* @property {String} label 左侧提示文字
* @property {Object} prop 表单域model对象的属性名在使用 validateresetFields 方法的情况下该属性是必填的
* @property {Boolean} border-bottom 是否显示表单域的下划线边框
* @property {String} label-position 表单域提示文字的位置left-左侧top-上方
* @property {String Number} label-width 提示文字的宽度单位rpx默认90
* @property {Object} label-style lable的样式对象形式
* @property {String} label-align lable的对齐方式
* @property {String} right-icon 右侧自定义字体图标(限uView内置图标)或图片地址
* @property {String} left-icon 左侧自定义字体图标(限uView内置图标)或图片地址
* @property {Object} left-icon-style 左侧图标的样式对象形式
* @property {Object} right-icon-style 右侧图标的样式对象形式
* @property {Boolean} required 是否显示左边的"*"这里仅起展示作用如需校验必填请通过rules配置必填规则(默认false)
* @example <u-form-item label="姓名"><u-input v-model="form.name" /></u-form-item>
*/
export default {
name: 'u-form-item',
mixins: [Emitter],
inject: {
uForm: {
default() {
return null
}
}
},
props: {
// inputlabel
label: {
type: String,
default: ''
},
//
prop: {
type: String,
default: ''
},
// 线
borderBottom: {
type: [Boolean, String],
default: ''
},
// labelleft-top-
labelPosition: {
type: String,
default: ''
},
// labelrpx
labelWidth: {
type: [String, Number],
default: ''
},
// lable
labelStyle: {
type: Object,
default() {
return {}
}
},
// lable
labelAlign: {
type: String,
default: ''
},
//
rightIcon: {
type: String,
default: ''
},
//
leftIcon: {
type: String,
default: ''
},
//
leftIconStyle: {
type: Object,
default() {
return {}
}
},
//
rightIconStyle: {
type: Object,
default() {
return {}
}
},
// rules
required: {
type: Boolean,
default: false
}
},
data() {
return {
initialValue: '', //
// isRequired: false, // "*"propsrequiredrules
validateState: '', //
validateMessage: '' ,//
// message-border-input
errorType: ['message'],
};
},
created() {
// provide/inject使created
this.parent = this.$u.$parent.call(this, 'u-form');
},
watch: {
validateState(val) {
this.broadcastInputError();
},
// u-formerrorType
"uForm.errorType"(val) {
this.errorType = val;
this.broadcastInputError();
},
},
computed: {
fieldValue() {
return this.uForm.model[this.prop];
},
showError() {
return type => {
// errorTypenonetoast
if(this.errorType.indexOf('none') >= 0) return false;
else if(this.errorType.indexOf(type) >= 0) return true;
else return false;
}
},
// label
elLabelWidth() {
// label90使u-form
return this.labelWidth ? this.labelWidth : (this.parent ? this.parent.labelWidth : 90);
},
// label
elLabelStyle() {
return Object.keys(this.labelStyle).length ? this.labelStyle : (this.parent ? this.parent.labelStyle : {});
},
// label
elLabelPosition() {
return this.labelPosition ? this.labelPosition : (this.parent ? this.parent.labelPosition : 'left');
},
// label
elLabelAlign() {
return this.labelAlign ? this.labelAlign : (this.parent ? this.parent.labelAlign : 'left');
},
// label线
elBorderBottom() {
// borderBottom使
return this.borderBottom !== '' ? this.borderBottom : this.parent ? this.parent.borderBottom : true;
}
},
methods: {
broadcastInputError() {
// truefalsetrue
this.broadcast('u-input', 'on-form-item-error', this.validateState === 'error' && this.showError('border'));
},
// required
setRules() {
let that = this;
// "*"propsrequiredrules
// u-formu-form-item
// let rules = this.getRules();
// if (rules.length) {
// this.isRequired = rules.some(rule => {
// // undefined
// return rule.required;
// });
// }
// blur
this.$on('on-form-blur', that.onFieldBlur);
// change
this.$on('on-form-change', that.onFieldChange);
},
// u-formrulesu-form-item
getRules() {
//
let rules = this.uForm.rules;
rules = rules ? rules[this.prop] : [];
//
return [].concat(rules || []);
},
// blur
onFieldBlur() {
this.validation('blur');
},
// change
onFieldChange() {
this.validation('change');
},
// rule
getFilteredRule(triggerType = '') {
let rules = this.getRules();
// triggerType
if(!triggerType) return rules;
// blurchange
// 使indexOftrigger['blur','change']
// trigger
return rules.filter(res => res.trigger && res.trigger.indexOf(triggerType) !== -1);
},
//
validation(trigger, callback = () => {}) {
// blurchange
let rules = this.getFilteredRule(trigger);
// u-form
// count
if (!rules || rules.length === 0) {
return callback('');
}
//
this.validateState = 'validating';
// async-validator
let validator = new schema({ [this.prop]: rules });
validator.validate({ [this.prop]: this.fieldValue }, { firstFields: true }, (errors, fields) => {
//
this.validateState = !errors ? 'success' : 'error';
this.validateMessage = errors ? errors[0].message : '';
//
callback(this.validateMessage);
});
},
// u-form-item
resetField() {
this.uForm.model[this.prop] = this.initialValue;
// `success`
this.validateState = 'success';
}
},
// u-form
mounted() {
// propuForm(u-form-input使uForm)
if (!this.prop || this.uForm === null) return;
//
this.dispatch('u-form', 'on-form-item-add', this);
this.errorType = this.uForm.errorType;
//
this.initialValue = this.fieldValue;
// $nextTicku-formrulesref
// $nextTickrefu-form
this.$nextTick(() =>{
this.setRules();
})
},
// Form
beforeDestroy() {
this.dispatch('u-form', 'on-form-item-remove', this);
},
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-form-item {
display: flex;
// align-items: flex-start;
padding: 20rpx 0;
font-size: 28rpx;
color: $u-main-color;
box-sizing: border-box;
line-height: $u-form-item-height;
flex-direction: column;
&__border-bottom--error:after {
border-color: $u-type-error;
}
&__body {
display: flex;
}
&--left {
display: flex;
align-items: center;
&__content {
position: relative;
display: flex;
align-items: center;
padding-right: 10rpx;
flex: 1;
&__icon {
margin-right: 8rpx;
}
&--required {
position: absolute;
left: -16rpx;
vertical-align: middle;
color: $u-type-error;
padding-top: 6rpx;
}
&__label {
display: flex;
align-items: center;
flex: 1;
}
}
}
&--right {
flex: 1;
&__content {
display: flex;
align-items: center;
flex: 1;
&__slot {
flex: 1;
/* #ifndef MP */
display: flex;
align-items: center;
/* #endif */
}
&__icon {
margin-left: 10rpx;
color: $u-light-color;
font-size: 30rpx;
}
}
}
&__message {
font-size: 24rpx;
line-height: 24rpx;
color: $u-type-error;
margin-top: 12rpx;
}
}
</style>

149
node_modules/uview-ui/components/u-form/u-form.vue

@ -0,0 +1,149 @@
<template>
<view class="u-form"><slot /></view>
</template>
<script>
/**
* form 表单
* @description 此组件一般用于表单场景可以配置Input输入框Select弹出框进行表单验证等
* @tutorial http://uviewui.com/components/form.html
* @property {Object} model 表单数据对象
* @property {Boolean} border-bottom 是否显示表单域的下划线边框
* @property {String} label-position 表单域提示文字的位置left-左侧top-上方
* @property {String Number} label-width 提示文字的宽度单位rpx默认90
* @property {Object} label-style lable的样式对象形式
* @property {String} label-align lable的对齐方式
* @property {Object} rules 通过ref设置见官网说明
* @property {Array} error-type 错误的提示方式数组形式见上方说明(默认['message'])
* @example <u-form :model="form" ref="uForm"></u-form>
*/
export default {
name: 'u-form',
props: {
// form
model: {
type: Object,
default() {
return {};
}
},
//
// rules: {
// type: [Object, Function, Array],
// default() {
// return {};
// }
// },
// message-border-input
// border-bottom-none-
errorType: {
type: Array,
default() {
return ['message', 'toast']
}
},
// 线
borderBottom: {
type: Boolean,
default: true
},
// labelleft-top-
labelPosition: {
type: String,
default: 'left'
},
// labelrpx
labelWidth: {
type: [String, Number],
default: 90
},
// lable
labelAlign: {
type: String,
default: 'left'
},
// lable
labelStyle: {
type: Object,
default() {
return {}
}
},
},
provide() {
return {
uForm: this
};
},
data() {
return {
rules: {}
};
},
created() {
// formu-form-item
// data
this.fields = [];
//
let that = this;
// on-form-item-addfields
this.$on('on-form-item-add', item => {
if (item) {
that.fields.push(item);
}
});
//
this.$on('on-form-item-remove', item => {
// prop
if (item.prop) {
that.fields.splice(that.fields.indexOf(item), 1);
}
});
},
methods: {
setRules(rules) {
this.rules = rules;
},
// u-form-itemu-form-itemresetField()
resetFields() {
this.fields.map(field => {
field.resetField();
});
},
//
validate(callback) {
return new Promise(resolve => {
// u-form-item
let valid = true; //
let count = 0; //
let errorArr = []; //
this.fields.map(field => {
// u-form-itemvalidation
field.validation('', error => {
// u-form-item
if (error) {
valid = false;
errorArr.push(error);
}
// u-form-itempromisethen
if (++count === this.fields.length) {
resolve(valid); // promisethen
// toast
if(this.errorType.indexOf('none') === -1 && this.errorType.indexOf('toast') >= 0 && errorArr.length) {
this.$u.toast(errorArr[0]);
}
//
if (typeof callback == 'function') callback(valid);
}
});
});
});
}
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
</style>

52
node_modules/uview-ui/components/u-full-screen/u-full-screen.vue

@ -0,0 +1,52 @@
<template>
<u-modal v-model="show" :show-cancel-button="true" confirm-text="升级" title="发现新版本" @cancel="cancel" @confirm="confirm">
<view class="u-update-content">
<rich-text :nodes="content"></rich-text>
</view>
</u-modal>
</template>
<script>
export default {
data() {
return {
show: false,
content: `
1. 修复badge组件的size参数无效问题<br>
2. 新增Modal模态框组件<br>
3. 新增压窗屏组件可以在APP上以弹窗的形式遮盖导航栏和底部tabbar<br>
4. 修复键盘组件在微信小程序上遮罩无效的问题
`,
}
},
onReady() {
this.show = true;
},
methods: {
cancel() {
this.closeModal();
},
confirm() {
this.closeModal();
},
closeModal() {
uni.navigateBack();
}
}
}
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-full-content {
background-color: #00C777;
}
.u-update-content {
font-size: 26rpx;
color: $u-content-color;
line-height: 1.7;
padding: 30rpx;
}
</style>

54
node_modules/uview-ui/components/u-gap/u-gap.vue

@ -0,0 +1,54 @@
<template>
<view class="u-gap" :style="[gapStyle]"></view>
</template>
<script>
/**
* gap 间隔槽
* @description 该组件一般用于内容块之间的用一个灰色块隔开的场景方便用户风格统一减少工作量
* @tutorial https://www.uviewui.com/components/gap.html
* @property {String} bg-color 背景颜色默认#f3f4f6
* @property {String Number} height 分割槽高度单位rpx默认30
* @property {String Number} margin-top 与前一个组件的距离单位rpx默认0
* @property {String Number} margin-bottom 与后一个组件的距离单位rpx0
* @example <u-gap height="80" bg-color="#bbb"></u-gap>
*/
export default {
name: "u-gap",
props: {
bgColor: {
type: String,
default: 'transparent ' //
},
//
height: {
type: [String, Number],
default: 30
},
//
marginTop: {
type: [String, Number],
default: 0
},
//
marginBottom: {
type: [String, Number],
default: 0
},
},
computed: {
gapStyle() {
return {
backgroundColor: this.bgColor,
height: this.height + 'rpx',
marginTop: this.marginTop + 'rpx',
marginBottom: this.marginBottom + 'rpx'
};
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
</style>

113
node_modules/uview-ui/components/u-grid-item/u-grid-item.vue

@ -0,0 +1,113 @@
<template>
<view class="u-grid-item" :hover-class="hoverClass"
:hover-stay-time="200" @tap="click" :style="{
background: bgColor,
width: width,
}">
<view class="u-grid-item-box" :class="[showBorder ? 'u-border-right u-border-bottom' : '']">
<slot />
</view>
</view>
</template>
<script>
/**
* gridItem 提示
* @description 宫格组件一般用于同时展示多个同类项目的场景可以给宫格的项目设置徽标组件(badge)或者图标等也可以扩展为左右滑动的轮播形式搭配u-grid使用
* @tutorial https://www.uviewui.com/components/grid.html
* @property {String} bg-color 宫格的背景颜色默认#ffffff
* @property {String Number} index 点击宫格时返回的值
* @event {Function} click 点击宫格触发
* @example <u-grid-item></u-grid-item>
*/
export default {
name: "u-grid-item",
props: {
//
bgColor: {
type: String,
default: '#ffffff'
},
// index
index: {
type: [Number, String],
default: ''
},
},
// providethis
inject: ['uGrid'],
data() {
return {
hoverClass: '', //
};
},
created() {
this.hoverClass = this.uGrid.hoverClass;
},
computed: {
// 221212
colNum() {
return this.col < 2 ? 2 : this.col > 12 ? 12 : this.col;
},
// grid-item
width() {
return 100 / Number(this.uGrid.col) + '%';
},
//
// created
showBorder() {
return this.uGrid.border;
}
},
methods: {
click() {
this.$emit('click', this.index);
this.uGrid.click(this.index);
}
},
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-grid-item {
box-sizing: border-box;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
position: relative;
flex-direction: column;
/* #ifdef MP */
position: relative;
float: left;
/* #endif */
}
.u-grid-item-hover {
background: #f7f7f7 !important;
}
.u-grid-marker-box {
position: absolute;
display: inline-block;
line-height: 0;
}
.u-grid-marker-wrap {
position: absolute;
}
.u-grid-item-box {
padding: 30rpx 0;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
flex: 1;
width: 100%;
height: 100%;
}
</style>

95
node_modules/uview-ui/components/u-grid/u-grid.vue

@ -0,0 +1,95 @@
<template>
<view class="u-grid" :class="{'u-border-top u-border-left': border}" :style="[gridStyle]"><slot /></view>
</template>
<script>
/**
* grid 宫格布局
* @description 宫格组件一般用于同时展示多个同类项目的场景可以给宫格的项目设置徽标组件(badge)或者图标等也可以扩展为左右滑动的轮播形式
* @tutorial https://www.uviewui.com/components/grid.html
* @property {String Number} col 宫格的列数默认3
* @property {Boolean} border 是否显示宫格的边框默认true
* @property {Boolean} hover-class 点击宫格的时候是否显示按下的灰色背景默认false
* @event {Function} click 点击宫格触发
* @example <u-grid :col="3" @click="click"></u-grid>
*/
export default {
name: 'u-grid',
props: {
//
col: {
type: [Number, String],
default: 3
},
//
border: {
type: Boolean,
default: true
},
//
align: {
type: String,
default: 'left'
},
// "none"
hoverClass: {
type: String,
default: 'u-hover-class'
}
},
data() {
return {
index: 0,
}
},
provide() {
return {
uGrid: this
}
},
computed: {
//
gridStyle() {
let style = {};
switch(this.align) {
case 'left':
style.justifyContent = 'flex-start';
break;
case 'center':
style.justifyContent = 'center';
break;
case 'right':
style.justifyContent = 'flex-end';
break;
default: style.justifyContent = 'flex-start';
};
return style;
}
},
methods: {
click(index) {
this.$emit('click', index);
}
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-grid {
width: 100%;
/* #ifdef MP */
position: relative;
box-sizing: border-box;
overflow: hidden;
/* #endif */
/* #ifndef MP */
display: flex;
flex-wrap: wrap;
align-items: center;
/* #endif */
}
</style>

238
node_modules/uview-ui/components/u-icon/u-icon.vue

@ -0,0 +1,238 @@
<template>
<view :style="[customStyle]" class="u-icon" @tap="click" :class="['u-icon--' + labelPos]">
<image class="u-icon__img" v-if="isImg" :src="name" :mode="imgMode" :style="[imgStyle]"></image>
<text v-else class="u-icon__icon" :class="customClass" :style="[iconStyle]" :hover-class="hoverClass" @touchstart="touchstart"></text>
<text v-if="label" class="u-icon__label" :style="{
color: labelColor,
fontSize: $u.addUnit(labelSize),
marginLeft: labelPos == 'right' ? $u.addUnit(marginLeft) : 0,
marginTop: labelPos == 'bottom' ? $u.addUnit(marginTop) : 0,
marginRight: labelPos == 'left' ? $u.addUnit(marginRight) : 0,
marginBottom: labelPos == 'top' ? $u.addUnit(marginBottom) : 0,
}">{{label}}</text>
</view>
</template>
<script>
/**
* icon 图标
* @description 基于字体的图标集包含了大多数常见场景的图标
* @tutorial https://www.uviewui.com/components/icon.html
* @property {String} name 图标名称见示例图标集
* @property {String} color 图标颜色默认inherit
* @property {String | Number} size 图标字体大小单位rpx默认32
* @property {String | Number} label-size label字体大小单位rpx默认28
* @property {String} label 图标右侧的label文字默认28
* @property {String} label-pos label文字相对于图标的位置只能right或bottom默认right
* @property {String} label-color label字体颜色默认#606266
* @property {Object} custom-style icon的样式对象形式
* @property {String} custom-prefix 自定义字体图标库时需要写上此值
* @property {String | Number} margin-left label在右侧时与图标的距离单位rpx默认6
* @property {String | Number} margin-top label在下方时与图标的距离单位rpx默认6
* @property {String | Number} margin-bottom label在上方时与图标的距离单位rpx默认6
* @property {String | Number} margin-right label在左侧时与图标的距离单位rpx默认6
* @property {String} label-pos label相对于图标的位置只能right或bottom默认right
* @property {String} index 一个用于区分多个图标的值点击图标时通过click事件传出
* @property {String} hover-class 图标按下去的样式类用法同uni的view组件的hover-class参数详情见官网
* @event {Function} click 点击图标时触发
* @example <u-icon name="photo" color="#2979ff" size="28"></u-icon>
*/
export default {
name: 'u-icon',
props: {
//
name: {
type: String,
default: ''
},
//
color: {
type: String,
default: ''
},
// rpx
size: {
type: [Number, String],
default: 'inherit'
},
//
bold: {
type: Boolean,
default: false
},
// index
index: {
type: [Number, String],
default: ''
},
//
hoverClass: {
type: String,
default: ''
},
// 便
customPrefix: {
type: String,
default: 'uicon'
},
//
label: {
type: String,
default: ''
},
// label
labelPos: {
type: String,
default: 'right'
},
// label
labelSize: {
type: [String, Number],
default: '28'
},
// label
labelColor: {
type: String,
default: '#606266'
},
// label()
marginLeft: {
type: [String, Number],
default: '6'
},
// label()
marginTop: {
type: [String, Number],
default: '6'
},
// label()
marginRight: {
type: [String, Number],
default: '6'
},
// label()
marginBottom: {
type: [String, Number],
default: '6'
},
// mode
imgMode: {
type: String,
default: 'widthFix'
},
//
customStyle: {
type: Object,
default() {
return {}
}
},
},
computed: {
customClass() {
let classes = [];
classes.push(this.customPrefix + '-' + this.name);
// uViewu-iconfont
if (this.customPrefix == 'uicon') classes.push('u-iconfont');
else classes.push(this.customPrefix);
//
if (this.color && this.$u.config.type.includes(this.color)) classes.push('u-icon__icon--' + this.color);
// 使[a, b, c]
//
//#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
classes = classes.join(' ');
//#endif
return classes;
},
iconStyle() {
let style = {};
style = {
fontSize: this.size == 'inherit' ? 'inherit' : this.$u.addUnit(this.size),
fontWeight: this.bold ? 'bold' : 'normal'
};
//
if (this.color && !this.$u.config.type.includes(this.color)) style.color = this.color;
return style;
},
// name"/"
isImg() {
return this.name.indexOf('/') !== -1;
},
imgStyle() {
let style = {};
style.width = this.$u.addUnit(this.size);
style.height = this.$u.addUnit(this.size);
return style;
}
},
methods: {
click() {
this.$emit('click', this.index);
},
touchstart() {
this.$emit('touchstart', this.index);
}
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
@import '../../iconfont.css';
.u-icon {
display: inline-flex;
align-items: center;
&--left {
flex-direction: row-reverse;
align-items: center;
}
&--right {
flex-direction: row;
align-items: center;
}
&--top {
flex-direction: column-reverse;
justify-content: center;
}
&--bottom {
flex-direction: column;
justify-content: center;
}
&__icon {
&--primary {
color: $u-type-primary;
}
&--success {
color: $u-type-success;
}
&--error {
color: $u-type-error;
}
&--warning {
color: $u-type-warning;
}
&--info {
color: $u-type-info;
}
}
&__img {
height: auto;
will-change: transform;
}
&__label {
line-height: 1;
}
}
</style>

215
node_modules/uview-ui/components/u-image/u-image.vue

@ -0,0 +1,215 @@
<template>
<view
class="u-image"
@tap="onClick"
:style="[wrapStyle, backgroundStyle]"
>
<image
v-if="!isError"
:src="src"
:mode="mode"
@error="onErrorHandler"
@load="onLoadHandler"
:lazy-load="lazyLoad"
class="u-image__image"
:style="{
borderRadius: shape == 'circle' ? '50%' : $u.addUnit(borderRadius),
}"
></image>
<view v-if="showLoading && loading" class="u-image__loading" :style="{
borderRadius: shape == 'circle' ? '50%' : $u.addUnit(borderRadius),
}">
<slot v-if="$slots.loading" name="loading" />
<u-icon v-else :name="loadingIcon"></u-icon>
</view>
<view v-if="showError && isError && !loading" class="u-image__error" :style="{
borderRadius: shape == 'circle' ? '50%' : $u.addUnit(borderRadius),
}">
<slot v-if="$slots.error" name="error" />
<u-icon v-else :name="errorIcon"></u-icon>
</view>
</view>
</template>
<script>
export default {
props: {
//
src: {
type: String,
default: ''
},
//
mode: {
type: String,
default: 'aspectFill'
},
//
width: {
type: [String, Number],
default: '100%'
},
//
height: {
type: [String, Number],
default: 'auto'
},
// circle-square-
shape: {
type: String,
default: 'square'
},
//
borderRadius: {
type: [String, Number],
default: 0
},
// App
lazyLoad: {
type: Boolean,
default: true
},
//
showMenuByLongpress: {
type: Boolean,
default: true
},
//
loadingIcon: {
type: String,
default: 'photo'
},
//
errorIcon: {
type: String,
default: 'error-circle'
},
// slot
showLoading: {
type: Boolean,
default: true
},
// slot
showError: {
type: Boolean,
default: true
},
//
fade: {
type: Boolean,
default: true
},
//
webp: {
type: Boolean,
default: false
},
// ms
duration: {
type: [String, Number],
default: 500
}
},
data() {
return {
//
isError: false,
//
loading: true,
//
opacity: 1,
// props
durationTime: this.duration,
// png
backgroundStyle: {}
};
},
computed: {
wrapStyle() {
let style = {};
// addUnit()pxrpx
style.width = this.$u.addUnit(this.width);
style.height = this.$u.addUnit(this.height);
// 50%
style.borderRadius = this.shape == 'circle' ? '50%' : this.$u.addUnit(this.borderRadius);
// hidden
style.overflow = this.borderRadius > 0 ? 'hidden' : 'visible';
if(this.fade) {
style.opacity = this.opacity;
style.transition = `opacity ${Number(this.durationTime) / 1000}s ease-in-out`;
}
return style;
}
},
methods: {
//
onClick() {
this.$emit('click');
},
//
onErrorHandler() {
this.loading = false;
this.isError = true;
this.$emit('error');
},
// loading
onLoadHandler() {
this.loading = false;
this.isError = false;
this.$emit('load');
//
// fadepng
if(!this.fade) return this.removeBgColor();
// opacity1()0()1
this.opacity = 0;
// 00duration()
//
this.durationTime = 0;
// 50msH5
setTimeout(() => {
this.durationTime = this.duration;
this.opacity = 1;
setTimeout(() => {
this.removeBgColor();
}, this.durationTime)
}, 50)
},
//
removeBgColor() {
// png
this.backgroundStyle = {
backgroundColor: 'transparent'
};
}
}
};
</script>
<style scoped lang="scss">
@import '../../libs/css/style.components.scss';
.u-image {
background-color: $u-bg-color;
position: relative;
transition: opacity 0.5s ease-in-out;
&__image {
width: 100%;
height: 100%;
}
&__loading, &__error {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: $u-bg-color;
color: $u-tips-color;
font-size: 46rpx;
}
}
</style>

81
node_modules/uview-ui/components/u-index-anchor/u-index-anchor.vue

@ -0,0 +1,81 @@
<template>
<view class="u-index-anchor-wrapper" :id="$u.guid()" :style="[wrapperStyle]">
<view class="u-index-anchor " :class="[active ? 'u-index-anchor--active' : '']" :style="[customAnchorStyle]">
<slot v-if="useSlot" />
<block v-else>
<text>{{ index }}</text>
</block>
</view>
</view>
</template>
<script>
/**
* indexAnchor 索引列表锚点
* @description 通过折叠面板收纳内容区域,搭配<u-index-anchor>使用
* @tutorial https://www.uviewui.com/components/indexList.html#indexanchor-props
* @property {Boolean} use-slot 是否使用自定义内容的插槽默认false
* @property {String Number} index 索引字符如果定义了use-slot此参数自动失效
* @property {Object} custStyle 自定义样式对象形式"{color: 'red'}"
* @event {Function} default 锚点位置显示内容默认为索引字符
* @example <u-index-anchor :index="item" />
*/
export default {
name: "u-index-anchor",
props: {
useSlot: {
type: Boolean,
default: false
},
index: {
type: String,
default: ''
},
customStyle: {
type: Object,
default () {
return {}
}
}
},
data() {
return {
active: false,
wrapperStyle: {},
anchorStyle: {}
}
},
inject: ['UIndexList'],
mounted() {
this.UIndexList.children.push(this);
this.UIndexList.updateData();
},
computed: {
customAnchorStyle() {
return Object.assign(this.anchorStyle, this.customStyle);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-index-anchor {
box-sizing: border-box;
padding: 14rpx 24rpx;
color: #606266;
width: 100%;
font-weight: 500;
font-size: 28rpx;
line-height: 1.2;
background-color: rgb(245, 245, 245);
}
.u-index-anchor--active {
right: 0;
left: 0;
color: #2979ff;
background-color: #fff;
}
</style>

318
node_modules/uview-ui/components/u-index-list/u-index-list.vue

@ -0,0 +1,318 @@
<template>
<view class="u-index-bar">
<slot />
<view v-if="showSidebar" class="u-index-bar__sidebar" @touchstart.stop.prevent="onTouchMove" @touchmove.stop.prevent="onTouchMove"
@touchend.stop.prevent="onTouchStop" @touchcancel.stop.prevent="onTouchStop">
<view v-for="(item, index) in indexList" :key="index" class="u-index-bar__index" :style="{zIndex: zIndex + 1, color: activeAnchorIndex === index ? activeColor : ''}"
:data-index="index">
{{ item }}
</view>
</view>
<view class="u-indexed-list-alert" v-if="touchmove && indexList[touchmoveIndex]" :style="{
zIndex: alertZIndex
}">
<text>{{indexList[touchmoveIndex]}}</text>
</view>
</view>
</template>
<script>
var indexList = function() {
var indexList = [];
var charCodeOfA = 'A'.charCodeAt(0);
for (var i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i));
}
return indexList;
};
/**
* indexList 索引列表
* @description 通过折叠面板收纳内容区域,搭配<u-index-anchor>使用
* @tutorial https://www.uviewui.com/components/indexList.html#indexanchor-props
* @property {Number String} scroll-top 当前滚动高度自定义组件无法获得滚动条事件所以依赖接入方传入
* @property {Array} index-list 索引字符列表数组默认A-Z
* @property {Number String} z-index 锚点吸顶时的层级默认965
* @property {Boolean} sticky 是否开启锚点自动吸顶默认true
* @property {Number String} offset-top 锚点自动吸顶时与顶部的距离默认0
* @property {String} highlight-color 锚点和右边索引字符高亮颜色默认#2979ff
* @event {Function} select 选中右边索引字符时触发
* @example <u-index-list :scrollTop="scrollTop"></u-index-list>
*/
export default {
name: "u-index-list",
props: {
sticky: {
type: Boolean,
default: true
},
zIndex: {
type: [Number, String],
default: ''
},
scrollTop: {
type: [Number, String],
default: 0,
},
offsetTop: {
type: [Number, String],
default: 0
},
indexList: {
type: Array,
default () {
return indexList()
}
},
activeColor: {
type: String,
default: '#2979ff'
}
},
created() {
// #ifdef H5
this.stickyOffsetTop = this.offsetTop ? uni.upx2px(this.offsetTop) : 44;
// #endif
// #ifndef H5
this.stickyOffsetTop = this.offsetTop ? uni.upx2px(this.offsetTop) : 0;
// #endif
// createdchildrendataprovide/inject
// push
this.children = [];
},
provide() {
return {
UIndexList: this
}
},
data() {
return {
activeAnchorIndex: 0,
showSidebar: true,
// children: [],
touchmove: false,
touchmoveIndex: 0,
}
},
watch: {
scrollTop() {
this.updateData()
}
},
computed: {
// toastz-index
alertZIndex() {
return this.$u.zIndex.toast;
}
},
methods: {
updateData() {
this.timer && clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.showSidebar = !!this.children.length;
this.setRect().then(() => {
this.onScroll();
});
}, 0);
},
setRect() {
return Promise.all([
this.setAnchorsRect(),
this.setListRect(),
this.setSiderbarRect()
]);
},
setAnchorsRect() {
return Promise.all(this.children.map((anchor, index) => anchor
.$uGetRect('.u-index-anchor-wrapper')
.then((rect) => {
Object.assign(anchor, {
height: rect.height,
top: rect.top
});
})));
},
setListRect() {
return this.$uGetRect('.u-index-bar').then((rect) => {
Object.assign(this, {
height: rect.height,
top: rect.top + this.scrollTop
});
});
},
setSiderbarRect() {
return this.$uGetRect('.u-index-bar__sidebar').then(rect => {
this.sidebar = {
height: rect.height,
top: rect.top
};
});
},
getActiveAnchorIndex() {
const {
children
} = this;
const {
sticky
} = this;
for (let i = this.children.length - 1; i >= 0; i--) {
const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
const reachTop = sticky ? preAnchorHeight : 0;
if (reachTop >= children[i].top) {
return i;
}
}
return -1;
},
onScroll() {
const {
children = []
} = this;
if (!children.length) {
return;
}
const {
sticky,
stickyOffsetTop,
zIndex,
scrollTop,
activeColor
} = this;
const active = this.getActiveAnchorIndex();
this.activeAnchorIndex = active;
if (sticky) {
let isActiveAnchorSticky = false;
if (active !== -1) {
isActiveAnchorSticky =
children[active].top <= 0;
}
children.forEach((item, index) => {
if (index === active) {
let wrapperStyle = '';
let anchorStyle = {
color: `${activeColor}`
};
if (isActiveAnchorSticky) {
wrapperStyle = {
height: `${children[index].height}px`
};
anchorStyle = {
position: 'fixed',
top: `${stickyOffsetTop}px`,
zIndex: `${zIndex ? zIndex : this.$u.zIndex.indexListSticky}`,
color: `${activeColor}`
};
}
item.active = active;
item.wrapperStyle = wrapperStyle;
item.anchorStyle = anchorStyle;
} else if (index === active - 1) {
const currentAnchor = children[index];
const currentOffsetTop = currentAnchor.top;
const targetOffsetTop = index === children.length - 1 ?
this.top :
children[index + 1].top;
const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
const translateY = parentOffsetHeight - currentAnchor.height;
const anchorStyle = {
position: 'relative',
transform: `translate3d(0, ${translateY}px, 0)`,
zIndex: `${zIndex ? zIndex : this.$u.zIndex.indexListSticky}`,
color: `${activeColor}`
};
item.active = active;
item.anchorStyle = anchorStyle;
} else {
item.active = false;
item.anchorStyle = '';
item.wrapperStyle = '';
}
});
}
},
onTouchMove(event) {
this.touchmove = true;
const sidebarLength = this.children.length;
const touch = event.touches[0];
const itemHeight = this.sidebar.height / sidebarLength;
let clientY = 0;
clientY = touch.clientY;
let index = Math.floor((clientY - this.sidebar.top) / itemHeight);
if (index < 0) {
index = 0;
} else if (index > sidebarLength - 1) {
index = sidebarLength - 1;
}
this.touchmoveIndex = index;
this.scrollToAnchor(index);
},
onTouchStop() {
this.touchmove = false;
this.scrollToAnchorIndex = null;
},
scrollToAnchor(index) {
if (this.scrollToAnchorIndex === index) {
return;
}
this.scrollToAnchorIndex = index;
const anchor = this.children.find((item) => item.index === this.indexList[index]);
if (anchor) {
this.$emit('select', anchor.index);
uni.pageScrollTo({
duration: 0,
scrollTop: anchor.top + this.scrollTop
});
}
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-index-bar {
position: relative
}
.u-index-bar__sidebar {
position: fixed;
top: 50%;
right: 0;
display: flex;
flex-direction: column;
text-align: center;
transform: translateY(-50%);
user-select: none;
z-index: 99;
}
.u-index-bar__index {
font-weight: 500;
padding: 8rpx 18rpx;
font-size: 22rpx;
line-height: 1
}
.u-indexed-list-alert {
position: fixed;
width: 120rpx;
height: 120rpx;
right: 90rpx;
top: 50%;
margin-top: -60rpx;
border-radius: 24rpx;
font-size: 50rpx;
color: #fff;
background-color: rgba(0, 0, 0, 0.65);
display: flex;
justify-content: center;
align-items: center;
padding: 0;
z-index: 9999999;
}
.u-indexed-list-alert text {
line-height: 50rpx;
}
</style>

351
node_modules/uview-ui/components/u-input/u-input.vue

@ -0,0 +1,351 @@
<template>
<view
class="u-input"
:class="{
'u-input--border': border,
'u-input--error': validateState
}"
:style="{
padding: `0 ${border ? 20 : 0}rpx`,
borderColor: borderColor,
textAlign: inputAlign
}"
@tap.stop="inputClick"
>
<textarea
v-if="type == 'textarea'"
class="u-input__input u-input__textarea"
:style="[getStyle]"
:value="value"
:placeholder="placeholder"
:placeholderStyle="placeholderStyle"
:disabled="disabled"
:maxlength="inputMaxlength"
:fixed="fixed"
:focus="focus"
:autoHeight="autoHeight"
@input="handleInput"
@blur="handleBlur"
@focus="onFocus"
@confirm="onConfirm"
/>
<input
v-else
class="u-input__input"
:type="type == 'password' ? 'text' : type"
:style="[getStyle]"
:value="defaultValue"
:password="type == 'password' && !showPassword"
:placeholder="placeholder"
:placeholderStyle="placeholderStyle"
:disabled="disabled || type === 'select'"
:maxlength="inputMaxlength"
:focus="focus"
:confirmType="confirmType"
:cursor-spacing="getCursorSpacing"
@focus="onFocus"
@blur="handleBlur"
@input="handleInput"
@confirm="onConfirm"
/>
<view class="u-input__right-icon u-flex">
<view class="u-input__right-icon__clear u-input__right-icon__item" v-if="clearable && value != '' && focused">
<u-icon size="32" name="close-circle-fill" color="#c0c4cc" @touchstart="onClear"/>
</view>
<view class="u-input__right-icon__clear u-input__right-icon__item" v-if="passwordIcon && type == 'password'">
<u-icon size="32" :name="!showPassword ? 'eye' : 'eye-fill'" color="#c0c4cc" @click="showPassword = !showPassword"/>
</view>
<view class="u-input__right-icon--select u-input__right-icon__item" v-if="type == 'select'" :class="{
'u-input__right-icon--select--reverse': selectOpen
}">
<u-icon name="arrow-down-fill" size="26" color="#c0c4cc"></u-icon>
</view>
</view>
</view>
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
/**
* input 输入框
* @description 此组件为一个输入框默认没有边框和样式是专门为配合表单组件u-form而设计的利用它可以快速实现表单验证输入内容下拉选择等功能
* @tutorial http://uviewui.com/components/input.html
* @property {String} type 模式选择见官网说明
* @property {Boolean} clearable 是否显示右侧的清除图标(默认true)
* @property {} v-model 用于双向绑定输入框的值
* @property {String} input-align 输入框文字的对齐方式(默认left)
* @property {String} placeholder placeholder显示值(默认 '请输入内容')
* @property {Boolean} disabled 是否禁用输入框(默认false)
* @property {String Number} maxlength 输入框的最大可输入长度(默认140)
* @property {String Number} cursor-spacing 指定光标与键盘的距离单位px(默认0)
* @property {String} placeholderStyle placeholder的样式字符串形式"color: red;"(默认 "color: #c0c4cc;")
* @property {String} confirm-type 设置键盘右下角按钮的文字仅在type为text时生效(默认done)
* @property {Object} custom-style 自定义输入框的样式对象形式
* @property {Boolean} focus 是否自动获得焦点(默认false)
* @property {Boolean} fixed 如果type为textarea且在一个"position:fixed"的区域需要指明为true(默认false)
* @property {Boolean} password-icon type为password时是否显示右侧的密码查看图标(默认true)
* @property {Boolean} border 是否显示边框(默认false)
* @property {String} border-color 输入框的边框颜色(默认#dcdfe6)
* @property {Boolean} auto-height 是否自动增高输入区域type为textarea时有效(默认true)
* @property {String Number} height 高度单位rpx(text类型时为70textarea时为100)
* @example <u-input v-model="value" :type="type" :border="border" />
*/
export default {
name: 'u-input',
mixins: [Emitter],
props: {
value: {
type: [String, Number],
default: ''
},
// textareatextnumber
type: {
type: String,
default: 'text'
},
inputAlign: {
type: String,
default: 'left'
},
placeholder: {
type: String,
default: '请输入内容'
},
disabled: {
type: Boolean,
default: false
},
maxlength: {
type: [Number, String],
default: 140
},
placeholderStyle: {
type: String,
default: 'color: #c0c4cc;'
},
confirmType: {
type: String,
default: 'done'
},
//
customStyle: {
type: Object,
default() {
return {};
}
},
// textarea position:fixed fixed true
fixed: {
type: Boolean,
default: false
},
//
focus: {
type: Boolean,
default: false
},
//
passwordIcon: {
type: Boolean,
default: true
},
// input|textarea
border: {
type: Boolean,
default: false
},
//
borderColor: {
type: String,
default: '#dcdfe6'
},
autoHeight: {
type: Boolean,
default: true
},
// type=selectselect
// open-close-
selectOpen: {
type: Boolean,
default: false
},
// rpx
height: {
type: [Number, String],
default: ''
},
//
clearable: {
type: Boolean,
default: true
},
// px
cursorSpacing: {
type: [Number, String],
default: 0
}
},
data() {
return {
defaultValue: this.value,
inputHeight: 70, // input
textareaHeight: 100, // textarea
validateState: false, // input
focused: false, //
showPassword: false, //
marginRight: 0, //
};
},
watch: {
value(nVal, oVal) {
this.defaultValue = nVal;
// select(inputdisabled@input)@input
if(nVal != oVal && this.type == 'select') this.handleInput({
detail: {
value: nVal
}
})
// input-align=right
if(oVal == '' && this.inputAlign == 'right') this.getMarginRight();
},
focused(nVal) {
if(this.clearable && this.value) {
this.getMarginRight();
}
}
},
computed: {
// uniappinputmaxlength
inputMaxlength() {
return Number(this.maxlength);
},
getStyle() {
let style = {};
// typeinputtextare
style.minHeight = this.height ? this.height + 'rpx' : this.type == 'textarea' ?
this.textareaHeight + 'rpx' : this.inputHeight + 'rpx';
style.marginRight = this.marginRight + 'px';
style = Object.assign(style, this.customStyle);
return style;
},
//
getCursorSpacing() {
return Number(this.cursorSpacing);
}
},
created() {
// u-form-item
this.$on('on-form-item-error', this.onFormItemError);
},
mounted() {
this.getMarginRight();
},
methods: {
//
getMarginRight() {
this.$nextTick(() => {
this.$uGetRect('.u-input__right-icon').then(res => {
this.marginRight = res.width;
})
})
},
/**
* change 事件
* @param event
*/
handleInput(event) {
// model
this.defaultValue = event.detail.value;
// vue return
this.$emit('input', event.detail.value);
// u-form-itemthis.$emit('input')
// u-form-item
this.$nextTick(() => {
// u-form-item
this.dispatch('u-form-item', 'on-form-change', event.detail.value);
});
},
/**
* blur 事件
* @param event
*/
handleBlur(event) {
this.focused = false;
// vue return
this.$emit('blur', event.detail.value);
this.$nextTick(() => {
// u-form-item
this.dispatch('u-form-item', 'on-form-blur', event.detail.value);
});
},
onFormItemError(status) {
this.validateState = status;
},
onFocus(event) {
this.focused = true;
this.$emit('focus');
},
onConfirm(e) {
this.$emit('confirm', e.detail.value);
},
onClear(event) {
this.$emit('input', '');
},
inputClick() {
this.$emit('click');
}
}
};
</script>
<style lang="scss" scoped>
.u-input {
position: relative;
flex: 1;
&__input {
//height: $u-form-item-height;
font-size: 28rpx;
color: $u-main-color;
}
&__textarea {
width: auto;
font-size: 28rpx;
color: $u-main-color;
padding: 10rpx 0;
line-height: normal;
}
&--border {
border-radius: 6rpx;
border-radius: 4px;
border: 1px solid $u-form-item-border-color;
}
&--error {
border-color: $u-type-error!important;
}
&__right-icon {
position: absolute;
right: 0;
top: 50%;
z-index: 3;
transform: translateY(-50%);
&__item {
margin-left: 10rpx;
}
&--select {
transition: transform .4s;
&--reverse {
transform: rotate(-180deg);
}
}
}
}
</style>

205
node_modules/uview-ui/components/u-keyboard/u-keyboard.vue

@ -0,0 +1,205 @@
<template>
<u-popup class="" :mask="mask" :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto"
:safeAreaInsetBottom="safeAreaInsetBottom" @close="popupClose">
<slot />
<view class="u-tooltip" v-if="tooltip">
<view class="u-tooltip-item u-tooltip-cancel" hover-class="u-tooltip-cancel-hover" @tap="onCancel">
{{cancelBtn ? '取消' : ''}}
</view>
<view v-if="showTips" class="u-tooltip-item u-tooltip-tips">
{{tips ? tips : mode == 'number' ? '数字键盘' : mode == 'card' ? '身份证键盘' : '车牌号键盘'}}
</view>
<view v-if="confirmBtn" @tap="onConfirm" class="u-tooltip-item u-tooltips-submit" hover-class="u-tooltips-submit-hover">
{{confirmBtn ? '完成' : ''}}
</view>
</view>
<block v-if="mode == 'number' || mode == 'card'">
<u-number-keyboard :random="random" @backspace="backspace" @change="change" :mode="mode" :dotEnabled="dotEnabled"></u-number-keyboard>
</block>
<block v-else>
<u-car-keyboard :random="random" @backspace="backspace" @change="change"></u-car-keyboard>
</block>
</u-popup>
</template>
<script>
/**
* keyboard 键盘
* @description 此为uViw自定义的键盘面板内含了数字键盘车牌号键身份证号键盘3中模式都有可以打乱按键顺序的选项
* @tutorial https://www.uviewui.com/components/keyboard.html
* @property {String} mode 键盘类型见官网基本使用的说明默认number
* @property {Boolean} dot-enabled 是否显示"."按键只在mode=number时有效默认true
* @property {Boolean} tooltip 是否显示键盘顶部工具条默认true
* @property {String} tips 工具条中间的提示文字见上方基本使用的说明如不需要请传""空字符
* @property {Boolean} cancel-btn 是否显示工具条左边的"取消"按钮默认true
* @property {Boolean} confirm-btn 是否显示工具条右边的"完成"按钮默认true
* @property {Boolean} mask 是否显示遮罩默认true
* @property {Number String} z-index 弹出键盘的z-index值默认1075
* @property {Boolean} random 是否打乱键盘按键的顺序默认false
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Boolean} mask-close-able 是否允许点击遮罩收起键盘默认true
* @event {Function} change 按键被点击(不包含退格键被点击)
* @event {Function} cancel 键盘顶部工具条左边的"取消"按钮被点击
* @event {Function} confirm 键盘顶部工具条右边的"完成"按钮被点击
* @event {Function} backspace 键盘退格键被点击
* @example <u-keyboard mode="number" v-model="show"></u-keyboard>
*/
export default {
name: "u-keyboard",
props: {
// number-card-car-
mode: {
type: String,
default: 'number'
},
// "."
dotEnabled: {
type: Boolean,
default: true
},
//
tooltip: {
type: Boolean,
default: true
},
//
showTips: {
type: Boolean,
default: true
},
//
tips: {
type: String,
default: ''
},
// ""
cancelBtn: {
type: Boolean,
default: true
},
// ""
confirmBtn: {
type: Boolean,
default: true
},
//
random: {
type: Boolean,
default: false
},
// iPhoneX
safeAreaInsetBottom: {
type: Boolean,
default: false
},
//
maskCloseAble: {
type: Boolean,
default: true
},
//
value: {
type: Boolean,
default: false
},
//
mask: {
type: Boolean,
default: true
},
// z-index
zIndex: {
type: [Number, String],
default: ''
}
},
data() {
return {
//show: false
}
},
computed: {
uZIndex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
methods: {
change(e) {
this.$emit('change', e);
},
//
popupClose() {
// inputpropsvalue
this.$emit('input', false);
},
//
onConfirm() {
this.popupClose();
this.$emit('confirm');
},
//
onCancel() {
this.popupClose();
this.$emit('cancel');
},
// 退
backspace() {
this.$emit('backspace');
},
//
// close() {
// this.show = false;
// },
// //
// open() {
// this.show = true;
// }
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-keyboard {
position: relative;
z-index: 1003;
}
.u-tooltip {
display: flex;
justify-content: space-between;
}
.u-tooltip-item {
color: #333333;
flex: 0 0 33.333333%;
text-align: center;
padding: 20rpx 10rpx;
font-size: 28rpx;
}
.u-tooltips-submit {
text-align: right;
flex-grow: 1;
flex-wrap: 0;
padding-right: 40rpx;
color: $u-type-primary;
}
.u-tooltip-cancel {
text-align: left;
flex-grow: 1;
flex-wrap: 0;
padding-left: 40rpx;
color: #888888;
}
.u-tooltips-submit-hover {
color: $u-type-success;
}
.u-tooltip-cancel-hover {
color: #333333;
}
</style>

227
node_modules/uview-ui/components/u-lazy-load/u-lazy-load.vue

@ -0,0 +1,227 @@
<template>
<view class="u-wrap" :style="{
opacity: Number(opacity),
borderRadius: borderRadius + 'rpx',
// time,duration(prop)
transition: `opacity ${time / 1000}s ease-in-out`
}"
:class="'u-lazy-item-' + elIndex">
<view :class="'u-lazy-item-' + elIndex">
<image :style="{borderRadius: borderRadius + 'rpx', height: imgHeight}" v-if="!isError" class="u-lazy-item"
:src="isShow ? image : loadingImg" :mode="imgMode" @load="imgLoaded" @error="loadError" @tap="clickImg"></image>
<image :style="{borderRadius: borderRadius + 'rpx', height: imgHeight}" class="u-lazy-item error" v-else :src="errorImg"
:mode="imgMode" @load="errorImgLoaded" @tap="clickImg"></image>
</view>
</view>
</template>
<script>
/**
* lazyLoad 懒加载
* @description 懒加载使用的场景为页面有很多图片时APP会同时加载所有的图片导致页面卡顿各个位置的图片出现前后不一致等.
* @tutorial https://www.uviewui.com/components/lazyLoad.html
* @property {String Number} index 用户自定义值在事件触发时回调用以区分是哪个图片
* @property {String} image 图片路径
* @property {String} loading-img 预加载时的占位图
* @property {String} error-img 图片加载出错时的占位图
* @property {String} threshold 触发加载时的位置见上方说明单位 rpx默认300
* @property {String Number} duration 图片加载成功时淡入淡出时间单位ms默认
* @property {String} effect 图片加载成功时淡入淡出的css动画效果默认ease-in-out
* @property {Boolean} is-effect 图片加载成功时是否启用淡入淡出效果默认true
* @property {String Number} border-radius 图片圆角值单位rpx默认0
* @property {String Number} height 图片高度注意实际高度可能受img-mode参数影响默认450
* @property {String Number} mg-mode 图片的裁剪模式详见image组件裁剪模式默认widthFix
* @event {Function} click 点击图片时触发
* @event {Function} load 图片加载成功时触发
* @event {Function} error 图片加载失败时触发
* @example <u-lazy-load :image="image" :loading-img="loadingImg" :error-img="errorImg"></u-lazy-load>
*/
export default {
name: 'u-lazy-load',
props: {
index: {
type: [Number, String]
},
//
image: {
type: String,
default: ''
},
//
imgMode: {
type: String,
default: 'widthFix'
},
//
loadingImg: {
type: String,
default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAMAAAC3Ycb+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM0QjNBQjkyQUQ2MTFFQTlCNUQ4RTIzNDE5RUIxNjciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM0QjNBQkEyQUQ2MTFFQTlCNUQ4RTIzNDE5RUIxNjciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzRCM0FCNzJBRDYxMUVBOUI1RDhFMjM0MTlFQjE2NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzRCM0FCODJBRDYxMUVBOUI1RDhFMjM0MTlFQjE2NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtRHfPcAAAAzUExURZWVldfX18PDw62trZubm9zc3Li4uKGhoebm5tLS0uHh4c3Nzaenp729vcjIyLKysuvr6141L40AAAcXSURBVHja7NzZlqpGAEBR5lG0//9rIw7IJKJi4or7PGTdtN10wr5SVAEGf/qqArsAiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAg+nmQFMi5Jis+sIniED23jSzIgLTtg2D//iYme/8QBM/9lQ+CAEhbNLM3N9hEHAThX7GPCiBfAxK1b51kD+R7QMLjXg7iCsgWIPUh7pfVozG791oeBPngm48G583uW5GkBvI+SBaM2xXDn1oqum423bX/mgF5FySc2cv93Voug9TdZotsggnkBZB2NzbhrSY5HnoG07jei8dvzsJB/c3W60SALILE46+WCztsbhPR7R2VJq0ukEcT49nyy8QhaKcRa3fYHZD4+ufqOJAcgDz8/59vtw1I3QP5K6JsOG0vm3hce4I8LQp/BaRZGJC3AAn7IKOKXbC+7EdA5vdmmVwOLksgRThqOqiH4XEGsht+peoPUE8U/jJIO5OLH4GEwUslV5G0PTBG5Uiw/Y2jyigO3l9HAHKv9PYb82LloH74dZBoBUgar+l48NsNvtD0fkez9iwrAvIYZDRCl+Xs149Hm/KZmQ+QjUCiO1ei4ru7EsgnQYrkznlQb7thCuRfAzlOAPN72427P4VA/i2Q/DKT/Ls/VR8fvIBsDZIuz7TPF6TCbnk4GJkB2RokejTjuE7/unlgCuSTIO0Cy+Plp6vDfnQlBchy8QtjSHVd3EgmK1bHLm+H6+nXYbz2DuQRSPnqoL7vvq0u70on4zvxgCyWD3b9UyDVdW24PaWaiGTnFZJwPIQAebDpIKheBIm7n124ZthMJipAlkqHO+IZkP1tbfzOJark/A7MgKyvvl60fRqkvXfhuow+t9+q00+0/yyBrK8ZngOtBzldhw2X9tvpNGty0gvkmbPeJ0Cy/r09s/stbmfo0yMWkEdjevgKyOn2t2pxv7UXoibTdCDLje9/Ww1ymqzn87dbp92242ZmMRjI8hASvwKSLq4udqN6ksw8nxXN3tszD9L8Gkg+2mFrQYql5az4tvFj5xOx4VwnSdeBtGdyPwUytxK77pBVlNHdO7OK3rh/eTPUvdutT3fO52tuHMqD4N7llv8pyOQQ//w19YVDfX27+Sfuby9/6nau4pdA8vEdOZuChEH/quHt0Jg+IRJ/5+PrHwKZXfjbDiS73Zo7mu5UkzX7uTsXe0e/7nC3ePf1O69+BUg2XDfZCqSqOu7rGVf8cHBe8zhC2b61dtUHXv0OkGo6ZL4JkpbRYXdUaFevivx2M/1GIOctNh949TtAoumQ+TpIHMX54CJu+8BDd8FkE5BqcZh/59XvAClmTvKfB0nDqIlHo3T70SftyW1eX9dXtgQJqs1f/Q6QaOa/7wmQKtxH8eiGoCRuovODIO3VxOMmruZbHrLyD7z6DSDtGyT7ew1kf9hNn07c986JTovzzem0Id9wUG+Vk/IDr34DSNR7huZJkMFT6vEhqrPx/j5cnlZML8N6/PAzh9Y99Flm5Yde/c9BquDOkvkKkMP58dA4qi9vivE8JOvGz/j8FokfPpr288+pH2ZPOZrLmeGD+7KOh6dqYWJ48ki7yUg0tz0go/fv/LLddfV3sgOLJyaGPY/zrSlh1a36Arkzoue9CyG35ze6E6/dzO2Ga0EGHqdRJIkfn9/8OEjTW8Vq91ZWh39FeehWA7Nu9ft8CpUEk1WWOyDF0OPyEU2Pnzf/bZC0P6IPzmAvu7KauQBVrgKpJ0tG2arHzX8e5Pb3PezNs/PrX+3JMyCLn9XXf37tPFHvt09WfCDDjx+yyn1/p1V11j7GnB/q3leLuVva79S/tzed+db08YpF4uOZtmz/9oXWMq6BCAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiAALELvqt/BBgACqVeUBXxcCkAAAAASUVORK5CYII='
},
//
errorImg: {
type: String,
default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAMAAAC3Ycb+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODdDMjhENDYyQUQ2MTFFQTlDQ0VBODgxQjFFOEEyMEMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODdDMjhENDcyQUQ2MTFFQTlDQ0VBODgxQjFFOEEyMEMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4N0MyOEQ0NDJBRDYxMUVBOUNDRUE4ODFCMUU4QTIwQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4N0MyOEQ0NTJBRDYxMUVBOUNDRUE4ODFCMUU4QTIwQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhLwhikAAAAzUExURZWVldfX162trcPDw5ubm7i4uNzc3Obm5s3NzaGhoeHh4cjIyKenp9LS0r29vbKysuvr67sDMEkAAAlpSURBVHja7NzpYqMgAIVRUVHc8/5PO66R1WAbOzX97q+ZtDEpR0AWTR7kVyWhCAAhgABCAAGEAAIIAQQQAggBBBACCCAEEEAIIIAQQAgggBBAACGAAEIAAYQAQgABhAACCAEEEAIIIAQQAgggBBBACCCAEEAAIYAQQAAhgABCAAGEAAIIAYQAAggBBBACCCAEEEAIIAQQQAgggBBAACGAAEIAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAAIYAQQAAhgABCAAGEAAIIAYQAAggBBBACCCAEEEAIIAQQQAgggBBAACGAAEIAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAIIIAQQAAhgABCAAGEAEIAAYQAAggBBBACCCAEEAIIIAQQQAgggBBAACGAEEAAIYAAsqeX5QWHKIcs/Ptl03lfL4zDFPWfBGmSpPn+IZzSH5KkCL5B+n+oklwz6Iz//R2QzFOabzhEmiRirAmZt/bl0w/dpMbLqeeo4wEdpC7zR5WAPKziHKtO7ql+ReKvIa9BxgNaL5ZtEkpeAGIVp5jKJa09xVo9vgSSzQcszdYvmOqjQNSQ6pHK6rO1n1Xj32788miwHLaZz1Tl9i/yayDlYJ/60/+lp8GSY7OY1B8E4p55bWmfquFk22GLuUUxi78cX+m+BjL2GLkhMrV+/muS6Sfic0CEp5T1Yu2OQdTzsKV0MJV73KVjroyTffxfuv5Tf3fd6iLT9wz8YdVHgUzF2Is9/Xhi5sYJqP1w/GUpjOiHVbaI0w2L+pg3GZzvtokcgHxWDXHaiy78l3sPke01qphamT5c+dqyeAGSumdL/mkggauTam0e3L/mPEiqtzKDbl0Z1Wn8xOa4ySo8X/7TQIJnY/seEKWf12UmC72CKP9xYjr19RPT7NNA+oMO+R0gwmlotAry+C6I0f59ch8yXVQOr0BKYcXt1IUYRyCt+Ur9HGsrQKI79WY9sY9ARPKlzFOFdb41ioD8b5Bp+mqeeRKAxINkESBFGpOpKhgv9OuYpH8A8l4Qa3qp60Kl2/k+rG2sWafuuyCBafb2j4JkgZUob3nWcmicpkxEgmTLLGejTxnWSWCi8lPmsk6DlIHFJv24ojiYyYoGacwL8zXTLEAVaDI/Ybb3NIgKDSv2oXpmHkvNs+PTpMASEdlk7fOZeRk37fwJ6yGnQarQsGIfqqcvx43rTOXY6jf7uKXdRzdLDRPbjIrx1cIj3Kr4KyBFezzgUGuR5893qkOQ19fR2uVBaU+r16LphJNOiatK7PeBZK/Kb+tUn71rcQjSvARpghfH/yG/D2RetTuI3N5QrMWdP46brP7FmKZ//CGQ9At9SL01DLkzY/Vs8Z97fQZ7gelw7jHqCz+/Wile5J4g3Vc79eb5a6oLSue+Ve83gaSv2jp5PxCzjzwFUm9zw9MllSMil1kS4d2E9SaQ1xNo9wMxx0+nQNLnew/WDHvveMAHYm08mofl3TFI/8pD3Q6kMAv6DIi2jTCwRJUvNdDYrrJum9oHhusCbWALonwxBRk1vXMnEGWuT5wAmfYuVGUYpJ7fUZujCN92hvzwWlrFgxSfANKb10DxIMbShnfrynyZZV30imA7P43ArXXHbvBVkTCIuGy25AdBrHmNeBCpL214QdLp9LZarG3IMWrmW0ehtuO7F2PS09UcgqS3B7FKPhpknrStD0HGF/vQRne37LwLG8EbHT4WxN7/Fg0yD9Yr/3br4nnstA+0Il6QxzdBmg8A6a2/IRbkcK9h/uzV8zywF/oSkOyageCPglRWgcWClHnEzs9q/t/SENVXgFijlsq3VtXdCsRp4qObrLLLgjuzSq3fX89ZZW6AfxNIzF6X9FYgThN/fk093KkvHX/hbWd+DqS/FUhlf+G3gohEXzVs3g9iDluWoaW8fL73QhB34u+tIHIf19nLuF4Q98a09Eynnl56q+ePgEhnX+dbQOp6H5XnJ0ACd8dFgkwf12nTOTcEqd2pom+CFF02TIPw6dKmrLS5qOtBpo8b5quUtrwrSGbuqPkeSJqllTFHO02NPxdMrm+y5LKdWyWXjw4vA5nGEtnjuyCFyHqNYvEolzmASm3zK1Eg5zr13lhqV1tlksnVw8Pkwgri7O07AVKLJkutRYw87bPlRpBpNXE8xGb+fhBlvEGrGPLqViu5sILIx9dAmqF1705sxF4M8+R8P5dOdQwi12fMnATpjJ2JSt/POIvU9wPJEs/jduJAjLvU0yFT0i64Yb1bsVi79dA4pEy3TzoHMq2O7Re4vXm5O9+l290NpE4CU+YRIMNye2iaqbVS2AUnn2fsekthYKReVNutVedA5juttyIXrT38mOds+ps9DWhwL7GWc61/DVKPzVN9UHDarf1icU98IOU8tm6L031Iq63t1tKzj3fe/FCpO4F0/i0Z2+yvA1KeGBjqj1qYx8/zoxpKZ1Yl367I1k+sfcft/QPy9csXy/32qX1qLZsrryG5BGQaRj0vc/b7N54XXq293TCLB5HO42Fy517obW19b+qjl3CHp0fdLJcWvmdy1etESi/uAdJrs1hTaUklHuW8qSDdC3UfXVR5cnD3rAFSSqtFb7z7eapErx7rC739jCXfbK3aWiipjXo8UbmxXPa7QQq9R289j2Gr88N7Ag5AlHPRKc37pNZv0CZtX1tVMG6rm8qW1/KlCgQvcMss933ybwXZz3dReW5yce4ByZtHFIhwT9kmjxg8BzbKDUe1PB9edBJqSN7/KM1LmqyuMZ5BpeTUw1aD/uDI0relPfSHa/Wn8Pxq1BNfxy/h3IdwOJqIKumb9CHvTqMefyY82RoQAgggBBBACCCAEEAAIYAQQAAhgABCAAGEAAIIAYQAAggBBBACCCAEEEAIIAQQQAgggBBAACGAAEIAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAIIIAQQAAhgABCAAGEAEIAAYQAAggBBBACCCAEEAIIIAQQQAgggBBAACGAEEAAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAIIIAQQAAhgABCAAGEAEIAAYQAAggBBBACCCAEEAIIIAQQQAgggBBAACGAEEAAIYAAQgABhAACCAGEAAIIAQQQAgggBBBACCAEEEAIIIAQQAAhgABCACGAAEIAAYQAAggBBBACCAEEEAIIIAQQQAggfyL/BBgA8PgLdH0TBtkAAAAASUVORK5CYII='
},
// rpx
// ()
threshold: {
type: [Number, String],
default: 100
},
//
duration: {
type: [Number, String],
default: 500
},
// 线
// linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n);
effect: {
type: String,
default: 'ease-in-out'
},
// 使
isEffect: {
type: Boolean,
default: true
},
//
borderRadius: {
type: [Number, String],
default: 0
},
// rpx
height: {
type: [Number, String],
default: '450'
}
},
data() {
return {
isShow: false,
opacity: 1,
time: this.duration,
loadStatus: '', //
isError: false, //
elIndex: this.$u.guid()
}
},
computed: {
// thresholdrpxpx
getThreshold() {
// thresholdthis.threshold
let thresholdPx = uni.upx2px(Math.abs(this.threshold));
return this.threshold < 0 ? -thresholdPx : thresholdPx;
},
// auto%
imgHeight() {
return this.height == 'auto' ? 'auto' : String(this.height).indexOf('%') != -1 ? this.height : this.height + 'rpx';
}
},
created() {
// data
this.observer = {};
},
watch: {
isShow(nVal) {
//
if (!this.isEffect) return;
this.time = 0;
// opacity1()0()1
this.opacity = 0;
// 30msH5
setTimeout(() => {
this.time = this.duration;
this.opacity = 1;
}, 30)
}
},
methods: {
// ,loadlazy-loading-loaded-
clickImg() {
let whichImg = '';
// isShowfalse
if (this.isShow == false) whichImg = 'lazyImg';
// isErrortrue
// ~
else if (this.isError == true) whichImg = 'errorImg';
//
else whichImg = 'realImg';
// index
this.$emit('click', this.index);
},
// isShow
imgLoaded() {
//
if (this.loadStatus == '') {
this.loadStatus = 'lazyed';
}
//
else if (this.loadStatus == 'lazyed') {
this.loadStatus = 'loaded';
this.$emit('load', this.index);
}
},
//
errorImgLoaded() {
this.$emit('error', this.index);
},
//
loadError() {
this.isError = true;
},
disconnectObserver(observerName) {
const observer = this[observerName];
observer && observer.disconnect();
},
},
beforeDestroy() {
//
//observer.disconnect();
},
mounted() {
// uOnReachBottommixin.js
this.$nextTick(() => {
uni.$once('uOnReachBottom', () => {
if (!this.isShow) this.isShow = true;
});
})
// mounted30ms
setTimeout(() => {
// uni.createIntersectionObserverthis.createIntersectionObserver
this.disconnectObserver('contentObserver');
const contentObserver = uni.createIntersectionObserver(this);
//
// https://blog.csdn.net/qq_25324335/article/details/83687695
contentObserver.relativeToViewport({
bottom: this.getThreshold,
}).observe('.u-lazy-item-' + this.elIndex, (res) => {
if (res.intersectionRatio > 0) {
//
this.isShow = true;
//
this.disconnectObserver('contentObserver');
}
})
this.contentObserver = contentObserver;
}, 30)
}
}
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-wrap {
background-color: #eee;
overflow: hidden;
}
.u-lazy-item {
width: 100%;
//
transform: transition3d(0, 0, 0);
//
will-change: transform;
display: block;
}
</style>

141
node_modules/uview-ui/components/u-line-progress/u-line-progress.vue

@ -0,0 +1,141 @@
<template>
<view class="u-progress" :style="{
borderRadius: round ? '100rpx' : 0,
height: height + 'rpx',
backgroundColor: inactiveColor
}">
<view :class="[
type ? `u-type-${type}-bg` : '',
striped ? 'u-striped' : '',
striped && stripedActive ? 'u-striped-active' : ''
]" class="u-active" :style="[progressStyle]">{{showPercent ? percent + '%' : ''}}
</view>
</view>
</template>
<script>
/**
* lineProgress 线型进度条
* @description 展示操作或任务的当前进度比如上传文件是一个线形的进度条
* @tutorial https://www.uviewui.com/components/lineProgress.html
* @property {String Number} percent 进度条百分比值为数值类型0-100
* @property {Boolean} round 进度条两端是否为半圆默认true
* @property {String} type 如设置active-color值将会失效
* @property {String} active-color 进度条激活部分的颜色默认#19be6b
* @property {String} inactive-color 进度条的底色默认#ececec
* @property {Boolean} show-percent 是否在进度条内部显示当前的百分比值数值默认true
* @property {String Number} height 进度条的高度单位rpx默认28
* @property {Boolean} striped 是否显示进度条激活部分的条纹默认false
* @property {Boolean} striped-active 条纹是否具有动态效果默认false
* @example <u-line-progress :percent="70" :show-percent="true"></u-line-progress>
*/
export default {
name: "u-line-progress",
props: {
//
round: {
type: Boolean,
default: true
},
//
type: {
type: String,
default: ''
},
//
activeColor: {
type: String,
default: '#19be6b'
},
inactiveColor: {
type: String,
default: '#ececec'
},
//
percent: {
type: Number,
default: 0
},
//
showPercent: {
type: Boolean,
default: true
},
// rpx
height: {
type: [Number, String],
default: 28
},
//
striped: {
type: Boolean,
default: false
},
//
stripedActive: {
type: Boolean,
default: false
}
},
data() {
return {
}
},
computed: {
progressStyle() {
let style = {};
style.width = this.percent + '%';
if(this.activeColor) style.backgroundColor = this.activeColor;
return style;
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-progress {
overflow: hidden;
height: 15px;
display: inline-flex;
align-items: center;
width: 100%;
border-radius: 100rpx;
}
.u-active {
width: 0;
height: 100%;
align-items: center;
display: flex;
justify-items: flex-end;
justify-content: space-around;
font-size: 20rpx;
color: #ffffff;
transition: all 0.4s ease;
}
.u-striped {
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-size: 39px 39px;
}
.u-striped-active {
animation: progress-stripes 2s linear infinite;
}
@keyframes progress-stripes {
0% {
background-position: 0 0;
}
100% {
background-position: 39px 0;
}
}
</style>

84
node_modules/uview-ui/components/u-line/u-line.vue

@ -0,0 +1,84 @@
<template>
<view class="u-line" :style="[lineStyle]">
</view>
</template>
<script>
/**
* line 线条
* @description 此组件一般用于显示一根线条用于分隔内容块有横向和竖向两种模式且能设置0.5px线条使用也很简单
* @tutorial https://www.uviewui.com/components/line.html
* @property {String} color 线条的颜色(默认#e4e7ed)
* @property {String} length 长度竖向时表现为高度横向时表现为长度可以为百分比带rpx单位的值等
* @property {String} direction 线条的方向row-横向col-竖向(默认row)
* @property {String} border-style 线条的类型solid-实线dashed-方形虚线dotted-圆点虚线(默认solid)
* @property {Boolean} hair-line 是否显示细线条(默认true)
* @property {String} margin 线条与上下左右元素的间距字符串形式"30rpx"
* @example <u-line color="red"></u-line>
*/
export default {
name: 'u-line',
props: {
color: {
type: String,
default: '#e4e7ed'
},
// rpx
length: {
type: String,
default: '100%'
},
// 线col-row-
direction: {
type: String,
default: 'row'
},
//
hairLine: {
type: Boolean,
default: true
},
// 线"30rpx""20rpx 30rpx"
margin: {
type: String,
default: '0'
},
// 线solid-线dashed-线dotted-线
borderStyle: {
type: String,
default: 'solid'
}
},
computed: {
lineStyle() {
let style = {};
style.margin = this.margin;
// 线1pxtransform0.5px
if(this.direction == 'row') {
// nvue
style.borderBottomWidth = '1px';
style.borderBottomStyle = this.borderStyle;
style.width = this.$u.addUnit(this.length);
if(this.hairLine) style.transform = 'scaleY(0.5)';
} else {
// 线1pxtransform0.5px
style.borderLeftWidth = '1px';
style.borderLeftStyle = this.borderStyle;
style.height = this.$u.addUnit(this.length);
if(this.hairLine) style.transform = 'scaleX(0.5)';
}
style.borderColor = this.color;
return style;
}
}
}
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-line {
vertical-align: middle;
}
</style>

89
node_modules/uview-ui/components/u-link/u-link.vue

@ -0,0 +1,89 @@
<template>
<text class="u-link" @tap.stop="openLink" :style="{
color: color,
fontSize: fontSize + 'rpx',
borderBottom: underLine ? `1px solid ${lineColor ? lineColor : color}` : 'none',
paddingBottom: underLine ? '0rpx' : '0'
}">
<slot></slot>
</text>
</template>
<script>
/**
* link 超链接
* @description 该组件为超链接组件在不同平台有不同表现形式在APP平台会通过plus环境打开内置浏览器在小程序中把链接复制到粘贴板同时提示信息在H5中通过window.open打开链接
* @tutorial https://www.uviewui.com/components/link.html
* @property {String} color 文字颜色默认#606266
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {Boolean} under-line 是否显示下划线默认false
* @property {String} href 跳转的链接要带上http(s)
* @property {String} line-color 下划线颜色默认同color参数颜色
* @property {String} mp-tips 各个小程序平台把链接复制到粘贴板后的提示语默认链接已复制请在浏览器打开
* @example <u-link href="http://www.uviewui.com">蜀道难难于上青天</u-link>
*/
export default {
name: "u-link",
props: {
//
color: {
type: String,
default: '#2979ff'
},
// rpx
fontSize: {
type: [String, Number],
default: 28
},
// 线
underLine: {
type: Boolean,
default: false
},
//
href: {
type: String,
default: ''
},
//
mpTips: {
type: String,
default: '链接已复制,请在浏览器打开'
},
// 线
lineColor: {
type: String,
default: ''
}
},
methods: {
openLink() {
// #ifdef APP-PLUS
plus.runtime.openURL(this.href)
// #endif
// #ifdef H5
window.open(this.href)
// #endif
// #ifdef MP
uni.setClipboardData({
data: this.href,
success() {
uni.hideToast();
}
});
this.$nextTick(() => {
this.$u.toast(this.mpTips);
})
// #endif
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-link {
line-height: 1;
}
</style>

101
node_modules/uview-ui/components/u-loading/u-loading.vue

@ -0,0 +1,101 @@
<template>
<view v-if="show" class="u-loading" :class="mode == 'circle' ? 'u-loading-circle' : 'u-loading-flower'" :style="[cricleStyle]">
</view>
</template>
<script>
/**
* loading 加载动画
* @description 警此组件为一个小动画目前用在uView的loadmore加载更多和switch开关等组件的正在加载状态场景
* @tutorial https://www.uviewui.com/components/loading.html
* @property {String} mode 模式选择见官网说明默认circle
* @property {String} color 动画活动区域的颜色只对 mode = flower 模式有效默认#c7c7c7
* @property {String Number} size 加载图标的大小单位rpx默认34
* @property {Boolean} show 是否显示动画默认true
* @example <u-loading mode="circle"></u-loading>
*/
export default {
name: "u-loading",
props: {
//
mode: {
type: String,
default: 'circle'
},
//
color: {
type: String,
default: '#c7c7c7'
},
// rpx
size: {
type: [String, Number],
default: '34'
},
//
show: {
type: Boolean,
default: true
}
},
computed: {
//
cricleStyle() {
let style = {};
style.width = this.size + 'rpx';
style.height = this.size + 'rpx';
if (this.mode == 'circle') style.borderColor = `#e4e4e4 #e4e4e4 #e4e4e4 ${this.color ? this.color : '#c7c7c7'}`;
return style;
},
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-loading-circle {
display: inline-block;
vertical-align: middle;
width: 28rpx;
height: 28rpx;
background: 0 0;
border-radius: 50%;
border: 2px solid;
border-color: #e5e5e5 #e5e5e5 #e5e5e5 #8f8d8e;
animation: u-circle 1s linear infinite;
}
.u-loading-flower {
width: 20px;
height: 20px;
display: inline-block;
vertical-align: middle;
-webkit-animation: a 1s steps(12) infinite;
animation: u-flower 1s steps(12) infinite;
background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;
background-size: 100%;
}
@keyframes u-flower {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}
@-webkit-keyframes u-circle {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
</style>

198
node_modules/uview-ui/components/u-loadmore/u-loadmore.vue

@ -0,0 +1,198 @@
<template>
<view class="u-load-more-wrap" :style="{
backgroundColor: bgColor,
marginBottom: marginBottom + 'rpx',
marginTop: marginTop + 'rpx',
height: $u.addUnit(height)
}">
<!-- 加载中和没有更多的状态才显示两边的横线 -->
<view :class="status == 'loadmore' || status == 'nomore' ? 'u-more' : ''" class="u-load-more-inner">
<u-loading class="u-loadmore-icon" :color="iconColor" :mode="iconType == 'circle' ? 'circle' : 'flower'" :show="status == 'loading' && icon"></u-loading>
<!-- 如果没有更多的状态下显示内容为dot粗点加载特定样式 -->
<view :style="[loadTextStyle]" :class="[(status == 'nomore' && isDot == true) ? 'u-dot-text' : 'u-more-text']" @tap="loadMore">
{{ showText }}
</view>
</view>
</view>
</template>
<script>
/**
* loadmore 加载更多
* @description 此组件一般用于标识页面底部加载数据时的状态
* @tutorial https://www.uviewui.com/components/loadMore.html
* @property {String} status 组件状态默认loadmore
* @property {String} bg-color 组件背景颜色在页面是非白色时会用到默认#ffffff
* @property {Boolean} icon 加载中时是否显示图标默认true
* @property {String} icon-type 加载中时的图标类型默认circle
* @property {String} icon-color icon-type为circle时有效加载中的动画图标的颜色默认#b7b7b7
* @property {Boolean} is-dot status为nomore时内容显示为一个"●"默认false
* @property {String} color 字体颜色默认#606266
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {Object} load-text 自定义显示的文字见上方说明示例
* @event {Function} loadmore status为loadmore时点击组件会发出此事件
* @example <u-loadmore :status="status" icon-type="iconType" load-text="loadText" />
*/
export default {
name: "u-loadmore",
props: {
//
bgColor: {
type: String,
default: '#ffffff'
},
//
icon: {
type: Boolean,
default: true
},
//
fontSize: {
type: String,
default: '28'
},
//
color: {
type: String,
default: '#606266'
},
// loadmore-loading-nomore-
status: {
type: String,
default: 'loadmore'
},
// flower-circle-
iconType: {
type: String,
default: 'circle'
},
//
loadText: {
type: Object,
default () {
return {
loadmore: '加载更多',
loading: '正在加载...',
nomore: '没有更多了'
}
}
},
//
isDot: {
type: Boolean,
default: false
},
//
iconColor: {
type: String,
default: '#b7b7b7'
},
//
marginTop: {
type: [String, Number],
default: 0
},
//
marginBottom: {
type: [String, Number],
default: 0
},
// rpx
height: {
type: [String, Number],
default: 'auto'
}
},
data() {
return {
//
dotText: "●"
}
},
computed: {
//
loadTextStyle() {
return {
color: this.color,
fontSize: this.fontSize + 'rpx',
position: 'relative',
zIndex: 1,
backgroundColor: this.bgColor,
//
padding: this.status == 'loading' ? '0 8px' : '0 12px',
}
},
//
cricleStyle() {
return {
borderColor: `#e5e5e5 #e5e5e5 #e5e5e5 ${this.circleColor}`
}
},
//
// base64
flowerStyle() {
return {
}
},
//
showText() {
let text = '';
if(this.status == 'loadmore') text = this.loadText.loadmore;
else if(this.status == 'loading') text = this.loadText.loading;
else if(this.status == 'nomore' && this.isDot) text = this.dotText;
else text = this.loadText.nomore;
return text;
}
},
methods: {
loadMore() {
//
if(this.status == 'loadmore') this.$emit('loadmore');
}
}
}
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-load-more-wrap {
width: 100%;
display: flex;
justify-content: center;
}
.u-load-more-inner {
display: flex;
justify-content: center;
align-items: center;
}
.u-more {
width: 60%;
position: relative;
display: flex;
justify-content: center;
}
.u-more::before {
content: ' ';
position: absolute;
border-bottom: 1px solid #d4d4d4;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
width: 100%;
top: 50%;
left: 0;
}
.u-dot-text {
font-size: 28rpx;
}
.u-loadmore-icon {
display: flex;
align-items: center;
justify-content: center;
}
</style>

122
node_modules/uview-ui/components/u-mask/u-mask.vue

@ -0,0 +1,122 @@
<template>
<view class="u-mask" :style="[maskStyle, zoomStyle]" @tap="click" @touchmove.stop.prevent :class="{
'u-mask-zoom': zoom,
'u-mask-show': show
}">
<slot />
</view>
</template>
<script>
/**
* mask 遮罩
* @description 创建一个遮罩层用于强调特定的页面元素并阻止用户对遮罩下层的内容进行操作一般用于弹窗场景
* @tutorial https://www.uviewui.com/components/mask.html
* @property {Boolean} show 是否显示遮罩默认false
* @property {String Number} z-index z-index 层级默认1070
* @property {Object} custom-style 自定义样式对象见上方说明
* @property {String Number} duration 动画时长单位毫秒默认300
* @property {Boolean} zoom 是否使用scale对这招进行缩放默认true
* @property {Boolean} mask-click-able 遮罩是否可点击为false时点击不会发送click事件默认true
* @event {Function} click mask-click-able为true时点击遮罩发送此事件
* @example <u-mask :show="show" @click="show = false"></u-mask>
*/
export default {
name: "u-mask",
props: {
//
show: {
type: Boolean,
default: false
},
// z-index
zIndex: {
type: [Number, String],
default: ''
},
//
customStyle: {
type: Object,
default () {
return {}
}
},
// 使使zoomscale
zoom: {
type: Boolean,
default: true
},
// ms
duration: {
type: [Number, String],
default: 300
},
//
maskClickAble: {
type: Boolean,
default: true
}
},
data() {
return {
zoomStyle: {
transform: ''
},
scale: 'scale(1.2, 1.2)'
}
},
watch: {
show(n) {
if(n && this.zoom) {
// scale1(1.2)
this.zoomStyle.transform = 'scale(1, 1)';
} else if(!n && this.zoom) {
// scale1.2(1)
this.zoomStyle.transform = this.scale;
}
}
},
computed: {
maskStyle() {
let style = {};
style.backgroundColor = "rgba(0, 0, 0, 0.6)";
if(this.show) style.zIndex = this.zIndex ? this.zIndex : this.$u.zIndex.mask;
else style.zIndex = -1;
style.transition = `all ${this.duration / 1000}s ease-in-out`;
//
if (Object.keys(this.customStyle).length) style = { ...style,
...this.customStyle
};
return style;
}
},
methods: {
click() {
if (!this.maskClickAble) return;
this.$emit('click');
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: 0;
transition: transform 0.3s;
}
.u-mask-show {
opacity: 1;
}
.u-mask-zoom {
transform: scale(1.2, 1.2);
}
</style>

304
node_modules/uview-ui/components/u-message-input/u-message-input.vue

@ -0,0 +1,304 @@
<template>
<view class="u-char-box">
<view class="u-char-flex">
<input :disabled="disabledKeyboard" :value="valueModel" type="number" :focus="focus" :maxlength="maxlength" class="u-input" @input="getVal"/>
<view v-for="(item, index) in maxlength" :key="index">
<view :class="[breathe && charArrLength == index ? 'u-breathe' : '', 'u-char-item',
charArrLength === index && mode == 'box' ? 'u-box-active' : '',
mode === 'box' ? 'u-box' : '']" :style="{
fontWeight: bold ? 'bold' : 'normal',
fontSize: fontSize + 'rpx',
width: width + 'rpx',
height: width + 'rpx',
color: inactiveColor
}">
<view class="u-placeholder-line" :style="{
display: charArrLength === index ? 'block' : 'none',
height: width * 0.5 +'rpx'
}"
v-if="mode !== 'middleLine'"
></view>
<view v-if="mode === 'middleLine' && charArrLength <= index" :class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-middle-line-active' : '']"
class="u-middle-line" :style="{height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor}"></view>
<view v-if="mode === 'bottomLine'" :class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-buttom-line-active' : '']"
class="u-bottom-line" :style="{height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor}"></view>
<block v-if="!dotFill"> {{ charArr[index] ? charArr[index] : ''}}</block>
<block v-else>
<text class="u-dot">{{ charArr[index] ? '●' : ''}}</text>
</block>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* messageInput 验证码输入框
* @description 该组件一般用于验证用户短信验证码的场景也可以结合uView的键盘组件使用
* @tutorial https://www.uviewui.com/components/messageInput.html
* @property {String Number} maxlength 输入字符个数默认4
* @property {Boolean} dot-fill 是否用圆点填充默认false
* @property {String} mode 模式选择见上方"基本使用"说明默认box
* @property {String Number} value 预置值
* @property {Boolean} breathe 是否开启呼吸效果见上方说明默认true
* @property {Boolean} focus 是否自动获取焦点默认false
* @property {Boolean} bold 字体和输入横线是否加粗默认true
* @property {String Number} font-size 字体大小单位rpx默认60
* @property {String} active-color 当前激活输入框的样式默认#2979ff
* @property {String} focus 非激活输入框的样式文字颜色同此值默认#606266
* @property {String | Number} width 输入框宽度单位rpx高等于宽默认80
* @property {Boolean} disabled-keyboard 禁止点击输入框唤起系统键盘默认false
* @event {Function} change 输入内容发生改变时触发具体见官网说明
* @event {Function} finish 输入字符个数达maxlength值时触发见官网说明
* @example <u-message-input mode="bottomLine"></u-message-input>
*/
export default {
name: "u-message-input",
props: {
//
maxlength: {
type: [Number, String],
default: 4
},
//
dotFill: {
type: Boolean,
default: false
},
// box-bottomLine-线middleLine-线
mode: {
type: String,
default: "box"
},
//
value: {
type: [String, Number],
default: ''
},
// item
breathe: {
type: Boolean,
default: true
},
//
focus: {
type: Boolean,
default: false
},
//
bold: {
type: Boolean,
default: false
},
//
fontSize: {
type: [String, Number],
default: 60
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#606266'
},
// rpx
width: {
type: [Number, String],
default: '80'
},
// true
disabledKeyboard: {
type: Boolean,
default: false
}
},
watch: {
maxlength: {
// truemaxlengthcreated
immediate: true,
handler(val) {
this.maxlength = Number(val);
}
},
value: {
immediate: true,
handler(val) {
//
val = String(val);
//
this.valueModel = val.substring(0, this.maxlength);
}
},
},
data() {
return {
valueModel: ""
}
},
computed: {
//
animationClass() {
return (index) => {
if (this.breathe && this.charArr.length == index) return 'u-breathe';
else return '';
}
},
//
charArr() {
return this.valueModel.split('');
},
charArrLength() {
return this.charArr.length;
}
},
methods: {
getVal(e) {
let {
value
} = e.detail
this.valueModel = value;
// maxlengthinputmaxlength
if (String(value).length > this.maxlength) return;
// maxlengthchangefinish
this.$emit('change', value);
if (String(value).length == this.maxlength) {
this.$emit('finish', value);
}
}
}
}
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
@keyframes breathe {
0% {
opacity: 0.3;
}
50% {
opacity: 1;
}
100% {
opacity: 0.3;
}
}
.u-char-box {
text-align: center;
}
.u-char-flex {
display: flex;
justify-content: center;
flex-wrap: wrap;
position: relative;
}
.u-input {
position: absolute;
top: 0;
left: -100%;
width: 200%;
height: 100%;
text-align: left;
z-index: 9;
opacity: 0;
background: none;
}
.u-char-item {
position: relative;
width: 90rpx;
height: 90rpx;
margin: 10rpx 10rpx;
font-size: 60rpx;
font-weight: bold;
color: $u-main-color;
line-height: 90rpx;
display: flex;
justify-content: center;
align-items: center;
}
.u-middle-line {
border: none;
}
.u-box {
box-sizing: border-box;
border: 2rpx solid #cccccc;
border-radius: 6rpx;
}
.u-box-active {
overflow: hidden;
animation-timing-function: ease-in-out;
animation-duration: 1500ms;
animation-iteration-count: infinite;
animation-direction: alternate;
border: 2rpx solid $u-type-primary;
}
.u-middle-line-active {
background: $u-type-primary;
}
.u-breathe {
animation: breathe 2s infinite ease;
}
.u-placeholder-line {
display: none;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 2rpx;
height: 40rpx;
background: #333333;
animation: twinkling 1.5s infinite ease;
}
.u-animation-breathe {
animation-name: breathe;
}
.u-dot {
font-size: 34rpx;
line-height: 34rpx;
}
.u-middle-line {
height: 4px;
background: #000000;
width: 80%;
position: absolute;
border-radius: 2px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.u-buttom-line-active {
background: $u-type-primary;
}
.u-bottom-line {
height: 4px;
background: #000000;
width: 80%;
position: absolute;
border-radius: 2px;
bottom: 0;
left: 50%;
transform: translate(-50%);
}
</style>

295
node_modules/uview-ui/components/u-modal/u-modal.vue

@ -0,0 +1,295 @@
<template>
<view>
<u-popup :zoom="zoom"
mode="center" :popup="false"
:z-index="uZIndex" v-model="value"
:length="width" :mask-close-able="maskCloseAble"
:border-radius="borderRadius"
@close="popupClose"
:negative-top="negativeTop"
>
<view class="u-model">
<view v-if="showTitle" class="u-model-title u-line-1" :style="[titleStyle]">{{ title }}</view>
<view class="u-model-content">
<view :style="[contentStyle]" v-if="$slots.default">
<slot />
</view>
<view v-else class="u-model-content-message" :style="[contentStyle]">{{ content }}</view>
</view>
<view class="u-model-footer u-border-top" v-if="showCancelButton || showConfirmButton">
<view
v-if="showCancelButton"
:hover-stay-time="100"
hover-class="btn-hover"
class="u-model-footer-button"
type="default"
:style="[cancelBtnStyle]"
@tap="cancel"
>
{{cancelText}}
</view>
<view
v-if="showConfirmButton"
:hover-stay-time="100"
:hover-class="asyncClose ? 'none' : 'btn-hover'"
class="u-model-footer-button hairline-left"
:style="[confirmBtnStyle]"
@tap="confirm"
>
<u-loading mode="circle" :color="confirmColor" v-if="loading"></u-loading>
<block v-else>
{{confirmText}}
</block>
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
/**
* modal 模态框
* @description 弹出模态框常用于消息提示消息确认在当前页面内完成特定的交互操作
* @tutorial https://www.uviewui.com/components/modal.html
* @property {Boolean} value 是否显示模态框
* @property {String | Number} z-index 层级
* @property {String} title 模态框标题默认"提示"
* @property {String | Number} width 模态框宽度默认600
* @property {String} content 模态框内容默认"内容"
* @property {Boolean} show-title 是否显示标题默认true
* @property {Boolean} async-close 是否异步关闭只对确定按钮有效默认false
* @property {Boolean} show-confirm-button 是否显示确认按钮默认true
* @property {Stringr | Number} negative-top modal往上偏移的值
* @property {Boolean} show-cancel-button 是否显示取消按钮默认false
* @property {Boolean} mask-close-able 是否允许点击遮罩关闭modal默认false
* @property {String} confirm-text 确认按钮的文字内容默认"确认"
* @property {String} cancel-text 取消按钮的文字内容默认"取消"
* @property {String} cancel-color 取消按钮的颜色默认"#606266"
* @property {String} confirm-color 确认按钮的文字内容默认"#2979ff"
* @property {String | Number} border-radius 模态框圆角值单位rpx默认16
* @property {Object} title-style 自定义标题样式对象形式
* @property {Object} content-style 自定义内容样式对象形式
* @property {Object} cancel-style 自定义取消按钮样式对象形式
* @property {Object} confirm-style 自定义确认按钮样式对象形式
* @property {Boolean} zoom 是否开启缩放模式默认true
* @event {Function} confirm 确认按钮被点击
* @event {Function} cancel 取消按钮被点击
* @example <u-modal :src="title" :content="content"></u-modal>
*/
export default {
name: 'u-modal',
props: {
// Modal
value: {
type: Boolean,
default: false
},
// z-index
zIndex: {
type: [Number, String],
default: ''
},
//
title: {
type: [String],
default: '提示'
},
// (rpx)auto
width: {
type: [Number, String],
default: 600
},
//
content: {
type: String,
default: '内容'
},
//
showTitle: {
type: Boolean,
default: true
},
//
showConfirmButton: {
type: Boolean,
default: true
},
//
showCancelButton: {
type: Boolean,
default: false
},
//
confirmText: {
type: String,
default: '确认'
},
//
cancelText: {
type: String,
default: '取消'
},
//
confirmColor: {
type: String,
default: '#2979ff'
},
//
cancelColor: {
type: String,
default: '#606266'
},
//
borderRadius: {
type: [Number, String],
default: 16
},
//
titleStyle: {
type: Object,
default() {
return {}
}
},
//
contentStyle: {
type: Object,
default() {
return {}
}
},
//
cancelStyle: {
type: Object,
default() {
return {}
}
},
//
confirmStyle: {
type: Object,
default() {
return {}
}
},
//
zoom: {
type: Boolean,
default: true
},
//
asyncClose: {
type: Boolean,
default: false
},
// modal
maskCloseAble: {
type: Boolean,
default: false
},
// margin-top
negativeTop: {
type: [String, Number],
default: 0
}
},
data() {
return {
loading: false, //
}
},
computed: {
cancelBtnStyle() {
return Object.assign({color: this.cancelColor}, this.cancelStyle);
},
confirmBtnStyle() {
return Object.assign({color: this.confirmColor}, this.confirmStyle);
},
uZIndex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
watch: {
// v-modelfalseloading
//
value(n) {
if(n === true) this.loading = false;
}
},
methods: {
confirm() {
this.$emit('confirm');
//
if(this.asyncClose) {
this.loading = true;
} else {
this.$emit('input', false);
}
},
cancel() {
this.$emit('cancel');
this.$emit('input', false);
// popup
// ""modal
setTimeout(() => {
this.loading = false;
}, 300);
},
// modalv-modelfalsemodal
popupClose() {
this.$emit('input', false);
},
//
clearLoading() {
this.loading = false;
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.btn-hover {
background-color: rgb(230, 230, 230);
}
.u-model {
height: auto;
overflow: hidden;
font-size: 32rpx;
background-color: #fff;
&-title {
padding-top: 48rpx;
font-weight: 500;
text-align: center;
color: $u-main-color;
}
&-content {
&-message {
padding: 48rpx;
font-size: 30rpx;
text-align: center;
color: $u-content-color;
}
}
&-footer {
display: flex;
&-button {
flex: 1;
height: 100rpx;
line-height: 100rpx;
font-size: 32rpx;
box-sizing: border-box;
cursor: pointer;
text-align: center;
border-radius: 4rpx;
}
}
}
</style>

295
node_modules/uview-ui/components/u-navbar/u-navbar.vue

@ -0,0 +1,295 @@
<template>
<view class="">
<view class="u-navbar" :style="[navbarStyle]" :class="{ 'u-navbar-fixed': isFixed, 'u-border-bottom': borderBottom }">
<view class="u-status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<view class="u-navbar-inner" :style="[navbarInnerStyle]">
<view class="u-back-wrap" v-if="isBack" @tap="goBack">
<view class="u-icon-wrap"><u-icon :name="backIconName" :color="backIconColor" :size="backIconSize"></u-icon></view>
<view class="u-icon-wrap u-back-text u-line-1" v-if="backText" :style="[backTextStyle]">{{ backText }}</view>
</view>
<view class="u-navbar-content-title" v-if="title" :style="[titleStyle]">
<view
class="u-title u-line-1"
:style="{
color: titleColor,
fontSize: titleSize + 'rpx'
}"
>
{{ title }}
</view>
</view>
<view class="u-slot-content"><slot></slot></view>
<view class="u-slot-right"><slot name="right"></slot></view>
</view>
</view>
<!-- 解决fixed定位后导航栏塌陷的问题 -->
<view class="u-navbar-placeholder" v-if="isFixed" :style="{ width: '100%', height: Number(navbarHeight) + statusBarHeight + 'px' }"></view>
</view>
</template>
<script>
//
let systemInfo = uni.getSystemInfoSync();
let menuButtonInfo = {};
// (API)
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
// #endif
/**
* navbar 自定义导航栏
* @description 此组件一般用于在特殊情况下需要自定义导航栏的时候用到一般建议使用uniapp自带的导航栏
* @tutorial https://www.uviewui.com/components/navbar.html
* @property {String Number} height 导航栏高度(不包括状态栏高度在内内部自动加上)注意这里的单位是px默认44
* @property {String} back-icon-color 左边返回图标的颜色默认#606266
* @property {String} back-icon-name 左边返回图标的名称只能为uView自带的图标默认arrow-left
* @property {String Number} back-icon-size 左边返回图标的大小单位rpx默认30
* @property {String} back-text 返回图标右边的辅助提示文字
* @property {Object} back-text-style 返回图标右边的辅助提示文字的样式对象形式默认{ color: '#606266' }
* @property {String} title 导航栏标题如设置为空字符将会隐藏标题占位区域
* @property {String Number} title-width 导航栏标题的最大宽度内容超出会以省略号隐藏单位rpx默认250
* @property {String} title-color 标题的颜色默认#606266
* @property {String Number} title-size 导航栏标题字体大小单位rpx默认32
* @property {Function} custom-back 自定义返回逻辑方法
* @property {String Number} z-index 固定在顶部时的z-index值默认980
* @property {Boolean} is-back 是否显示导航栏左边返回图标和辅助文字默认true
* @property {Object} background 导航栏背景设置见官网说明默认{ background: '#ffffff' }
* @property {Boolean} is-fixed 导航栏是否固定在顶部默认true
* @property {Boolean} border-bottom 导航栏底部是否显示下边框如定义了较深的背景颜色可取消此值默认true
* @example <u-navbar back-text="返回" title="剑未配妥,出门已是江湖"></u-navbar>
*/
export default {
name: "u-navbar",
props: {
// pxrpx
height: {
type: [String, Number],
default: ''
},
//
backIconColor: {
type: String,
default: '#606266'
},
//
backIconName: {
type: String,
default: 'arrow-left'
},
// rpx
backIconSize: {
type: [String, Number],
default: '30'
},
//
backText: {
type: String,
default: ''
},
//
backTextStyle: {
type: Object,
default() {
return {
color: '#606266'
}
}
},
//
title: {
type: String,
default: ''
},
// rpx
titleWidth: {
type: [String, Number],
default: '250'
},
//
titleColor: {
type: String,
default: '#606266'
},
//
titleSize: {
type: [String, Number],
default: 32
},
isBack: {
type: [Boolean, String],
default: true
},
// 线
background: {
type: Object,
default() {
return {
background: '#ffffff'
}
}
},
//
isFixed: {
type: Boolean,
default: true
},
//
borderBottom: {
type: Boolean,
default: true
},
zIndex: {
type: [String, Number],
default: ''
},
//
customBack: {
type: Function,
default: null
}
},
data() {
return {
menuButtonInfo: menuButtonInfo,
statusBarHeight: systemInfo.statusBarHeight
};
},
computed: {
//
navbarInnerStyle() {
let style = {};
//
style.height = this.navbarHeight + 'px';
// //
// #ifdef MP
let rightButtonWidth = systemInfo.windowWidth - menuButtonInfo.left;
style.marginRight = rightButtonWidth + 'px';
// #endif
return style;
},
//
navbarStyle() {
let style = {};
style.zIndex = this.zIndex ? this.zIndex : this.$u.zIndex.navbar;
//
Object.assign(style, this.background);
return style;
},
//
titleStyle() {
let style = {};
// #ifndef MP
style.left = (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + 'px';
style.right = (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + 'px';
// #endif
// #ifdef MP
// 使
let rightButtonWidth = systemInfo.windowWidth - menuButtonInfo.left;
style.left = (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + 'px';
style.right = rightButtonWidth - (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + rightButtonWidth + 'px';
// #endif
style.width = uni.upx2px(this.titleWidth) + 'px';
return style;
},
//
navbarHeight() {
// #ifdef APP-PLUS || H5
return this.height ? this.height : 44;
// #endif
// #ifdef MP
// = + ()
// (px)
// return menuButtonInfo.height + (menuButtonInfo.top - this.statusBarHeight) * 2;//
let height = systemInfo.platform == 'ios' ? 44 : 48;
return this.height ? this.height : height;
// #endif
}
},
created() {},
methods: {
goBack() {
//
if(typeof this.customBack === 'function') {
this.customBack();
} else {
uni.navigateBack();
}
}
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-navbar {
width: 100%;
}
.u-navbar-fixed {
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 991;
}
.u-status-bar {
width: 100%;
}
.u-navbar-inner {
display: flex;
justify-content: space-between;
position: relative;
align-items: center;
}
.u-back-wrap {
display: flex;
align-items: center;
flex: 1;
flex-grow: 0;
padding: 14rpx 14rpx 14rpx 24rpx;
}
.u-back-text {
padding-left: 4rpx;
font-size: 30rpx;
}
.u-navbar-content-title {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
position: absolute;
left: 0;
right: 0;
height: 60rpx;
text-align: center;
flex-shrink: 0;
}
.u-navbar-centent-slot {
flex: 1;
}
.u-title {
line-height: 60rpx;
font-size: 32rpx;
flex: 1;
}
.u-navbar-right {
flex: 1;
display: flex;
align-items: center;
justify-content: flex-end;
}
.u-slot-content {
flex: 1;
display: flex;
align-items: center;
}
</style>

233
node_modules/uview-ui/components/u-no-network/u-no-network.vue

File diff suppressed because one or more lines are too long

272
node_modules/uview-ui/components/u-notice-bar/u-notice-bar.vue

@ -0,0 +1,272 @@
<template>
<view class="u-notice-bar-wrap" v-if="isShow" :style="{
borderRadius: borderRadius + 'rpx',
}">
<block v-if="mode == 'horizontal' && isCircular">
<u-row-notice
:type="type"
:color="color"
:bgColor="bgColor"
:list="list"
:volumeIcon="volumeIcon"
:moreIcon="moreIcon"
:volumeSize="volumeSize"
:closeIcon="closeIcon"
:mode="mode"
:fontSize="fontSize"
:speed="speed"
:playState="playState"
:padding="padding"
@getMore="getMore"
@close="close"
@click="click"
></u-row-notice>
</block>
<block v-if="mode == 'vertical' || (mode == 'horizontal' && !isCircular)">
<u-column-notice
:type="type"
:color="color"
:bgColor="bgColor"
:list="list"
:volumeIcon="volumeIcon"
:moreIcon="moreIcon"
:closeIcon="closeIcon"
:mode="mode"
:volumeSize="volumeSize"
:disable-touch="disableTouch"
:fontSize="fontSize"
:duration="duration"
:playState="playState"
:padding="padding"
@getMore="getMore"
@close="close"
@click="click"
@end="end"
></u-column-notice>
</block>
</view>
</template>
<script>
/**
* noticeBar 滚动通知
* @description 该组件用于滚动通告场景有多种模式可供选择
* @tutorial https://www.uviewui.com/components/noticeBar.html
* @property {Array} list 滚动内容数组形式见上方说明
* @property {String} type 显示的主题默认warning
* @property {Boolean} volume-icon 是否显示小喇叭图标默认true
* @property {Boolean} more-icon 是否显示右边的向右箭头默认false
* @property {Boolean} close-icon 是否显示关闭图标默认false
* @property {Boolean} autoplay 是否自动播放默认true
* @property {String} color 文字颜色
* @property {String Number} bg-color 背景颜色
* @property {String} mode 滚动模式默认horizontal
* @property {Boolean} show 是否显示默认true
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {String Number} volume-size 左边喇叭的大小默认34
* @property {String Number} duration 滚动周期时长只对步进模式有效横向衔接模式无效单位ms默认2000
* @property {String Number} speed 水平滚动时的滚动速度即每秒移动多少距离只对水平衔接方式有效单位rpx默认160
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {Boolean} is-circular mode为horizontal时指明是否水平衔接滚动默认true
* @property {String} play-state 播放状态play - 播放paused - 暂停默认play
* @property {String Nubmer} border-radius 通知栏圆角默认为0
* @property {String Nubmer} padding 内边距字符串与普通的内边距css写法一直默认"18rpx 24rpx"
* @property {Boolean} no-list-hidden 列表为空时是否显示组件默认false
* @property {Boolean} disable-touch 是否禁止通过手动滑动切换通知只有mode = vertical或者mode = horizontal且is-circular = false时有效默认true
* @event {Function} click 点击通告文字触发只有mode = vertical或者mode = horizontal且is-circular = false时有效
* @event {Function} close 点击右侧关闭图标触发
* @event {Function} getMore 点击右侧向右图标触发
* @event {Function} end 列表的消息每次被播放一个周期时触发只有mode = vertical或者mode = horizontal且is-circular = false时有效
* @example <u-notice-bar :more-icon="true" :list="list"></u-notice-bar>
*/
export default {
name: "u-notice-bar",
props: {
//
list: {
type: Array,
default() {
return [];
}
},
// success|error|primary|info|warning
type: {
type: String,
default: 'warning'
},
//
volumeIcon: {
type: Boolean,
default: true
},
//
volumeSize: {
type: [Number, String],
default: 34
},
//
moreIcon: {
type: Boolean,
default: false
},
//
closeIcon: {
type: Boolean,
default: false
},
//
autoplay: {
type: Boolean,
default: true
},
// 使
color: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: ''
},
// horizontal-vertical-
mode: {
type: String,
default: 'horizontal'
},
//
show: {
type: Boolean,
default: true
},
// rpx
fontSize: {
type: [Number, String],
default: 28
},
// ms
duration: {
type: [Number, String],
default: 2000
},
// rpx
speed: {
type: [Number, String],
default: 160
},
//
// swiper
isCircular: {
type: Boolean,
default: true
},
// play-paused-
playState: {
type: String,
default: 'play'
},
//
// HX2.6.11App 2.5.5+H5 2.5.5+
disableTouch: {
type: Boolean,
default: true
},
//
borderRadius: {
type: [Number, String],
default: 0
},
//
padding: {
type: [Number, String],
default: '18rpx 24rpx'
},
// list
noListHidden: {
type: Boolean,
default: true
}
},
computed: {
// showfalsenoListHiddentruelist
isShow() {
if(this.show == false || (this.noListHidden == true && this.list.length == 0)) return false;
else return true;
}
},
methods: {
//
click(index) {
this.$emit('click', index);
},
//
close() {
this.$emit('close');
},
//
getMore() {
this.$emit('getMore');
},
//
end() {
this.$emit('end');
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-notice-bar-wrap {
overflow: hidden;
}
.u-notice-bar {
padding: 18rpx 24rpx;
overflow: hidden;
}
.u-direction-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.u-left-icon {
display: flex;
align-items: center;
}
.u-notice-box {
flex: 1;
display: flex;
overflow: hidden;
margin-left: 12rpx;
}
.u-right-icon {
margin-left: 12rpx;
display: flex;
align-items: center;
}
.u-notice-content {
line-height: 1;
white-space: nowrap;
font-size: 26rpx;
animation: u-loop-animation 10s linear infinite both;
text-align: right;
//
padding-left: 100%;
}
@keyframes u-loop-animation {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(-100%, 0, 0);
}
}
</style>

321
node_modules/uview-ui/components/u-number-box/u-number-box.vue

@ -0,0 +1,321 @@
<template>
<view class="u-numberbox">
<view class="u-icon-minus" @touchstart.stop="btnTouchStart('minus')" @touchend.stop="clearTimer" :class="{ 'u-icon-disabled': disabled || inputVal <= min }" :style="{
background: bgColor,
height: inputHeight + 'rpx',
color: color
}">
<u-icon name="minus" :size="size"></u-icon>
</view>
<input :disabled="disabledInput || disabled" :cursor-spacing="getCursorSpacing" :class="{ 'u-input-disabled': disabled }" v-model="inputVal" class="u-number-input" @blur="onBlur"
type="number" :style="{
color: color,
fontSize: size + 'rpx',
background: bgColor,
height: inputHeight + 'rpx',
width: inputWidth + 'rpx'
}" />
<view class="u-icon-plus" @touchstart.stop="btnTouchStart('plus')" @touchend.stop="clearTimer" :class="{ 'u-icon-disabled': disabled || inputVal >= max }" :style="{
background: bgColor,
height: inputHeight + 'rpx',
color: color
}">
<u-icon name="plus" :size="size"></u-icon>
</view>
</view>
</template>
<script>
/**
* numberBox 步进器
* @description 该组件一般用于商城购物选择物品数量的场景注意该输入框只能输入大于或等于0的整数不支持小数输入
* @tutorial https://www.uviewui.com/components/numberBox.html
* @property {Number} value 输入框初始值默认1
* @property {String} bg-color 输入框和按钮的背景颜色默认#F2F3F5
* @property {Number} min 用户可输入的最小值默认0
* @property {Number} max 用户可输入的最大值默认99999
* @property {Number} step 步长每次加或减的值默认1
* @property {Boolean} disabled 是否禁用操作禁用后无法加减或手动修改输入框的值默认false
* @property {Boolean} disabled-input 是否禁止输入框手动输入值默认false
* @property {String | Number} size 输入框文字和按钮字体大小单位rpx默认26
* @property {String} color 输入框文字和加减按钮图标的颜色默认#323233
* @property {String | Number} input-width 输入框宽度单位rpx默认80
* @property {String | Number} input-height 输入框和按钮的高度单位rpx默认50
* @property {String | Number} index 事件回调时用以区分当前发生变化的是哪个输入框
* @property {Boolean} long-press 是否开启长按连续递增或递减(默认true)
* @property {String | Number} press-time 开启长按触发后每触发一次需要多久单位ms(默认250)
* @property {String | Number} cursor-spacing 指定光标于键盘的距离避免键盘遮挡输入框单位rpx默认200
* @event {Function} change 输入框内容发生变化时触发对象形式
* @event {Function} blur 输入框失去焦点时触发对象形式
* @event {Function} minus 点击减少按钮时触发(按钮可点击情况下)对象形式
* @event {Function} plus 点击增加按钮时触发(按钮可点击情况下)对象形式
* @example <u-number-box :min="1" :max="100"></u-number-box>
*/
export default {
name: "u-number-box",
props: {
//
value: {
type: Number,
default: 1
},
//
bgColor: {
type: String,
default: '#F2F3F5'
},
//
min: {
type: Number,
default: 0
},
//
max: {
type: Number,
default: 99999
},
//
step: {
type: Number,
default: 1
},
//
disabled: {
type: Boolean,
default: false
},
// inputrpx
size: {
type: [Number, String],
default: 26
},
//
color: {
type: String,
default: '#323233'
},
// inputrpx
inputWidth: {
type: [Number, String],
default: 80
},
// inputrpx
inputHeight: {
type: [Number, String],
default: 50
},
// index使numberbox使forindex
index: {
type: [Number, String],
default: ''
},
// disabledOR
// disabledfalsedisabledInputtrue
disabledInput: {
type: Boolean,
default: false
},
//
cursorSpacing: {
type: [Number, String],
default: 100
},
//
longPress: {
type: Boolean,
default: true
},
//
pressTime: {
type: [Number, String],
default: 250
}
},
watch: {
value(val, val1) {
// changevalutchange
if(Number(val) != this.inputVal) this.inputVal = Number(val);
},
inputVal(v1, v2) {
//
if (v1 == '') return;
let value = 0;
// minmax使
let tmp = this.$u.test.number(v1);
if (tmp && v1 >= this.min && v1 <= this.max) value = v1;
else value = v2;
this.handleChange(value, 'change');
this.$nextTick(() => {
this.inputVal = v1;
})
}
},
data() {
return {
inputVal: 1 , // 使propsvalueprops
timer: null, //
};
},
created() {
this.inputVal = Number(this.value);
},
computed: {
getCursorSpacing() {
// px
return Number(uni.upx2px(this.cursorSpacing));
}
},
methods: {
// 退
btnTouchStart(callback) {
// clearTimer
this[callback]();
//
if(!this.longPress) return ;
clearInterval(this.timer); //
this.timer = null;
this.timer = setInterval(() => {
//
this[callback]();
}, this.pressTime);
},
clearTimer() {
this.$nextTick(() => {
clearInterval(this.timer);
this.timer = null;
})
},
minus() {
this.computeVal('minus');
},
plus() {
this.computeVal('plus');
},
//
calcPlus(num1, num2) {
let baseNum, baseNum1, baseNum2;
try {
baseNum1 = num1.toString().split('.')[1].length;
} catch (e) {
baseNum1 = 0;
}
try {
baseNum2 = num2.toString().split('.')[1].length;
} catch (e) {
baseNum2 = 0;
}
baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2; //
return ((num1 * baseNum + num2 * baseNum) / baseNum).toFixed(precision);
},
//
calcMinus(num1, num2) {
let baseNum, baseNum1, baseNum2;
try {
baseNum1 = num1.toString().split('.')[1].length;
} catch (e) {
baseNum1 = 0;
}
try {
baseNum2 = num2.toString().split('.')[1].length;
} catch (e) {
baseNum2 = 0;
}
console.log(num1, num2, baseNum1, baseNum2);
baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2;
return ((num1 * baseNum - num2 * baseNum) / baseNum).toFixed(precision);
},
computeVal(type) {
uni.hideKeyboard();
if (this.disabled) return;
let value = 0;
//
if (type === 'minus') {
value = this.calcMinus(this.inputVal, this.step);
} else if (type === 'plus') {
value = this.calcPlus(this.inputVal, this.step);
}
//
if (value < this.min || value > this.max) {
return;
}
this.inputVal = value;
this.handleChange(value, type);
},
//
onBlur(event) {
let val = 0;
let value = event.detail.value;
// 0-90min
// props min0
if (!/(^\d+$)/.test(value) || value[0] == 0) val = this.min;
val = +value;
if (val > this.max) {
val = this.max;
} else if (val < this.min) {
val = this.min;
}
this.$nextTick(() => {
this.inputVal = val;
})
this.handleChange(val, "blur");
},
handleChange(value, type) {
if (this.disabled) return;
// inputv-model
this.$emit('input', Number(value));
this.$emit(type, {
// Number
value: Number(value),
index: this.index
})
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-numberbox {
display: inline-flex;
align-items: center;
}
.u-number-input {
position: relative;
text-align: center;
padding: 0;
margin: 0 6rpx;
display: flex;
align-items: center;
justify-content: center;
}
.u-icon-plus,
.u-icon-minus {
width: 60rpx;
display: flex;
justify-content: center;
align-items: center;
}
.u-icon-plus {
border-radius: 0 8rpx 8rpx 0;
}
.u-icon-minus {
border-radius: 8rpx 0 0 8rpx;
}
.u-icon-disabled {
color: #c8c9cc !important;
background: #f7f8fa !important;
}
.u-input-disabled {
color: #c8c9cc !important;
background-color: #f2f3f5 !important;
}
</style>

158
node_modules/uview-ui/components/u-number-keyboard/u-number-keyboard.vue

@ -0,0 +1,158 @@
<template>
<view class="u-keyboard" @touchmove.stop.prevent>
<view class="u-keyboard-grids">
<view
class="u-keyboard-grids-item"
:class="[btnBgGray(index) ? 'u-bg-gray' : '', index <= 2 ? 'u-border-top' : '', index < 9 ? 'u-border-bottom' : '', (index + 1) % 3 != 0 ? 'u-border-right' : '']"
:style="[itemStyle(index)]"
v-for="(item, index) in numList"
:key="index"
:hover-class="hoverClass(index)"
:hover-stay-time="100"
@tap="keyboardClick(item)">
<view class="u-keyboard-grids-btn">{{ item }}</view>
</view>
<view class="u-keyboard-grids-item u-bg-gray" hover-class="u-hover-class" :hover-stay-time="100" @touchstart.stop="backspaceClick"
@touchend="clearTimer">
<view class="u-keyboard-back u-keyboard-grids-btn">
<u-icon name="backspace" :size="38" :bold="true"></u-icon>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
// number-card-
mode: {
type: String,
default: 'number'
},
// "."
dotEnabled: {
type: Boolean,
default: true
},
//
random: {
type: Boolean,
default: false
}
},
data() {
return {
backspace: 'backspace', // 退
dot: '.', //
timer: null, //
cardX: 'X' // X
};
},
computed: {
//
numList() {
let tmp = [];
if (!this.dotEnabled && this.mode == 'number') {
if (!this.random) {
return [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
} else {
return this.$u.randomArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
}
} else if (this.dotEnabled && this.mode == 'number') {
if (!this.random) {
return [1, 2, 3, 4, 5, 6, 7, 8, 9, this.dot, 0];
} else {
return this.$u.randomArray([1, 2, 3, 4, 5, 6, 7, 8, 9, this.dot, 0]);
}
} else if (this.mode == 'card') {
if (!this.random) {
return [1, 2, 3, 4, 5, 6, 7, 8, 9, this.cardX, 0];
} else {
return this.$u.randomArray([1, 2, 3, 4, 5, 6, 7, 8, 9, this.cardX, 0]);
}
}
},
// &&&&index9
itemStyle() {
return index => {
let style = {};
if (this.mode == 'number' && !this.dotEnabled && index == 9) style.flex = '0 0 66.6666666666%';
return style;
};
},
// &&&&
btnBgGray() {
return index => {
if (!this.random && index == 9 && (this.mode != 'number' || (this.mode == 'number' && this.dotEnabled))) return true;
else return false;
};
},
hoverClass() {
return index => {
if (!this.random && index == 9 && (this.mode == 'number' && this.dotEnabled || this.mode == 'card')) return 'u-hover-class';
else return 'u-keyboard-hover';
}
}
},
methods: {
// 退
backspaceClick() {
this.$emit('backspace');
clearInterval(this.timer); //
this.timer = null;
this.timer = setInterval(() => {
this.$emit('backspace');
}, 250);
},
clearTimer() {
clearInterval(this.timer);
this.timer = null;
},
//
keyboardClick(val) {
//
if (this.dotEnabled && val != this.dot && val != this.cardX) val = Number(val);
this.$emit('change', val);
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-keyboard {
position: relative;
z-index: 1003;
}
.u-keyboard-grids {
display: flex;
flex-wrap: wrap;
}
.u-keyboard-grids-item {
flex: 0 0 33.3333333333%;
text-align: center;
font-size: 50rpx;
color: #333;
display: flex;
align-items: center;
justify-content: center;
height: 110rpx;
font-weight: 500;
}
.u-bg-gray {
background-color: #e7e6eb;
}
.u-keyboard-back {
font-size: 36rpx;
}
.u-keyboard-hover {
background-color: #e7e6eb;
}
</style>

653
node_modules/uview-ui/components/u-picker/u-picker.vue

@ -0,0 +1,653 @@
<template>
<u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex">
<!-- 多加一个if判断避免微信小程序第二次打开后视图没有重新渲染而导致数据混乱 -->
<view class="u-datetime-picker" @tap.stop v-if="value">
<view class="u-picker-header" @touchmove.stop.prevent="">
<view class="u-btn-picker u-btn-picker--tips" :style="{ color: cancelColor }" hover-class="u-opacity" :hover-stay-time="150" @tap="getResult('cancel')">取消</view>
<view class="u-picker__title">{{ title }}</view>
<view
class="u-btn-picker u-btn-picker--primary"
:style="{ color: moving ? cancelColor : confirmColor }"
hover-class="u-opacity"
:hover-stay-time="150"
@touchmove.stop=""
@tap.stop="getResult('confirm')"
>
确定
</view>
</view>
<view class="u-picker-body">
<picker-view v-if="mode == 'region'" :value="valueArr" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
<picker-view-column v-if="params.province">
<view class="u-column-item" v-for="(item, index) in provinces" :key="index">
<view class="u-line-1">{{ item.label }}</view>
</view>
</picker-view-column>
<picker-view-column v-if="params.city">
<view class="u-column-item" v-for="(item, index) in citys" :key="index">
<view class="u-line-1">{{ item.label }}</view>
</view>
</picker-view-column>
<picker-view-column v-if="params.area">
<view class="u-column-item" v-for="(item, index) in areas" :key="index">
<view class="u-line-1">{{ item.label }}</view>
</view>
</picker-view-column>
</picker-view>
<picker-view v-else-if="mode == 'time'" :value="valueArr" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
<picker-view-column v-if="!reset && params.year">
<view class="u-column-item" v-for="(item, index) in years" :key="index">
{{ item }}
<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.month">
<view class="u-column-item" v-for="(item, index) in months" :key="index">
{{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.day">
<view class="u-column-item" v-for="(item, index) in days" :key="index">
{{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.hour">
<view class="u-column-item" v-for="(item, index) in hours" :key="index">
{{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.minute">
<view class="u-column-item" v-for="(item, index) in minutes" :key="index">
{{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.second">
<view class="u-column-item" v-for="(item, index) in seconds" :key="index">
{{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
</picker-view>
<picker-view v-else-if="mode == 'selector'" :value="defaultSelector" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
<picker-view-column>
<view class="u-column-item" v-for="(item, index) in range" :key="index">
<view class="u-line-1">{{ getItemValue(item, 'selector') }}</view>
</view>
</picker-view-column>
</picker-view>
<picker-view v-else-if="mode == 'multiSelector'" :value="defaultSelector" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
<picker-view-column v-for="(item, index) in range" :key="index">
<view class="u-column-item" v-for="(item1, index1) in item" :key="index1">
<view class="u-line-1">{{ getItemValue(item1, 'multiSelector') }}</view>
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</u-popup>
</template>
<script>
import provinces from '../../libs/util/province.js';
import citys from '../../libs/util/city.js';
import areas from '../../libs/util/area.js';
/**
* picker picker弹出选择器
* @description 此选择器有两种弹出模式一是时间模式可以配置年秒参数 二是地区模式可以配置省区参数
* @tutorial https://www.uviewui.com/components/picker.html
* @property {Object} params 需要显示的参数见官网说明
* @property {String} mode 模式选择region-地区类型time-时间类型默认time
* @property {String Number} start-year 可选的开始年份mode=time时有效默认1950
* @property {String Number} end-year 可选的结束年份mode=time时有效默认2050
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Boolean} show-time-tag 时间模式时是否显示后面的年月日中文提示
* @property {String} cancel-color 取消按钮的颜色默认#606266
* @property {String} confirm-color 确认按钮的颜色默认#2979ff
* @property {String} default-time 默认选中的时间mode=time时有效
* @property {String} default-region 默认选中的地区中文形式mode=region时有效
* @property {String} default-code 默认选中的地区编号形式mode=region时有效
* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker默认true
* @property {String Number} z-index 弹出时的z-index值默认1075
* @property {Array} default-selector 数组形式其中每一项表示选择了range对应项中的第几个
* @property {Array} range 自定义选择的数据mode=selector或mode=multiSelector时有效
* @property {String} range-key 当range参数的元素为对象时指定Object中的哪个key的值作为选择器显示内容
* @event {Function} confirm 点击确定按钮返回当前选择的值
* @event {Function} cancel 点击取消按钮返回当前选择的值
* @example <u-picker v-model="show" mode="time"></u-picker>
*/
export default {
name: 'u-picker',
props: {
// picker
params: {
type: Object,
default() {
return {
year: true,
month: true,
day: true,
hour: false,
minute: false,
second: false,
province: true,
city: true,
area: true,
timestamp: true,
};
}
},
// mode=selectormode=multiSelector
range: {
type: Array,
default() {
return [];
}
},
// mode=selectormode=multiSelector
defaultSelector: {
type: Array,
default() {
return [0];
}
},
// range ArrayObject range-key Object key
rangeKey: {
type: String,
default: ''
},
// region-time-selector-multiSelector-
mode: {
type: String,
default: 'time'
},
//
startYear: {
type: [String, Number],
default: 1950
},
//
endYear: {
type: [String, Number],
default: 2050
},
// ""
cancelColor: {
type: String,
default: '#606266'
},
// ""
confirmColor: {
type: String,
default: '#2979ff'
},
// 2025-07-02 || 2025-07-02 13:01:00 || 2025/07/02
defaultTime: {
type: String,
default: ''
},
// ["", "", ""]
defaultRegion: {
type: Array,
default() {
return [];
}
},
//
showTimeTag: {
type: Boolean,
default: true
},
// defaultRegionareaCodeareaCode["13", "1303", "130304"]
areaCode: {
type: Array,
default() {
return [];
}
},
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// Picker
maskCloseAble: {
type: Boolean,
default: true
},
//
value: {
type: Boolean,
default: false
},
// z-index
zIndex: {
type: [String, Number],
default: 0
},
//
title: {
type: String,
default: ''
}
},
data() {
return {
years: [],
months: [],
days: [],
hours: [],
minutes: [],
seconds: [],
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0,
startDate: '',
endDate: '',
valueArr: [],
reset: false,
provinces: provinces,
citys: citys[0],
areas: areas[0][0],
province: 0,
city: 0,
area: 0,
moving: false //
};
},
mounted() {
this.init();
},
computed: {
propsChange() {
//
return `${this.mode}-${this.defaultTime}-${this.startYear}-${this.endYear}-${this.defaultRegion}-${this.areaCode}`;
},
regionChange() {
//
return `${this.province}-${this.city}`;
},
yearAndMonth() {
return `${this.year}-${this.month}`;
},
uZIndex() {
// z-index使
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
watch: {
propsChange() {
this.reset = true;
setTimeout(() => this.init(), 10);
},
// pickerthis.citysthis.areas
regionChange(val) {
this.citys = citys[this.province];
this.areas = areas[this.province][this.city];
},
// watch
// 3031229228
yearAndMonth(val) {
if (this.params.year) this.setDays();
},
// QQ()
value(n) {
if (n) {
this.reset = true;
setTimeout(() => this.init(), 10);
}
}
},
methods: {
//
pickstart() {
// #ifdef MP-WEIXIN
this.moving = true;
// #endif
},
//
pickend() {
// #ifdef MP-WEIXIN
this.moving = false;
// #endif
},
//
getItemValue(item, mode) {
// (2020-05-25)uni-appv-iffalse
// getItemValue
if (this.mode == mode) {
return typeof item == 'object' ? item[this.rangeKey] : item;
}
},
// 100
formatNumber(num) {
return +num < 10 ? '0' + num : String(num);
},
//
generateArray: function(start, end) {
end = end > start ? end : start;
//
return [...Array(end + 1).keys()].slice(start);
},
getIndex: function(arr, val) {
let index = arr.indexOf(val);
// index-1(index)~(-1)=-(-1)-1=0
return ~index ? index : 0;
},
//
initTimeValue() {
// IE(uni)"-"
let fdate = this.defaultTime.replace(/\-/g, '/');
fdate = fdate && fdate.indexOf('/') == -1 ? `2020/01/01 ${fdate}` : fdate;
let time = null;
if (fdate) time = new Date(fdate);
else time = new Date();
//
this.year = time.getFullYear();
this.month = Number(time.getMonth()) + 1;
this.day = time.getDate();
this.hour = time.getHours();
this.minute = time.getMinutes();
this.second = time.getSeconds();
},
init() {
this.valueArr = [];
this.reset = false;
if (this.mode == 'time') {
this.initTimeValue();
if (this.params.year) {
this.valueArr.push(0);
this.setYears();
}
if (this.params.month) {
this.valueArr.push(0);
this.setMonths();
}
if (this.params.day) {
this.valueArr.push(0);
this.setDays();
}
if (this.params.hour) {
this.valueArr.push(0);
this.setHours();
}
if (this.params.minute) {
this.valueArr.push(0);
this.setMinutes();
}
if (this.params.second) {
this.valueArr.push(0);
this.setSeconds();
}
} else if (this.mode == 'region') {
if (this.params.province) {
this.valueArr.push(0);
this.setProvinces();
}
if (this.params.city) {
this.valueArr.push(0);
this.setCitys();
}
if (this.params.area) {
this.valueArr.push(0);
this.setAreas();
}
} else if (this.mode == 'selector') {
this.valueArr = this.defaultSelector;
} else if (this.mode == 'multiSelector') {
this.valueArr = this.defaultSelector;
this.multiSelectorValue = this.defaultSelector;
}
this.$forceUpdate();
},
// picker
setYears() {
//
this.years = this.generateArray(this.startYear, this.endYear);
// this.valueArrpicker
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.years, this.year));
},
setMonths() {
this.months = this.generateArray(1, 12);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.months, this.month));
},
setDays() {
let totalDays = new Date(this.year, this.month, 0).getDate();
this.days = this.generateArray(1, totalDays);
let index = 0;
// 使setMonths()this.valueArr.splice(this.valueArr.length - 1, xxx)
// this.monththis.yearwatchthis.setDays()this.valueArr.length
if (this.params.year && this.params.month) index = 2;
else if (this.params.month) index = 1;
else if (this.params.year) index = 1;
else index = 0;
this.valueArr.splice(index, 1, this.getIndex(this.days, this.day));
},
setHours() {
this.hours = this.generateArray(0, 23);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.hours, this.hour));
},
setMinutes() {
this.minutes = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.minutes, this.minute));
},
setSeconds() {
this.seconds = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this.second));
},
setProvinces() {
// province
if (!this.params.province) return;
let tmp = '';
let useCode = false;
// defaultRegionareaCode使areaCode
if (this.areaCode.length) {
tmp = this.areaCode[0];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[0];
else tmp = 0;
//
provinces.map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
}
});
this.province = tmp;
this.provinces = provinces;
//
this.valueArr.splice(0, 1, this.province);
},
setCitys() {
if (!this.params.city) return;
let tmp = '';
let useCode = false;
if (this.areaCode.length) {
tmp = this.areaCode[1];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[1];
else tmp = 0;
citys[this.province].map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
}
});
this.city = tmp;
this.citys = citys[this.province];
this.valueArr.splice(1, 1, this.city);
},
setAreas() {
if (!this.params.area) return;
let tmp = '';
let useCode = false;
if (this.areaCode.length) {
tmp = this.areaCode[2];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[2];
else tmp = 0;
areas[this.province][this.city].map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
}
});
this.area = tmp;
this.areas = areas[this.province][this.city];
this.valueArr.splice(2, 1, this.area);
},
close() {
this.$emit('input', false);
},
// picker
change(e) {
this.valueArr = e.detail.value;
let i = 0;
if (this.mode == 'time') {
// 使i++this.valueArrthis.params
// ifi1
if (this.params.year) this.year = this.years[this.valueArr[i++]];
if (this.params.month) this.month = this.months[this.valueArr[i++]];
if (this.params.day) this.day = this.days[this.valueArr[i++]];
if (this.params.hour) this.hour = this.hours[this.valueArr[i++]];
if (this.params.minute) this.minute = this.minutes[this.valueArr[i++]];
if (this.params.second) this.second = this.seconds[this.valueArr[i++]];
} else if (this.mode == 'region') {
if (this.params.province) this.province = this.valueArr[i++];
if (this.params.city) this.city = this.valueArr[i++];
if (this.params.area) this.area = this.valueArr[i++];
} else if (this.mode == 'multiSelector') {
let index = null;
//
this.defaultSelector.map((val, idx) => {
if (val != e.detail.value[idx]) index = idx;
});
//
if (index != null) {
this.$emit('columnchange', {
column: index,
index: e.detail.value[index]
});
}
}
},
//
getResult(event = null) {
// #ifdef MP-WEIXIN
if (this.moving) return;
// #endif
let result = {};
// this.paramstrue
if (this.mode == 'time') {
if (this.params.year) result.year = this.formatNumber(this.year || 0);
if (this.params.month) result.month = this.formatNumber(this.month || 0);
if (this.params.day) result.day = this.formatNumber(this.day || 0);
if (this.params.hour) result.hour = this.formatNumber(this.hour || 0);
if (this.params.minute) result.minute = this.formatNumber(this.minute || 0);
if (this.params.second) result.second = this.formatNumber(this.second || 0);
if (this.params.timestamp) result.timestamp = this.getTimestamp();
} else if (this.mode == 'region') {
if (this.params.province) result.province = provinces[this.province];
if (this.params.city) result.city = citys[this.province][this.city];
if (this.params.area) result.area = areas[this.province][this.city][this.area];
} else if (this.mode == 'selector') {
result = this.valueArr;
} else if (this.mode == 'multiSelector') {
result = this.valueArr;
}
if (event) this.$emit(event, result);
this.close();
},
//
getTimestamp() {
let time = this.year + '-' + this.month + '-' + this.day + ' ' + this.hour + ':' + this.minute + ':' + this.second;
return new Date(time).getTime() / 1000;
}
}
};
</script>
<style lang="scss" scoped>
@import '../../libs/css/style.components.scss';
.u-datetime-picker {
position: relative;
z-index: 999;
}
.u-picker-view {
height: 100%;
box-sizing: border-box;
}
.u-picker-header {
width: 100%;
height: 90rpx;
padding: 0 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
font-size: 30rpx;
background: #fff;
position: relative;
}
.u-picker-header::after {
content: '';
position: absolute;
border-bottom: 1rpx solid #eaeef1;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
bottom: 0;
right: 0;
left: 0;
}
.u-picker__title {
color: $u-content-color;
}
.u-picker-body {
width: 100%;
height: 500rpx;
overflow: hidden;
background-color: #fff;
}
.u-column-item {
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: $u-main-color;
padding: 0 8rpx;
}
.u-text {
font-size: 24rpx;
padding-left: 8rpx;
}
.u-btn-picker {
padding: 16rpx;
box-sizing: border-box;
text-align: center;
text-decoration: none;
}
.u-opacity {
opacity: 0.5;
}
.u-btn-picker--primary {
color: $u-type-primary;
}
.u-btn-picker--tips {
color: $u-tips-color;
}
</style>

439
node_modules/uview-ui/components/u-popup/u-popup.vue

@ -0,0 +1,439 @@
<template>
<view v-if="visibleSync" :style="[customStyle, {
zIndex: uZindex - 1
}]" :class="{ 'u-drawer-visible': showDrawer }" class="u-drawer">
<u-mask :maskClickAble="maskCloseAble" :z-index="uZindex - 2" :show="showDrawer && mask" @click="maskClick"></u-mask>
<view
class="u-drawer-content"
@tap="modeCenterClose(mode)"
:class="[
safeAreaInsetBottom ? 'safe-area-inset-bottom' : '',
'u-drawer-' + mode,
showDrawer ? 'u-drawer-content-visible' : '',
zoom && mode == 'center' ? 'u-animation-zoom' : ''
]"
@touchmove.stop.prevent
@tap.stop.prevent
:style="[style]"
>
<view class="u-mode-center-box" @tap.stop.prevent @touchmove.stop.prevent v-if="mode == 'center'" :style="[centerStyle]">
<u-icon
@click="close"
v-if="closeable"
class="u-close"
:class="['u-close--' + closeIconPos]"
:name="closeIcon"
:color="closeIconColor"
:size="closeIconSize"
></u-icon>
<scroll-view class="u-drawer__scroll-view" scroll-y="true">
<slot />
</scroll-view>
</view>
<scroll-view class="u-drawer__scroll-view" scroll-y="true" v-else>
<slot />
</scroll-view>
<view class="u-close" :class="['u-close--' + closeIconPos]">
<u-icon
v-if="mode != 'center' && closeable"
@click="close"
:name="closeIcon"
:color="closeIconColor"
:size="closeIconSize"
></u-icon>
</view>
</view>
</view>
</template>
<script>
/**
* popup 弹窗
* @description 弹出层容器用于展示弹窗信息提示等内容支持上右和中部弹出组件只提供容器内部内容由用户自定义
* @tutorial https://www.uviewui.com/components/popup.html
* @property {String} mode 弹出方向默认left
* @property {Boolean} mask 是否显示遮罩默认true
* @property {Stringr | Number} length mode=left | 见官网说明默认auto
* @property {Boolean} zoom 是否开启缩放动画只在mode为center时有效默认true
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Boolean} mask-close-able 点击遮罩是否可以关闭弹出层默认true
* @property {Object} custom-style 用户自定义样式
* @property {Stringr | Number} negative-top 中部弹出时往上偏移的值
* @property {Numberr | String} border-radius 弹窗圆角值默认0
* @property {Numberr | String} z-index 弹出内容的z-index值默认1075
* @property {Boolean} closeable 是否显示关闭图标默认false
* @property {String} close-icon 关闭图标的名称只能uView的内置图标
* @property {String} close-icon-pos 自定义关闭图标位置默认top-right
* @property {String} close-icon-color 关闭图标的颜色默认#909399
* @property {Number | String} close-icon-size 关闭图标的大小单位rpx默认30
* @event {Function} open 弹出层打开
* @event {Function} close 弹出层收起
* @example <u-popup v-model="show"><view>出淤泥而不染濯清涟而不妖</view></u-popup>
*/
export default {
name: 'u-popup',
props: {
/**
* 显示状态
*/
show: {
type: Boolean,
default: false
},
/**
* 弹出方向left|right|top|bottom|center
*/
mode: {
type: String,
default: 'left'
},
/**
* 是否显示遮罩
*/
mask: {
type: Boolean,
default: true
},
// (mode=left|right)(mode=top|bottom)rpx"auto"
// "50%"
length: {
type: [Number, String],
default: 'auto'
},
// mode=center
zoom: {
type: Boolean,
default: true
},
// iPhoneX
safeAreaInsetBottom: {
type: Boolean,
default: false
},
//
maskCloseAble: {
type: Boolean,
default: true
},
//
customStyle: {
type: Object,
default() {
return {};
}
},
value: {
type: Boolean,
default: false
},
// 使Pickerkeyboard
// v-modelprops
popup: {
type: Boolean,
default: true
},
// rpx
borderRadius: {
type: [Number, String],
default: 0
},
zIndex: {
type: [Number, String],
default: ''
},
//
closeable: {
type: Boolean,
default: false
},
// uView
closeIcon: {
type: String,
default: 'close'
},
// top-lefttop-rightbottom-leftbottom-right
closeIconPos: {
type: String,
default: 'top-right'
},
//
closeIconColor: {
type: String,
default: '#909399'
},
// rpx
closeIconSize: {
type: [String, Number],
default: '30'
},
// rpx"auto"
// "50%"length
width: {
type: String,
default: ''
},
// rpx"auto"
// "50%"length
height: {
type: String,
default: ''
},
// margin-topmode=center
negativeTop: {
type: [String, Number],
default: 0
}
},
data() {
return {
visibleSync: false,
showDrawer: false,
timer: null,
};
},
computed: {
// mode(mode = left|right)(mode = top|bottom)
style() {
let style = {};
// translate
if (this.mode == 'left' || this.mode == 'right') {
style = {
width: this.width ? this.getUnitValue(this.width) : this.getUnitValue(this.length),
height: '100%',
transform: `translate3D(${this.mode == 'left' ? '-100%' : '100%'},0px,0px)`
};
} else if (this.mode == 'top' || this.mode == 'bottom') {
style = {
width: '100%',
height: this.height ? this.getUnitValue(this.height) : this.getUnitValue(this.length),
transform: `translate3D(0px,${this.mode == 'top' ? '-100%' : '100%'},0px)`
};
}
style.zIndex = this.uZindex;
// borderRadius
if (this.borderRadius) {
switch (this.mode) {
case 'left':
style.borderRadius = `0 ${this.borderRadius}rpx ${this.borderRadius}rpx 0`;
break;
case 'top':
style.borderRadius = `0 0 ${this.borderRadius}rpx ${this.borderRadius}rpx`;
break;
case 'right':
style.borderRadius = `${this.borderRadius}rpx 0 0 ${this.borderRadius}rpx`;
break;
case 'bottom':
style.borderRadius = `${this.borderRadius}rpx ${this.borderRadius}rpx 0 0`;
break;
default:
}
//
style.overflow = 'hidden';
}
return style;
},
//
centerStyle() {
let style = {};
style.width = this.width ? this.getUnitValue(this.width) : this.getUnitValue(this.length);
// auto
style.height = this.height ? this.getUnitValue(this.height) : 'auto';
style.zIndex = this.uZindex;
style.marginTop = `-${this.$u.addUnit(this.negativeTop)}`;
if (this.borderRadius) {
style.borderRadius = `${this.borderRadius}rpx`;
//
style.overflow = 'hidden';
}
return style;
},
// z-index
uZindex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
watch: {
value(val) {
if (val) {
this.open();
} else {
this.close();
}
}
},
mounted() {
// valuetruepopup
this.value && this.open();
},
methods: {
// rpx
getUnitValue(val) {
if(/(%|px|rpx|auto)$/.test(val)) return val;
else return val + 'rpx'
},
//
maskClick() {
this.close();
},
close() {
this.change('showDrawer', 'visibleSync', false);
},
// .u-drawer-content
// mode=center
modeCenterClose(mode) {
if (mode != 'center' || !this.maskCloseAble) return;
this.close();
},
open() {
this.change('visibleSync', 'showDrawer', true);
},
//
//
change(param1, param2, status) {
// this.popupfalsepickeractionsheetpopup
if (this.popup == true) this.$emit('input', status);
this[param1] = status;
if(status) {
// #ifdef H5 || MP
this.timer = setTimeout(() => {
this[param2] = status;
this.$emit(status ? 'open' : 'close');
}, 50);
// #endif
// #ifndef H5 || MP
this.$nextTick(() => {
this[param2] = status;
this.$emit(status ? 'open' : 'close');
})
// #endif
} else {
this.timer = setTimeout(() => {
this[param2] = status;
this.$emit(status ? 'open' : 'close');
}, 300);
}
}
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-drawer {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.u-drawer-content {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: absolute;
z-index: 1003;
transition: all 0.3s linear;
}
.u-drawer__scroll-view {
width: 100%;
height: 100%;
}
.u-drawer-left {
top: 0;
bottom: 0;
left: 0;
background-color: #ffffff;
}
.u-drawer-right {
right: 0;
top: 0;
bottom: 0;
background-color: #ffffff;
}
.u-drawer-top {
top: 0;
left: 0;
right: 0;
background-color: #ffffff;
}
.u-drawer-bottom {
bottom: 0;
left: 0;
right: 0;
background-color: #ffffff;
}
.u-drawer-center {
/* #ifndef APP-NVUE */
display: flex;
flex-direction: column;
/* #endif */
bottom: 0;
left: 0;
right: 0;
top: 0;
justify-content: center;
align-items: center;
opacity: 0;
z-index: 99999;
}
.u-mode-center-box {
min-width: 100rpx;
min-height: 100rpx;
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: relative;
background-color: #ffffff;
}
.u-drawer-content-visible.u-drawer-center {
transform: scale(1);
opacity: 1;
}
.u-animation-zoom {
transform: scale(1.15);
}
.u-drawer-content-visible {
transform: translate3D(0px, 0px, 0px) !important;
}
.u-close {
position: absolute;
z-index: 3;
}
.u-close--top-left {
top: 30rpx;
left: 30rpx;
}
.u-close--top-right {
top: 30rpx;
right: 30rpx;
}
.u-close--bottom-left {
bottom: 30rpx;
left: 30rpx;
}
.u-close--bottom-right {
right: 30rpx;
bottom: 30rpx;
}
</style>

86
node_modules/uview-ui/components/u-radio-group/u-radio-group.vue

@ -0,0 +1,86 @@
<template>
<view class="u-radio-group u-clearfix">
<slot></slot>
</view>
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
/**
* radioRroup 单选框父组件
* @description 单选框用于有一个选择用户只能选择其中一个的场景搭配u-radio使用
* @tutorial https://www.uviewui.com/components/radio.html
* @property {Boolean} disabled 是否禁用所有radio默认false
* @property {String} active-color 选中时的颜色应用到所有子Radio组件默认#2979ff
* @event {Function} change 任一个radio状态发生变化时触发
* @property {String} width 宽度需带单位
* @property {Boolean} wrap 是否每个radio都换行默认false
* @example <u-radio-group v-model="value"></u-radio-group>
*/
export default {
name: "u-radio-group",
mixins: [Emitter],
props: {
//
disabled: {
type: Boolean,
default: false
},
// radioradionameradio
value: {
type: [String, Number],
default: ''
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
size: {
type: [String, Number],
default: 34
},
// checkboxu-checkbox-group
width: {
type: String,
default: 'auto'
},
// checkbox
wrap: {
type: Boolean,
default: false
}
},
provide() {
return {
radioGroup: this
}
},
methods: {
// radioradiovalue(propsvalue)
setValue(val) {
// emitv-model
this.$emit('input', val);
// this.$emit('input')
this.$nextTick(function() {
this.$emit('change', this.value);
// checkbox
// u-form-item
this.dispatch('u-form-item', 'on-form-change', this.value);
});
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-radio-group {
/* #ifndef MP */
display: inline-flex;
flex-wrap: wrap;
/* #endif */
}
</style>

229
node_modules/uview-ui/components/u-radio/u-radio.vue

@ -0,0 +1,229 @@
<template>
<view class="u-radio" :style="[radioStyle]">
<view class="u-radio__icon-wrap" @tap="toggle">
<u-icon :class="iconClass" name="checkbox-mark" :size="iconSize" :color="iconColor" class="u-radio__icon" :style="[iconStyle]" />
</view>
<view class="u-label-class u-radio__label" @tap="onClickLabel" :style="{
fontSize: labelSize + 'rpx'
}">
<slot />
</view>
</view>
</template>
<script>
/**
* radio 单选框
* @description 单选框用于有一个选择用户只能选择其中一个的场景搭配u-radio-group使用
* @tutorial https://www.uviewui.com/components/radio.html
* @property {String Number} icon-size 图标大小单位rpx默认24
* @property {String Number} label-size label字体大小单位rpx默认28
* @property {String Number} name radio组件的标示符
* @property {String} shape 形状见上方说明默认circle
* @property {Boolean} disabled 是否禁用默认false
* @property {Boolean} label-disabled 点击文本是否可以操作radio默认true
* @property {String} active-color 选中时的颜色如设置radioGroup的active-color将失效
* @event {Function} change 某个radio状态发生变化时触发(选中状态)
* @example <u-radio :label-disabled="false">门掩黄昏无计留春住</u-radio>
*/
export default {
name: "u-radio",
props: {
// radio
name: {
type: [String, Number],
default: ''
},
// squarecircle
shape: {
type: String,
default: 'circle'
},
//
disabled: {
type: Boolean,
default: false
},
//
labelDisabled: {
type: Boolean,
default: false
},
// radioGroupactiveColor
activeColor: {
type: String,
default: ''
},
// rpx
iconSize: {
type: [String, Number],
default: 20
},
// labelrpx
labelSize: {
type: [String, Number],
default: 28
},
},
inject: ['radioGroup'],
data() {
return {
parentDisabled: false
};
},
created() {
this.parentDisabled = this.radioGroup.disabled;
},
computed: {
// radioradionameradioGroupvalue
iconStyle() {
let style = {};
if (this.radioActiveColor && this.name == this.radioGroup.value && !this.disabled && !this.parentDisabled) {
style.borderColor = this.radioActiveColor;
style.backgroundColor = this.radioActiveColor;
}
style.width = this.radioGroup.size + 'rpx';
style.height = this.radioGroup.size + 'rpx';
return style;
},
iconColor() {
return this.name == this.radioGroup.value ? '#ffffff' : 'transparent';
},
iconClass() {
let classs = [];
classs.push('u-radio__icon--' + this.shape);
if (this.name == this.radioGroup.value) classs.push('u-radio__icon--checked');
if (this.disabled || this.parentDisabled) classs.push('u-radio__icon--disabled');
if (this.name == this.radioGroup.value && (this.disabled || this.parentDisabled)) classs.push(
'u-radio__icon--disabled--checked');
return classs;
},
// radioGroupactiveColor
// activeColor
radioActiveColor() {
return this.activeColor ? this.activeColor : this.radioGroup.activeColor;
},
radioStyle() {
let style = {};
if(this.radioGroup.width) {
style.width = this.radioGroup.width;
// #ifdef MP
// 使float
style.float = 'left';
// #endif
// #ifndef MP
// H5APP使flex
style.flex = `0 0 ${this.radioGroup.width}`;
// #endif
}
if(this.radioGroup.wrap) {
style.width = '100%';
// #ifndef MP
// H5APP使flex100%
style.flex = '0 0 100%';
// #endif
}
return style;
}
},
methods: {
onClickLabel() {
if (!this.disabled && !this.labelDisabled && !this.parentDisabled) {
this.radioGroup.setValue(this.name);
this.emitEvent();
}
},
toggle() {
if (!this.disabled && !this.parentDisabled) {
this.radioGroup.setValue(this.name);
this.emitEvent();
}
},
emitEvent() {
this.$emit('change', this.name)
},
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-radio {
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
overflow: hidden;
-webkit-user-select: none;
user-select: none;
line-height: 1.8;
}
.u-radio__icon-wrap,
.u-radio__label {
color: $u-content-color;
}
.u-radio__icon-wrap {
-webkit-flex: none;
flex: none;
}
.u-radio__icon {
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
box-sizing: border-box;
width: 42rpx;
height: 42rpx;
color: transparent;
text-align: center;
transition-property: color, border-color, background-color;
font-size: 20px;
border: 1px solid #c8c9cc;
transition-duration: 0.2s;
}
.u-radio__icon--circle {
border-radius: 100%;
}
.u-radio__icon--square {
border-radius: 3px;
}
.u-radio__icon--checked {
color: #fff;
background-color: #2979ff;
border-color: #2979ff;
}
.u-radio__icon--disabled {
background-color: #ebedf0;
border-color: #c8c9cc;
}
.u-radio__icon--disabled--checked {
color: #c8c9cc !important;
}
.u-radio__label {
word-wrap: break-word;
margin-left: 10rpx;
margin-right: 24rpx;
color: $u-content-color;
font-size: 30rpx;
}
.u-radio__label--disabled {
color: #c8c9cc;
}
.u-radio__label:empty {
margin: 0;
}
</style>

214
node_modules/uview-ui/components/u-rate/u-rate.vue

@ -0,0 +1,214 @@
<template>
<view class="u-rate" :id="elId" @touchmove.stop.prevent="touchMove">
<view class="u-star-wrap" v-for="(item, index) in count" :key="index" :class="[elClass]">
<u-icon
:name="activeIndex > index ? activeIcon : inactiveIcon"
@click="click(index + 1, $event)"
:color="activeIndex > index ? activeColor : inactiveColor"
:style="{
fontSize: size + 'rpx',
padding: `0 ${gutter / 2 + 'rpx'}`
}"
></u-icon>
</view>
</view>
</template>
<script>
/**
* rate 评分
* @description 该组件一般用于满意度调查星型评分的场景
* @tutorial https://www.uviewui.com/components/rate.html
* @property {String Number} count 最多可选的星星数量默认5
* @property {String Number} current 默认选中的星星数量默认0
* @property {Boolean} disabled 是否禁止用户操作默认false
* @property {String Number} size 星星的大小单位rpx默认32
* @property {String} inactive-color 未选中星星的颜色默认#b2b2b2
* @property {String} active-color 选中的星星颜色默认#FA3534
* @property {String} active-icon 选中时的图标名只能为uView的内置图标默认star-fill
* @property {String} inactive-icon 未选中时的图标名只能为uView的内置图标默认star
* @property {String} gutter 星星之间的距离默认10
* @property {String Number} min-count 最少选中星星的个数默认0
* @property {Boolean} allow-half 是否允许半星选择默认false
* @event {Function} change 选中的星星发生变化时触发
* @example <u-rate :count="count" :current="2"></u-rate>
*/
export default {
name: 'u-rate',
props: {
// v-model
// 1.4.5
value: {
type: [Number, String],
default: -1
},
//
count: {
type: [Number, String],
default: 5
},
// ()
// 1.4.5value使
current: {
type: [Number, String],
default: 0
},
//
disabled: {
type: Boolean,
default: false
},
// rpx
size: {
type: [Number, String],
default: 32
},
//
inactiveColor: {
type: String,
default: '#b2b2b2'
},
//
activeColor: {
type: String,
default: '#FA3534'
},
// rpx
gutter: {
type: [Number, String],
default: 10
},
//
minCount: {
type: [Number, String],
default: 0
},
// ()
allowHalf: {
type: Boolean,
default: false
},
// ()
activeIcon: {
type: String,
default: 'star-fill'
},
// ()
inactiveIcon: {
type: String,
default: 'star'
}
},
data() {
return {
// id
elId: this.$u.guid(),
elClass: this.$u.guid(),
starBoxLeft: 0, //
// indexvalue使value(1.4.5)
activeIndex: this.value != -1 ? this.value : this.current,
starWidth: 0, //
starWidthArr: [] //
};
},
watch: {
current(val) {
this.activeIndex = val;
},
value(val) {
this.activeIndex = val;
}
},
methods: {
//
getElRectById() {
// uView
this.$u.getRect('#' + this.elId).then(res => {
this.starBoxLeft = res.left;
})
},
//
getElRectByClass() {
// uView
this.$u.getRect('.' + this.elClass).then(res => {
this.starWidth = res.width;
//
for (let i = 0; i < this.count; i++) {
this.starWidthArr[i] = (i + 1) * this.starWidth;
}
})
},
//
touchMove(e) {
if (this.disabled) {
return;
}
if (!e.changedTouches[0]) {
return;
}
const movePageX = e.changedTouches[0].pageX;
//
const distance = movePageX - this.starBoxLeft;
// 0
if (distance <= 0) {
this.activeIndex = 0;
}
//
let index = Math.ceil(distance / this.starWidth);
this.activeIndex = index > this.count ? this.count : index;
//
if (this.activeIndex < this.minCount) this.activeIndex = this.minCount;
this.emitEvent();
},
//
click(index, e) {
if (this.disabled) {
return;
}
//
if (this.allowHalf) {
}
// 0
if (index == 1) {
if (this.activeIndex == 1) this.activeIndex = 0;
else this.activeIndex = 1;
} else {
this.activeIndex = index;
}
//
if (this.activeIndex < this.minCount) this.activeIndex = this.minCount;
this.emitEvent();
},
//
emitEvent() {
// change
this.$emit('change', this.activeIndex);
// value
if(this.value != -1) {
this.$emit('input', this.activeIndex);
}
}
},
mounted() {
this.getElRectById();
this.getElRectByClass();
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-rate {
display: -webkit-inline-flex;
display: inline-flex;
align-items: center;
margin: 0;
padding: 0;
}
.u-icon {
box-sizing: border-box;
}
</style>

161
node_modules/uview-ui/components/u-read-more/u-read-more.vue

@ -0,0 +1,161 @@
<template>
<view class="">
<view class="u-content" :class="[elId]" :style="{ height: isLongContent && !showMore ? showHeight + 'rpx' : 'auto' }">
<slot></slot>
</view>
<view @tap="toggleReadMore" v-if="isLongContent" class="u-showmore-wrap"
:class="{ 'u-show-more': showMore }"
:style="[innerShadowStyle]"
>
<text class="u-readmore-btn" :style="{
fontSize: fontSize + 'rpx',
color: color
}">
{{ showMore ? openText : closeText }}
</text>
<u-icon :color="color" :size="fontSize" class="u-icon" :name="showMore ? 'arrow-up' : 'arrow-down'"></u-icon>
</view>
</view>
</template>
<script>
/**
* readMore 阅读更多
* @description 该组件一般用于内容较长预先收起一部分点击展开全部内容的场景
* @tutorial https://www.uviewui.com/components/readMore.html
* @property {String Number} show-height 内容超出此高度才会显示展开全文按钮单位rpx默认400
* @property {Boolean} toggle 展开后是否显示收起按钮默认false
* @property {String} close-text 关闭时的提示文字默认展开阅读全文
* @property {String Number} font-size 提示文字的大小单位rpx默认28
* @property {String} open-text 展开时的提示文字默认收起
* @property {String} color 提示文字的颜色默认#2979ff
* @example <u-read-more><rich-text :nodes="content"></rich-text></u-read-more>
*/
export default {
name: "u-read-more",
props: {
// rpx
showHeight: {
type: [Number, String],
default: 400
},
// ""
toggle: {
type: Boolean,
default: false
},
//
closeText: {
type: String,
default: '展开阅读全文'
},
//
openText: {
type: String,
default: '收起'
},
//
color: {
type: String,
default: '#2979ff'
},
//
fontSize: {
type: [String, Number],
default: 28
},
//
shadowStyle: {
type: Object,
default() {
return {
backgroundImage: "linear-gradient(-180deg, rgba(255, 255, 255, 0) 0%, #fff 80%)",
paddingTop: "300rpx",
marginTop: "-300rpx"
}
}
}
},
watch: {
paramsChange(val) {
this.init();
}
},
computed: {
paramsChange() {
return `${this.toggle}-${this.showHeight}`;
},
//
innerShadowStyle() {
if(this.showMore) return {};
else return this.shadowStyle
}
},
data() {
return {
isLongContent: false, //
showMore: false, // true-false-
elId: this.$u.guid(), // class
};
},
mounted() {
this.init();
},
methods: {
init() {
this.$uGetRect('.' + this.elId).then(res => {
//
if (res.height > uni.upx2px(this.showHeight)) {
this.isLongContent = true;
this.showMore = false;
}
})
},
//
toggleReadMore() {
this.showMore = !this.showMore;
// togglefalse""
if (this.toggle == false) this.isLongContent = false;
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-content {
font-size: 30rpx;
color: $u-content-color;
line-height: 1.8;
text-align: left;
text-indent: 2em;
overflow: hidden;
}
.u-showmore-wrap {
position: relative;
width: 100%;
padding-bottom: 26rpx;
display: flex;
align-items: center;
justify-content: center;
}
.u-show-more {
padding-top: 0;
background: none;
margin-top: 20rpx;
}
.u-readmore-btn {
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
}
.u-icon {
margin-left: 14rpx;
}
</style>

267
node_modules/uview-ui/components/u-row-notice/u-row-notice.vue

@ -0,0 +1,267 @@
<template>
<view
v-if="show"
class="u-notice-bar"
:style="{
background: computeBgColor,
padding: padding
}"
:class="[
type ? `u-type-${type}-light-bg` : ''
]"
>
<view class="u-direction-row">
<view class="u-icon-wrap">
<u-icon class="u-left-icon" v-if="volumeIcon" name="volume-fill" :size="volumeSize" :color="computeColor"></u-icon>
</view>
<view class="u-notice-box" id="u-notice-box">
<view
class="u-notice-content"
id="u-notice-content"
:style="{
animationDuration: animationDuration,
animationPlayState: animationPlayState,
}"
>
<text class="u-notice-text" @tap="click" :style="[textStyle]"
:class="['u-type-' + type]">{{showText}}</text>
</view>
</view>
<view class="u-icon-wrap">
<u-icon @click="getMore" class="u-right-icon" v-if="moreIcon" name="arrow-right" :size="26" :color="computeColor"></u-icon>
<u-icon @click="close" class="u-right-icon" v-if="closeIcon" name="close" :size="24" :color="computeColor"></u-icon>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
//
list: {
type: Array,
default() {
return [];
}
},
// success|error|primary|info|warning|none
// none(contentColor)
type: {
type: String,
default: 'warning'
},
//
volumeIcon: {
type: Boolean,
default: true
},
//
moreIcon: {
type: Boolean,
default: false
},
//
closeIcon: {
type: Boolean,
default: false
},
//
autoplay: {
type: Boolean,
default: true
},
// 使
color: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: ''
},
//
show: {
type: Boolean,
default: true
},
// rpx
fontSize: {
type: [Number, String],
default: 26
},
//
volumeSize: {
type: [Number, String],
default: 34
},
// rpx
speed: {
type: [Number, String],
default: 160
},
// play-paused-
playState: {
type: String,
default: 'play'
},
//
padding: {
type: [Number, String],
default: '18rpx 24rpx'
}
},
data() {
return {
textWidth: 0, //
boxWidth: 0, //
animationDuration: '10s', //
animationPlayState: 'paused', //
showText: '' //
};
},
watch: {
list: {
immediate: true,
handler(val) {
this.showText = val.join(',');
this.$nextTick(() => {
this.initSize();
});
}
},
playState(val) {
if(val == 'play') this.animationPlayState = 'running';
else this.animationPlayState = 'paused';
},
speed(val) {
this.initSize();
}
},
computed: {
// uview
computeColor() {
if (this.color) return this.color;
// 使content-color
else if(this.type == 'none') return '#606266';
else return this.type;
},
//
textStyle() {
let style = {};
if (this.color) style.color = this.color;
else if(this.type == 'none') style.color = '#606266';
style.fontSize = this.fontSize + 'rpx';
return style;
},
//
computeBgColor() {
if (this.bgColor) return this.bgColor;
else if(this.type == 'none') return 'transparent';
}
},
mounted() {
this.$nextTick(() => {
this.initSize();
});
},
methods: {
initSize() {
let query = [],
boxWidth = 0,
textWidth = 0;
let textQuery = new Promise((resolve, reject) => {
uni.createSelectorQuery()
.in(this)
.select(`#u-notice-content`)
.boundingClientRect()
.exec(ret => {
this.textWidth = ret[0].width;
resolve();
});
});
query.push(textQuery);
Promise.all(query).then(() => {
// t=s/v(=/)#u-notice-box.u-notice-contentpadding-left: 100%
// #u-notice-box
this.animationDuration = `${this.textWidth / uni.upx2px(this.speed)}s`;
// APP(HX2.4.6IOS13)
this.animationPlayState = 'paused';
setTimeout(() => {
if(this.playState == 'play' && this.autoplay) this.animationPlayState = 'running';
}, 10);
});
},
//
click(index) {
this.$emit('click');
},
//
close() {
this.$emit('close');
},
//
getMore() {
this.$emit('getMore');
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-notice-bar {
padding: 18rpx 24rpx;
overflow: hidden;
}
.u-direction-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.u-left-icon {
display: inline-flex;
align-items: center;
}
.u-notice-box {
flex: 1;
display: flex;
overflow: hidden;
margin-left: 12rpx;
}
.u-right-icon {
margin-left: 12rpx;
display: inline-flex;
align-items: center;
}
.u-notice-content {
animation: u-loop-animation 10s linear infinite both;
text-align: right;
//
padding-left: 100%;
display: flex;
flex-wrap: nowrap;
}
.u-notice-text {
font-size: 26rpx;
word-break: keep-all;
white-space: nowrap
}
@keyframes u-loop-animation {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(-100%, 0, 0);
}
}
</style>

84
node_modules/uview-ui/components/u-row/u-row.vue

@ -0,0 +1,84 @@
<template>
<view class="u-row" :style="{
alignItems: uAlignItem,
justifyContent: uJustify
}"
@tap.stop.prevent="click"
>
<slot />
</view>
</template>
<script>
/**
* row 行布局
* @description 通过基础的 12 分栏迅速简便地创建布局
* @tutorial https://www.uviewui.com/components/layout.html#row-props
* @property {String Number} gutter 栅格间隔左右各为此值的一半单位rpx默认0
* @property {String} justify 水平排列方式(微信小程序暂不支持)默认start(或flex-start)
* @property {String} align 垂直排列方式默认center
* @example <u-row gutter="16"></u-row>
*/
export default {
name: "u-row",
props: {
// col
gutter: {
type: [String, Number],
default: 20
},
// `start`(`flex-start`)`end`(`flex-end`)`center``around`(`space-around`)`between`(`space-between`)
justify: {
type: String,
default: 'start'
},
// topcenterbottom
align: {
type: String,
default: 'center'
}
},
provide() {
return {
gutter: this.gutter
}
},
computed: {
uJustify() {
if (this.justify == 'end' || this.justify == 'start') return 'flex-' + this.justify;
else if (this.justify == 'around' || this.justify == 'between') return 'space-' + this.justify;
else return this.justify;
},
uAlignItem() {
if (this.align == 'top') return 'flex-start';
if (this.align == 'bottom') return 'flex-end';
else return this.align;
}
},
methods: {
click() {
this.$emit('click');
}
}
}
</script>
<style lang="scss">
@import "../../libs/css/style.components.scss";
.u-row {
// 使floatflex
/* #ifndef MP-WEIXIN */
display: flex;
/* #endif */
flex-wrap: wrap;
}
.u-row:after {
/* #ifdef MP-WEIXIN */
display: table;
clear: both;
content: "";
/* #endif */
}
</style>

334
node_modules/uview-ui/components/u-search/u-search.vue

@ -0,0 +1,334 @@
<template>
<view class="u-search" :style="{
margin: margin,
}">
<view
class="u-content"
:style="{
backgroundColor: bgColor,
borderRadius: shape == 'round' ? '100rpx' : '10rpx',
border: borderStyle,
height: height + 'rpx'
}"
>
<view class="u-icon-wrap">
<u-icon class="u-clear-icon" :size="30" :name="searchIcon" :color="searchIconColor ? searchIconColor : color"></u-icon>
</view>
<input
confirm-type="search"
@blur="blur"
:value="value"
@confirm="search"
@input="inputChange"
:disabled="disabled"
@focus="getFocus"
:maxlength="getMaxlength"
:focus="focus"
placeholder-class="u-placeholder-class"
:placeholder="placeholder"
:placeholder-style="`color: ${placeholderColor}`"
class="u-input"
type="text"
:style="[{
textAlign: inputAlign,
color: color,
backgroundColor: bgColor,
}, inputStyle]"
/>
<view class="u-close-wrap" v-if="keyword && clearabled && focused" @touchstart="clear">
<u-icon class="u-clear-icon" name="close-circle-fill" size="34" color="#c0c4cc"></u-icon>
</view>
</view>
<view :style="[actionStyle]" class="u-action"
:class="[showActionBtn || show ? 'u-action-active' : '']"
@touchstart.stop.prevent="custom"
>{{ actionText }}</view>
</view>
</template>
<script>
/**
* search 搜索框
* @description 搜索组件集成了常见搜索框所需功能用户可以一键引入开箱即用
* @tutorial https://www.uviewui.com/components/search.html
* @property {String} shape 搜索框形状round-圆形square-方形默认round
* @property {String} bg-color 搜索框背景颜色默认#f2f2f2
* @property {String} border-color 边框颜色配置了颜色才会有边框
* @property {String} placeholder 占位文字内容默认请输入关键字
* @property {Boolean} clearabled 是否启用清除控件默认true
* @property {Boolean} focus 是否自动获得焦点默认false
* @property {Boolean} show-action 是否显示右侧控件默认true
* @property {String} action-text 右侧控件文字默认搜索
* @property {Object} action-style 右侧控件的样式对象形式
* @property {String} input-align 输入框内容水平对齐方式默认left
* @property {Object} input-style 自定义输入框样式对象形式
* @property {Boolean} disabled 是否启用输入框默认false
* @property {String} search-icon-color 搜索图标的颜色默认同输入框字体颜色
* @property {String} color 输入框字体颜色默认#606266
* @property {String} placeholder-color placeholder的颜色默认#909399
* @property {String} search-icon 输入框左边的图标可以为uView图标名称或图片路径
* @property {String} margin 组件与其他上下左右元素之间的距离带单位的字符串形式"30rpx"
* @property {Boolean} animation 是否开启动画见上方说明默认false
* @property {String} value 输入框初始值
* @property {String | Number} maxlength 输入框最大能输入的长度-1为不限制长度
* @property {Boolean} input-style input输入框的样式可以定义文字颜色大小等对象形式
* @property {String | Number} height 输入框高度单位rpx默认64
* @event {Function} change 输入框内容发生变化时触发
* @event {Function} search 用户确定搜索时触发用户按回车键或者手机键盘右下角的"搜索"键时触发
* @event {Function} custom 用户点击右侧控件时触发
* @event {Function} clear 用户点击清除按钮时触发
* @example <u-search placeholder="日照香炉生紫烟" v-model="keyword"></u-search>
*/
export default {
name: "u-search",
props: {
// round-square-
shape: {
type: String,
default: 'round'
},
// #f2f2f2
bgColor: {
type: String,
default: '#f2f2f2'
},
//
placeholder: {
type: String,
default: '请输入关键字'
},
//
clearabled: {
type: Boolean,
default: true
},
//
focus: {
type: Boolean,
default: false
},
//
showAction: {
type: Boolean,
default: true
},
//
actionStyle: {
type: Object,
default() {
return {};
}
},
//
actionText: {
type: String,
default: '搜索'
},
// left|center|right
inputAlign: {
type: String,
default: 'left'
},
//
disabled: {
type: Boolean,
default: false
},
// showActioninput
animation: {
type: Boolean,
default: false
},
//
borderColor: {
type: String,
default: 'none'
},
//
value: {
type: String,
default: ''
},
// rpx
height: {
type: [Number, String],
default: 64
},
// input
inputStyle: {
type: Object,
default() {
return {}
}
},
// -1(uniapp)
maxlength: {
type: [Number, String],
default: -1
},
//
searchIconColor: {
type: String,
default: ''
},
//
color: {
type: String,
default: '#606266'
},
// placeholder
placeholderColor: {
type: String,
default: '#909399'
},
// "30rpx""30rpx 20rpx"
margin: {
type: String,
default: '0'
},
// uView
searchIcon: {
type: String,
default: 'search'
}
},
data() {
return {
keyword: '',
showClear: false, //
show: false,
// input
focused: this.focus
//
// inputValue: this.value
};
},
watch: {
keyword(nVal) {
// v-model
this.$emit('input', nVal);
// changev-model
this.$emit('change', nVal);
},
value: {
immediate: true,
handler(nVal) {
this.keyword = nVal;
}
}
},
computed: {
showActionBtn() {
if (!this.animation && this.showAction) return true;
else return false;
},
// none
borderStyle() {
if (this.borderColor) return `1px solid ${this.borderColor}`;
else return 'none';
},
// maxlength
getMaxlength() {
return Number(this.maxlength);
}
},
methods: {
// HX2.6.9 v-modelinput
inputChange(e) {
this.keyword = e.detail.value;
},
//
// this.$refs
clear() {
this.keyword = '';
// clearvalue()
this.$nextTick(() => {
this.$emit('clear');
})
},
//
search(e) {
this.$emit('search', e.detail.value);
//
uni.hideKeyboard();
},
//
custom() {
this.$emit('custom', this.keyword);
//
uni.hideKeyboard();
},
//
getFocus() {
this.focused = true;
//
if (this.animation && this.showAction) this.show = true;
this.$emit('focus', this.keyword);
},
//
blur() {
this.focused = false;
this.show = false;
this.$emit('blur', this.keyword);
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-search {
display: flex;
align-items: center;
flex: 1;
}
.u-content {
display: flex;
align-items: center;
padding: 0 18rpx;
flex: 1;
}
.u-clear-icon {
display: flex;
align-items: center;
}
.u-input {
flex: 1;
font-size: 28rpx;
line-height: 1;
margin: 0 10rpx;
color: $u-tips-color;
}
.u-close-wrap {
width: 40rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.u-placeholder-class {
color: $u-tips-color;
}
.u-action {
font-size: 28rpx;
color: $u-main-color;
width: 0;
overflow: hidden;
transition: all 0.3s;
white-space: nowrap;
text-align: center;
}
.u-action-active {
width: 80rpx;
margin-left: 10rpx;
}
</style>

131
node_modules/uview-ui/components/u-section/u-section.vue

@ -0,0 +1,131 @@
<template>
<view class="u-section">
<view class="u-section-title" :style="{
fontWeight: bold ? 'bold' : 'normal',
color: color,
fontSize: fontSize + 'rpx',
paddingLeft: showLine ? '10rpx' : 0
}" :class="{
'u-section--line': showLine
}">
{{title}}
</view>
<view class="u-right-info" v-if="right" :style="{
color: subColor
}" @tap="rightClick">
{{subTitle}}
<view class="u-icon-arrow">
<u-icon name="arrow-right" size="24" :color="subColor"></u-icon>
</view>
</view>
</view>
</template>
<script>
/**
* section 查看更多
* @description 该组件一般用于分类信息有很多但是限于篇幅只能列出一部分让用户通过"查看更多"获得更多信息的场景实际效果见演示
* @tutorial https://www.uviewui.com/components/section.html
* @property {String} title 左边主标题
* @property {String} sub-title 右边副标题默认更多
* @property {Boolean} right 是否显示右边的内容默认true
* @property {Boolean} showLine 是否显示左边的竖条默认true
* @property {String Number} font-size 主标题的字体大小默认28
* @property {Boolean} bold 主标题是否加粗默认true
* @property {String} color 主标题颜色默认#303133
* @event {Function} click 组件右侧的内容被点击时触发用于跳转"更多"
* @example <u-section title="今日热门" :right="false"></u-section>
*/
export default {
name: "u-section",
props: {
//
title: {
type: String,
default: ''
},
//
subTitle: {
type: String,
default: '更多'
},
//
right: {
type: Boolean,
default: true
},
fontSize: {
type: [Number, String],
default: 28
},
//
bold: {
type: Boolean,
default: true
},
//
color: {
type: String,
default: '#303133'
},
//
subColor: {
type: String,
default: '#909399'
},
//
showLine: {
type: Boolean,
default: true
}
},
data() {
return {
}
},
methods: {
rightClick() {
this.$emit('click');
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-section {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.u-section-title {
position: relative;
font-size: 28rpx;
line-height: 1;
}
.u-section--line:after {
position: absolute;
width: 4px;
height: 100%;
content: '';
left: 0;
border-radius: 10px;
background-color: currentColor;
}
.u-right-info {
color: $u-tips-color;
font-size: 26rpx;
display: flex;
align-items: center;
}
.u-icon-arrow {
margin-left: 6rpx;
}
</style>

406
node_modules/uview-ui/components/u-select/u-select.vue

@ -0,0 +1,406 @@
<template>
<view class="u-select">
<!-- <view class="u-select__action" :class="{
'u-select--border': border
}" @tap.stop="selectHandler">
<view class="u-select__action__icon" :class="{
'u-select__action__icon--reverse': value == true
}">
<u-icon name="arrow-down-fill" size="26" color="#c0c4cc"></u-icon>
</view>
</view> -->
<u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex">
<!-- 多加一个if判断避免微信小程序第二次打开后视图没有重新渲染而导致数据混乱 -->
<view class="u-select" v-if="value">
<view class="u-select__header" @touchmove.stop.prevent="">
<view
class="u-select__header__cancel u-select__header__btn"
:style="{ color: cancelColor }"
hover-class="u-hover-class"
:hover-stay-time="150"
@tap="getResult('cancel')"
>
取消
</view>
<view class="u-select__header__title">
{{title}}
</view>
<view
class="u-select__header__confirm u-select__header__btn"
:style="{ color: moving ? cancelColor : confirmColor }"
hover-class="u-hover-class"
:hover-stay-time="150"
@touchmove.stop=""
@tap.stop="getResult('confirm')"
>
确定
</view>
</view>
<view class="u-select__body">
<picker-view @change="columnChange" class="u-select__body__picker-view" :value="defaultSelector" @pickstart="pickstart" @pickend="pickend">
<picker-view-column v-for="(item, index) in columnData" :key="index">
<view class="u-select__body__picker-view__item" v-for="(item1, index1) in item" :key="index1">
<view class="u-line-1">{{ item1[labelName] }}</view>
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
/**
* select 列选择器
* @description 此选择器用于单列多列多列联动的选择场景(从1.3.0版本起不建议使用Picker组件的单列和多列模式Select组件是专门为列选择而构造的组件更简单易用)
* @tutorial http://uviewui.com/components/select.html
* @property {String} mode 模式选择"single-column"-单列模式"mutil-column"-多列模式"mutil-column-auto"-多列联动模式
* @property {Array} list 列数据数组形式见官网说明
* @property {Boolean} v-model 布尔值变量用于控制选择器的弹出与收起
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false)
* @property {String} cancel-color 取消按钮的颜色默认#606266
* @property {String} confirm-color 确认按钮的颜色(默认#2979ff)
* @property {String} default-value 提供的默认选中的下标见官网说明
* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker(默认true)
* @property {String Number} z-index 弹出时的z-index值(默认10075)
* @property {String} value-name 自定义list数据的value属性名 1.3.6
* @property {String} label-name 自定义list数据的label属性名 1.3.6
* @property {String} child-name 自定义list数据的children属性名只对多列联动模式有效 1.3.7
* @event {Function} confirm 点击确定按钮返回当前选择的值
* @example <u-select v-model="show" :list="list"></u-select>
*/
export default {
props: {
//
list: {
type: Array,
default() {
return [];
}
},
//
border: {
type: Boolean,
default: true
},
//
value: {
type: Boolean,
default: false
},
// ""
cancelColor: {
type: String,
default: '#606266'
},
// ""
confirmColor: {
type: String,
default: '#2979ff'
},
// z-index
zIndex: {
type: [String, Number],
default: 0
},
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// Picker
maskCloseAble: {
type: Boolean,
default: true
},
//
defaultValue: {
type: Array,
default() {
return [0];
}
},
// single-column-mutil-column-mutil-column-auto-
mode: {
type: String,
default: 'single-column'
},
// value
valueName: {
type: String,
default: 'value'
},
// label
labelName: {
type: String,
default: 'label'
},
// children
childName: {
type: String,
default: 'children'
},
//
title: {
type: String,
default: ''
}
},
data() {
return {
//
defaultSelector: [0],
// picker-view
columnData: [],
//
selectValue: [],
// index
lastSelectIndex: [],
//
columnNum: 0,
//
moving: false
};
},
watch: {
// select
value: {
immediate: true,
handler(val) {
if(val) setTimeout(() => this.init(), 10);
}
},
},
computed: {
uZIndex() {
// z-index使
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
},
},
methods: {
//
pickstart() {
// #ifdef MP-WEIXIN
this.moving = true;
// #endif
},
//
pickend() {
// #ifdef MP-WEIXIN
this.moving = false;
// #endif
},
init() {
this.setColumnNum();
this.setDefaultSelector();
this.setColumnData();
this.setSelectValue();
},
//
setDefaultSelector() {
// columnNum0
this.defaultSelector = this.defaultValue.length == this.columnNum ? this.defaultValue : Array(this.columnNum).fill(0);
this.lastSelectIndex = this.$u.deepClone(this.defaultSelector);
},
//
setColumnNum() {
// 1
if(this.mode == 'single-column') this.columnNum = 1;
// this.list
else if(this.mode == 'mutil-column') this.columnNum = this.list.length;
// this.list
else if(this.mode == 'mutil-column-auto') {
let num = 1;
let column = this.list;
// children
while(column[0][this.childName]) {
column = column[0] ? column[0][this.childName] : {};
num ++;
}
this.columnNum = num;
}
},
// picker
setColumnData() {
let data = [];
this.selectValue = [];
if(this.mode == 'mutil-column-auto') {
//
let column = this.list[this.defaultSelector.length ? this.defaultSelector[0] : 0];
//
for (let i = 0; i < this.columnNum; i++) {
// list
if (i == 0) {
data[i] = this.list;
column = column[this.childName];
} else {
//
data[i] = column;
column = column[this.defaultSelector[i]][this.childName];
}
}
} else if(this.mode == 'single-column') {
data[0] = this.list;
} else {
data = this.list;
}
this.columnData = data;
},
// defaultValue
setSelectValue() {
let tmp = null;
for(let i = 0; i < this.columnNum; i++) {
tmp = this.columnData[i][this.defaultSelector[i]];
let data = {
value: tmp ? tmp[this.valueName] : null,
label: tmp ? tmp[this.labelName] : null
};
//
if(tmp && tmp.extra) data.extra = tmp.extra;
this.selectValue.push(data)
}
},
//
columnChange(e) {
let index = null;
let columnIndex = e.detail.value;
// push
this.selectValue = [];
if(this.mode == 'mutil-column-auto') {
//
this.lastSelectIndex.map((val, idx) => {
if (val != columnIndex[idx]) index = idx;
});
this.defaultSelector = columnIndex;
for (let i = index + 1; i < this.columnNum; i++) {
// children
//
this.columnData[i] = this.columnData[i - 1][i - 1 == index ? columnIndex[index] : 0][this.childName];
//
this.defaultSelector[i] = 0;
}
// this.columnDatacolumnChange
// undefined
columnIndex.map((item, index) => {
let data = this.columnData[index][columnIndex[index]];
let tmp = {
value: data ? data[this.valueName] : null,
label: data ? data[this.labelName] : null,
};
//
if(data && data.extra) tmp.extra = data.extra;
this.selectValue.push(tmp);
})
//
this.lastSelectIndex = columnIndex;
} else if(this.mode == 'single-column') {
let data = this.columnData[0][columnIndex[0]];
//
let tmp = {
value: data ? data[this.valueName] : null,
label: data ? data[this.labelName] : null,
};
//
if(data && data.extra) tmp.extra = data.extra;
this.selectValue.push(tmp);
} else if(this.mode == 'mutil-column') {
//
columnIndex.map((item, index) => {
let data = this.columnData[index][columnIndex[index]];
//
let tmp = {
value: data ? data[this.valueName] : null,
label: data ? data[this.labelName] : null,
};
//
if(data && data.extra) tmp.extra = data.extra;
this.selectValue.push(tmp);
})
}
},
close() {
this.$emit('input', false);
},
//
getResult(event = null) {
// #ifdef MP-WEIXIN
if (this.moving) return;
// #endif
if (event) this.$emit(event, this.selectValue);
this.close();
},
selectHandler() {
this.$emit('click');
}
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-select {
&__action {
position: relative;
line-height: $u-form-item-height;
height: $u-form-item-height;
&__icon {
position: absolute;
right: 20rpx;
top: 50%;
transition: transform .4s;
transform: translateY(-50%);
z-index: 1;
&--reverse {
transform: rotate(-180deg) translateY(50%);
}
}
}
&__hader {
&__title {
color: $u-content-color;
}
}
&--border {
border-radius: 6rpx;
border-radius: 4px;
border: 1px solid $u-form-item-border-color;
}
&__header {
display: flex;
align-items: center;
justify-content: space-between;
height: 80rpx;
padding: 0 40rpx;
}
&__body {
width: 100%;
height: 500rpx;
overflow: hidden;
background-color: #fff;
&__picker-view {
height: 100%;
box-sizing: border-box;
&__item {
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: $u-main-color;
padding: 0 8rpx;
}
}
}
}
</style>

167
node_modules/uview-ui/components/u-skeleton/u-skeleton.vue

@ -0,0 +1,167 @@
<template>
<view v-if="loading" :style="{
width: windowWinth + 'px',
height: windowHeight + 'px',
backgroundColor: bgColor,
position: 'absolute',
left: left + 'px',
top: top + 'px',
zIndex: 9998,
overflow: 'hidden'
}"
@touchmove.stop.prevent>
<view v-for="(item, index) in RectNodes" :key="$u.guid()" :class="[animation ? 'skeleton-fade' : '']" :style="{
width: item.width + 'px',
height: item.height + 'px',
backgroundColor: elColor,
position: 'absolute',
left: (item.left - left) + 'px',
top: (item.top - top) + 'px'
}"></view>
<view v-for="(item, index) in circleNodes" :key="$u.guid()" :class="animation ? 'skeleton-fade' : ''" :style="{
width: item.width + 'px',
height: item.height + 'px',
backgroundColor: elColor,
borderRadius: item.width/2 + 'px',
position: 'absolute',
left: (item.left - left) + 'px',
top: (item.top - top) + 'px'
}"></view>
<view v-for="(item, index) in filletNodes" :key="$u.guid()" :class="animation ? 'skeleton-fade' : ''" :style="{
width: item.width + 'px',
height: item.height + 'px',
backgroundColor: elColor,
borderRadius: borderRadius + 'rpx',
position: 'absolute',
left: (item.left - left) + 'px',
top: (item.top - top) + 'px'
}"></view>
</view>
</template>
<script>
/**
* skeleton 骨架屏
* @description 骨架屏一般用于页面在请求远程数据尚未完成时页面用灰色块预显示本来的页面结构给用户更好的体验
* @tutorial https://www.uviewui.com/components/skeleton.html
* @property {String} el-color 骨架块状元素的背景颜色默认#e5e5e5
* @property {String} bg-color 骨架组件背景颜色默认#ffffff
* @property {Boolean} animation 骨架块是否显示动画效果默认false
* @property {String Number} border-radius u-skeleton-fillet类名元素对应的骨架块的圆角大小单位rpx默认10
* @property {Boolean} loading 是否显示骨架组件请求完成后将此值设置为false默认true
* @example <u-skeleton :loading="true" :animation="true"></u-skeleton>
*/
export default {
name: "u-skeleton",
props: {
// rgb
elColor: {
type: String,
default: '#e5e5e5'
},
//
bgColor: {
type: String,
default: '#ffffff'
},
//
animation: {
type: Boolean,
default: false
},
// u-skeleton-fillet
borderRadius: {
type: [String, Number],
default: "10"
},
// true-false-
loading: {
type: Boolean,
default: true
}
},
data() {
return {
windowWinth: 750, //
windowHeight: 1500, //
filletNodes: [], //
circleNodes: [], //
RectNodes: [], //
top: 0,
left: 0,
}
},
methods: {
//
selecterQueryInfo() {
//
uni.createSelectorQuery().selectAll('.u-skeleton').boundingClientRect().exec((res) => {
this.windowHeight = res[0][0].height;
this.windowWinth = res[0][0].width;
this.top = res[0][0].bottom - res[0][0].height;
this.left = res[0][0].left;
});
//
this.getRectEls();
//
this.getCircleEls();
//
this.getFilletEls();
},
//
getRectEls() {
uni.createSelectorQuery().selectAll('.u-skeleton-rect').boundingClientRect().exec((res) => {
this.RectNodes = res[0];
});
},
//
getFilletEls() {
uni.createSelectorQuery().selectAll('.u-skeleton-fillet').boundingClientRect().exec((res) => {
this.filletNodes = res[0];
});
},
//
getCircleEls() {
uni.createSelectorQuery().selectAll('.u-skeleton-circle').boundingClientRect().exec((res) => {
this.circleNodes = res[0];
});
}
},
//
mounted() {
//
let systemInfo = uni.getSystemInfoSync();
this.windowHeight = systemInfo.windowHeight;
this.windowWinth = systemInfo.windowWidth;
this.selecterQueryInfo();
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.skeleton-fade {
width: 100%;
height: 100%;
background: rgb(194, 207, 214);
animation-duration: 1.5s;
animation-name: blink;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
}
@keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0.4;
}
100% {
opacity: 1;
}
}
</style>

254
node_modules/uview-ui/components/u-slider/u-slider.vue

@ -0,0 +1,254 @@
<template>
<view class="u-slider" @tap="onClick" :class="[disabled ? 'u-slider--disabled' : '']" :style="{
backgroundColor: inactiveColor
}">
<view
class="u-slider__gap"
:style="[
barStyle,
{
height: height + 'rpx',
backgroundColor: activeColor
}
]"
>
<view class="u-slider__button-wrap" @touchstart="onTouchStart"
@touchmove="onTouchMove" @touchend="onTouchEnd"
@touchcancel="onTouchEnd">
<slot v-if="$slots.default"/>
<view v-else class="u-slider__button" :style="[blockStyle, {
height: blockWidth + 'rpx',
width: blockWidth + 'rpx'
}]"></view>
</view>
</view>
</view>
</template>
<script>
/**
* slider 滑块选择器
* @tutorial https://uviewui.com/components/slider.html
* @property {Number | String} value 滑块默认值默认0
* @property {Number | String} min 最小值默认0
* @property {Number | String} max 最大值默认100
* @property {Number | String} step 步长默认1
* @property {Number | String} blockWidth 滑块宽度高等于宽30
* @property {Number | String} height 滑块条高度单位rpx默认6
* @property {String} inactiveColor 底部条背景颜色默认#c0c4cc
* @property {String} activeColor 底部选择部分的背景颜色默认#2979ff
* @property {String} blockColor 滑块颜色默认#ffffff
* @property {Object} blockStyle 给滑块自定义样式对象形式
* @property {Boolean} disabled 是否禁用滑块(默认为false)
* @event {Function} start 滑动触发
* @event {Function} moving 正在滑动中
* @event {Function} end 滑动结束
* @example <u-slider v-model="value" />
*/
export default {
name: 'u-slider',
props: {
// 0-100
value: {
type: [Number, String],
default: 0
},
//
disabled: {
type: Boolean,
default: false
},
// rpx
blockWidth: {
type: [Number, String],
default: 30
},
//
min: {
type: [Number, String],
default: 0
},
//
max: {
type: [Number, String],
default: 100
},
//
step: {
type: [Number, String],
default: 1
},
// rpx
height: {
type: [Number, String],
default: 6
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#c0c4cc'
},
//
blockColor: {
type: String,
default: '#ffffff'
},
//
blockStyle: {
type: Object,
default() {
return {};
}
},
},
data() {
return {
startX: 0,
status: 'end',
newValue: 0,
distanceX: 0,
startValue: 0,
barStyle: {},
sliderRect: {
left: 0,
width: 0
}
};
},
watch: {
value(n) {
// value
if(this.status == 'end') this.updateValue(this.value, false);
}
},
created() {
this.updateValue(this.value, false);
},
mounted() {
//
this.$uGetRect('.u-slider').then(rect => {
this.sliderRect = rect;
});
},
methods: {
onTouchStart(event) {
if (this.disabled) return;
this.startX = 0;
//
let touches = event.touches[0];
//
this.startX = touches.clientX;
// this.valueprops$emit('input')
this.startValue = this.format(this.value);
//
this.status = 'start';
},
onTouchMove(event) {
if (this.disabled) return;
//
// statusmoving
if (this.status == 'start') this.$emit('start');
let touches = event.touches[0];
//
this.distanceX = touches.clientX - this.sliderRect.left;
//
// step
this.newValue = (this.distanceX / this.sliderRect.width) * 100;
this.status = 'moving';
// moving
this.$emit('moving');
this.updateValue(this.newValue, true);
},
onTouchEnd() {
if (this.disabled) return;
if (this.status === 'moving') {
this.updateValue(this.newValue, false);
this.$emit('end');
}
this.status = 'end';
},
updateValue(value, drag) {
// step
const width = this.format(value);
//
let barStyle = {
width: width + '%'
};
//
if (drag == true) {
barStyle.transition = 'none';
} else {
// css
delete barStyle.transition;
}
// value
this.$emit('input', width);
this.barStyle = barStyle;
},
format(value) {
//
return Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step;
},
onClick(event) {
if (this.disabled) return;
// onTouchMove
const value = ((event.detail.x - this.sliderRect.left) / this.sliderRect.width) * 100;
this.updateValue(value, false);
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-slider {
position: relative;
border-radius: 999px;
border-radius: 999px;
background-color: #ebedf0;
}
.u-slider:before {
position: absolute;
right: 0;
left: 0;
content: '';
top: -8px;
bottom: -8px;
z-index: -1;
}
.u-slider__gap {
position: relative;
border-radius: inherit;
transition: width 0.2s;
transition: width 0.2s;
background-color: #1989fa;
}
.u-slider__button {
width: 24px;
height: 24px;
border-radius: 50%;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
background-color: #fff;
cursor: pointer;
}
.u-slider__button-wrap {
position: absolute;
top: 50%;
right: 0;
transform: translate3d(50%, -50%, 0);
}
.u-slider--disabled {
opacity: 0.5;
}
</style>

200
node_modules/uview-ui/components/u-steps/u-steps.vue

@ -0,0 +1,200 @@
<template>
<view class="">
<view
class="u-steps"
:style="{
flexDirection: direction
}"
>
<view class="u-steps__item"
:class="['u-steps__item--' + direction]"
v-for="(item, index) in list" :key="index"
>
<view
class="u-steps__item__num"
v-if="mode == 'number'"
:style="{
backgroundColor: current < index ? 'transparent' : activeColor,
borderColor: current < index ? unActiveColor : activeColor
}"
>
<text v-if="current < index" :style="{
color: current < index ? unActiveColor : activeColor,
}">
{{ index + 1 }}
</text>
<u-icon v-else size="22" color="#ffffff" :name="icon"></u-icon>
</view>
<view class="u-steps__item__dot" v-if="mode == 'dot'" :style="{
backgroundColor: index <= current ? activeColor : unActiveColor
}"></view>
<text :style="{
color: index <= current ? activeColor : unActiveColor,
}" :class="['u-steps__item__text--' + direction]">
{{ item.name }}
</text>
<view class="u-steps__item__line" :class="['u-steps__item__line--' + mode]" v-if="index < list.length - 1">
<u-line :direction="direction" length="100%" :hair-line="false" :color="unActiveColor"></u-line>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* steps 步骤条
* @description 该组件一般用于完成一个任务要分几个步骤标识目前处于第几步的场景
* @tutorial https://www.uviewui.com/components/steps.html
* @property {String} mode 设置模式默认dot
* @property {Array} list 数轴条数据数组具体见上方示例
* @property {String} type type主题默认primary
* @property {String} direction row-横向column-竖向默认row
* @property {Number String} current 设置当前处于第几步
* @property {String} active-color 已完成步骤的激活颜色如设置type值会失效
* @property {String} un-active-color 未激活的颜色用于表示未完成步骤的颜色默认#606266
* @example <u-steps :list="numList" active-color="#fa3534"></u-steps>
*/
export default {
name: 'u-steps',
props: {
// dot|number
mode: {
type: String,
default: 'dot'
},
//
list: {
type: Array,
default() {
return [];
}
},
// , primary|success|info|warning|error
type: {
type: String,
default: 'primary'
},
//
current: {
type: [Number, String],
default: 0
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
unActiveColor: {
type: String,
default: '#909399'
},
//
icon: {
type: String,
default: 'checkmark'
},
// steprow-column-
direction: {
type: String,
default: 'row'
}
},
data() {
return {};
},
};
</script>
<style lang="scss" scoped>
@import '../../libs/css/style.components.scss';
$u-steps-item-number-width: 44rpx;
$u-steps-item-dot-width: 20rpx;
.u-steps {
display: flex;
.u-steps__item {
flex: 1;
text-align: center;
position: relative;
min-width: 100rpx;
font-size: 26rpx;
color: #8799a3;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
&--row {
display: flex;
flex-direction: column;
.u-steps__item__line {
position: absolute;
z-index: 0;
left: 75%;
width: 50%;
&--dot {
top: calc(#{$u-steps-item-dot-width} / 2);
}
&--number {
top: calc(#{$u-steps-item-number-width} / 2);
}
}
}
&--column {
display: flex;
flex-direction: row;
justify-content: flex-start;
min-height: 120rpx;
.u-steps__item__line {
position: absolute;
z-index: 0;
height: 50%;
top: 75%;
&--dot {
left: calc(#{$u-steps-item-dot-width} / 2);
}
&--number {
left: calc(#{$u-steps-item-number-width} / 2);
}
}
}
&__num {
display: flex;
align-items: center;
justify-content: center;
width: $u-steps-item-number-width;
height: $u-steps-item-number-width;
border: 1px solid #8799a3;
border-radius: 50%;
overflow: hidden;
}
&__dot {
width: $u-steps-item-dot-width;
height: $u-steps-item-dot-width;
display: flex;
border-radius: 50%;
}
&__text--row {
margin-top: 14rpx;
}
&__text--column {
margin-left: 14rpx;
}
}
}
</style>

152
node_modules/uview-ui/components/u-sticky/u-sticky.vue

@ -0,0 +1,152 @@
<template>
<view class="">
<view class="u-sticky-wrap" :class="[elClass]" :style="{
height: fixed ? height + 'px' : 'auto',
backgroundColor: bgColor
}">
<view class="u-sticky" :style="{
position: fixed ? 'fixed' : 'static',
top: stickyTop + 'px',
left: left + 'px',
width: width == 'auto' ? 'auto' : width + 'px',
zIndex: uZIndex
}">
<slot></slot>
</view>
</view>
</view>
</template>
<script>
/**
* sticky 吸顶
* @description 该组件与CSS中position: sticky属性实现的效果一致当组件达到预设的到顶部距离时 就会固定在指定位置组件位置大于预设的顶部距离时会重新按照正常的布局排列
* @tutorial https://www.uviewui.com/components/sticky.html
* @property {String Number} offset-top 吸顶时与顶部的距离单位rpx默认0
* @property {String Number} index 自定义标识用于区分是哪一个组件
* @property {Boolean} enable 是否开启吸顶功能默认true
* @property {String} bg-color 组件背景颜色默认#ffffff
* @property {String Number} z-index 吸顶时的z-index值默认970
* @property {String Number} h5-nav-height 导航栏高度自定义导航栏时(无导航栏时需设置为0)需要传入此值单位px默认44
* @event {Function} fixed 组件吸顶时触发
* @example <u-sticky offset-top="200"><view>塞下秋来风景异衡阳雁去无留意</view></u-sticky>
*/
export default {
name: "u-sticky",
props: {
// H5NavigationBar44px
offsetTop: {
type: [Number, String],
default: 0
},
//
index: {
type: [Number, String],
default: ''
},
//
enable: {
type: Boolean,
default: true
},
// h5
h5NavHeight: {
type: [Number, String],
default: 44
},
//
bgColor: {
type: String,
default: '#ffffff'
},
// z-index
zIndex: {
type: [Number, String],
default: ''
}
},
data() {
return {
fixed: false,
height: 'auto',
stickyTop: 0,
elClass: this.$u.guid(),
left: 0,
width: 'auto',
};
},
watch: {
offsetTop(val) {
this.initObserver();
},
enable(val) {
if (val == false) {
this.fixed = false;
this.disconnectObserver('contentObserver');
} else {
this.initObserver();
}
}
},
computed: {
uZIndex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.sticky;
}
},
mounted() {
this.initObserver();
},
methods: {
initObserver() {
if (!this.enable) return;
// #ifdef H5
this.stickyTop = this.offsetTop != 0 ? uni.upx2px(this.offsetTop) + this.h5NavHeight : this.h5NavHeight;
// #endif
// #ifndef H5
this.stickyTop = this.offsetTop != 0 ? uni.upx2px(this.offsetTop) : 0;
// #endif
this.disconnectObserver('contentObserver');
this.$uGetRect('.' + this.elClass).then((res) => {
this.height = res.height;
this.left = res.left;
this.width = res.width;
this.$nextTick(() => {
this.observeContent();
});
});
},
observeContent() {
this.disconnectObserver('contentObserver');
const contentObserver = this.createIntersectionObserver({
thresholds: [0.95, 0.98, 1]
});
contentObserver.relativeToViewport({
top: -this.stickyTop
});
contentObserver.observe('.' + this.elClass, res => {
if (!this.enable) return;
this.setFixed(res.boundingClientRect.top);
});
this.contentObserver = contentObserver;
},
setFixed(top) {
const fixed = top < this.stickyTop;
this.fixed = fixed;
if (fixed) this.$emit('fixed', this.index);
},
disconnectObserver(observerName) {
const observer = this[observerName];
observer && observer.disconnect();
},
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-sticky {
z-index: 9999999999;
}
</style>

356
node_modules/uview-ui/components/u-subsection/u-subsection.vue

@ -0,0 +1,356 @@
<template>
<view class="u-subsection" :style="[subsectionStyle]">
<view class="u-item u-line-1" :style="[itemStyle(index)]" @tap="click(index)" :class="[noBorderRight(index), 'u-item-' + index]"
v-for="(item, index) in listInfo" :key="index">
<view :style="[textStyle(index)]" class="u-item-text u-line-1">{{ item.name }}</view>
</view>
<view class="u-item-bg" :style="[itemBarStyle]"></view>
</view>
</template>
<script>
/**
* subsection 分段器
* @description 该分段器一般用于用户从几个选项中选择某一个的场景
* @tutorial https://www.uviewui.com/components/subsection.html
* @property {Array} list 选项的数组形式见上方"基本使用"
* @property {String Number} current 初始化时默认选中的选项索引值默认0
* @property {String} active-color 激活时的颜色mode为subsection时固定为白色默认#303133
* @property {String} inactive-color 未激活时字体的颜色mode为subsection时无效默认#606266
* @property {String} mode 模式选择见官网"模式选择"说明默认button
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {String Number} height 组件高度单位rpx默认70
* @property {Boolean} animation 是否开启动画效果见上方说明默认true
* @property {Boolean} bold 激活选项的字体是否加粗默认true
* @property {String} bg-color 组件背景颜色mode为button时有效默认#eeeeef
* @property {String} button-color 按钮背景颜色mode为button时有效默认#ffffff
* @event {Function} change 分段器选项发生改变时触发
* @example <u-subsection active-color="#ff9900"></u-subsection>
*/
export default {
name: "u-subsection",
props: {
// tab
list: {
type: Array,
default () {
return [];
}
},
// tabindex
current: {
type: [Number, String],
default: 0
},
//
activeColor: {
type: String,
default: '#303133'
},
//
inactiveColor: {
type: String,
default: '#606266'
},
// mode=buttonmode=subsection
mode: {
type: String,
default: 'button'
},
// rpx
fontSize: {
type: [Number, String],
default: 28
},
//
animation: {
type: Boolean,
default: true
},
// rpx
height: {
type: [Number, String],
default: 70
},
// tab
bold: {
type: Boolean,
default: true
},
// mode=button
bgColor: {
type: String,
default: '#eeeeef'
},
// mode = button
buttonColor: {
type: String,
default: '#ffffff'
},
//
vibrateShort: {
type: Boolean,
default: false
}
},
data() {
return {
listInfo: [],
itemBgStyle: {
width: 0,
left: 0,
backgroundColor: '#ffffff',
height: '100%',
transition: ''
},
currentIndex: this.current,
buttonPadding: 3, // mode = button
borderRadius: 5, //
firstTimeVibrateShort: true // current
};
},
watch: {
current: {
immediate: true,
handler(nVal) {
this.currentIndex = nVal;
this.changeSectionStatus(nVal);
}
}
},
created() {
// listlistInfopropslist
// ['', ''],[{name: ''}, {name: ''}]
this.listInfo = this.list.map((val, index) => {
if (typeof val != 'object') {
let obj = {
width: 0,
name: val
};
return obj;
} else {
val.width = 0;
return val;
}
});
},
computed: {
// mode=subsection
noBorderRight() {
return index => {
if (this.mode != 'subsection') return;
let classs = '';
//
if (index < this.list.length - 1) classs += ' u-none-border-right';
//
if (index == 0) classs += ' u-item-first';
if (index == this.list.length - 1) classs += ' u-item-last';
return classs;
};
},
//
textStyle() {
return index => {
let style = {};
//
if (this.mode == 'subsection') {
if (index == this.currentIndex) {
style.color = '#ffffff';
} else {
style.color = this.activeColor;
}
} else {
if (index == this.currentIndex) {
style.color = this.activeColor;
} else {
style.color = this.inactiveColor;
}
}
//
if (index == this.currentIndex && this.bold) style.fontWeight = 'bold';
//
style.fontSize = this.fontSize + 'rpx';
return style;
};
},
// item
itemStyle() {
return index => {
let style = {};
if (this.mode == 'subsection') {
// border
style.borderColor = this.activeColor;
style.borderWidth = '1px';
style.borderStyle = 'solid';
}
return style;
};
},
// mode=buttonview
subsectionStyle() {
let style = {};
style.height = uni.upx2px(this.height) + 'px';
if (this.mode == 'button') {
style.backgroundColor = this.bgColor;
style.padding = `${this.buttonPadding}px`;
style.borderRadius = `${this.borderRadius}px`;
}
return style;
},
//
itemBarStyle() {
let style = {};
style.backgroundColor = this.activeColor;
style.zIndex = 1;
if (this.mode == 'button') {
style.backgroundColor = this.buttonColor;
style.borderRadius = `${this.borderRadius}px`;
style.bottom = `${this.buttonPadding}px`;
style.height = uni.upx2px(this.height) - this.buttonPadding * 2 + 'px';
style.zIndex = 0;
}
return Object.assign(this.itemBgStyle, style);
}
},
mounted() {
setTimeout(() => {
this.getTabsInfo();
}, 10);
},
methods: {
//
changeSectionStatus(nVal) {
if (this.mode == 'subsection') {
//
if (nVal == this.list.length - 1) {
this.itemBgStyle.borderRadius = `0 ${this.buttonPadding}px ${this.buttonPadding}px 0`;
}
if (nVal == 0) {
this.itemBgStyle.borderRadius = `${this.buttonPadding}px 0 0 ${this.buttonPadding}px`;
}
if (nVal > 0 && nVal < this.list.length - 1) {
this.itemBgStyle.borderRadius = '0';
}
}
//
setTimeout(() => {
this.itemBgLeft();
}, 10);
if (this.vibrateShort && !this.firstTimeVibrateShort) {
// 使APP(HX 2.6.8)H5
// #ifndef H5
uni.vibrateShort();
// #endif
}
// firstTimeVibrateShortfalse()
this.firstTimeVibrateShort = false;
},
click(index) {
//
if (index == this.currentIndex) return;
this.currentIndex = index;
this.changeSectionStatus(index);
this.$emit('change', Number(index));
},
// tab
getTabsInfo() {
let view = uni.createSelectorQuery().in(this);
for (let i = 0; i < this.list.length; i++) {
view.select('.u-item-' + i).boundingClientRect();
}
view.exec(res => {
if (!res.length) {
setTimeout(() => {
this.getTabsInfo();
return;
}, 10);
}
// itemlistInfo
res.map((val, index) => {
this.listInfo[index].width = val.width;
});
//
if (this.mode == 'subsection') {
this.itemBgStyle.width = this.listInfo[0].width + 'px';
} else if (this.mode == 'button') {
this.itemBgStyle.width = this.listInfo[0].width + 'px';
}
//
this.itemBgLeft();
});
},
itemBgLeft() {
//
if (this.animation) {
this.itemBgStyle.transition = 'all 0.35s';
} else {
this.itemBgStyle.transition = 'all 0s';
}
let left = 0;
// item
this.listInfo.map((val, index) => {
if (index < this.currentIndex) left += val.width;
});
// mode
if (this.mode == 'subsection') {
this.itemBgStyle.left = left + 'px';
} else if (this.mode == 'button') {
this.itemBgStyle.left = left + this.buttonPadding + 'px';
}
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-subsection {
display: flex;
align-items: center;
overflow: hidden;
position: relative;
}
.u-item {
flex: 1;
text-align: center;
font-size: 26rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: $u-main-color;
display: inline-flex;
padding: 0 6rpx;
}
.u-item-bg {
background-color: $u-type-primary;
position: absolute;
z-index: -1;
}
.u-none-border-right {
border-right: none !important;
}
.u-item-first {
border-top-left-radius: 8rpx;
border-bottom-left-radius: 8rpx;
}
.u-item-last {
border-top-right-radius: 8rpx;
border-bottom-right-radius: 8rpx;
}
.u-item-text {
transition: all 0.35s;
color: $u-main-color;
display: flex;
align-items: center;
position: relative;
z-index: 3;
}
</style>

253
node_modules/uview-ui/components/u-swipe-action/u-swipe-action.vue

@ -0,0 +1,253 @@
<template>
<movable-area class="u-swipe-action" :style="{ backgroundColor: bgColor }">
<movable-view
class="u-swipe-view"
@change="change"
@touchend="touchend"
@touchstart="touchstart"
direction="horizontal"
:disabled="disabled"
:x="moveX"
:style="{
width: movableViewWidth ? movableViewWidth : '100%'
}"
>
<view
class="u-swipe-content"
@tap.stop="contentClick"
>
<slot></slot>
</view>
<view class="u-swipe-del" v-if="showBtn" @tap.stop="btnClick(index)" :style="[btnStyle(item.style)]" v-for="(item, index) in options" :key="index">
<view class="u-btn-text">{{ item.text }}</view>
</view>
</movable-view>
</movable-area>
</template>
<script>
/**
* swipeAction 左滑单元格
* @description 该组件一般用于左滑唤出操作菜单的场景用的最多的是左滑删除操作
* @tutorial https://www.uviewui.com/components/swipeAction.html
* @property {String} bg-color 整个组件背景颜色默认#ffffff
* @property {Array} options 数组形式可以配置背景颜色和文字
* @property {String Number} index 标识符点击时候用于区分点击了哪一个用v-for循环时的index即可
* @property {String Number} btn-width 按钮宽度单位rpx默认180
* @property {Boolean} disabled 是否禁止某个swipeAction滑动默认false
* @property {Boolean} show 打开或者关闭某个组件默认false
* @event {Function} click 点击组件时触发
* @event {Function} close 组件触发关闭状态时
* @event {Function} content-click 点击内容时触发
* @event {Function} open 组件触发打开状态时
* @example <u-swipe-action btn-text="收藏">...</u-swipe-action>
*/
export default {
name: 'u-swipe-action',
props: {
// index
index: {
type: [Number, String],
default: ''
},
// rpx
btnWidth: {
type: [String, Number],
default: 180
},
// action
disabled: {
type: Boolean,
default: false
},
//
show: {
type: Boolean,
default: false
},
//
bgColor: {
type: String,
default: '#ffffff'
},
// 使iOS(2020-05-06)
vibrateShort: {
type: Boolean,
default: false
},
//
options: {
type: Array,
default() {
return [];
}
}
},
watch: {
show: {
immediate: true,
handler(nVal, oVal) {
if (nVal) {
this.open();
} else {
this.close();
}
}
}
},
data() {
return {
moveX: 0, // movable-viewx
scrollX: 0, // movable-viewchangex
status: false, //
movableAreaWidth: 0, //
elId: this.$u.guid(), // id
showBtn: false, //
};
},
computed: {
movableViewWidth() {
return this.movableAreaWidth + this.allBtnWidth + 'px';
},
innerBtnWidth() {
return uni.upx2px(this.btnWidth);
},
allBtnWidth() {
return uni.upx2px(this.btnWidth) * this.options.length;
},
btnStyle() {
return style => {
let css = {};
style.width = this.btnWidth + 'rpx';
return style;
};
}
},
mounted() {
this.getActionRect();
},
methods: {
//
btnClick(index) {
this.status = false;
// this.indexindex(options)
this.$emit('click', this.index, index);
},
// movable-view
change(e) {
this.scrollX = e.detail.x;
},
//
close() {
this.moveX = 0;
this.status = false;
},
//
open() {
if (this.disabled) return;
this.moveX = -this.allBtnWidth;
this.status = true;
},
// movable-view
touchend() {
this.moveX = this.scrollX;
//
//
// this.moveX
// propsmovable-view
// https://uniapp.dcloud.io/use?id=%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98
this.$nextTick(function() {
if (this.status == false) {
// x
if (this.scrollX <= -this.allBtnWidth / 4) {
this.moveX = -this.allBtnWidth; // movable-view
this.status = true; //
this.emitOpenEvent();
//
if (this.vibrateShort) uni.vibrateShort();
} else {
this.moveX = 0; //
this.status = false;
this.emitCloseEvent();
}
} else {
// X()
if (this.scrollX > (-this.allBtnWidth * 3) / 4) {
this.moveX = 0;
this.$nextTick(() => {
this.moveX = 101;
});
this.status = false;
this.emitCloseEvent();
} else {
this.moveX = -this.allBtnWidth;
this.status = true;
this.emitOpenEvent();
}
}
});
},
emitOpenEvent() {
this.$emit('open', this.index);
},
emitCloseEvent() {
this.$emit('close', this.index);
},
//
touchstart() {},
getActionRect() {
this.$uGetRect('.u-swipe-action').then(res => {
this.movableAreaWidth = res.width;
// ""
this.$nextTick(() => {
this.showBtn = true;
})
});
},
//
contentClick() {
//
if (this.status == true) {
this.status = 'close';
this.moveX = 0;
}
this.$emit('content-click', this.index);
}
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-swipe-action {
width: auto;
height: initial;
position: relative;
overflow: hidden;
}
.u-swipe-view {
display: flex;
height: initial;
position: relative;
/* 这一句很关键,覆盖默认的绝对定位 */
}
.u-swipe-content {
flex: 1;
}
.u-swipe-del {
position: relative;
font-size: 30rpx;
color: #ffffff;
}
.u-btn-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>

317
node_modules/uview-ui/components/u-swiper/u-swiper.vue

@ -0,0 +1,317 @@
<template>
<view class="u-swiper-wrap" :style="{
borderRadius: `${borderRadius}rpx`
}">
<swiper @change="change" @animationfinish="animationfinish" :interval="interval" :circular="circular" :duration="duration" :autoplay="autoplay"
:previous-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'" :next-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'"
:style="{
height: height + 'rpx'
}">
<swiper-item class="u-swiper-item" v-for="(item, index) in list" :key="index">
<view class="u-list-image-wrap" @tap.stop.prevent="listClick(index)" :class="[current != index ? 'u-list-scale' : '']" :style="{
borderRadius: `${borderRadius}rpx`,
transform: effect3d && current != index ? 'scaleY(0.9)' : 'scaleY(1)',
margin: effect3d && current != index ? '0 20rpx' : 0,
backgroundColor: bgColor
}">
<image class="u-swiper-image" :src="item[name]" :mode="imgMode"></image>
<view v-if="title" class="u-swiper-title u-line-1" :style="{
'padding-bottom': titlePaddingBottom
}">
{{ item.title }}
</view>
</view>
</swiper-item>
</swiper>
<view class="u-swiper-indicator" :style="{
top: indicatorPos == 'topLeft' || indicatorPos == 'topCenter' || indicatorPos == 'topRight' ? '12rpx' : 'auto',
bottom: indicatorPos == 'bottomLeft' || indicatorPos == 'bottomCenter' || indicatorPos == 'bottomRight' ? '12rpx' : 'auto',
justifyContent: justifyContent,
padding: `0 ${effect3d ? '74rpx' : '24rpx'}`
}">
<block v-if="mode == 'rect'">
<view class="u-indicator-item-rect" :class="{ 'u-indicator-item-rect-active': index == current }" v-for="(item, index) in list"
:key="index"></view>
</block>
<block v-if="mode == 'dot'">
<view class="u-indicator-item-dot" :class="{ 'u-indicator-item-dot-active': index == current }" v-for="(item, index) in list"
:key="index"></view>
</block>
<block v-if="mode == 'round'">
<view class="u-indicator-item-round" :class="{ 'u-indicator-item-round-active': index == current }" v-for="(item, index) in list"
:key="index"></view>
</block>
<block v-if="mode == 'number'">
<view class="u-indicator-item-number">{{ current + 1 }}/{{ list.length }}</view>
</block>
</view>
</view>
</template>
<script>
/**
* swiper 轮播图
* @description 该组件一般用于导航轮播广告展示等场景,可开箱即用
* @tutorial https://www.uviewui.com/components/swiper.html
* @property {Array} list 轮播图数据见官网"基本使用"说明
* @property {Boolean} title 是否显示标题文字需要配合list参数见官网说明默认false
* @property {String} mode 指示器模式见官网说明默认round
* @property {String Number} height 轮播图组件高度单位rpx默认250
* @property {String} indicator-pos 指示器的位置默认bottomCenter
* @property {Boolean} effect3d 是否开启3D效果默认false
* @property {Boolean} autoplay 是否自动播放默认true
* @property {String Number} interval 自动轮播时间间隔单位ms默认2500
* @property {Boolean} circular 是否衔接播放见官网说明默认true
* @property {String} bg-color 背景颜色默认#f3f4f6
* @property {String Number} border-radius 轮播图圆角值单位rpx默认8
* @property {Object} title-style 自定义标题样式
* @property {String Number} effect3d-previous-margin mode = true模式的情况下激活项与前后项之间的距离单位rpx默认50
* @property {String} img-mode 图片的裁剪模式详见image组件裁剪模式默认aspectFill
* @event {Function} click 点击轮播图时触发
* @example <u-swiper :list="list" mode="dot" indicator-pos="bottomRight"></u-swiper>
*/
export default {
name: "u-swiper",
props: {
// ,[{image: 'xxxx', title: 'xxxx'}{image: 'yyyy', title: 'yyyy'}]title
list: {
type: Array,
default () {
return [];
}
},
// title
title: {
type: Boolean,
default: false
},
//
indicator: {
type: Object,
default () {
return {};
}
},
//
borderRadius: {
type: [Number, String],
default: 8
},
//
interval: {
type: [String, Number],
default: 3000
},
// rect|dot|number|round
mode: {
type: String,
default: 'round'
},
// listrpx
height: {
type: [Number, String],
default: 250
},
// topLeft|topCenter|topRight|bottomLeft|bottomCenter|bottomRight
indicatorPos: {
type: String,
default: 'bottomCenter'
},
//
effect3d: {
type: Boolean,
default: false
},
// 3Ditemitemrpx
effect3dPreviousMargin: {
type: [Number, String],
default: 50
},
//
autoplay: {
type: Boolean,
default: true
},
// ms
duration: {
type: [Number, String],
default: 500
},
//
circular: {
type: Boolean,
default: true
},
//
imgMode: {
type: String,
default: 'aspectFill'
},
// list
name: {
type: String,
default: 'image'
},
//
bgColor: {
type: String,
default: '#f3f4f6'
}
},
watch: {
// listcurrent
list(nVal, oVal) {
if(nVal.length !== oVal.length) this.current = 0;
}
},
data() {
return {
current: 0 // swiper-itemindex
};
},
computed: {
justifyContent() {
if (this.indicatorPos == 'topLeft' || this.indicatorPos == 'bottomLeft') return 'flex-start';
if (this.indicatorPos == 'topCenter' || this.indicatorPos == 'bottomCenter') return 'center';
if (this.indicatorPos == 'topRight' || this.indicatorPos == 'bottomRight') return 'flex-end';
},
titlePaddingBottom() {
let tmp = 0;
if (this.mode == 'none') return '12rpx';
if (['bottomLeft', 'bottomCenter', 'bottomRight'].indexOf(this.indicatorPos) >= 0 && this.mode == 'number') {
tmp = '60rpx';
} else if (['bottomLeft', 'bottomCenter', 'bottomRight'].indexOf(this.indicatorPos) >= 0 && this.mode != 'number') {
tmp = '40rpx';
} else {
tmp = '12rpx';
}
return tmp;
}
},
methods: {
listClick(index) {
this.$emit('click', index);
},
change(e) {
let current = e.detail.current;
this.current = current;
// changeindex0
this.$emit('change', current);
},
// animationfinishchange
// swipercurrent
animationfinish(e) {
// #ifndef MP-TOUTIAO
// this.current = e.detail.current;
// #endif
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-swiper-wrap {
position: relative;
overflow: hidden;
transform: translateY(0);
}
.u-swiper-image {
width: 100%;
will-change: transform;
height: 100%;
display: block;
/* #ifdef H5 */
pointer-events: none;
/* #endif */
}
.u-swiper-indicator {
padding: 0 24rpx;
position: absolute;
display: flex;
width: 100%;
z-index: 1;
}
.u-indicator-item-rect {
width: 26rpx;
height: 8rpx;
margin: 0 6rpx;
transition: all 0.5s;
background-color: rgba(0, 0, 0, 0.3);
}
.u-indicator-item-rect-active {
background-color: rgba(255, 255, 255, 0.8);
}
.u-indicator-item-dot {
width: 14rpx;
height: 14rpx;
margin: 0 6rpx;
border-radius: 20rpx;
transition: all 0.5s;
background-color: rgba(0, 0, 0, 0.3);
}
.u-indicator-item-dot-active {
background-color: rgba(255, 255, 255, 0.8);
}
.u-indicator-item-round {
width: 14rpx;
height: 14rpx;
margin: 0 6rpx;
border-radius: 20rpx;
transition: all 0.5s;
background-color: rgba(0, 0, 0, 0.3);
}
.u-indicator-item-round-active {
width: 34rpx;
background-color: rgba(255, 255, 255, 0.8);
}
.u-indicator-item-number {
padding: 6rpx 16rpx;
line-height: 1;
background-color: rgba(0, 0, 0, 0.3);
border-radius: 100rpx;
font-size: 26rpx;
color: rgba(255, 255, 255, 0.8);
}
.u-list-scale {
transform-origin: center center;
}
.u-list-image-wrap {
width: 100%;
height: 100%;
flex: 1;
transition: all 0.5s;
overflow: hidden;
box-sizing: content-box;
position: relative;
}
.u-swiper-title {
position: absolute;
background-color: rgba(0, 0, 0, 0.3);
bottom: 0;
left: 0;
width: 100%;
font-size: 28rpx;
padding: 12rpx 24rpx;
color: rgba(255, 255, 255, 0.9);
}
.u-swiper-item {
display: flex;
overflow: hidden;
align-items: center;
}
</style>

160
node_modules/uview-ui/components/u-switch/u-switch.vue

@ -0,0 +1,160 @@
<template>
<view class="u-switch" :class="[value == true ? 'u-switch--on' : '', disabled ? 'u-switch--disabled' : '']" @tap="onClick"
:style="[switchStyle]">
<view class="u-switch__node node-class">
<u-loading :show="loading" class="u-switch__loading" :size="size * 0.6" :color="loadingColor" />
</view>
</view>
</template>
<script>
/**
* switch 开关选择器
* @description 选择开关一般用于只有两个选择且只能选其一的场景
* @tutorial https://www.uviewui.com/components/switch.html
* @property {Boolean} loading 是否处于加载中默认false
* @property {Boolean} disabled 是否禁用默认false
* @property {String Number} size 开关尺寸单位rpx默认50
* @property {String} active-color 打开时的背景色默认#2979ff
* @property {Boolean} inactive-color 关闭时的背景色默认#ffffff
* @property {Boolean | Number | String} active-value 打开选择器时通过change事件发出的值默认true
* @property {Boolean | Number | String} inactive-value 关闭选择器时通过change事件发出的值默认false
* @event {Function} change 在switch打开或关闭时触发
* @example <u-switch v-model="checked" active-color="red" inactive-color="#eee"></u-switch>
*/
export default {
name: "u-switch",
props: {
//
loading: {
type: Boolean,
default: false
},
//
disabled: {
type: Boolean,
default: false
},
// rpx
size: {
type: [Number, String],
default: 50
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#ffffff'
},
// v-model
value: {
type: Boolean,
default: false
},
// 使iOS(2020-05-06)
vibrateShort: {
type: Boolean,
default: false
},
//
activeValue: {
type: [Number, String, Boolean],
default: true
},
//
inactiveValue: {
type: [Number, String, Boolean],
default: false
},
},
data() {
return {
}
},
computed: {
switchStyle() {
let style = {};
style.fontSize = this.size + 'rpx';
style.backgroundColor = this.value ? this.activeColor : this.inactiveColor;
return style;
},
loadingColor() {
return this.value ? this.activeColor : null;
}
},
methods: {
onClick() {
if (!this.disabled && !this.loading) {
// 使APP(HX 2.6.8)H5
if(this.vibrateShort) uni.vibrateShort();
this.$emit('input', !this.value);
// value
this.$nextTick(() => {
this.$emit('change', this.value ? this.activeValue : this.inactiveValue);
})
}
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-switch {
position: relative;
display: inline-block;
box-sizing: initial;
width: 2em;
height: 1em;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 1em;
transition: background-color 0.3s;
font-size: 50rpx;
}
.u-switch__node {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
border-radius: 100%;
z-index: 1;
width: 1em;
height: 1em;
background-color: #fff;
background-color: #fff;
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);
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);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05), -webkit-transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05)
}
.u-switch__loading {
display: flex;
align-items: center;
justify-content: center;
}
.u-switch--on {
background-color: #1989fa;
}
.u-switch--on .u-switch__node {
transform: translateX(1em);
}
.u-switch--disabled {
opacity: 0.4;
}
</style>

246
node_modules/uview-ui/components/u-tabbar/u-tabbar.vue

@ -0,0 +1,246 @@
<template>
<view v-if="show" class="u-tabbar" @touchmove.stop.prevent>
<view class="u-tabbar__content safe-area-inset-bottom" :style="{
height: $u.addUnit(height),
backgroundColor: bgColor,
}" :class="{
'u-border-top': borderTop
}">
<view class="u-tabbar__content__item" v-for="(item, index) in list" :key="index" :class="{
'u-tabbar__content__circle': midButton &&item.midButton
}" @tap.stop="clickHandler(index)" :style="{
backgroundColor: bgColor
}">
<view :class="[
midButton && item.midButton ? 'u-tabbar__content__circle__button' : 'u-tabbar__content__item__button'
]">
<u-icon
:size="midButton && item.midButton ? midButtonSize : iconSize"
:name="index == value ? item.selectedIconPath : item.iconPath"
:color="index == value ? activeColor : inactiveColor"
:custom-prefix="item.customIcon ? 'custom-icon' : 'uicon'"
></u-icon>
<u-badge :count="item.count" :is-dot="item.isDot"
v-if="item.count > 0"
:offset="[-2, getOffsetRight(item.count, item.isDot)]"
></u-badge>
</view>
<view class="u-tabbar__content__item__text" :style="{
color: index == value ? activeColor : inactiveColor
}">
<text class="u-line-1">{{item.text}}</text>
</view>
</view>
<view v-if="midButton" class="u-tabbar__content__circle__border" :class="{
'u-border': borderTop,
}" :style="{
backgroundColor: bgColor
}">
</view>
</view>
<!-- 这里加上一个48rpx的高度,是为了增高有凸起按钮时的防塌陷高度(也即按钮凸出来部分的高度) -->
<view class="u-fixed-placeholder safe-area-inset-bottom" :style="{
height: `calc(${$u.addUnit(height)} + ${midButton ? 48 : 0}rpx)`,
}"></view>
</view>
</template>
<script>
export default {
props: {
//
show: {
type: Boolean,
default: true
},
// v-modelcurrent
value: {
type: [String, Number],
default: 0
},
// tabbar
bgColor: {
type: String,
default: '#ffffff'
},
// tabbar50pxrpx
height: {
type: [String, Number],
default: '50px'
},
// rpx
iconSize: {
type: [String, Number],
default: 40
},
// rpx
midButtonSize: {
type: [String, Number],
default: 90
},
//
activeColor: {
type: String,
default: '#303133'
},
//
inactiveColor: {
type: String,
default: '#606266'
},
//
midButton: {
type: Boolean,
default: false
},
//
list: {
type: Array,
default () {
return []
}
},
//
beforeSwitch: {
type: Function,
default: null
},
// 线
borderTop: {
type: Boolean,
default: true
},
},
data() {
return {
}
},
methods: {
async clickHandler(index) {
if(this.beforeSwitch && typeof(this.beforeSwitch) === 'function') {
//
let beforeSwitch = this.beforeSwitch(index);
// promise
if (!!beforeSwitch && typeof beforeSwitch.then === 'function') {
await beforeSwitch.then(res => {
// promise
this.switchTab(index);
}).catch(err => {
})
} else if(beforeSwitch === true) {
// true
this.switchTab(index);
}
} else {
this.switchTab(index);
}
},
// tab
switchTab(index) {
// v-model
this.$emit('change', index);
this.$emit('input', index);
},
// right
getOffsetRight(count, isDot) {
// count9()right
if(isDot) {
return -20;
} else if(count > 9) {
return -40;
} else {
return -30;
}
}
}
}
</script>
<style scoped lang="scss">
.u-fixed-placeholder {
box-sizing: content-box;
}
.u-tabbar {
&__content {
display: flex;
align-items: center;
position: relative;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 998;
box-sizing: content-box;
&__circle__border {
border-radius: 100%;
width: 110rpx;
height: 110rpx;
top: -48rpx;
left: 50%;
transform: translateX(-50%);
position: absolute;
z-index: 4;
background-color: #ffffff;
&:after {
border-radius: 100px;
}
}
&__item {
flex: 1;
justify-content: center;
height: 100%;
padding: 12rpx 0;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
&__button {
position: absolute;
top: 10rpx;
}
&__text {
color: $u-content-color;
font-size: 26rpx;
line-height: 28rpx;
position: absolute;
bottom: 12rpx;
left: 50%;
transform: translateX(-50%);
}
}
&__circle {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
z-index: 10;
height: calc(100% - 1px);
&__button {
width: 90rpx;
height: 90rpx;
border-radius: 100%;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
background-color: #ffffff;
top: -40rpx;
left: 50%;
z-index: 6;
transform: translateX(-50%);
}
}
}
}
</style>

96
node_modules/uview-ui/components/u-table/u-table.vue

@ -0,0 +1,96 @@
<template>
<view class="u-table" :style="[tableStyle]">
<slot />
</view>
</template>
<script>
/**
* table 表格
* @description 表格组件一般用于展示大量结构化数据的场景
* @tutorial https://www.uviewui.com/components/table.html
* @property {String} border-color 表格边框的颜色默认#e4e7ed
* @property {String} bg-color 表格的背景颜色默认#ffffff
* @property {String} align 单元格的内容对齐方式作用类似css的text-align默认center
* @property {String} padding 单元格的内边距同css的padding写法默认10rpx 0
* @property {String Number} font-size 单元格字体大小单位rpx默认28
* @property {String} color 单元格字体颜色默认#606266
* @property {Object} th-style th单元格的样式对象形式(将th所需参数放在table组件是为了避免每一个th组件要写一遍
* @event {Function} click 点击组件时触发
* @event {Function} close 点击关闭按钮时触发
* @example <u-table></u-table>
*/
export default {
name: "u-table",
props: {
borderColor: {
type: String,
default: '#e4e7ed'
},
align: {
type: String,
default: 'center'
},
// td
padding: {
type: String,
default: '10rpx 6rpx'
},
//
fontSize: {
type: [String, Number],
default: 28
},
//
color: {
type: String,
default: '#606266'
},
// th
thStyle: {
type: Object,
default () {
return {}
}
},
// table
bgColor: {
type: String,
default: '#ffffff'
}
},
provide() {
return {
uTable: this,
uTd: this
};
},
data() {
return {}
},
computed: {
tableStyle() {
let style = {};
style.borderLeft = `solid 1px ${this.borderColor}`;
style.borderTop = `solid 1px ${this.borderColor}`;
style.backgroundColor = this.bgColor;;
return style;
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-table {
width: 100%;
box-sizing: border-box;
}
/* #ifdef MP */
.u-table /deep/ t-tr {
display: flex;
}
/* #endif */
</style>

475
node_modules/uview-ui/components/u-tabs-swiper/u-tabs-swiper.vue

@ -0,0 +1,475 @@
<template>
<view class="u-tabs" :style="{
zIndex: zIndex,
background: bgColor
}">
<scroll-view scroll-x class="u-scroll-view" :scroll-left="scrollLeft" scroll-with-animation :style="{ zIndex: zIndex + 1 }">
<view class="u-tabs-scroll-box" :class="{'u-tabs-scorll-flex': !isScroll}">
<view class="u-tabs-item" :style="[tabItemStyle(index)]"
v-for="(item, index) in getTabs" :key="index" :class="[preId + index]" @tap="emit(index)">
{{ item[name] || item['name']}}
</view>
<view v-if="showBar" class="u-scroll-bar" :style="[tabBarStyle]"></view>
</view>
</scroll-view>
</view>
</template>
<script>
import colorGradient from '../../libs/function/colorGradient';
let color = colorGradient;
const {
windowWidth
} = uni.getSystemInfoSync();
const preId = 'UEl_';
/**
* tabsSwiper 全屏选项卡
* @description 该组件内部实现主要依托于uniapp的scroll-view和swiper组件主要特色是切换过程中tabsSwiper文字的颜色可以渐变底部滑块可以 跟随式滑动活动tab滚动居中等应用场景可以用于需要左右切换页面比如商城的订单中心(待收货-待付款-待评价-已退货)等应用场景
* @tutorial https://www.uviewui.com/components/tabsSwiper.html
* @property {Boolean} is-scroll tabs是否可以左右拖动默认true
* @property {Array} list 标签数组元素为对象[{name: '推荐'}]
* @property {String Number} current 指定哪个tab为激活状态默认0
* @property {String Number} height 导航栏的高度单位rpx默认80
* @property {String Number} font-size tab文字大小单位rpx默认30
* @property {String Number} swiper-width tabs组件外部swiper的宽度默认为屏幕宽度单位rpx默认750
* @property {String} active-color 滑块和激活tab文字的颜色默认#2979ff
* @property {String} inactive-color tabs文字颜色默认#303133
* @property {String Number} bar-width 滑块宽度单位rpx默认40
* @property {String Number} bar-height 滑块高度单位rpx默认6
* @property {Object} bar-style 底部滑块的样式对象形式
* @property {Object} active-item-style 活动tabs item的样式对象形式
* @property {Boolean} show-bar 是否显示底部的滑块默认true
* @property {String Number} gutter 单个tab标签的左右内边距之和单位rpx默认40
* @property {String} bg-color tabs导航栏的背景颜色默认#ffffff
* @property {String} name 组件内部读取的list参数中的属性名见官网说明默认name
* @property {Boolean} bold 激活选项的字体是否加粗默认true
* @event {Function} change 点击标签时触发
* @example <u-tabs-swiper ref="tabs" :list="list" :is-scroll="false"></u-tabs-swiper>
*/
export default {
name: "u-tabs-swiper",
props: {
// 23使flextab
isScroll: {
type: Boolean,
default: true
},
//
list: {
type: Array,
default () {
return [];
}
},
// tab
current: {
type: [Number, String],
default: 0
},
// rpx
height: {
type: [Number, String],
default: 80
},
// rpx
fontSize: {
type: [Number, String],
default: 30
},
// , s
// duration: {
// type: [Number, String],
// default: 0.5
// },
swiperWidth: {
//line3, swiper, rpx
type: [String, Number],
default: 750
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#303133'
},
// barrpx
barWidth: {
type: [Number, String],
default: 40
},
// bar
barHeight: {
type: [Number, String],
default: 6
},
// tabrpx
gutter: {
type: [Number, String],
default: 40
},
// z-index
zIndex: {
type: [Number, String],
default: 1
},
//
bgColor: {
type: String,
default: '#ffffff'
},
//
autoCenterMode: {
type: String,
default: 'window'
},
//
name: {
type: String,
default: 'name'
},
// tab
bold: {
type: Boolean,
default: true
},
// tab item
activeItemStyle: {
type: Object,
default() {
return {}
}
},
//
showBar: {
type: Boolean,
default: true
},
//
barStyle: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
scrollLeft: 0, // scroll-view
tabQueryInfo: [], // tab
windowWidth: 0, // px
//scrollBarLeft: 0, // bartranslateX()
animationFinishCurrent: this.current,
componentsWidth: 0,
line3AddDx: 0,
line3Dx: 0,
preId,
sW: 0,
tabsInfo: [],
colorGradientArr: [],
colorStep: 100 //
};
},
computed: {
// current
getCurrent() {
const current = Number(this.current);
//
if (current > this.getTabs.length - 1) {
return this.getTabs.length - 1;
}
if (current < 0) return 0;
return current;
},
getTabs() {
return this.list;
},
//
scrollBarLeft() {
return Number(this.line3Dx) + Number(this.line3AddDx);
},
// px
barWidthPx() {
return uni.upx2px(this.barWidth);
},
// tab
tabItemStyle() {
return (index) => {
let style = {
height: this.height + 'rpx',
lineHeight: this.height + 'rpx',
padding: `0 ${this.gutter / 2}rpx`,
color: this.tabsInfo.length > 0 ? (this.tabsInfo[index] ? this.tabsInfo[index].color : this.activeColor) : this.inactiveColor,
fontSize: this.fontSize + 'rpx',
zIndex: this.zIndex + 2,
fontWeight: (index == this.getCurrent && this.bold) ? 'bold' : 'normal'
};
if(index == this.getCurrent) {
// tab item
style = Object.assign(style, this.activeItemStyle);
}
return style;
}
},
//
tabBarStyle() {
let style = {
width: this.barWidthPx + 'px',
height: this.barHeight + 'rpx',
borderRadius: '100px',
backgroundColor: this.activeColor,
left: this.scrollBarLeft + 'px'
};
return Object.assign(style, this.barStyle);
}
},
watch: {
current(n, o) {
this.change(n);
this.setFinishCurrent(n);
},
list() {
this.$nextTick(() => {
this.init();
})
}
},
mounted() {
this.init();
},
methods: {
async init() {
this.countPx();
await this.getTabsInfo();
this.countLine3Dx();
this.getQuery(() => {
this.setScrollViewToCenter();
});
//
this.colorGradientArr = color.colorGradient(this.inactiveColor, this.activeColor, this.colorStep);
},
// tab
getTabsInfo() {
return new Promise((resolve, reject) => {
let view = uni.createSelectorQuery().in(this);
for (let i = 0; i < this.list.length; i++) {
view.select('.' + preId + i).boundingClientRect();
}
view.exec(res => {
const arr = [];
for (let i = 0; i < res.length; i++) {
// tab
res[i].color = this.inactiveColor;
// tabactiveColor
if (i == this.getCurrent) res[i].color = this.activeColor;
arr.push(res[i]);
}
this.tabsInfo = arr;
resolve();
});
})
},
// swiper
countLine3Dx() {
const tab = this.tabsInfo[this.animationFinishCurrent];
// tab
if (tab) this.line3Dx = tab.left + tab.width / 2 - this.barWidthPx / 2 - this.tabsInfo[0].left;
},
countPx() {
// swiperrpxpxdxpx
this.sW = uni.upx2px(Number(this.swiperWidth));
},
emit(index) {
this.$emit('change', index);
},
change() {
this.setScrollViewToCenter();
},
getQuery(cb) {
try {
let view = uni.createSelectorQuery().in(this).select('.u-tabs');
view.fields({
size: true
},
data => {
if (data) {
this.componentsWidth = data.width;
if (cb && typeof cb === 'function') cb(data);
} else {
this.getQuery(cb);
}
}
).exec();
} catch (e) {
this.componentsWidth = windowWidth;
}
},
// tab
setScrollViewToCenter() {
let tab;
tab = this.tabsInfo[this.animationFinishCurrent];
if (tab) {
let tabCenter = tab.left + tab.width / 2;
let fatherWidth;
// tabtab
if (this.autoCenterMode === 'window') {
fatherWidth = windowWidth;
} else {
fatherWidth = this.componentsWidth;
}
this.scrollLeft = tabCenter - fatherWidth / 2;
}
},
setDx(dx) {
let nextTabIndex = dx > 0 ? this.animationFinishCurrent + 1 : this.animationFinishCurrent - 1;
//
nextTabIndex = nextTabIndex <= 0 ? 0 : nextTabIndex;
nextTabIndex = nextTabIndex >= this.list.length ? this.list.length - 1 : nextTabIndex;
const tab = this.tabsInfo[nextTabIndex];
// tabx
let nowTab = this.tabsInfo[this.animationFinishCurrent];
let nowTabX = nowTab.left + nowTab.width / 2;
// tab
let nextTab = this.tabsInfo[nextTabIndex];
let nextTabX = nextTab.left + nextTab.width / 2;
// tabtabtab
let distanceX = Math.abs(nextTabX - nowTabX);
this.line3AddDx = (dx / this.sW) * distanceX;
this.setTabColor(this.animationFinishCurrent, nextTabIndex, dx);
},
// tab
setTabColor(nowTabIndex, nextTabIndex, dx) {
let colorIndex = Math.abs(Math.ceil((dx / this.sW) * 100));
let colorLength = this.colorGradientArr.length;
//
colorIndex = colorIndex >= colorLength ? colorLength - 1 : colorIndex <= 0 ? 0 : colorIndex;
// tab
this.tabsInfo[nextTabIndex].color = this.colorGradientArr[colorIndex];
// tab
this.tabsInfo[nowTabIndex].color = this.colorGradientArr[colorLength - 1 - colorIndex];
},
// swiper
setFinishCurrent(current) {
// tabtab
if (current != this.animationFinishCurrent) {
this.tabsInfo.map((val, index) => {
if (current == index) val.color = this.activeColor;
else val.color = this.inactiveColor;
return val;
});
}
this.line3AddDx = 0;
this.animationFinishCurrent = current;
this.countLine3Dx();
}
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
view,
scroll-view {
box-sizing: border-box;
}
.u-tabs {
width: 100%;
transition-property: background-color, color;
}
::-webkit-scrollbar,
::-webkit-scrollbar,
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
/* #ifdef H5 */
// 穿H5scroll-view
scroll-view /deep/ ::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
/* #endif */
.u-scroll-view {
width: 100%;
white-space: nowrap;
position: relative;
}
.u-tabs-scroll-box {
position: relative;
}
.u-tabs-scorll-flex {
display: flex;
justify-content: space-between;
}
.u-tabs-scorll-flex .u-tabs-item {
flex: 1;
}
.u-tabs-item {
position: relative;
display: inline-block;
text-align: center;
transition-property: background-color, color, font-weight;
}
.content {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.boxStyle {
pointer-events: none;
position: absolute;
transition-property: all;
}
.boxStyle2 {
pointer-events: none;
position: absolute;
bottom: 0;
transition-property: all;
transform: translateY(-100%);
}
.itemBackgroundBox {
pointer-events: none;
position: absolute;
top: 0;
transition-property: left, background-color;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.itemBackground {
height: 100%;
width: 100%;
transition-property: all;
}
.u-scroll-bar {
position: absolute;
bottom: 4rpx;
}
</style>

337
node_modules/uview-ui/components/u-tabs/u-tabs.vue

@ -0,0 +1,337 @@
<template>
<view class="u-tabs" :id="id" :style="{
background: bgColor
}">
<scroll-view scroll-x class="u-scroll-view" :scroll-left="scrollLeft" scroll-with-animation>
<view class="u-scroll-box" :class="{'u-tabs-scorll-flex': !isScroll}">
<view class="u-tab-item" :id="'u-tab-item-' + index" v-for="(item, index) in list" :key="index" @tap="clickTab(index)"
:style="[tabItemStyle(index)]">
{{ item[name] || item['name']}}
</view>
<view v-if="showBar" class="u-tab-bar" :style="[tabBarStyle]"></view>
</view>
</scroll-view>
</view>
</template>
<script>
/**
* tabs 标签
* @description 该组件是一个tabs标签组件在标签多的时候可以配置为左右滑动标签少的时候可以禁止滑动 该组件的一个特点是配置为滚动模式时激活的tab会自动移动到组件的中间位置
* @tutorial https://www.uviewui.com/components/tabs.html
* @property {Boolean} is-scroll tabs是否可以左右拖动默认true
* @property {Array} list 标签数组元素为对象[{name: '推荐'}]
* @property {String Number} current 指定哪个tab为激活状态默认0
* @property {String Number} height 导航栏的高度单位rpx默认80
* @property {String Number} font-size tab文字大小单位rpx默认30
* @property {String Number} duration 滑块移动一次所需的时间单位秒默认0.5
* @property {String} active-color 滑块和激活tab文字的颜色默认#2979ff
* @property {String} inactive-color tabs文字颜色默认#303133
* @property {String Number} bar-width 滑块宽度单位rpx默认40
* @property {Object} active-item-style 活动tabs item的样式对象形式
* @property {Object} bar-style 底部滑块的样式对象形式
* @property {Boolean} show-bar 是否显示底部的滑块默认true
* @property {String Number} bar-height 滑块高度单位rpx默认6
* @property {String Number} gutter 单个tab标签的左右内边距之和单位rpx默认40
* @property {String} bg-color tabs导航栏的背景颜色默认#ffffff
* @property {String} name 组件内部读取的list参数中的属性名见官网说明默认name
* @property {Boolean} bold 激活选项的字体是否加粗默认true
* @event {Function} change 点击标签时触发
* @example <u-tabs ref="tabs" :list="list" :is-scroll="false"></u-tabs>
*/
export default {
name: "u-tabs",
props: {
// 23使flextab
isScroll: {
type: Boolean,
default: true
},
//
list: {
type: Array,
default () {
return [];
}
},
// tab
current: {
type: [Number, String],
default: 0
},
//
height: {
type: [String, Number],
default: 80
},
//
fontSize: {
type: [String, Number],
default: 30
},
// , ms
duration: {
type: [String, Number],
default: 0.5
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#303133'
},
// barrpx
barWidth: {
type: [String, Number],
default: 40
},
// bar
barHeight: {
type: [String, Number],
default: 6
},
// tab
gutter: {
type: [String, Number],
default: 30
},
//
bgColor: {
type: String,
default: '#ffffff'
},
//
name: {
type: String,
default: 'name'
},
// tab
bold: {
type: Boolean,
default: true
},
// tab item
activeItemStyle: {
type: Object,
default() {
return {}
}
},
//
showBar: {
type: Boolean,
default: true
},
//
barStyle: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
scrollLeft: 0, // scroll-view
tabQueryInfo: [], // tab
componentWidth: 0, // px
scrollBarLeft: 0, // bartranslateX()
parentLeft: 0, // (tabs)
id: this.$u.guid(), // id
currentIndex: this.current,
barFirstTimeMove: true, // ()
};
},
watch: {
// tabtab使
// applist
list(n, o) {
// list
if(n.length !== o.length) this.currentIndex = 0;
// $nextTicktabtab
this.$nextTick(() => {
this.init();
});
},
current: {
immediate: true,
handler(nVal, oVal) {
//
this.$nextTick(() => {
this.currentIndex = nVal;
this.scrollByIndex();
});
}
},
},
computed: {
// bar
tabBarStyle() {
let style = {
width: this.barWidth + 'rpx',
transform: `translate(${this.scrollBarLeft}px, -100%)`,
//
'transition-duration': `${this.barFirstTimeMove ? 0 : this.duration }s`,
'background-color': this.activeColor,
height: this.barHeight + 'rpx',
//
'border-radius': `${this.barHeight / 2}px`
};
Object.assign(style, this.barStyle);
return style;
},
// tab
tabItemStyle() {
return (index) => {
let style = {
height: this.height + 'rpx',
'line-height': this.height + 'rpx',
'font-size': this.fontSize + 'rpx',
'transition-duration': `${this.duration}s`,
padding: this.isScroll ? `0 ${this.gutter}rpx` : '',
flex: this.isScroll ? 'auto' : '1'
};
//
if (index == this.currentIndex && this.bold) style.fontWeight = 'bold';
if (index == this.currentIndex) {
style.color = this.activeColor;
// tab item
style = Object.assign(style, this.activeItemStyle);
} else {
style.color = this.inactiveColor;
}
return style;
}
}
},
methods: {
// init便
async init() {
// tabs
let tabRect = await this.$uGetRect('#' + this.id);
// tabs
this.parentLeft = tabRect.left;
// tabs
this.componentWidth = tabRect.width;
this.getTabRect();
},
// tab
clickTab(index) {
// tab
if(index == this.currentIndex) return ;
//
this.$emit('change', index);
},
// tab
getTabRect() {
//
let query = uni.createSelectorQuery().in(this);
// tab使exec()
for (let i = 0; i < this.list.length; i++) {
// sizerect
query.select(`#u-tab-item-${i}`).fields({
size: true,
rect: true
});
}
//
query.exec(
function(res) {
this.tabQueryInfo = res;
// bar
this.scrollByIndex();
}.bind(this)
);
},
// scroll-viewtab
scrollByIndex() {
// tabtabwidthleft()
let tabInfo = this.tabQueryInfo[this.currentIndex];
if (!tabInfo) return;
// tab
let tabWidth = tabInfo.width;
// itemtabsitemlefttabsleft
let offsetLeft = tabInfo.left - this.parentLeft;
// tabs-itemscroll-view
let scrollLeft = offsetLeft - (this.componentWidth - tabWidth) / 2;
this.scrollLeft = scrollLeft < 0 ? 0 : scrollLeft;
// item
let left = tabInfo.left + tabInfo.width / 2 - this.parentLeft;
// item
this.scrollBarLeft = left - uni.upx2px(this.barWidth) / 2;
// barFirstTimeMovetruefalse
// scrollBarLeftcomputed
if(this.barFirstTimeMove == true) {
setTimeout(() => {
this.barFirstTimeMove = false;
}, 100)
}
}
},
mounted() {
this.init();
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
view,
scroll-view {
box-sizing: border-box;
}
::-webkit-scrollbar,
::-webkit-scrollbar,
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
.u-scroll-box {
position: relative;
}
/* #ifdef H5 */
// 穿H5scroll-view
scroll-view /deep/ ::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
/* #endif */
.u-scroll-view {
width: 100%;
white-space: nowrap;
position: relative;
}
.u-tab-item {
position: relative;
display: inline-block;
text-align: center;
transition-property: background-color, color;
}
.u-tab-bar {
position: absolute;
bottom: 0;
}
.u-tabs-scorll-flex {
display: flex;
justify-content: space-between;
}
</style>

292
node_modules/uview-ui/components/u-tag/u-tag.vue

@ -0,0 +1,292 @@
<template>
<view v-if="show" :class="[
disabled ? 'u-disabled' : '',
'u-size-' + size,
'u-shape-' + shape,
'u-mode-' + mode + '-' + type
]"
class="u-tag" :style="[customStyle]" @tap="clickTag">
{{text}}
<view class="u-icon-wrap" @tap.stop>
<u-icon @click="close" size="22" v-if="closeable" :color="closeIconColor"
name="close" class="u-close-icon" :style="[iconStyle]"></u-icon>
</view>
</view>
</template>
<script>
/**
* tag 提示
* @description 该组件一般用于标记和选择
* @tutorial https://www.uviewui.com/components/tag.html
* @property {String} type 主题类型默认primary
* @property {String} size 标签大小默认default
* @property {String} shape 标签形状默认square
* @property {String} text 标签的文字内容
* @property {String} bg-color 自定义标签的背景颜色
* @property {String} border-color 标签的边框颜色
* @property {String} close-color 关闭按钮的颜色
* @property {String Number} index 点击标签时会通过click事件返回该值
* @property {String} mode 模式选择见官网说明默认light
* @property {Boolean} closeable 是否可关闭设置为true文字右边会出现一个关闭图标默认false
* @property {Boolean} show 标签显示与否默认true
* @event {Function} click 点击标签触发
* @event {Function} close closeable为true时点击标签关闭按钮触发
* @example <u-tag text="雪月夜" type="success" />
*/
export default {
name: 'u-tag',
//
props: {
// infoprimarysuccesswarningerror
type: {
type: String,
default: 'primary'
},
disabled: {
type: [Boolean, String],
default: false
},
// defaultmini
size: {
type: String,
default: 'default'
},
// tagcircle, squarecircleLeftcircleRight
shape: {
type: String,
default: 'square'
},
//
text: {
type: [String, Number],
default: ''
},
//
bgColor: {
type: String,
default: ''
},
//
color: {
type: String,
default: ''
},
//
borderColor: {
type: String,
default: ''
},
//
closeColor: {
type: String,
default: ''
},
//
index: {
type: [Number, String],
default: ''
},
// dark|light|plain
mode: {
type: String,
default: 'light'
},
//
closeable: {
type: Boolean,
default: false
},
//
show: {
type: Boolean,
default: true
}
},
data() {
return {
}
},
computed: {
customStyle() {
let style = {};
// type
if(this.color) style.color = this.color+"!important";
// tagtype
if(this.bgColor) style.backgroundColor = this.bgColor+"!important";
// tagborderColor使color
if(this.mode == 'plain' && this.color && !this.borderColor) style.borderColor = this.color;
else style.borderColor = this.borderColor;
return style;
},
iconStyle() {
if(!this.closeable) return ;
let style = {};
if(this.size == 'mini') style.fontSize = '20rpx';
else style.fontSize = '22rpx';
if(this.mode == 'plain' || this.mode == 'light') style.color = this.type;
else if(this.mode == 'dark') style.color = "#ffffff";
if(this.closeColor) style.color = this.closeColor;
return style;
},
//
closeIconColor() {
//
// dark
// type
let color = '';
if(this.closeColor) return this.closeColor;
else if(this.color) return this.color;
else if(this.mode == 'dark') return '#ffffff';
else return this.type;
}
},
methods: {
//
clickTag() {
// disabled
if(this.disabled) return ;
this.$emit('click', this.index);
},
//
close() {
this.$emit('close', this.index);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-tag {
box-sizing: border-box;
align-items: center;
border-radius: 6rpx;
display: inline-block;
line-height: 1;
}
.u-size-default {
font-size: 22rpx;
padding: 12rpx 22rpx;
}
.u-size-mini {
font-size: 20rpx;
padding: 6rpx 12rpx;
}
.u-mode-light-primary {
background-color: $u-type-primary-light;
color: $u-type-primary;
border: 1px solid $u-type-primary-disabled;
}
.u-mode-light-success {
background-color: $u-type-success-light;
color: $u-type-success;
border: 1px solid $u-type-success-disabled;
}
.u-mode-light-error {
background-color: $u-type-error-light;
color: $u-type-error;
border: 1px solid $u-type-error-disabled;
}
.u-mode-light-warning {
background-color: $u-type-warning-light;
color: $u-type-warning;
border: 1px solid $u-type-warning-disabled;
}
.u-mode-light-info {
background-color: $u-type-info-light;
color: $u-type-info;
border: 1px solid $u-type-info-disabled;
}
.u-mode-dark-primary {
background-color: $u-type-primary;
color: #FFFFFF;
}
.u-mode-dark-success {
background-color: $u-type-success;
color: #FFFFFF;
}
.u-mode-dark-error {
background-color: $u-type-error;
color: #FFFFFF;
}
.u-mode-dark-warning {
background-color: $u-type-warning;
color: #FFFFFF;
}
.u-mode-dark-info {
background-color: $u-type-info;
color: #FFFFFF;
}
.u-mode-plain-primary {
background-color: #FFFFFF;
color: $u-type-primary;
border: 1px solid $u-type-primary;
}
.u-mode-plain-success {
background-color: #FFFFFF;
color: $u-type-success;
border: 1px solid $u-type-success;
}
.u-mode-plain-error {
background-color: #FFFFFF;
color: $u-type-error;
border: 1px solid $u-type-error;
}
.u-mode-plain-warning {
background-color: #FFFFFF;
color: $u-type-warning;
border: 1px solid $u-type-warning;
}
.u-mode-plain-info {
background-color: #FFFFFF;
color: $u-type-info;
border: 1px solid $u-type-info;
}
.u-disabled {
opacity: 0.55;
}
.u-shape-circle {
border-radius: 100rpx;
}
.u-shape-circleRight {
border-radius: 0 100rpx 100rpx 0;
}
.u-shape-circleLeft {
border-radius: 100rpx 0 0 100rpx;
}
.u-close-icon {
margin-left: 14rpx;
font-size: 22rpx;
color: $u-type-success;
}
.u-icon-wrap {
display: inline-flex;
transform: scale(0.86);
}
</style>

115
node_modules/uview-ui/components/u-td/u-td.vue

@ -0,0 +1,115 @@
<template>
<view class="u-td" :style="[tdStyle]">
<slot></slot>
</view>
</template>
<script>
/**
* td td单元格
* @description 表格组件一般用于展示大量结构化数据的场景搭配u-table使用
* @tutorial https://www.uviewui.com/components/table.html#td-props
* @property {String Number} width 单元格宽度百分比或者具体带单位的值如30% 200rpx等一般使用百分比单元格宽度默认为均分tr的长度默认auto
* @example <u-td>二年级</u-td>
*/
export default {
name: "u-td",
props: {
// 30% 200rpx使
width: {
type: [Number, String],
default: 'auto'
}
},
data() {
return {
tr: []
};
},
inject: ['uTable', 'uTr'],
provide() {
return {
uTd: this
}
},
created() {
},
computed: {
tdStyle() {
let style = {};
if (this.width != "auto") style.flex = `0 0 ${this.width}`;
style.textAlign = this.uTable.align;
style.padding = this.tr.length == 0 ? this.uTable.padding : 0;
style.borderBottom = this.tr.length == 0 ? `solid 1px ${this.uTable.borderColor}` : 0;
style.borderRight = this.tr.length == 0 ? `solid 1px ${this.uTable.borderColor}` : 0;
style.fontSize = this.uTable.fontSize + 'rpx';
style.color = this.uTable.color;
return style;
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-td {
display: flex;
flex-direction: column;
flex: 1;
justify-content: center;
font-size: 28rpx;
color: $u-content-color;
align-self: stretch;
box-sizing: border-box;
}
.u-col-1 {
flex: 0 0 calc(100%/12);
}
.u-col-2 {
flex: 0 0 calc(100%/12 * 2);
}
.u-col-3 {
flex: 0 0 calc(100%/12 * 3);
}
.u-col-4 {
flex: 0 0 calc(100%/12 * 4);
}
.u-col-5 {
flex: 0 0 calc(100%/12 * 5);
}
.u-col-6 {
flex: 0 0 calc(100%/12 * 6);
}
.u-col-7 {
flex: 0 0 calc(100%/12 * 7);
}
.u-col-8 {
flex: 0 0 calc(100%/12 * 8);
}
.u-col-9 {
flex: 0 0 calc(100%/12 * 9);
}
.u-col-10 {
flex: 0 0 calc(100%/12 * 10);
}
.u-col-11 {
flex: 0 0 calc(100%/12 * 11);
}
.u-col-12 {
flex: 0 0 calc(100%/12 * 12);
}
</style>

58
node_modules/uview-ui/components/u-th/u-th.vue

@ -0,0 +1,58 @@
<template>
<view class="u-th" :style="[thStyle]">
<slot></slot>
</view>
</template>
<script>
/**
* th th单元格
* @description 表格组件一般用于展示大量结构化数据的场景搭配u-table使用
* @tutorial https://www.uviewui.com/components/table.html#td-props
* @property {String Number} width 标题单元格宽度百分比或者具体带单位的值如30%200rpx等一般使用百分比单元格宽度默认为均分tr的长度
* @example 暂无示例
*/
export default {
name: "u-th",
props: {
// 30% 200rpx使
width: {
type: [Number, String],
default: ''
}
},
data() {
return {
};
},
inject: ['uTable'],
computed: {
thStyle() {
let style = {};
if (this.width) style.flex = `0 0 ${this.width}`;
style.textAlign = this.uTable.align;
style.padding = this.uTable.padding;
style.borderBottom = `solid 1px ${this.uTable.borderColor}`;
style.borderRight = `solid 1px ${this.uTable.borderColor}`;
Object.assign(style, this.uTable.thStyle);
return style;
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-th {
display: flex;
flex-direction: column;
flex: 1;
justify-content: center;
font-size: 28rpx;
color: $u-main-color;
font-weight: bold;
background-color: rgb(245, 246, 248);
}
</style>

83
node_modules/uview-ui/components/u-time-line-item/u-time-line-item.vue

@ -0,0 +1,83 @@
<template>
<view class="u-time-axis-item">
<slot name="content" />
<view class="u-time-axis-node" :style="[nodeStyle]">
<slot name="node">
<view class="u-dot">
</view>
</slot>
</view>
</view>
</template>
<script>
/**
* timeLineItem 时间轴Item
* @description 时间轴组件一般用于物流信息展示各种跟时间相关的记录等场景(搭配u-time-line使用)
* @tutorial https://www.uviewui.com/components/timeLine.html
* @property {String} bg-color 左边节点的背景颜色一般通过slot内容自定义背景颜色即可默认#ffffff
* @property {String Number} node-top 节点左边图标绝对定位的top值单位rpx
* @example <u-time-line-item node-top="2">...</u-time-line-item>
*/
export default {
name: "u-time-line-item",
props: {
//
bgColor: {
type: String,
default: "#ffffff"
},
// top
nodeTop: {
type: [String, Number],
default: ""
}
},
data() {
return {
}
},
computed: {
nodeStyle() {
let style = {
backgroundColor: this.bgColor,
};
if (this.nodeTop != "") style.top = this.nodeTop + 'rpx';
return style;
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-time-axis-item {
display: flex;
flex-direction: column;
width: 100%;
position: relative;
margin-bottom: 32rpx;
}
.u-time-axis-node {
position: absolute;
top: 12rpx;
left: -40rpx;
transform-origin: 0;
transform: translateX(-50%);
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
font-size: 24rpx;
}
.u-dot {
height: 16rpx;
width: 16rpx;
border-radius: 100rpx;
background: #ddd;
}
</style>

43
node_modules/uview-ui/components/u-time-line/u-time-line.vue

@ -0,0 +1,43 @@
<template>
<view class="u-time-axis">
<slot />
</view>
</template>
<script>
/**
* timeLine 时间轴
* @description 时间轴组件一般用于物流信息展示各种跟时间相关的记录等场景
* @tutorial https://www.uviewui.com/components/timeLine.html
* @example <u-time-line></u-time-line>
*/
export default {
name: "u-time-line",
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-time-axis {
padding-left: 40rpx;
position: relative;
}
.u-time-axis::before {
content: " ";
position: absolute;
left: 0;
top: 12rpx;
width: 1px;
bottom: 0;
border-left: 1px solid #ddd;
transform-origin: 0 0;
transform: scaleX(0.5);
}
</style>

222
node_modules/uview-ui/components/u-toast/u-toast.vue

@ -0,0 +1,222 @@
<template>
<view class="u-toast" :class="[isShow ? 'u-show' : '', 'u-type-' + config.type, 'u-position-' + config.position]" :style="{
zIndex: uZIndex
}">
<view class="u-icon-wrap">
<u-icon v-if="config.icon" class="u-icon" :name="iconName" :size="30" :color="config.type"></u-icon>
</view>
<text class="u-text">{{config.title}}</text>
</view>
</template>
<script>
/**
* toast 消息提示
* @description 此组件表现形式类似uni的uni.showToastAPI但也有不同的地方
* @tutorial https://www.uviewui.com/components/toast.html
* @property {String} z-index toast展示时的z-index值
* @event {Function} show 显示toast如需一进入页面就显示toast请在onReady生命周期调用
* @example <u-toast ref="uToast" />
*/
export default {
name: "u-toast",
props: {
// z-index
zIndex: {
type: [Number, String],
default: ''
},
},
data() {
return {
isShow: false,
timer: null, //
config: {
params: {}, // URL
title: '', //
type: '', // primarysuccesserrorwarningblack
duration: 2000, //
isTab: false, // tab
url: '', // toastback
icon: true, //
position: 'center', // toast
callback: null, //
back: false, // toast
}
};
},
computed: {
iconName() {
// nonetypeerror|warning|succes|info
if (['error', 'warning', 'success', 'info'].indexOf(this.config.type) >= 0 && this.config.icon) {
let icon = this.$u.type2icon(this.config.type);
return icon;
}
},
uZIndex() {
// toastz-index使
return this.isShow ? (this.zIndex ? this.zIndex : this.$u.zIndex.toast) : '999999';
}
},
methods: {
// toastthis.$refs.xxx.show(options)
show(options) {
this.config = this.$u.deepMerge(this.config, options);
if (this.timer) {
//
clearTimeout(this.timer);
this.timer = null;
}
this.isShow = true;
this.timer = setTimeout(() => {
// toast
this.isShow = false;
clearTimeout(this.timer);
this.timer = null;
// callback
typeof(this.config.callback) === 'function' && this.config.callback();
this.timeEnd();
}, this.config.duration);
},
// toastthis.$refs.xxx.hide()
hide() {
this.isShow = false;
if (this.timer) {
//
clearTimeout(this.timer);
this.timer = null;
}
},
//
timeEnd() {
// urlisTabtruefalse
if (this.config.url) {
// url"/"uni"/"
if (this.config.url[0] != '/') this.config.url = '/' + this.config.url;
//
if (Object.keys(this.config.params).length) {
// url
// 使"/","?","="/page/index/index?name=mary"
// params"?"
let query = '';
if (/.*\/.*\?.*=.*/.test(this.config.url)) {
// objectget
query = this.$u.queryParams(this.config.params, false);
this.config.url = this.config.url + "&" + query;
} else {
query = this.$u.queryParams(this.config.params);
this.config.url += query;
}
}
// tab使uni.switchTab
if (this.config.isTab) {
uni.switchTab({
url: this.config.url
});
} else {
uni.navigateTo({
url: this.config.url
});
}
} else if(this.config.back) {
// 退
this.$u.route({
type: 'back'
})
}
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-toast {
position: fixed;
z-index: -1;
transition: opacity 0.3s;
text-align: center;
color: #fff;
border-radius: 8rpx;
background: #585858;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
opacity: 0;
pointer-events: none;
padding:0 40rpx;
}
.u-toast.u-show {
opacity: 1;
}
.u-text {
word-break: keep-all;
white-space: nowrap;
line-height: normal;
}
.u-icon {
margin-right: 10rpx;
display: flex;
align-items: center;
line-height: normal;
}
.u-position-center {
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
}
.u-position-top {
left: 50%;
top: 20%;
transform: translateX(-50%) translateY(-50%);
}
.u-position-bottom {
left: 50%;
bottom: 20%;
transform: translateX(-50%) translateY(-50%);
}
.u-type-primary {
color: $u-type-primary;
background-color: $u-type-primary-light;
border: 1px solid rgb(215, 234, 254);
}
.u-type-success {
color: $u-type-success;
background-color: $u-type-success-light;
border: 1px solid #BEF5C8;
}
.u-type-error {
color: $u-type-error;
background-color: $u-type-error-light;
border: 1px solid #fde2e2;
}
.u-type-warning {
color: $u-type-warning;
background-color: $u-type-warning-light;
border: 1px solid #faecd8;
}
.u-type-info {
color: $u-type-info;
background-color: $u-type-info-light;
border: 1px solid #ebeef5;
}
.u-type-default {
color: #fff;
background-color: #585858;
}
</style>

121
node_modules/uview-ui/components/u-top-tips/u-top-tips.vue

@ -0,0 +1,121 @@
<template>
<view class="u-tips" :class="['u-' + type, isShow ? 'u-tip-show' : '']" :style="{
top: navbarHeight + 'px',
zIndex: uZIndex
}">{{ title }}</view>
</template>
<script>
/**
* topTips 顶部提示
* @description 该组件一般用于页面顶部向下滑出一个提示尔后自动收起的场景
* @tutorial https://www.uviewui.com/components/topTips.html
* @property {String Number} navbar-height 导航栏高度(包含状态栏高度在内)单位PX
* @property {String Number} z-index z-index值默认975
* @example <u-top-tips ref="uTips"></u-top-tips>
*/
export default {
name: "u-top-tips",
props: {
//
navbarHeight: {
type: [Number, String],
// #ifndef H5
default: 0,
// #endif
// #ifdef H5
default: 44,
// #endif
},
// z-index
zIndex: {
type: [Number, String],
default: ''
}
},
data() {
return {
timer: null, //
isShow: false, //
title: '', //
type: 'primary', // primarysuccesserrorwarninginfo
duration: 2000, //
};
},
computed: {
uZIndex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.topTips;
}
},
methods: {
show(config = {}) {
//
clearTimeout(this.timer);
// (type)
if (config.duration) this.duration = config.duration;
if (config.type) this.type = config.type;
this.title = config.title;
this.isShow = true;
//
this.timer = setTimeout(() => {
this.isShow = false;
clearTimeout(this.timer);
this.timer = null;
}, this.duration);
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
view {
box-sizing: border-box;
}
//
.u-tips {
width: 100%;
position: fixed;
z-index: 1;
padding: 20rpx 30rpx;
color: #FFFFFF;
font-size: 28rpx;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
// translateY(-100%)Y(h5)(app)
transform: translateY(-100%);
transition: all 0.35s linear;
}
.u-tip-show {
transform: translateY(0);
opacity: 1;
z-index: 99;
}
.u-primary {
background: $u-type-primary;
}
.u-success {
background: $u-type-success;
}
.u-warning {
background: $u-type-warning;
}
.u-error {
background: $u-type-error;
}
.u-info {
background: $u-type-info;
}
</style>

36
node_modules/uview-ui/components/u-tr/u-tr.vue

@ -0,0 +1,36 @@
<template>
<view class="u-tr">
<slot></slot>
</view>
</template>
<script>
/**
* tr 表格行标签
* @description 表格组件一般用于展示大量结构化数据的场景搭配<u-table>使用
* @tutorial https://www.uviewui.com/components/table.html
* @example <u-tr></u-tr>
*/
export default {
name: "u-tr",
inject: ['uTable', 'uTd'],
provide() {
return {
uTr: this,
};
},
created() {
if (this.uTd && this.uTd.tr) {
this.uTd.tr.push(this);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-tr {
display: flex;
}
</style>

580
node_modules/uview-ui/components/u-upload/u-upload.vue

@ -0,0 +1,580 @@
<template>
<view class="u-upload" v-if="!disabled">
<view
v-if="showUploadList"
class="u-list-item u-preview-wrap"
v-for="(item, index) in lists"
:key="index"
:style="{
width: width + 'rpx',
height: width + 'rpx'
}"
>
<view
v-if="deletable"
class="u-delete-icon"
@tap.stop="deleteItem(index)"
:style="{
background: delBgColor
}"
>
<u-icon class="u-icon" :name="delIcon" size="20" :color="delColor"></u-icon>
</view>
<u-line-progress
v-if="showProgress && item.progress > 0 && !item.error"
:show-percent="false"
height="16"
class="u-progress"
:percent="item.progress"
></u-line-progress>
<view @tap.stop="retry(index)" v-if="item.error" class="u-error-btn">点击重试</view>
<image @tap.stop="doPreviewImage(item.url || item.path, index)" class="u-preview-image" v-if="!item.isImage" :src="item.url || item.path" :mode="imageMode"></image>
</view>
<slot name="file" :file="lists"></slot>
<view style="display: inline-block;" @tap="selectFile" v-if="maxCount > lists.length">
<slot name="addBtn"></slot>
<view
v-if="!customBtn"
class="u-list-item u-add-wrap"
hover-class="u-add-wrap__hover"
hover-stay-time="150"
:style="{
width: width + 'rpx',
height: width + 'rpx'
}"
>
<u-icon name="plus" class="u-add-btn" size="40"></u-icon>
<view class="u-add-tips">{{ uploadText }}</view>
</view>
</view>
</view>
</template>
<script>
/**
* upload 图片上传
* @description 该组件用于上传图片场景
* @tutorial https://www.uviewui.com/components/upload.html
* @property {String} action 服务器上传地址
* @property {String Number} max-count 最大选择图片的数量默认99
* @property {Boolean} custom-btn 如果需要自定义选择图片的按钮设置为true默认false
* @property {Boolean} show-progress 是否显示进度条默认true
* @property {Boolean} disabled 是否启用(显示/移仓)组件默认false
* @property {String} image-mode 预览图片等显示模式可选值为uni的image的mode属性值默认aspectFill
* @property {String} del-icon 右上角删除图标名称只能为uView内置图标
* @property {String} del-bg-color 右上角关闭按钮的背景颜色
* @property {String} del-color 右上角关闭按钮图标的颜色
* @property {Object} header 上传携带的头信息对象形式
* @property {Object} form-data 上传额外携带的参数
* @property {String} name 上传文件的字段名供后端获取使用默认file
* @property {Array<String>} size-type original 原图compressed 压缩图默认二者都有默认['original', 'compressed']
* @property {Array<String>} source-type 选择图片的来源album-从相册选图camera-使用相机默认二者都有默认['album', 'camera']
* @property {Boolean} preview-full-image 是否可以通过uni.previewImage预览已选择的图片默认true
* @property {Boolean} multiple 是否开启图片多选部分安卓机型不支持默认true
* @property {Boolean} deletable 是否显示删除图片的按钮默认true
* @property {String Number} max-size 选择单个文件的最大大小单位B(byte)默认不限制默认Number.MAX_VALUE
* @property {Array<Object>} file-list 默认显示的图片列表数组元素为对象必须提供url属性
* @property {Boolean} upload-text 选择图片按钮的提示文字默认选择图片
* @property {Boolean} auto-upload 选择完图片是否自动上传见上方说明默认true
* @property {Boolean} show-tips 特殊情况下是否自动提示toast见上方说明默认true
* @property {Boolean} show-upload-list 是否显示组件内部的图片预览默认true
* @event {Function} on-oversize 图片大小超出最大允许大小
* @event {Function} on-preview 全屏预览图片时触发
* @event {Function} on-remove 移除图片时触发
* @event {Function} on-success 图片上传成功时触发
* @event {Function} on-change 图片上传后无论成功或者失败都会触发
* @event {Function} on-error 图片上传失败时触发
* @event {Function} on-progress 图片上传过程中的进度变化过程触发
* @event {Function} on-uploaded 所有图片上传完毕触发
* @event {Function} on-choose-complete 每次选择图片后触发只是让外部可以得知每次选择后内部的文件列表
* @example <u-upload :action="action" :file-list="fileList" ></u-upload>
*/
export default {
name: 'u-upload',
props: {
//
showUploadList: {
type: Boolean,
default: true
},
//
action: {
type: String,
default: ''
},
//
maxCount: {
type: [String, Number],
default: 52
},
//
showProgress: {
type: Boolean,
default: true
},
//
disabled: {
type: Boolean,
default: false
},
// imagemode
imageMode: {
type: String,
default: 'aspectFill'
},
//
header: {
type: Object,
default() {
return {};
}
},
//
formData: {
type: Object,
default() {
return {};
}
},
//
name: {
type: String,
default: 'file'
},
// , original compressed
sizeType: {
type: Array,
default() {
return ['original', 'compressed'];
}
},
sourceType: {
type: Array,
default() {
return ['album', 'camera'];
}
},
//
previewFullImage: {
type: Boolean,
default: true
},
//
multiple: {
type: Boolean,
default: true
},
//
deletable: {
type: Boolean,
default: true
},
// byte
maxSize: {
type: [String, Number],
default: Number.MAX_VALUE
},
//
fileList: {
type: Array,
default() {
return [];
}
},
//
uploadText: {
type: String,
default: '选择图片'
},
//
autoUpload: {
type: Boolean,
default: true
},
// toast
showTips: {
type: Boolean,
default: true
},
// slot
customBtn: {
type: Boolean,
default: false
},
//
width: {
type: [String, Number],
default: 200
},
//
delBgColor: {
type: String,
default: '#fa3534'
},
//
delColor: {
type: String,
default: '#ffffff'
},
// uView
delIcon: {
type: String,
default: 'close'
},
// jsonjson
toJson: {
type: Boolean,
default: true
},
//
beforeUpload: {
type: Function,
default: null
}
},
mounted() {},
data() {
return {
lists: [],
isInCount: true,
uploading: false
};
},
watch: {
fileList: {
immediate: true,
handler(val) {
val.map(value => {
// fileList()fileList
// watchthis.lists
// sometrueeverytrue
let tmp = this.lists.some(val => {
return val.url == value.url;
})
// (tmpfalse)
!tmp && this.lists.push({ url: value.url, error: false, progress: 100 });
});
}
},
// lists
lists(n) {
this.$emit('on-list-change', n);
}
},
methods: {
//
clear() {
this.lists = [];
},
//
reUpload() {
this.uploadFile();
},
//
selectFile() {
if (this.disabled) return;
const { name = '', maxCount, multiple, maxSize, sizeType, lists, camera, compressed, maxDuration, sourceType } = this;
let chooseFile = null;
const newMaxCount = maxCount - lists.length;
// 使 chooseImage
chooseFile = new Promise((resolve, reject) => {
uni.chooseImage({
count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
sourceType: sourceType,
sizeType,
success: resolve,
fail: reject
});
});
chooseFile
.then(res => {
let file = null;
let listOldLength = this.lists.length;
res.tempFiles.map((val, index) => {
// index1
if (!multiple && index >= 1) return;
if (val.size > maxSize) {
this.$emit('on-oversize', val, this.lists);
this.showToast('超出允许的文件大小');
} else {
if (maxCount <= lists.length) {
this.$emit('on-exceed', val, this.lists);
this.showToast('超出最大允许的文件个数');
return;
}
lists.push({
url: val.path,
progress: 0,
error: false
});
}
});
//
this.$emit('on-choose-complete', this.lists);
if (this.autoUpload) this.uploadFile(listOldLength);
})
.catch(error => {
// this.$emit('on-error', error);
});
},
//
showToast(message, force = false) {
if (this.showTips || force) {
uni.showToast({
title: message,
icon: 'none'
});
}
},
// ref
upload() {
this.uploadFile();
},
//
retry(index) {
this.lists[index].progress = 0;
this.lists[index].error = false;
this.lists[index].response = null;
uni.showLoading({
title: '重新上传'
});
this.uploadFile(index);
},
//
async uploadFile(index = 0) {
if (this.disabled) return;
if (this.uploading) return;
//
if (index >= this.lists.length) {
this.$emit('on-uploaded', this.lists);
return;
}
//
if (!this.action) {
this.showToast('请配置上传地址', true);
return;
}
//
if (this.lists[index].progress == 100) {
if (this.autoUpload == false) this.uploadFile(index + 1);
return;
}
// before-upload
if(this.beforeUpload && typeof(this.beforeUpload) === 'function') {
//
let beforeResponse = this.beforeUpload(index, this.lists);
// promise
if (!!beforeResponse && typeof beforeResponse.then === 'function') {
await beforeResponse.then(res => {
// promise
}).catch(err => {
// catch
return this.uploadFile(index + 1);
})
} else if(beforeResponse === false) {
// false
return this.uploadFile(index + 1);
}
}
this.lists[index].error = false;
this.uploading = true;
//
const task = uni.uploadFile({
url: this.action,
filePath: this.lists[index].url,
name: this.name,
formData: this.formData,
header: this.header,
success: res => {
// jsonjson
let data = this.toJson && this.checkIsJSON(res.data) ? JSON.parse(res.data) : res.data;
if (![200, 201].includes(res.statusCode)) {
this.uploadError(index, data);
} else {
//
this.lists[index].response = data;
this.lists[index].progress = 100;
this.lists[index].error = false;
this.$emit('on-success', data, index, this.lists);
}
},
fail: e => {
this.uploadError(index, e);
},
complete: res => {
uni.hideLoading();
this.uploading = false;
this.uploadFile(index + 1);
this.$emit('on-change', res, index, this.lists);
}
});
task.onProgressUpdate(res => {
if (res.progress > 0) {
this.lists[index].progress = res.progress;
this.$emit('on-progress', res, index, this.lists);
}
});
},
//
uploadError(index, err) {
this.lists[index].progress = 0;
this.lists[index].error = true;
this.lists[index].response = null;
this.$emit('on-error', err, index, this.lists);
this.showToast('上传失败,请重试');
},
//
deleteItem(index) {
uni.showModal({
title: '提示',
content: '您确定要删除此项吗?',
success: res => {
if (res.confirm) {
if (this.lists[index].process < 100 && this.lists[index].process > 0) {
typeof this.lists[index].uploadTask != 'undefined' && this.lists[index].uploadTask.abort();
}
this.lists.splice(index, 1);
this.$forceUpdate();
this.$emit('on-remove', index, this.lists);
this.showToast('移除成功');
}
}
});
},
// ref
remove(index) {
//
if (index >= 0 && index < this.lists.length) {
this.lists.splice(index, 1);
this.$emit('on-list-change', this.lists);
}
},
//
doPreviewImage(url, index) {
if (!this.previewFullImage) return;
const images = this.lists.map(item => item.url || item.path);
uni.previewImage({
urls: images,
current: url,
success: () => {
this.$emit('on-preview', url, this.lists);
},
fail: () => {
uni.showToast({
title: '预览图片失败',
icon: 'none'
});
}
});
},
// json
checkIsJSON(str) {
if (typeof str == 'string') {
try {
var obj = JSON.parse(str);
if (typeof obj == 'object' && obj) {
return true;
} else {
return false;
}
} catch (e) {
return false;
}
}
return false;
}
}
};
</script>
<style lang="scss" scoped>
@import '../../libs/css/style.components.scss';
.u-upload {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.u-list-item {
width: 200rpx;
height: 200rpx;
overflow: hidden;
margin: 10rpx;
background: rgb(244, 245, 246);
position: relative;
border-radius: 10rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}
.u-preview-wrap {
border: 1px solid rgb(235, 236, 238);
}
.u-add-wrap {
flex-direction: column;
color: $u-content-color;
font-size: 28rpx;
}
.u-add-tips {
margin-top: 20rpx;
line-height: 40rpx;
}
.u-add-wrap__hover {
background-color: rgb(235, 236, 238);
}
.u-preview-image {
display: block;
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.u-delete-icon {
position: absolute;
top: 10rpx;
right: 10rpx;
z-index: 10;
background-color: $u-type-error;
border-radius: 100rpx;
width: 44rpx;
height: 44rpx;
display: flex;
align-items: center;
justify-content: center;
}
.u-icon {
display: flex;
align-items: center;
justify-content: center;
}
.u-progress {
position: absolute;
bottom: 10rpx;
left: 8rpx;
right: 8rpx;
z-index: 9;
width: auto;
}
.u-error-btn {
color: #ffffff;
background-color: $u-type-error;
font-size: 20rpx;
padding: 4px 0;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
z-index: 9;
line-height: 1;
}
</style>

164
node_modules/uview-ui/components/u-verification-code/u-verification-code.vue

@ -0,0 +1,164 @@
<template>
<view class="u-code-wrap">
<!-- 此组件功能由js完成无需写html逻辑 -->
</view>
</template>
<script>
/**
* verificationCode 验证码输入框
* @description 考虑到用户实际发送验证码的场景可能是一个按钮也可能是一段文字提示语各有不同所以本组件 不提供界面显示只提供提示语由用户将提示语嵌入到具体的场景
* @tutorial https://www.uviewui.com/components/verificationCode.html
* @property {Number String} seconds 倒计时所需的秒数默认60
* @property {String} start-text 开始前的提示语见官网说明默认获取验证码
* @property {String} change-text 倒计时期间的提示语必须带有字母"x"见官网说明默认X秒重新获取
* @property {String} end-text 倒计结束的提示语见官网说明默认重新获取
* @property {Boolean} keep-running 是否在H5刷新或各端返回再进入时继续倒计时默认false
* @event {Function} change 倒计时期间每秒触发一次
* @event {Function} start 开始倒计时触发
* @event {Function} end 结束倒计时触发
* @example <u-verification-code :seconds="seconds" @end="end" @start="start" ref="uCode"
*/
export default {
name: "u-verification-code",
props: {
//
seconds: {
type: [String, Number],
default: 60
},
//
startText: {
type: String,
default: '获取验证码'
},
//
changeText: {
type: String,
default: 'X秒重新获取'
},
//
endText: {
type: String,
default: '重新获取'
},
// H5
keepRunning: {
type: Boolean,
default: false
},
//
uniqueKey: {
type: String,
default: ''
}
},
data() {
return {
secNum: this.seconds,
timer: null,
canGetCode: true, //
}
},
mounted() {
this.checkKeepRunning();
},
watch: {
seconds: {
immediate: true,
handler(n) {
this.secNum = n;
}
}
},
methods: {
checkKeepRunning() {
// 退(H5)
let lastTimestamp = Number(uni.getStorageSync(this.uniqueKey + '_$uCountDownTimestamp'));
if(!lastTimestamp) return this.changeEvent(this.startText);
//
let nowTimestamp = Math.floor((+ new Date()) / 1000);
//
if(this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) {
//
this.secNum = lastTimestamp - nowTimestamp;
//
uni.removeStorageSync(this.uniqueKey + '_$uCountDownTimestamp');
//
this.start();
} else {
//
this.changeEvent(this.startText);
}
},
//
start() {
//
if(this.timer) {
clearInterval(this.timer);
this.timer = null;
}
this.$emit('start');
this.canGetCode = false;
// setInterval1
this.changeEvent(this.changeText.replace(/x|X/, this.secNum));
this.setTimeToStorage();
this.timer = setInterval(() => {
if (--this.secNum) {
// "x"
this.changeEvent(this.changeText.replace(/x|X/, this.secNum));
} else {
clearInterval(this.timer);
this.timer = null;
this.changeEvent(this.endText);
this.secNum = this.seconds;
this.$emit('end');
this.canGetCode = true;
}
}, 1000);
},
//
reset() {
this.canGetCode = true;
clearInterval(this.timer);
this.secNum = this.seconds;
this.changeEvent(this.endText);
},
changeEvent(text) {
this.$emit('change', text);
},
// H5
setTimeToStorage() {
if(!this.keepRunning || !this.timer) return;
//
// 0
if(this.secNum > 0 && this.secNum <= this.seconds) {
// (+ new Date())1000
let nowTimestamp = Math.floor((+ new Date()) / 1000);
// => +
uni.setStorage({
key: this.uniqueKey + '_$uCountDownTimestamp',
data: nowTimestamp + Number(this.secNum)
})
}
}
},
//
beforeDestroy() {
this.setTimeToStorage();
clearTimeout(this.timer);
this.timer = null;
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-code-wrap {
width: 0;
height: 0;
position: fixed;
z-index: -1;
}
</style>

180
node_modules/uview-ui/components/u-waterfall/u-waterfall.vue

@ -0,0 +1,180 @@
<template>
<view class="u-waterfall">
<view id="u-left-column" class="u-column"><slot name="left" :leftList="leftList"></slot></view>
<view id="u-right-column" class="u-column"><slot name="right" :rightList="rightList"></slot></view>
</view>
</template>
<script>
/**
* waterfall 瀑布流
* @description 这是一个瀑布流形式的组件内容分为左右两列结合uView的懒加载组件效果更佳相较于某些只是奇偶数左右分别或者没有利用vue作用域插槽的做法uView的瀑布流实现了真正的 组件化搭配LazyLoad 懒加载和loadMore 加载更多组件让您开箱即用眼前一亮
* @tutorial https://www.uviewui.com/components/waterfall.html
* @property {Array} flow-list 用于渲染的数据
* @property {String Number} add-time 单条数据添加到队列的时间间隔单位ms见上方注意事项说明默认200
* @example <u-waterfall :flowList="flowList"></u-waterfall>
*/
export default {
name: "u-waterfall",
props: {
value: {
//
type: Array,
required: true,
default: function() {
return [];
}
},
//
// ms
addTime: {
type: [Number, String],
default: 200
},
// ididKey{idx: 22, name: 'lisa'}
// idKeyidx
idKey: {
type: String,
default: 'id'
}
},
provide() {
return {
uWaterfall: this
}
},
data() {
return {
leftList: [],
rightList: [],
tempList: [],
children: []
}
},
watch: {
copyFlowList(nVal, oVal) {
//
let startIndex = Array.isArray(oVal) && oVal.length > 0 ? oVal.length : 0;
//
this.tempList = this.tempList.concat(this.cloneData(nVal.slice(startIndex)));
this.splitData();
}
},
mounted() {
this.tempList = this.cloneData(this.copyFlowList);
this.splitData();
},
computed: {
// flowListwatch
copyFlowList() {
return this.cloneData(this.value);
}
},
methods: {
async splitData() {
if (!this.tempList.length) return;
let leftRect = await this.$uGetRect('#u-left-column');
let rightRect = await this.$uGetRect('#u-right-column');
//
let item = this.tempList[0];
// await
// []itemundefined
if(!item) return ;
if (leftRect.height < rightRect.height) {
this.leftList.push(item);
} else if (leftRect.height > rightRect.height) {
this.rightList.push(item);
} else {
//
// 0
if (this.leftList.length <= this.rightList.length) {
this.leftList.push(item);
} else {
this.rightList.push(item);
}
}
//
this.tempList.splice(0, 1);
//
if (this.tempList.length) {
setTimeout(() => {
this.splitData();
}, this.addTime)
}
},
//
cloneData(data) {
return JSON.parse(JSON.stringify(data));
},
//
clear() {
this.leftList = [];
this.rightList = [];
//
this.$emit('input', []);
},
// id
remove(id) {
// findIndex-1
let index = -1;
index = this.leftList.findIndex(val => val[this.idKey] == id);
if(index != -1) {
// index-1idindex
this.leftList.splice(index, 1);
} else {
//
index = this.rightList.findIndex(val => val[this.idKey] == id);
if(index != -1) this.rightList.splice(index, 1);
}
// id
index = this.value.findIndex(val => val[this.idKey] == id);
if(index != -1) this.$emit('input', this.value.splice(index, 1));
},
//
modify(id, key, value) {
// findIndex-1
let index = -1;
index = this.leftList.findIndex(val => val[this.idKey] == id);
if(index != -1) {
// index-1idkey
this.leftList[key] = value;
} else {
//
index = this.rightList.findIndex(val => val[this.idKey] == id);
if(index != -1) this.leftList[key] = value;
}
// id
index = this.value.findIndex(val => val[this.idKey] == id);
if(index != -1) {
// value
let data = this.cloneData(this.value);
// keyvalue
data[index][key] = value;
// v-model
this.$emit('input', data);
}
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-waterfall {
display: flex;
flex-direction: row;
align-items: flex-start;
}
.u-column {
display: flex;
flex: 1;
flex-direction: column;
height: auto;
}
.u-image {
width: 100%;
}
</style>

883
node_modules/uview-ui/iconfont.css

File diff suppressed because one or more lines are too long

125
node_modules/uview-ui/index.js

@ -0,0 +1,125 @@
// 引入全局mixin
import mixin from './libs/mixin/mixin.js'
// 引入关于是否mixin集成小程序分享的配置
// import wxshare from './libs/mixin/mpShare.js'
// 全局挂载引入http相关请求拦截插件
import http from './libs/request'
function wranning(str) {
// 开发环境进行信息输出,主要是一些报错信息
// 这个环境的来由是在程序编写时候,点击hx编辑器运行调试代码的时候,详见:
// https://uniapp.dcloud.io/frame?id=%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e5%92%8c%e7%94%9f%e4%ba%a7%e7%8e%af%e5%a2%83
if (process.env.NODE_ENV === 'development') {
console.warn(str)
}
}
// 尝试判断在根目录的/store中是否有$u.mixin.js,此文件uView默认为需要挂在到全局的vuex的state变量
// HX2.6.11版本,放到try中,控制台依然会警告,暂时不用此方式,
// let vuexStore = {};
// try {
// vuexStore = require("@/store/$u.mixin.js");
// } catch (e) {
// //TODO handle the exception
// }
// post类型对象参数转为get类型url参数
import queryParams from './libs/function/queryParams.js'
// 路由封装
import route from './libs/function/route.js'
// 时间格式化
import timeFormat from './libs/function/timeFormat.js'
// 时间戳格式化,返回多久之前
import timeFrom from './libs/function/timeFrom.js'
// 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制
import colorGradient from './libs/function/colorGradient.js'
// 生成全局唯一guid字符串
import guid from './libs/function/guid.js'
// 主题相关颜色,info|success|warning|primary|default|error,此颜色已在uview.scss中定义,但是为js中也能使用,故也定义一份
import color from './libs/function/color.js'
// 根据type获取图标名称
import type2icon from './libs/function/type2icon.js'
// 打乱数组的顺序
import randomArray from './libs/function/randomArray.js'
// 对象和数组的深度克隆
import deepClone from './libs/function/deepClone.js'
// 对象深度拷贝
import deepMerge from './libs/function/deepMerge.js'
// 添加单位
import addUnit from './libs/function/addUnit.js'
// 规则检验
import test from './libs/function/test.js'
// 随机数
import random from './libs/function/random.js'
// 去除空格
import trim from './libs/function/trim.js'
// toast提示,对uni.showToast的封装
import toast from './libs/function/toast.js'
// 获取父组件参数
import getParent from './libs/function/getParent.js'
// 获取整个父组件
import $parent from './libs/function/$parent.js'
// 配置信息
import config from './libs/config/config.js'
// 各个需要fixed的地方的z-index配置文件
import zIndex from './libs/config/zIndex.js'
const $u = {
queryParams: queryParams,
route: route,
timeFormat: timeFormat,
date: timeFormat, // 另名date
timeFrom,
colorGradient: colorGradient.colorGradient,
guid,
color,
type2icon,
randomArray,
wranning,
get: http.get,
post: http.post,
put: http.put,
'delete': http.delete,
hexToRgb: colorGradient.hexToRgb,
rgbToHex: colorGradient.rgbToHex,
test,
random,
deepClone,
deepMerge,
getParent,
$parent,
addUnit,
trim,
type: ['primary', 'success', 'error', 'warning', 'info'],
http,
toast,
config, // uView配置信息相关,比如版本号
zIndex
}
const install = Vue => {
Vue.mixin(mixin)
if (Vue.prototype.openShare) {
Vue.mixin(mpShare);
}
// Vue.mixin(vuexStore);
// 时间格式化,同时两个名称,date和timeFormat
Vue.filter('timeFormat', (timestamp, format) => {
return timeFormat(timestamp, format)
})
Vue.filter('date', (timestamp, format) => {
return timeFormat(timestamp, format)
})
// 将多久以前的方法,注入到全局过滤器
Vue.filter('timeFrom', (timestamp, format) => {
return timeFrom(timestamp, format)
})
Vue.prototype.$u = $u
}
export default {
install
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save