zhuxiuping 3 years ago
parent
commit
1c56862234
100 changed files with 17830 additions and 17706 deletions
  1. 44 16
      App.vue
  2. 1 1
      README.md
  3. 21 21
      main.js
  4. 14 5
      manifest.json
  5. 41 40
      pages.json
  6. 1 1
      pages/IOSDownLoad/IOSDownLoad.vue
  7. 265 228
      pages/index/index.vue
  8. 6 6
      pages/kongbai/kongbai.vue
  9. 241 213
      pages/login/login.vue
  10. 136 115
      pages/video/video.vue
  11. BIN
      static/indexbg.png
  12. BIN
      static/login-bg.png
  13. BIN
      static/loginout.png
  14. BIN
      static/share.png
  15. BIN
      static/video_bg.png
  16. BIN
      static/xiazai.png
  17. 1 1
      store/rsaKeys.js
  18. 268 268
      uni_modules/uni-badge/components/uni-badge/uni-badge.vue
  19. 2 2
      uni_modules/uni-breadcrumb/changelog.md
  20. 120 120
      uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue
  21. 29 29
      uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue
  22. 8 8
      uni_modules/uni-breadcrumb/readme.md
  23. 11 11
      uni_modules/uni-calendar/components/uni-calendar/i18n/en.json
  24. 7 7
      uni_modules/uni-calendar/components/uni-calendar/i18n/index.js
  25. 11 11
      uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json
  26. 5 5
      uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json
  27. 188 188
      uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
  28. 562 562
      uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
  29. 350 350
      uni_modules/uni-calendar/components/uni-calendar/util.js
  30. 254 254
      uni_modules/uni-card/components/uni-card/uni-card.vue
  31. 401 401
      uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue
  32. 139 139
      uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue
  33. 5 5
      uni_modules/uni-countdown/components/uni-countdown/i18n/en.json
  34. 7 7
      uni_modules/uni-countdown/components/uni-countdown/i18n/index.js
  35. 5 5
      uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json
  36. 5 5
      uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json
  37. 238 238
      uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue
  38. 792 792
      uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
  39. 546 546
      uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
  40. 318 318
      uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
  41. 440 440
      uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue
  42. 85 85
      uni_modules/uni-data-select/package.json
  43. 185 185
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
  44. 909 909
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
  45. 20 20
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json
  46. 7 7
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js
  47. 946 946
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue
  48. 1012 1012
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
  49. 389 389
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
  50. 183 183
      uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue
  51. 55 55
      uni_modules/uni-easyinput/components/uni-easyinput/common.js
  52. 679 679
      uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
  53. 490 490
      uni_modules/uni-fab/components/uni-fab/uni-fab.vue
  54. 3 3
      uni_modules/uni-fav/components/uni-fav/i18n/en.json
  55. 7 7
      uni_modules/uni-fav/components/uni-fav/i18n/index.js
  56. 3 3
      uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json
  57. 3 3
      uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json
  58. 155 155
      uni_modules/uni-fav/components/uni-fav/uni-fav.vue
  59. 223 223
      uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
  60. 651 651
      uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
  61. 299 299
      uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
  62. 254 254
      uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
  63. 630 630
      uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
  64. 394 394
      uni_modules/uni-forms/components/uni-forms/uni-forms.vue
  65. 281 281
      uni_modules/uni-forms/components/uni-forms/utils.js
  66. 485 485
      uni_modules/uni-forms/components/uni-forms/validate.js
  67. 6 6
      uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json
  68. 8 8
      uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js
  69. 6 6
      uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json
  70. 6 6
      uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json
  71. 224 224
      uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue
  72. 127 127
      uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue
  73. 142 142
      uni_modules/uni-grid/components/uni-grid/uni-grid.vue
  74. 130 130
      uni_modules/uni-group/components/uni-group/uni-group.vue
  75. 64 64
      uni_modules/uni-icons/components/uni-icons/uni-icons.vue
  76. 144 144
      uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue
  77. 367 367
      uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue
  78. 107 107
      uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
  79. 4 4
      uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss
  80. 538 538
      uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
  81. 108 108
      uni_modules/uni-list/components/uni-list/uni-list.vue
  82. 1 1
      uni_modules/uni-load-more/components/uni-load-more/i18n/en.json
  83. 7 7
      uni_modules/uni-load-more/components/uni-load-more/i18n/index.js
  84. 1 1
      uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json
  85. 1 1
      uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json
  86. 392 392
      uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
  87. 356 356
      uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
  88. 27 27
      uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
  89. 426 426
      uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
  90. 221 221
      uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue
  91. 15 15
      uni_modules/uni-pagination/changelog.md
  92. 4 4
      uni_modules/uni-pagination/components/uni-pagination/i18n/en.json
  93. 4 4
      uni_modules/uni-pagination/components/uni-pagination/i18n/es.json
  94. 4 4
      uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json
  95. 11 11
      uni_modules/uni-pagination/components/uni-pagination/i18n/index.js
  96. 4 4
      uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json
  97. 4 4
      uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json
  98. 459 459
      uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue
  99. 82 82
      uni_modules/uni-pagination/package.json
  100. 0 0
      uni_modules/uni-pagination/readme.md

+ 44 - 16
App.vue

@@ -1,19 +1,47 @@
-<script>
-	export default {
+<script>
+	export default {
 		onLaunch: function() {
 		onLaunch: function() {
-			console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
-			console.log('App Launch')
-		},
-		onShow: function() {
-			console.log('App Show')
-		},
-		onHide: function() {
-			console.log('App Hide')
-		}
-	}
-</script>
-
-<style lang="scss">
+			console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
+			console.log('App Launch')
+			// 验证登录是否过期
+			// wx.checkSession({
+			//   success: function (res) {
+			// 	console.log(res, '登录未过期');
+				
+			// 	// wx.showToast({
+			// 	//   title: '登录未过期'
+			// 	// });
+			//   },
+			//   fail: function (res) {
+			// 	console.log(res, '登录已过期');
+			// 	uni.showModal({
+			// 	  title: '提示',
+			// 	  content: '登录已过期,请重新登录',
+			// 	  success(res) {
+			// 		if (res.confirm) {
+			// 		  uni.navigateTo({
+			// 		  	url: 'pages/login/login'
+			// 		  });
+			// 		} else if (res.cancel) {
+			// 		  uni.navigateTo({
+			// 		  	url: 'pages/login/login'
+			// 		  });
+			// 		}
+			// 	  }
+			// 	});
+			//   }
+			// });
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style lang="scss">
 	/*每个页面公共css */
 	/*每个页面公共css */
 	@import '@/uni_modules/uni-scss/index.scss';
 	@import '@/uni_modules/uni-scss/index.scss';
 	/* #ifndef APP-NVUE */
 	/* #ifndef APP-NVUE */
@@ -28,5 +56,5 @@
 		font-size: 14px;
 		font-size: 14px;
 		color: #333;
 		color: #333;
 		padding: 10px;
 		padding: 10px;
-	}
+	}
 </style>
 </style>

+ 1 - 1
README.md

@@ -1 +1 @@
-#WebDevelopmentFramework
+#WebDevelopmentFramework

+ 21 - 21
main.js

@@ -1,24 +1,24 @@
 
 
-// #ifndef VUE3
-import Vue from 'vue'
-import App from './App'
-import wx from  "jweixin-module"
-import axios from "axios"
-import VueClipboard from 'vue-clipboard2'
+// #ifndef VUE3
+import Vue from 'vue'
+import App from './App'
+import wx from  "jweixin-module"
+import axios from "axios"
+import VueClipboard from 'vue-clipboard2'
 import fns from './common/js/fns.js'
 import fns from './common/js/fns.js'
-Vue.use(VueClipboard)
-
+Vue.use(VueClipboard)
+
 Vue.prototype.$axios = axios;
 Vue.prototype.$axios = axios;
-Vue.prototype.$wx = wx 
-Vue.prototype.$fns = fns
-
-Vue.config.productionTip = false
-
-
-App.mpType = 'app'
-
-const app = new Vue({
-	fns,
-    ...App
-})
-app.$mount()
+Vue.prototype.$wx = wx 
+Vue.prototype.$fns = fns
+
+Vue.config.productionTip = false
+
+
+App.mpType = 'app'
+
+const app = new Vue({
+	fns,
+    ...App
+})
+app.$mount()

+ 14 - 5
manifest.json

@@ -64,7 +64,7 @@
             "proxy" : {
             "proxy" : {
                 //使用代理
                 //使用代理
                 "/img" : {
                 "/img" : {
-                    "target" : "http://139.199.2.142:8081//img", //目标地址
+                    "target" : "https://chtech.ncjti.edu.cn/testingServer/img", //目标地址
                     "changeOrigin" : true,
                     "changeOrigin" : true,
                     "secure" : false,
                     "secure" : false,
                     // 设置地址重定向,把程序中/api开头的路径替换成:http://t.yushu.im"
                     // 设置地址重定向,把程序中/api开头的路径替换成:http://t.yushu.im"
@@ -72,14 +72,23 @@
                         "/img" : "" // 设置/api路径重定向
                         "/img" : "" // 设置/api路径重定向
                     }
                     }
                 },
                 },
+                // "/api" : {
+                //     "target" : "http://192.168.161.224:8082/api", //目标地址https://chtech.ncjti.edu.cn/testingServer/shareVideo
+                //     "changeOrigin" : true,
+                //     "secure" : false,
+                //     // 设置地址重定向,把程序中/api开头的路径替换成:http://t.yushu.im"
+                //     "pathRewrite" : {
+                //         "/api" : "" // 设置/api路径重定向
+                //     }
+                // }
                 // /testingServer/shareVideo
                 // /testingServer/shareVideo
-                "/shareVideo" : {
-                    "target" : "http://139.199.2.142:8081/shareVideo", //目标地址https://chtech.ncjti.edu.cn/testingServer/shareVideo
+                "/videos" : {
+                    "target" : "http://139.199.2.142:8081/videos", //目标地址https://chtech.ncjti.edu.cn/testingServer/shareVideo
                     "changeOrigin" : true,
                     "changeOrigin" : true,
                     "secure" : false,
                     "secure" : false,
                     // 设置地址重定向,把程序中/api开头的路径替换成:http://t.yushu.im"
                     // 设置地址重定向,把程序中/api开头的路径替换成:http://t.yushu.im"
                     "pathRewrite" : {
                     "pathRewrite" : {
-                        "/shareVideo" : "" // 设置/api路径重定向
+                        "/videos" : "" // 设置/api路径重定向
                     }
                     }
                 }
                 }
             }
             }
@@ -95,7 +104,7 @@
         // }
         // }
         "router" : {
         "router" : {
             "mode" : "history",
             "mode" : "history",
-            "base" : "/shareVideoH5/"
+            "base" : "/videosH5/"
         }
         }
     },
     },
     // "base" : "/testingServer/shareVideoH5/"
     // "base" : "/testingServer/shareVideoH5/"

+ 41 - 40
pages.json

@@ -1,41 +1,42 @@
-{
-	"pages": [
-	// 	{
-	// 	"path": "pages/kongbai/kongbai",
-	// 	"style": {
-	// 		"navigationBarTitleText": "登录"
-	// 	}
-	// },
-	{
-		"path": "pages/login/login",
-		"style": {
-			"navigationBarTitleText": "登录"
-		}
-	},{
-		"path": "pages/index/index",
-		"style": {
-			"navigationBarTitleText": "项目列表",
-			"backgroundColor": "#FFFFFF"
-		}
-	},{
-		"path": "pages/video/video",
-		"style": {
-			"navigationBarTitleText": "视频播放"
-		}
-	},{
-		"path": "pages/IOSDownLoad/IOSDownLoad",
-		"style": {
-			"navigationBarTitleText": "下载"
-		}
-	}],
-	"globalStyle": {
-		"navigationBarTextStyle": "black",
-		"navigationBarTitleText": "uni-app",
-		"navigationBarBackgroundColor": "#F8F8F8",
-		"backgroundColor": "#F8F8F8",
-		"app-plus": {
-			"background": "#efeff4"
-		},
-		"pageOrientation":"auto"//全局视频旋转
-	}
+{
+	"pages": [
+	// 	{
+	// 	"path": "pages/kongbai/kongbai",
+	// 	"style": {
+	// 		"navigationBarTitleText": "登录"
+	// 	}
+	// },
+	{
+		"path": "pages/index/index",
+		"style": {
+			"navigationBarTitleText": "项目列表",
+			"backgroundColor": "#FFFFFF"
+		}
+	},
+	{
+		"path": "pages/login/login",
+		"style": {
+			"navigationBarTitleText": "登录"
+		}
+	},{
+		"path": "pages/video/video",
+		"style": {
+			"navigationBarTitleText": "视频播放"
+		}
+	},{
+		"path": "pages/IOSDownLoad/IOSDownLoad",
+		"style": {
+			"navigationBarTitleText": "下载"
+		}
+	}],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "uni-app",
+		"navigationBarBackgroundColor": "#F8F8F8",
+		"backgroundColor": "#F8F8F8",
+		"app-plus": {
+			"background": "#efeff4"
+		},
+		"pageOrientation":"auto"//全局视频旋转
+	}
 }
 }

+ 1 - 1
pages/IOSDownLoad/IOSDownLoad.vue

@@ -46,7 +46,7 @@
 					title: "正在请求数据"
 					title: "正在请求数据"
 				});
 				});
 				uni.request({
 				uni.request({
-					url: '/img'+this.fileUrl, //获取文件流的请求路径
+					url: '/img'+this.fileUrl, //获取文件流的请求路径
 					// url: '/api//img/1.pdf',
 					// url: '/api//img/1.pdf',
 					responseType: "arraybuffer",
 					responseType: "arraybuffer",
 					success: (response) => {
 					success: (response) => {

+ 265 - 228
pages/index/index.vue

@@ -1,230 +1,267 @@
-<template>
+<template>
 	<view class="container">
 	<view class="container">
-		<view style="background-color: #FFFFFF;width: 750rpx;height: 72px;">
-			<image src="../../static/touxiang.png" class="touxiang"></image>
-			<view class="username">{{name}}</view>
-			<text class="phone">{{phone}}</text>
-			<image src="../../static/share.png" class="share" @click="share"></image>
-			<image src="../../static/loginout.png" class="loginout" @click="loginout"></image>
-		</view>
-		<!-- 项目列表 -->
-		<view class="list-item" v-for="(item,index) in list" :key="index">
-			<view class="list-title">快乐体操</view>
-			<view class="list-icon"></view>
-			<view class="list-title2">学习视频</view>
-			<!-- 视频 -->
-			<view style="margin-left: 40px;height: 104px;margin-top: 10px;">
-				<image class="video" @click="playVideo(item)" :src="item.pictureUrl"></image>
-				<view class="jieshao">{{item.videoName}}</view>
-				<view class="xiang">{{item.videoDescription}}</view>
-			</view>
-			<view class="list-icon"></view>
-			<view class="list-title2">学习资料</view>
-			<!-- 资料 -->
-			<view style="width: 690rpx;margin-left: 40px;margin-top: 10px;" v-for="(item,index) in item.videoElseList" :key="index">
-				<view class="ziliao">{{item.videoElesName}}</view>
-				<image src="../../static/xiazai.png" class="xiazai" @click="download(item)"></image>
-			</view>
-			<view style="height:20px"></view>
-			<!-- <view style="width: 690rpx;margin-left: 40px;margin-top: 10px;">
-				<view class="ziliao">资料2</view>
-				<image src="../../static/xiazai.png" class="xiazai"></image>
-			</view> -->
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		data() {
-			return {
-				name:'xxx',//用户名
-				phone:'xxxxxxxxxxx',//手机号
-				fileUrl:'https://chuanghai-tech.com/video/txt.pdf',//下载链接
-				list:[],//当前页面数组数据
-				list2:[],//下载的东西2
-				token:'',//缓存token
-				resultDecodeN:'',//解密后数据
-			}
-		},
-		onLoad() {
-			if(wx.getStorageSync('userName')!='' || wx.getStorageSync('telPhone')!=''){
-				this.name=wx.getStorageSync('userName')
-				this.phone=wx.getStorageSync('telPhone')
-			}
-			this.token=wx.getStorageSync('token')
-			this.getList()
-		},
-		methods: {
-			//列表
-			getList(){
-				this.$axios.get('/shareVideo/api/video/video',
-				{
-					headers:{
-						'token':this.token
-					}
-				}
-				).then(res => {
-					if (res.data.success) {
-						console.log(res.data)
-						var shu=res.data.data
-						// 开始解密
-						this.resultDecodeN = this.$fns.rsaDecode(shu[0])+
-						this.$fns.rsaDecode(shu[1])+this.$fns.rsaDecode(shu[2])+
-						this.$fns.rsaDecode(shu[3])+this.$fns.rsaDecode(shu[4])+
-						this.$fns.rsaDecode(shu[5])+this.$fns.rsaDecode(shu[6])+
-						this.$fns.rsaDecode(shu[7])+this.$fns.rsaDecode(shu[8])+
-						this.$fns.rsaDecode(shu[9])+this.$fns.rsaDecode(shu[10])
-						//解析
-						console.log(JSON.parse(this.resultDecodeN));
-						//获取数组
-						JSON.parse(this.resultDecodeN).forEach(data => {
-							this.list.push(data)
-							// this.list2.push(data.videoElseList)
-						})
-					} else {
-						uni.showToast({ title: res.data.message, icon: 'none' });
-					}
-				}).catch(res =>{
-				});
-			},
-			//跳转播放视频
-			playVideo(item){
-				uni.navigateTo({
-					url:'/pages/video/video?id='+item.id
-				})
-			},
-			//下载文件
-			download(item) {
-				if(this.isIos()){
-						uni.navigateTo({
-						    url:'/pages/IOSDownLoad/IOSDownLoad?url='+item.videoElesUrl
-					    })
-					}else{
-				        //直接在浏览器中打开
-						window.location.href = 'http://139.199.2.142:8081//img'+item.videoElesUrl;
-					}
-			},
-			//判断是否ios
-			isIos() {
-				let u = navigator.userAgent
-				let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
-			 
-				if (isIOS) {
-					return true
-				} else {
-					return false
-				}
-			},
-			//分享链接
-			share(){
-				wx.setClipboardData({
-					data: uni.getStorageSync('url'),
-					
-					success: function(res) {
-						wx.showToast({
-							title: '复制'+uni.getStorageSync('url')+'成功',
-							icon: "none",
-							mask: "true"
-						})
-					}
-				})
-			},
-			//退出登录
-			loginout(){
-				uni.navigateTo({
-					url:'/pages/login/login'
-				})
-			}
-		}
-	}
-</script>
-
-<style>
-	.container {
-		padding: 10px 20px 20px 0px;
-		font-size: 16px;
-		line-height: 24px;
-	}
-	.touxiang{
-		width: 100rpx;
-		height: 100rpx;
-		padding: 10px 10px 10px 10px;
-	}
-	.username{
-		margin-left: 70px;
-		margin-top: -65px;
-	}
-	.phone{
-		margin-left: 70px;
-		font-size: 14px;
-	}
-	.share{
-		width: 50rpx;
-		height: 50rpx;
-		/* position: absolute; */
-		margin-left: 140px;
-		margin-top: -15px;
-	}
-	.loginout{
-		width: 50rpx;
-		height: 50rpx;
-		/* position: absolute; */
-		margin-left: 10px;
-		margin-top: -15px;
-	}
-	/* 项目列表 */
-	.list-item{
-		margin-top: 10px;
-		width: 750rpx;
-		height: auto;
-		border-radius: 15rpx;
-		background-color: #FFFFFF;
-	}
-	.list-title{
-		padding-top: 20px;
-		font-size: 27px;
-		text-align: center;
-	}
-	.list-icon{
-		margin-left: 20px;
-		margin-top: 20rpx;
-		width: 8rpx;
-		height: 32rpx;
-		opacity: 1;
-		border-radius: 33rpx;
-		background: #1E7DFB;
-	}
-	.list-title2{
-		margin-top: -20px;
-		margin-left: 30px;
-	}
-	/* 视频 */
-	.video{
-		width: 394rpx;
-		height: 200rpx;
-		background-color: antiquewhite;
-		/* float: left; */
-	}
-	.jieshao{
-		margin-top: -100px;
-		margin-left: 220px;
-	}
-	.xiang{
-		margin-left: 220px;
-		margin-top: 10px;
-	}
-	/* 资料 */
-	.ziliao{
-		width: 170px;
-		line-height: 40rpx;
-		font-size: 32rpx;
-		float: left;
-	}
-	.xiazai{
-		width: 40rpx;
-		height: 40rpx;
-		margin-left: 120px;
-		/* float: right; */
-	}
+		<view style="background-color: rgba(255, 255, 255, 0.2);width: 750rpx;height: 72px;">
+			<image src="../../static/touxiang.png" class="touxiang"></image>
+			<view class="username">{{name}}</view>
+			<text class="phone">{{phone}}</text>
+			<image src="../../static/share.png" class="share" @click="share"></image>
+			<image src="../../static/loginout.png" class="loginout" @click="loginout"></image>
+		</view>
+		<!-- 项目列表 -->
+		<view class="list-item" v-for="(item,index) in list" :key="index">
+			<view class="list-title">体适能</view>
+			<view class="list-icon"></view>
+			<view class="list-title2">学习视频</view>
+			<!-- 视频 -->
+			<view style="margin-left: 40px;height: 104px;margin-top: 10px;">
+				<image class="video" @click="playVideo(item)" :src="item.pictureUrl"></image>
+				<view class="jieshao">{{item.videoName}}</view>
+				<view class="xiang">{{item.videoDescription}}</view>
+			</view>
+			<view class="list-icon"></view>
+			<view class="list-title2">学习资料</view>
+			<!-- 资料 -->
+			<view style="width: 690rpx;margin-left: 40px;margin-top: 10px;" v-for="(item,index) in item.videoElseList" :key="index">
+				<view class="ziliao">{{item.videoElesName}}</view>
+				<image src="../../static/xiazai.png" class="xiazai" @click="download(item)"></image>
+			</view>
+			<view style="height:20px"></view>
+			<!-- <view style="width: 690rpx;margin-left: 40px;margin-top: 10px;">
+				<view class="ziliao">资料2</view>
+				<image src="../../static/xiazai.png" class="xiazai"></image>
+			</view> -->
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				name:'xxx',//用户名
+				phone:'xxxxxxxxxxx',//手机号
+				fileUrl:'https://chuanghai-tech.com/video/txt.pdf',//下载链接
+				list:[],//当前页面数组数据
+				list2:[],//下载的东西2
+				token:'',//缓存token
+				resultDecodeN:'',//解密后数据
+			}
+		},
+		onShow() {
+			if(wx.getStorageSync('userName')!='' || wx.getStorageSync('telPhone')!=''){
+				this.name=wx.getStorageSync('userName')
+				this.phone=wx.getStorageSync('telPhone')
+			}
+			this.token=wx.getStorageSync('token')
+			this.getList()
+			if(wx.getStorageSync('token')==''){
+				uni.navigateTo({
+					url:'/pages/login/login'
+				})
+			}
+		},
+		onLoad() {
+			
+		},
+		methods: {
+			//列表
+			getList(){
+				this.list=[]
+				this.resultDecodeN=''
+				this.$axios.get('/videos/api/video/video',
+				{
+					headers:{
+						'token':wx.getStorageSync('token')
+					}
+				}
+				).then(res => {
+					if(res.data.message=='token已过期'){
+						uni.navigateTo({
+							url:'/pages/login/login'
+						})
+					}
+					if (res.data.success) {
+						var shu=res.data.data
+						var length=Object.values(res.data.data).length
+						// console.log(Object.values(res.data.data).length)
+						// 开始解密
+						for(var i=0;i<length;i++){
+							this.resultDecodeN =this.resultDecodeN+this.$fns.rsaDecode(shu[i])
+						}
+						
+						// 开始解密
+						// this.resultDecodeN = this.$fns.rsaDecode(shu[0])+
+						// this.$fns.rsaDecode(shu[1])+this.$fns.rsaDecode(shu[2])+
+						// this.$fns.rsaDecode(shu[3])+this.$fns.rsaDecode(shu[4])+
+						// this.$fns.rsaDecode(shu[5])+this.$fns.rsaDecode(shu[6])+
+						// this.$fns.rsaDecode(shu[7])+this.$fns.rsaDecode(shu[8])+
+						// this.$fns.rsaDecode(shu[9])
+						
+						//解析
+						console.log(this.resultDecodeN);
+						console.log(JSON.parse(this.resultDecodeN));
+						//获取数组
+						JSON.parse(this.resultDecodeN).forEach(data => {
+							this.list.push(data)
+							// this.list2.push(data.videoElseList)
+						})
+					} else {
+						uni.showToast({ title: res.data.message, icon: 'none' });
+					}
+				}).catch(res =>{
+				});
+			},
+			//跳转播放视频
+			playVideo(item){
+				uni.navigateTo({
+					url:'/pages/video/video?id='+item.id
+				})
+			},
+			//下载文件
+			download(item) {
+				if(this.isIos()){
+						uni.navigateTo({
+						    url:'/pages/IOSDownLoad/IOSDownLoad?url='+item.videoElesUrl
+					    })
+					}else{
+				        //直接在浏览器中打开
+						window.location.href = 'http://139.199.2.142:8081//img'+item.videoElesUrl;
+					}
+			},
+			//判断是否ios
+			isIos() {
+				let u = navigator.userAgent
+				let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
+			 
+				if (isIOS) {
+					return true
+				} else {
+					return false
+				}
+			},
+			//分享链接
+			share(){
+				wx.setClipboardData({
+					data: uni.getStorageSync('url'),
+					
+					success: function(res) {
+						wx.showToast({
+							title: '复制'+uni.getStorageSync('url')+'成功',
+							icon: "none",
+							mask: "true"
+						})
+					}
+				})
+			},
+			//退出登录
+			loginout(){
+				uni.navigateTo({
+					url:'/pages/login/login'
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+	.container {
+		padding: 10px 20px 20px 0px;
+		font-size: 16px;
+		line-height: 24px;
+		background-image: url('../../static/indexbg.png');
+		background-size: 100%;
+		width: 750rpx;
+		height: 1334rpx;
+	}
+	.touxiang{
+		width: 100rpx;
+		height: 100rpx;
+		padding: 10px 10px 10px 10px;
+	}
+	.username{
+		margin-left: 70px;
+		margin-top: -65px;
+		color: #FFFFFF;
+	}
+	.phone{
+		margin-left: 70px;
+		font-size: 14px;
+		color: #FFFFFF;
+	}
+	.share{
+		width: 50rpx;
+		height: 50rpx;
+		/* position: absolute; */
+		margin-left: 160px;
+		margin-top: -15px;
+		background-size: 100%;
+	}
+	.loginout{
+		width: 50rpx;
+		height: 50rpx;
+		/* position: absolute; */
+		margin-left: 10px;
+		margin-top: -15px;
+		background-size: 100%;
+	}
+	/* 项目列表 */
+	.list-item{
+		margin-top: 10px;
+		width: 750rpx;
+		height: auto;
+		border-radius: 15rpx;
+		background-color: rgba(255, 255, 255, 0.2);
+	}
+	.list-title{
+		padding-top: 20px;
+		font-size: 27px;
+		text-align: center;
+		color: #FFFFFF;
+	}
+	.list-icon{
+		margin-left: 20px;
+		margin-top: 20rpx;
+		width: 8rpx;
+		height: 32rpx;
+		opacity: 1;
+		border-radius: 33rpx;
+		background: #1E7DFB;
+	}
+	.list-title2{
+		margin-top: -20px;
+		margin-left: 30px;
+		color: #FFFFFF;
+	}
+	/* 视频 */
+	.video{
+		width: 394rpx;
+		height: 200rpx;
+		background-color: antiquewhite;
+		/* float: left; */
+	}
+	.jieshao{
+		margin-top: -100px;
+		margin-left: 220px;
+		color: #FFFFFF;
+	}
+	.xiang{
+		margin-left: 220px;
+		margin-top: 10px;
+		color: #FFFFFF;
+	}
+	/* 资料 */
+	.ziliao{
+		width: 200px;
+		line-height: 40rpx;
+		font-size: 32rpx;
+		float: left;
+		color: #FFFFFF;
+	}
+	.xiazai{
+		width: 40rpx;
+		height: 40rpx;
+		margin-left: 120px;
+		background-size: 100%;
+		/* float: right; */
+	}
 </style>
 </style>

+ 6 - 6
pages/kongbai/kongbai.vue

@@ -1,14 +1,14 @@
-<template>
+<template>
 	<view class="cointar">资料准备中,暂未开放</view>
 	<view class="cointar">资料准备中,暂未开放</view>
 </template>
 </template>
 
 
 <script>
 <script>
 </script>
 </script>
 
 
-<style>
-	.cointar{
-		text-align: center;
-		font-size: 28px;
-		margin-top: 200px;
+<style>
+	.cointar{
+		text-align: center;
+		font-size: 28px;
+		margin-top: 200px;
 	}
 	}
 </style>
 </style>

+ 241 - 213
pages/login/login.vue

@@ -1,221 +1,249 @@
-<template>
-	<view class="container">
-		<!-- <view class="title">登录</view> -->
-		<input class="input-phone" placeholder="请输入手机号码" type='number' maxlength="11" :value="phone" 
-		@input="phone_input" @blur="yz_phone"/>
-		<view style="margin-top: 20px;margin-left: 30px;width: 290px;">
-			<input class="input-yanzhen" placeholder="请输入验证码" @input="yan_input" type='number' :value="yanzhen"/>
-			<view class="send" @click="sendCode" v-if="disabled==false">发送验证码</view>
-			<view class="send" style="background-color: #CCCCCC;" v-else>{{codeMsg}}</view>
-		</view>
-		
-		<view class="login" @click="login">登录</view>
+<template>
+	<view class="container">
+		<!-- <view class="title">登录</view> -->
+		<input class="input-phone" placeholder="请输入手机号码" type='number' maxlength="11" :value="phone" 
+		@input="phone_input" @blur="yz_phone"/>
+		<view style="margin-top: 20px;margin-left: 30px;width: 290px;">
+			<input class="input-yanzhen" placeholder="请输入验证码" @input="yan_input" type='number' :value="yanzhen"/>
+			<view class="send" @click="sendCode" v-if="disabled==false">发送验证码</view>
+			<view class="send" style="background-color: #CCCCCC;" v-else>{{codeMsg}}</view>
+		</view>
+		
+		<view class="login" @click="login">登录</view>
 	</view>
 	</view>
 </template>
 </template>
 
 
-<script>
-	import until from '../../common/jiaoyan.js'
-	import { JSEncrypt } from 'jsencrypt';
-	export default {
-		data() {
-			return {
-				phone:'',//手机号
-				yanzhen:'',//验证码
-				numbercode:60,//倒计时时间
-				codeMsg:'',//倒计时验证码内容
-				disabled:false,
-				name:'',//同户名
-				// RSA加密结果
-				resultEncodeP: '',//加密手机号
-				resultEncodeY: '',//加密验证码
-				// RSA解密结果
-				resultDecodeN: '',//解密
-				resultDecodeY: '',
-				list:[]
-			}
-		},
-		onReady() {
-			this.codeMsg = '重发('+this.numbercode+')';
-		},
-		onLoad() {
-			
-			// let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
-			// let curRoute = routes[routes.length - 1].route //获取当前页面路由
-			let url=location.href
-			uni.setStorageSync('url',url)
-		},
-		methods: {
-			// // 加密
-			// export function encrypt (txt: string): string {
-			//   let cryptFirst = new JSEncryptWX()
-			//   cryptFirst.setPublicKey(publicKey)
-			//   return cryptFirst.encrypt(txt) || ''
-			// },
-			 
-			// // 解密
-			// export function decrypt (txt: string): string {
-			//   let cryptFirst = new JSEncryptWX()
-			//   cryptFirst.setPrivateKey(privateKey)
-			//   return cryptFirst.decrypt(txt) || ''
-			// },
-			//登录
-			login(){
-				// 开始加密
-				this.resultEncodeP = this.$fns.rsaEncode(this.phone)
-				console.log(this.resultEncodeP);
-				// 开始解密
-				this.resultDecodeY = this.$fns.rsaDecode(this.resultEncodeP)
-				console.log(this.resultDecodeY);
-				this.resultEncodeY = this.$fns.rsaEncode(this.yanzhen)
-				this.$axios.post('/shareVideo/api/logInfo/logIn?phone='+this.resultEncodeP+'&code='+this.resultEncodeY,
-				
-				{
-				  headers:{
-				  }
-				}).then(res => {
-					if (res.data.success) {
-						console.log(res.data.data)
-						var shu=res.data.data
-						// for(var i=0;i<shu.length;i++){
-						// 	var jiemi=this.$fns.rsaDecode(shu[i])
-						// 	this.resultDecodeN=jiemi
-						// 	console.log(this.resultDecodeN);
-						// }
-						// 开始解密
-						this.resultDecodeN = this.$fns.rsaDecode(shu[0])+
-						this.$fns.rsaDecode(shu[1])+this.$fns.rsaDecode(shu[2])+
-						this.$fns.rsaDecode(shu[3])+this.$fns.rsaDecode(shu[4])+
-						this.$fns.rsaDecode(shu[5])+this.$fns.rsaDecode(shu[6])
-						console.log(JSON.parse(this.resultDecodeN));
-						console.log(JSON.parse(this.resultDecodeN).token)
-						uni.setStorageSync('token',JSON.parse(this.resultDecodeN).token)
-						uni.setStorageSync('userName',JSON.parse(this.resultDecodeN).userName)
-						uni.setStorageSync('telPhone',JSON.parse(this.resultDecodeN).telPhone)
-						// this.name=JSON.parse(this.resultDecodeN).userName
-						uni.navigateTo({
-							url:'/pages/index/index'
-						})
-					} else {
-						uni.showToast({ title: res.data.message, icon: 'none' });
-					}
-				}).catch(res =>{
-				});
-				
-			},
-			// 输入手机号
-			phone_input(e) {
-				this.phone = e.detail.value;
-			},
-			// 验证手机号
-			yz_phone() {
-				if (this.phone == '') {
-					uni.showToast({ title: '请输入手机号', icon: 'none' });
-					return;
-				}
-				if (!until.checkMobile(this.phone)) {
-					uni.showToast({ title: '手机号格式错误', icon: 'none' });
-					return;
-				}
-			},
-			//输入验证码
-			yan_input(e){
-				this.yanzhen=e.detail.value;
-			},
-			//点击验证码发送
-			sendCode(){
-				//验证手机号是否存在
-				this.$axios.get('/shareVideo/api/logInfo/verify?phone='+parseInt(this.phone),
-				).then(res => {
-					if (res.data.success) {
-						this.disabled = true;
-						let timer = setInterval(()=>{
-							--this.numbercode;
-							this.codeMsg = '重发('+this.numbercode+')';
-						},1000);
-						setTimeout(()=>{
-							clearInterval(timer);
-							this.numbercode=60;
-							this.disabled = false;
-						},60000)
-					} else {
-						uni.showToast({ title: '手机号无权限', icon: 'none' });
-					}
-				}).catch(res =>{
-				});
-				
-			},
-		}
+<script>
+	import until from '../../common/jiaoyan.js'
+	import { JSEncrypt } from 'jsencrypt';
+	export default {
+		data() {
+			return {
+				phone:'',//手机号
+				yanzhen:'',//验证码
+				numbercode:60,//倒计时时间
+				codeMsg:'',//倒计时验证码内容
+				disabled:false,
+				name:'',//同户名
+				// RSA加密结果
+				resultEncodeP: '',//加密手机号
+				resultEncodeY: '',//加密验证码
+				// RSA解密结果
+				resultDecodeN: '',//解密
+				resultDecodeY: '',
+				list:[]
+			}
+		},
+		onReady() {
+			this.codeMsg = '重发('+this.numbercode+')';
+		},
+		onLoad() {
+			
+			// let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
+			// let curRoute = routes[routes.length - 1].route //获取当前页面路由
+			let url=location.href
+			uni.setStorageSync('url',url)
+		},
+		methods: {
+			// // 加密
+			// export function encrypt (txt: string): string {
+			//   let cryptFirst = new JSEncryptWX()
+			//   cryptFirst.setPublicKey(publicKey)
+			//   return cryptFirst.encrypt(txt) || ''
+			// },
+			 
+			// // 解密
+			// export function decrypt (txt: string): string {
+			//   let cryptFirst = new JSEncryptWX()
+			//   cryptFirst.setPrivateKey(privateKey)
+			//   return cryptFirst.decrypt(txt) || ''
+			// },
+			//登录
+			login(){
+				// 开始加密
+				this.resultEncodeP = this.$fns.rsaEncode(this.phone)
+				console.log(this.resultEncodeP);
+				// 开始解密
+				this.resultDecodeY = this.$fns.rsaDecode(this.resultEncodeP)
+				console.log(this.resultDecodeY);
+				this.resultEncodeY = this.$fns.rsaEncode(this.yanzhen)
+				this.$axios.post('/videos/api/logInfo/logIn?phone='+this.resultEncodeP+'&code='+this.resultEncodeY,
+				
+				{
+				  headers:{
+				  }
+				}).then(res => {
+					if (res.data.success) {
+						console.log(res.data.data)
+						var shu=res.data.data
+						// for(var i=0;i<shu.length;i++){
+						// 	var jiemi=this.$fns.rsaDecode(shu[i])
+						// 	this.resultDecodeN=jiemi
+						// 	console.log(this.resultDecodeN);
+						// }
+						// 开始解密
+						this.resultDecodeN = this.$fns.rsaDecode(shu[0])+
+						this.$fns.rsaDecode(shu[1])+this.$fns.rsaDecode(shu[2])+
+						this.$fns.rsaDecode(shu[3])+this.$fns.rsaDecode(shu[4])+
+						this.$fns.rsaDecode(shu[5])+this.$fns.rsaDecode(shu[6])
+						console.log(JSON.parse(this.resultDecodeN));
+						console.log(JSON.parse(this.resultDecodeN).token)
+						uni.setStorageSync('token',JSON.parse(this.resultDecodeN).token)
+						uni.setStorageSync('userName',JSON.parse(this.resultDecodeN).userName)
+						uni.setStorageSync('telPhone',JSON.parse(this.resultDecodeN).telPhone)
+						// this.name=JSON.parse(this.resultDecodeN).userName
+						uni.navigateTo({
+							url:'/pages/index/index'
+						})
+					} else {
+						uni.showToast({ title: res.data.message, icon: 'none' });
+					}
+				}).catch(res =>{
+				});
+				
+			},
+			// 输入手机号
+			phone_input(e) {
+				this.phone = e.detail.value;
+			},
+			// 验证手机号
+			yz_phone() {
+				if (this.phone == '') {
+					uni.showToast({ title: '请输入手机号', icon: 'none' });
+					return;
+				}
+				if (!until.checkMobile(this.phone)) {
+					uni.showToast({ title: '手机号格式错误', icon: 'none' });
+					return;
+				}
+			},
+			//输入验证码
+			yan_input(e){
+				this.yanzhen=e.detail.value;
+			},
+			//点击验证码发送
+			sendCode(){
+				//验证手机号是否存在
+				this.$axios.get('/videos/api/logInfo/verify?phone='+parseInt(this.phone),
+				).then(res => {
+					if (res.data.success) {
+						this.disabled = true;
+						let timer = setInterval(()=>{
+							--this.numbercode;
+							this.codeMsg = '重发('+this.numbercode+')';
+						},1000);
+						setTimeout(()=>{
+							clearInterval(timer);
+							this.numbercode=60;
+							this.disabled = false;
+						},60000)
+					} else {
+						uni.showToast({ title: '手机号无权限', icon: 'none' });
+					}
+				}).catch(res =>{
+				});
+				
+			},
+		}
 	}
 	}
 </script>
 </script>
 
 
-<style>
-	.container {
-		padding: 80px 20px 0 20px;
-		background-image: url('../../static/login-bg.png');
-		width: 749rpx;
-		height: 1211rpx;
-		background-size: 100%;
-		font-size: 14px;
-		line-height: 24px;
-	}
-	.title{
-		font-size: 27px;
-		text-align: center;
-	}
-	.input-phone{
-		position: absolute;
-		padding-left: 50rpx;
-		margin-top: 264rpx;
-		margin-left: 30px;
-		width: 540rpx;
-		height: 90rpx;
-		opacity: 1;
-		opacity: 1;
-		border-radius: 15rpx;
-		border: 1rpx solid rgba(128, 128, 128, 1);      
-	}
-	.input-yanzhen{
-		position: absolute;
-		padding-left: 50rpx;
-		margin-top: 354rpx;
-		width: 180px;
-		height: 90rpx;
-		opacity: 1;
-		border-radius: 15rpx;
-		border: 1rpx solid rgba(128, 128, 128, 1);
-		float: left;
-	}
-	.send{
-		position: absolute;
-		margin-left: 414rpx;
-		margin-top: 354rpx;
-		width: 175rpx;
-		height: 90rpx;
-		opacity: 1;
-		border-radius: 15rpx;
-		background: #00A0E9;
-		font-size: 32rpx;
-		font-weight: 400;
-		line-height: 78rpx;
-		color: rgba(255, 255, 255, 1);
-		text-align: center;
-		float: right;
-	}
-	.login{
-		position: absolute;
-		margin-left: 30rpx;
-		margin-top: 524rpx;
-		width: 589rpx;
-		height: 90rpx;
-		margin-left: 30px;
-		opacity: 1;
-		border-radius: 6rpx;
-		background: #00A0E9;
-		box-shadow: 0px -5rpx 13rpx 0px rgba(0, 0, 0, 0.25);
-		font-size: 32rpx;
-		font-weight: 400;
-		line-height: 90rpx;
-		color: rgba(255, 255, 255, 1);
-		text-align: center;
+<style>
+	.container {
+		padding: 80px 0px 0 0px;
+		background-image: url('../../static/login-bg.png');
+		width: 749rpx;
+		height: 1211rpx;
+		background-size: 100%;
+		font-size: 14px;
+		line-height: 24px;
+	}
+	.title{
+		font-size: 27px;
+		text-align: center;
+	}
+	.input-phone{
+		position: absolute;
+		padding-left: 50rpx;
+		margin-top: 264rpx;
+		margin-left: 30px;
+		width: 540rpx;
+		height: 90rpx;
+		opacity: 1;
+		opacity: 1;
+		border-radius: 15rpx;
+		border: 1rpx solid rgba(225, 225, 225, 1);      
+	}
+	.input-yanzhen{
+		position: absolute;
+		padding-left: 50rpx;
+		margin-top: 354rpx;
+		width: 180px;
+		height: 90rpx;
+		opacity: 1;
+		border-radius: 15rpx;
+		border: 1rpx solid rgba(225, 225, 225, 1);
+		float: left;
+	}
+	>>>.uni-input-placeholder {
+	    position: absolute;
+	    top: auto!important;
+	    left: 0;
+	    color: #FFFFFF;
+	    overflow: hidden;
+	    text-overflow: clip;
+	    white-space: pre;
+	    word-break: keep-all;
+	    pointer-events: none;
+	    line-height: inherit;
+	}
+	>>>.uni-input-input {
+	    position: relative;
+	    display: block;
+	    height: 100%;
+	    background: none;
+	    color: inherit;
+	    opacity: 1;
+	    font: inherit;
+	    line-height: inherit;
+	    letter-spacing: inherit;
+	    text-align: inherit;
+	    text-indent: inherit;
+	    text-transform: inherit;
+	    text-shadow: inherit;
+	    color: #FFFFFF;
+	}
+	.send{
+		position: absolute;
+		margin-left: 414rpx;
+		margin-top: 354rpx;
+		width: 175rpx;
+		height: 90rpx;
+		opacity: 1;
+		border-radius: 15rpx;
+		background: #365CFF;
+		font-size: 32rpx;
+		font-weight: 400;
+		line-height: 78rpx;
+		color: rgba(255, 255, 255, 1);
+		text-align: center;
+		float: right;
+	}
+	.login{
+		position: absolute;
+		margin-left: 30rpx;
+		margin-top: 524rpx;
+		width: 589rpx;
+		height: 90rpx;
+		margin-left: 30px;
+		opacity: 1;
+		border-radius: 6rpx;
+		background: #365CFF;
+		box-shadow: 0px -5rpx 13rpx 0px rgba(0, 0, 0, 0.25);
+		font-size: 32rpx;
+		font-weight: 400;
+		line-height: 90rpx;
+		color: rgba(255, 255, 255, 1);
+		text-align: center;
 	}
 	}
 </style>
 </style>

+ 136 - 115
pages/video/video.vue

@@ -1,123 +1,144 @@
-<template>
-	<view class="container">
-		<view class="list-icon"></view>
-		<view class="title">{{videoName}}</view>
-		<video class="video" id="myVideo" ref="video1" :src="videoUrl"
-				 loop=true 
-				 enable-danmu danmu-btn controls enable-progress-gesture show-mute-btn
-				></video>
-		<!-- <view class="video"></view> -->
-		<view class="jieshao">{{videoDescription}}</view>
+<template>
+	<view class="container">
+		<view class="list-icon"></view>
+		<view class="title">{{videoName}}</view>
+		<video class="video" id="myVideo" ref="video1" :src="videoUrl"
+				 loop=true 
+				 enable-danmu danmu-btn controls enable-progress-gesture show-mute-btn
+				></video>
+		<!-- <view class="video"></view> -->
+		<view class="jieshao">{{videoDescription}}</view>
 	</view>
 	</view>
 </template>
 </template>
 
 
-<script>
-	export default {
-		data() {
-			return {
-				videoUrl:'',//视频链接
-				videoDescription:'',
-				videoName:'',//视频名
-				id:'',
-				list:[],//当前页面数据
-				resultDecodeN:'',//解密后
-				token:'',//缓存token
-			}
-		},
-		onLoad(option) {
-			// this.videoUrl=option.video
-			// this.videoDescription=option.videoDescription
-			// this.videoName=option.videoName
-			this.id=option.id
-			this.token=wx.getStorageSync('token')
-			this.getList()
-		},
-		methods: {
-			getList(){
-				this.$axios.get('/shareVideo/api/video/video',
-				{
-					headers:{
-						'token':this.token
-					}
-				}
-				).then(res => {
-					if (res.data.success) {
-						console.log(res.data)
-						var shu=res.data.data
-						// 开始解密
-						this.resultDecodeN = this.$fns.rsaDecode(shu[0])+
-						this.$fns.rsaDecode(shu[1])+this.$fns.rsaDecode(shu[2])+
-						this.$fns.rsaDecode(shu[3])+this.$fns.rsaDecode(shu[4])+
-						this.$fns.rsaDecode(shu[5])+this.$fns.rsaDecode(shu[6])+
-						this.$fns.rsaDecode(shu[7])+this.$fns.rsaDecode(shu[8])+
-						this.$fns.rsaDecode(shu[9])+this.$fns.rsaDecode(shu[10])
-						//解析
-						console.log(JSON.parse(this.resultDecodeN));
-						//获取数组
-						JSON.parse(this.resultDecodeN).forEach(data => {
-							this.list.push(data)
-						})
-						var length=JSON.parse(this.resultDecodeN).length
-						//根据id判断
-						for(var i=0;i<length;i++){
-							console.log(this.list[i].id)
-							if(this.id==this.list[i].id){
-								this.videoUrl=this.list[i].videoUrl
-								this.videoDescription=this.list[i].videoDescription
-								this.videoName=this.list[i].videoName
-							}
-						}
-					} else {
-						uni.showToast({ title: res.data.message, icon: 'none' });
-					}
-				}).catch(res =>{
-				});
-			},
-		}
+<script>
+	export default {
+		data() {
+			return {
+				videoUrl:'',//视频链接
+				videoDescription:'',
+				videoName:'',//视频名
+				id:'',
+				list:[],//当前页面数据
+				resultDecodeN:'',//解密后
+				token:'',//缓存token
+			}
+		},
+		onShow(){
+			this.getList()
+			if(wx.getStorageSync('token')==''){
+				uni.navigateTo({
+					url:'/pages/login/login'
+				})
+			}
+		},
+		onLoad(option) {
+			// this.videoUrl=option.video
+			// this.videoDescription=option.videoDescription
+			// this.videoName=option.videoName
+			this.id=option.id
+			this.token=wx.getStorageSync('token')
+			
+		},
+		methods: {
+			getList(){
+				this.list=[]
+				this.resultDecodeN=''
+				this.$axios.get('/videos/api/video/video',
+				{
+					headers:{
+						'token':wx.getStorageSync('token')
+					}
+				}
+				).then(res => {
+					if(res.data.message=='token已过期'){
+						uni.navigateTo({
+							url:'/pages/login/login'
+						})
+					}
+					if (res.data.success) {
+						var shu=res.data.data
+						var length=Object.values(res.data.data).length
+						// console.log(Object.values(res.data.data).length)
+						// 开始解密
+						for(var i=0;i<length;i++){
+							this.resultDecodeN =this.resultDecodeN+this.$fns.rsaDecode(shu[i])
+						}
+						// 开始解密
+						// this.resultDecodeN = this.$fns.rsaDecode(shu[0])+
+						// this.$fns.rsaDecode(shu[1])+this.$fns.rsaDecode(shu[2])+
+						// this.$fns.rsaDecode(shu[3])+this.$fns.rsaDecode(shu[4])+
+						// this.$fns.rsaDecode(shu[5])+this.$fns.rsaDecode(shu[6])+
+						// this.$fns.rsaDecode(shu[7])+this.$fns.rsaDecode(shu[8])+
+						// this.$fns.rsaDecode(shu[9])
+						
+						//解析
+						console.log(JSON.parse(this.resultDecodeN));
+						//获取数组
+						JSON.parse(this.resultDecodeN).forEach(data => {
+							this.list.push(data)
+						})
+						var length=JSON.parse(this.resultDecodeN).length
+						//根据id判断
+						for(var i=0;i<length;i++){
+							console.log(this.list[i].id)
+							if(this.id==this.list[i].id){
+								this.videoUrl=this.list[i].videoUrl
+								this.videoDescription=this.list[i].videoDescription
+								this.videoName=this.list[i].videoName
+							}
+						}
+					} else {
+						uni.showToast({ title: res.data.message, icon: 'none' });
+					}
+				}).catch(res =>{
+				});
+			},
+		}
 	}
 	}
 </script>
 </script>
 
 
-<style>
-	.container {
-		/* padding: 10px 20px 20px 15px; */
-		font-size: 16px;
-		line-height: 24px;
-		background-image: url('../../static/video_bg.png');
-		width: 749rpx;
-		height: 1211rpx;
-		background-size: 100%;
-	}
-	.list-icon{
-		position: absolute;
-		margin-left: 120rpx;
-		margin-top: 203px;
-		width: 8rpx;
-		height: 32rpx;
-		opacity: 1;
-		border-radius: 33rpx;
-		background: #1682AA;
-	}
-	.title{
-		font-size: 22px;
-		position: absolute;
-		margin-left: 141rpx;
-		margin-top: 382rpx;
-		font-size: 34rpx;
-		font-family: Microsoft YaHei-3970(82674968);
-		font-weight: 400;
-		color: #1682AA;
-	}
-	.video{
-		position: absolute;
-		margin-left: 121rpx;
-		margin-top: 439rpx;
-		width: 506rpx;
-		height: 347rpx;
-	}
-	.jieshao{
-		position: absolute;
-		margin-left: 121rpx;
-		margin-top: 809rpx;
-		
+<style>
+	.container {
+		/* padding: 10px 20px 20px 15px; */
+		font-size: 16px;
+		line-height: 24px;
+		background-image: url('../../static/video_bg.png');
+		width: 749rpx;
+		height: 1211rpx;
+		background-size: 100%;
+	}
+	.list-icon{
+		position: absolute;
+		margin-left: 32px;
+		margin-top: 253px;
+		width: 8rpx;
+		height: 18px;
+		opacity: 1;
+		border-radius: 33rpx;
+		background: #FFFFFF;
+	}
+	.title{
+		line-height: 19px;
+		position: absolute;
+		margin-left: 43px;
+		margin-top: 251px;
+		font-size: 19px;
+		font-family: Microsoft YaHei-3970(82674968);
+		font-weight: 400;
+		color: #FFFFFF;
+	}
+	.video{
+		position: absolute;
+		margin-left: 42px;
+		margin-top: 278px;
+		width: 283px;
+		height: 347rpx;
+	}
+	.jieshao{
+		position: absolute;
+		margin-left: 32px;
+		margin-top: 465px;
+		color: #FFFFFF;
 	}
 	}
 </style>
 </style>

BIN
static/indexbg.png


BIN
static/login-bg.png


BIN
static/loginout.png


BIN
static/share.png


BIN
static/video_bg.png


BIN
static/xiazai.png


+ 1 - 1
store/rsaKeys.js

@@ -20,7 +20,7 @@ MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMw5w8HTq7nIrJCw+N9VaJaBsQit3XiS
 // RSA公钥
 // RSA公钥
 const rsaPublicKey = `-----BEGIN PUBLIC KEY-----
 const rsaPublicKey = `-----BEGIN PUBLIC KEY-----
 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMOcPB06u5yKyQsPjfVWiWgbEIrd14kiXNNihciaVKb6HnkQvq7zpQuZ80WEX94spnUMI3iOAl/GmIvHrpGwcbB4hJbznm+PajiwnUSPuCCXA68YJF640cJKb/8KeM7WVz69OFkIEPHhVxOy4FFF5QWe/kt6zOZ19HmE+ak+5x/QIDAQAB
 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMOcPB06u5yKyQsPjfVWiWgbEIrd14kiXNNihciaVKb6HnkQvq7zpQuZ80WEX94spnUMI3iOAl/GmIvHrpGwcbB4hJbznm+PajiwnUSPuCCXA68YJF640cJKb/8KeM7WVz69OFkIEPHhVxOy4FFF5QWe/kt6zOZ19HmE+ak+5x/QIDAQAB
------END PUBLIC KEY-----`
+-----END PUBLIC KEY-----`
 
 
  
  
  
  

+ 268 - 268
uni_modules/uni-badge/components/uni-badge/uni-badge.vue

@@ -1,268 +1,268 @@
-<template>
-	<view class="uni-badge--x">
-		<slot />
-		<text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
-			class="uni-badge" @click="onClick()">{{displayValue}}</text>
-	</view>
-</template>
-
-<script>
-	/**
-	 * Badge 数字角标
-	 * @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=21
-	 * @property {String} text 角标内容
-	 * @property {String} size = [normal|small] 角标内容
-	 * @property {String} type = [info|primary|success|warning|error] 颜色类型
-	 * 	@value info 灰色
-	 * 	@value primary 蓝色
-	 * 	@value success 绿色
-	 * 	@value warning 黄色
-	 * 	@value error 红色
-	 * @property {String} inverted = [true|false] 是否无需背景颜色
-	 * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
-	 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上		
-	 * 	@value rightTop 右上
-	 * 	@value rightBottom 右下
-	 * 	@value leftTop 左上
-	 * 	@value leftBottom 左下
-	 * @property {Array[number]} offset	距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
-	 * @property {String} isDot = [true|false] 是否显示为一个小点
-	 * @event {Function} click 点击 Badge 触发事件
-	 * @example <uni-badge text="1"></uni-badge>
-	 */
-
-	export default {
-		name: 'UniBadge',
-		emits: ['click'],
-		props: {
-			type: {
-				type: String,
-				default: 'error'
-			},
-			inverted: {
-				type: Boolean,
-				default: false
-			},
-			isDot: {
-				type: Boolean,
-				default: false
-			},
-			maxNum: {
-				type: Number,
-				default: 99
-			},
-			absolute: {
-				type: String,
-				default: ''
-			},
-			offset: {
-				type: Array,
-				default () {
-					return [0, 0]
-				}
-			},
-			text: {
-				type: [String, Number],
-				default: ''
-			},
-			size: {
-				type: String,
-				default: 'small'
-			},
-			customStyle: {
-				type: Object,
-				default () {
-					return {}
-				}
-			}
-		},
-		data() {
-			return {};
-		},
-		computed: {
-			width() {
-				return String(this.text).length * 8 + 12
-			},
-			classNames() {
-				const {
-					inverted,
-					type,
-					size,
-					absolute
-				} = this
-				return [
-					inverted ? 'uni-badge--' + type + '-inverted' : '',
-					'uni-badge--' + type,
-					'uni-badge--' + size,
-					absolute ? 'uni-badge--absolute' : ''
-				].join(' ')
-			},
-			positionStyle() {
-				if (!this.absolute) return {}
-				let w = this.width / 2,
-					h = 10
-				if (this.isDot) {
-					w = 5
-					h = 5
-				}
-				const x = `${- w  + this.offset[0]}px`
-				const y = `${- h + this.offset[1]}px`
-
-				const whiteList = {
-					rightTop: {
-						right: x,
-						top: y
-					},
-					rightBottom: {
-						right: x,
-						bottom: y
-					},
-					leftBottom: {
-						left: x,
-						bottom: y
-					},
-					leftTop: {
-						left: x,
-						top: y
-					}
-				}
-				const match = whiteList[this.absolute]
-				return match ? match : whiteList['rightTop']
-			},
-			dotStyle() {
-				if (!this.isDot) return {}
-				return {
-					width: '10px',
-					minWidth: '0',
-					height: '10px',
-					padding: '0',
-					borderRadius: '10px'
-				}
-			},
-			displayValue() {
-				const {
-					isDot,
-					text,
-					maxNum
-				} = this
-				return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
-			}
-		},
-		methods: {
-			onClick() {
-				this.$emit('click');
-			}
-		}
-	};
-</script>
-
-<style lang="scss" >
-	$uni-primary: #2979ff !default;
-	$uni-success: #4cd964 !default;
-	$uni-warning: #f0ad4e !default;
-	$uni-error: #dd524d !default;
-	$uni-info: #909399 !default;
-
-
-	$bage-size: 12px;
-	$bage-small: scale(0.8);
-
-	.uni-badge--x {
-		/* #ifdef APP-NVUE */
-		// align-self: flex-start;
-		/* #endif */
-		/* #ifndef APP-NVUE */
-		display: inline-block;
-		/* #endif */
-		position: relative;
-	}
-
-	.uni-badge--absolute {
-		position: absolute;
-	}
-
-	.uni-badge--small {
-		transform: $bage-small;
-		transform-origin: center center;
-	}
-
-	.uni-badge {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		overflow: hidden;
-		box-sizing: border-box;
-		/* #endif */
-		justify-content: center;
-		flex-direction: row;
-		height: 20px;
-		min-width: 20px;
-		padding: 0 4px;
-		line-height: 18px;
-		color: #fff;
-		border-radius: 100px;
-		background-color: $uni-info;
-		background-color: transparent;
-		border: 1px solid #fff;
-		text-align: center;
-		font-family: 'Helvetica Neue', Helvetica, sans-serif;
-		font-feature-settings: "tnum";
-		font-size: $bage-size;
-		/* #ifdef H5 */
-		z-index: 999;
-		cursor: pointer;
-		/* #endif */
-
-		&--info {
-			color: #fff;
-			background-color: $uni-info;
-		}
-
-		&--primary {
-			background-color: $uni-primary;
-		}
-
-		&--success {
-			background-color: $uni-success;
-		}
-
-		&--warning {
-			background-color: $uni-warning;
-		}
-
-		&--error {
-			background-color: $uni-error;
-		}
-
-		&--inverted {
-			padding: 0 5px 0 0;
-			color: $uni-info;
-		}
-
-		&--info-inverted {
-			color: $uni-info;
-			background-color: transparent;
-		}
-
-		&--primary-inverted {
-			color: $uni-primary;
-			background-color: transparent;
-		}
-
-		&--success-inverted {
-			color: $uni-success;
-			background-color: transparent;
-		}
-
-		&--warning-inverted {
-			color: $uni-warning;
-			background-color: transparent;
-		}
-
-		&--error-inverted {
-			color: $uni-error;
-			background-color: transparent;
-		}
-
-	}
-</style>
+<template>
+	<view class="uni-badge--x">
+		<slot />
+		<text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
+			class="uni-badge" @click="onClick()">{{displayValue}}</text>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Badge 数字角标
+	 * @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=21
+	 * @property {String} text 角标内容
+	 * @property {String} size = [normal|small] 角标内容
+	 * @property {String} type = [info|primary|success|warning|error] 颜色类型
+	 * 	@value info 灰色
+	 * 	@value primary 蓝色
+	 * 	@value success 绿色
+	 * 	@value warning 黄色
+	 * 	@value error 红色
+	 * @property {String} inverted = [true|false] 是否无需背景颜色
+	 * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
+	 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上		
+	 * 	@value rightTop 右上
+	 * 	@value rightBottom 右下
+	 * 	@value leftTop 左上
+	 * 	@value leftBottom 左下
+	 * @property {Array[number]} offset	距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
+	 * @property {String} isDot = [true|false] 是否显示为一个小点
+	 * @event {Function} click 点击 Badge 触发事件
+	 * @example <uni-badge text="1"></uni-badge>
+	 */
+
+	export default {
+		name: 'UniBadge',
+		emits: ['click'],
+		props: {
+			type: {
+				type: String,
+				default: 'error'
+			},
+			inverted: {
+				type: Boolean,
+				default: false
+			},
+			isDot: {
+				type: Boolean,
+				default: false
+			},
+			maxNum: {
+				type: Number,
+				default: 99
+			},
+			absolute: {
+				type: String,
+				default: ''
+			},
+			offset: {
+				type: Array,
+				default () {
+					return [0, 0]
+				}
+			},
+			text: {
+				type: [String, Number],
+				default: ''
+			},
+			size: {
+				type: String,
+				default: 'small'
+			},
+			customStyle: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {};
+		},
+		computed: {
+			width() {
+				return String(this.text).length * 8 + 12
+			},
+			classNames() {
+				const {
+					inverted,
+					type,
+					size,
+					absolute
+				} = this
+				return [
+					inverted ? 'uni-badge--' + type + '-inverted' : '',
+					'uni-badge--' + type,
+					'uni-badge--' + size,
+					absolute ? 'uni-badge--absolute' : ''
+				].join(' ')
+			},
+			positionStyle() {
+				if (!this.absolute) return {}
+				let w = this.width / 2,
+					h = 10
+				if (this.isDot) {
+					w = 5
+					h = 5
+				}
+				const x = `${- w  + this.offset[0]}px`
+				const y = `${- h + this.offset[1]}px`
+
+				const whiteList = {
+					rightTop: {
+						right: x,
+						top: y
+					},
+					rightBottom: {
+						right: x,
+						bottom: y
+					},
+					leftBottom: {
+						left: x,
+						bottom: y
+					},
+					leftTop: {
+						left: x,
+						top: y
+					}
+				}
+				const match = whiteList[this.absolute]
+				return match ? match : whiteList['rightTop']
+			},
+			dotStyle() {
+				if (!this.isDot) return {}
+				return {
+					width: '10px',
+					minWidth: '0',
+					height: '10px',
+					padding: '0',
+					borderRadius: '10px'
+				}
+			},
+			displayValue() {
+				const {
+					isDot,
+					text,
+					maxNum
+				} = this
+				return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
+			}
+		},
+		methods: {
+			onClick() {
+				this.$emit('click');
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$uni-primary: #2979ff !default;
+	$uni-success: #4cd964 !default;
+	$uni-warning: #f0ad4e !default;
+	$uni-error: #dd524d !default;
+	$uni-info: #909399 !default;
+
+
+	$bage-size: 12px;
+	$bage-small: scale(0.8);
+
+	.uni-badge--x {
+		/* #ifdef APP-NVUE */
+		// align-self: flex-start;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: inline-block;
+		/* #endif */
+		position: relative;
+	}
+
+	.uni-badge--absolute {
+		position: absolute;
+	}
+
+	.uni-badge--small {
+		transform: $bage-small;
+		transform-origin: center center;
+	}
+
+	.uni-badge {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		overflow: hidden;
+		box-sizing: border-box;
+		/* #endif */
+		justify-content: center;
+		flex-direction: row;
+		height: 20px;
+		min-width: 20px;
+		padding: 0 4px;
+		line-height: 18px;
+		color: #fff;
+		border-radius: 100px;
+		background-color: $uni-info;
+		background-color: transparent;
+		border: 1px solid #fff;
+		text-align: center;
+		font-family: 'Helvetica Neue', Helvetica, sans-serif;
+		font-feature-settings: "tnum";
+		font-size: $bage-size;
+		/* #ifdef H5 */
+		z-index: 999;
+		cursor: pointer;
+		/* #endif */
+
+		&--info {
+			color: #fff;
+			background-color: $uni-info;
+		}
+
+		&--primary {
+			background-color: $uni-primary;
+		}
+
+		&--success {
+			background-color: $uni-success;
+		}
+
+		&--warning {
+			background-color: $uni-warning;
+		}
+
+		&--error {
+			background-color: $uni-error;
+		}
+
+		&--inverted {
+			padding: 0 5px 0 0;
+			color: $uni-info;
+		}
+
+		&--info-inverted {
+			color: $uni-info;
+			background-color: transparent;
+		}
+
+		&--primary-inverted {
+			color: $uni-primary;
+			background-color: transparent;
+		}
+
+		&--success-inverted {
+			color: $uni-success;
+			background-color: transparent;
+		}
+
+		&--warning-inverted {
+			color: $uni-warning;
+			background-color: transparent;
+		}
+
+		&--error-inverted {
+			color: $uni-error;
+			background-color: transparent;
+		}
+
+	}
+</style>

+ 2 - 2
uni_modules/uni-breadcrumb/changelog.md

@@ -2,5 +2,5 @@
 - 修复 微信小程序 separator 不显示问题
 - 修复 微信小程序 separator 不显示问题
 ## 0.1.1(2022-06-02)
 ## 0.1.1(2022-06-02)
 - 新增 支持 uni.scss 修改颜色
 - 新增 支持 uni.scss 修改颜色
-## 0.1.0(2022-04-21)
-- 初始化
+## 0.1.0(2022-04-21)
+- 初始化

+ 120 - 120
uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue

@@ -1,121 +1,121 @@
-<template>
-	<view class="uni-breadcrumb-item">
-		<view :class="{
-			'uni-breadcrumb-item--slot': true,
-			'uni-breadcrumb-item--slot-link': to && currentPage !== to
-			}" @click="navTo">
-			<slot />
-		</view>
-		<i v-if="separatorClass" class="uni-breadcrumb-item--separator" :class="separatorClass" />
-		<text v-else class="uni-breadcrumb-item--separator">{{ separator }}</text>
-	</view>
-</template>
-<script>
-	/**
-	 * BreadcrumbItem 面包屑导航子组件
-	 * @property {String/Object} to 路由跳转页面路径/对象
-	 * @property {Boolean} replace 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持)
-	 */
-	export default {
-		data() {
-			return {
-				currentPage: ""
-			}
-		},
-		options: {
-			virtualHost: true
-		},
-		props: {
-			to: {
-				type: String,
-				default: ''
-			},
-			replace:{
-				type: Boolean,
-				default: false
-			}
-		},
-		inject: {
-			uniBreadcrumb: {
-				from: "uniBreadcrumb",
-				default: null
-			}
-		},
-		created(){
-			const pages = getCurrentPages()
-			const page = pages[pages.length-1]
-
-			if(page){
-				this.currentPage = `/${page.route}`
-			}
-		},
-		computed: {
-			separator() {
-				return this.uniBreadcrumb.separator
-			},
-			separatorClass() {
-				return this.uniBreadcrumb.separatorClass
-			}
-		},
-		methods: {
-			navTo() {
-				const { to } = this
-
-				if (!to || this.currentPage === to){
-					return
-				}
-
-				if(this.replace){
-					uni.redirectTo({
-						url:to
-					})
-				}else{
-					uni.navigateTo({
-						url:to
-					})
-				}
-			}
+<template>
+	<view class="uni-breadcrumb-item">
+		<view :class="{
+			'uni-breadcrumb-item--slot': true,
+			'uni-breadcrumb-item--slot-link': to && currentPage !== to
+			}" @click="navTo">
+			<slot />
+		</view>
+		<i v-if="separatorClass" class="uni-breadcrumb-item--separator" :class="separatorClass" />
+		<text v-else class="uni-breadcrumb-item--separator">{{ separator }}</text>
+	</view>
+</template>
+<script>
+	/**
+	 * BreadcrumbItem 面包屑导航子组件
+	 * @property {String/Object} to 路由跳转页面路径/对象
+	 * @property {Boolean} replace 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持)
+	 */
+	export default {
+		data() {
+			return {
+				currentPage: ""
+			}
+		},
+		options: {
+			virtualHost: true
+		},
+		props: {
+			to: {
+				type: String,
+				default: ''
+			},
+			replace:{
+				type: Boolean,
+				default: false
+			}
+		},
+		inject: {
+			uniBreadcrumb: {
+				from: "uniBreadcrumb",
+				default: null
+			}
+		},
+		created(){
+			const pages = getCurrentPages()
+			const page = pages[pages.length-1]
+
+			if(page){
+				this.currentPage = `/${page.route}`
+			}
+		},
+		computed: {
+			separator() {
+				return this.uniBreadcrumb.separator
+			},
+			separatorClass() {
+				return this.uniBreadcrumb.separatorClass
+			}
+		},
+		methods: {
+			navTo() {
+				const { to } = this
+
+				if (!to || this.currentPage === to){
+					return
+				}
+
+				if(this.replace){
+					uni.redirectTo({
+						url:to
+					})
+				}else{
+					uni.navigateTo({
+						url:to
+					})
+				}
+			}
+		}
+	}
+</script>
+<style lang="scss">
+	$uni-primary: #2979ff !default;
+	$uni-base-color: #6a6a6a !default;
+	$uni-main-color: #3a3a3a !default;
+	.uni-breadcrumb-item {
+		display: flex;
+		align-items: center;
+		white-space: nowrap;
+		font-size: 14px;
+
+		&--slot {
+			color: $uni-base-color;
+			padding: 0 10px;
+
+			&-link {
+				color: $uni-main-color;
+				font-weight: bold;
+				/* #ifndef APP-NVUE */
+				cursor: pointer;
+				/* #endif */
+
+				&:hover {
+					color: $uni-primary;
+				}
+			}
+		}
+
+		&--separator {
+			font-size: 12px;
+			color: $uni-base-color;
+		}
+
+		&:first-child &--slot {
+			padding-left: 0;
 		}
 		}
-	}
-</script>
-<style lang="scss">
-	$uni-primary: #2979ff !default;
-	$uni-base-color: #6a6a6a !default;
-	$uni-main-color: #3a3a3a !default;
-	.uni-breadcrumb-item {
-		display: flex;
-		align-items: center;
-		white-space: nowrap;
-		font-size: 14px;
-
-		&--slot {
-			color: $uni-base-color;
-			padding: 0 10px;
-
-			&-link {
-				color: $uni-main-color;
-				font-weight: bold;
-				/* #ifndef APP-NVUE */
-				cursor: pointer;
-				/* #endif */
-
-				&:hover {
-					color: $uni-primary;
-				}
-			}
-		}
-
-		&--separator {
-			font-size: 12px;
-			color: $uni-base-color;
-		}
-
-		&:first-child &--slot {
-			padding-left: 0;
-		}
-		
-		&:last-child &--separator {
-			display: none;
-		}
-	}
-</style>
+		
+		&:last-child &--separator {
+			display: none;
+		}
+	}
+</style>

+ 29 - 29
uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue

@@ -1,8 +1,8 @@
-<template>
-	<view class="uni-breadcrumb">
-		<slot />
-	</view>
-</template>
+<template>
+	<view class="uni-breadcrumb">
+		<slot />
+	</view>
+</template>
 <script>
 <script>
 	/**
 	/**
 	 * Breadcrumb 面包屑导航父组件
 	 * Breadcrumb 面包屑导航父组件
@@ -10,32 +10,32 @@
 	 * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
 	 * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
 	 * @property {String} separator 分隔符,默认为斜杠'/'
 	 * @property {String} separator 分隔符,默认为斜杠'/'
 	 * @property {String} separatorClass 图标分隔符 class
 	 * @property {String} separatorClass 图标分隔符 class
-	 */
+	 */
 	export default {
 	export default {
 		options: {
 		options: {
 			virtualHost: true
 			virtualHost: true
-		},
-		props: {
-			separator: {
-				type: String,
-				default: '/'
-			},
-			separatorClass: {
-				type: String,
-				default: ''
-			}
-		},
-
-		provide() {
-			return {
-				uniBreadcrumb: this
-			}
-		}
-
-	}
-</script>
-<style lang="scss">
-	.uni-breadcrumb {
+		},
+		props: {
+			separator: {
+				type: String,
+				default: '/'
+			},
+			separatorClass: {
+				type: String,
+				default: ''
+			}
+		},
+
+		provide() {
+			return {
+				uniBreadcrumb: this
+			}
+		}
+
+	}
+</script>
+<style lang="scss">
+	.uni-breadcrumb {
 		display: flex;
 		display: flex;
-	}
+	}
 </style>
 </style>

+ 8 - 8
uni_modules/uni-breadcrumb/readme.md

@@ -16,16 +16,16 @@
 在 ``template`` 中使用组件
 在 ``template`` 中使用组件
 
 
 ```html
 ```html
-<uni-breadcrumb separator="/">
+<uni-breadcrumb separator="/">
 	<uni-breadcrumb-item v-for="(route,index) in routes" :key="index" :to="route.to">{{route.name}}</uni-breadcrumb-item>
 	<uni-breadcrumb-item v-for="(route,index) in routes" :key="index" :to="route.to">{{route.name}}</uni-breadcrumb-item>
 </uni-breadcrumb>
 </uni-breadcrumb>
 ```
 ```
 
 
 ```js
 ```js
-export default {
-		name: "uni-stat-breadcrumb",
-		data() {
-			return {
+export default {
+		name: "uni-stat-breadcrumb",
+		data() {
+			return {
 				routes: [{
 				routes: [{
 					to: '/A',
 					to: '/A',
 					name: 'A页面'
 					name: 'A页面'
@@ -35,9 +35,9 @@ export default {
 				}, {
 				}, {
 					to: '/C',
 					to: '/C',
 					name: 'C页面'
 					name: 'C页面'
-				}]
-			};
-		}
+				}]
+			};
+		}
 	}
 	}
 ```
 ```
 
 

+ 11 - 11
uni_modules/uni-calendar/components/uni-calendar/i18n/en.json

@@ -1,12 +1,12 @@
-{
-	"uni-calender.ok": "ok",
-	"uni-calender.cancel": "cancel",
-	"uni-calender.today": "today",
-	"uni-calender.MON": "MON",
-	"uni-calender.TUE": "TUE",
-	"uni-calender.WED": "WED",
-	"uni-calender.THU": "THU",
-	"uni-calender.FRI": "FRI",
-	"uni-calender.SAT": "SAT",
-	"uni-calender.SUN": "SUN"
+{
+	"uni-calender.ok": "ok",
+	"uni-calender.cancel": "cancel",
+	"uni-calender.today": "today",
+	"uni-calender.MON": "MON",
+	"uni-calender.TUE": "TUE",
+	"uni-calender.WED": "WED",
+	"uni-calender.THU": "THU",
+	"uni-calender.FRI": "FRI",
+	"uni-calender.SAT": "SAT",
+	"uni-calender.SUN": "SUN"
 }
 }

+ 7 - 7
uni_modules/uni-calendar/components/uni-calendar/i18n/index.js

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

+ 11 - 11
uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json

@@ -1,12 +1,12 @@
-{
-	"uni-calender.ok": "确定",
-	"uni-calender.cancel": "取消",
-	"uni-calender.today": "今日",
-	"uni-calender.SUN": "日",
-	"uni-calender.MON": "一",
-	"uni-calender.TUE": "二",
-	"uni-calender.WED": "三",
-	"uni-calender.THU": "四",
-	"uni-calender.FRI": "五",
-	"uni-calender.SAT": "六"
+{
+	"uni-calender.ok": "确定",
+	"uni-calender.cancel": "取消",
+	"uni-calender.today": "今日",
+	"uni-calender.SUN": "日",
+	"uni-calender.MON": "一",
+	"uni-calender.TUE": "二",
+	"uni-calender.WED": "三",
+	"uni-calender.THU": "四",
+	"uni-calender.FRI": "五",
+	"uni-calender.SAT": "六"
 }
 }

+ 5 - 5
uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json

@@ -1,12 +1,12 @@
-{
-	"uni-calender.ok": "確定",
-	"uni-calender.cancel": "取消",
-	"uni-calender.today": "今日",
+{
+	"uni-calender.ok": "確定",
+	"uni-calender.cancel": "取消",
+	"uni-calender.today": "今日",
 	"uni-calender.SUN": "日",
 	"uni-calender.SUN": "日",
 	"uni-calender.MON": "一",
 	"uni-calender.MON": "一",
 	"uni-calender.TUE": "二",
 	"uni-calender.TUE": "二",
 	"uni-calender.WED": "三",
 	"uni-calender.WED": "三",
 	"uni-calender.THU": "四",
 	"uni-calender.THU": "四",
 	"uni-calender.FRI": "五",
 	"uni-calender.FRI": "五",
-	"uni-calender.SAT": "六"
+	"uni-calender.SAT": "六"
 }
 }

+ 188 - 188
uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue

@@ -1,188 +1,188 @@
-<template>
-	<view class="uni-calendar-item__weeks-box" :class="{
-		'uni-calendar-item--disable':weeks.disable,
-		'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
-		'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
-		'uni-calendar-item--before-checked':weeks.beforeMultiple,
-		'uni-calendar-item--multiple': weeks.multiple,
-		'uni-calendar-item--after-checked':weeks.afterMultiple,
-		}"
-	 @click="choiceDate(weeks)">
-		<view class="uni-calendar-item__weeks-box-item">
-			<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
-			<text class="uni-calendar-item__weeks-box-text" :class="{
-				'uni-calendar-item--isDay-text': weeks.isDay,
-				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
-				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
-				'uni-calendar-item--before-checked':weeks.beforeMultiple,
-				'uni-calendar-item--multiple': weeks.multiple,
-				'uni-calendar-item--after-checked':weeks.afterMultiple,
-				'uni-calendar-item--disable':weeks.disable,
-				}">{{weeks.date}}</text>
-			<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
-				'uni-calendar-item--isDay-text':weeks.isDay,
-				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
-				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
-				'uni-calendar-item--before-checked':weeks.beforeMultiple,
-				'uni-calendar-item--multiple': weeks.multiple,
-				'uni-calendar-item--after-checked':weeks.afterMultiple,
-				}">{{todayText}}</text>
-			<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
-				'uni-calendar-item--isDay-text':weeks.isDay,
-				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
-				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
-				'uni-calendar-item--before-checked':weeks.beforeMultiple,
-				'uni-calendar-item--multiple': weeks.multiple,
-				'uni-calendar-item--after-checked':weeks.afterMultiple,
-				'uni-calendar-item--disable':weeks.disable,
-				}">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
-			<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
-				'uni-calendar-item--extra':weeks.extraInfo.info,
-				'uni-calendar-item--isDay-text':weeks.isDay,
-				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
-				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
-				'uni-calendar-item--before-checked':weeks.beforeMultiple,
-				'uni-calendar-item--multiple': weeks.multiple,
-				'uni-calendar-item--after-checked':weeks.afterMultiple,
-				'uni-calendar-item--disable':weeks.disable,
-				}">{{weeks.extraInfo.info}}</text>
-		</view>
-	</view>
-</template>
-
-<script>
-	import {
-	initVueI18n
-	} from '@dcloudio/uni-i18n'
-	import messages from './i18n/index.js'
-	const {	t	} = initVueI18n(messages)
-	export default {
-		emits:['change'],
-		props: {
-			weeks: {
-				type: Object,
-				default () {
-					return {}
-				}
-			},
-			calendar: {
-				type: Object,
-				default: () => {
-					return {}
-				}
-			},
-			selected: {
-				type: Array,
-				default: () => {
-					return []
-				}
-			},
-			lunar: {
-				type: Boolean,
-				default: false
-			}
-		},
-		computed: {
-			todayText() {
-				return t("uni-calender.today")
-			},
-		},
-		methods: {
-			choiceDate(weeks) {
-				this.$emit('change', weeks)
-			}
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	$uni-font-size-base:14px;
-	$uni-text-color:#333;
-	$uni-font-size-sm:12px;
-	$uni-color-error: #e43d33;
-	$uni-opacity-disabled: 0.3;
-	$uni-text-color-disable:#c0c0c0;
-	$uni-primary: #2979ff !default;
-	.uni-calendar-item__weeks-box {
-		flex: 1;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: column;
-		justify-content: center;
-		align-items: center;
-	}
-
-	.uni-calendar-item__weeks-box-text {
-		font-size: $uni-font-size-base;
-		color: $uni-text-color;
-	}
-
-	.uni-calendar-item__weeks-lunar-text {
-		font-size: $uni-font-size-sm;
-		color: $uni-text-color;
-	}
-
-	.uni-calendar-item__weeks-box-item {
-		position: relative;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: column;
-		justify-content: center;
-		align-items: center;
-		width: 100rpx;
-		height: 100rpx;
-	}
-
-	.uni-calendar-item__weeks-box-circle {
-		position: absolute;
-		top: 5px;
-		right: 5px;
-		width: 8px;
-		height: 8px;
-		border-radius: 8px;
-		background-color: $uni-color-error;
-
-	}
-
-	.uni-calendar-item--disable {
-		background-color: rgba(249, 249, 249, $uni-opacity-disabled);
-		color: $uni-text-color-disable;
-	}
-
-	.uni-calendar-item--isDay-text {
-		color: $uni-primary;
-	}
-
-	.uni-calendar-item--isDay {
-		background-color: $uni-primary;
-		opacity: 0.8;
-		color: #fff;
-	}
-
-	.uni-calendar-item--extra {
-		color: $uni-color-error;
-		opacity: 0.8;
-	}
-
-	.uni-calendar-item--checked {
-		background-color: $uni-primary;
-		color: #fff;
-		opacity: 0.8;
-	}
-
-	.uni-calendar-item--multiple {
-		background-color: $uni-primary;
-		color: #fff;
-		opacity: 0.8;
-	}
-	.uni-calendar-item--before-checked {
-		background-color: #ff5a5f;
-		color: #fff;
-	}
-	.uni-calendar-item--after-checked {
-		background-color: #ff5a5f;
-		color: #fff;
-	}
-</style>
+<template>
+	<view class="uni-calendar-item__weeks-box" :class="{
+		'uni-calendar-item--disable':weeks.disable,
+		'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+		'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
+		'uni-calendar-item--before-checked':weeks.beforeMultiple,
+		'uni-calendar-item--multiple': weeks.multiple,
+		'uni-calendar-item--after-checked':weeks.afterMultiple,
+		}"
+	 @click="choiceDate(weeks)">
+		<view class="uni-calendar-item__weeks-box-item">
+			<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
+			<text class="uni-calendar-item__weeks-box-text" :class="{
+				'uni-calendar-item--isDay-text': weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">{{weeks.date}}</text>
+			<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
+				'uni-calendar-item--isDay-text':weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				}">{{todayText}}</text>
+			<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
+				'uni-calendar-item--isDay-text':weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
+			<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
+				'uni-calendar-item--extra':weeks.extraInfo.info,
+				'uni-calendar-item--isDay-text':weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">{{weeks.extraInfo.info}}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+	initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	export default {
+		emits:['change'],
+		props: {
+			weeks: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			calendar: {
+				type: Object,
+				default: () => {
+					return {}
+				}
+			},
+			selected: {
+				type: Array,
+				default: () => {
+					return []
+				}
+			},
+			lunar: {
+				type: Boolean,
+				default: false
+			}
+		},
+		computed: {
+			todayText() {
+				return t("uni-calender.today")
+			},
+		},
+		methods: {
+			choiceDate(weeks) {
+				this.$emit('change', weeks)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	$uni-font-size-base:14px;
+	$uni-text-color:#333;
+	$uni-font-size-sm:12px;
+	$uni-color-error: #e43d33;
+	$uni-opacity-disabled: 0.3;
+	$uni-text-color-disable:#c0c0c0;
+	$uni-primary: #2979ff !default;
+	.uni-calendar-item__weeks-box {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-calendar-item__weeks-box-text {
+		font-size: $uni-font-size-base;
+		color: $uni-text-color;
+	}
+
+	.uni-calendar-item__weeks-lunar-text {
+		font-size: $uni-font-size-sm;
+		color: $uni-text-color;
+	}
+
+	.uni-calendar-item__weeks-box-item {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		width: 100rpx;
+		height: 100rpx;
+	}
+
+	.uni-calendar-item__weeks-box-circle {
+		position: absolute;
+		top: 5px;
+		right: 5px;
+		width: 8px;
+		height: 8px;
+		border-radius: 8px;
+		background-color: $uni-color-error;
+
+	}
+
+	.uni-calendar-item--disable {
+		background-color: rgba(249, 249, 249, $uni-opacity-disabled);
+		color: $uni-text-color-disable;
+	}
+
+	.uni-calendar-item--isDay-text {
+		color: $uni-primary;
+	}
+
+	.uni-calendar-item--isDay {
+		background-color: $uni-primary;
+		opacity: 0.8;
+		color: #fff;
+	}
+
+	.uni-calendar-item--extra {
+		color: $uni-color-error;
+		opacity: 0.8;
+	}
+
+	.uni-calendar-item--checked {
+		background-color: $uni-primary;
+		color: #fff;
+		opacity: 0.8;
+	}
+
+	.uni-calendar-item--multiple {
+		background-color: $uni-primary;
+		color: #fff;
+		opacity: 0.8;
+	}
+	.uni-calendar-item--before-checked {
+		background-color: #ff5a5f;
+		color: #fff;
+	}
+	.uni-calendar-item--after-checked {
+		background-color: #ff5a5f;
+		color: #fff;
+	}
+</style>

File diff suppressed because it is too large
+ 562 - 562
uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue


+ 350 - 350
uni_modules/uni-calendar/components/uni-calendar/util.js

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

+ 254 - 254
uni_modules/uni-card/components/uni-card/uni-card.vue

@@ -1,270 +1,270 @@
-<template>
-	<view class="uni-card" :class="{ 'uni-card--full': isFull, 'uni-card--shadow': isShadow,'uni-card--border':border}"
+<template>
+	<view class="uni-card" :class="{ 'uni-card--full': isFull, 'uni-card--shadow': isShadow,'uni-card--border':border}"
 		:style="{'margin':isFull?0:margin,'padding':spacing,'box-shadow':isShadow?shadow:''}">
 		:style="{'margin':isFull?0:margin,'padding':spacing,'box-shadow':isShadow?shadow:''}">
-		<!-- 封面 -->
-		<slot name="cover">
-			<view v-if="cover" class="uni-card__cover">
-				<image class="uni-card__cover-image" mode="widthFix" @click="onClick('cover')" :src="cover"></image>
-			</view>
-		</slot>
-		<slot name="title">
-			<view v-if="title || extra" class="uni-card__header">
-				<!-- 卡片标题 -->
-				<view class="uni-card__header-box" @click="onClick('title')">
-					<view v-if="thumbnail" class="uni-card__header-avatar">
-						<image class="uni-card__header-avatar-image" :src="thumbnail" mode="aspectFit" />
-					</view>
-					<view class="uni-card__header-content">
-						<text class="uni-card__header-content-title uni-ellipsis">{{ title }}</text>
-						<text v-if="title&&subTitle"
-							class="uni-card__header-content-subtitle uni-ellipsis">{{ subTitle }}</text>
-					</view>
-				</view>
-				<view class="uni-card__header-extra" @click="onClick('extra')">
-					<text class="uni-card__header-extra-text">{{ extra }}</text>
-				</view>
-			</view>
-		</slot>
-		<!-- 卡片内容 -->
-		<view class="uni-card__content" :style="{padding:padding}" @click="onClick('content')">
-			<slot></slot>
-		</view>
-		<view class="uni-card__actions" @click="onClick('actions')">
-			<slot name="actions"></slot>
-		</view>
-	</view>
-</template>
-
-<script>
-	/**
-	 * Card 卡片
-	 * @description 卡片视图组件
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=22
-	 * @property {String} title 标题文字
-	 * @property {String} subTitle 副标题
-	 * @property {Number} padding 内容内边距
-	 * @property {Number} margin 卡片外边距
-	 * @property {Number} spacing 卡片内边距
-	 * @property {String} extra 标题额外信息
-	 * @property {String} cover 封面图(本地路径需要引入)
-	 * @property {String} thumbnail 标题左侧缩略图
-	 * @property {Boolean} is-full = [true | false] 卡片内容是否通栏,为 true 时将去除padding值
-	 * @property {Boolean} is-shadow = [true | false] 卡片内容是否开启阴影
-	 * @property {String} shadow 卡片阴影
-	 * @property {Boolean} border 卡片边框
-	 * @event {Function} click 点击 Card 触发事件
-	 */
-	export default {
-		name: 'UniCard',
-		emits: ['click'],
-		props: {
-			title: {
-				type: String,
-				default: ''
-			},
-			subTitle: {
-				type: String,
-				default: ''
-			},
-			padding: {
-				type: String,
-				default: '10px'
-			},
-			margin: {
-				type: String,
-				default: '15px'
-			},
-			spacing: {
-				type: String,
-				default: '0 10px'
-			},
-			extra: {
-				type: String,
-				default: ''
-			},
-			cover: {
-				type: String,
-				default: ''
-			},
-			thumbnail: {
-				type: String,
-				default: ''
-			},
-			isFull: {
-				// 内容区域是否通栏
-				type: Boolean,
-				default: false
-			},
-			isShadow: {
-				// 是否开启阴影
-				type: Boolean,
-				default: true
-			},
-			shadow: {
-				type: String,
-				default: '0px 0px 3px 1px rgba(0, 0, 0, 0.08)'
-			},
-			border: {
-				type: Boolean,
-				default: true
-			}
-		},
-		methods: {
-			onClick(type) {
-				this.$emit('click', type)
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
-	$uni-border-3: #EBEEF5 !default;
-	$uni-shadow-base:0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
-	$uni-main-color: #3a3a3a !default;
-	$uni-base-color: #6a6a6a !default;
-	$uni-secondary-color: #909399 !default;
-	$uni-spacing-sm: 8px !default;
-	$uni-border-color:$uni-border-3;
-	$uni-shadow: $uni-shadow-base;
-	$uni-card-title: 15px;
-	$uni-cart-title-color:$uni-main-color;
-	$uni-card-subtitle: 12px;
-	$uni-cart-subtitle-color:$uni-secondary-color;
-	$uni-card-spacing: 10px;
-	$uni-card-content-color: $uni-base-color;
-
-	.uni-card {
-		margin: $uni-card-spacing;
-		padding: 0 $uni-spacing-sm;
-		border-radius: 4px;
-		overflow: hidden;
-		font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
-		background-color: #fff;
-		flex: 1;
-
-		.uni-card__cover {
-			position: relative;
+		<!-- 封面 -->
+		<slot name="cover">
+			<view v-if="cover" class="uni-card__cover">
+				<image class="uni-card__cover-image" mode="widthFix" @click="onClick('cover')" :src="cover"></image>
+			</view>
+		</slot>
+		<slot name="title">
+			<view v-if="title || extra" class="uni-card__header">
+				<!-- 卡片标题 -->
+				<view class="uni-card__header-box" @click="onClick('title')">
+					<view v-if="thumbnail" class="uni-card__header-avatar">
+						<image class="uni-card__header-avatar-image" :src="thumbnail" mode="aspectFit" />
+					</view>
+					<view class="uni-card__header-content">
+						<text class="uni-card__header-content-title uni-ellipsis">{{ title }}</text>
+						<text v-if="title&&subTitle"
+							class="uni-card__header-content-subtitle uni-ellipsis">{{ subTitle }}</text>
+					</view>
+				</view>
+				<view class="uni-card__header-extra" @click="onClick('extra')">
+					<text class="uni-card__header-extra-text">{{ extra }}</text>
+				</view>
+			</view>
+		</slot>
+		<!-- 卡片内容 -->
+		<view class="uni-card__content" :style="{padding:padding}" @click="onClick('content')">
+			<slot></slot>
+		</view>
+		<view class="uni-card__actions" @click="onClick('actions')">
+			<slot name="actions"></slot>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Card 卡片
+	 * @description 卡片视图组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=22
+	 * @property {String} title 标题文字
+	 * @property {String} subTitle 副标题
+	 * @property {Number} padding 内容内边距
+	 * @property {Number} margin 卡片外边距
+	 * @property {Number} spacing 卡片内边距
+	 * @property {String} extra 标题额外信息
+	 * @property {String} cover 封面图(本地路径需要引入)
+	 * @property {String} thumbnail 标题左侧缩略图
+	 * @property {Boolean} is-full = [true | false] 卡片内容是否通栏,为 true 时将去除padding值
+	 * @property {Boolean} is-shadow = [true | false] 卡片内容是否开启阴影
+	 * @property {String} shadow 卡片阴影
+	 * @property {Boolean} border 卡片边框
+	 * @event {Function} click 点击 Card 触发事件
+	 */
+	export default {
+		name: 'UniCard',
+		emits: ['click'],
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			subTitle: {
+				type: String,
+				default: ''
+			},
+			padding: {
+				type: String,
+				default: '10px'
+			},
+			margin: {
+				type: String,
+				default: '15px'
+			},
+			spacing: {
+				type: String,
+				default: '0 10px'
+			},
+			extra: {
+				type: String,
+				default: ''
+			},
+			cover: {
+				type: String,
+				default: ''
+			},
+			thumbnail: {
+				type: String,
+				default: ''
+			},
+			isFull: {
+				// 内容区域是否通栏
+				type: Boolean,
+				default: false
+			},
+			isShadow: {
+				// 是否开启阴影
+				type: Boolean,
+				default: true
+			},
+			shadow: {
+				type: String,
+				default: '0px 0px 3px 1px rgba(0, 0, 0, 0.08)'
+			},
+			border: {
+				type: Boolean,
+				default: true
+			}
+		},
+		methods: {
+			onClick(type) {
+				this.$emit('click', type)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$uni-border-3: #EBEEF5 !default;
+	$uni-shadow-base:0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
+	$uni-main-color: #3a3a3a !default;
+	$uni-base-color: #6a6a6a !default;
+	$uni-secondary-color: #909399 !default;
+	$uni-spacing-sm: 8px !default;
+	$uni-border-color:$uni-border-3;
+	$uni-shadow: $uni-shadow-base;
+	$uni-card-title: 15px;
+	$uni-cart-title-color:$uni-main-color;
+	$uni-card-subtitle: 12px;
+	$uni-cart-subtitle-color:$uni-secondary-color;
+	$uni-card-spacing: 10px;
+	$uni-card-content-color: $uni-base-color;
+
+	.uni-card {
+		margin: $uni-card-spacing;
+		padding: 0 $uni-spacing-sm;
+		border-radius: 4px;
+		overflow: hidden;
+		font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
+		background-color: #fff;
+		flex: 1;
+
+		.uni-card__cover {
+			position: relative;
 			margin-top: $uni-card-spacing;
 			margin-top: $uni-card-spacing;
-			flex-direction: row;
-			overflow: hidden;
+			flex-direction: row;
+			overflow: hidden;
 			border-radius: 4px;
 			border-radius: 4px;
 			.uni-card__cover-image {
 			.uni-card__cover-image {
-				flex: 1;
+				flex: 1;
 				// width: 100%;
 				// width: 100%;
 				/* #ifndef APP-PLUS */
 				/* #ifndef APP-PLUS */
 				vertical-align: middle;
 				vertical-align: middle;
 				/* #endif */
 				/* #endif */
-			}
-		}
-
-		.uni-card__header {
-			display: flex;
+			}
+		}
+
+		.uni-card__header {
+			display: flex;
 			border-bottom: 1px $uni-border-color solid;
 			border-bottom: 1px $uni-border-color solid;
-			flex-direction: row;
-			align-items: center;
-			padding: $uni-card-spacing;
-			overflow: hidden;
-
-			.uni-card__header-box {
-				/* #ifndef APP-NVUE */
-				display: flex;
-				/* #endif */
-				flex: 1;
-				flex-direction: row;
-				align-items: center;
-				overflow: hidden;
-			}
-
-			.uni-card__header-avatar {
-				width: 40px;
-				height: 40px;
-				overflow: hidden;
-				border-radius: 5px;
-				margin-right: $uni-card-spacing;
+			flex-direction: row;
+			align-items: center;
+			padding: $uni-card-spacing;
+			overflow: hidden;
+
+			.uni-card__header-box {
+				/* #ifndef APP-NVUE */
+				display: flex;
+				/* #endif */
+				flex: 1;
+				flex-direction: row;
+				align-items: center;
+				overflow: hidden;
+			}
+
+			.uni-card__header-avatar {
+				width: 40px;
+				height: 40px;
+				overflow: hidden;
+				border-radius: 5px;
+				margin-right: $uni-card-spacing;
 				.uni-card__header-avatar-image {
 				.uni-card__header-avatar-image {
-					flex: 1;
+					flex: 1;
 					width: 40px;
 					width: 40px;
-					height: 40px;
-				}
-			}
-
-			.uni-card__header-content {
-				/* #ifndef APP-NVUE */
-				display: flex;
-				/* #endif */
-				flex-direction: column;
-				justify-content: center;
-				flex: 1;
-				// height: 40px;
-				overflow: hidden;
-
-				.uni-card__header-content-title {
-					font-size: $uni-card-title;
-					color: $uni-cart-title-color;
-					// line-height: 22px;
-				}
-
-				.uni-card__header-content-subtitle {
-					font-size: $uni-card-subtitle;
-					margin-top: 5px;
-					color: $uni-cart-subtitle-color;
-				}
-			}
-
-			.uni-card__header-extra {
-				line-height: 12px;
-
-				.uni-card__header-extra-text {
-					font-size: 12px;
-					color: $uni-cart-subtitle-color;
-				}
-			}
-		}
-
-		.uni-card__content {
-			padding: $uni-card-spacing;
-			font-size: 14px;
-			color: $uni-card-content-color;
-			line-height: 22px;
-		}
-
-		.uni-card__actions {
-			font-size: 12px;
-		}
-	}
+					height: 40px;
+				}
+			}
+
+			.uni-card__header-content {
+				/* #ifndef APP-NVUE */
+				display: flex;
+				/* #endif */
+				flex-direction: column;
+				justify-content: center;
+				flex: 1;
+				// height: 40px;
+				overflow: hidden;
+
+				.uni-card__header-content-title {
+					font-size: $uni-card-title;
+					color: $uni-cart-title-color;
+					// line-height: 22px;
+				}
+
+				.uni-card__header-content-subtitle {
+					font-size: $uni-card-subtitle;
+					margin-top: 5px;
+					color: $uni-cart-subtitle-color;
+				}
+			}
+
+			.uni-card__header-extra {
+				line-height: 12px;
+
+				.uni-card__header-extra-text {
+					font-size: 12px;
+					color: $uni-cart-subtitle-color;
+				}
+			}
+		}
+
+		.uni-card__content {
+			padding: $uni-card-spacing;
+			font-size: 14px;
+			color: $uni-card-content-color;
+			line-height: 22px;
+		}
+
+		.uni-card__actions {
+			font-size: 12px;
+		}
+	}
 
 
 	.uni-card--border {
 	.uni-card--border {
 		border: 1px solid $uni-border-color;
 		border: 1px solid $uni-border-color;
 	}
 	}
-
-	.uni-card--shadow {
-		position: relative;
-		/* #ifndef APP-NVUE */
-		box-shadow: $uni-shadow;
-		/* #endif */
-	}
-
-	.uni-card--full {
-		margin: 0;
-		border-left-width: 0;
-		border-left-width: 0;
-		border-radius: 0;
-	}
-
-	/* #ifndef APP-NVUE */
-	.uni-card--full:after {
-		border-radius: 0;
-	}
-
-	/* #endif */
-	.uni-ellipsis {
-		/* #ifndef APP-NVUE */
-		overflow: hidden;
-		white-space: nowrap;
-		text-overflow: ellipsis;
-		/* #endif */
-		/* #ifdef APP-NVUE */
-		lines: 1;
-		/* #endif */
-	}
+
+	.uni-card--shadow {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		box-shadow: $uni-shadow;
+		/* #endif */
+	}
+
+	.uni-card--full {
+		margin: 0;
+		border-left-width: 0;
+		border-left-width: 0;
+		border-radius: 0;
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-card--full:after {
+		border-radius: 0;
+	}
+
+	/* #endif */
+	.uni-ellipsis {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		/* #endif */
+	}
 </style>
 </style>

+ 401 - 401
uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue

@@ -1,402 +1,402 @@
-<template>
-	<view class="uni-collapse-item">
-		<!-- onClick(!isOpen) -->
-		<view @click="onClick(!isOpen)" class="uni-collapse-item__title"
-			:class="{'is-open':isOpen &&titleBorder === 'auto' ,'uni-collapse-item-border':titleBorder !== 'none'}">
-			<view class="uni-collapse-item__title-wrap">
-				<slot name="title">
-					<view class="uni-collapse-item__title-box" :class="{'is-disabled':disabled}">
-						<image v-if="thumb" :src="thumb" class="uni-collapse-item__title-img" />
-						<text class="uni-collapse-item__title-text">{{ title }}</text>
-					</view>
-				</slot>
-			</view>
-			<view v-if="showArrow"
-				:class="{ 'uni-collapse-item__title-arrow-active': isOpen, 'uni-collapse-item--animation': showAnimation === true }"
-				class="uni-collapse-item__title-arrow">
-				<uni-icons :color="disabled?'#ddd':'#bbb'" size="14" type="bottom" />
-			</view>
-		</view>
-		<view class="uni-collapse-item__wrap" :class="{'is--transition':showAnimation}"
-			:style="{height: (isOpen?height:0) +'px'}">
-			<view :id="elId" ref="collapse--hook" class="uni-collapse-item__wrap-content"
-				:class="{open:isheight,'uni-collapse-item--border':border&&isOpen}">
-				<slot></slot>
-			</view>
-		</view>
-
-	</view>
-</template>
-
-<script>
-	// #ifdef APP-NVUE
-	const dom = weex.requireModule('dom')
-	// #endif
-	/**
-	 * CollapseItem 折叠面板子组件
-	 * @description 折叠面板子组件
-	 * @property {String} title 标题文字
-	 * @property {String} thumb 标题左侧缩略图
-	 * @property {String} name 唯一标志符
-	 * @property {Boolean} open = [true|false] 是否展开组件
-	 * @property {Boolean} titleBorder = [true|false] 是否显示标题分隔线
-	 * @property {Boolean} border = [true|false] 是否显示分隔线
-	 * @property {Boolean} disabled = [true|false] 是否展开面板
-	 * @property {Boolean} showAnimation = [true|false] 开启动画
-	 * @property {Boolean} showArrow = [true|false] 是否显示右侧箭头
-	 */
-	export default {
-		name: 'uniCollapseItem',
-		props: {
-			// 列表标题
-			title: {
-				type: String,
-				default: ''
-			},
-			name: {
-				type: [Number, String],
-				default: ''
-			},
-			// 是否禁用
-			disabled: {
-				type: Boolean,
-				default: false
-			},
-			// #ifdef APP-PLUS
-			// 是否显示动画,app 端默认不开启动画,卡顿严重
-			showAnimation: {
-				type: Boolean,
-				default: false
-			},
-			// #endif
-			// #ifndef APP-PLUS
-			// 是否显示动画
-			showAnimation: {
-				type: Boolean,
-				default: true
-			},
-			// #endif
-			// 是否展开
-			open: {
-				type: Boolean,
-				default: false
-			},
-			// 缩略图
-			thumb: {
-				type: String,
-				default: ''
-			},
-			// 标题分隔线显示类型
-			titleBorder: {
-				type: String,
-				default: 'auto'
-			},
-			border: {
-				type: Boolean,
-				default: true
-			},
-			showArrow: {
-				type: Boolean,
-				default: true
-			}
-		},
-		data() {
-			// TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug
-			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
-			return {
-				isOpen: false,
-				isheight: null,
-				height: 0,
-				elId,
-				nameSync: 0
-			}
-		},
-		watch: {
-			open(val) {
-				this.isOpen = val
-				this.onClick(val, 'init')
-			}
-		},
-		updated(e) {
-			this.$nextTick(() => {
-				this.init(true)
-			})
-		},
-		created() {
-			this.collapse = this.getCollapse()
-			this.oldHeight = 0
-			this.onClick(this.open, 'init')
-		},
-		// #ifndef VUE3
-		// TODO vue2
-		destroyed() {
-			if (this.__isUnmounted) return
-			this.uninstall()
-		},
-		// #endif
-		// #ifdef VUE3
-		// TODO vue3
-		unmounted() {
-			this.__isUnmounted = true
-			this.uninstall()
-		},
-		// #endif
-		mounted() {
-			if (!this.collapse) return
-			if (this.name !== '') {
-				this.nameSync = this.name
-			} else {
-				this.nameSync = this.collapse.childrens.length + ''
-			}
-			if (this.collapse.names.indexOf(this.nameSync) === -1) {
-				this.collapse.names.push(this.nameSync)
-			} else {
-				console.warn(`name 值 ${this.nameSync} 重复`);
-			}
-			if (this.collapse.childrens.indexOf(this) === -1) {
-				this.collapse.childrens.push(this)
-			}
-			this.init()
-		},
-		methods: {
-			init(type) {
-				// #ifndef APP-NVUE
-				this.getCollapseHeight(type)
-				// #endif
-				// #ifdef APP-NVUE
-				this.getNvueHwight(type)
-				// #endif
-			},
-			uninstall() {
-				if (this.collapse) {
-					this.collapse.childrens.forEach((item, index) => {
-						if (item === this) {
-							this.collapse.childrens.splice(index, 1)
-						}
-					})
-					this.collapse.names.forEach((item, index) => {
-						if (item === this.nameSync) {
-							this.collapse.names.splice(index, 1)
-						}
-					})
-				}
-			},
-			onClick(isOpen, type) {
-				if (this.disabled) return
-				this.isOpen = isOpen
-				if (this.isOpen && this.collapse) {
-					this.collapse.setAccordion(this)
-				}
-				if (type !== 'init') {
-					this.collapse.onChange(isOpen, this)
-				}
-			},
-			getCollapseHeight(type, index = 0) {
-				const views = uni.createSelectorQuery().in(this)
-				views
-					.select(`#${this.elId}`)
-					.fields({
-						size: true
-					}, data => {
-						// TODO 百度中可能获取不到节点信息 ,需要循环获取
-						if (index >= 10) return
-						if (!data) {
-							index++
-							this.getCollapseHeight(false, index)
-							return
-						}
-						// #ifdef APP-NVUE
-						this.height = data.height + 1
-						// #endif
-						// #ifndef APP-NVUE
-						this.height = data.height
-						// #endif
-						this.isheight = true
-						if (type) return
-						this.onClick(this.isOpen, 'init')
-					})
-					.exec()
-			},
-			getNvueHwight(type) {
-				const result = dom.getComponentRect(this.$refs['collapse--hook'], option => {
-					if (option && option.result && option.size) {
-						// #ifdef APP-NVUE
-						this.height = option.size.height + 1
-						// #endif
-						// #ifndef APP-NVUE
-						this.height = option.size.height
-						// #endif
-						this.isheight = true
-						if (type) return
-						this.onClick(this.open, 'init')
-					}
-				})
-			},
-			/**
-			 * 获取父元素实例
-			 */
-			getCollapse(name = 'uniCollapse') {
-				let parent = this.$parent;
-				let parentName = parent.$options.name;
-				while (parentName !== name) {
-					parent = parent.$parent;
-					if (!parent) return false;
-					parentName = parent.$options.name;
-				}
-				return parent;
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
-	.uni-collapse-item {
-		/* #ifndef APP-NVUE */
-		box-sizing: border-box;
-
-		/* #endif */
-		&__title {
-			/* #ifndef APP-NVUE */
-			display: flex;
-			width: 100%;
-			box-sizing: border-box;
-			/* #endif */
-			flex-direction: row;
-			align-items: center;
-			transition: border-bottom-color .3s;
-
-			// transition-property: border-bottom-color;
-			// transition-duration: 5s;
-			&-wrap {
-				width: 100%;
-				flex: 1;
-
-			}
-
-			&-box {
-				padding: 0 15px;
-				/* #ifndef APP-NVUE */
-				display: flex;
-				width: 100%;
-				box-sizing: border-box;
-				/* #endif */
-				flex-direction: row;
-				justify-content: space-between;
-				align-items: center;
-				height: 48px;
-				line-height: 48px;
-				background-color: #fff;
-				color: #303133;
-				font-size: 13px;
-				font-weight: 500;
-				/* #ifdef H5 */
-				cursor: pointer;
-				outline: none;
-
-				/* #endif */
-				&.is-disabled {
-					.uni-collapse-item__title-text {
-						color: #999;
-					}
-				}
-
-			}
-
-			&.uni-collapse-item-border {
-				border-bottom: 1px solid #ebeef5;
-			}
-
-			&.is-open {
-				border-bottom-color: transparent;
-			}
-
-			&-img {
-				height: 22px;
-				width: 22px;
-				margin-right: 10px;
-			}
-
-			&-text {
-				flex: 1;
-				font-size: 14px;
-				/* #ifndef APP-NVUE */
-				white-space: nowrap;
-				color: inherit;
-				/* #endif */
-				/* #ifdef APP-NVUE */
-				lines: 1;
-				/* #endif */
-				overflow: hidden;
-				text-overflow: ellipsis;
-			}
-
-			&-arrow {
-				/* #ifndef APP-NVUE */
-				display: flex;
-				box-sizing: border-box;
-				/* #endif */
-				align-items: center;
-				justify-content: center;
-				width: 20px;
-				height: 20px;
-				margin-right: 10px;
-				transform: rotate(0deg);
-
-				&-active {
-					transform: rotate(-180deg);
-				}
-			}
-
-
-		}
-
-		&__wrap {
-			/* #ifndef APP-NVUE */
-			will-change: height;
-			box-sizing: border-box;
-			/* #endif */
-			background-color: #fff;
-			overflow: hidden;
-			position: relative;
-			height: 0;
-
-			&.is--transition {
-				// transition: all 0.3s;
-				transition-property: height, border-bottom-width;
-				transition-duration: 0.3s;
-				/* #ifndef APP-NVUE */
-				will-change: height;
-				/* #endif */
-			}
-
-
-
-			&-content {
-				position: absolute;
-				font-size: 13px;
-				color: #303133;
-				// transition: height 0.3s;
-				border-bottom-color: transparent;
-				border-bottom-style: solid;
-				border-bottom-width: 0;
-
-				&.uni-collapse-item--border {
-					border-bottom-width: 1px;
-					border-bottom-color: red;
-					border-bottom-color: #ebeef5;
-				}
-
-				&.open {
-					position: relative;
-				}
-			}
-		}
-
-		&--animation {
-			transition-property: transform;
-			transition-duration: 0.3s;
-			transition-timing-function: ease;
-		}
-
-	}
+<template>
+	<view class="uni-collapse-item">
+		<!-- onClick(!isOpen) -->
+		<view @click="onClick(!isOpen)" class="uni-collapse-item__title"
+			:class="{'is-open':isOpen &&titleBorder === 'auto' ,'uni-collapse-item-border':titleBorder !== 'none'}">
+			<view class="uni-collapse-item__title-wrap">
+				<slot name="title">
+					<view class="uni-collapse-item__title-box" :class="{'is-disabled':disabled}">
+						<image v-if="thumb" :src="thumb" class="uni-collapse-item__title-img" />
+						<text class="uni-collapse-item__title-text">{{ title }}</text>
+					</view>
+				</slot>
+			</view>
+			<view v-if="showArrow"
+				:class="{ 'uni-collapse-item__title-arrow-active': isOpen, 'uni-collapse-item--animation': showAnimation === true }"
+				class="uni-collapse-item__title-arrow">
+				<uni-icons :color="disabled?'#ddd':'#bbb'" size="14" type="bottom" />
+			</view>
+		</view>
+		<view class="uni-collapse-item__wrap" :class="{'is--transition':showAnimation}"
+			:style="{height: (isOpen?height:0) +'px'}">
+			<view :id="elId" ref="collapse--hook" class="uni-collapse-item__wrap-content"
+				:class="{open:isheight,'uni-collapse-item--border':border&&isOpen}">
+				<slot></slot>
+			</view>
+		</view>
+
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = weex.requireModule('dom')
+	// #endif
+	/**
+	 * CollapseItem 折叠面板子组件
+	 * @description 折叠面板子组件
+	 * @property {String} title 标题文字
+	 * @property {String} thumb 标题左侧缩略图
+	 * @property {String} name 唯一标志符
+	 * @property {Boolean} open = [true|false] 是否展开组件
+	 * @property {Boolean} titleBorder = [true|false] 是否显示标题分隔线
+	 * @property {Boolean} border = [true|false] 是否显示分隔线
+	 * @property {Boolean} disabled = [true|false] 是否展开面板
+	 * @property {Boolean} showAnimation = [true|false] 开启动画
+	 * @property {Boolean} showArrow = [true|false] 是否显示右侧箭头
+	 */
+	export default {
+		name: 'uniCollapseItem',
+		props: {
+			// 列表标题
+			title: {
+				type: String,
+				default: ''
+			},
+			name: {
+				type: [Number, String],
+				default: ''
+			},
+			// 是否禁用
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			// #ifdef APP-PLUS
+			// 是否显示动画,app 端默认不开启动画,卡顿严重
+			showAnimation: {
+				type: Boolean,
+				default: false
+			},
+			// #endif
+			// #ifndef APP-PLUS
+			// 是否显示动画
+			showAnimation: {
+				type: Boolean,
+				default: true
+			},
+			// #endif
+			// 是否展开
+			open: {
+				type: Boolean,
+				default: false
+			},
+			// 缩略图
+			thumb: {
+				type: String,
+				default: ''
+			},
+			// 标题分隔线显示类型
+			titleBorder: {
+				type: String,
+				default: 'auto'
+			},
+			border: {
+				type: Boolean,
+				default: true
+			},
+			showArrow: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			// TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug
+			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			return {
+				isOpen: false,
+				isheight: null,
+				height: 0,
+				elId,
+				nameSync: 0
+			}
+		},
+		watch: {
+			open(val) {
+				this.isOpen = val
+				this.onClick(val, 'init')
+			}
+		},
+		updated(e) {
+			this.$nextTick(() => {
+				this.init(true)
+			})
+		},
+		created() {
+			this.collapse = this.getCollapse()
+			this.oldHeight = 0
+			this.onClick(this.open, 'init')
+		},
+		// #ifndef VUE3
+		// TODO vue2
+		destroyed() {
+			if (this.__isUnmounted) return
+			this.uninstall()
+		},
+		// #endif
+		// #ifdef VUE3
+		// TODO vue3
+		unmounted() {
+			this.__isUnmounted = true
+			this.uninstall()
+		},
+		// #endif
+		mounted() {
+			if (!this.collapse) return
+			if (this.name !== '') {
+				this.nameSync = this.name
+			} else {
+				this.nameSync = this.collapse.childrens.length + ''
+			}
+			if (this.collapse.names.indexOf(this.nameSync) === -1) {
+				this.collapse.names.push(this.nameSync)
+			} else {
+				console.warn(`name 值 ${this.nameSync} 重复`);
+			}
+			if (this.collapse.childrens.indexOf(this) === -1) {
+				this.collapse.childrens.push(this)
+			}
+			this.init()
+		},
+		methods: {
+			init(type) {
+				// #ifndef APP-NVUE
+				this.getCollapseHeight(type)
+				// #endif
+				// #ifdef APP-NVUE
+				this.getNvueHwight(type)
+				// #endif
+			},
+			uninstall() {
+				if (this.collapse) {
+					this.collapse.childrens.forEach((item, index) => {
+						if (item === this) {
+							this.collapse.childrens.splice(index, 1)
+						}
+					})
+					this.collapse.names.forEach((item, index) => {
+						if (item === this.nameSync) {
+							this.collapse.names.splice(index, 1)
+						}
+					})
+				}
+			},
+			onClick(isOpen, type) {
+				if (this.disabled) return
+				this.isOpen = isOpen
+				if (this.isOpen && this.collapse) {
+					this.collapse.setAccordion(this)
+				}
+				if (type !== 'init') {
+					this.collapse.onChange(isOpen, this)
+				}
+			},
+			getCollapseHeight(type, index = 0) {
+				const views = uni.createSelectorQuery().in(this)
+				views
+					.select(`#${this.elId}`)
+					.fields({
+						size: true
+					}, data => {
+						// TODO 百度中可能获取不到节点信息 ,需要循环获取
+						if (index >= 10) return
+						if (!data) {
+							index++
+							this.getCollapseHeight(false, index)
+							return
+						}
+						// #ifdef APP-NVUE
+						this.height = data.height + 1
+						// #endif
+						// #ifndef APP-NVUE
+						this.height = data.height
+						// #endif
+						this.isheight = true
+						if (type) return
+						this.onClick(this.isOpen, 'init')
+					})
+					.exec()
+			},
+			getNvueHwight(type) {
+				const result = dom.getComponentRect(this.$refs['collapse--hook'], option => {
+					if (option && option.result && option.size) {
+						// #ifdef APP-NVUE
+						this.height = option.size.height + 1
+						// #endif
+						// #ifndef APP-NVUE
+						this.height = option.size.height
+						// #endif
+						this.isheight = true
+						if (type) return
+						this.onClick(this.open, 'init')
+					}
+				})
+			},
+			/**
+			 * 获取父元素实例
+			 */
+			getCollapse(name = 'uniCollapse') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false;
+					parentName = parent.$options.name;
+				}
+				return parent;
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.uni-collapse-item {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+
+		/* #endif */
+		&__title {
+			/* #ifndef APP-NVUE */
+			display: flex;
+			width: 100%;
+			box-sizing: border-box;
+			/* #endif */
+			flex-direction: row;
+			align-items: center;
+			transition: border-bottom-color .3s;
+
+			// transition-property: border-bottom-color;
+			// transition-duration: 5s;
+			&-wrap {
+				width: 100%;
+				flex: 1;
+
+			}
+
+			&-box {
+				padding: 0 15px;
+				/* #ifndef APP-NVUE */
+				display: flex;
+				width: 100%;
+				box-sizing: border-box;
+				/* #endif */
+				flex-direction: row;
+				justify-content: space-between;
+				align-items: center;
+				height: 48px;
+				line-height: 48px;
+				background-color: #fff;
+				color: #303133;
+				font-size: 13px;
+				font-weight: 500;
+				/* #ifdef H5 */
+				cursor: pointer;
+				outline: none;
+
+				/* #endif */
+				&.is-disabled {
+					.uni-collapse-item__title-text {
+						color: #999;
+					}
+				}
+
+			}
+
+			&.uni-collapse-item-border {
+				border-bottom: 1px solid #ebeef5;
+			}
+
+			&.is-open {
+				border-bottom-color: transparent;
+			}
+
+			&-img {
+				height: 22px;
+				width: 22px;
+				margin-right: 10px;
+			}
+
+			&-text {
+				flex: 1;
+				font-size: 14px;
+				/* #ifndef APP-NVUE */
+				white-space: nowrap;
+				color: inherit;
+				/* #endif */
+				/* #ifdef APP-NVUE */
+				lines: 1;
+				/* #endif */
+				overflow: hidden;
+				text-overflow: ellipsis;
+			}
+
+			&-arrow {
+				/* #ifndef APP-NVUE */
+				display: flex;
+				box-sizing: border-box;
+				/* #endif */
+				align-items: center;
+				justify-content: center;
+				width: 20px;
+				height: 20px;
+				margin-right: 10px;
+				transform: rotate(0deg);
+
+				&-active {
+					transform: rotate(-180deg);
+				}
+			}
+
+
+		}
+
+		&__wrap {
+			/* #ifndef APP-NVUE */
+			will-change: height;
+			box-sizing: border-box;
+			/* #endif */
+			background-color: #fff;
+			overflow: hidden;
+			position: relative;
+			height: 0;
+
+			&.is--transition {
+				// transition: all 0.3s;
+				transition-property: height, border-bottom-width;
+				transition-duration: 0.3s;
+				/* #ifndef APP-NVUE */
+				will-change: height;
+				/* #endif */
+			}
+
+
+
+			&-content {
+				position: absolute;
+				font-size: 13px;
+				color: #303133;
+				// transition: height 0.3s;
+				border-bottom-color: transparent;
+				border-bottom-style: solid;
+				border-bottom-width: 0;
+
+				&.uni-collapse-item--border {
+					border-bottom-width: 1px;
+					border-bottom-color: red;
+					border-bottom-color: #ebeef5;
+				}
+
+				&.open {
+					position: relative;
+				}
+			}
+		}
+
+		&--animation {
+			transition-property: transform;
+			transition-duration: 0.3s;
+			transition-timing-function: ease;
+		}
+
+	}
 </style>
 </style>

+ 139 - 139
uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue

@@ -1,147 +1,147 @@
-<template>
-	<view class="uni-collapse">
-		<slot />
-	</view>
-</template>
-<script>
-	/**
-	 * Collapse 折叠面板
-	 * @description 展示可以折叠 / 展开的内容区域
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=23
-	 * @property {String|Array} value 当前激活面板改变时触发(如果是手风琴模式,参数类型为string,否则为array)
-	 * @property {Boolean} accordion = [true|false] 是否开启手风琴效果是否开启手风琴效果
-	 * @event {Function} change 切换面板时触发,如果是手风琴模式,返回类型为string,否则为array
-	 */
-	export default {
-		name: 'uniCollapse',
-		emits:['change','activeItem','input','update:modelValue'],
-		props: {
-			value: {
-				type: [String, Array],
-				default: ''
-			},
-			modelValue: {
-				type: [String, Array],
-				default: ''
-			},
-			accordion: {
-				// 是否开启手风琴效果
-				type: [Boolean, String],
-				default: false
-			},
-		},
-		data() {
-			return {}
-		},
-		computed: {
-			// TODO 兼容 vue2 和 vue3
-			dataValue() {
-				let value = (typeof this.value === 'string' && this.value === '') ||
-					(Array.isArray(this.value) && this.value.length === 0)
-				let modelValue = (typeof this.modelValue === 'string' && this.modelValue === '') ||
-					(Array.isArray(this.modelValue) && this.modelValue.length === 0)
-				if (value) {
-					return this.modelValue
-				}
-				if (modelValue) {
-					return this.value
-				}
-
-				return this.value
-			}
-		},
-		watch: {
+<template>
+	<view class="uni-collapse">
+		<slot />
+	</view>
+</template>
+<script>
+	/**
+	 * Collapse 折叠面板
+	 * @description 展示可以折叠 / 展开的内容区域
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=23
+	 * @property {String|Array} value 当前激活面板改变时触发(如果是手风琴模式,参数类型为string,否则为array)
+	 * @property {Boolean} accordion = [true|false] 是否开启手风琴效果是否开启手风琴效果
+	 * @event {Function} change 切换面板时触发,如果是手风琴模式,返回类型为string,否则为array
+	 */
+	export default {
+		name: 'uniCollapse',
+		emits:['change','activeItem','input','update:modelValue'],
+		props: {
+			value: {
+				type: [String, Array],
+				default: ''
+			},
+			modelValue: {
+				type: [String, Array],
+				default: ''
+			},
+			accordion: {
+				// 是否开启手风琴效果
+				type: [Boolean, String],
+				default: false
+			},
+		},
+		data() {
+			return {}
+		},
+		computed: {
+			// TODO 兼容 vue2 和 vue3
+			dataValue() {
+				let value = (typeof this.value === 'string' && this.value === '') ||
+					(Array.isArray(this.value) && this.value.length === 0)
+				let modelValue = (typeof this.modelValue === 'string' && this.modelValue === '') ||
+					(Array.isArray(this.modelValue) && this.modelValue.length === 0)
+				if (value) {
+					return this.modelValue
+				}
+				if (modelValue) {
+					return this.value
+				}
+
+				return this.value
+			}
+		},
+		watch: {
 			dataValue(val) {
 			dataValue(val) {
-				this.setOpen(val)
-			}
-		},
-		created() {
-			this.childrens = []
-			this.names = []
-		},
+				this.setOpen(val)
+			}
+		},
+		created() {
+			this.childrens = []
+			this.names = []
+		},
 		mounted() {
 		mounted() {
 			this.$nextTick(()=>{
 			this.$nextTick(()=>{
 				this.setOpen(this.dataValue)
 				this.setOpen(this.dataValue)
 			})
 			})
-		},
-		methods: {
-			setOpen(val) {
-				let str = typeof val === 'string'
+		},
+		methods: {
+			setOpen(val) {
+				let str = typeof val === 'string'
 				let arr = Array.isArray(val)
 				let arr = Array.isArray(val)
-				this.childrens.forEach((vm, index) => {
-					if (str) {
-						if (val === vm.nameSync) {
-							if (!this.accordion) {
-								console.warn('accordion 属性为 false ,v-model 类型应该为 array')
-								return
-							}
-							vm.isOpen = true
-						}
+				this.childrens.forEach((vm, index) => {
+					if (str) {
+						if (val === vm.nameSync) {
+							if (!this.accordion) {
+								console.warn('accordion 属性为 false ,v-model 类型应该为 array')
+								return
+							}
+							vm.isOpen = true
+						}
 					}
 					}
-					if (arr) {
-						val.forEach(v => {
+					if (arr) {
+						val.forEach(v => {
 							if (v === vm.nameSync) {
 							if (v === vm.nameSync) {
-								if (this.accordion) {
-									console.warn('accordion 属性为 true ,v-model 类型应该为 string')
-									return
-								}
-								vm.isOpen = true
-							}
-						})
-					}
-				})
-				this.emit(val)
-			},
-			setAccordion(self) {
-				if (!this.accordion) return
-				this.childrens.forEach((vm, index) => {
-					if (self !== vm) {
-						vm.isOpen = false
-					}
-				})
-			},
-			resize() {
-				this.childrens.forEach((vm, index) => {
-					// #ifndef APP-NVUE
-					vm.getCollapseHeight()
-					// #endif
-					// #ifdef APP-NVUE
-					vm.getNvueHwight()
-					// #endif
-				})
-			},
-			onChange(isOpen, self) {
-				let activeItem = []
-
-				if (this.accordion) {
-					activeItem = isOpen ? self.nameSync : ''
-				} else {
-					this.childrens.forEach((vm, index) => {
-						if (vm.isOpen) {
-							activeItem.push(vm.nameSync)
-						}
-					})
-				}
-				this.$emit('change', activeItem)
-				this.emit(activeItem)
-			},
-			emit(val){
-				this.$emit('input', val)
-				this.$emit('update:modelValue', val)
-			}
-		}
-	}
-</script>
-<style lang="scss" >
-	.uni-collapse {
-		/* #ifndef APP-NVUE */
-		width: 100%;
-		display: flex;
-		/* #endif */
-		/* #ifdef APP-NVUE */
-		flex: 1;
-		/* #endif */
-		flex-direction: column;
-		background-color: #fff;
-	}
-</style>
+								if (this.accordion) {
+									console.warn('accordion 属性为 true ,v-model 类型应该为 string')
+									return
+								}
+								vm.isOpen = true
+							}
+						})
+					}
+				})
+				this.emit(val)
+			},
+			setAccordion(self) {
+				if (!this.accordion) return
+				this.childrens.forEach((vm, index) => {
+					if (self !== vm) {
+						vm.isOpen = false
+					}
+				})
+			},
+			resize() {
+				this.childrens.forEach((vm, index) => {
+					// #ifndef APP-NVUE
+					vm.getCollapseHeight()
+					// #endif
+					// #ifdef APP-NVUE
+					vm.getNvueHwight()
+					// #endif
+				})
+			},
+			onChange(isOpen, self) {
+				let activeItem = []
+
+				if (this.accordion) {
+					activeItem = isOpen ? self.nameSync : ''
+				} else {
+					this.childrens.forEach((vm, index) => {
+						if (vm.isOpen) {
+							activeItem.push(vm.nameSync)
+						}
+					})
+				}
+				this.$emit('change', activeItem)
+				this.emit(activeItem)
+			},
+			emit(val){
+				this.$emit('input', val)
+				this.$emit('update:modelValue', val)
+			}
+		}
+	}
+</script>
+<style lang="scss" >
+	.uni-collapse {
+		/* #ifndef APP-NVUE */
+		width: 100%;
+		display: flex;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+		flex-direction: column;
+		background-color: #fff;
+	}
+</style>

+ 5 - 5
uni_modules/uni-countdown/components/uni-countdown/i18n/en.json

@@ -1,6 +1,6 @@
-{
-	"uni-countdown.day": "day",
-	"uni-countdown.h": "h",
-	"uni-countdown.m": "m",
-	"uni-countdown.s": "s"
+{
+	"uni-countdown.day": "day",
+	"uni-countdown.h": "h",
+	"uni-countdown.m": "m",
+	"uni-countdown.s": "s"
 }
 }

+ 7 - 7
uni_modules/uni-countdown/components/uni-countdown/i18n/index.js

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

+ 5 - 5
uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json

@@ -1,6 +1,6 @@
-{
-	"uni-countdown.day": "天",
-	"uni-countdown.h": "时",
-	"uni-countdown.m": "分",
-	"uni-countdown.s": "秒"
+{
+	"uni-countdown.day": "天",
+	"uni-countdown.h": "时",
+	"uni-countdown.m": "分",
+	"uni-countdown.s": "秒"
 }
 }

+ 5 - 5
uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json

@@ -1,6 +1,6 @@
-{
-	"uni-countdown.day": "天",
-	"uni-countdown.h": "時",
-	"uni-countdown.m": "分",
-	"uni-countdown.s": "秒"
+{
+	"uni-countdown.day": "天",
+	"uni-countdown.h": "時",
+	"uni-countdown.m": "分",
+	"uni-countdown.s": "秒"
 }
 }

+ 238 - 238
uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue

@@ -1,271 +1,271 @@
-<template>
-	<view class="uni-countdown">
-		<text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text>
-		<text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{dayText}}</text>
-		<text :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text>
-		<text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text>
-		<text :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text>
-		<text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text>
-		<text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text>
-		<text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{secondText}}</text>
-	</view>
-</template>
-<script>
-	import {
-		initVueI18n
-	} from '@dcloudio/uni-i18n'
-	import messages from './i18n/index.js'
-	const {
-		t
-	} = initVueI18n(messages)
-	/**
-	 * Countdown 倒计时
-	 * @description 倒计时组件
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=25
-	 * @property {String} backgroundColor 背景色
-	 * @property {String} color 文字颜色
-	 * @property {Number} day 天数
-	 * @property {Number} hour 小时
-	 * @property {Number} minute 分钟
-	 * @property {Number} second 秒
-	 * @property {Number} timestamp 时间戳
-	 * @property {Boolean} showDay = [true|false] 是否显示天数
-	 * @property {Boolean} show-colon = [true|false] 是否以冒号为分隔符
-	 * @property {String} splitorColor 分割符号颜色
-	 * @event {Function} timeup 倒计时时间到触发事件
-	 * @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
-	 */
-	export default {
-		name: 'UniCountdown',
-		emits: ['timeup'],
-		props: {
-			showDay: {
-				type: Boolean,
-				default: true
-			},
-			showColon: {
-				type: Boolean,
-				default: true
-			},
-			start: {
-				type: Boolean,
-				default: true
-			},
-			backgroundColor: {
-				type: String,
-				default: ''
-			},
-			color: {
-				type: String,
-				default: '#333'
+<template>
+	<view class="uni-countdown">
+		<text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text>
+		<text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{dayText}}</text>
+		<text :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text>
+		<text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text>
+		<text :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text>
+		<text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text>
+		<text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text>
+		<text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{secondText}}</text>
+	</view>
+</template>
+<script>
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {
+		t
+	} = initVueI18n(messages)
+	/**
+	 * Countdown 倒计时
+	 * @description 倒计时组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=25
+	 * @property {String} backgroundColor 背景色
+	 * @property {String} color 文字颜色
+	 * @property {Number} day 天数
+	 * @property {Number} hour 小时
+	 * @property {Number} minute 分钟
+	 * @property {Number} second 秒
+	 * @property {Number} timestamp 时间戳
+	 * @property {Boolean} showDay = [true|false] 是否显示天数
+	 * @property {Boolean} show-colon = [true|false] 是否以冒号为分隔符
+	 * @property {String} splitorColor 分割符号颜色
+	 * @event {Function} timeup 倒计时时间到触发事件
+	 * @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
+	 */
+	export default {
+		name: 'UniCountdown',
+		emits: ['timeup'],
+		props: {
+			showDay: {
+				type: Boolean,
+				default: true
+			},
+			showColon: {
+				type: Boolean,
+				default: true
+			},
+			start: {
+				type: Boolean,
+				default: true
+			},
+			backgroundColor: {
+				type: String,
+				default: ''
+			},
+			color: {
+				type: String,
+				default: '#333'
 			},
 			},
 			fontSize: {
 			fontSize: {
 				type: Number,
 				type: Number,
 				default: 14
 				default: 14
-			},
-			splitorColor: {
-				type: String,
-				default: '#333'
-			},
-			day: {
-				type: Number,
-				default: 0
-			},
-			hour: {
-				type: Number,
-				default: 0
-			},
-			minute: {
-				type: Number,
-				default: 0
-			},
-			second: {
-				type: Number,
-				default: 0
-			},
-			timestamp: {
-				type: Number,
-				default: 0
-			}
-		},
-		data() {
-			return {
-				timer: null,
-				syncFlag: false,
-				d: '00',
-				h: '00',
-				i: '00',
-				s: '00',
-				leftTime: 0,
-				seconds: 0
-			}
-		},
-		computed: {
-			dayText() {
-				return t("uni-countdown.day")
-			},
-			hourText(val) {
-				return t("uni-countdown.h")
-			},
-			minuteText(val) {
-				return t("uni-countdown.m")
-			},
-			secondText(val) {
-				return t("uni-countdown.s")
-			},
-			timeStyle() {
-				const {
-					color,
+			},
+			splitorColor: {
+				type: String,
+				default: '#333'
+			},
+			day: {
+				type: Number,
+				default: 0
+			},
+			hour: {
+				type: Number,
+				default: 0
+			},
+			minute: {
+				type: Number,
+				default: 0
+			},
+			second: {
+				type: Number,
+				default: 0
+			},
+			timestamp: {
+				type: Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				timer: null,
+				syncFlag: false,
+				d: '00',
+				h: '00',
+				i: '00',
+				s: '00',
+				leftTime: 0,
+				seconds: 0
+			}
+		},
+		computed: {
+			dayText() {
+				return t("uni-countdown.day")
+			},
+			hourText(val) {
+				return t("uni-countdown.h")
+			},
+			minuteText(val) {
+				return t("uni-countdown.m")
+			},
+			secondText(val) {
+				return t("uni-countdown.s")
+			},
+			timeStyle() {
+				const {
+					color,
 					backgroundColor,
 					backgroundColor,
-					fontSize
-				} = this
-				return {
-					color,
+					fontSize
+				} = this
+				return {
+					color,
 					backgroundColor,
 					backgroundColor,
 					fontSize: `${fontSize}px`,
 					fontSize: `${fontSize}px`,
 					width: `${fontSize * 22 / 14}px`, // 按字体大小为 14px 时的比例缩放
 					width: `${fontSize * 22 / 14}px`, // 按字体大小为 14px 时的比例缩放
  					lineHeight: `${fontSize * 20 / 14}px`,
  					lineHeight: `${fontSize * 20 / 14}px`,
 					borderRadius: `${fontSize * 3 / 14}px`,
 					borderRadius: `${fontSize * 3 / 14}px`,
-				}
-			},
+				}
+			},
 			splitorStyle() {
 			splitorStyle() {
 				const { splitorColor, fontSize, backgroundColor } = this
 				const { splitorColor, fontSize, backgroundColor } = this
 				return {
 				return {
 					color: splitorColor,
 					color: splitorColor,
 					fontSize: `${fontSize * 12 / 14}px`,
 					fontSize: `${fontSize * 12 / 14}px`,
-					margin: backgroundColor ? `${fontSize * 4 / 14}px` : ''
-				}
-			}
-		},
-		watch: {
-			day(val) {
-				this.changeFlag()
-			},
+					margin: backgroundColor ? `${fontSize * 4 / 14}px` : ''
+				}
+			}
+		},
+		watch: {
+			day(val) {
+				this.changeFlag()
+			},
 			hour(val) {
 			hour(val) {
-				this.changeFlag()
-			},
+				this.changeFlag()
+			},
 			minute(val) {
 			minute(val) {
-				this.changeFlag()
-			},
-			second(val) {
-				this.changeFlag()
-			},
-			start: {
-				immediate: true,
-				handler(newVal, oldVal) {
-					if (newVal) {
-						this.startData();
-					} else {
-						if (!oldVal) return
-						clearInterval(this.timer)
-					}
-				}
-
-			}
-		},
-		created: function(e) {
-			this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
-			this.countDown()
-		},
-		// #ifndef VUE3
-		destroyed() {
-			clearInterval(this.timer)
-		},
-		// #endif
-		// #ifdef VUE3
-		unmounted() {
-			clearInterval(this.timer)
-		},
-		// #endif
-		methods: {
-			toSeconds(timestamp, day, hours, minutes, seconds) {
-				if (timestamp) {
-					return timestamp - parseInt(new Date().getTime() / 1000, 10)
-				}
-				return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
-			},
-			timeUp() {
-				clearInterval(this.timer)
-				this.$emit('timeup')
-			},
-			countDown() {
-				let seconds = this.seconds
-				let [day, hour, minute, second] = [0, 0, 0, 0]
-				if (seconds > 0) {
-					day = Math.floor(seconds / (60 * 60 * 24))
-					hour = Math.floor(seconds / (60 * 60)) - (day * 24)
-					minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
-					second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
-				} else {
-					this.timeUp()
-				}
-				if (day < 10) {
-					day = '0' + day
-				}
-				if (hour < 10) {
-					hour = '0' + hour
-				}
-				if (minute < 10) {
-					minute = '0' + minute
-				}
-				if (second < 10) {
-					second = '0' + second
-				}
-				this.d = day
-				this.h = hour
-				this.i = minute
+				this.changeFlag()
+			},
+			second(val) {
+				this.changeFlag()
+			},
+			start: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					if (newVal) {
+						this.startData();
+					} else {
+						if (!oldVal) return
+						clearInterval(this.timer)
+					}
+				}
+
+			}
+		},
+		created: function(e) {
+			this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+			this.countDown()
+		},
+		// #ifndef VUE3
+		destroyed() {
+			clearInterval(this.timer)
+		},
+		// #endif
+		// #ifdef VUE3
+		unmounted() {
+			clearInterval(this.timer)
+		},
+		// #endif
+		methods: {
+			toSeconds(timestamp, day, hours, minutes, seconds) {
+				if (timestamp) {
+					return timestamp - parseInt(new Date().getTime() / 1000, 10)
+				}
+				return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
+			},
+			timeUp() {
+				clearInterval(this.timer)
+				this.$emit('timeup')
+			},
+			countDown() {
+				let seconds = this.seconds
+				let [day, hour, minute, second] = [0, 0, 0, 0]
+				if (seconds > 0) {
+					day = Math.floor(seconds / (60 * 60 * 24))
+					hour = Math.floor(seconds / (60 * 60)) - (day * 24)
+					minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
+					second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
+				} else {
+					this.timeUp()
+				}
+				if (day < 10) {
+					day = '0' + day
+				}
+				if (hour < 10) {
+					hour = '0' + hour
+				}
+				if (minute < 10) {
+					minute = '0' + minute
+				}
+				if (second < 10) {
+					second = '0' + second
+				}
+				this.d = day
+				this.h = hour
+				this.i = minute
 				this.s = second
 				this.s = second
-			},
-			startData() {
-				this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+			},
+			startData() {
+				this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
 				if (this.seconds <= 0) {
 				if (this.seconds <= 0) {
 					this.seconds = this.toSeconds(0, 0, 0, 0, 0)
 					this.seconds = this.toSeconds(0, 0, 0, 0, 0)
-					this.countDown()
-					return
+					this.countDown()
+					return
 				}
 				}
-				clearInterval(this.timer)
-				this.countDown()
-				this.timer = setInterval(() => {
-					this.seconds--
-					if (this.seconds < 0) {
-						this.timeUp()
-						return
-					}
-					this.countDown()
-				}, 1000)
+				clearInterval(this.timer)
+				this.countDown()
+				this.timer = setInterval(() => {
+					this.seconds--
+					if (this.seconds < 0) {
+						this.timeUp()
+						return
+					}
+					this.countDown()
+				}, 1000)
 			},
 			},
 			update(){
 			update(){
 				this.startData();
 				this.startData();
-			},
+			},
 			changeFlag() {
 			changeFlag() {
-				if (!this.syncFlag) {
-					this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
-					this.startData();
-					this.syncFlag = true;
-				}
-			}
-		}
-	}
-</script>
-<style lang="scss" scoped>
+				if (!this.syncFlag) {
+					this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+					this.startData();
+					this.syncFlag = true;
+				}
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
 	$font-size: 14px;
 	$font-size: 14px;
-
+
 	.uni-countdown {
 	.uni-countdown {
-		display: flex;
-		flex-direction: row;
-		justify-content: flex-start;
+		display: flex;
+		flex-direction: row;
+		justify-content: flex-start;
 		align-items: center;
 		align-items: center;
-
-		&__splitor {
-			margin: 0 2px;
+
+		&__splitor {
+			margin: 0 2px;
 			font-size: $font-size;
 			font-size: $font-size;
 			color: #333;
 			color: #333;
-		}
-
+		}
+
 		&__number {
 		&__number {
-			border-radius: 3px;
-			text-align: center;
+			border-radius: 3px;
+			text-align: center;
 			font-size: $font-size;
 			font-size: $font-size;
-		}
-	}
+		}
+	}
 </style>
 </style>

File diff suppressed because it is too large
+ 792 - 792
uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue


File diff suppressed because it is too large
+ 546 - 546
uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue


+ 318 - 318
uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue

@@ -1,321 +1,321 @@
-<template>
-  <view class="uni-data-pickerview">
-    <scroll-view v-if="!isCloudDataList" class="selected-area" scroll-x="true">
-      <view class="selected-list">
-        <template v-for="(item,index) in selected">
-          <view class="selected-item"
-            :class="{'selected-item-active':index==selectedIndex}"
-            v-if="item.text" @click="handleSelect(index)">
-            <text>{{item.text}}</text>
-          </view>
-        </template>
-      </view>
-    </scroll-view>
-    <view class="tab-c">
-      <template v-for="(child, i) in dataList">
-        <scroll-view class="list" :key="i" v-if="i==selectedIndex" :scroll-y="true">
-          <view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in child"
-            @click="handleNodeClick(item, i, j)">
-            <text class="item-text">{{item[map.text]}}</text>
-            <view class="check" v-if="selected.length > i && item[map.value] == selected[i].value"></view>
-          </view>
-        </scroll-view>
-      </template>
-
-      <view class="loading-cover" v-if="loading">
-        <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
-      </view>
-      <view class="error-message" v-if="errorMessage">
-        <text class="error-text">{{errorMessage}}</text>
-      </view>
-    </view>
-  </view>
-</template>
-
-<script>
-  import dataPicker from "./uni-data-picker.js"
-
-  /**
-   * DataPickerview
-   * @description uni-data-pickerview
-   * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
-   * @property {Array} localdata 本地数据,参考
-   * @property {Boolean} step-searh = [true|false] 是否分布查询
-   * @value true 启用分布查询,仅查询当前选中节点
-   * @value false 关闭分布查询,一次查询出所有数据
-   * @property {String|DBFieldString} self-field 分布查询当前字段名称
-   * @property {String|DBFieldString} parent-field 分布查询父字段名称
-   * @property {String|DBCollectionString} collection 表名
-   * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
-   * @property {String} orderby 排序字段及正序倒叙设置
-   * @property {String|JQLString} where 查询条件
-   */
-  export default {
-    name: 'UniDataPickerView',
-    emits: ['nodeclick', 'change', 'datachange', 'update:modelValue'],
-    mixins: [dataPicker],
-    props: {
-      managedMode: {
-        type: Boolean,
-        default: false
-      },
-      ellipsis: {
-        type: Boolean,
-        default: true
-      }
-    },
-    created() {
-      if (!this.managedMode) {
-        this.$nextTick(() => {
-          this.loadData();
-        })
-      }
-    },
-    methods: {
-      onPropsChange() {
-        this._treeData = [];
-        this.selectedIndex = 0;
-        this.$nextTick(() => {
-          this.loadData();
-        })
-      },
-      handleSelect(index) {
-        this.selectedIndex = index;
-      },
-      handleNodeClick(item, i, j) {
-        if (item.disable) {
-          return;
-        }
-
-        const node = this.dataList[i][j];
-        const text = node[this.map.text];
-        const value = node[this.map.value];
-
-        if (i < this.selected.length - 1) {
-          this.selected.splice(i, this.selected.length - i)
-          this.selected.push({
-            text,
-            value
-          })
-        } else if (i === this.selected.length - 1) {
-          this.selected.splice(i, 1, {
-            text,
-            value
-          })
-        }
-
-        if (node.isleaf) {
-          this.onSelectedChange(node, node.isleaf)
-          return
-        }
-
-        const {
-          isleaf,
-          hasNodes
-        } = this._updateBindData()
-
-        // 本地数据
-        if (this.isLocalData) {
-          this.onSelectedChange(node, (!hasNodes || isleaf))
-        } else if (this.isCloudDataList) { // Cloud 数据 (单列)
-          this.onSelectedChange(node, true)
-        } else if (this.isCloudDataTree) { // Cloud 数据 (树形)
-          if (isleaf) {
-            this.onSelectedChange(node, node.isleaf)
-          } else if (!hasNodes) { // 请求一次服务器以确定是否为叶子节点
-            this.loadCloudDataNode((data) => {
-              if (!data.length) {
-                node.isleaf = true
-              } else {
-                this._treeData.push(...data)
-                this._updateBindData(node)
-              }
-              this.onSelectedChange(node, node.isleaf)
-            })
-          }
-        }
-      },
-      updateData(data) {
-        this._treeData = data.treeData
-        this.selected = data.selected
-        if (!this._treeData.length) {
-          this.loadData()
-        } else {
-          //this.selected = data.selected
-          this._updateBindData()
-        }
-      },
-      onDataChange() {
-        this.$emit('datachange');
-      },
-      onSelectedChange(node, isleaf) {
-        if (isleaf) {
-          this._dispatchEvent()
-        }
-
-        if (node) {
-          this.$emit('nodeclick', node)
-        }
-      },
-      _dispatchEvent() {
-        this.$emit('change', this.selected.slice(0))
-      }
-    }
-  }
-</script>
-
+<template>
+  <view class="uni-data-pickerview">
+    <scroll-view v-if="!isCloudDataList" class="selected-area" scroll-x="true">
+      <view class="selected-list">
+        <template v-for="(item,index) in selected">
+          <view class="selected-item"
+            :class="{'selected-item-active':index==selectedIndex}"
+            v-if="item.text" @click="handleSelect(index)">
+            <text>{{item.text}}</text>
+          </view>
+        </template>
+      </view>
+    </scroll-view>
+    <view class="tab-c">
+      <template v-for="(child, i) in dataList">
+        <scroll-view class="list" :key="i" v-if="i==selectedIndex" :scroll-y="true">
+          <view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in child"
+            @click="handleNodeClick(item, i, j)">
+            <text class="item-text">{{item[map.text]}}</text>
+            <view class="check" v-if="selected.length > i && item[map.value] == selected[i].value"></view>
+          </view>
+        </scroll-view>
+      </template>
+
+      <view class="loading-cover" v-if="loading">
+        <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
+      </view>
+      <view class="error-message" v-if="errorMessage">
+        <text class="error-text">{{errorMessage}}</text>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+  import dataPicker from "./uni-data-picker.js"
+
+  /**
+   * DataPickerview
+   * @description uni-data-pickerview
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+   * @property {Array} localdata 本地数据,参考
+   * @property {Boolean} step-searh = [true|false] 是否分布查询
+   * @value true 启用分布查询,仅查询当前选中节点
+   * @value false 关闭分布查询,一次查询出所有数据
+   * @property {String|DBFieldString} self-field 分布查询当前字段名称
+   * @property {String|DBFieldString} parent-field 分布查询父字段名称
+   * @property {String|DBCollectionString} collection 表名
+   * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
+   * @property {String} orderby 排序字段及正序倒叙设置
+   * @property {String|JQLString} where 查询条件
+   */
+  export default {
+    name: 'UniDataPickerView',
+    emits: ['nodeclick', 'change', 'datachange', 'update:modelValue'],
+    mixins: [dataPicker],
+    props: {
+      managedMode: {
+        type: Boolean,
+        default: false
+      },
+      ellipsis: {
+        type: Boolean,
+        default: true
+      }
+    },
+    created() {
+      if (!this.managedMode) {
+        this.$nextTick(() => {
+          this.loadData();
+        })
+      }
+    },
+    methods: {
+      onPropsChange() {
+        this._treeData = [];
+        this.selectedIndex = 0;
+        this.$nextTick(() => {
+          this.loadData();
+        })
+      },
+      handleSelect(index) {
+        this.selectedIndex = index;
+      },
+      handleNodeClick(item, i, j) {
+        if (item.disable) {
+          return;
+        }
+
+        const node = this.dataList[i][j];
+        const text = node[this.map.text];
+        const value = node[this.map.value];
+
+        if (i < this.selected.length - 1) {
+          this.selected.splice(i, this.selected.length - i)
+          this.selected.push({
+            text,
+            value
+          })
+        } else if (i === this.selected.length - 1) {
+          this.selected.splice(i, 1, {
+            text,
+            value
+          })
+        }
+
+        if (node.isleaf) {
+          this.onSelectedChange(node, node.isleaf)
+          return
+        }
+
+        const {
+          isleaf,
+          hasNodes
+        } = this._updateBindData()
+
+        // 本地数据
+        if (this.isLocalData) {
+          this.onSelectedChange(node, (!hasNodes || isleaf))
+        } else if (this.isCloudDataList) { // Cloud 数据 (单列)
+          this.onSelectedChange(node, true)
+        } else if (this.isCloudDataTree) { // Cloud 数据 (树形)
+          if (isleaf) {
+            this.onSelectedChange(node, node.isleaf)
+          } else if (!hasNodes) { // 请求一次服务器以确定是否为叶子节点
+            this.loadCloudDataNode((data) => {
+              if (!data.length) {
+                node.isleaf = true
+              } else {
+                this._treeData.push(...data)
+                this._updateBindData(node)
+              }
+              this.onSelectedChange(node, node.isleaf)
+            })
+          }
+        }
+      },
+      updateData(data) {
+        this._treeData = data.treeData
+        this.selected = data.selected
+        if (!this._treeData.length) {
+          this.loadData()
+        } else {
+          //this.selected = data.selected
+          this._updateBindData()
+        }
+      },
+      onDataChange() {
+        this.$emit('datachange');
+      },
+      onSelectedChange(node, isleaf) {
+        if (isleaf) {
+          this._dispatchEvent()
+        }
+
+        if (node) {
+          this.$emit('nodeclick', node)
+        }
+      },
+      _dispatchEvent() {
+        this.$emit('change', this.selected.slice(0))
+      }
+    }
+  }
+</script>
+
 <style lang="scss">
 <style lang="scss">
 	$uni-primary: #007aff !default;
 	$uni-primary: #007aff !default;
-
-	.uni-data-pickerview {
-		flex: 1;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: column;
-		overflow: hidden;
-		height: 100%;
-	}
-
-  .error-text {
-    color: #DD524D;
-  }
-
-  .loading-cover {
-    position: absolute;
-    left: 0;
-    top: 0;
-    right: 0;
-    bottom: 0;
-    background-color: rgba(255, 255, 255, .5);
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    flex-direction: column;
-    align-items: center;
-    z-index: 1001;
-  }
-
-  .load-more {
-    /* #ifndef APP-NVUE */
-    margin: auto;
-    /* #endif */
-  }
-
-  .error-message {
-    background-color: #fff;
-    position: absolute;
-    left: 0;
-    top: 0;
-    right: 0;
-    bottom: 0;
-    padding: 15px;
-    opacity: .9;
-    z-index: 102;
-  }
-
-  /* #ifdef APP-NVUE */
-  .selected-area {
-    width: 750rpx;
-  }
-  /* #endif */
-
-  .selected-list {
-    /* #ifndef APP-NVUE */
-    display: flex;
-    flex-wrap: nowrap;
-    /* #endif */
-    flex-direction: row;
-    padding: 0 5px;
-    border-bottom: 1px solid #f8f8f8;
-  }
-
-  .selected-item {
-    margin-left: 10px;
-    margin-right: 10px;
-    padding: 12px 0;
-    text-align: center;
-    /* #ifndef APP-NVUE */
-    white-space: nowrap;
-    /* #endif */
-  }
-
-  .selected-item-text-overflow {
-    width: 168px;
-    /* fix nvue */
-    overflow: hidden;
-    /* #ifndef APP-NVUE */
-    width: 6em;
-    white-space: nowrap;
-    text-overflow: ellipsis;
-    -o-text-overflow: ellipsis;
-    /* #endif */
-  }
-
-	.selected-item-active {
-		border-bottom: 2px solid $uni-primary;
-	}
-
-	.selected-item-text {
-		color: $uni-primary;
-	}
-
-  .tab-c {
-    position: relative;
-    flex: 1;
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    flex-direction: row;
-    overflow: hidden;
-  }
-
-  .list {
-    flex: 1;
-  }
-
-  .item {
-    padding: 12px 15px;
-    /* border-bottom: 1px solid #f0f0f0; */
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    flex-direction: row;
-    justify-content: space-between;
-  }
-
-  .is-disabled {
-    opacity: .5;
-  }
-
-  .item-text {
-    /* flex: 1; */
-    color: #333333;
-  }
-
-  .item-text-overflow {
-    width: 280px;
-    /* fix nvue */
-    overflow: hidden;
-    /* #ifndef APP-NVUE */
-    width: 20em;
-    white-space: nowrap;
-    text-overflow: ellipsis;
-    -o-text-overflow: ellipsis;
-    /* #endif */
-  }
-
-	.check {
-		margin-right: 5px;
-		border: 2px solid $uni-primary;
-		border-left: 0;
-		border-top: 0;
-		height: 12px;
-		width: 6px;
-		transform-origin: center;
-		/* #ifndef APP-NVUE */
-		transition: all 0.3s;
-		/* #endif */
-		transform: rotate(45deg);
-	}
+
+	.uni-data-pickerview {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		overflow: hidden;
+		height: 100%;
+	}
+
+  .error-text {
+    color: #DD524D;
+  }
+
+  .loading-cover {
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(255, 255, 255, .5);
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: column;
+    align-items: center;
+    z-index: 1001;
+  }
+
+  .load-more {
+    /* #ifndef APP-NVUE */
+    margin: auto;
+    /* #endif */
+  }
+
+  .error-message {
+    background-color: #fff;
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    padding: 15px;
+    opacity: .9;
+    z-index: 102;
+  }
+
+  /* #ifdef APP-NVUE */
+  .selected-area {
+    width: 750rpx;
+  }
+  /* #endif */
+
+  .selected-list {
+    /* #ifndef APP-NVUE */
+    display: flex;
+    flex-wrap: nowrap;
+    /* #endif */
+    flex-direction: row;
+    padding: 0 5px;
+    border-bottom: 1px solid #f8f8f8;
+  }
+
+  .selected-item {
+    margin-left: 10px;
+    margin-right: 10px;
+    padding: 12px 0;
+    text-align: center;
+    /* #ifndef APP-NVUE */
+    white-space: nowrap;
+    /* #endif */
+  }
+
+  .selected-item-text-overflow {
+    width: 168px;
+    /* fix nvue */
+    overflow: hidden;
+    /* #ifndef APP-NVUE */
+    width: 6em;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    -o-text-overflow: ellipsis;
+    /* #endif */
+  }
+
+	.selected-item-active {
+		border-bottom: 2px solid $uni-primary;
+	}
+
+	.selected-item-text {
+		color: $uni-primary;
+	}
+
+  .tab-c {
+    position: relative;
+    flex: 1;
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+    overflow: hidden;
+  }
+
+  .list {
+    flex: 1;
+  }
+
+  .item {
+    padding: 12px 15px;
+    /* border-bottom: 1px solid #f0f0f0; */
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+    justify-content: space-between;
+  }
+
+  .is-disabled {
+    opacity: .5;
+  }
+
+  .item-text {
+    /* flex: 1; */
+    color: #333333;
+  }
+
+  .item-text-overflow {
+    width: 280px;
+    /* fix nvue */
+    overflow: hidden;
+    /* #ifndef APP-NVUE */
+    width: 20em;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    -o-text-overflow: ellipsis;
+    /* #endif */
+  }
+
+	.check {
+		margin-right: 5px;
+		border: 2px solid $uni-primary;
+		border-left: 0;
+		border-top: 0;
+		height: 12px;
+		width: 6px;
+		transform-origin: center;
+		/* #ifndef APP-NVUE */
+		transition: all 0.3s;
+		/* #endif */
+		transform: rotate(45deg);
+	}
 </style>
 </style>

+ 440 - 440
uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue

@@ -1,440 +1,440 @@
-<template>
-	<view class="uni-stat__select">
-		<span v-if="label" class="uni-label-text hide-on-phone">{{label + ':'}}</span>
-		<view class="uni-stat-box" :class="{'uni-stat__actived': current}">
-			<view class="uni-select"  :class="{'uni-select--disabled':disabled}">
-				<view class="uni-select__input-box" @click="toggleSelector">
-					<view v-if="current" class="uni-select__input-text">{{current}}</view>
-					<view v-else class="uni-select__input-text uni-select__input-placeholder">{{typePlaceholder}}</view>
-					<uni-icons v-if="current && clear" type="clear" color="#c0c4cc" size="24" @click="clearVal" />
-					<uni-icons v-else :type="showSelector? 'top' : 'bottom'" size="14" color="#999" />
-				</view>
-				<view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" />
-				<view class="uni-select__selector" v-if="showSelector">
-					<view class="uni-popper__arrow"></view>
-					<scroll-view scroll-y="true" class="uni-select__selector-scroll">
-						<view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0">
-							<text>{{emptyTips}}</text>
-						</view>
-						<view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData"
-							:key="index" @click="change(item)">
-							<text
-								:class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text>
-						</view>
-					</scroll-view>
-				</view>
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	/**
-	 * DataChecklist 数据选择器
-	 * @description 通过数据渲染的下拉框组件
-	 * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select
-	 * @property {String} value 默认值
-	 * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
-	 * @property {Boolean} clear 是否可以清空已选项
-	 * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
-	 * @property {String} label 左侧标题
-	 * @property {String} placeholder 输入框的提示文字
-	 * @property {Boolean} disabled 是否禁用
-	 * @event {Function} change  选中发生变化触发
-	 */
-
-	export default {
-		name: "uni-stat-select",
-		mixins: [uniCloud.mixinDatacom || {}],
-		data() {
-			return {
-				showSelector: false,
-				current: '',
-				mixinDatacomResData: [],
-				apps: [],
-				channels: []
-			};
-		},
-		props: {
-			localdata: {
-				type: Array,
-				default () {
-					return []
-				}
-			},
-			value: {
-				type: [String, Number],
-				default: ''
-			},
-			modelValue: {
-				type: [String, Number],
-				default: ''
-			},
-			label: {
-				type: String,
-				default: ''
-			},
-			placeholder: {
-				type: String,
-				default: '请选择'
-			},
-			emptyTips: {
-				type: String,
-				default: '无选项'
-			},
-			clear: {
-				type: Boolean,
-				default: true
-			},
-			defItem: {
-				type: Number,
-				default: 0
-			},
-      disabled: {
-				type: Boolean,
-				default: false
-			}
-		},
-		created() {
-			this.last = `${this.collection}_last_selected_option_value`
-			if (this.collection && !this.localdata.length) {
-				this.mixinDatacomEasyGet()
-			}
-		},
-		computed: {
-			typePlaceholder() {
-				const text = {
-					'opendb-stat-app-versions': '版本',
-					'opendb-app-channels': '渠道',
-					'opendb-app-list': '应用'
-				}
-				const common = this.placeholder
-				const placeholder = text[this.collection]
-				return placeholder ?
-					common + placeholder :
-					common
-			}
-		},
-		watch: {
-			localdata: {
-				immediate: true,
-				handler(val, old) {
-					if (Array.isArray(val) && old !== val) {
-						this.mixinDatacomResData = val
-					}
-				}
-			},
-			// #ifndef VUE3
-			value() {
-				this.initDefVal()
-			},
-			// #endif
-			// #ifdef VUE3
-			modelValue() {
-				this.initDefVal()
-			},
-			// #endif
-			mixinDatacomResData: {
-				immediate: true,
-				handler(val) {
-					if (val.length) {
-						this.initDefVal()
-					}
-				}
-			}
-		},
-		methods: {
-			initDefVal() {
-				let defValue = ''
-				if ((this.value || this.value === 0) && !this.isDisabled(this.value)) {
-					defValue = this.value
-				} else if ((this.modelValue || this.modelValue === 0) && !this.isDisabled(this.modelValue)) {
-					defValue = this.modelValue
-				} else {
-					let strogeValue
-					if (this.collection) {
-						strogeValue = uni.getStorageSync(this.last)
-					}
-					if (strogeValue || strogeValue === 0) {
-						defValue = strogeValue
-					} else {
-						let defItem = ''
-						if (this.defItem > 0 && this.defItem < this.mixinDatacomResData.length) {
-							defItem = this.mixinDatacomResData[this.defItem - 1].value
-						}
-						defValue = defItem
-					}
-					this.emit(defValue)
-				}
-				const def = this.mixinDatacomResData.find(item => item.value === defValue)
-				this.current = def ? this.formatItemName(def) : ''
-			},
-
-			/**
-			 * @param {[String, Number]} value
-			 * 判断用户给的 value 是否同时为禁用状态
-			 */
-			isDisabled(value) {
-				let isDisabled = false;
-
-				this.mixinDatacomResData.forEach(item => {
-					if (item.value === value) {
-						isDisabled = item.disable
-					}
-				})
-
-				return isDisabled;
-			},
-
-			clearVal() {
-				this.emit('')
-				if (this.collection) {
-					uni.removeStorageSync(this.last)
-				}
-			},
-			change(item) {
-				if (!item.disable) {
-					this.showSelector = false
-					this.current = this.formatItemName(item)
-					this.emit(item.value)
-				}
-			},
-			emit(val) {
-				this.$emit('change', val)
-				this.$emit('input', val)
-				this.$emit('update:modelValue', val)
-				if (this.collection) {
-					uni.setStorageSync(this.last, val)
-				}
-			},
-
-			toggleSelector() {
-        if(this.disabled){
-          return
-        }
-
-				this.showSelector = !this.showSelector
-			},
-			formatItemName(item) {
-				let {
-					text,
-					value,
-					channel_code
-				} = item
-				channel_code = channel_code ? `(${channel_code})` : ''
-				return this.collection.indexOf('app-list') > 0 ?
-					`${text}(${value})` :
-					(
-						text ?
-						text :
-						`未命名${channel_code}`
-					)
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
-	$uni-base-color: #6a6a6a !default;
-	$uni-main-color: #333 !default;
-	$uni-secondary-color: #909399 !default;
-	$uni-border-3: #e5e5e5;
-
-
-	/* #ifndef APP-NVUE */
-	@media screen and (max-width: 500px) {
-		.hide-on-phone {
-			display: none;
-		}
-	}
-
-	/* #endif */
-	.uni-stat__select {
-		display: flex;
-		align-items: center;
-		// padding: 15px;
-		cursor: pointer;
-		width: 100%;
-		flex: 1;
-		box-sizing: border-box;
-	}
-
-	.uni-stat-box {
-		width: 100%;
-		flex: 1;
-	}
-
-	.uni-stat__actived {
-		width: 100%;
-		flex: 1;
-		// outline: 1px solid #2979ff;
-	}
-
-	.uni-label-text {
-		font-size: 14px;
-		font-weight: bold;
-		color: $uni-base-color;
-		margin: auto 0;
-		margin-right: 5px;
-	}
-
-	.uni-select {
-		font-size: 14px;
-		border: 1px solid $uni-border-3;
-		box-sizing: border-box;
-		border-radius: 4px;
-		padding: 0 5px;
-		padding-left: 10px;
-		position: relative;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		user-select: none;
-		/* #endif */
-		flex-direction: row;
-		align-items: center;
-		border-bottom: solid 1px $uni-border-3;
-		width: 100%;
-		flex: 1;
-		height: 35px;
-
-    &--disabled{
-      background-color: #f5f7fa;
-      cursor: not-allowed;
-    }
-	}
-
-	.uni-select__label {
-		font-size: 16px;
-		// line-height: 22px;
-		height: 35px;
-		padding-right: 10px;
-		color: $uni-secondary-color;
-	}
-
-	.uni-select__input-box {
-		height: 35px;
-		position: relative;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex: 1;
-		flex-direction: row;
-		align-items: center;
-	}
-
-	.uni-select__input {
-		flex: 1;
-		font-size: 14px;
-		height: 22px;
-		line-height: 22px;
-	}
-
-	.uni-select__input-plac {
-		font-size: 14px;
-		color: $uni-secondary-color;
-	}
-
-	.uni-select__selector {
-		/* #ifndef APP-NVUE */
-		box-sizing: border-box;
-		/* #endif */
-		position: absolute;
-		top: calc(100% + 12px);
-		left: 0;
-		width: 100%;
-		background-color: #FFFFFF;
-		border: 1px solid #EBEEF5;
-		border-radius: 6px;
-		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-		z-index: 3;
-		padding: 4px 0;
-	}
-
-	.uni-select__selector-scroll {
-		/* #ifndef APP-NVUE */
-		max-height: 200px;
-		box-sizing: border-box;
-		/* #endif */
-	}
-
-	.uni-select__selector-empty,
-	.uni-select__selector-item {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		cursor: pointer;
-		/* #endif */
-		line-height: 35px;
-		font-size: 14px;
-		text-align: center;
-		/* border-bottom: solid 1px $uni-border-3; */
-		padding: 0px 10px;
-	}
-
-	.uni-select__selector-item:hover {
-		background-color: #f9f9f9;
-	}
-
-	.uni-select__selector-empty:last-child,
-	.uni-select__selector-item:last-child {
-		/* #ifndef APP-NVUE */
-		border-bottom: none;
-		/* #endif */
-	}
-
-	.uni-select__selector__disabled {
-		opacity: 0.4;
-		cursor: default;
-	}
-
-	/* picker 弹出层通用的指示小三角 */
-	.uni-popper__arrow,
-	.uni-popper__arrow::after {
-		position: absolute;
-		display: block;
-		width: 0;
-		height: 0;
-		border-color: transparent;
-		border-style: solid;
-		border-width: 6px;
-	}
-
-	.uni-popper__arrow {
-		filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
-		top: -6px;
-		left: 10%;
-		margin-right: 3px;
-		border-top-width: 0;
-		border-bottom-color: #EBEEF5;
-	}
-
-	.uni-popper__arrow::after {
-		content: " ";
-		top: 1px;
-		margin-left: -6px;
-		border-top-width: 0;
-		border-bottom-color: #fff;
-	}
-
-	.uni-select__input-text {
-		// width: 280px;
-		width: 100%;
-		color: $uni-main-color;
-		white-space: nowrap;
-		text-overflow: ellipsis;
-		-o-text-overflow: ellipsis;
-		overflow: hidden;
-	}
-
-	.uni-select__input-placeholder {
-		color: $uni-base-color;
-		font-size: 12px;
-	}
-
-	.uni-select--mask {
-		position: fixed;
-		top: 0;
-		bottom: 0;
-		right: 0;
-		left: 0;
-	}
-</style>
+<template>
+	<view class="uni-stat__select">
+		<span v-if="label" class="uni-label-text hide-on-phone">{{label + ':'}}</span>
+		<view class="uni-stat-box" :class="{'uni-stat__actived': current}">
+			<view class="uni-select"  :class="{'uni-select--disabled':disabled}">
+				<view class="uni-select__input-box" @click="toggleSelector">
+					<view v-if="current" class="uni-select__input-text">{{current}}</view>
+					<view v-else class="uni-select__input-text uni-select__input-placeholder">{{typePlaceholder}}</view>
+					<uni-icons v-if="current && clear" type="clear" color="#c0c4cc" size="24" @click="clearVal" />
+					<uni-icons v-else :type="showSelector? 'top' : 'bottom'" size="14" color="#999" />
+				</view>
+				<view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" />
+				<view class="uni-select__selector" v-if="showSelector">
+					<view class="uni-popper__arrow"></view>
+					<scroll-view scroll-y="true" class="uni-select__selector-scroll">
+						<view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0">
+							<text>{{emptyTips}}</text>
+						</view>
+						<view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData"
+							:key="index" @click="change(item)">
+							<text
+								:class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text>
+						</view>
+					</scroll-view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * DataChecklist 数据选择器
+	 * @description 通过数据渲染的下拉框组件
+	 * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select
+	 * @property {String} value 默认值
+	 * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
+	 * @property {Boolean} clear 是否可以清空已选项
+	 * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
+	 * @property {String} label 左侧标题
+	 * @property {String} placeholder 输入框的提示文字
+	 * @property {Boolean} disabled 是否禁用
+	 * @event {Function} change  选中发生变化触发
+	 */
+
+	export default {
+		name: "uni-stat-select",
+		mixins: [uniCloud.mixinDatacom || {}],
+		data() {
+			return {
+				showSelector: false,
+				current: '',
+				mixinDatacomResData: [],
+				apps: [],
+				channels: []
+			};
+		},
+		props: {
+			localdata: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			value: {
+				type: [String, Number],
+				default: ''
+			},
+			modelValue: {
+				type: [String, Number],
+				default: ''
+			},
+			label: {
+				type: String,
+				default: ''
+			},
+			placeholder: {
+				type: String,
+				default: '请选择'
+			},
+			emptyTips: {
+				type: String,
+				default: '无选项'
+			},
+			clear: {
+				type: Boolean,
+				default: true
+			},
+			defItem: {
+				type: Number,
+				default: 0
+			},
+      disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		created() {
+			this.last = `${this.collection}_last_selected_option_value`
+			if (this.collection && !this.localdata.length) {
+				this.mixinDatacomEasyGet()
+			}
+		},
+		computed: {
+			typePlaceholder() {
+				const text = {
+					'opendb-stat-app-versions': '版本',
+					'opendb-app-channels': '渠道',
+					'opendb-app-list': '应用'
+				}
+				const common = this.placeholder
+				const placeholder = text[this.collection]
+				return placeholder ?
+					common + placeholder :
+					common
+			}
+		},
+		watch: {
+			localdata: {
+				immediate: true,
+				handler(val, old) {
+					if (Array.isArray(val) && old !== val) {
+						this.mixinDatacomResData = val
+					}
+				}
+			},
+			// #ifndef VUE3
+			value() {
+				this.initDefVal()
+			},
+			// #endif
+			// #ifdef VUE3
+			modelValue() {
+				this.initDefVal()
+			},
+			// #endif
+			mixinDatacomResData: {
+				immediate: true,
+				handler(val) {
+					if (val.length) {
+						this.initDefVal()
+					}
+				}
+			}
+		},
+		methods: {
+			initDefVal() {
+				let defValue = ''
+				if ((this.value || this.value === 0) && !this.isDisabled(this.value)) {
+					defValue = this.value
+				} else if ((this.modelValue || this.modelValue === 0) && !this.isDisabled(this.modelValue)) {
+					defValue = this.modelValue
+				} else {
+					let strogeValue
+					if (this.collection) {
+						strogeValue = uni.getStorageSync(this.last)
+					}
+					if (strogeValue || strogeValue === 0) {
+						defValue = strogeValue
+					} else {
+						let defItem = ''
+						if (this.defItem > 0 && this.defItem < this.mixinDatacomResData.length) {
+							defItem = this.mixinDatacomResData[this.defItem - 1].value
+						}
+						defValue = defItem
+					}
+					this.emit(defValue)
+				}
+				const def = this.mixinDatacomResData.find(item => item.value === defValue)
+				this.current = def ? this.formatItemName(def) : ''
+			},
+
+			/**
+			 * @param {[String, Number]} value
+			 * 判断用户给的 value 是否同时为禁用状态
+			 */
+			isDisabled(value) {
+				let isDisabled = false;
+
+				this.mixinDatacomResData.forEach(item => {
+					if (item.value === value) {
+						isDisabled = item.disable
+					}
+				})
+
+				return isDisabled;
+			},
+
+			clearVal() {
+				this.emit('')
+				if (this.collection) {
+					uni.removeStorageSync(this.last)
+				}
+			},
+			change(item) {
+				if (!item.disable) {
+					this.showSelector = false
+					this.current = this.formatItemName(item)
+					this.emit(item.value)
+				}
+			},
+			emit(val) {
+				this.$emit('change', val)
+				this.$emit('input', val)
+				this.$emit('update:modelValue', val)
+				if (this.collection) {
+					uni.setStorageSync(this.last, val)
+				}
+			},
+
+			toggleSelector() {
+        if(this.disabled){
+          return
+        }
+
+				this.showSelector = !this.showSelector
+			},
+			formatItemName(item) {
+				let {
+					text,
+					value,
+					channel_code
+				} = item
+				channel_code = channel_code ? `(${channel_code})` : ''
+				return this.collection.indexOf('app-list') > 0 ?
+					`${text}(${value})` :
+					(
+						text ?
+						text :
+						`未命名${channel_code}`
+					)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$uni-base-color: #6a6a6a !default;
+	$uni-main-color: #333 !default;
+	$uni-secondary-color: #909399 !default;
+	$uni-border-3: #e5e5e5;
+
+
+	/* #ifndef APP-NVUE */
+	@media screen and (max-width: 500px) {
+		.hide-on-phone {
+			display: none;
+		}
+	}
+
+	/* #endif */
+	.uni-stat__select {
+		display: flex;
+		align-items: center;
+		// padding: 15px;
+		cursor: pointer;
+		width: 100%;
+		flex: 1;
+		box-sizing: border-box;
+	}
+
+	.uni-stat-box {
+		width: 100%;
+		flex: 1;
+	}
+
+	.uni-stat__actived {
+		width: 100%;
+		flex: 1;
+		// outline: 1px solid #2979ff;
+	}
+
+	.uni-label-text {
+		font-size: 14px;
+		font-weight: bold;
+		color: $uni-base-color;
+		margin: auto 0;
+		margin-right: 5px;
+	}
+
+	.uni-select {
+		font-size: 14px;
+		border: 1px solid $uni-border-3;
+		box-sizing: border-box;
+		border-radius: 4px;
+		padding: 0 5px;
+		padding-left: 10px;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		user-select: none;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		border-bottom: solid 1px $uni-border-3;
+		width: 100%;
+		flex: 1;
+		height: 35px;
+
+    &--disabled{
+      background-color: #f5f7fa;
+      cursor: not-allowed;
+    }
+	}
+
+	.uni-select__label {
+		font-size: 16px;
+		// line-height: 22px;
+		height: 35px;
+		padding-right: 10px;
+		color: $uni-secondary-color;
+	}
+
+	.uni-select__input-box {
+		height: 35px;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.uni-select__input {
+		flex: 1;
+		font-size: 14px;
+		height: 22px;
+		line-height: 22px;
+	}
+
+	.uni-select__input-plac {
+		font-size: 14px;
+		color: $uni-secondary-color;
+	}
+
+	.uni-select__selector {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+		position: absolute;
+		top: calc(100% + 12px);
+		left: 0;
+		width: 100%;
+		background-color: #FFFFFF;
+		border: 1px solid #EBEEF5;
+		border-radius: 6px;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+		z-index: 3;
+		padding: 4px 0;
+	}
+
+	.uni-select__selector-scroll {
+		/* #ifndef APP-NVUE */
+		max-height: 200px;
+		box-sizing: border-box;
+		/* #endif */
+	}
+
+	.uni-select__selector-empty,
+	.uni-select__selector-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		cursor: pointer;
+		/* #endif */
+		line-height: 35px;
+		font-size: 14px;
+		text-align: center;
+		/* border-bottom: solid 1px $uni-border-3; */
+		padding: 0px 10px;
+	}
+
+	.uni-select__selector-item:hover {
+		background-color: #f9f9f9;
+	}
+
+	.uni-select__selector-empty:last-child,
+	.uni-select__selector-item:last-child {
+		/* #ifndef APP-NVUE */
+		border-bottom: none;
+		/* #endif */
+	}
+
+	.uni-select__selector__disabled {
+		opacity: 0.4;
+		cursor: default;
+	}
+
+	/* picker 弹出层通用的指示小三角 */
+	.uni-popper__arrow,
+	.uni-popper__arrow::after {
+		position: absolute;
+		display: block;
+		width: 0;
+		height: 0;
+		border-color: transparent;
+		border-style: solid;
+		border-width: 6px;
+	}
+
+	.uni-popper__arrow {
+		filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+		top: -6px;
+		left: 10%;
+		margin-right: 3px;
+		border-top-width: 0;
+		border-bottom-color: #EBEEF5;
+	}
+
+	.uni-popper__arrow::after {
+		content: " ";
+		top: 1px;
+		margin-left: -6px;
+		border-top-width: 0;
+		border-bottom-color: #fff;
+	}
+
+	.uni-select__input-text {
+		// width: 280px;
+		width: 100%;
+		color: $uni-main-color;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		-o-text-overflow: ellipsis;
+		overflow: hidden;
+	}
+
+	.uni-select__input-placeholder {
+		color: $uni-base-color;
+		font-size: 12px;
+	}
+
+	.uni-select--mask {
+		position: fixed;
+		top: 0;
+		bottom: 0;
+		right: 0;
+		left: 0;
+	}
+</style>

+ 85 - 85
uni_modules/uni-data-select/package.json

@@ -1,85 +1,85 @@
-{
-  "id": "uni-data-select",
-  "displayName": "uni-data-select 下拉框选择器",
-  "version": "0.1.9",
-  "description": "通过数据驱动的下拉框选择器",
-  "keywords": [
-    "uni-ui",
-    "select",
-    "uni-data-select",
-    "下拉框",
-    "下拉选"
-],
-  "repository": "https://github.com/dcloudio/uni-ui",
-  "engines": {
-    "HBuilderX": "^3.1.1"
-  },
-  "directories": {
-    "example": "../../temps/example_temps"
-  },
-"dcloudext": {
-    "sale": {
-      "regular": {
-        "price": "0.00"
-      },
-      "sourcecode": {
-        "price": "0.00"
-      }
-    },
-    "contact": {
-      "qq": ""
-    },
-    "declaration": {
-      "ads": "无",
-      "data": "无",
-      "permissions": "无"
-    },
-    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
-    "type": "component-vue"
-  },
-  "uni_modules": {
-    "dependencies": ["uni-load-more"],
-    "encrypt": [],
-    "platforms": {
-      "cloud": {
-        "tcb": "y",
-        "aliyun": "y"
-      },
-      "client": {
-        "App": {
-          "app-vue": "u",
-          "app-nvue": "n"
-        },
-        "H5-mobile": {
-          "Safari": "y",
-          "Android Browser": "y",
-          "微信浏览器(Android)": "y",
-          "QQ浏览器(Android)": "y"
-        },
-        "H5-pc": {
-          "Chrome": "y",
-          "IE": "y",
-          "Edge": "y",
-          "Firefox": "y",
-          "Safari": "y"
-        },
-        "小程序": {
-          "微信": "y",
-          "阿里": "u",
-          "百度": "u",
-          "字节跳动": "u",
-        "QQ": "u",
-        "京东": "u"
-        },
-        "快应用": {
-          "华为": "u",
-          "联盟": "u"
-        },
-        "Vue": {
-            "vue2": "y",
-            "vue3": "y"
-        }
-      }
-    }
-  }
-}
+{
+  "id": "uni-data-select",
+  "displayName": "uni-data-select 下拉框选择器",
+  "version": "0.1.9",
+  "description": "通过数据驱动的下拉框选择器",
+  "keywords": [
+    "uni-ui",
+    "select",
+    "uni-data-select",
+    "下拉框",
+    "下拉选"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.1.1"
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-load-more"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "u",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+        "QQ": "u",
+        "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 185 - 185
uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue

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

File diff suppressed because it is too large
+ 909 - 909
uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue


+ 20 - 20
uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json

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

+ 7 - 7
uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js

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

File diff suppressed because it is too large
+ 946 - 946
uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue


File diff suppressed because it is too large
+ 1012 - 1012
uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue


+ 389 - 389
uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js

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

+ 183 - 183
uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue

@@ -1,183 +1,183 @@
-<template>
-	<view v-if="visibleSync" :class="{ 'uni-drawer--visible': showDrawer }" class="uni-drawer" @touchmove.stop.prevent="clear">
-		<view class="uni-drawer__mask" :class="{ 'uni-drawer__mask--visible': showDrawer && mask }" @tap="close('mask')" />
-		<view class="uni-drawer__content" :class="{'uni-drawer--right': rightMode,'uni-drawer--left': !rightMode, 'uni-drawer__content--visible': showDrawer}" :style="{width:drawerWidth+'px'}">
-			<slot />
-		</view>
-		<!-- #ifdef H5 -->
-		<keypress @esc="close('mask')" />
-		<!-- #endif -->
-	</view>
-</template>
-
-<script>
-	// #ifdef H5
-	import keypress from './keypress.js'
-	// #endif
-	/**
-	 * Drawer 抽屉
-	 * @description 抽屉侧滑菜单
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=26
-	 * @property {Boolean} mask = [true | false] 是否显示遮罩
-	 * @property {Boolean} maskClick = [true | false] 点击遮罩是否关闭
-	 * @property {Boolean} mode = [left | right] Drawer 滑出位置
-	 * 	@value left 从左侧滑出
-	 * 	@value right 从右侧侧滑出
-	 * @property {Number} width 抽屉的宽度 ,仅 vue 页面生效
-	 * @event {Function} close 组件关闭时触发事件
-	 */
-	export default {
-		name: 'UniDrawer',
-		components: {
-			// #ifdef H5
-			keypress
-			// #endif
-		},
-		emits:['change'],
-		props: {
-			/**
-			 * 显示模式(左、右),只在初始化生效
-			 */
-			mode: {
-				type: String,
-				default: ''
-			},
-			/**
-			 * 蒙层显示状态
-			 */
-			mask: {
-				type: Boolean,
-				default: true
-			},
-			/**
-			 * 遮罩是否可点击关闭
-			 */
-			maskClick:{
-				type: Boolean,
-				default: true
-			},
-			/**
-			 * 抽屉宽度
-			 */
-			width: {
-				type: Number,
-				default: 220
-			}
-		},
-		data() {
-			return {
-				visibleSync: false,
-				showDrawer: false,
-				rightMode: false,
-				watchTimer: null,
-				drawerWidth: 220
-			}
-		},
-		created() {
-			// #ifndef APP-NVUE
-			this.drawerWidth = this.width
-			// #endif
-			this.rightMode = this.mode === 'right'
-		},
-		methods: {
-			clear(){},
-			close(type) {
-				// fixed by mehaotian 抽屉尚未完全关闭或遮罩禁止点击时不触发以下逻辑
-				if((type === 'mask' && !this.maskClick) || !this.visibleSync) return
-				this._change('showDrawer', 'visibleSync', false)
-			},
-			open() {
-				// fixed by mehaotian 处理重复点击打开的事件
-				if(this.visibleSync) return
-				this._change('visibleSync', 'showDrawer', true)
-			},
-			_change(param1, param2, status) {
-				this[param1] = status
-				if (this.watchTimer) {
-					clearTimeout(this.watchTimer)
-				}
-				this.watchTimer = setTimeout(() => {
-					this[param2] = status
-					this.$emit('change',status)
-				}, status ? 50 : 300)
-			}
-		}
-	}
-</script>
-
-<style lang="scss" >
-	$uni-mask: rgba($color: #000000, $alpha: 0.4) ;
-	// 抽屉宽度
-	$drawer-width: 220px;
-
-	.uni-drawer {
-		/* #ifndef APP-NVUE */
-		display: block;
-		/* #endif */
-		position: fixed;
-		top: 0;
-		left: 0;
-		right: 0;
-		bottom: 0;
-		overflow: hidden;
-		z-index: 999;
-	}
-
-	.uni-drawer__content {
-		/* #ifndef APP-NVUE */
-		display: block;
-		/* #endif */
-		position: absolute;
-		top: 0;
-		width: $drawer-width;
-		bottom: 0;
-		background-color: $uni-bg-color;
-		transition: transform 0.3s ease;
-	}
-
-	.uni-drawer--left {
-		left: 0;
-		/* #ifdef APP-NVUE */
-		transform: translateX(-$drawer-width);
-		/* #endif */
-		/* #ifndef APP-NVUE */
-		transform: translateX(-100%);
-		/* #endif */
-	}
-
-	.uni-drawer--right {
-		right: 0;
-		/* #ifdef APP-NVUE */
-		transform: translateX($drawer-width);
-		/* #endif */
-		/* #ifndef APP-NVUE */
-		transform: translateX(100%);
-		/* #endif */
-	}
-
-	.uni-drawer__content--visible {
-		transform: translateX(0px);
-	}
-
-
-	.uni-drawer__mask {
-		/* #ifndef APP-NVUE */
-		display: block;
-		/* #endif */
-		opacity: 0;
-		position: absolute;
-		top: 0;
-		left: 0;
-		bottom: 0;
-		right: 0;
-		background-color: $uni-mask;
-		transition: opacity 0.3s;
-	}
-
-	.uni-drawer__mask--visible {
-		/* #ifndef APP-NVUE */
-		display: block;
-		/* #endif */
-		opacity: 1;
-	}
-</style>
+<template>
+	<view v-if="visibleSync" :class="{ 'uni-drawer--visible': showDrawer }" class="uni-drawer" @touchmove.stop.prevent="clear">
+		<view class="uni-drawer__mask" :class="{ 'uni-drawer__mask--visible': showDrawer && mask }" @tap="close('mask')" />
+		<view class="uni-drawer__content" :class="{'uni-drawer--right': rightMode,'uni-drawer--left': !rightMode, 'uni-drawer__content--visible': showDrawer}" :style="{width:drawerWidth+'px'}">
+			<slot />
+		</view>
+		<!-- #ifdef H5 -->
+		<keypress @esc="close('mask')" />
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	// #ifdef H5
+	import keypress from './keypress.js'
+	// #endif
+	/**
+	 * Drawer 抽屉
+	 * @description 抽屉侧滑菜单
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=26
+	 * @property {Boolean} mask = [true | false] 是否显示遮罩
+	 * @property {Boolean} maskClick = [true | false] 点击遮罩是否关闭
+	 * @property {Boolean} mode = [left | right] Drawer 滑出位置
+	 * 	@value left 从左侧滑出
+	 * 	@value right 从右侧侧滑出
+	 * @property {Number} width 抽屉的宽度 ,仅 vue 页面生效
+	 * @event {Function} close 组件关闭时触发事件
+	 */
+	export default {
+		name: 'UniDrawer',
+		components: {
+			// #ifdef H5
+			keypress
+			// #endif
+		},
+		emits:['change'],
+		props: {
+			/**
+			 * 显示模式(左、右),只在初始化生效
+			 */
+			mode: {
+				type: String,
+				default: ''
+			},
+			/**
+			 * 蒙层显示状态
+			 */
+			mask: {
+				type: Boolean,
+				default: true
+			},
+			/**
+			 * 遮罩是否可点击关闭
+			 */
+			maskClick:{
+				type: Boolean,
+				default: true
+			},
+			/**
+			 * 抽屉宽度
+			 */
+			width: {
+				type: Number,
+				default: 220
+			}
+		},
+		data() {
+			return {
+				visibleSync: false,
+				showDrawer: false,
+				rightMode: false,
+				watchTimer: null,
+				drawerWidth: 220
+			}
+		},
+		created() {
+			// #ifndef APP-NVUE
+			this.drawerWidth = this.width
+			// #endif
+			this.rightMode = this.mode === 'right'
+		},
+		methods: {
+			clear(){},
+			close(type) {
+				// fixed by mehaotian 抽屉尚未完全关闭或遮罩禁止点击时不触发以下逻辑
+				if((type === 'mask' && !this.maskClick) || !this.visibleSync) return
+				this._change('showDrawer', 'visibleSync', false)
+			},
+			open() {
+				// fixed by mehaotian 处理重复点击打开的事件
+				if(this.visibleSync) return
+				this._change('visibleSync', 'showDrawer', true)
+			},
+			_change(param1, param2, status) {
+				this[param1] = status
+				if (this.watchTimer) {
+					clearTimeout(this.watchTimer)
+				}
+				this.watchTimer = setTimeout(() => {
+					this[param2] = status
+					this.$emit('change',status)
+				}, status ? 50 : 300)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	$uni-mask: rgba($color: #000000, $alpha: 0.4) ;
+	// 抽屉宽度
+	$drawer-width: 220px;
+
+	.uni-drawer {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: fixed;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		overflow: hidden;
+		z-index: 999;
+	}
+
+	.uni-drawer__content {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: absolute;
+		top: 0;
+		width: $drawer-width;
+		bottom: 0;
+		background-color: $uni-bg-color;
+		transition: transform 0.3s ease;
+	}
+
+	.uni-drawer--left {
+		left: 0;
+		/* #ifdef APP-NVUE */
+		transform: translateX(-$drawer-width);
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		transform: translateX(-100%);
+		/* #endif */
+	}
+
+	.uni-drawer--right {
+		right: 0;
+		/* #ifdef APP-NVUE */
+		transform: translateX($drawer-width);
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		transform: translateX(100%);
+		/* #endif */
+	}
+
+	.uni-drawer__content--visible {
+		transform: translateX(0px);
+	}
+
+
+	.uni-drawer__mask {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		opacity: 0;
+		position: absolute;
+		top: 0;
+		left: 0;
+		bottom: 0;
+		right: 0;
+		background-color: $uni-mask;
+		transition: opacity 0.3s;
+	}
+
+	.uni-drawer__mask--visible {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		opacity: 1;
+	}
+</style>

+ 55 - 55
uni_modules/uni-easyinput/components/uni-easyinput/common.js

@@ -1,56 +1,56 @@
-/**
- * @desc 函数防抖
- * @param func 目标函数
- * @param wait 延迟执行毫秒数
- * @param immediate true - 立即执行, false - 延迟执行
- */
-export const debounce = function(func, wait = 1000, immediate = true) {
-	let timer;
-	console.log(1);
-	return function() {
-		console.log(123);
-		let context = this,
-			args = arguments;
-		if (timer) clearTimeout(timer);
-		if (immediate) {
-			let callNow = !timer;
-			timer = setTimeout(() => {
-				timer = null;
-			}, wait);
-			if (callNow) func.apply(context, args);
-		} else {
-			timer = setTimeout(() => {
-				func.apply(context, args);
-			}, wait)
-		}
-	}
-}
-/**
- * @desc 函数节流
- * @param func 函数
- * @param wait 延迟执行毫秒数
- * @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
- */
-export const throttle = (func, wait = 1000, type = 1) => {
-	let previous = 0;
-	let timeout;
-	return function() {
-		let context = this;
-		let args = arguments;
-		if (type === 1) {
-			let now = Date.now();
-
-			if (now - previous > wait) {
-				func.apply(context, args);
-				previous = now;
-			}
-		} else if (type === 2) {
-			if (!timeout) {
-				timeout = setTimeout(() => {
-					timeout = null;
-					func.apply(context, args)
-				}, wait)
-			}
-		}
-	}
+/**
+ * @desc 函数防抖
+ * @param func 目标函数
+ * @param wait 延迟执行毫秒数
+ * @param immediate true - 立即执行, false - 延迟执行
+ */
+export const debounce = function(func, wait = 1000, immediate = true) {
+	let timer;
+	console.log(1);
+	return function() {
+		console.log(123);
+		let context = this,
+			args = arguments;
+		if (timer) clearTimeout(timer);
+		if (immediate) {
+			let callNow = !timer;
+			timer = setTimeout(() => {
+				timer = null;
+			}, wait);
+			if (callNow) func.apply(context, args);
+		} else {
+			timer = setTimeout(() => {
+				func.apply(context, args);
+			}, wait)
+		}
+	}
+}
+/**
+ * @desc 函数节流
+ * @param func 函数
+ * @param wait 延迟执行毫秒数
+ * @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
+ */
+export const throttle = (func, wait = 1000, type = 1) => {
+	let previous = 0;
+	let timeout;
+	return function() {
+		let context = this;
+		let args = arguments;
+		if (type === 1) {
+			let now = Date.now();
+
+			if (now - previous > wait) {
+				func.apply(context, args);
+				previous = now;
+			}
+		} else if (type === 2) {
+			if (!timeout) {
+				timeout = setTimeout(() => {
+					timeout = null;
+					func.apply(context, args)
+				}, wait)
+			}
+		}
+	}
 }
 }

File diff suppressed because it is too large
+ 679 - 679
uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue


+ 490 - 490
uni_modules/uni-fab/components/uni-fab/uni-fab.vue

@@ -1,490 +1,490 @@
-<template>
-	<view class="uni-cursor-point">
-		<view v-if="popMenu && (leftBottom||rightBottom||leftTop||rightTop) && content.length > 0" :class="{
-        'uni-fab--leftBottom': leftBottom,
-        'uni-fab--rightBottom': rightBottom,
-        'uni-fab--leftTop': leftTop,
-        'uni-fab--rightTop': rightTop
-      }" class="uni-fab"
-				:style="nvueBottom"
-			>
-			<view :class="{
-          'uni-fab__content--left': horizontal === 'left',
-          'uni-fab__content--right': horizontal === 'right',
-          'uni-fab__content--flexDirection': direction === 'vertical',
-          'uni-fab__content--flexDirectionStart': flexDirectionStart,
-          'uni-fab__content--flexDirectionEnd': flexDirectionEnd,
-		  'uni-fab__content--other-platform': !isAndroidNvue
-        }" :style="{ width: boxWidth, height: boxHeight, backgroundColor: styles.backgroundColor }"
-				class="uni-fab__content" elevation="5">
-				<view v-if="flexDirectionStart || horizontalLeft" class="uni-fab__item uni-fab__item--first" />
-				<view v-for="(item, index) in content" :key="index" :class="{ 'uni-fab__item--active': isShow }"
-					class="uni-fab__item" @click="_onItemClick(index, item)">
-					<image :src="item.active ? item.selectedIconPath : item.iconPath" class="uni-fab__item-image"
-						mode="aspectFit" />
-					<text class="uni-fab__item-text"
-						:style="{ color: item.active ? styles.selectedColor : styles.color }">{{ item.text }}</text>
-				</view>
-				<view v-if="flexDirectionEnd || horizontalRight" class="uni-fab__item uni-fab__item--first" />
-			</view>
-		</view>
-		<view :class="{
-		  'uni-fab__circle--leftBottom': leftBottom,
-		  'uni-fab__circle--rightBottom': rightBottom,
-		  'uni-fab__circle--leftTop': leftTop,
-		  'uni-fab__circle--rightTop': rightTop,
-		  'uni-fab__content--other-platform': !isAndroidNvue
-		}" class="uni-fab__circle uni-fab__plus" :style="{ 'background-color': styles.buttonColor, 'bottom': nvueBottom }" @click="_onClick">
-			<uni-icons class="fab-circle-icon" type="plusempty" :color="styles.iconColor" size="32"
-				:class="{'uni-fab__plus--active': isShow && content.length > 0}"></uni-icons>
-			<!-- <view class="fab-circle-v"  :class="{'uni-fab__plus--active': isShow && content.length > 0}"></view>
-			<view class="fab-circle-h" :class="{'uni-fab__plus--active': isShow  && content.length > 0}"></view> -->
-		</view>
-	</view>
-</template>
-
-<script>
-	let platform = 'other'
-	// #ifdef APP-NVUE
-	platform = uni.getSystemInfoSync().platform
-	// #endif
-
-	/**
-	 * Fab 悬浮按钮
-	 * @description 点击可展开一个图形按钮菜单
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=144
-	 * @property {Object} pattern 可选样式配置项
-	 * @property {Object} horizontal = [left | right] 水平对齐方式
-	 * 	@value left 左对齐
-	 * 	@value right 右对齐
-	 * @property {Object} vertical = [bottom | top] 垂直对齐方式
-	 * 	@value bottom 下对齐
-	 * 	@value top 上对齐
-	 * @property {Object} direction = [horizontal | vertical] 展开菜单显示方式
-	 * 	@value horizontal 水平显示
-	 * 	@value vertical 垂直显示
-	 * @property {Array} content 展开菜单内容配置项
-	 * @property {Boolean} popMenu 是否使用弹出菜单
-	 * @event {Function} trigger 展开菜单点击事件,返回点击信息
-	 * @event {Function} fabClick 悬浮按钮点击事件
-	 */
-	export default {
-		name: 'UniFab',
-		emits: ['fabClick', 'trigger'],
-		props: {
-			pattern: {
-				type: Object,
-				default () {
-					return {}
-				}
-			},
-			horizontal: {
-				type: String,
-				default: 'left'
-			},
-			vertical: {
-				type: String,
-				default: 'bottom'
-			},
-			direction: {
-				type: String,
-				default: 'horizontal'
-			},
-			content: {
-				type: Array,
-				default () {
-					return []
-				}
-			},
-			show: {
-				type: Boolean,
-				default: false
-			},
-			popMenu: {
-				type: Boolean,
-				default: true
-			}
-		},
-		data() {
-			return {
-				fabShow: false,
-				isShow: false,
-				isAndroidNvue: platform === 'android',
-				styles: {
-					color: '#3c3e49',
-					selectedColor: '#007AFF',
-					backgroundColor: '#fff',
-					buttonColor: '#007AFF',
-					iconColor: '#fff'
-				}
-			}
-		},
-		computed: {
-			contentWidth(e) {
-				return (this.content.length + 1) * 55 + 15 + 'px'
-			},
-			contentWidthMin() {
-				return '55px'
-			},
-			// 动态计算宽度
-			boxWidth() {
-				return this.getPosition(3, 'horizontal')
-			},
-			// 动态计算高度
-			boxHeight() {
-				return this.getPosition(3, 'vertical')
-			},
-			// 计算左下位置
-			leftBottom() {
-				return this.getPosition(0, 'left', 'bottom')
-			},
-			// 计算右下位置
-			rightBottom() {
-				return this.getPosition(0, 'right', 'bottom')
-			},
-			// 计算左上位置
-			leftTop() {
-				return this.getPosition(0, 'left', 'top')
-			},
-			rightTop() {
-				return this.getPosition(0, 'right', 'top')
-			},
-			flexDirectionStart() {
-				return this.getPosition(1, 'vertical', 'top')
-			},
-			flexDirectionEnd() {
-				return this.getPosition(1, 'vertical', 'bottom')
-			},
-			horizontalLeft() {
-				return this.getPosition(2, 'horizontal', 'left')
-			},
-			horizontalRight() {
-				return this.getPosition(2, 'horizontal', 'right')
-			},
-			// 计算 nvue bottom
-			nvueBottom() {
-				const safeBottom = uni.getSystemInfoSync().windowBottom;
-				// #ifdef APP-NVUE
-				return 30 + safeBottom
-				// #endif
-				// #ifndef APP-NVUE
-				return 30
-				// #endif
-			}
-		},
-		watch: {
-			pattern: {
-				handler(val, oldVal) {
-					this.styles = Object.assign({}, this.styles, val)
-				},
-				deep: true
-			}
-		},
-		created() {
-			this.isShow = this.show
-			if (this.top === 0) {
-				this.fabShow = true
-			}
-			// 初始化样式
-			this.styles = Object.assign({}, this.styles, this.pattern)
-		},
-		methods: {
-			_onClick() {
-				this.$emit('fabClick')
-				if (!this.popMenu) {
-					return
-				}
-				this.isShow = !this.isShow
-			},
-			open() {
-				this.isShow = true
-			},
-			close() {
-				this.isShow = false
-			},
-			/**
-			 * 按钮点击事件
-			 */
-			_onItemClick(index, item) {
-				if (!this.isShow) {
-					return
-				}
-				this.$emit('trigger', {
-					index,
-					item
-				})
-			},
-			/**
-			 * 获取 位置信息
-			 */
-			getPosition(types, paramA, paramB) {
-				if (types === 0) {
-					return this.horizontal === paramA && this.vertical === paramB
-				} else if (types === 1) {
-					return this.direction === paramA && this.vertical === paramB
-				} else if (types === 2) {
-					return this.direction === paramA && this.horizontal === paramB
-				} else {
-					return this.isShow && this.direction === paramA ? this.contentWidth : this.contentWidthMin
-				}
-			}
-		}
-	}
-</script>
-
-<style lang="scss" >
-	$uni-shadow-base:0 1px 5px 2px rgba($color: #000000, $alpha: 0.3) !default;
-
-	.uni-fab {
-		position: fixed;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		justify-content: center;
-		align-items: center;
-		z-index: 10;
-		border-radius: 45px;
-		box-shadow: $uni-shadow-base;
-	}
-
-	.uni-cursor-point {
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-fab--active {
-		opacity: 1;
-	}
-
-	.uni-fab--leftBottom {
-		left: 15px;
-		bottom: 30px;
-		/* #ifdef H5 */
-		left: calc(15px + var(--window-left));
-		bottom: calc(30px + var(--window-bottom));
-		/* #endif */
-		// padding: 10px;
-	}
-
-	.uni-fab--leftTop {
-		left: 15px;
-		top: 30px;
-		/* #ifdef H5 */
-		left: calc(15px + var(--window-left));
-		top: calc(30px + var(--window-top));
-		/* #endif */
-		// padding: 10px;
-	}
-
-	.uni-fab--rightBottom {
-		right: 15px;
-		bottom: 30px;
-		/* #ifdef H5 */
-		right: calc(15px + var(--window-right));
-		bottom: calc(30px + var(--window-bottom));
-		/* #endif */
-		// padding: 10px;
-	}
-
-	.uni-fab--rightTop {
-		right: 15px;
-		top: 30px;
-		/* #ifdef H5 */
-		right: calc(15px + var(--window-right));
-		top: calc(30px + var(--window-top));
-		/* #endif */
-		// padding: 10px;
-	}
-
-	.uni-fab__circle {
-		position: fixed;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		justify-content: center;
-		align-items: center;
-		width: 55px;
-		height: 55px;
-		background-color: #3c3e49;
-		border-radius: 45px;
-		z-index: 11;
-		// box-shadow: $uni-shadow-base;
-	}
-
-	.uni-fab__circle--leftBottom {
-		left: 15px;
-		bottom: 30px;
-		/* #ifdef H5 */
-		left: calc(15px + var(--window-left));
-		bottom: calc(30px + var(--window-bottom));
-		/* #endif */
-	}
-
-	.uni-fab__circle--leftTop {
-		left: 15px;
-		top: 30px;
-		/* #ifdef H5 */
-		left: calc(15px + var(--window-left));
-		top: calc(30px + var(--window-top));
-		/* #endif */
-	}
-
-	.uni-fab__circle--rightBottom {
-		right: 15px;
-		bottom: 30px;
-		/* #ifdef H5 */
-		right: calc(15px + var(--window-right));
-		bottom: calc(30px + var(--window-bottom));
-		/* #endif */
-	}
-
-	.uni-fab__circle--rightTop {
-		right: 15px;
-		top: 30px;
-		/* #ifdef H5 */
-		right: calc(15px + var(--window-right));
-		top: calc(30px + var(--window-top));
-		/* #endif */
-	}
-
-	.uni-fab__circle--left {
-		left: 0;
-	}
-
-	.uni-fab__circle--right {
-		right: 0;
-	}
-
-	.uni-fab__circle--top {
-		top: 0;
-	}
-
-	.uni-fab__circle--bottom {
-		bottom: 0;
-	}
-
-	.uni-fab__plus {
-		font-weight: bold;
-	}
-
-	// .fab-circle-v {
-	// 	position: absolute;
-	// 	width: 2px;
-	// 	height: 24px;
-	// 	left: 0;
-	// 	top: 0;
-	// 	right: 0;
-	// 	bottom: 0;
-	// 	/* #ifndef APP-NVUE */
-	// 	margin: auto;
-	// 	/* #endif */
-	// 	background-color: white;
-	// 	transform: rotate(0deg);
-	// 	transition: transform 0.3s;
-	// }
-
-	// .fab-circle-h {
-	// 	position: absolute;
-	// 	width: 24px;
-	// 	height: 2px;
-	// 	left: 0;
-	// 	top: 0;
-	// 	right: 0;
-	// 	bottom: 0;
-	// 	/* #ifndef APP-NVUE */
-	// 	margin: auto;
-	// 	/* #endif */
-	// 	background-color: white;
-	// 	transform: rotate(0deg);
-	// 	transition: transform 0.3s;
-	// }
-
-	.fab-circle-icon {
-		transform: rotate(0deg);
-		transition: transform 0.3s;
-		font-weight: 200;
-	}
-
-	.uni-fab__plus--active {
-		transform: rotate(135deg);
-	}
-
-	.uni-fab__content {
-		/* #ifndef APP-NVUE */
-		box-sizing: border-box;
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-		border-radius: 55px;
-		overflow: hidden;
-		transition-property: width, height;
-		transition-duration: 0.2s;
-		width: 55px;
-		border-color: #DDDDDD;
-		border-width: 1rpx;
-		border-style: solid;
-	}
-
-	.uni-fab__content--other-platform {
-		border-width: 0px;
-		box-shadow: $uni-shadow-base;
-	}
-
-	.uni-fab__content--left {
-		justify-content: flex-start;
-	}
-
-	.uni-fab__content--right {
-		justify-content: flex-end;
-	}
-
-	.uni-fab__content--flexDirection {
-		flex-direction: column;
-		justify-content: flex-end;
-	}
-
-	.uni-fab__content--flexDirectionStart {
-		flex-direction: column;
-		justify-content: flex-start;
-	}
-
-	.uni-fab__content--flexDirectionEnd {
-		flex-direction: column;
-		justify-content: flex-end;
-	}
-
-	.uni-fab__item {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: column;
-		justify-content: center;
-		align-items: center;
-		width: 55px;
-		height: 55px;
-		opacity: 0;
-		transition: opacity 0.2s;
-	}
-
-	.uni-fab__item--active {
-		opacity: 1;
-	}
-
-	.uni-fab__item-image {
-		width: 20px;
-		height: 20px;
-		margin-bottom: 4px;
-	}
-
-	.uni-fab__item-text {
-		color: #FFFFFF;
-		font-size: 12px;
-		line-height: 12px;
-		margin-top: 2px;
-	}
-
-	.uni-fab__item--first {
-		width: 55px;
-	}
-</style>
+<template>
+	<view class="uni-cursor-point">
+		<view v-if="popMenu && (leftBottom||rightBottom||leftTop||rightTop) && content.length > 0" :class="{
+        'uni-fab--leftBottom': leftBottom,
+        'uni-fab--rightBottom': rightBottom,
+        'uni-fab--leftTop': leftTop,
+        'uni-fab--rightTop': rightTop
+      }" class="uni-fab"
+				:style="nvueBottom"
+			>
+			<view :class="{
+          'uni-fab__content--left': horizontal === 'left',
+          'uni-fab__content--right': horizontal === 'right',
+          'uni-fab__content--flexDirection': direction === 'vertical',
+          'uni-fab__content--flexDirectionStart': flexDirectionStart,
+          'uni-fab__content--flexDirectionEnd': flexDirectionEnd,
+		  'uni-fab__content--other-platform': !isAndroidNvue
+        }" :style="{ width: boxWidth, height: boxHeight, backgroundColor: styles.backgroundColor }"
+				class="uni-fab__content" elevation="5">
+				<view v-if="flexDirectionStart || horizontalLeft" class="uni-fab__item uni-fab__item--first" />
+				<view v-for="(item, index) in content" :key="index" :class="{ 'uni-fab__item--active': isShow }"
+					class="uni-fab__item" @click="_onItemClick(index, item)">
+					<image :src="item.active ? item.selectedIconPath : item.iconPath" class="uni-fab__item-image"
+						mode="aspectFit" />
+					<text class="uni-fab__item-text"
+						:style="{ color: item.active ? styles.selectedColor : styles.color }">{{ item.text }}</text>
+				</view>
+				<view v-if="flexDirectionEnd || horizontalRight" class="uni-fab__item uni-fab__item--first" />
+			</view>
+		</view>
+		<view :class="{
+		  'uni-fab__circle--leftBottom': leftBottom,
+		  'uni-fab__circle--rightBottom': rightBottom,
+		  'uni-fab__circle--leftTop': leftTop,
+		  'uni-fab__circle--rightTop': rightTop,
+		  'uni-fab__content--other-platform': !isAndroidNvue
+		}" class="uni-fab__circle uni-fab__plus" :style="{ 'background-color': styles.buttonColor, 'bottom': nvueBottom }" @click="_onClick">
+			<uni-icons class="fab-circle-icon" type="plusempty" :color="styles.iconColor" size="32"
+				:class="{'uni-fab__plus--active': isShow && content.length > 0}"></uni-icons>
+			<!-- <view class="fab-circle-v"  :class="{'uni-fab__plus--active': isShow && content.length > 0}"></view>
+			<view class="fab-circle-h" :class="{'uni-fab__plus--active': isShow  && content.length > 0}"></view> -->
+		</view>
+	</view>
+</template>
+
+<script>
+	let platform = 'other'
+	// #ifdef APP-NVUE
+	platform = uni.getSystemInfoSync().platform
+	// #endif
+
+	/**
+	 * Fab 悬浮按钮
+	 * @description 点击可展开一个图形按钮菜单
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=144
+	 * @property {Object} pattern 可选样式配置项
+	 * @property {Object} horizontal = [left | right] 水平对齐方式
+	 * 	@value left 左对齐
+	 * 	@value right 右对齐
+	 * @property {Object} vertical = [bottom | top] 垂直对齐方式
+	 * 	@value bottom 下对齐
+	 * 	@value top 上对齐
+	 * @property {Object} direction = [horizontal | vertical] 展开菜单显示方式
+	 * 	@value horizontal 水平显示
+	 * 	@value vertical 垂直显示
+	 * @property {Array} content 展开菜单内容配置项
+	 * @property {Boolean} popMenu 是否使用弹出菜单
+	 * @event {Function} trigger 展开菜单点击事件,返回点击信息
+	 * @event {Function} fabClick 悬浮按钮点击事件
+	 */
+	export default {
+		name: 'UniFab',
+		emits: ['fabClick', 'trigger'],
+		props: {
+			pattern: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			horizontal: {
+				type: String,
+				default: 'left'
+			},
+			vertical: {
+				type: String,
+				default: 'bottom'
+			},
+			direction: {
+				type: String,
+				default: 'horizontal'
+			},
+			content: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			show: {
+				type: Boolean,
+				default: false
+			},
+			popMenu: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				fabShow: false,
+				isShow: false,
+				isAndroidNvue: platform === 'android',
+				styles: {
+					color: '#3c3e49',
+					selectedColor: '#007AFF',
+					backgroundColor: '#fff',
+					buttonColor: '#007AFF',
+					iconColor: '#fff'
+				}
+			}
+		},
+		computed: {
+			contentWidth(e) {
+				return (this.content.length + 1) * 55 + 15 + 'px'
+			},
+			contentWidthMin() {
+				return '55px'
+			},
+			// 动态计算宽度
+			boxWidth() {
+				return this.getPosition(3, 'horizontal')
+			},
+			// 动态计算高度
+			boxHeight() {
+				return this.getPosition(3, 'vertical')
+			},
+			// 计算左下位置
+			leftBottom() {
+				return this.getPosition(0, 'left', 'bottom')
+			},
+			// 计算右下位置
+			rightBottom() {
+				return this.getPosition(0, 'right', 'bottom')
+			},
+			// 计算左上位置
+			leftTop() {
+				return this.getPosition(0, 'left', 'top')
+			},
+			rightTop() {
+				return this.getPosition(0, 'right', 'top')
+			},
+			flexDirectionStart() {
+				return this.getPosition(1, 'vertical', 'top')
+			},
+			flexDirectionEnd() {
+				return this.getPosition(1, 'vertical', 'bottom')
+			},
+			horizontalLeft() {
+				return this.getPosition(2, 'horizontal', 'left')
+			},
+			horizontalRight() {
+				return this.getPosition(2, 'horizontal', 'right')
+			},
+			// 计算 nvue bottom
+			nvueBottom() {
+				const safeBottom = uni.getSystemInfoSync().windowBottom;
+				// #ifdef APP-NVUE
+				return 30 + safeBottom
+				// #endif
+				// #ifndef APP-NVUE
+				return 30
+				// #endif
+			}
+		},
+		watch: {
+			pattern: {
+				handler(val, oldVal) {
+					this.styles = Object.assign({}, this.styles, val)
+				},
+				deep: true
+			}
+		},
+		created() {
+			this.isShow = this.show
+			if (this.top === 0) {
+				this.fabShow = true
+			}
+			// 初始化样式
+			this.styles = Object.assign({}, this.styles, this.pattern)
+		},
+		methods: {
+			_onClick() {
+				this.$emit('fabClick')
+				if (!this.popMenu) {
+					return
+				}
+				this.isShow = !this.isShow
+			},
+			open() {
+				this.isShow = true
+			},
+			close() {
+				this.isShow = false
+			},
+			/**
+			 * 按钮点击事件
+			 */
+			_onItemClick(index, item) {
+				if (!this.isShow) {
+					return
+				}
+				this.$emit('trigger', {
+					index,
+					item
+				})
+			},
+			/**
+			 * 获取 位置信息
+			 */
+			getPosition(types, paramA, paramB) {
+				if (types === 0) {
+					return this.horizontal === paramA && this.vertical === paramB
+				} else if (types === 1) {
+					return this.direction === paramA && this.vertical === paramB
+				} else if (types === 2) {
+					return this.direction === paramA && this.horizontal === paramB
+				} else {
+					return this.isShow && this.direction === paramA ? this.contentWidth : this.contentWidthMin
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	$uni-shadow-base:0 1px 5px 2px rgba($color: #000000, $alpha: 0.3) !default;
+
+	.uni-fab {
+		position: fixed;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		z-index: 10;
+		border-radius: 45px;
+		box-shadow: $uni-shadow-base;
+	}
+
+	.uni-cursor-point {
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-fab--active {
+		opacity: 1;
+	}
+
+	.uni-fab--leftBottom {
+		left: 15px;
+		bottom: 30px;
+		/* #ifdef H5 */
+		left: calc(15px + var(--window-left));
+		bottom: calc(30px + var(--window-bottom));
+		/* #endif */
+		// padding: 10px;
+	}
+
+	.uni-fab--leftTop {
+		left: 15px;
+		top: 30px;
+		/* #ifdef H5 */
+		left: calc(15px + var(--window-left));
+		top: calc(30px + var(--window-top));
+		/* #endif */
+		// padding: 10px;
+	}
+
+	.uni-fab--rightBottom {
+		right: 15px;
+		bottom: 30px;
+		/* #ifdef H5 */
+		right: calc(15px + var(--window-right));
+		bottom: calc(30px + var(--window-bottom));
+		/* #endif */
+		// padding: 10px;
+	}
+
+	.uni-fab--rightTop {
+		right: 15px;
+		top: 30px;
+		/* #ifdef H5 */
+		right: calc(15px + var(--window-right));
+		top: calc(30px + var(--window-top));
+		/* #endif */
+		// padding: 10px;
+	}
+
+	.uni-fab__circle {
+		position: fixed;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		width: 55px;
+		height: 55px;
+		background-color: #3c3e49;
+		border-radius: 45px;
+		z-index: 11;
+		// box-shadow: $uni-shadow-base;
+	}
+
+	.uni-fab__circle--leftBottom {
+		left: 15px;
+		bottom: 30px;
+		/* #ifdef H5 */
+		left: calc(15px + var(--window-left));
+		bottom: calc(30px + var(--window-bottom));
+		/* #endif */
+	}
+
+	.uni-fab__circle--leftTop {
+		left: 15px;
+		top: 30px;
+		/* #ifdef H5 */
+		left: calc(15px + var(--window-left));
+		top: calc(30px + var(--window-top));
+		/* #endif */
+	}
+
+	.uni-fab__circle--rightBottom {
+		right: 15px;
+		bottom: 30px;
+		/* #ifdef H5 */
+		right: calc(15px + var(--window-right));
+		bottom: calc(30px + var(--window-bottom));
+		/* #endif */
+	}
+
+	.uni-fab__circle--rightTop {
+		right: 15px;
+		top: 30px;
+		/* #ifdef H5 */
+		right: calc(15px + var(--window-right));
+		top: calc(30px + var(--window-top));
+		/* #endif */
+	}
+
+	.uni-fab__circle--left {
+		left: 0;
+	}
+
+	.uni-fab__circle--right {
+		right: 0;
+	}
+
+	.uni-fab__circle--top {
+		top: 0;
+	}
+
+	.uni-fab__circle--bottom {
+		bottom: 0;
+	}
+
+	.uni-fab__plus {
+		font-weight: bold;
+	}
+
+	// .fab-circle-v {
+	// 	position: absolute;
+	// 	width: 2px;
+	// 	height: 24px;
+	// 	left: 0;
+	// 	top: 0;
+	// 	right: 0;
+	// 	bottom: 0;
+	// 	/* #ifndef APP-NVUE */
+	// 	margin: auto;
+	// 	/* #endif */
+	// 	background-color: white;
+	// 	transform: rotate(0deg);
+	// 	transition: transform 0.3s;
+	// }
+
+	// .fab-circle-h {
+	// 	position: absolute;
+	// 	width: 24px;
+	// 	height: 2px;
+	// 	left: 0;
+	// 	top: 0;
+	// 	right: 0;
+	// 	bottom: 0;
+	// 	/* #ifndef APP-NVUE */
+	// 	margin: auto;
+	// 	/* #endif */
+	// 	background-color: white;
+	// 	transform: rotate(0deg);
+	// 	transition: transform 0.3s;
+	// }
+
+	.fab-circle-icon {
+		transform: rotate(0deg);
+		transition: transform 0.3s;
+		font-weight: 200;
+	}
+
+	.uni-fab__plus--active {
+		transform: rotate(135deg);
+	}
+
+	.uni-fab__content {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		border-radius: 55px;
+		overflow: hidden;
+		transition-property: width, height;
+		transition-duration: 0.2s;
+		width: 55px;
+		border-color: #DDDDDD;
+		border-width: 1rpx;
+		border-style: solid;
+	}
+
+	.uni-fab__content--other-platform {
+		border-width: 0px;
+		box-shadow: $uni-shadow-base;
+	}
+
+	.uni-fab__content--left {
+		justify-content: flex-start;
+	}
+
+	.uni-fab__content--right {
+		justify-content: flex-end;
+	}
+
+	.uni-fab__content--flexDirection {
+		flex-direction: column;
+		justify-content: flex-end;
+	}
+
+	.uni-fab__content--flexDirectionStart {
+		flex-direction: column;
+		justify-content: flex-start;
+	}
+
+	.uni-fab__content--flexDirectionEnd {
+		flex-direction: column;
+		justify-content: flex-end;
+	}
+
+	.uni-fab__item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		width: 55px;
+		height: 55px;
+		opacity: 0;
+		transition: opacity 0.2s;
+	}
+
+	.uni-fab__item--active {
+		opacity: 1;
+	}
+
+	.uni-fab__item-image {
+		width: 20px;
+		height: 20px;
+		margin-bottom: 4px;
+	}
+
+	.uni-fab__item-text {
+		color: #FFFFFF;
+		font-size: 12px;
+		line-height: 12px;
+		margin-top: 2px;
+	}
+
+	.uni-fab__item--first {
+		width: 55px;
+	}
+</style>

+ 3 - 3
uni_modules/uni-fav/components/uni-fav/i18n/en.json

@@ -1,4 +1,4 @@
-{
-	"uni-fav.collect": "collect",
-	"uni-fav.collected": "collected"
+{
+	"uni-fav.collect": "collect",
+	"uni-fav.collected": "collected"
 }
 }

+ 7 - 7
uni_modules/uni-fav/components/uni-fav/i18n/index.js

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

+ 3 - 3
uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json

@@ -1,4 +1,4 @@
-{
-	"uni-fav.collect": "收藏",
-	"uni-fav.collected": "已收藏"
+{
+	"uni-fav.collect": "收藏",
+	"uni-fav.collected": "已收藏"
 }
 }

+ 3 - 3
uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json

@@ -1,4 +1,4 @@
-{
-	"uni-fav.collect": "收藏",
-	"uni-fav.collected": "已收藏"
+{
+	"uni-fav.collect": "收藏",
+	"uni-fav.collected": "已收藏"
 }
 }

+ 155 - 155
uni_modules/uni-fav/components/uni-fav/uni-fav.vue

@@ -1,161 +1,161 @@
-<template>
-	<view :class="[circle === true || circle === 'true' ? 'uni-fav--circle' : '']" :style="[{ backgroundColor: checked ? bgColorChecked : bgColor }]"
-	 @click="onClick" class="uni-fav">
-		<!-- #ifdef MP-ALIPAY -->
-		<view class="uni-fav-star" v-if="!checked && (star === true || star === 'true')">
-			<uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" size="14" type="star-filled" />
-		</view>
-		<!-- #endif -->
-		<!-- #ifndef MP-ALIPAY -->
-		<uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-star" size="14" type="star-filled"
-		 v-if="!checked && (star === true || star === 'true')" />
-		<!-- #endif -->
-		<text :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-text">{{ checked ? contentFav : contentDefault }}</text>
-	</view>
-</template>
-
-<script>
-
-	/**
-	 * Fav 收藏按钮
-	 * @description 用于收藏功能,可点击切换选中、不选中的状态
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=864
-	 * @property {Boolean} star = [true|false] 按钮是否带星星
-	 * @property {String} bgColor 未收藏时的背景色
-	 * @property {String} bgColorChecked 已收藏时的背景色
-	 * @property {String} fgColor 未收藏时的文字颜色
-	 * @property {String} fgColorChecked 已收藏时的文字颜色
-	 * @property {Boolean} circle = [true|false] 是否为圆角
-	 * @property {Boolean} checked = [true|false] 是否为已收藏
+<template>
+	<view :class="[circle === true || circle === 'true' ? 'uni-fav--circle' : '']" :style="[{ backgroundColor: checked ? bgColorChecked : bgColor }]"
+	 @click="onClick" class="uni-fav">
+		<!-- #ifdef MP-ALIPAY -->
+		<view class="uni-fav-star" v-if="!checked && (star === true || star === 'true')">
+			<uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" size="14" type="star-filled" />
+		</view>
+		<!-- #endif -->
+		<!-- #ifndef MP-ALIPAY -->
+		<uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-star" size="14" type="star-filled"
+		 v-if="!checked && (star === true || star === 'true')" />
+		<!-- #endif -->
+		<text :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-text">{{ checked ? contentFav : contentDefault }}</text>
+	</view>
+</template>
+
+<script>
+
+	/**
+	 * Fav 收藏按钮
+	 * @description 用于收藏功能,可点击切换选中、不选中的状态
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=864
+	 * @property {Boolean} star = [true|false] 按钮是否带星星
+	 * @property {String} bgColor 未收藏时的背景色
+	 * @property {String} bgColorChecked 已收藏时的背景色
+	 * @property {String} fgColor 未收藏时的文字颜色
+	 * @property {String} fgColorChecked 已收藏时的文字颜色
+	 * @property {Boolean} circle = [true|false] 是否为圆角
+	 * @property {Boolean} checked = [true|false] 是否为已收藏
 	 * @property {Object} contentText = [true|false] 收藏按钮文字
 	 * @property {Object} contentText = [true|false] 收藏按钮文字
-	 * @property {Boolean} stat 是否开启统计功能
-	 * @event {Function} click 点击 fav按钮触发事件
-	 * @example <uni-fav :checked="true"/>
-	 */
-
-	import {
-		initVueI18n
-	} from '@dcloudio/uni-i18n'
-	import messages from './i18n/index.js'
-	const {	t	} = initVueI18n(messages)
-
-	export default {
-		name: "UniFav",
-		// TODO 兼容 vue3,需要注册事件
-		emits: ['click'],
-		props: {
-			star: {
-				type: [Boolean, String],
-				default: true
-			},
-			bgColor: {
-				type: String,
-				default: "#eeeeee"
-			},
-			fgColor: {
-				type: String,
-				default: "#666666"
-			},
-			bgColorChecked: {
-				type: String,
-				default: "#007aff"
-			},
-			fgColorChecked: {
-				type: String,
-				default: "#FFFFFF"
-			},
-			circle: {
-				type: [Boolean, String],
-				default: false
-			},
-			checked: {
-				type: Boolean,
-				default: false
-			},
-			contentText: {
-				type: Object,
-				default () {
-					return {
-						contentDefault: "",
-						contentFav: ""
-					};
-				}
+	 * @property {Boolean} stat 是否开启统计功能
+	 * @event {Function} click 点击 fav按钮触发事件
+	 * @example <uni-fav :checked="true"/>
+	 */
+
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+
+	export default {
+		name: "UniFav",
+		// TODO 兼容 vue3,需要注册事件
+		emits: ['click'],
+		props: {
+			star: {
+				type: [Boolean, String],
+				default: true
+			},
+			bgColor: {
+				type: String,
+				default: "#eeeeee"
+			},
+			fgColor: {
+				type: String,
+				default: "#666666"
+			},
+			bgColorChecked: {
+				type: String,
+				default: "#007aff"
+			},
+			fgColorChecked: {
+				type: String,
+				default: "#FFFFFF"
+			},
+			circle: {
+				type: [Boolean, String],
+				default: false
+			},
+			checked: {
+				type: Boolean,
+				default: false
+			},
+			contentText: {
+				type: Object,
+				default () {
+					return {
+						contentDefault: "",
+						contentFav: ""
+					};
+				}
 			},
 			},
 			stat:{
 			stat:{
 				type: Boolean,
 				type: Boolean,
 				default: false
 				default: false
-			}
-		},
-		computed: {
-			contentDefault() {
-				return this.contentText.contentDefault || t("uni-fav.collect")
-			},
-			contentFav() {
-				return this.contentText.contentFav || t("uni-fav.collected")
-			},
-		},
-		watch: {
+			}
+		},
+		computed: {
+			contentDefault() {
+				return this.contentText.contentDefault || t("uni-fav.collect")
+			},
+			contentFav() {
+				return this.contentText.contentFav || t("uni-fav.collected")
+			},
+		},
+		watch: {
 			checked() {
 			checked() {
-				if (uni.report && this.stat) {
-					if (this.checked) {
-						uni.report("收藏", "收藏");
-					} else {
-						uni.report("取消收藏", "取消收藏");
-					}
-				}
-			}
-		},
-		methods: {
-			onClick() {
-				this.$emit("click");
-			}
-		}
-	};
-</script>
-
-<style lang="scss" >
-	$fav-height: 25px;
-
-	.uni-fav {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-		align-items: center;
-		justify-content: center;
-		width: 60px;
-		height: $fav-height;
-		line-height: $fav-height;
-		text-align: center;
-		border-radius: 3px;
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-fav--circle {
-		border-radius: 30px;
-	}
-
-	.uni-fav-star {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		height: $fav-height;
-		line-height: 24px;
-		margin-right: 3px;
-		align-items: center;
-		justify-content: center;
-	}
-
-	.uni-fav-text {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		height: $fav-height;
-		line-height: $fav-height;
-		align-items: center;
-		justify-content: center;
-		font-size: 12px;
-	}
-</style>
+				if (uni.report && this.stat) {
+					if (this.checked) {
+						uni.report("收藏", "收藏");
+					} else {
+						uni.report("取消收藏", "取消收藏");
+					}
+				}
+			}
+		},
+		methods: {
+			onClick() {
+				this.$emit("click");
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$fav-height: 25px;
+
+	.uni-fav {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		width: 60px;
+		height: $fav-height;
+		line-height: $fav-height;
+		text-align: center;
+		border-radius: 3px;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-fav--circle {
+		border-radius: 30px;
+	}
+
+	.uni-fav-star {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		height: $fav-height;
+		line-height: 24px;
+		margin-right: 3px;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-fav-text {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		height: $fav-height;
+		line-height: $fav-height;
+		align-items: center;
+		justify-content: center;
+		font-size: 12px;
+	}
+</style>

+ 223 - 223
uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js

@@ -1,224 +1,224 @@
-'use strict';
-
-const ERR_MSG_OK = 'chooseAndUploadFile:ok';
-const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
-
-function chooseImage(opts) {
-	const {
-		count,
-		sizeType = ['original', 'compressed'],
-		sourceType = ['album', 'camera'],
-		extension
-	} = opts
-	return new Promise((resolve, reject) => {
-		uni.chooseImage({
-			count,
-			sizeType,
-			sourceType,
-			extension,
-			success(res) {
-				resolve(normalizeChooseAndUploadFileRes(res, 'image'));
-			},
-			fail(res) {
-				reject({
-					errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
-				});
-			},
-		});
-	});
-}
-
-function chooseVideo(opts) {
-	const {
-		camera,
-		compressed,
-		maxDuration,
-		sourceType = ['album', 'camera'],
-		extension
-	} = opts;
-	return new Promise((resolve, reject) => {
-		uni.chooseVideo({
-			camera,
-			compressed,
-			maxDuration,
-			sourceType,
-			extension,
-			success(res) {
-				const {
-					tempFilePath,
-					duration,
-					size,
-					height,
-					width
-				} = res;
-				resolve(normalizeChooseAndUploadFileRes({
-					errMsg: 'chooseVideo:ok',
-					tempFilePaths: [tempFilePath],
-					tempFiles: [
-					{
-						name: (res.tempFile && res.tempFile.name) || '',
-						path: tempFilePath,
-						size,
-						type: (res.tempFile && res.tempFile.type) || '',
-						width,
-						height,
-						duration,
-						fileType: 'video',
-						cloudPath: '',
-					}, ],
-				}, 'video'));
-			},
-			fail(res) {
-				reject({
-					errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
-				});
-			},
-		});
-	});
-}
-
-function chooseAll(opts) {
-	const {
-		count,
-		extension
-	} = opts;
-	return new Promise((resolve, reject) => {
-		let chooseFile = uni.chooseFile;
-		if (typeof wx !== 'undefined' &&
-			typeof wx.chooseMessageFile === 'function') {
-			chooseFile = wx.chooseMessageFile;
-		}
-		if (typeof chooseFile !== 'function') {
-			return reject({
-				errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
-			});
-		}
-		chooseFile({
-			type: 'all',
-			count,
-			extension,
-			success(res) {
-				resolve(normalizeChooseAndUploadFileRes(res));
-			},
-			fail(res) {
-				reject({
-					errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
-				});
-			},
-		});
-	});
-}
-
-function normalizeChooseAndUploadFileRes(res, fileType) {
-	res.tempFiles.forEach((item, index) => {
-		if (!item.name) {
-			item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
-		}
-		if (fileType) {
-			item.fileType = fileType;
-		}
-		item.cloudPath =
-			Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
-	});
-	if (!res.tempFilePaths) {
-		res.tempFilePaths = res.tempFiles.map((file) => file.path);
-	}
-	return res;
-}
-
-function uploadCloudFiles(files, max = 5, onUploadProgress) {
-	files = JSON.parse(JSON.stringify(files))
-	const len = files.length
-	let count = 0
-	let self = this
-	return new Promise(resolve => {
-		while (count < max) {
-			next()
-		}
-
-		function next() {
-			let cur = count++
-			if (cur >= len) {
-				!files.find(item => !item.url && !item.errMsg) && resolve(files)
-				return
-			}
-			const fileItem = files[cur]
-			const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
-			fileItem.url = ''
-			delete fileItem.errMsg
-
-			uniCloud
-				.uploadFile({
-					filePath: fileItem.path,
-					cloudPath: fileItem.cloudPath,
-					fileType: fileItem.fileType,
-					onUploadProgress: res => {
-						res.index = index
-						onUploadProgress && onUploadProgress(res)
-					}
-				})
-				.then(res => {
-					fileItem.url = res.fileID
-					fileItem.index = index
-					if (cur < len) {
-						next()
-					}
-				})
-				.catch(res => {
-					fileItem.errMsg = res.errMsg || res.message
-					fileItem.index = index
-					if (cur < len) {
-						next()
-					}
-				})
-		}
-	})
-}
-
-
-
-
-
-function uploadFiles(choosePromise, {
-	onChooseFile,
-	onUploadProgress
-}) {
-	return choosePromise
-		.then((res) => {
-			if (onChooseFile) {
-				const customChooseRes = onChooseFile(res);
-				if (typeof customChooseRes !== 'undefined') {
-					return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
-						res : chooseRes);
-				}
-			}
-			return res;
-		})
-		.then((res) => {
-			if (res === false) {
-				return {
-					errMsg: ERR_MSG_OK,
-					tempFilePaths: [],
-					tempFiles: [],
-				};
-			}
-			return res
-		})
-}
-
-function chooseAndUploadFile(opts = {
-	type: 'all'
-}) {
-	if (opts.type === 'image') {
-		return uploadFiles(chooseImage(opts), opts);
-	}
-	else if (opts.type === 'video') {
-		return uploadFiles(chooseVideo(opts), opts);
-	}
-	return uploadFiles(chooseAll(opts), opts);
-}
-
-export {
-	chooseAndUploadFile,
-	uploadCloudFiles
+'use strict';
+
+const ERR_MSG_OK = 'chooseAndUploadFile:ok';
+const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
+
+function chooseImage(opts) {
+	const {
+		count,
+		sizeType = ['original', 'compressed'],
+		sourceType = ['album', 'camera'],
+		extension
+	} = opts
+	return new Promise((resolve, reject) => {
+		uni.chooseImage({
+			count,
+			sizeType,
+			sourceType,
+			extension,
+			success(res) {
+				resolve(normalizeChooseAndUploadFileRes(res, 'image'));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
+				});
+			},
+		});
+	});
+}
+
+function chooseVideo(opts) {
+	const {
+		camera,
+		compressed,
+		maxDuration,
+		sourceType = ['album', 'camera'],
+		extension
+	} = opts;
+	return new Promise((resolve, reject) => {
+		uni.chooseVideo({
+			camera,
+			compressed,
+			maxDuration,
+			sourceType,
+			extension,
+			success(res) {
+				const {
+					tempFilePath,
+					duration,
+					size,
+					height,
+					width
+				} = res;
+				resolve(normalizeChooseAndUploadFileRes({
+					errMsg: 'chooseVideo:ok',
+					tempFilePaths: [tempFilePath],
+					tempFiles: [
+					{
+						name: (res.tempFile && res.tempFile.name) || '',
+						path: tempFilePath,
+						size,
+						type: (res.tempFile && res.tempFile.type) || '',
+						width,
+						height,
+						duration,
+						fileType: 'video',
+						cloudPath: '',
+					}, ],
+				}, 'video'));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
+				});
+			},
+		});
+	});
+}
+
+function chooseAll(opts) {
+	const {
+		count,
+		extension
+	} = opts;
+	return new Promise((resolve, reject) => {
+		let chooseFile = uni.chooseFile;
+		if (typeof wx !== 'undefined' &&
+			typeof wx.chooseMessageFile === 'function') {
+			chooseFile = wx.chooseMessageFile;
+		}
+		if (typeof chooseFile !== 'function') {
+			return reject({
+				errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
+			});
+		}
+		chooseFile({
+			type: 'all',
+			count,
+			extension,
+			success(res) {
+				resolve(normalizeChooseAndUploadFileRes(res));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
+				});
+			},
+		});
+	});
+}
+
+function normalizeChooseAndUploadFileRes(res, fileType) {
+	res.tempFiles.forEach((item, index) => {
+		if (!item.name) {
+			item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
+		}
+		if (fileType) {
+			item.fileType = fileType;
+		}
+		item.cloudPath =
+			Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
+	});
+	if (!res.tempFilePaths) {
+		res.tempFilePaths = res.tempFiles.map((file) => file.path);
+	}
+	return res;
+}
+
+function uploadCloudFiles(files, max = 5, onUploadProgress) {
+	files = JSON.parse(JSON.stringify(files))
+	const len = files.length
+	let count = 0
+	let self = this
+	return new Promise(resolve => {
+		while (count < max) {
+			next()
+		}
+
+		function next() {
+			let cur = count++
+			if (cur >= len) {
+				!files.find(item => !item.url && !item.errMsg) && resolve(files)
+				return
+			}
+			const fileItem = files[cur]
+			const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
+			fileItem.url = ''
+			delete fileItem.errMsg
+
+			uniCloud
+				.uploadFile({
+					filePath: fileItem.path,
+					cloudPath: fileItem.cloudPath,
+					fileType: fileItem.fileType,
+					onUploadProgress: res => {
+						res.index = index
+						onUploadProgress && onUploadProgress(res)
+					}
+				})
+				.then(res => {
+					fileItem.url = res.fileID
+					fileItem.index = index
+					if (cur < len) {
+						next()
+					}
+				})
+				.catch(res => {
+					fileItem.errMsg = res.errMsg || res.message
+					fileItem.index = index
+					if (cur < len) {
+						next()
+					}
+				})
+		}
+	})
+}
+
+
+
+
+
+function uploadFiles(choosePromise, {
+	onChooseFile,
+	onUploadProgress
+}) {
+	return choosePromise
+		.then((res) => {
+			if (onChooseFile) {
+				const customChooseRes = onChooseFile(res);
+				if (typeof customChooseRes !== 'undefined') {
+					return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
+						res : chooseRes);
+				}
+			}
+			return res;
+		})
+		.then((res) => {
+			if (res === false) {
+				return {
+					errMsg: ERR_MSG_OK,
+					tempFilePaths: [],
+					tempFiles: [],
+				};
+			}
+			return res
+		})
+}
+
+function chooseAndUploadFile(opts = {
+	type: 'all'
+}) {
+	if (opts.type === 'image') {
+		return uploadFiles(chooseImage(opts), opts);
+	}
+	else if (opts.type === 'video') {
+		return uploadFiles(chooseVideo(opts), opts);
+	}
+	return uploadFiles(chooseAll(opts), opts);
+}
+
+export {
+	chooseAndUploadFile,
+	uploadCloudFiles
 };
 };

File diff suppressed because it is too large
+ 651 - 651
uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue


+ 299 - 299
uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue

@@ -1,325 +1,325 @@
-<template>
-	<view class="uni-file-picker__files">
-		<view v-if="!readonly" class="files-button" @click="choose">
-			<slot></slot>
-		</view>
-		<!-- :class="{'is-text-box':showType === 'list'}" -->
-		<view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
-			<!-- ,'is-list-card':showType === 'list-card' -->
-
-			<view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
-				'files-border':index !== 0 && styles.dividline}"
-			 :style="index !== 0 && styles.dividline &&borderLineStyle">
-				<view class="uni-file-picker__item">
-					<!-- :class="{'is-text-image':showType === 'list'}" -->
-					<!-- 	<view class="files__image is-text-image">
-						<image class="header-image" :src="item.logo" mode="aspectFit"></image>
-					</view> -->
-					<view class="files__name">{{item.name}}</view>
-					<view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
-						<view class="icon-del icon-files"></view>
-						<view class="icon-del rotate"></view>
-					</view>
-				</view>
-				<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
-					<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
-					 :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
-				</view>
-				<view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
-					点击重试
+<template>
+	<view class="uni-file-picker__files">
+		<view v-if="!readonly" class="files-button" @click="choose">
+			<slot></slot>
+		</view>
+		<!-- :class="{'is-text-box':showType === 'list'}" -->
+		<view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
+			<!-- ,'is-list-card':showType === 'list-card' -->
+
+			<view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
+				'files-border':index !== 0 && styles.dividline}"
+			 :style="index !== 0 && styles.dividline &&borderLineStyle">
+				<view class="uni-file-picker__item">
+					<!-- :class="{'is-text-image':showType === 'list'}" -->
+					<!-- 	<view class="files__image is-text-image">
+						<image class="header-image" :src="item.logo" mode="aspectFit"></image>
+					</view> -->
+					<view class="files__name">{{item.name}}</view>
+					<view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
+						<view class="icon-del icon-files"></view>
+						<view class="icon-del rotate"></view>
+					</view>
+				</view>
+				<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
+					<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
+					 :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
 				</view>
 				</view>
-			</view>
-
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		name: "uploadFile",
-		emits:['uploadFiles','choose','delFile'],
-		props: {
-			filesList: {
-				type: Array,
-				default () {
-					return []
-				}
-			},
-			delIcon: {
-				type: Boolean,
-				default: true
-			},
-			limit: {
-				type: [Number, String],
-				default: 9
-			},
-			showType: {
-				type: String,
-				default: ''
-			},
-			listStyles: {
-				type: Object,
-				default () {
-					return {
-						// 是否显示边框
-						border: true,
-						// 是否显示分隔线
-						dividline: true,
-						// 线条样式
-						borderStyle: {}
-					}
-				}
+				<view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
+					点击重试
+				</view>
+			</view>
+
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "uploadFile",
+		emits:['uploadFiles','choose','delFile'],
+		props: {
+			filesList: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			delIcon: {
+				type: Boolean,
+				default: true
+			},
+			limit: {
+				type: [Number, String],
+				default: 9
+			},
+			showType: {
+				type: String,
+				default: ''
+			},
+			listStyles: {
+				type: Object,
+				default () {
+					return {
+						// 是否显示边框
+						border: true,
+						// 是否显示分隔线
+						dividline: true,
+						// 线条样式
+						borderStyle: {}
+					}
+				}
 			},
 			},
 			readonly:{
 			readonly:{
 				type:Boolean,
 				type:Boolean,
 				default:false
 				default:false
-			}
-		},
-		computed: {
-			list() {
-				let files = []
-				this.filesList.forEach(v => {
-					files.push(v)
-				})
-				return files
-			},
-			styles() {
-				let styles = {
-					border: true,
-					dividline: true,
-					'border-style': {}
+			}
+		},
+		computed: {
+			list() {
+				let files = []
+				this.filesList.forEach(v => {
+					files.push(v)
+				})
+				return files
+			},
+			styles() {
+				let styles = {
+					border: true,
+					dividline: true,
+					'border-style': {}
+				}
+				return Object.assign(styles, this.listStyles)
+			},
+			borderStyle() {
+				let {
+					borderStyle,
+					border
+				} = this.styles
+				let obj = {}
+				if (!border) {
+					obj.border = 'none'
+				} else {
+					let width = (borderStyle && borderStyle.width) || 1
+					width = this.value2px(width)
+					let radius = (borderStyle && borderStyle.radius) || 5
+					radius = this.value2px(radius)
+					obj = {
+						'border-width': width,
+						'border-style': (borderStyle && borderStyle.style) || 'solid',
+						'border-color': (borderStyle && borderStyle.color) || '#eee',
+						'border-radius': radius
+					}
+				}
+				let classles = ''
+				for (let i in obj) {
+					classles += `${i}:${obj[i]};`
 				}
 				}
-				return Object.assign(styles, this.listStyles)
-			},
-			borderStyle() {
-				let {
-					borderStyle,
-					border
-				} = this.styles
-				let obj = {}
-				if (!border) {
-					obj.border = 'none'
-				} else {
-					let width = (borderStyle && borderStyle.width) || 1
-					width = this.value2px(width)
-					let radius = (borderStyle && borderStyle.radius) || 5
-					radius = this.value2px(radius)
-					obj = {
-						'border-width': width,
-						'border-style': (borderStyle && borderStyle.style) || 'solid',
-						'border-color': (borderStyle && borderStyle.color) || '#eee',
-						'border-radius': radius
-					}
-				}
-				let classles = ''
-				for (let i in obj) {
-					classles += `${i}:${obj[i]};`
-				}
-				return classles
-			},
-			borderLineStyle() {
-				let obj = {}
-				let {
-					borderStyle
-				} = this.styles
-				if (borderStyle && borderStyle.color) {
-					obj['border-color'] = borderStyle.color
-				}
-				if (borderStyle && borderStyle.width) {
-					let width = borderStyle && borderStyle.width || 1
-					let style = borderStyle && borderStyle.style || 0
-					if (typeof width === 'number') {
-						width += 'px'
-					} else {
-						width = width.indexOf('px') ? width : width + 'px'
-					}
+				return classles
+			},
+			borderLineStyle() {
+				let obj = {}
+				let {
+					borderStyle
+				} = this.styles
+				if (borderStyle && borderStyle.color) {
+					obj['border-color'] = borderStyle.color
+				}
+				if (borderStyle && borderStyle.width) {
+					let width = borderStyle && borderStyle.width || 1
+					let style = borderStyle && borderStyle.style || 0
+					if (typeof width === 'number') {
+						width += 'px'
+					} else {
+						width = width.indexOf('px') ? width : width + 'px'
+					}
 					obj['border-width'] = width
 					obj['border-width'] = width
 
 
 					if (typeof style === 'number') {
 					if (typeof style === 'number') {
 						style += 'px'
 						style += 'px'
 					} else {
 					} else {
 						style = style.indexOf('px') ? style : style + 'px'
 						style = style.indexOf('px') ? style : style + 'px'
-					}
-					obj['border-top-style'] = style
-				}
-				let classles = ''
-				for (let i in obj) {
-					classles += `${i}:${obj[i]};`
-				}
-				return classles
-			}
-		},
-
-		methods: {
-			uploadFiles(item, index) {
-				this.$emit("uploadFiles", {
-					item,
-					index
-				})
-			},
-			choose() {
-				this.$emit("choose")
-			},
-			delFile(index) {
-				this.$emit('delFile', index)
-			},
-			value2px(value) {
-				if (typeof value === 'number') {
-					value += 'px'
-				} else {
-					value = value.indexOf('px') !== -1 ? value : value + 'px'
+					}
+					obj['border-top-style'] = style
+				}
+				let classles = ''
+				for (let i in obj) {
+					classles += `${i}:${obj[i]};`
 				}
 				}
-				return value
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
+				return classles
+			}
+		},
+
+		methods: {
+			uploadFiles(item, index) {
+				this.$emit("uploadFiles", {
+					item,
+					index
+				})
+			},
+			choose() {
+				this.$emit("choose")
+			},
+			delFile(index) {
+				this.$emit('delFile', index)
+			},
+			value2px(value) {
+				if (typeof value === 'number') {
+					value += 'px'
+				} else {
+					value = value.indexOf('px') !== -1 ? value : value + 'px'
+				}
+				return value
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
 	.uni-file-picker__files {
 	.uni-file-picker__files {
-		/* #ifndef APP-NVUE */
+		/* #ifndef APP-NVUE */
 		display: flex;
 		display: flex;
-		/* #endif */
-		flex-direction: column;
-		justify-content: flex-start;
-	}
-
-	.files-button {
-		// border: 1px red solid;
-	}
-
-	.uni-file-picker__lists {
-		position: relative;
-		margin-top: 5px;
-		overflow: hidden;
-	}
-
+		/* #endif */
+		flex-direction: column;
+		justify-content: flex-start;
+	}
+
+	.files-button {
+		// border: 1px red solid;
+	}
+
+	.uni-file-picker__lists {
+		position: relative;
+		margin-top: 5px;
+		overflow: hidden;
+	}
+
 	.file-picker__mask {
 	.file-picker__mask {
-		/* #ifndef APP-NVUE */
+		/* #ifndef APP-NVUE */
 		display: flex;
 		display: flex;
-		/* #endif */
-		justify-content: center;
-		align-items: center;
-		position: absolute;
-		right: 0;
-		top: 0;
-		bottom: 0;
-		left: 0;
-		color: #fff;
-		font-size: 14px;
-		background-color: rgba(0, 0, 0, 0.4);
-	}
-
-	.uni-file-picker__lists-box {
-		position: relative;
-	}
-
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		right: 0;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		color: #fff;
+		font-size: 14px;
+		background-color: rgba(0, 0, 0, 0.4);
+	}
+
+	.uni-file-picker__lists-box {
+		position: relative;
+	}
+
 	.uni-file-picker__item {
 	.uni-file-picker__item {
-		/* #ifndef APP-NVUE */
+		/* #ifndef APP-NVUE */
 		display: flex;
 		display: flex;
-		/* #endif */
-		align-items: center;
-		padding: 8px 10px;
-		padding-right: 5px;
-		padding-left: 10px;
-	}
-
-	.files-border {
-		border-top: 1px #eee solid;
-	}
-
-	.files__name {
-		flex: 1;
-		font-size: 14px;
-		color: #666;
+		/* #endif */
+		align-items: center;
+		padding: 8px 10px;
+		padding-right: 5px;
+		padding-left: 10px;
+	}
+
+	.files-border {
+		border-top: 1px #eee solid;
+	}
+
+	.files__name {
+		flex: 1;
+		font-size: 14px;
+		color: #666;
 		margin-right: 25px;
 		margin-right: 25px;
-		/* #ifndef APP-NVUE */
-		word-break: break-all;
+		/* #ifndef APP-NVUE */
+		word-break: break-all;
 		word-wrap: break-word;
 		word-wrap: break-word;
-		/* #endif */
-	}
-
+		/* #endif */
+	}
+
 	.icon-files {
 	.icon-files {
-		/* #ifndef APP-NVUE */
-		position: static;
+		/* #ifndef APP-NVUE */
+		position: static;
 		background-color: initial;
 		background-color: initial;
-		/* #endif */
-	}
-
-	// .icon-files .icon-del {
-	// 	background-color: #333;
-	// 	width: 12px;
-	// 	height: 1px;
-	// }
-
-
-	.is-list-card {
-		border: 1px #eee solid;
-		margin-bottom: 5px;
-		border-radius: 5px;
-		box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
-		padding: 5px;
-	}
-
-	.files__image {
-		width: 40px;
-		height: 40px;
-		margin-right: 10px;
-	}
-
-	.header-image {
-		width: 100%;
-		height: 100%;
-	}
-
-	.is-text-box {
-		border: 1px #eee solid;
-		border-radius: 5px;
-	}
-
-	.is-text-image {
-		width: 25px;
-		height: 25px;
-		margin-left: 5px;
-	}
-
-	.rotate {
-		position: absolute;
-		transform: rotate(90deg);
-	}
-
+		/* #endif */
+	}
+
+	// .icon-files .icon-del {
+	// 	background-color: #333;
+	// 	width: 12px;
+	// 	height: 1px;
+	// }
+
+
+	.is-list-card {
+		border: 1px #eee solid;
+		margin-bottom: 5px;
+		border-radius: 5px;
+		box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
+		padding: 5px;
+	}
+
+	.files__image {
+		width: 40px;
+		height: 40px;
+		margin-right: 10px;
+	}
+
+	.header-image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.is-text-box {
+		border: 1px #eee solid;
+		border-radius: 5px;
+	}
+
+	.is-text-image {
+		width: 25px;
+		height: 25px;
+		margin-left: 5px;
+	}
+
+	.rotate {
+		position: absolute;
+		transform: rotate(90deg);
+	}
+
 	.icon-del-box {
 	.icon-del-box {
-		/* #ifndef APP-NVUE */
-		display: flex;
+		/* #ifndef APP-NVUE */
+		display: flex;
 		margin: auto 0;
 		margin: auto 0;
-		/* #endif */
-		align-items: center;
-		justify-content: center;
-		position: absolute;
-		top: 0px;
-		bottom: 0;
-		right: 5px;
-		height: 26px;
-		width: 26px;
-		// border-radius: 50%;
-		// background-color: rgba(0, 0, 0, 0.5);
-		z-index: 2;
-		transform: rotate(-45deg);
-	}
-
-	.icon-del {
-		width: 15px;
-		height: 1px;
-		background-color: #333;
-		// border-radius: 1px;
-	}
-
-	/* #ifdef H5 */
-	@media all and (min-width: 768px) {
-		.uni-file-picker__files {
-			max-width: 375px;
-		}
-	}
-
-	/* #endif */
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+		position: absolute;
+		top: 0px;
+		bottom: 0;
+		right: 5px;
+		height: 26px;
+		width: 26px;
+		// border-radius: 50%;
+		// background-color: rgba(0, 0, 0, 0.5);
+		z-index: 2;
+		transform: rotate(-45deg);
+	}
+
+	.icon-del {
+		width: 15px;
+		height: 1px;
+		background-color: #333;
+		// border-radius: 1px;
+	}
+
+	/* #ifdef H5 */
+	@media all and (min-width: 768px) {
+		.uni-file-picker__files {
+			max-width: 375px;
+		}
+	}
+
+	/* #endif */
 </style>
 </style>

+ 254 - 254
uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue

@@ -1,292 +1,292 @@
-<template>
+<template>
 	<view class="uni-file-picker__container">
 	<view class="uni-file-picker__container">
 		<view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle">
 		<view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle">
 			<view class="file-picker__box-content" :style="borderStyle">
 			<view class="file-picker__box-content" :style="borderStyle">
-				<image class="file-image" :src="item.url" mode="aspectFill" @click.stop="prviewImage(item,index)"></image>
-				<view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)">
-					<view class="icon-del"></view>
-					<view class="icon-del rotate"></view>
-				</view>
-				<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
-					<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
-					 :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
-				</view>
-				<view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
-					点击重试
-				</view>
-			</view>
-		</view>
-		<view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle">
-			<view class="file-picker__box-content is-add" :style="borderStyle" @click="choose">
-				<slot>
-					<view class="icon-add"></view>
-					<view class="icon-add rotate"></view>
-				</slot>
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		name: "uploadImage",
-		emits:['uploadFiles','choose','delFile'],
-		props: {
-			filesList: {
-				type: Array,
-				default () {
-					return []
-				}
+				<image class="file-image" :src="item.url" mode="aspectFill" @click.stop="prviewImage(item,index)"></image>
+				<view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)">
+					<view class="icon-del"></view>
+					<view class="icon-del rotate"></view>
+				</view>
+				<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
+					<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
+					 :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
+				</view>
+				<view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
+					点击重试
+				</view>
+			</view>
+		</view>
+		<view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle">
+			<view class="file-picker__box-content is-add" :style="borderStyle" @click="choose">
+				<slot>
+					<view class="icon-add"></view>
+					<view class="icon-add rotate"></view>
+				</slot>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "uploadImage",
+		emits:['uploadFiles','choose','delFile'],
+		props: {
+			filesList: {
+				type: Array,
+				default () {
+					return []
+				}
 			},
 			},
 			disabled:{
 			disabled:{
 				type: Boolean,
 				type: Boolean,
 				default: false
 				default: false
-			},
-			disablePreview: {
-				type: Boolean,
-				default: false
-			},
-			limit: {
-				type: [Number, String],
-				default: 9
-			},
-			imageStyles: {
-				type: Object,
-				default () {
-					return {
-						width: 'auto',
-						height: 'auto',
-						border: {}
-					}
-				}
-			},
-			delIcon: {
-				type: Boolean,
-				default: true
+			},
+			disablePreview: {
+				type: Boolean,
+				default: false
+			},
+			limit: {
+				type: [Number, String],
+				default: 9
+			},
+			imageStyles: {
+				type: Object,
+				default () {
+					return {
+						width: 'auto',
+						height: 'auto',
+						border: {}
+					}
+				}
+			},
+			delIcon: {
+				type: Boolean,
+				default: true
 			},
 			},
 			readonly:{
 			readonly:{
 				type:Boolean,
 				type:Boolean,
 				default:false
 				default:false
-			}
-		},
-		computed: {
-			styles() {
-				let styles = {
-					width: 'auto',
-					height: 'auto',
-					border: {}
-				}
-				return Object.assign(styles, this.imageStyles)
-			},
-			boxStyle() {
-				const {
-					width = 'auto',
-						height = 'auto'
-				} = this.styles
-				let obj = {}
-				if (height === 'auto') {
-					if (width !== 'auto') {
-						obj.height = this.value2px(width)
-						obj['padding-top'] = 0
-					} else {
-						obj.height = 0
-					}
-				} else {
-					obj.height = this.value2px(height)
-					obj['padding-top'] = 0
-				}
-
-				if (width === 'auto') {
-					if (height !== 'auto') {
-						obj.width = this.value2px(height)
-					} else {
-						obj.width = '33.3%'
-					}
-				} else {
-					obj.width = this.value2px(width)
+			}
+		},
+		computed: {
+			styles() {
+				let styles = {
+					width: 'auto',
+					height: 'auto',
+					border: {}
+				}
+				return Object.assign(styles, this.imageStyles)
+			},
+			boxStyle() {
+				const {
+					width = 'auto',
+						height = 'auto'
+				} = this.styles
+				let obj = {}
+				if (height === 'auto') {
+					if (width !== 'auto') {
+						obj.height = this.value2px(width)
+						obj['padding-top'] = 0
+					} else {
+						obj.height = 0
+					}
+				} else {
+					obj.height = this.value2px(height)
+					obj['padding-top'] = 0
+				}
+
+				if (width === 'auto') {
+					if (height !== 'auto') {
+						obj.width = this.value2px(height)
+					} else {
+						obj.width = '33.3%'
+					}
+				} else {
+					obj.width = this.value2px(width)
 				}
 				}
 
 
 				let classles = ''
 				let classles = ''
 				for(let i in obj){
 				for(let i in obj){
 					classles+= `${i}:${obj[i]};`
 					classles+= `${i}:${obj[i]};`
 				}
 				}
-				return classles
-			},
-			borderStyle() {
-				let {
-					border
-				} = this.styles
+				return classles
+			},
+			borderStyle() {
+				let {
+					border
+				} = this.styles
 				let obj = {}
 				let obj = {}
 				const widthDefaultValue = 1
 				const widthDefaultValue = 1
-				const radiusDefaultValue = 3
-				if (typeof border === 'boolean') {
-					obj.border = border ? '1px #eee solid' : 'none'
-				} else {
-					let width = (border && border.width) || widthDefaultValue
-					width = this.value2px(width)
-					let radius = (border && border.radius) || radiusDefaultValue
-					radius = this.value2px(radius)
-					obj = {
-						'border-width': width,
-						'border-style': (border && border.style) || 'solid',
-						'border-color': (border && border.color) || '#eee',
-						'border-radius': radius
-					}
+				const radiusDefaultValue = 3
+				if (typeof border === 'boolean') {
+					obj.border = border ? '1px #eee solid' : 'none'
+				} else {
+					let width = (border && border.width) || widthDefaultValue
+					width = this.value2px(width)
+					let radius = (border && border.radius) || radiusDefaultValue
+					radius = this.value2px(radius)
+					obj = {
+						'border-width': width,
+						'border-style': (border && border.style) || 'solid',
+						'border-color': (border && border.color) || '#eee',
+						'border-radius': radius
+					}
 				}
 				}
 				let classles = ''
 				let classles = ''
 				for(let i in obj){
 				for(let i in obj){
 					classles+= `${i}:${obj[i]};`
 					classles+= `${i}:${obj[i]};`
-				}
-				return classles
-			}
-		},
-		methods: {
-			uploadFiles(item, index) {
-				this.$emit("uploadFiles", item)
-			},
-			choose() {
-				this.$emit("choose")
-			},
-			delFile(index) {
-				this.$emit('delFile', index)
-			},
-			prviewImage(img, index) {
+				}
+				return classles
+			}
+		},
+		methods: {
+			uploadFiles(item, index) {
+				this.$emit("uploadFiles", item)
+			},
+			choose() {
+				this.$emit("choose")
+			},
+			delFile(index) {
+				this.$emit('delFile', index)
+			},
+			prviewImage(img, index) {
 				let urls = []
 				let urls = []
 				if(Number(this.limit) === 1&&this.disablePreview&&!this.disabled){
 				if(Number(this.limit) === 1&&this.disablePreview&&!this.disabled){
 					this.$emit("choose")
 					this.$emit("choose")
-				}
+				}
 				if(this.disablePreview) return
 				if(this.disablePreview) return
-				this.filesList.forEach(i => {
-					urls.push(i.url)
-				})
-
-				uni.previewImage({
-					urls: urls,
-					current: index
-				});
-			},
-			value2px(value) {
-				if (typeof value === 'number') {
-					value += 'px'
-				} else {
-					if (value.indexOf('%') === -1) {
-						value = value.indexOf('px') !== -1 ? value : value + 'px'
-					}
-				}
-				return value
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
+				this.filesList.forEach(i => {
+					urls.push(i.url)
+				})
+
+				uni.previewImage({
+					urls: urls,
+					current: index
+				});
+			},
+			value2px(value) {
+				if (typeof value === 'number') {
+					value += 'px'
+				} else {
+					if (value.indexOf('%') === -1) {
+						value = value.indexOf('px') !== -1 ? value : value + 'px'
+					}
+				}
+				return value
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
 	.uni-file-picker__container {
 	.uni-file-picker__container {
-		/* #ifndef APP-NVUE */
-		display: flex;
+		/* #ifndef APP-NVUE */
+		display: flex;
 		box-sizing: border-box;
 		box-sizing: border-box;
-		/* #endif */
-		flex-wrap: wrap;
-		margin: -5px;
-	}
-
-	.file-picker__box {
-		position: relative;
-		// flex: 0 0 33.3%;
-		width: 33.3%;
-		height: 0;
+		/* #endif */
+		flex-wrap: wrap;
+		margin: -5px;
+	}
+
+	.file-picker__box {
+		position: relative;
+		// flex: 0 0 33.3%;
+		width: 33.3%;
+		height: 0;
 		padding-top: 33.33%;
 		padding-top: 33.33%;
-		/* #ifndef APP-NVUE */
+		/* #ifndef APP-NVUE */
 		box-sizing: border-box;
 		box-sizing: border-box;
-		/* #endif */
-	}
-
-	.file-picker__box-content {
-		position: absolute;
-		top: 0;
-		right: 0;
-		bottom: 0;
-		left: 0;
-		margin: 5px;
-		border: 1px #eee solid;
-		border-radius: 5px;
-		overflow: hidden;
-	}
-
-	.file-picker__progress {
-		position: absolute;
-		bottom: 0;
-		left: 0;
-		right: 0;
-		/* border: 1px red solid; */
-		z-index: 2;
-	}
-
-	.file-picker__progress-item {
-		width: 100%;
-	}
-
+		/* #endif */
+	}
+
+	.file-picker__box-content {
+		position: absolute;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		margin: 5px;
+		border: 1px #eee solid;
+		border-radius: 5px;
+		overflow: hidden;
+	}
+
+	.file-picker__progress {
+		position: absolute;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		/* border: 1px red solid; */
+		z-index: 2;
+	}
+
+	.file-picker__progress-item {
+		width: 100%;
+	}
+
 	.file-picker__mask {
 	.file-picker__mask {
-		/* #ifndef APP-NVUE */
+		/* #ifndef APP-NVUE */
 		display: flex;
 		display: flex;
-		/* #endif */
-		justify-content: center;
-		align-items: center;
-		position: absolute;
-		right: 0;
-		top: 0;
-		bottom: 0;
-		left: 0;
-		color: #fff;
-		font-size: 12px;
-		background-color: rgba(0, 0, 0, 0.4);
-	}
-
-	.file-image {
-		width: 100%;
-		height: 100%;
-	}
-
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		right: 0;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		color: #fff;
+		font-size: 12px;
+		background-color: rgba(0, 0, 0, 0.4);
+	}
+
+	.file-image {
+		width: 100%;
+		height: 100%;
+	}
+
 	.is-add {
 	.is-add {
-		/* #ifndef APP-NVUE */
+		/* #ifndef APP-NVUE */
 		display: flex;
 		display: flex;
-		/* #endif */
-		align-items: center;
-		justify-content: center;
-	}
-
-	.icon-add {
-		width: 50px;
-		height: 5px;
-		background-color: #f1f1f1;
-		border-radius: 2px;
-	}
-
-	.rotate {
-		position: absolute;
-		transform: rotate(90deg);
-	}
-
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+	}
+
+	.icon-add {
+		width: 50px;
+		height: 5px;
+		background-color: #f1f1f1;
+		border-radius: 2px;
+	}
+
+	.rotate {
+		position: absolute;
+		transform: rotate(90deg);
+	}
+
 	.icon-del-box {
 	.icon-del-box {
-		/* #ifndef APP-NVUE */
+		/* #ifndef APP-NVUE */
 		display: flex;
 		display: flex;
-		/* #endif */
-		align-items: center;
-		justify-content: center;
-		position: absolute;
-		top: 3px;
-		right: 3px;
-		height: 26px;
-		width: 26px;
-		border-radius: 50%;
-		background-color: rgba(0, 0, 0, 0.5);
-		z-index: 2;
-		transform: rotate(-45deg);
-	}
-
-	.icon-del {
-		width: 15px;
-		height: 2px;
-		background-color: #fff;
-		border-radius: 2px;
-	}
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+		position: absolute;
+		top: 3px;
+		right: 3px;
+		height: 26px;
+		width: 26px;
+		border-radius: 50%;
+		background-color: rgba(0, 0, 0, 0.5);
+		z-index: 2;
+		transform: rotate(-45deg);
+	}
+
+	.icon-del {
+		width: 15px;
+		height: 2px;
+		background-color: #fff;
+		border-radius: 2px;
+	}
 </style>
 </style>

File diff suppressed because it is too large
+ 630 - 630
uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue


+ 394 - 394
uni_modules/uni-forms/components/uni-forms/uni-forms.vue

@@ -1,397 +1,397 @@
-<template>
-	<view class="uni-forms">
-		<form>
-			<slot></slot>
-		</form>
-	</view>
-</template>
-
-<script>
-	import Validator from './validate.js';
-	import {
-		deepCopy,
-		getValue,
-		isRequiredField,
-		setDataValue,
-		getDataValue,
-		realName,
-		isRealName,
-		rawData,
-		isEqual
-	} from './utils.js'
-
-	// #ifndef VUE3
-	// 后续会慢慢废弃这个方法
-	import Vue from 'vue';
-	Vue.prototype.binddata = function(name, value, formName) {
-		if (formName) {
-			this.$refs[formName].setValue(name, value);
-		} else {
-			let formVm;
-			for (let i in this.$refs) {
-				const vm = this.$refs[i];
-				if (vm && vm.$options && vm.$options.name === 'uniForms') {
-					formVm = vm;
-					break;
-				}
-			}
-			if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
-			formVm.setValue(name, value);
-		}
-	};
-	// #endif
-	/**
-	 * Forms 表单
-	 * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
-	 * @property {Object} rules	表单校验规则
-	 * @property {String} validateTrigger = [bind|submit|blur]	校验触发器方式 默认 submit
-	 * @value bind		发生变化时触发
-	 * @value submit	提交时触发
-	 * @value blur	  失去焦点时触发
-	 * @property {String} labelPosition = [top|left]	label 位置 默认 left
-	 * @value top		顶部显示 label
-	 * @value left	左侧显示 label
-	 * @property {String} labelWidth	label 宽度,默认 65px
-	 * @property {String} labelAlign = [left|center|right]	label 居中方式  默认 left
-	 * @value left		label 左侧显示
-	 * @value center	label 居中
-	 * @value right		label 右侧对齐
-	 * @property {String} errShowType = [undertext|toast|modal]	校验错误信息提示方式
-	 * @value undertext	错误信息在底部显示
-	 * @value toast			错误信息toast显示
-	 * @value modal			错误信息modal显示
-	 * @event {Function} submit	提交时触发
-	 * @event {Function} validate	校验结果发生变化触发
-	 */
-	export default {
-		name: 'uniForms',
-		emits: ['validate', 'submit'],
-		options: {
-			virtualHost: true
-		},
-		props: {
-			// 即将弃用
-			value: {
-				type: Object,
-				default () {
-					return null;
-				}
-			},
-			// vue3 替换 value 属性
-			modelValue: {
-				type: Object,
-				default () {
-					return null;
-				}
-			},
-			// 1.4.0 开始将不支持 v-model ,且废弃 value 和 modelValue
-			model: {
-				type: Object,
-				default () {
-					return null;
-				}
-			},
-			// 表单校验规则
-			rules: {
-				type: Object,
-				default () {
-					return {};
-				}
-			},
-			//校验错误信息提示方式 默认 undertext 取值 [undertext|toast|modal]
-			errShowType: {
-				type: String,
-				default: 'undertext'
-			},
-			// 校验触发器方式 默认 bind 取值 [bind|submit]
-			validateTrigger: {
-				type: String,
-				default: 'submit'
-			},
-			// label 位置,默认 left 取值  top/left
-			labelPosition: {
-				type: String,
-				default: 'left'
-			},
-			// label 宽度
-			labelWidth: {
-				type: [String, Number],
-				default: ''
-			},
-			// label 居中方式,默认 left 取值 left/center/right
-			labelAlign: {
-				type: String,
-				default: 'left'
-			},
-			border: {
-				type: Boolean,
-				default: false
-			}
-		},
-		provide() {
-			return {
-				uniForm: this
-			}
-		},
-		data() {
-			return {
-				// 表单本地值的记录,不应该与传如的值进行关联
-				formData: {},
-				formRules: {}
-			};
-		},
-		computed: {
-			// 计算数据源变化的
-			localData() {
-				const localVal = this.model || this.modelValue || this.value
-				if (localVal) {
-					return deepCopy(localVal)
-				}
-				return {}
-			}
-		},
-		watch: {
-			// 监听数据变化 ,暂时不使用,需要单独赋值
-			// localData: {},
-			// 监听规则变化
-			rules: {
-				handler: function(val, oldVal) {
-					this.setRules(val)
-				},
-				deep: true,
-				immediate: true
-			}
-		},
-		created() {
-			// #ifdef VUE3
-			let getbinddata = getApp().$vm.$.appContext.config.globalProperties.binddata
-			if (!getbinddata) {
-				getApp().$vm.$.appContext.config.globalProperties.binddata = function(name, value, formName) {
-					if (formName) {
-						this.$refs[formName].setValue(name, value);
-					} else {
-						let formVm;
-						for (let i in this.$refs) {
-							const vm = this.$refs[i];
-							if (vm && vm.$options && vm.$options.name === 'uniForms') {
-								formVm = vm;
-								break;
-							}
-						}
-						if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
-						formVm.setValue(name, value);
-					}
-				}
-			}
-			// #endif
-
-			// 子组件实例数组
+<template>
+	<view class="uni-forms">
+		<form>
+			<slot></slot>
+		</form>
+	</view>
+</template>
+
+<script>
+	import Validator from './validate.js';
+	import {
+		deepCopy,
+		getValue,
+		isRequiredField,
+		setDataValue,
+		getDataValue,
+		realName,
+		isRealName,
+		rawData,
+		isEqual
+	} from './utils.js'
+
+	// #ifndef VUE3
+	// 后续会慢慢废弃这个方法
+	import Vue from 'vue';
+	Vue.prototype.binddata = function(name, value, formName) {
+		if (formName) {
+			this.$refs[formName].setValue(name, value);
+		} else {
+			let formVm;
+			for (let i in this.$refs) {
+				const vm = this.$refs[i];
+				if (vm && vm.$options && vm.$options.name === 'uniForms') {
+					formVm = vm;
+					break;
+				}
+			}
+			if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
+			formVm.setValue(name, value);
+		}
+	};
+	// #endif
+	/**
+	 * Forms 表单
+	 * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
+	 * @property {Object} rules	表单校验规则
+	 * @property {String} validateTrigger = [bind|submit|blur]	校验触发器方式 默认 submit
+	 * @value bind		发生变化时触发
+	 * @value submit	提交时触发
+	 * @value blur	  失去焦点时触发
+	 * @property {String} labelPosition = [top|left]	label 位置 默认 left
+	 * @value top		顶部显示 label
+	 * @value left	左侧显示 label
+	 * @property {String} labelWidth	label 宽度,默认 65px
+	 * @property {String} labelAlign = [left|center|right]	label 居中方式  默认 left
+	 * @value left		label 左侧显示
+	 * @value center	label 居中
+	 * @value right		label 右侧对齐
+	 * @property {String} errShowType = [undertext|toast|modal]	校验错误信息提示方式
+	 * @value undertext	错误信息在底部显示
+	 * @value toast			错误信息toast显示
+	 * @value modal			错误信息modal显示
+	 * @event {Function} submit	提交时触发
+	 * @event {Function} validate	校验结果发生变化触发
+	 */
+	export default {
+		name: 'uniForms',
+		emits: ['validate', 'submit'],
+		options: {
+			virtualHost: true
+		},
+		props: {
+			// 即将弃用
+			value: {
+				type: Object,
+				default () {
+					return null;
+				}
+			},
+			// vue3 替换 value 属性
+			modelValue: {
+				type: Object,
+				default () {
+					return null;
+				}
+			},
+			// 1.4.0 开始将不支持 v-model ,且废弃 value 和 modelValue
+			model: {
+				type: Object,
+				default () {
+					return null;
+				}
+			},
+			// 表单校验规则
+			rules: {
+				type: Object,
+				default () {
+					return {};
+				}
+			},
+			//校验错误信息提示方式 默认 undertext 取值 [undertext|toast|modal]
+			errShowType: {
+				type: String,
+				default: 'undertext'
+			},
+			// 校验触发器方式 默认 bind 取值 [bind|submit]
+			validateTrigger: {
+				type: String,
+				default: 'submit'
+			},
+			// label 位置,默认 left 取值  top/left
+			labelPosition: {
+				type: String,
+				default: 'left'
+			},
+			// label 宽度
+			labelWidth: {
+				type: [String, Number],
+				default: ''
+			},
+			// label 居中方式,默认 left 取值 left/center/right
+			labelAlign: {
+				type: String,
+				default: 'left'
+			},
+			border: {
+				type: Boolean,
+				default: false
+			}
+		},
+		provide() {
+			return {
+				uniForm: this
+			}
+		},
+		data() {
+			return {
+				// 表单本地值的记录,不应该与传如的值进行关联
+				formData: {},
+				formRules: {}
+			};
+		},
+		computed: {
+			// 计算数据源变化的
+			localData() {
+				const localVal = this.model || this.modelValue || this.value
+				if (localVal) {
+					return deepCopy(localVal)
+				}
+				return {}
+			}
+		},
+		watch: {
+			// 监听数据变化 ,暂时不使用,需要单独赋值
+			// localData: {},
+			// 监听规则变化
+			rules: {
+				handler: function(val, oldVal) {
+					this.setRules(val)
+				},
+				deep: true,
+				immediate: true
+			}
+		},
+		created() {
+			// #ifdef VUE3
+			let getbinddata = getApp().$vm.$.appContext.config.globalProperties.binddata
+			if (!getbinddata) {
+				getApp().$vm.$.appContext.config.globalProperties.binddata = function(name, value, formName) {
+					if (formName) {
+						this.$refs[formName].setValue(name, value);
+					} else {
+						let formVm;
+						for (let i in this.$refs) {
+							const vm = this.$refs[i];
+							if (vm && vm.$options && vm.$options.name === 'uniForms') {
+								formVm = vm;
+								break;
+							}
+						}
+						if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
+						formVm.setValue(name, value);
+					}
+				}
+			}
+			// #endif
+
+			// 子组件实例数组
 			this.childrens = []
 			this.childrens = []
 			// TODO 兼容旧版 uni-data-picker ,新版本中无效,只是避免报错
 			// TODO 兼容旧版 uni-data-picker ,新版本中无效,只是避免报错
-			this.inputChildrens = []
-			this.setRules(this.rules)
-		},
-		methods: {
-			/**
-			 * 外部调用方法
-			 * 设置规则 ,主要用于小程序自定义检验规则
-			 * @param {Array} rules 规则源数据
-			 */
-			setRules(rules) {
-				// TODO 有可能子组件合并规则的时机比这个要早,所以需要合并对象 ,而不是直接赋值,可能会被覆盖
-				this.formRules = Object.assign({}, this.formRules, rules)
-				// 初始化校验函数
-				this.validator = new Validator(rules);
-			},
-
-			/**
-			 * 外部调用方法
-			 * 设置数据,用于设置表单数据,公开给用户使用 , 不支持在动态表单中使用
-			 * @param {Object} key
-			 * @param {Object} value
-			 */
-			setValue(key, value) {
-				let example = this.childrens.find(child => child.name === key);
-				if (!example) return null;
-				this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || [])
-				return example.onFieldChange(this.formData[key]);
-			},
-
-			/**
-			 * 外部调用方法
-			 * 手动提交校验表单
-			 * 对整个表单进行校验的方法,参数为一个回调函数。
-			 * @param {Array} keepitem 保留不参与校验的字段
-			 * @param {type} callback 方法回调
-			 */
-			validate(keepitem, callback) {
-				return this.checkAll(this.formData, keepitem, callback);
-			},
-
-			/**
-			 * 外部调用方法
-			 * 部分表单校验
-			 * @param {Array|String} props 需要校验的字段
-			 * @param {Function} 回调函数
-			 */
-			validateField(props = [], callback) {
-				props = [].concat(props);
-				let invalidFields = {};
-				this.childrens.forEach(item => {
-					const name = realName(item.name)
-					if (props.indexOf(name) !== -1) {
-						invalidFields = Object.assign({}, invalidFields, {
-							[name]: this.formData[name]
-						});
-					}
-				});
-				return this.checkAll(invalidFields, [], callback);
-			},
-
-			/**
-			 * 外部调用方法
-			 * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
-			 * @param {Array|String} props 需要移除校验的字段 ,不填为所有
-			 */
-			clearValidate(props = []) {
-				props = [].concat(props);
-				this.childrens.forEach(item => {
-					if (props.length === 0) {
-						item.errMsg = '';
-					} else {
-						const name = realName(item.name)
-						if (props.indexOf(name) !== -1) {
-							item.errMsg = '';
-						}
-					}
-				});
-			},
-
-			/**
-			 * 外部调用方法 ,即将废弃
-			 * 手动提交校验表单
-			 * 对整个表单进行校验的方法,参数为一个回调函数。
-			 * @param {Array} keepitem 保留不参与校验的字段
-			 * @param {type} callback 方法回调
-			 */
-			submit(keepitem, callback, type) {
-				for (let i in this.dataValue) {
-					const itemData = this.childrens.find(v => v.name === i);
-					if (itemData) {
-						if (this.formData[i] === undefined) {
-							this.formData[i] = this._getValue(i, this.dataValue[i]);
-						}
-					}
-				}
-
-				if (!type) {
-					console.warn('submit 方法即将废弃,请使用validate方法代替!');
-				}
-
-				return this.checkAll(this.formData, keepitem, callback, 'submit');
-			},
-
-			// 校验所有
-			async checkAll(invalidFields, keepitem, callback, type) {
-				// 不存在校验规则 ,则停止校验流程
-				if (!this.validator) return
-				let childrens = []
-				// 处理参与校验的item实例
-				for (let i in invalidFields) {
-					const item = this.childrens.find(v => realName(v.name) === i)
-					if (item) {
-						childrens.push(item)
-					}
-				}
-
-				// 如果validate第一个参数是funciont ,那就走回调
-				if (!callback && typeof keepitem === 'function') {
-					callback = keepitem;
-				}
-
-				let promise;
-				// 如果不存在回调,那么使用 Promise 方式返回
-				if (!callback && typeof callback !== 'function' && Promise) {
-					promise = new Promise((resolve, reject) => {
-						callback = function(valid, invalidFields) {
-							!valid ? resolve(invalidFields) : reject(valid);
-						};
-					});
-				}
-
-				let results = [];
-				// 避免引用错乱 ,建议拷贝对象处理
-				let tempFormData = JSON.parse(JSON.stringify(invalidFields))
-				// 所有子组件参与校验,使用 for 可以使用  awiat
-				for (let i in childrens) {
-					const child = childrens[i]
-					let name = realName(child.name);
-					const result = await child.onFieldChange(tempFormData[name]);
-					if (result) {
-						results.push(result);
-						// toast ,modal 只需要执行第一次就可以
-						if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
-					}
-				}
-
-
-				if (Array.isArray(results)) {
-					if (results.length === 0) results = null;
-				}
-				if (Array.isArray(keepitem)) {
-					keepitem.forEach(v => {
-						let vName = realName(v);
-						let value = getDataValue(v, this.localData)
-						if (value !== undefined) {
-							tempFormData[vName] = value
-						}
-					});
-				}
-
-				// TODO submit 即将废弃
-				if (type === 'submit') {
-					this.$emit('submit', {
-						detail: {
-							value: tempFormData,
-							errors: results
-						}
-					});
-				} else {
-					this.$emit('validate', results);
-				}
-
-				// const resetFormData = rawData(tempFormData, this.localData, this.name)
-				let resetFormData = {}
-				resetFormData = rawData(tempFormData, this.name)
-				callback && typeof callback === 'function' && callback(results, resetFormData);
-
-				if (promise && callback) {
-					return promise;
-				} else {
-					return null;
-				}
-
-			},
-
-			/**
-			 * 返回validate事件
-			 * @param {Object} result
-			 */
-			validateCheck(result) {
-				this.$emit('validate', result);
-			},
-			_getValue: getValue,
-			_isRequiredField: isRequiredField,
-			_setDataValue: setDataValue,
-			_getDataValue: getDataValue,
-			_realName: realName,
-			_isRealName: isRealName,
-			_isEqual: isEqual
-		}
-	};
-</script>
-
-<style lang="scss">
-	.uni-forms {}
+			this.inputChildrens = []
+			this.setRules(this.rules)
+		},
+		methods: {
+			/**
+			 * 外部调用方法
+			 * 设置规则 ,主要用于小程序自定义检验规则
+			 * @param {Array} rules 规则源数据
+			 */
+			setRules(rules) {
+				// TODO 有可能子组件合并规则的时机比这个要早,所以需要合并对象 ,而不是直接赋值,可能会被覆盖
+				this.formRules = Object.assign({}, this.formRules, rules)
+				// 初始化校验函数
+				this.validator = new Validator(rules);
+			},
+
+			/**
+			 * 外部调用方法
+			 * 设置数据,用于设置表单数据,公开给用户使用 , 不支持在动态表单中使用
+			 * @param {Object} key
+			 * @param {Object} value
+			 */
+			setValue(key, value) {
+				let example = this.childrens.find(child => child.name === key);
+				if (!example) return null;
+				this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || [])
+				return example.onFieldChange(this.formData[key]);
+			},
+
+			/**
+			 * 外部调用方法
+			 * 手动提交校验表单
+			 * 对整个表单进行校验的方法,参数为一个回调函数。
+			 * @param {Array} keepitem 保留不参与校验的字段
+			 * @param {type} callback 方法回调
+			 */
+			validate(keepitem, callback) {
+				return this.checkAll(this.formData, keepitem, callback);
+			},
+
+			/**
+			 * 外部调用方法
+			 * 部分表单校验
+			 * @param {Array|String} props 需要校验的字段
+			 * @param {Function} 回调函数
+			 */
+			validateField(props = [], callback) {
+				props = [].concat(props);
+				let invalidFields = {};
+				this.childrens.forEach(item => {
+					const name = realName(item.name)
+					if (props.indexOf(name) !== -1) {
+						invalidFields = Object.assign({}, invalidFields, {
+							[name]: this.formData[name]
+						});
+					}
+				});
+				return this.checkAll(invalidFields, [], callback);
+			},
+
+			/**
+			 * 外部调用方法
+			 * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
+			 * @param {Array|String} props 需要移除校验的字段 ,不填为所有
+			 */
+			clearValidate(props = []) {
+				props = [].concat(props);
+				this.childrens.forEach(item => {
+					if (props.length === 0) {
+						item.errMsg = '';
+					} else {
+						const name = realName(item.name)
+						if (props.indexOf(name) !== -1) {
+							item.errMsg = '';
+						}
+					}
+				});
+			},
+
+			/**
+			 * 外部调用方法 ,即将废弃
+			 * 手动提交校验表单
+			 * 对整个表单进行校验的方法,参数为一个回调函数。
+			 * @param {Array} keepitem 保留不参与校验的字段
+			 * @param {type} callback 方法回调
+			 */
+			submit(keepitem, callback, type) {
+				for (let i in this.dataValue) {
+					const itemData = this.childrens.find(v => v.name === i);
+					if (itemData) {
+						if (this.formData[i] === undefined) {
+							this.formData[i] = this._getValue(i, this.dataValue[i]);
+						}
+					}
+				}
+
+				if (!type) {
+					console.warn('submit 方法即将废弃,请使用validate方法代替!');
+				}
+
+				return this.checkAll(this.formData, keepitem, callback, 'submit');
+			},
+
+			// 校验所有
+			async checkAll(invalidFields, keepitem, callback, type) {
+				// 不存在校验规则 ,则停止校验流程
+				if (!this.validator) return
+				let childrens = []
+				// 处理参与校验的item实例
+				for (let i in invalidFields) {
+					const item = this.childrens.find(v => realName(v.name) === i)
+					if (item) {
+						childrens.push(item)
+					}
+				}
+
+				// 如果validate第一个参数是funciont ,那就走回调
+				if (!callback && typeof keepitem === 'function') {
+					callback = keepitem;
+				}
+
+				let promise;
+				// 如果不存在回调,那么使用 Promise 方式返回
+				if (!callback && typeof callback !== 'function' && Promise) {
+					promise = new Promise((resolve, reject) => {
+						callback = function(valid, invalidFields) {
+							!valid ? resolve(invalidFields) : reject(valid);
+						};
+					});
+				}
+
+				let results = [];
+				// 避免引用错乱 ,建议拷贝对象处理
+				let tempFormData = JSON.parse(JSON.stringify(invalidFields))
+				// 所有子组件参与校验,使用 for 可以使用  awiat
+				for (let i in childrens) {
+					const child = childrens[i]
+					let name = realName(child.name);
+					const result = await child.onFieldChange(tempFormData[name]);
+					if (result) {
+						results.push(result);
+						// toast ,modal 只需要执行第一次就可以
+						if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
+					}
+				}
+
+
+				if (Array.isArray(results)) {
+					if (results.length === 0) results = null;
+				}
+				if (Array.isArray(keepitem)) {
+					keepitem.forEach(v => {
+						let vName = realName(v);
+						let value = getDataValue(v, this.localData)
+						if (value !== undefined) {
+							tempFormData[vName] = value
+						}
+					});
+				}
+
+				// TODO submit 即将废弃
+				if (type === 'submit') {
+					this.$emit('submit', {
+						detail: {
+							value: tempFormData,
+							errors: results
+						}
+					});
+				} else {
+					this.$emit('validate', results);
+				}
+
+				// const resetFormData = rawData(tempFormData, this.localData, this.name)
+				let resetFormData = {}
+				resetFormData = rawData(tempFormData, this.name)
+				callback && typeof callback === 'function' && callback(results, resetFormData);
+
+				if (promise && callback) {
+					return promise;
+				} else {
+					return null;
+				}
+
+			},
+
+			/**
+			 * 返回validate事件
+			 * @param {Object} result
+			 */
+			validateCheck(result) {
+				this.$emit('validate', result);
+			},
+			_getValue: getValue,
+			_isRequiredField: isRequiredField,
+			_setDataValue: setDataValue,
+			_getDataValue: getDataValue,
+			_realName: realName,
+			_isRealName: isRealName,
+			_isEqual: isEqual
+		}
+	};
+</script>
+
+<style lang="scss">
+	.uni-forms {}
 </style>
 </style>

+ 281 - 281
uni_modules/uni-forms/components/uni-forms/utils.js

@@ -1,293 +1,293 @@
-/**
- * 简单处理对象拷贝
- * @param {Obejct} 被拷贝对象
- * @@return {Object} 拷贝对象
- */
-export const deepCopy = (val) => {
-	return JSON.parse(JSON.stringify(val))
-}
-/**
- * 过滤数字类型
- * @param {String} format 数字类型
- * @@return {Boolean} 返回是否为数字类型
- */
-export const typeFilter = (format) => {
-	return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
-}
-
-/**
- * 把 value 转换成指定的类型,用于处理初始值,原因是初始值需要入库不能为 undefined
- * @param {String} key 字段名
- * @param {any} value 字段值
- * @param {Object} rules 表单校验规则
- */
-export const getValue = (key, value, rules) => {
-	const isRuleNumType = rules.find(val => val.format && typeFilter(val.format));
-	const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
-	// 输入类型为 number
-	if (!!isRuleNumType) {
-		if (!value && value !== 0) {
-			value = null
-		} else {
-			value = isNumber(Number(value)) ? Number(value) : value
-		}
-	}
-
-	// 输入类型为 boolean
-	if (!!isRuleBoolType) {
-		value = isBoolean(value) ? value : false
-	}
-
-	return value;
-}
-
-/**
- * 获取表单数据
- * @param {String|Array} name 真实名称,需要使用 realName 获取
- * @param {Object} data 原始数据
- * @param {any} value  需要设置的值
- */
-export const setDataValue = (field, formdata, value) => {
-	formdata[field] = value
-	return value || ''
-}
-
-/**
- * 获取表单数据
- * @param {String|Array} field 真实名称,需要使用 realName 获取
- * @param {Object} data 原始数据
- */
-export const getDataValue = (field, data) => {
-	return objGet(data, field)
-}
-
-/**
- * 获取表单类型
- * @param {String|Array} field 真实名称,需要使用 realName 获取
- */
-export const getDataValueType = (field, data) => {
-	const value = getDataValue(field, data)
-	return {
-		type: type(value),
-		value
-	}
-}
-
-/**
- * 获取表单可用的真实name
- * @param {String|Array} name 表单name
- * @@return {String} 表单可用的真实name
- */
+/**
+ * 简单处理对象拷贝
+ * @param {Obejct} 被拷贝对象
+ * @@return {Object} 拷贝对象
+ */
+export const deepCopy = (val) => {
+	return JSON.parse(JSON.stringify(val))
+}
+/**
+ * 过滤数字类型
+ * @param {String} format 数字类型
+ * @@return {Boolean} 返回是否为数字类型
+ */
+export const typeFilter = (format) => {
+	return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
+}
+
+/**
+ * 把 value 转换成指定的类型,用于处理初始值,原因是初始值需要入库不能为 undefined
+ * @param {String} key 字段名
+ * @param {any} value 字段值
+ * @param {Object} rules 表单校验规则
+ */
+export const getValue = (key, value, rules) => {
+	const isRuleNumType = rules.find(val => val.format && typeFilter(val.format));
+	const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
+	// 输入类型为 number
+	if (!!isRuleNumType) {
+		if (!value && value !== 0) {
+			value = null
+		} else {
+			value = isNumber(Number(value)) ? Number(value) : value
+		}
+	}
+
+	// 输入类型为 boolean
+	if (!!isRuleBoolType) {
+		value = isBoolean(value) ? value : false
+	}
+
+	return value;
+}
+
+/**
+ * 获取表单数据
+ * @param {String|Array} name 真实名称,需要使用 realName 获取
+ * @param {Object} data 原始数据
+ * @param {any} value  需要设置的值
+ */
+export const setDataValue = (field, formdata, value) => {
+	formdata[field] = value
+	return value || ''
+}
+
+/**
+ * 获取表单数据
+ * @param {String|Array} field 真实名称,需要使用 realName 获取
+ * @param {Object} data 原始数据
+ */
+export const getDataValue = (field, data) => {
+	return objGet(data, field)
+}
+
+/**
+ * 获取表单类型
+ * @param {String|Array} field 真实名称,需要使用 realName 获取
+ */
+export const getDataValueType = (field, data) => {
+	const value = getDataValue(field, data)
+	return {
+		type: type(value),
+		value
+	}
+}
+
+/**
+ * 获取表单可用的真实name
+ * @param {String|Array} name 表单name
+ * @@return {String} 表单可用的真实name
+ */
 export const realName = (name, data = {}) => {
 export const realName = (name, data = {}) => {
 	const base_name = _basePath(name)
 	const base_name = _basePath(name)
-	if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) {
-		const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_')
-		return realname
-	}
-	return base_name[0] || name
-}
-
-/**
- * 判断是否表单可用的真实name
- * @param {String|Array} name 表单name
- * @@return {String} 表单可用的真实name
- */
-export const isRealName = (name) => {
-	const reg = /^_formdata_#*/
-	return reg.test(name)
-}
-
-/**
- * 获取表单数据的原始格式
- * @@return {Object|Array} object 需要解析的数据
- */
-export const rawData = (object = {}, name) => {
+	if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) {
+		const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_')
+		return realname
+	}
+	return base_name[0] || name
+}
+
+/**
+ * 判断是否表单可用的真实name
+ * @param {String|Array} name 表单name
+ * @@return {String} 表单可用的真实name
+ */
+export const isRealName = (name) => {
+	const reg = /^_formdata_#*/
+	return reg.test(name)
+}
+
+/**
+ * 获取表单数据的原始格式
+ * @@return {Object|Array} object 需要解析的数据
+ */
+export const rawData = (object = {}, name) => {
 	let newData = JSON.parse(JSON.stringify(object))
 	let newData = JSON.parse(JSON.stringify(object))
-	let formData = {}
+	let formData = {}
 	for(let i in newData){
 	for(let i in newData){
 		let path = name2arr(i)
 		let path = name2arr(i)
 		objSet(formData,path,newData[i])
 		objSet(formData,path,newData[i])
 	}
 	}
 	return formData
 	return formData
-}
-
-/**
- * 真实name还原为 array
- * @param {*} name 
- */
-export const name2arr = (name) => {
-	let field = name.replace('_formdata_#', '')
-	field = field.split('#').map(v => (isNumber(v) ? Number(v) : v))
-	return field
-}
-
-/**
- * 对象中设置值
- * @param {Object|Array} object 源数据
- * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
- * @param {String} value 需要设置的值
- */
-export const objSet = (object, path, value) => {
-	if (typeof object !== 'object') return object;
-	_basePath(path).reduce((o, k, i, _) => {
+}
+
+/**
+ * 真实name还原为 array
+ * @param {*} name 
+ */
+export const name2arr = (name) => {
+	let field = name.replace('_formdata_#', '')
+	field = field.split('#').map(v => (isNumber(v) ? Number(v) : v))
+	return field
+}
+
+/**
+ * 对象中设置值
+ * @param {Object|Array} object 源数据
+ * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
+ * @param {String} value 需要设置的值
+ */
+export const objSet = (object, path, value) => {
+	if (typeof object !== 'object') return object;
+	_basePath(path).reduce((o, k, i, _) => {
 		if (i === _.length - 1) { 
 		if (i === _.length - 1) { 
-			// 若遍历结束直接赋值
-			o[k] = value
-			return null
+			// 若遍历结束直接赋值
+			o[k] = value
+			return null
 		} else if (k in o) { 
 		} else if (k in o) { 
-			// 若存在对应路径,则返回找到的对象,进行下一次遍历
-			return o[k]
+			// 若存在对应路径,则返回找到的对象,进行下一次遍历
+			return o[k]
 		} else { 
 		} else { 
-			// 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象
-			o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
-			return o[k]
-		}
-	}, object)
-	// 返回object
-	return object;
-}
-
-// 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用
-function _basePath(path) {
-	// 若是数组,则直接返回
-	if (Array.isArray(path)) return path
-	// 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']'
-	return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
-}
-
-/**
- * 从对象中获取值
- * @param {Object|Array} object 源数据
- * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
- * @param {String} defaultVal 如果无法从调用链中获取值的默认值
- */
-export const objGet = (object, path, defaultVal = 'undefined') => {
-	// 先将path处理成统一格式
-	let newPath = _basePath(path)
-	// 递归处理,返回最后结果
-	let val = newPath.reduce((o, k) => {
-		return (o || {})[k]
-	}, object);
-	return !val || val !== undefined ? val : defaultVal
-}
-
-
-/**
- * 是否为 number 类型 
- * @param {any} num 需要判断的值
- * @return {Boolean} 是否为 number
- */
-export const isNumber = (num) => {
-	return !isNaN(Number(num))
-}
-
-/**
- * 是否为 boolean 类型 
- * @param {any} bool 需要判断的值
- * @return {Boolean} 是否为 boolean
- */
-export const isBoolean = (bool) => {
-	return (typeof bool === 'boolean')
-}
-/**
- * 是否有必填字段
- * @param {Object} rules 规则
- * @return {Boolean} 是否有必填字段
- */
-export const isRequiredField = (rules) => {
-	let isNoField = false;
-	for (let i = 0; i < rules.length; i++) {
-		const ruleData = rules[i];
-		if (ruleData.required) {
-			isNoField = true;
-			break;
-		}
-	}
-	return isNoField;
-}
-
-
-/**
- * 获取数据类型
- * @param {Any} obj 需要获取数据类型的值
- */
-export const type = (obj) => {
-	var class2type = {};
-
-	// 生成class2type映射
-	"Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
-		class2type["[object " + item + "]"] = item.toLowerCase();
-	})
-	if (obj == null) {
-		return obj + "";
-	}
-	return typeof obj === "object" || typeof obj === "function" ?
-		class2type[Object.prototype.toString.call(obj)] || "object" :
-		typeof obj;
-}
-
-/**
- * 判断两个值是否相等
- * @param {any} a 值  
- * @param {any} b 值  
- * @return {Boolean} 是否相等
- */
-export const isEqual = (a, b) => {
-	//如果a和b本来就全等
-	if (a === b) {
-		//判断是否为0和-0
-		return a !== 0 || 1 / a === 1 / b;
-	}
-	//判断是否为null和undefined
-	if (a == null || b == null) {
-		return a === b;
-	}
-	//接下来判断a和b的数据类型
-	var classNameA = toString.call(a),
-		classNameB = toString.call(b);
-	//如果数据类型不相等,则返回false
-	if (classNameA !== classNameB) {
-		return false;
-	}
-	//如果数据类型相等,再根据不同数据类型分别判断
-	switch (classNameA) {
-		case '[object RegExp]':
-		case '[object String]':
-			//进行字符串转换比较
-			return '' + a === '' + b;
-		case '[object Number]':
-			//进行数字转换比较,判断是否为NaN
-			if (+a !== +a) {
-				return +b !== +b;
-			}
-			//判断是否为0或-0
-			return +a === 0 ? 1 / +a === 1 / b : +a === +b;
-		case '[object Date]':
-		case '[object Boolean]':
-			return +a === +b;
-	}
-	//如果是对象类型
-	if (classNameA == '[object Object]') {
-		//获取a和b的属性长度
-		var propsA = Object.getOwnPropertyNames(a),
-			propsB = Object.getOwnPropertyNames(b);
-		if (propsA.length != propsB.length) {
-			return false;
-		}
-		for (var i = 0; i < propsA.length; i++) {
-			var propName = propsA[i];
-			//如果对应属性对应值不相等,则返回false
-			if (a[propName] !== b[propName]) {
-				return false;
-			}
-		}
-		return true;
-	}
-	//如果是数组类型
-	if (classNameA == '[object Array]') {
-		if (a.toString() == b.toString()) {
-			return true;
-		}
-		return false;
-	}
+			// 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象
+			o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
+			return o[k]
+		}
+	}, object)
+	// 返回object
+	return object;
+}
+
+// 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用
+function _basePath(path) {
+	// 若是数组,则直接返回
+	if (Array.isArray(path)) return path
+	// 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']'
+	return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
+}
+
+/**
+ * 从对象中获取值
+ * @param {Object|Array} object 源数据
+ * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
+ * @param {String} defaultVal 如果无法从调用链中获取值的默认值
+ */
+export const objGet = (object, path, defaultVal = 'undefined') => {
+	// 先将path处理成统一格式
+	let newPath = _basePath(path)
+	// 递归处理,返回最后结果
+	let val = newPath.reduce((o, k) => {
+		return (o || {})[k]
+	}, object);
+	return !val || val !== undefined ? val : defaultVal
+}
+
+
+/**
+ * 是否为 number 类型 
+ * @param {any} num 需要判断的值
+ * @return {Boolean} 是否为 number
+ */
+export const isNumber = (num) => {
+	return !isNaN(Number(num))
+}
+
+/**
+ * 是否为 boolean 类型 
+ * @param {any} bool 需要判断的值
+ * @return {Boolean} 是否为 boolean
+ */
+export const isBoolean = (bool) => {
+	return (typeof bool === 'boolean')
+}
+/**
+ * 是否有必填字段
+ * @param {Object} rules 规则
+ * @return {Boolean} 是否有必填字段
+ */
+export const isRequiredField = (rules) => {
+	let isNoField = false;
+	for (let i = 0; i < rules.length; i++) {
+		const ruleData = rules[i];
+		if (ruleData.required) {
+			isNoField = true;
+			break;
+		}
+	}
+	return isNoField;
+}
+
+
+/**
+ * 获取数据类型
+ * @param {Any} obj 需要获取数据类型的值
+ */
+export const type = (obj) => {
+	var class2type = {};
+
+	// 生成class2type映射
+	"Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
+		class2type["[object " + item + "]"] = item.toLowerCase();
+	})
+	if (obj == null) {
+		return obj + "";
+	}
+	return typeof obj === "object" || typeof obj === "function" ?
+		class2type[Object.prototype.toString.call(obj)] || "object" :
+		typeof obj;
+}
+
+/**
+ * 判断两个值是否相等
+ * @param {any} a 值  
+ * @param {any} b 值  
+ * @return {Boolean} 是否相等
+ */
+export const isEqual = (a, b) => {
+	//如果a和b本来就全等
+	if (a === b) {
+		//判断是否为0和-0
+		return a !== 0 || 1 / a === 1 / b;
+	}
+	//判断是否为null和undefined
+	if (a == null || b == null) {
+		return a === b;
+	}
+	//接下来判断a和b的数据类型
+	var classNameA = toString.call(a),
+		classNameB = toString.call(b);
+	//如果数据类型不相等,则返回false
+	if (classNameA !== classNameB) {
+		return false;
+	}
+	//如果数据类型相等,再根据不同数据类型分别判断
+	switch (classNameA) {
+		case '[object RegExp]':
+		case '[object String]':
+			//进行字符串转换比较
+			return '' + a === '' + b;
+		case '[object Number]':
+			//进行数字转换比较,判断是否为NaN
+			if (+a !== +a) {
+				return +b !== +b;
+			}
+			//判断是否为0或-0
+			return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+		case '[object Date]':
+		case '[object Boolean]':
+			return +a === +b;
+	}
+	//如果是对象类型
+	if (classNameA == '[object Object]') {
+		//获取a和b的属性长度
+		var propsA = Object.getOwnPropertyNames(a),
+			propsB = Object.getOwnPropertyNames(b);
+		if (propsA.length != propsB.length) {
+			return false;
+		}
+		for (var i = 0; i < propsA.length; i++) {
+			var propName = propsA[i];
+			//如果对应属性对应值不相等,则返回false
+			if (a[propName] !== b[propName]) {
+				return false;
+			}
+		}
+		return true;
+	}
+	//如果是数组类型
+	if (classNameA == '[object Array]') {
+		if (a.toString() == b.toString()) {
+			return true;
+		}
+		return false;
+	}
 }
 }

+ 485 - 485
uni_modules/uni-forms/components/uni-forms/validate.js

@@ -1,486 +1,486 @@
-var pattern = {
-	email: /^\S+?@\S+?\.\S+?$/,
-	idcard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
-	url: new RegExp(
-		"^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$",
-		'i')
-};
-
-const FORMAT_MAPPING = {
-	"int": 'integer',
-	"bool": 'boolean',
-	"double": 'number',
-	"long": 'number',
-	"password": 'string'
-	// "fileurls": 'array'
-}
-
-function formatMessage(args, resources = '') {
-	var defaultMessage = ['label']
-	defaultMessage.forEach((item) => {
-		if (args[item] === undefined) {
-			args[item] = ''
-		}
-	})
-
-	let str = resources
-	for (let key in args) {
-		let reg = new RegExp('{' + key + '}')
-		str = str.replace(reg, args[key])
-	}
-	return str
-}
-
-function isEmptyValue(value, type) {
-	if (value === undefined || value === null) {
-		return true;
-	}
-
-	if (typeof value === 'string' && !value) {
-		return true;
-	}
-
-	if (Array.isArray(value) && !value.length) {
-		return true;
-	}
-
-	if (type === 'object' && !Object.keys(value).length) {
-		return true;
-	}
-
-	return false;
-}
-
-const types = {
-	integer(value) {
-		return types.number(value) && parseInt(value, 10) === value;
-	},
-	string(value) {
-		return typeof value === 'string';
-	},
-	number(value) {
-		if (isNaN(value)) {
-			return false;
-		}
-		return typeof value === 'number';
-	},
-	"boolean": function(value) {
-		return typeof value === 'boolean';
-	},
-	"float": function(value) {
-		return types.number(value) && !types.integer(value);
-	},
-	array(value) {
-		return Array.isArray(value);
-	},
-	object(value) {
-		return typeof value === 'object' && !types.array(value);
-	},
-	date(value) {
-		return value instanceof Date;
-	},
-	timestamp(value) {
-		if (!this.integer(value) || Math.abs(value).toString().length > 16) {
-			return false
-		}
-		return true;
-	},
-	file(value) {
-		return typeof value.url === 'string';
-	},
-	email(value) {
-		return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255;
-	},
-	url(value) {
-		return typeof value === 'string' && !!value.match(pattern.url);
-	},
-	pattern(reg, value) {
-		try {
-			return new RegExp(reg).test(value);
-		} catch (e) {
-			return false;
-		}
-	},
-	method(value) {
-		return typeof value === 'function';
-	},
-	idcard(value) {
-		return typeof value === 'string' && !!value.match(pattern.idcard);
-	},
-	'url-https'(value) {
-		return this.url(value) && value.startsWith('https://');
-	},
-	'url-scheme'(value) {
-		return value.startsWith('://');
-	},
-	'url-web'(value) {
-		return false;
-	}
-}
-
-class RuleValidator {
-
-	constructor(message) {
-		this._message = message
-	}
-
-	async validateRule(fieldKey, fieldValue, value, data, allData) {
-		var result = null
-
-		let rules = fieldValue.rules
-
-		let hasRequired = rules.findIndex((item) => {
-			return item.required
-		})
-		if (hasRequired < 0) {
-			if (value === null || value === undefined) {
-				return result
-			}
-			if (typeof value === 'string' && !value.length) {
-				return result
-			}
-		}
-
-		var message = this._message
-
-		if (rules === undefined) {
-			return message['default']
-		}
-
-		for (var i = 0; i < rules.length; i++) {
-			let rule = rules[i]
-			let vt = this._getValidateType(rule)
-
-			Object.assign(rule, {
-				label: fieldValue.label || `["${fieldKey}"]`
-			})
-
-			if (RuleValidatorHelper[vt]) {
-				result = RuleValidatorHelper[vt](rule, value, message)
-				if (result != null) {
-					break
-				}
-			}
-
-			if (rule.validateExpr) {
-				let now = Date.now()
-				let resultExpr = rule.validateExpr(value, allData, now)
-				if (resultExpr === false) {
-					result = this._getMessage(rule, rule.errorMessage || this._message['default'])
-					break
-				}
-			}
-
-			if (rule.validateFunction) {
-				result = await this.validateFunction(rule, value, data, allData, vt)
-				if (result !== null) {
-					break
-				}
-			}
-		}
-
-		if (result !== null) {
-			result = message.TAG + result
-		}
-
-		return result
-	}
-
-	async validateFunction(rule, value, data, allData, vt) {
-		let result = null
-		try {
-			let callbackMessage = null
-			const res = await rule.validateFunction(rule, value, allData || data, (message) => {
-				callbackMessage = message
-			})
-			if (callbackMessage || (typeof res === 'string' && res) || res === false) {
-				result = this._getMessage(rule, callbackMessage || res, vt)
-			}
-		} catch (e) {
-			result = this._getMessage(rule, e.message, vt)
-		}
-		return result
-	}
-
-	_getMessage(rule, message, vt) {
-		return formatMessage(rule, message || rule.errorMessage || this._message[vt] || message['default'])
-	}
-
-	_getValidateType(rule) {
-		var result = ''
-		if (rule.required) {
-			result = 'required'
-		} else if (rule.format) {
-			result = 'format'
-		} else if (rule.arrayType) {
-			result = 'arrayTypeFormat'
-		} else if (rule.range) {
-			result = 'range'
-		} else if (rule.maximum !== undefined || rule.minimum !== undefined) {
-			result = 'rangeNumber'
-		} else if (rule.maxLength !== undefined || rule.minLength !== undefined) {
-			result = 'rangeLength'
-		} else if (rule.pattern) {
-			result = 'pattern'
-		} else if (rule.validateFunction) {
-			result = 'validateFunction'
-		}
-		return result
-	}
-}
-
-const RuleValidatorHelper = {
-	required(rule, value, message) {
-		if (rule.required && isEmptyValue(value, rule.format || typeof value)) {
-			return formatMessage(rule, rule.errorMessage || message.required);
-		}
-
-		return null
-	},
-
-	range(rule, value, message) {
-		const {
-			range,
-			errorMessage
-		} = rule;
-
-		let list = new Array(range.length);
-		for (let i = 0; i < range.length; i++) {
-			const item = range[i];
-			if (types.object(item) && item.value !== undefined) {
-				list[i] = item.value;
-			} else {
-				list[i] = item;
-			}
-		}
-
-		let result = false
-		if (Array.isArray(value)) {
-			result = (new Set(value.concat(list)).size === list.length);
-		} else {
-			if (list.indexOf(value) > -1) {
-				result = true;
-			}
-		}
-
-		if (!result) {
-			return formatMessage(rule, errorMessage || message['enum']);
-		}
-
-		return null
-	},
-
-	rangeNumber(rule, value, message) {
-		if (!types.number(value)) {
-			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
-		}
-
-		let {
-			minimum,
-			maximum,
-			exclusiveMinimum,
-			exclusiveMaximum
-		} = rule;
-		let min = exclusiveMinimum ? value <= minimum : value < minimum;
-		let max = exclusiveMaximum ? value >= maximum : value > maximum;
-
-		if (minimum !== undefined && min) {
-			return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMinimum ?
-				'exclusiveMinimum' : 'minimum'
-			])
-		} else if (maximum !== undefined && max) {
-			return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMaximum ?
-				'exclusiveMaximum' : 'maximum'
-			])
-		} else if (minimum !== undefined && maximum !== undefined && (min || max)) {
-			return formatMessage(rule, rule.errorMessage || message['number'].range)
-		}
-
-		return null
-	},
-
-	rangeLength(rule, value, message) {
-		if (!types.string(value) && !types.array(value)) {
-			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
-		}
-
-		let min = rule.minLength;
-		let max = rule.maxLength;
-		let val = value.length;
-
-		if (min !== undefined && val < min) {
-			return formatMessage(rule, rule.errorMessage || message['length'].minLength)
-		} else if (max !== undefined && val > max) {
-			return formatMessage(rule, rule.errorMessage || message['length'].maxLength)
-		} else if (min !== undefined && max !== undefined && (val < min || val > max)) {
-			return formatMessage(rule, rule.errorMessage || message['length'].range)
-		}
-
-		return null
-	},
-
-	pattern(rule, value, message) {
-		if (!types['pattern'](rule.pattern, value)) {
-			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
-		}
-
-		return null
-	},
-
-	format(rule, value, message) {
-		var customTypes = Object.keys(types);
-		var format = FORMAT_MAPPING[rule.format] ? FORMAT_MAPPING[rule.format] : (rule.format || rule.arrayType);
-
-		if (customTypes.indexOf(format) > -1) {
-			if (!types[format](value)) {
-				return formatMessage(rule, rule.errorMessage || message.typeError);
-			}
-		}
-
-		return null
-	},
-
-	arrayTypeFormat(rule, value, message) {
-		if (!Array.isArray(value)) {
-			return formatMessage(rule, rule.errorMessage || message.typeError);
-		}
-
-		for (let i = 0; i < value.length; i++) {
-			const element = value[i];
-			let formatResult = this.format(rule, element, message)
-			if (formatResult !== null) {
-				return formatResult
-			}
-		}
-
-		return null
-	}
-}
-
-class SchemaValidator extends RuleValidator {
-
-	constructor(schema, options) {
-		super(SchemaValidator.message);
-
-		this._schema = schema
-		this._options = options || null
-	}
-
-	updateSchema(schema) {
-		this._schema = schema
-	}
-
-	async validate(data, allData) {
-		let result = this._checkFieldInSchema(data)
-		if (!result) {
-			result = await this.invokeValidate(data, false, allData)
-		}
-		return result.length ? result[0] : null
-	}
-
-	async validateAll(data, allData) {
-		let result = this._checkFieldInSchema(data)
-		if (!result) {
-			result = await this.invokeValidate(data, true, allData)
-		}
-		return result
-	}
-
-	async validateUpdate(data, allData) {
-		let result = this._checkFieldInSchema(data)
-		if (!result) {
-			result = await this.invokeValidateUpdate(data, false, allData)
-		}
-		return result.length ? result[0] : null
-	}
-
-	async invokeValidate(data, all, allData) {
-		let result = []
-		let schema = this._schema
-		for (let key in schema) {
-			let value = schema[key]
-			let errorMessage = await this.validateRule(key, value, data[key], data, allData)
-			if (errorMessage != null) {
-				result.push({
-					key,
-					errorMessage
-				})
-				if (!all) break
-			}
-		}
-		return result
-	}
-
-	async invokeValidateUpdate(data, all, allData) {
-		let result = []
-		for (let key in data) {
-			let errorMessage = await this.validateRule(key, this._schema[key], data[key], data, allData)
-			if (errorMessage != null) {
-				result.push({
-					key,
-					errorMessage
-				})
-				if (!all) break
-			}
-		}
-		return result
-	}
-
-	_checkFieldInSchema(data) {
-		var keys = Object.keys(data)
-		var keys2 = Object.keys(this._schema)
-		if (new Set(keys.concat(keys2)).size === keys2.length) {
-			return ''
-		}
-
-		var noExistFields = keys.filter((key) => {
-			return keys2.indexOf(key) < 0;
-		})
-		var errorMessage = formatMessage({
-			field: JSON.stringify(noExistFields)
-		}, SchemaValidator.message.TAG + SchemaValidator.message['defaultInvalid'])
-		return [{
-			key: 'invalid',
-			errorMessage
-		}]
-	}
-}
-
-function Message() {
-	return {
-		TAG: "",
-		default: '验证错误',
-		defaultInvalid: '提交的字段{field}在数据库中并不存在',
-		validateFunction: '验证无效',
-		required: '{label}必填',
-		'enum': '{label}超出范围',
-		timestamp: '{label}格式无效',
-		whitespace: '{label}不能为空',
-		typeError: '{label}类型无效',
-		date: {
-			format: '{label}日期{value}格式无效',
-			parse: '{label}日期无法解析,{value}无效',
-			invalid: '{label}日期{value}无效'
-		},
-		length: {
-			minLength: '{label}长度不能少于{minLength}',
-			maxLength: '{label}长度不能超过{maxLength}',
-			range: '{label}必须介于{minLength}和{maxLength}之间'
-		},
-		number: {
-			minimum: '{label}不能小于{minimum}',
-			maximum: '{label}不能大于{maximum}',
-			exclusiveMinimum: '{label}不能小于等于{minimum}',
-			exclusiveMaximum: '{label}不能大于等于{maximum}',
-			range: '{label}必须介于{minimum}and{maximum}之间'
-		},
-		pattern: {
-			mismatch: '{label}格式不匹配'
-		}
-	};
-}
-
-
-SchemaValidator.message = new Message();
-
+var pattern = {
+	email: /^\S+?@\S+?\.\S+?$/,
+	idcard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
+	url: new RegExp(
+		"^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$",
+		'i')
+};
+
+const FORMAT_MAPPING = {
+	"int": 'integer',
+	"bool": 'boolean',
+	"double": 'number',
+	"long": 'number',
+	"password": 'string'
+	// "fileurls": 'array'
+}
+
+function formatMessage(args, resources = '') {
+	var defaultMessage = ['label']
+	defaultMessage.forEach((item) => {
+		if (args[item] === undefined) {
+			args[item] = ''
+		}
+	})
+
+	let str = resources
+	for (let key in args) {
+		let reg = new RegExp('{' + key + '}')
+		str = str.replace(reg, args[key])
+	}
+	return str
+}
+
+function isEmptyValue(value, type) {
+	if (value === undefined || value === null) {
+		return true;
+	}
+
+	if (typeof value === 'string' && !value) {
+		return true;
+	}
+
+	if (Array.isArray(value) && !value.length) {
+		return true;
+	}
+
+	if (type === 'object' && !Object.keys(value).length) {
+		return true;
+	}
+
+	return false;
+}
+
+const types = {
+	integer(value) {
+		return types.number(value) && parseInt(value, 10) === value;
+	},
+	string(value) {
+		return typeof value === 'string';
+	},
+	number(value) {
+		if (isNaN(value)) {
+			return false;
+		}
+		return typeof value === 'number';
+	},
+	"boolean": function(value) {
+		return typeof value === 'boolean';
+	},
+	"float": function(value) {
+		return types.number(value) && !types.integer(value);
+	},
+	array(value) {
+		return Array.isArray(value);
+	},
+	object(value) {
+		return typeof value === 'object' && !types.array(value);
+	},
+	date(value) {
+		return value instanceof Date;
+	},
+	timestamp(value) {
+		if (!this.integer(value) || Math.abs(value).toString().length > 16) {
+			return false
+		}
+		return true;
+	},
+	file(value) {
+		return typeof value.url === 'string';
+	},
+	email(value) {
+		return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255;
+	},
+	url(value) {
+		return typeof value === 'string' && !!value.match(pattern.url);
+	},
+	pattern(reg, value) {
+		try {
+			return new RegExp(reg).test(value);
+		} catch (e) {
+			return false;
+		}
+	},
+	method(value) {
+		return typeof value === 'function';
+	},
+	idcard(value) {
+		return typeof value === 'string' && !!value.match(pattern.idcard);
+	},
+	'url-https'(value) {
+		return this.url(value) && value.startsWith('https://');
+	},
+	'url-scheme'(value) {
+		return value.startsWith('://');
+	},
+	'url-web'(value) {
+		return false;
+	}
+}
+
+class RuleValidator {
+
+	constructor(message) {
+		this._message = message
+	}
+
+	async validateRule(fieldKey, fieldValue, value, data, allData) {
+		var result = null
+
+		let rules = fieldValue.rules
+
+		let hasRequired = rules.findIndex((item) => {
+			return item.required
+		})
+		if (hasRequired < 0) {
+			if (value === null || value === undefined) {
+				return result
+			}
+			if (typeof value === 'string' && !value.length) {
+				return result
+			}
+		}
+
+		var message = this._message
+
+		if (rules === undefined) {
+			return message['default']
+		}
+
+		for (var i = 0; i < rules.length; i++) {
+			let rule = rules[i]
+			let vt = this._getValidateType(rule)
+
+			Object.assign(rule, {
+				label: fieldValue.label || `["${fieldKey}"]`
+			})
+
+			if (RuleValidatorHelper[vt]) {
+				result = RuleValidatorHelper[vt](rule, value, message)
+				if (result != null) {
+					break
+				}
+			}
+
+			if (rule.validateExpr) {
+				let now = Date.now()
+				let resultExpr = rule.validateExpr(value, allData, now)
+				if (resultExpr === false) {
+					result = this._getMessage(rule, rule.errorMessage || this._message['default'])
+					break
+				}
+			}
+
+			if (rule.validateFunction) {
+				result = await this.validateFunction(rule, value, data, allData, vt)
+				if (result !== null) {
+					break
+				}
+			}
+		}
+
+		if (result !== null) {
+			result = message.TAG + result
+		}
+
+		return result
+	}
+
+	async validateFunction(rule, value, data, allData, vt) {
+		let result = null
+		try {
+			let callbackMessage = null
+			const res = await rule.validateFunction(rule, value, allData || data, (message) => {
+				callbackMessage = message
+			})
+			if (callbackMessage || (typeof res === 'string' && res) || res === false) {
+				result = this._getMessage(rule, callbackMessage || res, vt)
+			}
+		} catch (e) {
+			result = this._getMessage(rule, e.message, vt)
+		}
+		return result
+	}
+
+	_getMessage(rule, message, vt) {
+		return formatMessage(rule, message || rule.errorMessage || this._message[vt] || message['default'])
+	}
+
+	_getValidateType(rule) {
+		var result = ''
+		if (rule.required) {
+			result = 'required'
+		} else if (rule.format) {
+			result = 'format'
+		} else if (rule.arrayType) {
+			result = 'arrayTypeFormat'
+		} else if (rule.range) {
+			result = 'range'
+		} else if (rule.maximum !== undefined || rule.minimum !== undefined) {
+			result = 'rangeNumber'
+		} else if (rule.maxLength !== undefined || rule.minLength !== undefined) {
+			result = 'rangeLength'
+		} else if (rule.pattern) {
+			result = 'pattern'
+		} else if (rule.validateFunction) {
+			result = 'validateFunction'
+		}
+		return result
+	}
+}
+
+const RuleValidatorHelper = {
+	required(rule, value, message) {
+		if (rule.required && isEmptyValue(value, rule.format || typeof value)) {
+			return formatMessage(rule, rule.errorMessage || message.required);
+		}
+
+		return null
+	},
+
+	range(rule, value, message) {
+		const {
+			range,
+			errorMessage
+		} = rule;
+
+		let list = new Array(range.length);
+		for (let i = 0; i < range.length; i++) {
+			const item = range[i];
+			if (types.object(item) && item.value !== undefined) {
+				list[i] = item.value;
+			} else {
+				list[i] = item;
+			}
+		}
+
+		let result = false
+		if (Array.isArray(value)) {
+			result = (new Set(value.concat(list)).size === list.length);
+		} else {
+			if (list.indexOf(value) > -1) {
+				result = true;
+			}
+		}
+
+		if (!result) {
+			return formatMessage(rule, errorMessage || message['enum']);
+		}
+
+		return null
+	},
+
+	rangeNumber(rule, value, message) {
+		if (!types.number(value)) {
+			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+		}
+
+		let {
+			minimum,
+			maximum,
+			exclusiveMinimum,
+			exclusiveMaximum
+		} = rule;
+		let min = exclusiveMinimum ? value <= minimum : value < minimum;
+		let max = exclusiveMaximum ? value >= maximum : value > maximum;
+
+		if (minimum !== undefined && min) {
+			return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMinimum ?
+				'exclusiveMinimum' : 'minimum'
+			])
+		} else if (maximum !== undefined && max) {
+			return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMaximum ?
+				'exclusiveMaximum' : 'maximum'
+			])
+		} else if (minimum !== undefined && maximum !== undefined && (min || max)) {
+			return formatMessage(rule, rule.errorMessage || message['number'].range)
+		}
+
+		return null
+	},
+
+	rangeLength(rule, value, message) {
+		if (!types.string(value) && !types.array(value)) {
+			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+		}
+
+		let min = rule.minLength;
+		let max = rule.maxLength;
+		let val = value.length;
+
+		if (min !== undefined && val < min) {
+			return formatMessage(rule, rule.errorMessage || message['length'].minLength)
+		} else if (max !== undefined && val > max) {
+			return formatMessage(rule, rule.errorMessage || message['length'].maxLength)
+		} else if (min !== undefined && max !== undefined && (val < min || val > max)) {
+			return formatMessage(rule, rule.errorMessage || message['length'].range)
+		}
+
+		return null
+	},
+
+	pattern(rule, value, message) {
+		if (!types['pattern'](rule.pattern, value)) {
+			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+		}
+
+		return null
+	},
+
+	format(rule, value, message) {
+		var customTypes = Object.keys(types);
+		var format = FORMAT_MAPPING[rule.format] ? FORMAT_MAPPING[rule.format] : (rule.format || rule.arrayType);
+
+		if (customTypes.indexOf(format) > -1) {
+			if (!types[format](value)) {
+				return formatMessage(rule, rule.errorMessage || message.typeError);
+			}
+		}
+
+		return null
+	},
+
+	arrayTypeFormat(rule, value, message) {
+		if (!Array.isArray(value)) {
+			return formatMessage(rule, rule.errorMessage || message.typeError);
+		}
+
+		for (let i = 0; i < value.length; i++) {
+			const element = value[i];
+			let formatResult = this.format(rule, element, message)
+			if (formatResult !== null) {
+				return formatResult
+			}
+		}
+
+		return null
+	}
+}
+
+class SchemaValidator extends RuleValidator {
+
+	constructor(schema, options) {
+		super(SchemaValidator.message);
+
+		this._schema = schema
+		this._options = options || null
+	}
+
+	updateSchema(schema) {
+		this._schema = schema
+	}
+
+	async validate(data, allData) {
+		let result = this._checkFieldInSchema(data)
+		if (!result) {
+			result = await this.invokeValidate(data, false, allData)
+		}
+		return result.length ? result[0] : null
+	}
+
+	async validateAll(data, allData) {
+		let result = this._checkFieldInSchema(data)
+		if (!result) {
+			result = await this.invokeValidate(data, true, allData)
+		}
+		return result
+	}
+
+	async validateUpdate(data, allData) {
+		let result = this._checkFieldInSchema(data)
+		if (!result) {
+			result = await this.invokeValidateUpdate(data, false, allData)
+		}
+		return result.length ? result[0] : null
+	}
+
+	async invokeValidate(data, all, allData) {
+		let result = []
+		let schema = this._schema
+		for (let key in schema) {
+			let value = schema[key]
+			let errorMessage = await this.validateRule(key, value, data[key], data, allData)
+			if (errorMessage != null) {
+				result.push({
+					key,
+					errorMessage
+				})
+				if (!all) break
+			}
+		}
+		return result
+	}
+
+	async invokeValidateUpdate(data, all, allData) {
+		let result = []
+		for (let key in data) {
+			let errorMessage = await this.validateRule(key, this._schema[key], data[key], data, allData)
+			if (errorMessage != null) {
+				result.push({
+					key,
+					errorMessage
+				})
+				if (!all) break
+			}
+		}
+		return result
+	}
+
+	_checkFieldInSchema(data) {
+		var keys = Object.keys(data)
+		var keys2 = Object.keys(this._schema)
+		if (new Set(keys.concat(keys2)).size === keys2.length) {
+			return ''
+		}
+
+		var noExistFields = keys.filter((key) => {
+			return keys2.indexOf(key) < 0;
+		})
+		var errorMessage = formatMessage({
+			field: JSON.stringify(noExistFields)
+		}, SchemaValidator.message.TAG + SchemaValidator.message['defaultInvalid'])
+		return [{
+			key: 'invalid',
+			errorMessage
+		}]
+	}
+}
+
+function Message() {
+	return {
+		TAG: "",
+		default: '验证错误',
+		defaultInvalid: '提交的字段{field}在数据库中并不存在',
+		validateFunction: '验证无效',
+		required: '{label}必填',
+		'enum': '{label}超出范围',
+		timestamp: '{label}格式无效',
+		whitespace: '{label}不能为空',
+		typeError: '{label}类型无效',
+		date: {
+			format: '{label}日期{value}格式无效',
+			parse: '{label}日期无法解析,{value}无效',
+			invalid: '{label}日期{value}无效'
+		},
+		length: {
+			minLength: '{label}长度不能少于{minLength}',
+			maxLength: '{label}长度不能超过{maxLength}',
+			range: '{label}必须介于{minLength}和{maxLength}之间'
+		},
+		number: {
+			minimum: '{label}不能小于{minimum}',
+			maximum: '{label}不能大于{maximum}',
+			exclusiveMinimum: '{label}不能小于等于{minimum}',
+			exclusiveMaximum: '{label}不能大于等于{maximum}',
+			range: '{label}必须介于{minimum}and{maximum}之间'
+		},
+		pattern: {
+			mismatch: '{label}格式不匹配'
+		}
+	};
+}
+
+
+SchemaValidator.message = new Message();
+
 export default SchemaValidator
 export default SchemaValidator

+ 6 - 6
uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json

@@ -1,6 +1,6 @@
-{
-	"uni-goods-nav.options.shop": "shop",
-	"uni-goods-nav.options.cart": "cart",
-	"uni-goods-nav.buttonGroup.addToCart": "add to cart",
-	"uni-goods-nav.buttonGroup.buyNow": "buy now"
-}
+{
+	"uni-goods-nav.options.shop": "shop",
+	"uni-goods-nav.options.cart": "cart",
+	"uni-goods-nav.buttonGroup.addToCart": "add to cart",
+	"uni-goods-nav.buttonGroup.buyNow": "buy now"
+}

+ 8 - 8
uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js

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

+ 6 - 6
uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json

@@ -1,6 +1,6 @@
-{
-	"uni-goods-nav.options.shop": "店铺",
-	"uni-goods-nav.options.cart": "购物车",
-	"uni-goods-nav.buttonGroup.addToCart": "加入购物车",
-	"uni-goods-nav.buttonGroup.buyNow": "立即购买"
-}
+{
+	"uni-goods-nav.options.shop": "店铺",
+	"uni-goods-nav.options.cart": "购物车",
+	"uni-goods-nav.buttonGroup.addToCart": "加入购物车",
+	"uni-goods-nav.buttonGroup.buyNow": "立即购买"
+}

+ 6 - 6
uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json

@@ -1,6 +1,6 @@
-{
-	"uni-goods-nav.options.shop": "店鋪",
-	"uni-goods-nav.options.cart": "購物車",
-	"uni-goods-nav.buttonGroup.addToCart": "加入購物車",
-	"uni-goods-nav.buttonGroup.buyNow": "立即購買"
-}
+{
+	"uni-goods-nav.options.shop": "店鋪",
+	"uni-goods-nav.options.cart": "購物車",
+	"uni-goods-nav.buttonGroup.addToCart": "加入購物車",
+	"uni-goods-nav.buttonGroup.buyNow": "立即購買"
+}

+ 224 - 224
uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue

@@ -1,229 +1,229 @@
-<template>
-	<view class="uni-goods-nav">
-		<!-- 底部占位 -->
-		<view class="uni-tab__seat" />
-		<view class="uni-tab__cart-box flex">
-			<view class="flex uni-tab__cart-sub-left">
-				<view v-for="(item,index) in options" :key="index" class="flex uni-tab__cart-button-left uni-tab__shop-cart" @click="onClick(index,item)">
-					<view class="uni-tab__icon">
-						<uni-icons :type="item.icon" size="20" color="#646566"></uni-icons>
-						<!-- <image class="image" :src="item.icon" mode="widthFix" /> -->
-					</view>
-					<text class="uni-tab__text">{{ item.text }}</text>
-					<view class="flex uni-tab__dot-box">
-						<text v-if="item.info" :class="{ 'uni-tab__dots': item.info > 9 }" class="uni-tab__dot " :style="{'backgroundColor':item.infoBackgroundColor?item.infoBackgroundColor:'#ff0000',
-						color:item.infoColor?item.infoColor:'#fff'
-						}">{{ item.info }}</text>
-					</view>
-				</view>
-			</view>
-			<view :class="{'uni-tab__right':fill}" class="flex uni-tab__cart-sub-right ">
-				<view v-for="(item,index) in buttonGroup" :key="index" :style="{background:item.backgroundColor,color:item.color}"
-				 class="flex uni-tab__cart-button-right" @click="buttonClick(index,item)"><text :style="{color:item.color}" class="uni-tab__cart-button-right-text">{{ item.text }}</text></view>
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	import {
-	initVueI18n
-	} from '@dcloudio/uni-i18n'
-	import messages from './i18n/index.js'
-	const {	t	} = initVueI18n(messages)
-	/**
-	 * GoodsNav 商品导航
-	 * @description 商品加入购物车、立即购买等
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=865
-	 * @property {Array} options 组件参数
-	 * @property {Array} buttonGroup 组件按钮组参数
+<template>
+	<view class="uni-goods-nav">
+		<!-- 底部占位 -->
+		<view class="uni-tab__seat" />
+		<view class="uni-tab__cart-box flex">
+			<view class="flex uni-tab__cart-sub-left">
+				<view v-for="(item,index) in options" :key="index" class="flex uni-tab__cart-button-left uni-tab__shop-cart" @click="onClick(index,item)">
+					<view class="uni-tab__icon">
+						<uni-icons :type="item.icon" size="20" color="#646566"></uni-icons>
+						<!-- <image class="image" :src="item.icon" mode="widthFix" /> -->
+					</view>
+					<text class="uni-tab__text">{{ item.text }}</text>
+					<view class="flex uni-tab__dot-box">
+						<text v-if="item.info" :class="{ 'uni-tab__dots': item.info > 9 }" class="uni-tab__dot " :style="{'backgroundColor':item.infoBackgroundColor?item.infoBackgroundColor:'#ff0000',
+						color:item.infoColor?item.infoColor:'#fff'
+						}">{{ item.info }}</text>
+					</view>
+				</view>
+			</view>
+			<view :class="{'uni-tab__right':fill}" class="flex uni-tab__cart-sub-right ">
+				<view v-for="(item,index) in buttonGroup" :key="index" :style="{background:item.backgroundColor,color:item.color}"
+				 class="flex uni-tab__cart-button-right" @click="buttonClick(index,item)"><text :style="{color:item.color}" class="uni-tab__cart-button-right-text">{{ item.text }}</text></view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+	initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	/**
+	 * GoodsNav 商品导航
+	 * @description 商品加入购物车、立即购买等
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=865
+	 * @property {Array} options 组件参数
+	 * @property {Array} buttonGroup 组件按钮组参数
 	 * @property {Boolean} fill = [true | false] 组件按钮组参数
 	 * @property {Boolean} fill = [true | false] 组件按钮组参数
-	 * @property {Boolean} stat 是否开启统计功能
-	 * @event {Function} click 左侧点击事件
-	 * @event {Function} buttonClick 右侧按钮组点击事件
-	 * @example <uni-goods-nav :fill="true"  options="" buttonGroup="buttonGroup"  @click="" @buttonClick="" />
-	 */
-	export default {
-		name: 'UniGoodsNav',
-		emits:['click','buttonClick'],
-		props: {
-			options: {
-				type: Array,
-				default () {
-					return [{
-						icon: 'shop',
-						text: t("uni-goods-nav.options.shop"),
-					}, {
-						icon: 'cart',
-						text: t("uni-goods-nav.options.cart")
-					}]
-				}
-			},
-			buttonGroup: {
-				type: Array,
-				default () {
-					return [{
-							text: t("uni-goods-nav.buttonGroup.addToCart"),
-							backgroundColor: 'linear-gradient(90deg, #FFCD1E, #FF8A18)',
-							color: '#fff'
-						},
-						{
-							text: t("uni-goods-nav.buttonGroup.buyNow"),
-							backgroundColor: 'linear-gradient(90deg, #FE6035, #EF1224)',
-							color: '#fff'
-						}
-					]
-				}
-			},
-			fill: {
-				type: Boolean,
-				default: false
+	 * @property {Boolean} stat 是否开启统计功能
+	 * @event {Function} click 左侧点击事件
+	 * @event {Function} buttonClick 右侧按钮组点击事件
+	 * @example <uni-goods-nav :fill="true"  options="" buttonGroup="buttonGroup"  @click="" @buttonClick="" />
+	 */
+	export default {
+		name: 'UniGoodsNav',
+		emits:['click','buttonClick'],
+		props: {
+			options: {
+				type: Array,
+				default () {
+					return [{
+						icon: 'shop',
+						text: t("uni-goods-nav.options.shop"),
+					}, {
+						icon: 'cart',
+						text: t("uni-goods-nav.options.cart")
+					}]
+				}
+			},
+			buttonGroup: {
+				type: Array,
+				default () {
+					return [{
+							text: t("uni-goods-nav.buttonGroup.addToCart"),
+							backgroundColor: 'linear-gradient(90deg, #FFCD1E, #FF8A18)',
+							color: '#fff'
+						},
+						{
+							text: t("uni-goods-nav.buttonGroup.buyNow"),
+							backgroundColor: 'linear-gradient(90deg, #FE6035, #EF1224)',
+							color: '#fff'
+						}
+					]
+				}
+			},
+			fill: {
+				type: Boolean,
+				default: false
 			},
 			},
 			stat:{
 			stat:{
 				type: Boolean,
 				type: Boolean,
 				default: false
 				default: false
-			}
-		},
-		methods: {
-			onClick(index, item) {
-				this.$emit('click', {
-					index,
-					content: item,
-				})
-			},
-			buttonClick(index, item) {
-				if (uni.report && this.stat) {
-					uni.report(item.text, item.text)
-				}
-				this.$emit('buttonClick', {
-					index,
-					content: item
-				})
-			}
-		}
-	}
-</script>
-
-<style lang="scss" >
-	.flex {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-	}
-
-	.uni-goods-nav {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex: 1;
-		flex-direction: row;
-	}
-
-	.uni-tab__cart-box {
-		flex: 1;
-		height: 50px;
-		background-color: #fff;
-		z-index: 900;
-	}
-
-	.uni-tab__cart-sub-left {
-		padding: 0 5px;
-	}
-
-	.uni-tab__cart-sub-right {
-		flex: 1;
-	}
-
-	.uni-tab__right {
-		margin: 5px 0;
-		margin-right: 10px;
-		border-radius: 100px;
-		overflow: hidden;
-	}
-
-	.uni-tab__cart-button-left {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		// flex: 1;
-		position: relative;
-		justify-content: center;
-		align-items: center;
-		flex-direction: column;
-		margin: 0 10px;
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-tab__icon {
-		width: 18px;
-		height: 18px;
-	}
-
-	.image {
-		width: 18px;
-		height: 18px;
-	}
-
-	.uni-tab__text {
-		margin-top: 3px;
-		font-size: 12px;
-		color: #646566;
-	}
-
-	.uni-tab__cart-button-right {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		flex-direction: column;
-		/* #endif */
-		flex: 1;
-		justify-content: center;
-		align-items: center;
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-tab__cart-button-right-text {
-		font-size: 14px;
-		color: #fff;
-	}
-
-	.uni-tab__cart-button-right:active {
-		opacity: 0.7;
-	}
-
-	.uni-tab__dot-box {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		flex-direction: column;
-		/* #endif */
-		position: absolute;
-		right: -2px;
-		top: 2px;
-		justify-content: center;
-		align-items: center;
-		// width: 0;
-		// height: 0;
-	}
-
-	.uni-tab__dot {
-		// width: 30rpx;
-		// height: 30rpx;
-		padding: 0 4px;
-		line-height: 15px;
-		color: #ffffff;
-		text-align: center;
-		font-size: 12px;
-		background-color: #ff0000;
-		border-radius: 15px;
-	}
-
-	.uni-tab__dots {
-		padding: 0 4px;
-		// width: auto;
-		border-radius: 15px;
-	}
-</style>
+			}
+		},
+		methods: {
+			onClick(index, item) {
+				this.$emit('click', {
+					index,
+					content: item,
+				})
+			},
+			buttonClick(index, item) {
+				if (uni.report && this.stat) {
+					uni.report(item.text, item.text)
+				}
+				this.$emit('buttonClick', {
+					index,
+					content: item
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.flex {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-goods-nav {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+	}
+
+	.uni-tab__cart-box {
+		flex: 1;
+		height: 50px;
+		background-color: #fff;
+		z-index: 900;
+	}
+
+	.uni-tab__cart-sub-left {
+		padding: 0 5px;
+	}
+
+	.uni-tab__cart-sub-right {
+		flex: 1;
+	}
+
+	.uni-tab__right {
+		margin: 5px 0;
+		margin-right: 10px;
+		border-radius: 100px;
+		overflow: hidden;
+	}
+
+	.uni-tab__cart-button-left {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		// flex: 1;
+		position: relative;
+		justify-content: center;
+		align-items: center;
+		flex-direction: column;
+		margin: 0 10px;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-tab__icon {
+		width: 18px;
+		height: 18px;
+	}
+
+	.image {
+		width: 18px;
+		height: 18px;
+	}
+
+	.uni-tab__text {
+		margin-top: 3px;
+		font-size: 12px;
+		color: #646566;
+	}
+
+	.uni-tab__cart-button-right {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-direction: column;
+		/* #endif */
+		flex: 1;
+		justify-content: center;
+		align-items: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-tab__cart-button-right-text {
+		font-size: 14px;
+		color: #fff;
+	}
+
+	.uni-tab__cart-button-right:active {
+		opacity: 0.7;
+	}
+
+	.uni-tab__dot-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-direction: column;
+		/* #endif */
+		position: absolute;
+		right: -2px;
+		top: 2px;
+		justify-content: center;
+		align-items: center;
+		// width: 0;
+		// height: 0;
+	}
+
+	.uni-tab__dot {
+		// width: 30rpx;
+		// height: 30rpx;
+		padding: 0 4px;
+		line-height: 15px;
+		color: #ffffff;
+		text-align: center;
+		font-size: 12px;
+		background-color: #ff0000;
+		border-radius: 15px;
+	}
+
+	.uni-tab__dots {
+		padding: 0 4px;
+		// width: auto;
+		border-radius: 15px;
+	}
+</style>

+ 127 - 127
uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue

@@ -1,127 +1,127 @@
-<template>
-	<view v-if="width" :style="'width:'+width+';'+(square?'height:'+width:'')" class="uni-grid-item">
-		<view :class="{ 'uni-grid-item--border': showBorder,  'uni-grid-item--border-top': showBorder && index < column, 'uni-highlight': highlight }"
-		 :style="{'border-right-color': borderColor ,'border-bottom-color': borderColor ,'border-top-color': borderColor }"
-		 class="uni-grid-item__box" @click="_onClick">
-			<slot />
-		</view>
-	</view>
-</template>
-
-<script>
-	/**
-	 * GridItem 宫格
-	 * @description 宫格组件
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=27
-	 * @property {Number} index 子组件的唯一标识 ,点击gird会返回当前的标识
-	 */
-	export default {
-		name: 'UniGridItem',
-		inject: ['grid'],
-		props: {
-			index: {
-				type: Number,
-				default: 0
-			}
-		},
-		data() {
-			return {
-				column: 0,
-				showBorder: true,
-				square: true,
-				highlight: true,
-				left: 0,
-				top: 0,
-				openNum: 2,
-				width: 0,
-				borderColor: '#e5e5e5'
-			}
-		},
-		created() {
-			this.column = this.grid.column
-			this.showBorder = this.grid.showBorder
-			this.square = this.grid.square
-			this.highlight = this.grid.highlight
-			this.top = this.hor === 0 ? this.grid.hor : this.hor
-			this.left = this.ver === 0 ? this.grid.ver : this.ver
-			this.borderColor = this.grid.borderColor
-			this.grid.children.push(this)
-			// this.grid.init()
-			this.width = this.grid.width
-		},
-		beforeDestroy() {
-			this.grid.children.forEach((item, index) => {
-				if (item === this) {
-					this.grid.children.splice(index, 1)
-				}
-			})
-		},
-		methods: {
-			_onClick() {
-				this.grid.change({
-					detail: {
-						index: this.index
-					}
-				})
-			}
-		}
-	}
-</script>
-
-<style lang="scss" >
-	.uni-grid-item {
-		/* #ifndef APP-NVUE */
-		height: 100%;
-		display: flex;
-		/* #endif */
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-grid-item__box {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		width: 100%;
-		/* #endif */
-		position: relative;
-		flex: 1;
-		flex-direction: column;
-		// justify-content: center;
-		// align-items: center;
-	}
-
-	.uni-grid-item--border {
-		position: relative;
-		/* #ifdef APP-NVUE */
-		border-bottom-color: #D2D2D2;
-		border-bottom-style: solid;
-		border-bottom-width: 0.5px;
-		border-right-color: #D2D2D2;
-		border-right-style: solid;
-		border-right-width: 0.5px;
-		/* #endif */
-		/* #ifndef APP-NVUE */
-		z-index: 0;
-		border-bottom: 1px #D2D2D2 solid;
-		border-right: 1px #D2D2D2 solid;
-		/* #endif */
-	}
-	.uni-grid-item--border-top {
-		position: relative;
-		/* #ifdef APP-NVUE */
-		border-top-color: #D2D2D2;
-		border-top-style: solid;
-		border-top-width: 0.5px;
-		/* #endif */
-		/* #ifndef APP-NVUE */
-		border-top: 1px #D2D2D2 solid;
-		z-index: 0;
-		/* #endif */
-	}
-
-
-	.uni-highlight:active {
-		background-color: #f1f1f1;
-	}
-</style>
+<template>
+	<view v-if="width" :style="'width:'+width+';'+(square?'height:'+width:'')" class="uni-grid-item">
+		<view :class="{ 'uni-grid-item--border': showBorder,  'uni-grid-item--border-top': showBorder && index < column, 'uni-highlight': highlight }"
+		 :style="{'border-right-color': borderColor ,'border-bottom-color': borderColor ,'border-top-color': borderColor }"
+		 class="uni-grid-item__box" @click="_onClick">
+			<slot />
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * GridItem 宫格
+	 * @description 宫格组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=27
+	 * @property {Number} index 子组件的唯一标识 ,点击gird会返回当前的标识
+	 */
+	export default {
+		name: 'UniGridItem',
+		inject: ['grid'],
+		props: {
+			index: {
+				type: Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				column: 0,
+				showBorder: true,
+				square: true,
+				highlight: true,
+				left: 0,
+				top: 0,
+				openNum: 2,
+				width: 0,
+				borderColor: '#e5e5e5'
+			}
+		},
+		created() {
+			this.column = this.grid.column
+			this.showBorder = this.grid.showBorder
+			this.square = this.grid.square
+			this.highlight = this.grid.highlight
+			this.top = this.hor === 0 ? this.grid.hor : this.hor
+			this.left = this.ver === 0 ? this.grid.ver : this.ver
+			this.borderColor = this.grid.borderColor
+			this.grid.children.push(this)
+			// this.grid.init()
+			this.width = this.grid.width
+		},
+		beforeDestroy() {
+			this.grid.children.forEach((item, index) => {
+				if (item === this) {
+					this.grid.children.splice(index, 1)
+				}
+			})
+		},
+		methods: {
+			_onClick() {
+				this.grid.change({
+					detail: {
+						index: this.index
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-grid-item {
+		/* #ifndef APP-NVUE */
+		height: 100%;
+		display: flex;
+		/* #endif */
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-grid-item__box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		width: 100%;
+		/* #endif */
+		position: relative;
+		flex: 1;
+		flex-direction: column;
+		// justify-content: center;
+		// align-items: center;
+	}
+
+	.uni-grid-item--border {
+		position: relative;
+		/* #ifdef APP-NVUE */
+		border-bottom-color: #D2D2D2;
+		border-bottom-style: solid;
+		border-bottom-width: 0.5px;
+		border-right-color: #D2D2D2;
+		border-right-style: solid;
+		border-right-width: 0.5px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		z-index: 0;
+		border-bottom: 1px #D2D2D2 solid;
+		border-right: 1px #D2D2D2 solid;
+		/* #endif */
+	}
+	.uni-grid-item--border-top {
+		position: relative;
+		/* #ifdef APP-NVUE */
+		border-top-color: #D2D2D2;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		border-top: 1px #D2D2D2 solid;
+		z-index: 0;
+		/* #endif */
+	}
+
+
+	.uni-highlight:active {
+		background-color: #f1f1f1;
+	}
+</style>

+ 142 - 142
uni_modules/uni-grid/components/uni-grid/uni-grid.vue

@@ -1,142 +1,142 @@
-<template>
-	<view class="uni-grid-wrap">
-		<view :id="elId" ref="uni-grid" class="uni-grid" :class="{ 'uni-grid--border': showBorder }" :style="{ 'border-left-color':borderColor}">
-			<slot />
-		</view>
-	</view>
-</template>
-
-<script>
-	// #ifdef APP-NVUE
-	const dom = uni.requireNativePlugin('dom');
-	// #endif
-
-	/**
-	 * Grid 宫格
-	 * @description 宫格组件
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=27
-	 * @property {Number} column 每列显示个数
-	 * @property {String} borderColor 边框颜色
-	 * @property {Boolean} showBorder 是否显示边框
-	 * @property {Boolean} square 是否方形显示
-	 * @property {Boolean} Boolean 点击背景是否高亮
-	 * @event {Function} change 点击 grid 触发,e={detail:{index:0}},index 为当前点击 gird 下标
-	 */
-	export default {
-		name: 'UniGrid',
-		emits:['change'],
-		props: {
-			// 每列显示个数
-			column: {
-				type: Number,
-				default: 3
-			},
-			// 是否显示边框
-			showBorder: {
-				type: Boolean,
-				default: true
-			},
-			// 边框颜色
-			borderColor: {
-				type: String,
-				default: '#D2D2D2'
-			},
-			// 是否正方形显示,默认为 true
-			square: {
-				type: Boolean,
-				default: true
-			},
-			highlight: {
-				type: Boolean,
-				default: true
-			}
-		},
-		provide() {
-			return {
-				grid: this
-			}
-		},
-		data() {
-			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
-			return {
-				elId,
-				width: 0
-			}
-		},
-		created() {
-			this.children = []
-		},
-		mounted() {
-			this.$nextTick(()=>{
-				this.init()
-			})
-		},
-		methods: {
-			init() {
-				setTimeout(() => {
-					this._getSize((width) => {
-						this.children.forEach((item, index) => {
-							item.width = width
-						})
-					})
-				}, 50)
-			},
-			change(e) {
-				this.$emit('change', e)
-			},
-			_getSize(fn) {
-				// #ifndef APP-NVUE
-				uni.createSelectorQuery()
-					.in(this)
-					.select(`#${this.elId}`)
-					.boundingClientRect()
-					.exec(ret => {
-						this.width = parseInt((ret[0].width - 1) / this.column) + 'px'
-						fn(this.width)
-					})
-				// #endif
-				// #ifdef APP-NVUE
-				dom.getComponentRect(this.$refs['uni-grid'], (ret) => {
-					this.width = parseInt((ret.size.width - 1) / this.column) + 'px'
-					fn(this.width)
-				})
-				// #endif
-			}
-		}
-	}
-</script>
-
-<style lang="scss" >
-	.uni-grid-wrap {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex: 1;
-		flex-direction: column;
-		/* #ifdef H5 */
-		width: 100%;
-		/* #endif */
-	}
-
-	.uni-grid {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		// flex: 1;
-		flex-direction: row;
-		flex-wrap: wrap;
-	}
-
-	.uni-grid--border {
-		position: relative;
-		/* #ifdef APP-NVUE */
-		border-left-color: #D2D2D2;
-		border-left-style: solid;
-		border-left-width: 0.5px;
-		/* #endif */
-		/* #ifndef APP-NVUE */
-		z-index: 1;
-		border-left: 1px #D2D2D2 solid;
-		/* #endif */
-	}
-</style>
+<template>
+	<view class="uni-grid-wrap">
+		<view :id="elId" ref="uni-grid" class="uni-grid" :class="{ 'uni-grid--border': showBorder }" :style="{ 'border-left-color':borderColor}">
+			<slot />
+		</view>
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = uni.requireNativePlugin('dom');
+	// #endif
+
+	/**
+	 * Grid 宫格
+	 * @description 宫格组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=27
+	 * @property {Number} column 每列显示个数
+	 * @property {String} borderColor 边框颜色
+	 * @property {Boolean} showBorder 是否显示边框
+	 * @property {Boolean} square 是否方形显示
+	 * @property {Boolean} Boolean 点击背景是否高亮
+	 * @event {Function} change 点击 grid 触发,e={detail:{index:0}},index 为当前点击 gird 下标
+	 */
+	export default {
+		name: 'UniGrid',
+		emits:['change'],
+		props: {
+			// 每列显示个数
+			column: {
+				type: Number,
+				default: 3
+			},
+			// 是否显示边框
+			showBorder: {
+				type: Boolean,
+				default: true
+			},
+			// 边框颜色
+			borderColor: {
+				type: String,
+				default: '#D2D2D2'
+			},
+			// 是否正方形显示,默认为 true
+			square: {
+				type: Boolean,
+				default: true
+			},
+			highlight: {
+				type: Boolean,
+				default: true
+			}
+		},
+		provide() {
+			return {
+				grid: this
+			}
+		},
+		data() {
+			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			return {
+				elId,
+				width: 0
+			}
+		},
+		created() {
+			this.children = []
+		},
+		mounted() {
+			this.$nextTick(()=>{
+				this.init()
+			})
+		},
+		methods: {
+			init() {
+				setTimeout(() => {
+					this._getSize((width) => {
+						this.children.forEach((item, index) => {
+							item.width = width
+						})
+					})
+				}, 50)
+			},
+			change(e) {
+				this.$emit('change', e)
+			},
+			_getSize(fn) {
+				// #ifndef APP-NVUE
+				uni.createSelectorQuery()
+					.in(this)
+					.select(`#${this.elId}`)
+					.boundingClientRect()
+					.exec(ret => {
+						this.width = parseInt((ret[0].width - 1) / this.column) + 'px'
+						fn(this.width)
+					})
+				// #endif
+				// #ifdef APP-NVUE
+				dom.getComponentRect(this.$refs['uni-grid'], (ret) => {
+					this.width = parseInt((ret.size.width - 1) / this.column) + 'px'
+					fn(this.width)
+				})
+				// #endif
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-grid-wrap {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: column;
+		/* #ifdef H5 */
+		width: 100%;
+		/* #endif */
+	}
+
+	.uni-grid {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		// flex: 1;
+		flex-direction: row;
+		flex-wrap: wrap;
+	}
+
+	.uni-grid--border {
+		position: relative;
+		/* #ifdef APP-NVUE */
+		border-left-color: #D2D2D2;
+		border-left-style: solid;
+		border-left-width: 0.5px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		z-index: 1;
+		border-left: 1px #D2D2D2 solid;
+		/* #endif */
+	}
+</style>

+ 130 - 130
uni_modules/uni-group/components/uni-group/uni-group.vue

@@ -1,134 +1,134 @@
-<template>
-	<view class="uni-group" :class="['uni-group--'+mode ,margin?'group-margin':'']" :style="{marginTop: `${top}px` }">
-		<slot name="title">
-			<view v-if="title" class="uni-group__title" :style="{'padding-left':border?'30px':'15px'}">
-				<text class="uni-group__title-text">{{ title }}</text>
-			</view>
-		</slot>
-		<view class="uni-group__content" :class="{'group-conent-padding':border}">
-			<slot />
-		</view>
-	</view>
-</template>
-
-<script>
-	/**
-	 * Group 分组
-	 * @description 表单字段分组
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3281
-	 * @property {String} title 主标题
-	 * @property {Number} top 分组间隔
-	 * @property {Number} mode 模式
-	 */
-	export default {
-		name: 'uniGroup',
-		emits:['click'],
-		props: {
-			title: {
-				type: String,
-				default: ''
-			},
-			top: {
-				type: [Number, String],
-				default: 10
-			},
-			mode: {
-				type: String,
-				default: 'default'
+<template>
+	<view class="uni-group" :class="['uni-group--'+mode ,margin?'group-margin':'']" :style="{marginTop: `${top}px` }">
+		<slot name="title">
+			<view v-if="title" class="uni-group__title" :style="{'padding-left':border?'30px':'15px'}">
+				<text class="uni-group__title-text">{{ title }}</text>
+			</view>
+		</slot>
+		<view class="uni-group__content" :class="{'group-conent-padding':border}">
+			<slot />
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Group 分组
+	 * @description 表单字段分组
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3281
+	 * @property {String} title 主标题
+	 * @property {Number} top 分组间隔
+	 * @property {Number} mode 模式
+	 */
+	export default {
+		name: 'uniGroup',
+		emits:['click'],
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			top: {
+				type: [Number, String],
+				default: 10
+			},
+			mode: {
+				type: String,
+				default: 'default'
 			},
 			},
 			stat:{
 			stat:{
 				type: Boolean,
 				type: Boolean,
 				default: false
 				default: false
-			}
-		},
-		data() {
-			return {
-				margin: false,
-				border: false
-			}
-		},
-		watch: {
-			title(newVal) {
-				if (uni.report && this.stat && newVal !== '') {
-					uni.report('title', newVal)
-				}
-			}
-		},
-		created() {
-			this.form = this.getForm()
-			if (this.form) {
-				this.margin = true
-				this.border = this.form.border
-			}
-		},
-		methods: {
-			/**
-			 * 获取父元素实例
-			 */
-			getForm() {
-				let parent = this.$parent;
-				let parentName = parent.$options.name;
-				while (parentName !== 'uniForms') {
-					parent = parent.$parent;
-					if (!parent) return false
-					parentName = parent.$options.name;
-				}
-				return parent;
-			},
-			onClick() {
-				this.$emit('click')
-			}
-		}
-	}
-</script>
-<style lang="scss" >
-	.uni-group {
-		background: #fff;
-		margin-top: 10px;
-		// border: 1px red solid;
-	}
-
-	.group-margin {
-		// margin: 0 -15px;
-	}
-
-	.uni-group__title {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-		align-items: center;
-		padding-left: 15px;
-		height: 40px;
-		background-color: #eee;
-		font-weight: normal;
-		color: #666;
-	}
-
-	.uni-group__content {
-		padding: 15px;
-		// padding-bottom: 5px;
-		// background-color: #FFF;
-	}
-
-	.group-conent-padding {
-		padding: 0 15px;
-	}
-
-	.uni-group__title-text {
-		font-size: 14px;
-		color: #666;
-	}
-
-	.distraction {
-		flex-direction: row;
-		align-items: center;
-	}
-
-	.uni-group--card {
-		margin: 10px;
-		border-radius: 5px;
-		overflow: hidden;
-		box-shadow: 0 0 5px 1px rgba($color: #000000, $alpha: 0.08);
-	}
-</style>
+			}
+		},
+		data() {
+			return {
+				margin: false,
+				border: false
+			}
+		},
+		watch: {
+			title(newVal) {
+				if (uni.report && this.stat && newVal !== '') {
+					uni.report('title', newVal)
+				}
+			}
+		},
+		created() {
+			this.form = this.getForm()
+			if (this.form) {
+				this.margin = true
+				this.border = this.form.border
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm() {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== 'uniForms') {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			onClick() {
+				this.$emit('click')
+			}
+		}
+	}
+</script>
+<style lang="scss" >
+	.uni-group {
+		background: #fff;
+		margin-top: 10px;
+		// border: 1px red solid;
+	}
+
+	.group-margin {
+		// margin: 0 -15px;
+	}
+
+	.uni-group__title {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		padding-left: 15px;
+		height: 40px;
+		background-color: #eee;
+		font-weight: normal;
+		color: #666;
+	}
+
+	.uni-group__content {
+		padding: 15px;
+		// padding-bottom: 5px;
+		// background-color: #FFF;
+	}
+
+	.group-conent-padding {
+		padding: 0 15px;
+	}
+
+	.uni-group__title-text {
+		font-size: 14px;
+		color: #666;
+	}
+
+	.distraction {
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.uni-group--card {
+		margin: 10px;
+		border-radius: 5px;
+		overflow: hidden;
+		box-shadow: 0 0 5px 1px rgba($color: #000000, $alpha: 0.08);
+	}
+</style>

+ 64 - 64
uni_modules/uni-icons/components/uni-icons/uni-icons.vue

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

+ 144 - 144
uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue

@@ -1,144 +1,144 @@
-<template>
-	<view>
-		<view v-if="loaded || list.itemIndex < 15" class="uni-indexed-list__title-wrapper">
-			<text v-if="list.items && list.items.length > 0" class="uni-indexed-list__title">{{ list.key }}</text>
-		</view>
-		<view v-if="(loaded || list.itemIndex < 15) && list.items && list.items.length > 0" class="uni-indexed-list__list">
-			<view v-for="(item, index) in list.items" :key="index" class="uni-indexed-list__item" hover-class="uni-indexed-list__item--hover">
-				<view class="uni-indexed-list__item-container" @click="onClick(idx, index)">
-					<view class="uni-indexed-list__item-border" :class="{'uni-indexed-list__item-border--last':index===list.items.length-1}">
-						<view v-if="showSelect" style="margin-right: 20rpx;">
-							<uni-icons :type="item.checked ? 'checkbox-filled' : 'circle'" :color="item.checked ? '#007aff' : '#C0C0C0'" size="24" />
-						</view>
-						<text class="uni-indexed-list__item-content">{{ item.name }}</text>
-					</view>
-				</view>
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		name: 'UniIndexedList',
-		emits:['itemClick'],
-		props: {
-			loaded: {
-				type: Boolean,
-				default: false
-			},
-			idx: {
-				type: Number,
-				default: 0
-			},
-			list: {
-				type: Object,
-				default () {
-					return {}
-				}
-			},
-			showSelect: {
-				type: Boolean,
-				default: false
-			}
-		},
-		methods: {
-			onClick(idx, index) {
-				this.$emit("itemClick", {
-					idx,
-					index
-				})
-			}
-		}
-	}
-</script>
-
-<style lang="scss" >
-	.uni-indexed-list__list {
-		background-color: $uni-bg-color;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: column;
-		border-top-style: solid;
-		border-top-width: 1px;
-		border-top-color: #DEDEDE;
-	}
-
-	.uni-indexed-list__item {
-		font-size: 14px;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex: 1;
-		flex-direction: row;
-		justify-content: space-between;
-		align-items: center;
-	}
-
-	.uni-indexed-list__item-container {
-		padding-left: 15px;
-		flex: 1;
-		position: relative;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		box-sizing: border-box;
-		/* #endif */
-		flex-direction: row;
-		justify-content: space-between;
-		align-items: center;
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-indexed-list__item-border {
-		flex: 1;
-		position: relative;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		box-sizing: border-box;
-		/* #endif */
-		flex-direction: row;
-		justify-content: space-between;
-		align-items: center;
-		height: 50px;
-		padding: 25px;
-		padding-left: 0;
-		border-bottom-style: solid;
-		border-bottom-width: 1px;
-		border-bottom-color:  #DEDEDE;
-	}
-
-	.uni-indexed-list__item-border--last {
-		border-bottom-width: 0px;
-	}
-
-	.uni-indexed-list__item-content {
-		flex: 1;
-		font-size: 14px;
-		color: #191919;
-	}
-
-	.uni-indexed-list {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-	}
-
-	.uni-indexed-list__title-wrapper {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		width: 100%;
-		/* #endif */
-		background-color: #f7f7f7;
-	}
-
-	.uni-indexed-list__title {
-		padding: 6px 12px;
-		line-height: 24px;
-		font-size: 16px;
-		font-weight: 500;
-	}
-</style>
+<template>
+	<view>
+		<view v-if="loaded || list.itemIndex < 15" class="uni-indexed-list__title-wrapper">
+			<text v-if="list.items && list.items.length > 0" class="uni-indexed-list__title">{{ list.key }}</text>
+		</view>
+		<view v-if="(loaded || list.itemIndex < 15) && list.items && list.items.length > 0" class="uni-indexed-list__list">
+			<view v-for="(item, index) in list.items" :key="index" class="uni-indexed-list__item" hover-class="uni-indexed-list__item--hover">
+				<view class="uni-indexed-list__item-container" @click="onClick(idx, index)">
+					<view class="uni-indexed-list__item-border" :class="{'uni-indexed-list__item-border--last':index===list.items.length-1}">
+						<view v-if="showSelect" style="margin-right: 20rpx;">
+							<uni-icons :type="item.checked ? 'checkbox-filled' : 'circle'" :color="item.checked ? '#007aff' : '#C0C0C0'" size="24" />
+						</view>
+						<text class="uni-indexed-list__item-content">{{ item.name }}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'UniIndexedList',
+		emits:['itemClick'],
+		props: {
+			loaded: {
+				type: Boolean,
+				default: false
+			},
+			idx: {
+				type: Number,
+				default: 0
+			},
+			list: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			showSelect: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods: {
+			onClick(idx, index) {
+				this.$emit("itemClick", {
+					idx,
+					index
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-indexed-list__list {
+		background-color: $uni-bg-color;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		border-top-style: solid;
+		border-top-width: 1px;
+		border-top-color: #DEDEDE;
+	}
+
+	.uni-indexed-list__item {
+		font-size: 14px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+	}
+
+	.uni-indexed-list__item-container {
+		padding-left: 15px;
+		flex: 1;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		box-sizing: border-box;
+		/* #endif */
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-indexed-list__item-border {
+		flex: 1;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		box-sizing: border-box;
+		/* #endif */
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+		height: 50px;
+		padding: 25px;
+		padding-left: 0;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+		border-bottom-color:  #DEDEDE;
+	}
+
+	.uni-indexed-list__item-border--last {
+		border-bottom-width: 0px;
+	}
+
+	.uni-indexed-list__item-content {
+		flex: 1;
+		font-size: 14px;
+		color: #191919;
+	}
+
+	.uni-indexed-list {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-indexed-list__title-wrapper {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		width: 100%;
+		/* #endif */
+		background-color: #f7f7f7;
+	}
+
+	.uni-indexed-list__title {
+		padding: 6px 12px;
+		line-height: 24px;
+		font-size: 16px;
+		font-weight: 500;
+	}
+</style>

+ 367 - 367
uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue

@@ -1,367 +1,367 @@
-<template>
-	<view class="uni-indexed-list" ref="list" id="list">
-		<!-- #ifdef APP-NVUE -->
-		<list class="uni-indexed-list__scroll" scrollable="true" show-scrollbar="false">
-			<cell v-for="(list, idx) in lists" :key="idx" :ref="'uni-indexed-list-' + idx">
-				<!-- #endif -->
-				<!-- #ifndef APP-NVUE -->
-				<scroll-view :scroll-into-view="scrollViewId" class="uni-indexed-list__scroll" scroll-y>
-					<view v-for="(list, idx) in lists" :key="idx" :id="'uni-indexed-list-' + idx">
-						<!-- #endif -->
-						<indexed-list-item :list="list" :loaded="loaded" :idx="idx" :showSelect="showSelect"
-							@itemClick="onClick"></indexed-list-item>
-						<!-- #ifndef APP-NVUE -->
-					</view>
-				</scroll-view>
-				<!-- #endif -->
-				<!-- #ifdef APP-NVUE -->
-			</cell>
-		</list>
-		<!-- #endif -->
-		<view class="uni-indexed-list__menu" @touchstart="touchStart" @touchmove.stop.prevent="touchMove"
-			@touchend="touchEnd" @mousedown.stop="mousedown" @mousemove.stop.prevent="mousemove"
-			@mouseleave.stop="mouseleave">
-			<view v-for="(list, key) in lists" :key="key" class="uni-indexed-list__menu-item"
-				:class="touchmoveIndex == key ? 'uni-indexed-list__menu--active' : ''">
-				<text class="uni-indexed-list__menu-text"
-					:class="touchmoveIndex == key ? 'uni-indexed-list__menu-text--active' : ''">{{ list.key }}</text>
-			</view>
-		</view>
-		<view v-if="touchmove" class="uni-indexed-list__alert-wrapper">
-			<text class="uni-indexed-list__alert">{{ lists[touchmoveIndex].key }}</text>
-		</view>
-	</view>
-</template>
-<script>
-	import indexedListItem from './uni-indexed-list-item.vue'
-	// #ifdef APP-NVUE
-	const dom = weex.requireModule('dom');
-	// #endif
-	// #ifdef APP-PLUS
-	function throttle(func, delay) {
-		var prev = Date.now();
-		return function() {
-			var context = this;
-			var args = arguments;
-			var now = Date.now();
-			if (now - prev >= delay) {
-				func.apply(context, args);
-				prev = Date.now();
-			}
-		}
-	}
-
-	function touchMove(e) {
-		let pageY = e.touches[0].pageY
-		let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
-		if (this.touchmoveIndex === index) {
-			return false
-		}
-		let item = this.lists[index]
-		if (item) {
-			// #ifndef APP-NVUE
-			this.scrollViewId = 'uni-indexed-list-' + index
-			this.touchmoveIndex = index
-			// #endif
-			// #ifdef APP-NVUE
-			dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
-				animated: false
-			})
-			this.touchmoveIndex = index
-			// #endif
-		}
-	}
-	const throttleTouchMove = throttle(touchMove, 40)
-	// #endif
-
-	/**
-	 * IndexedList 索引列表
-	 * @description 用于展示索引列表
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=375
-	 * @property {Boolean} showSelect = [true|false] 展示模式
-	 * 	@value true 展示模式
-	 * 	@value false 选择模式
-	 * @property {Object} options 索引列表需要的数据对象
-	 * @event {Function} click 点击列表事件 ,返回当前选择项的事件对象
-	 * @example <uni-indexed-list options="" showSelect="false" @click=""></uni-indexed-list>
-	 */
-	export default {
-		name: 'UniIndexedList',
-		components: {
-			indexedListItem
-		},
-		emits: ['click'],
-		props: {
-			options: {
-				type: Array,
-				default () {
-					return []
-				}
-			},
-			showSelect: {
-				type: Boolean,
-				default: false
-			}
-		},
-		data() {
-			return {
-				lists: [],
-				winHeight: 0,
-				itemHeight: 0,
-				winOffsetY: 0,
-				touchmove: false,
-				touchmoveIndex: -1,
-				scrollViewId: '',
-				touchmovable: true,
-				loaded: false,
-				isPC: false
-			}
-		},
-		watch: {
-			options: {
-				handler: function() {
-					this.setList()
-				},
-				deep: true
-			}
-		},
-		mounted() {
-			// #ifdef H5
-			this.isPC = this.IsPC()
-			// #endif
-			setTimeout(() => {
-				this.setList()
-			}, 50)
-			setTimeout(() => {
-				this.loaded = true
-			}, 300);
-		},
-		methods: {
-			setList() {
-				let index = 0;
-				this.lists = []
-				this.options.forEach((value) => {
-					if (value.data.length === 0) {
-						return
-					}
-					let indexBefore = index
-					let items = value.data.map(item => {
-						let obj = {}
-						obj['key'] = value.letter
-						obj['name'] = item
-						obj['itemIndex'] = index
-						index++
-						obj.checked = item.checked ? item.checked : false
-						return obj
-					})
-					this.lists.push({
-						title: value.letter,
-						key: value.letter,
-						items: items,
-						itemIndex: indexBefore
-					})
-				})
-				// #ifndef APP-NVUE
-				uni.createSelectorQuery()
-					.in(this)
-					.select('#list')
-					.boundingClientRect()
-					.exec(ret => {
-						this.winOffsetY = ret[0].top
-						this.winHeight = ret[0].height
-						this.itemHeight = this.winHeight / this.lists.length
-					})
-				// #endif
-				// #ifdef APP-NVUE
-				dom.getComponentRect(this.$refs['list'], (res) => {
-					this.winOffsetY = res.size.top
-					this.winHeight = res.size.height
-					this.itemHeight = this.winHeight / this.lists.length
-				})
-				// #endif
-			},
-			touchStart(e) {
-				this.touchmove = true
-				let pageY = this.isPC ? e.pageY : e.touches[0].pageY
-				let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
-				let item = this.lists[index]
-				if (item) {
-					this.scrollViewId = 'uni-indexed-list-' + index
-					this.touchmoveIndex = index
-					// #ifdef APP-NVUE
-					dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
-						animated: false
-					})
-					// #endif
-				}
-			},
-			touchMove(e) {
-				// #ifndef APP-PLUS
-				let pageY = this.isPC ? e.pageY : e.touches[0].pageY
-				let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
-				if (this.touchmoveIndex === index) {
-					return false
-				}
-				let item = this.lists[index]
-				if (item) {
-					this.scrollViewId = 'uni-indexed-list-' + index
-					this.touchmoveIndex = index
-				}
-				// #endif
-				// #ifdef APP-PLUS
-				throttleTouchMove.call(this, e)
-				// #endif
-			},
-			touchEnd() {
-				this.touchmove = false
-				// this.touchmoveIndex = -1
-			},
-
-			/**
-			 * 兼容 PC @tian
-			 */
-
-			mousedown(e) {
-				if (!this.isPC) return
-				this.touchStart(e)
-			},
-			mousemove(e) {
-				if (!this.isPC) return
-				this.touchMove(e)
-			},
-			mouseleave(e) {
-				if (!this.isPC) return
-				this.touchEnd(e)
-			},
-
-			// #ifdef H5
-			IsPC() {
-				var userAgentInfo = navigator.userAgent;
-				var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
-				var flag = true;
-				for (let v = 0; v < Agents.length - 1; v++) {
-					if (userAgentInfo.indexOf(Agents[v]) > 0) {
-						flag = false;
-						break;
-					}
-				}
-				return flag;
-			},
-			// #endif
-
-
-			onClick(e) {
-				let {
-					idx,
-					index
-				} = e
-				let obj = {}
-				for (let key in this.lists[idx].items[index]) {
-					obj[key] = this.lists[idx].items[index][key]
-				}
-				let select = []
-				if (this.showSelect) {
-					this.lists[idx].items[index].checked = !this.lists[idx].items[index].checked
-					this.lists.forEach((value, idx) => {
-						value.items.forEach((item, index) => {
-							if (item.checked) {
-								let obj = {}
-								for (let key in this.lists[idx].items[index]) {
-									obj[key] = this.lists[idx].items[index][key]
-								}
-								select.push(obj)
-							}
-						})
-					})
-				}
-				this.$emit('click', {
-					item: obj,
-					select: select
-				})
-			}
-		}
-	}
-</script>
-<style lang="scss" >
-	.uni-indexed-list {
-		position: absolute;
-		left: 0;
-		top: 0;
-		right: 0;
-		bottom: 0;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-	}
-
-	.uni-indexed-list__scroll {
-		flex: 1;
-	}
-
-	.uni-indexed-list__menu {
-		width: 24px;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: column;
-	}
-
-	.uni-indexed-list__menu-item {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex: 1;
-		align-items: center;
-		justify-content: center;
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-indexed-list__menu-text {
-		font-size: 12px;
-		text-align: center;
-		color: #aaa;
-	}
-
-	.uni-indexed-list__menu--active {
-		// background-color: rgb(200, 200, 200);
-	}
-
-	.uni-indexed-list__menu--active {}
-
-	.uni-indexed-list__menu-text--active {
-		border-radius: 16px;
-		width: 16px;
-		height: 16px;
-		line-height: 16px;
-		background-color: #007aff;
-		color: #fff;
-	}
-
-	.uni-indexed-list__alert-wrapper {
-		position: absolute;
-		left: 0;
-		top: 0;
-		right: 0;
-		bottom: 0;
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-		align-items: center;
-		justify-content: center;
-	}
-
-	.uni-indexed-list__alert {
-		width: 80px;
-		height: 80px;
-		border-radius: 80px;
-		text-align: center;
-		line-height: 80px;
-		font-size: 35px;
-		color: #fff;
-		background-color: rgba(0, 0, 0, 0.5);
-	}
-</style>
+<template>
+	<view class="uni-indexed-list" ref="list" id="list">
+		<!-- #ifdef APP-NVUE -->
+		<list class="uni-indexed-list__scroll" scrollable="true" show-scrollbar="false">
+			<cell v-for="(list, idx) in lists" :key="idx" :ref="'uni-indexed-list-' + idx">
+				<!-- #endif -->
+				<!-- #ifndef APP-NVUE -->
+				<scroll-view :scroll-into-view="scrollViewId" class="uni-indexed-list__scroll" scroll-y>
+					<view v-for="(list, idx) in lists" :key="idx" :id="'uni-indexed-list-' + idx">
+						<!-- #endif -->
+						<indexed-list-item :list="list" :loaded="loaded" :idx="idx" :showSelect="showSelect"
+							@itemClick="onClick"></indexed-list-item>
+						<!-- #ifndef APP-NVUE -->
+					</view>
+				</scroll-view>
+				<!-- #endif -->
+				<!-- #ifdef APP-NVUE -->
+			</cell>
+		</list>
+		<!-- #endif -->
+		<view class="uni-indexed-list__menu" @touchstart="touchStart" @touchmove.stop.prevent="touchMove"
+			@touchend="touchEnd" @mousedown.stop="mousedown" @mousemove.stop.prevent="mousemove"
+			@mouseleave.stop="mouseleave">
+			<view v-for="(list, key) in lists" :key="key" class="uni-indexed-list__menu-item"
+				:class="touchmoveIndex == key ? 'uni-indexed-list__menu--active' : ''">
+				<text class="uni-indexed-list__menu-text"
+					:class="touchmoveIndex == key ? 'uni-indexed-list__menu-text--active' : ''">{{ list.key }}</text>
+			</view>
+		</view>
+		<view v-if="touchmove" class="uni-indexed-list__alert-wrapper">
+			<text class="uni-indexed-list__alert">{{ lists[touchmoveIndex].key }}</text>
+		</view>
+	</view>
+</template>
+<script>
+	import indexedListItem from './uni-indexed-list-item.vue'
+	// #ifdef APP-NVUE
+	const dom = weex.requireModule('dom');
+	// #endif
+	// #ifdef APP-PLUS
+	function throttle(func, delay) {
+		var prev = Date.now();
+		return function() {
+			var context = this;
+			var args = arguments;
+			var now = Date.now();
+			if (now - prev >= delay) {
+				func.apply(context, args);
+				prev = Date.now();
+			}
+		}
+	}
+
+	function touchMove(e) {
+		let pageY = e.touches[0].pageY
+		let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
+		if (this.touchmoveIndex === index) {
+			return false
+		}
+		let item = this.lists[index]
+		if (item) {
+			// #ifndef APP-NVUE
+			this.scrollViewId = 'uni-indexed-list-' + index
+			this.touchmoveIndex = index
+			// #endif
+			// #ifdef APP-NVUE
+			dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
+				animated: false
+			})
+			this.touchmoveIndex = index
+			// #endif
+		}
+	}
+	const throttleTouchMove = throttle(touchMove, 40)
+	// #endif
+
+	/**
+	 * IndexedList 索引列表
+	 * @description 用于展示索引列表
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=375
+	 * @property {Boolean} showSelect = [true|false] 展示模式
+	 * 	@value true 展示模式
+	 * 	@value false 选择模式
+	 * @property {Object} options 索引列表需要的数据对象
+	 * @event {Function} click 点击列表事件 ,返回当前选择项的事件对象
+	 * @example <uni-indexed-list options="" showSelect="false" @click=""></uni-indexed-list>
+	 */
+	export default {
+		name: 'UniIndexedList',
+		components: {
+			indexedListItem
+		},
+		emits: ['click'],
+		props: {
+			options: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			showSelect: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				lists: [],
+				winHeight: 0,
+				itemHeight: 0,
+				winOffsetY: 0,
+				touchmove: false,
+				touchmoveIndex: -1,
+				scrollViewId: '',
+				touchmovable: true,
+				loaded: false,
+				isPC: false
+			}
+		},
+		watch: {
+			options: {
+				handler: function() {
+					this.setList()
+				},
+				deep: true
+			}
+		},
+		mounted() {
+			// #ifdef H5
+			this.isPC = this.IsPC()
+			// #endif
+			setTimeout(() => {
+				this.setList()
+			}, 50)
+			setTimeout(() => {
+				this.loaded = true
+			}, 300);
+		},
+		methods: {
+			setList() {
+				let index = 0;
+				this.lists = []
+				this.options.forEach((value) => {
+					if (value.data.length === 0) {
+						return
+					}
+					let indexBefore = index
+					let items = value.data.map(item => {
+						let obj = {}
+						obj['key'] = value.letter
+						obj['name'] = item
+						obj['itemIndex'] = index
+						index++
+						obj.checked = item.checked ? item.checked : false
+						return obj
+					})
+					this.lists.push({
+						title: value.letter,
+						key: value.letter,
+						items: items,
+						itemIndex: indexBefore
+					})
+				})
+				// #ifndef APP-NVUE
+				uni.createSelectorQuery()
+					.in(this)
+					.select('#list')
+					.boundingClientRect()
+					.exec(ret => {
+						this.winOffsetY = ret[0].top
+						this.winHeight = ret[0].height
+						this.itemHeight = this.winHeight / this.lists.length
+					})
+				// #endif
+				// #ifdef APP-NVUE
+				dom.getComponentRect(this.$refs['list'], (res) => {
+					this.winOffsetY = res.size.top
+					this.winHeight = res.size.height
+					this.itemHeight = this.winHeight / this.lists.length
+				})
+				// #endif
+			},
+			touchStart(e) {
+				this.touchmove = true
+				let pageY = this.isPC ? e.pageY : e.touches[0].pageY
+				let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
+				let item = this.lists[index]
+				if (item) {
+					this.scrollViewId = 'uni-indexed-list-' + index
+					this.touchmoveIndex = index
+					// #ifdef APP-NVUE
+					dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
+						animated: false
+					})
+					// #endif
+				}
+			},
+			touchMove(e) {
+				// #ifndef APP-PLUS
+				let pageY = this.isPC ? e.pageY : e.touches[0].pageY
+				let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
+				if (this.touchmoveIndex === index) {
+					return false
+				}
+				let item = this.lists[index]
+				if (item) {
+					this.scrollViewId = 'uni-indexed-list-' + index
+					this.touchmoveIndex = index
+				}
+				// #endif
+				// #ifdef APP-PLUS
+				throttleTouchMove.call(this, e)
+				// #endif
+			},
+			touchEnd() {
+				this.touchmove = false
+				// this.touchmoveIndex = -1
+			},
+
+			/**
+			 * 兼容 PC @tian
+			 */
+
+			mousedown(e) {
+				if (!this.isPC) return
+				this.touchStart(e)
+			},
+			mousemove(e) {
+				if (!this.isPC) return
+				this.touchMove(e)
+			},
+			mouseleave(e) {
+				if (!this.isPC) return
+				this.touchEnd(e)
+			},
+
+			// #ifdef H5
+			IsPC() {
+				var userAgentInfo = navigator.userAgent;
+				var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+				var flag = true;
+				for (let v = 0; v < Agents.length - 1; v++) {
+					if (userAgentInfo.indexOf(Agents[v]) > 0) {
+						flag = false;
+						break;
+					}
+				}
+				return flag;
+			},
+			// #endif
+
+
+			onClick(e) {
+				let {
+					idx,
+					index
+				} = e
+				let obj = {}
+				for (let key in this.lists[idx].items[index]) {
+					obj[key] = this.lists[idx].items[index][key]
+				}
+				let select = []
+				if (this.showSelect) {
+					this.lists[idx].items[index].checked = !this.lists[idx].items[index].checked
+					this.lists.forEach((value, idx) => {
+						value.items.forEach((item, index) => {
+							if (item.checked) {
+								let obj = {}
+								for (let key in this.lists[idx].items[index]) {
+									obj[key] = this.lists[idx].items[index][key]
+								}
+								select.push(obj)
+							}
+						})
+					})
+				}
+				this.$emit('click', {
+					item: obj,
+					select: select
+				})
+			}
+		}
+	}
+</script>
+<style lang="scss" >
+	.uni-indexed-list {
+		position: absolute;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-indexed-list__scroll {
+		flex: 1;
+	}
+
+	.uni-indexed-list__menu {
+		width: 24px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-indexed-list__menu-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		align-items: center;
+		justify-content: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-indexed-list__menu-text {
+		font-size: 12px;
+		text-align: center;
+		color: #aaa;
+	}
+
+	.uni-indexed-list__menu--active {
+		// background-color: rgb(200, 200, 200);
+	}
+
+	.uni-indexed-list__menu--active {}
+
+	.uni-indexed-list__menu-text--active {
+		border-radius: 16px;
+		width: 16px;
+		height: 16px;
+		line-height: 16px;
+		background-color: #007aff;
+		color: #fff;
+	}
+
+	.uni-indexed-list__alert-wrapper {
+		position: absolute;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-indexed-list__alert {
+		width: 80px;
+		height: 80px;
+		border-radius: 80px;
+		text-align: center;
+		line-height: 80px;
+		font-size: 35px;
+		color: #fff;
+		background-color: rgba(0, 0, 0, 0.5);
+	}
+</style>

+ 107 - 107
uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue

@@ -1,107 +1,107 @@
-<template>
-	<!-- #ifdef APP-NVUE -->
-	<cell>
-		<!-- #endif -->
-		<view class="uni-list-ad">
-			<view v-if="borderShow" :class="{'uni-list--border':border,'uni-list-item--first':isFirstChild}"></view>
-			<ad style="width: 200px;height: 300px;border-width: 1px;border-color: red;border-style: solid;" adpid="1111111111"
-			 unit-id="" appid="" apid="" type="feed" @error="aderror" @close="closeAd"></ad>
-		</view>
-		<!-- #ifdef APP-NVUE -->
-	</cell>
-	<!-- #endif -->
-
-</template>
-
-<script>
-	// #ifdef APP-NVUE
-	const dom = uni.requireNativePlugin('dom');
-	// #endif
-	export default {
-		name: 'UniListAd',
-		props: {
-			title: {
-				type: String,
-				default: '',
-
-			}
-		},
-		// inject: ['list'],
-		data() {
-			return {
-				isFirstChild: false,
-				border: false,
-				borderShow: true,
-			}
-		},
-
-		mounted() {
-			this.list = this.getForm()
-			if (this.list) {
-				if (!this.list.firstChildAppend) {
-					this.list.firstChildAppend = true
-					this.isFirstChild = true
-				}
-				this.border = this.list.border
-			}
-		},
-		methods: {
-			/**
-			 * 获取父元素实例
-			 */
-			getForm(name = 'uniList') {
-				let parent = this.$parent;
-				let parentName = parent.$options.name;
-				while (parentName !== name) {
-					parent = parent.$parent;
-					if (!parent) return false
-					parentName = parent.$options.name;
-				}
-				return parent;
-			},
-			aderror(e) {
-				console.log("aderror: " + JSON.stringify(e.detail));
-			},
-			closeAd(e) {
-				this.borderShow = false
-			}
-		}
-	}
-</script>
-
-<style lang="scss" >
-	.uni-list-ad {
-		position: relative;
-		border: 1px red solid;
-	}
-
-	.uni-list--border {
-		position: relative;
-		padding-bottom: 1px;
-		/* #ifdef APP-PLUS */
-		border-top-color: $uni-border-color;
-		border-top-style: solid;
-		border-top-width: 0.5px;
-		/* #endif */
-		margin-left: $uni-spacing-row-lg;
-	}
-
-	/* #ifndef APP-NVUE */
-	.uni-list--border:after {
-		position: absolute;
-		top: 0;
-		right: 0;
-		left: 0;
-		height: 1px;
-		content: '';
-		-webkit-transform: scaleY(.5);
-		transform: scaleY(.5);
-		background-color: $uni-border-color;
-	}
-
-	.uni-list-item--first:after {
-		height: 0px;
-	}
-
-	/* #endif */
-</style>
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell>
+		<!-- #endif -->
+		<view class="uni-list-ad">
+			<view v-if="borderShow" :class="{'uni-list--border':border,'uni-list-item--first':isFirstChild}"></view>
+			<ad style="width: 200px;height: 300px;border-width: 1px;border-color: red;border-style: solid;" adpid="1111111111"
+			 unit-id="" appid="" apid="" type="feed" @error="aderror" @close="closeAd"></ad>
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = uni.requireNativePlugin('dom');
+	// #endif
+	export default {
+		name: 'UniListAd',
+		props: {
+			title: {
+				type: String,
+				default: '',
+
+			}
+		},
+		// inject: ['list'],
+		data() {
+			return {
+				isFirstChild: false,
+				border: false,
+				borderShow: true,
+			}
+		},
+
+		mounted() {
+			this.list = this.getForm()
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true
+					this.isFirstChild = true
+				}
+				this.border = this.list.border
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			aderror(e) {
+				console.log("aderror: " + JSON.stringify(e.detail));
+			},
+			closeAd(e) {
+				this.borderShow = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-list-ad {
+		position: relative;
+		border: 1px red solid;
+	}
+
+	.uni-list--border {
+		position: relative;
+		padding-bottom: 1px;
+		/* #ifdef APP-PLUS */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+		margin-left: $uni-spacing-row-lg;
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(.5);
+		transform: scaleY(.5);
+		background-color: $uni-border-color;
+	}
+
+	.uni-list-item--first:after {
+		height: 0px;
+	}
+
+	/* #endif */
+</style>

+ 4 - 4
uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss

@@ -14,8 +14,8 @@ $divide-line-color : #e5e5e5;
 $avatar-width : 45px ;
 $avatar-width : 45px ;
 
 
 // 头像边框
 // 头像边框
-$avatar-border-radius: 5px;
-$avatar-border-color: #eee;
+$avatar-border-radius: 5px;
+$avatar-border-color: #eee;
 $avatar-border-width: 1px;
 $avatar-border-width: 1px;
 
 
 // 标题文字样式
 // 标题文字样式
@@ -36,11 +36,11 @@ $right-text-weight : normal;
 // 角标样式
 // 角标样式
 // nvue 页面不支持修改圆点位置以及大小
 // nvue 页面不支持修改圆点位置以及大小
 // 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动
 // 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动
-$badge-left: 0px;
+$badge-left: 0px;
 $badge-top: 0px;
 $badge-top: 0px;
 
 
 // 显示圆点时,圆点大小
 // 显示圆点时,圆点大小
-$dot-width: 10px;
+$dot-width: 10px;
 $dot-height: 10px;
 $dot-height: 10px;
 
 
 // 显示角标时,角标大小和字体大小
 // 显示角标时,角标大小和字体大小

File diff suppressed because it is too large
+ 538 - 538
uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue


+ 108 - 108
uni_modules/uni-list/components/uni-list/uni-list.vue

@@ -1,108 +1,108 @@
-<template>
-	<!-- #ifndef APP-NVUE -->
-	<view class="uni-list uni-border-top-bottom">
-		<view v-if="border" class="uni-list--border-top"></view>
-		<slot />
-		<view v-if="border" class="uni-list--border-bottom"></view>
-	</view>
-	<!-- #endif -->
-	<!-- #ifdef APP-NVUE -->
-	<list class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop" loadmoreoffset="15"><slot /></list>
-	<!-- #endif -->
-</template>
-
-<script>
-/**
- * List 列表
- * @description 列表组件
- * @tutorial https://ext.dcloud.net.cn/plugin?id=24
- * @property {String} 	border = [true|false] 		标题
- */
-export default {
-	name: 'uniList',
-	'mp-weixin': {
-		options: {
-			multipleSlots: false
-		}
-	},
-	props: {
-		enableBackToTop: {
-			type: [Boolean, String],
-			default: false
-		},
-		scrollY: {
-			type: [Boolean, String],
-			default: false
-		},
-		border: {
-			type: Boolean,
-			default: true
-		}
-	},
-	// provide() {
-	// 	return {
-	// 		list: this
-	// 	};
-	// },
-	created() {
-		this.firstChildAppend = false;
-	},
-	methods: {
-		loadMore(e) {
-			this.$emit('scrolltolower');
-		}
-	}
-};
-</script>
-<style lang="scss" >
-$uni-bg-color:#ffffff;
-$uni-border-color:#e5e5e5;
-.uni-list {
-	/* #ifndef APP-NVUE */
-	display: flex;
-	/* #endif */
-	background-color: $uni-bg-color;
-	position: relative;
-	flex-direction: column;
-}
-
-.uni-list--border {
-	position: relative;
-	/* #ifdef APP-NVUE */
-	border-top-color: $uni-border-color;
-	border-top-style: solid;
-	border-top-width: 0.5px;
-	border-bottom-color: $uni-border-color;
-	border-bottom-style: solid;
-	border-bottom-width: 0.5px;
-	/* #endif */
-	z-index: -1;
-}
-
-/* #ifndef APP-NVUE */
-
-.uni-list--border-top {
-	position: absolute;
-	top: 0;
-	right: 0;
-	left: 0;
-	height: 1px;
-	-webkit-transform: scaleY(0.5);
-	transform: scaleY(0.5);
-	background-color: $uni-border-color;
-	z-index: 1;
-}
-
-.uni-list--border-bottom {
-	position: absolute;
-	bottom: 0;
-	right: 0;
-	left: 0;
-	height: 1px;
-	-webkit-transform: scaleY(0.5);
-	transform: scaleY(0.5);
-	background-color: $uni-border-color;
-}
-
-/* #endif */
-</style>
+<template>
+	<!-- #ifndef APP-NVUE -->
+	<view class="uni-list uni-border-top-bottom">
+		<view v-if="border" class="uni-list--border-top"></view>
+		<slot />
+		<view v-if="border" class="uni-list--border-bottom"></view>
+	</view>
+	<!-- #endif -->
+	<!-- #ifdef APP-NVUE -->
+	<list class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop" loadmoreoffset="15"><slot /></list>
+	<!-- #endif -->
+</template>
+
+<script>
+/**
+ * List 列表
+ * @description 列表组件
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+ * @property {String} 	border = [true|false] 		标题
+ */
+export default {
+	name: 'uniList',
+	'mp-weixin': {
+		options: {
+			multipleSlots: false
+		}
+	},
+	props: {
+		enableBackToTop: {
+			type: [Boolean, String],
+			default: false
+		},
+		scrollY: {
+			type: [Boolean, String],
+			default: false
+		},
+		border: {
+			type: Boolean,
+			default: true
+		}
+	},
+	// provide() {
+	// 	return {
+	// 		list: this
+	// 	};
+	// },
+	created() {
+		this.firstChildAppend = false;
+	},
+	methods: {
+		loadMore(e) {
+			this.$emit('scrolltolower');
+		}
+	}
+};
+</script>
+<style lang="scss" >
+$uni-bg-color:#ffffff;
+$uni-border-color:#e5e5e5;
+.uni-list {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	background-color: $uni-bg-color;
+	position: relative;
+	flex-direction: column;
+}
+
+.uni-list--border {
+	position: relative;
+	/* #ifdef APP-NVUE */
+	border-top-color: $uni-border-color;
+	border-top-style: solid;
+	border-top-width: 0.5px;
+	border-bottom-color: $uni-border-color;
+	border-bottom-style: solid;
+	border-bottom-width: 0.5px;
+	/* #endif */
+	z-index: -1;
+}
+
+/* #ifndef APP-NVUE */
+
+.uni-list--border-top {
+	position: absolute;
+	top: 0;
+	right: 0;
+	left: 0;
+	height: 1px;
+	-webkit-transform: scaleY(0.5);
+	transform: scaleY(0.5);
+	background-color: $uni-border-color;
+	z-index: 1;
+}
+
+.uni-list--border-bottom {
+	position: absolute;
+	bottom: 0;
+	right: 0;
+	left: 0;
+	height: 1px;
+	-webkit-transform: scaleY(0.5);
+	transform: scaleY(0.5);
+	background-color: $uni-border-color;
+}
+
+/* #endif */
+</style>

+ 1 - 1
uni_modules/uni-load-more/components/uni-load-more/i18n/en.json

@@ -1,4 +1,4 @@
-{
+{
 	"uni-load-more.contentdown": "Pull up to show more",
 	"uni-load-more.contentdown": "Pull up to show more",
 	"uni-load-more.contentrefresh": "loading...",
 	"uni-load-more.contentrefresh": "loading...",
 	"uni-load-more.contentnomore": "No more data"
 	"uni-load-more.contentnomore": "No more data"

+ 7 - 7
uni_modules/uni-load-more/components/uni-load-more/i18n/index.js

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

+ 1 - 1
uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json

@@ -1,4 +1,4 @@
-{
+{
 	"uni-load-more.contentdown": "上拉显示更多",
 	"uni-load-more.contentdown": "上拉显示更多",
 	"uni-load-more.contentrefresh": "正在加载...",
 	"uni-load-more.contentrefresh": "正在加载...",
 	"uni-load-more.contentnomore": "没有更多数据了"
 	"uni-load-more.contentnomore": "没有更多数据了"

+ 1 - 1
uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json

@@ -1,4 +1,4 @@
-{
+{
 	"uni-load-more.contentdown": "上拉顯示更多",
 	"uni-load-more.contentdown": "上拉顯示更多",
 	"uni-load-more.contentrefresh": "正在加載...",
 	"uni-load-more.contentrefresh": "正在加載...",
 	"uni-load-more.contentnomore": "沒有更多數據了"
 	"uni-load-more.contentnomore": "沒有更多數據了"

File diff suppressed because it is too large
+ 392 - 392
uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue


+ 356 - 356
uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue

@@ -1,357 +1,357 @@
-<template>
-	<view class="uni-navbar" :class="{'uni-dark':dark, 'uni-nvue-fixed': fixed}">
-		<view class="uni-navbar__content" :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }"
-			:style="{ 'background-color': themeBgColor }" >
-			<status-bar v-if="statusBar" />
-			<view :style="{ color: themeColor,backgroundColor: themeBgColor ,height:navbarHeight}"
-				class="uni-navbar__header">
-				<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left"
-					:style="{width:leftIconWidth}">
-					<slot name="left">
-						<view class="uni-navbar__content_view" v-if="leftIcon.length > 0">
-							<uni-icons :color="themeColor" :type="leftIcon" size="20" />
-						</view>
-						<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length > 0 }" class="uni-navbar-btn-text"
-							v-if="leftText.length">
-							<text :style="{ color: themeColor, fontSize: '12px' }">{{ leftText }}</text>
-						</view>
-					</slot>
-				</view>
-				<view class="uni-navbar__header-container " @tap="onClickTitle">
-					<slot>
-						<view class="uni-navbar__header-container-inner" v-if="title.length>0">
-							<text class="uni-nav-bar-text uni-ellipsis-1"
-								:style="{color: themeColor }">{{ title }}</text>
-						</view>
-					</slot>
-				</view>
-				<view @click="onClickRight" class="uni-navbar__header-btns uni-navbar__header-btns-right"
-					:style="{width:rightIconWidth}">
-					<slot name="right">
-						<view v-if="rightIcon.length">
-							<uni-icons :color="themeColor" :type="rightIcon" size="22" />
-						</view>
-						<view class="uni-navbar-btn-text" v-if="rightText.length && !rightIcon.length">
-							<text class="uni-nav-bar-right-text" :style="{ color: themeColor}">{{ rightText }}</text>
-						</view>
-					</slot>
-				</view>
-			</view>
+<template>
+	<view class="uni-navbar" :class="{'uni-dark':dark, 'uni-nvue-fixed': fixed}">
+		<view class="uni-navbar__content" :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }"
+			:style="{ 'background-color': themeBgColor }" >
+			<status-bar v-if="statusBar" />
+			<view :style="{ color: themeColor,backgroundColor: themeBgColor ,height:navbarHeight}"
+				class="uni-navbar__header">
+				<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left"
+					:style="{width:leftIconWidth}">
+					<slot name="left">
+						<view class="uni-navbar__content_view" v-if="leftIcon.length > 0">
+							<uni-icons :color="themeColor" :type="leftIcon" size="20" />
+						</view>
+						<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length > 0 }" class="uni-navbar-btn-text"
+							v-if="leftText.length">
+							<text :style="{ color: themeColor, fontSize: '12px' }">{{ leftText }}</text>
+						</view>
+					</slot>
+				</view>
+				<view class="uni-navbar__header-container " @tap="onClickTitle">
+					<slot>
+						<view class="uni-navbar__header-container-inner" v-if="title.length>0">
+							<text class="uni-nav-bar-text uni-ellipsis-1"
+								:style="{color: themeColor }">{{ title }}</text>
+						</view>
+					</slot>
+				</view>
+				<view @click="onClickRight" class="uni-navbar__header-btns uni-navbar__header-btns-right"
+					:style="{width:rightIconWidth}">
+					<slot name="right">
+						<view v-if="rightIcon.length">
+							<uni-icons :color="themeColor" :type="rightIcon" size="22" />
+						</view>
+						<view class="uni-navbar-btn-text" v-if="rightText.length && !rightIcon.length">
+							<text class="uni-nav-bar-right-text" :style="{ color: themeColor}">{{ rightText }}</text>
+						</view>
+					</slot>
+				</view>
+			</view>
 		</view>
 		</view>
-		<!-- #ifndef APP-NVUE -->
-		<view class="uni-navbar__placeholder" v-if="fixed">
-			<status-bar v-if="statusBar" />
-			<view class="uni-navbar__placeholder-view" :style="{ height:navbarHeight}" />
-		</view>
-		<!-- #endif -->
-	</view>
-</template>
-
-<script>
-	import statusBar from "./uni-status-bar.vue";
-	const getVal = (val) => typeof val === 'number' ? val + 'px' : val;
-
-	/**
-	 * 
-	 * 
-	 * NavBar 自定义导航栏
-	 * @description 导航栏组件,主要用于头部导航
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=52
-	 * @property {Boolean} dark 开启黑暗模式
-	 * @property {String} title 标题文字
-	 * @property {String} leftText 左侧按钮文本
-	 * @property {String} rightText 右侧按钮文本
-	 * @property {String} leftIcon 左侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
-	 * @property {String} rightIcon 右侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
-	 * @property {String} color 图标和文字颜色
-	 * @property {String} backgroundColor 导航栏背景颜色
-	 * @property {Boolean} fixed = [true|false] 是否固定顶部
-	 * @property {Boolean} statusBar = [true|false] 是否包含状态栏
-	 * @property {Boolean} shadow = [true|false] 导航栏下是否有阴影
-	 * @property {Boolean} stat 是否开启统计标题上报
-	 * @event {Function} clickLeft 左侧按钮点击时触发
-	 * @event {Function} clickRight 右侧按钮点击时触发
-	 * @event {Function} clickTitle 中间标题点击时触发
-	 */
-	export default {
-		name: "UniNavBar",
-		components: {
-			statusBar
-		},
-		emits: ['clickLeft', 'clickRight', 'clickTitle'],
-		props: {
-			dark: {
-				type: Boolean,
-				default: false
-			},
-			title: {
-				type: String,
-				default: ""
-			},
-			leftText: {
-				type: String,
-				default: ""
-			},
-			rightText: {
-				type: String,
-				default: ""
-			},
-			leftIcon: {
-				type: String,
-				default: ""
-			},
-			rightIcon: {
-				type: String,
-				default: ""
-			},
-			fixed: {
-				type: [Boolean, String],
-				default: false
-			},
-			color: {
-				type: String,
-				default: ""
-			},
-			backgroundColor: {
-				type: String,
-				default: ""
-			},
-			statusBar: {
-				type: [Boolean, String],
-				default: false
-			},
-			shadow: {
-				type: [Boolean, String],
-				default: false
-			},
-			border: {
-				type: [Boolean, String],
-				default: true
-			},
-			height: {
-				type: [Number, String],
-				default: 44
-			},
-			leftWidth: {
-				type: [Number, String],
-				default: 60
-			},
-			rightWidth: {
-				type: [Number, String],
-				default: 60
-			},
-			stat: {
-				type: [Boolean, String],
-				default: ''
-			}
-		},
-		computed: {
-			themeBgColor() {
-				if (this.dark) {
-					// 默认值
-					if (this.backgroundColor) {
-						return this.backgroundColor
-					} else {
-						return this.dark ? '#333' : '#FFF'
-					}
-				}
-				return this.backgroundColor || '#FFF'
-			},
-			themeColor() {
-				if (this.dark) {
-					// 默认值
-					if (this.color) {
-						return this.color
-					} else {
-						return this.dark ? '#fff' : '#333'
-					}
-				}
-				return this.color || '#333'
-			},
-			navbarHeight() {
-				return getVal(this.height)
-			},
-			leftIconWidth() {
-				return getVal(this.leftWidth)
-			},
-			rightIconWidth() {
-				return getVal(this.rightWidth)
-			}
-		},
-		mounted() {
-			if (uni.report && this.stat && this.title !== '') {
-				uni.report('title', this.title)
-			}
-		},
-		methods: {
-			onClickLeft() {
-				this.$emit("clickLeft");
-			},
-			onClickRight() {
-				this.$emit("clickRight");
-			},
-			onClickTitle() {
-				this.$emit("clickTitle");
-			}
-		}
-	};
-</script>
-
-<style lang="scss" scoped>
-	$nav-height: 44px;
-
-	.uni-nvue-fixed {
-		/* #ifdef APP-NVUE */
-		position: sticky;
-		/* #endif */
-	}
-	.uni-navbar {
-		// box-sizing: border-box;
-	}
-
-	.uni-nav-bar-text {
-		/* #ifdef APP-PLUS */
-		font-size: 34rpx;
-		/* #endif */
-		/* #ifndef APP-PLUS */
-		font-size: 14px;
-		/* #endif */
-	}
-
-	.uni-nav-bar-right-text {
-		font-size: 12px;
-	}
-
-	.uni-navbar__content {
-		position: relative;
-		// background-color: #fff;
-		// box-sizing: border-box;
-		background-color: transparent;
-	}
-
-	.uni-navbar__content_view {
-		// box-sizing: border-box;
-	}
-
-	.uni-navbar-btn-text {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: column;
-		justify-content: flex-start;
-		align-items: center;
-		line-height: 12px;
-	}
-
-	.uni-navbar__header {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		padding: 0 10px;
-		flex-direction: row;
-		height: $nav-height;
-		font-size: 12px;
-	}
-
-	.uni-navbar__header-btns {
-		/* #ifndef APP-NVUE */
-		overflow: hidden;
-		display: flex;
-		/* #endif */
-		flex-wrap: nowrap;
-		flex-direction: row;
-		width: 120rpx;
-		// padding: 0 6px;
-		justify-content: center;
-		align-items: center;
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-navbar__header-btns-left {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		width: 120rpx;
-		justify-content: flex-start;
-		align-items: center;
-	}
-
-	.uni-navbar__header-btns-right {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-		// width: 150rpx;
-		// padding-right: 30rpx;
-		justify-content: flex-end;
-		align-items: center;
-	}
-
-	.uni-navbar__header-container {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex: 1;
-		padding: 0 10px;
-		overflow: hidden;
-	}
-
-	.uni-navbar__header-container-inner {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex: 1;
-		flex-direction: row;
-		align-items: center;
-		justify-content: center;
-		font-size: 12px;
-		overflow: hidden;
-		// box-sizing: border-box;
-	}
-
-
-	.uni-navbar__placeholder-view {
-		height: $nav-height;
-	}
-
-	.uni-navbar--fixed {
-		position: fixed;
-		z-index: 998;
-		/* #ifdef H5 */
-		left: var(--window-left);
-		right: var(--window-right);
-		/* #endif */
-		/* #ifndef H5 */
-		left: 0;
-		right: 0;
-		/* #endif */
-
-	}
-
-	.uni-navbar--shadow {
-		box-shadow: 0 1px 6px #ccc;
-	}
-
-	.uni-navbar--border {
-		border-bottom-width: 1rpx;
-		border-bottom-style: solid;
-		border-bottom-color: #eee;
-	}
-
-	.uni-ellipsis-1 {
-		overflow: hidden;
-		/* #ifndef APP-NVUE */
-		white-space: nowrap;
-		text-overflow: ellipsis;
-		/* #endif */
-		/* #ifdef APP-NVUE */
-		lines: 1;
-		text-overflow: ellipsis;
-		/* #endif */
-	}
-
-	// 暗主题配置
-	.uni-dark {}
-</style>
+		<!-- #ifndef APP-NVUE -->
+		<view class="uni-navbar__placeholder" v-if="fixed">
+			<status-bar v-if="statusBar" />
+			<view class="uni-navbar__placeholder-view" :style="{ height:navbarHeight}" />
+		</view>
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	import statusBar from "./uni-status-bar.vue";
+	const getVal = (val) => typeof val === 'number' ? val + 'px' : val;
+
+	/**
+	 * 
+	 * 
+	 * NavBar 自定义导航栏
+	 * @description 导航栏组件,主要用于头部导航
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=52
+	 * @property {Boolean} dark 开启黑暗模式
+	 * @property {String} title 标题文字
+	 * @property {String} leftText 左侧按钮文本
+	 * @property {String} rightText 右侧按钮文本
+	 * @property {String} leftIcon 左侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
+	 * @property {String} rightIcon 右侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
+	 * @property {String} color 图标和文字颜色
+	 * @property {String} backgroundColor 导航栏背景颜色
+	 * @property {Boolean} fixed = [true|false] 是否固定顶部
+	 * @property {Boolean} statusBar = [true|false] 是否包含状态栏
+	 * @property {Boolean} shadow = [true|false] 导航栏下是否有阴影
+	 * @property {Boolean} stat 是否开启统计标题上报
+	 * @event {Function} clickLeft 左侧按钮点击时触发
+	 * @event {Function} clickRight 右侧按钮点击时触发
+	 * @event {Function} clickTitle 中间标题点击时触发
+	 */
+	export default {
+		name: "UniNavBar",
+		components: {
+			statusBar
+		},
+		emits: ['clickLeft', 'clickRight', 'clickTitle'],
+		props: {
+			dark: {
+				type: Boolean,
+				default: false
+			},
+			title: {
+				type: String,
+				default: ""
+			},
+			leftText: {
+				type: String,
+				default: ""
+			},
+			rightText: {
+				type: String,
+				default: ""
+			},
+			leftIcon: {
+				type: String,
+				default: ""
+			},
+			rightIcon: {
+				type: String,
+				default: ""
+			},
+			fixed: {
+				type: [Boolean, String],
+				default: false
+			},
+			color: {
+				type: String,
+				default: ""
+			},
+			backgroundColor: {
+				type: String,
+				default: ""
+			},
+			statusBar: {
+				type: [Boolean, String],
+				default: false
+			},
+			shadow: {
+				type: [Boolean, String],
+				default: false
+			},
+			border: {
+				type: [Boolean, String],
+				default: true
+			},
+			height: {
+				type: [Number, String],
+				default: 44
+			},
+			leftWidth: {
+				type: [Number, String],
+				default: 60
+			},
+			rightWidth: {
+				type: [Number, String],
+				default: 60
+			},
+			stat: {
+				type: [Boolean, String],
+				default: ''
+			}
+		},
+		computed: {
+			themeBgColor() {
+				if (this.dark) {
+					// 默认值
+					if (this.backgroundColor) {
+						return this.backgroundColor
+					} else {
+						return this.dark ? '#333' : '#FFF'
+					}
+				}
+				return this.backgroundColor || '#FFF'
+			},
+			themeColor() {
+				if (this.dark) {
+					// 默认值
+					if (this.color) {
+						return this.color
+					} else {
+						return this.dark ? '#fff' : '#333'
+					}
+				}
+				return this.color || '#333'
+			},
+			navbarHeight() {
+				return getVal(this.height)
+			},
+			leftIconWidth() {
+				return getVal(this.leftWidth)
+			},
+			rightIconWidth() {
+				return getVal(this.rightWidth)
+			}
+		},
+		mounted() {
+			if (uni.report && this.stat && this.title !== '') {
+				uni.report('title', this.title)
+			}
+		},
+		methods: {
+			onClickLeft() {
+				this.$emit("clickLeft");
+			},
+			onClickRight() {
+				this.$emit("clickRight");
+			},
+			onClickTitle() {
+				this.$emit("clickTitle");
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	$nav-height: 44px;
+
+	.uni-nvue-fixed {
+		/* #ifdef APP-NVUE */
+		position: sticky;
+		/* #endif */
+	}
+	.uni-navbar {
+		// box-sizing: border-box;
+	}
+
+	.uni-nav-bar-text {
+		/* #ifdef APP-PLUS */
+		font-size: 34rpx;
+		/* #endif */
+		/* #ifndef APP-PLUS */
+		font-size: 14px;
+		/* #endif */
+	}
+
+	.uni-nav-bar-right-text {
+		font-size: 12px;
+	}
+
+	.uni-navbar__content {
+		position: relative;
+		// background-color: #fff;
+		// box-sizing: border-box;
+		background-color: transparent;
+	}
+
+	.uni-navbar__content_view {
+		// box-sizing: border-box;
+	}
+
+	.uni-navbar-btn-text {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: flex-start;
+		align-items: center;
+		line-height: 12px;
+	}
+
+	.uni-navbar__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		padding: 0 10px;
+		flex-direction: row;
+		height: $nav-height;
+		font-size: 12px;
+	}
+
+	.uni-navbar__header-btns {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		display: flex;
+		/* #endif */
+		flex-wrap: nowrap;
+		flex-direction: row;
+		width: 120rpx;
+		// padding: 0 6px;
+		justify-content: center;
+		align-items: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-navbar__header-btns-left {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		width: 120rpx;
+		justify-content: flex-start;
+		align-items: center;
+	}
+
+	.uni-navbar__header-btns-right {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		// width: 150rpx;
+		// padding-right: 30rpx;
+		justify-content: flex-end;
+		align-items: center;
+	}
+
+	.uni-navbar__header-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		padding: 0 10px;
+		overflow: hidden;
+	}
+
+	.uni-navbar__header-container-inner {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		font-size: 12px;
+		overflow: hidden;
+		// box-sizing: border-box;
+	}
+
+
+	.uni-navbar__placeholder-view {
+		height: $nav-height;
+	}
+
+	.uni-navbar--fixed {
+		position: fixed;
+		z-index: 998;
+		/* #ifdef H5 */
+		left: var(--window-left);
+		right: var(--window-right);
+		/* #endif */
+		/* #ifndef H5 */
+		left: 0;
+		right: 0;
+		/* #endif */
+
+	}
+
+	.uni-navbar--shadow {
+		box-shadow: 0 1px 6px #ccc;
+	}
+
+	.uni-navbar--border {
+		border-bottom-width: 1rpx;
+		border-bottom-style: solid;
+		border-bottom-color: #eee;
+	}
+
+	.uni-ellipsis-1 {
+		overflow: hidden;
+		/* #ifndef APP-NVUE */
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		text-overflow: ellipsis;
+		/* #endif */
+	}
+
+	// 暗主题配置
+	.uni-dark {}
+</style>

+ 27 - 27
uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue

@@ -1,27 +1,27 @@
-<template>
-	<view :style="{ height: statusBarHeight }" class="uni-status-bar">
-		<slot />
-	</view>
-</template>
-
-<script>
-	export default {
-		name: 'UniStatusBar',
-		data() {
-			return {
-				statusBarHeight: 20
-			}
-		},
-		mounted() {
-			this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
-		}
-	}
-</script>
-
-<style lang="scss" >
-	.uni-status-bar {
-		// width: 750rpx;
-		height: 20px;
-		// height: var(--status-bar-height);
-	}
-</style>
+<template>
+	<view :style="{ height: statusBarHeight }" class="uni-status-bar">
+		<slot />
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'UniStatusBar',
+		data() {
+			return {
+				statusBarHeight: 20
+			}
+		},
+		mounted() {
+			this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-status-bar {
+		// width: 750rpx;
+		height: 20px;
+		// height: var(--status-bar-height);
+	}
+</style>

+ 426 - 426
uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue

@@ -1,426 +1,426 @@
-<template>
-	<view v-if="show" class="uni-noticebar" :style="{ backgroundColor }" @click="onClick">
-		<uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound"
-			:color="color" :size="fontSize * 1.5" />
-		<view ref="textBox" class="uni-noticebar__content-wrapper"
-			:class="{
-				'uni-noticebar__content-wrapper--scrollable': scrollable,
-				'uni-noticebar__content-wrapper--single': !scrollable && (single || moreText)
-			}"
-			:style="{ height: scrollable ? fontSize * 1.5 + 'px' : 'auto' }"
-		>
-			<view :id="elIdBox" class="uni-noticebar__content"
-				:class="{
-					'uni-noticebar__content--scrollable': scrollable,
-					'uni-noticebar__content--single': !scrollable && (single || moreText)
-				}"
-			>
-				<text :id="elId" ref="animationEle" class="uni-noticebar__content-text" 
-					:class="{
-						'uni-noticebar__content-text--scrollable': scrollable,
-						'uni-noticebar__content-text--single': !scrollable && (single || showGetMore)
-					}" 
-					:style="{
-						color: color,
-						fontSize: fontSize + 'px',
-						lineHeight: fontSize * 1.5 + 'px',
-						width: wrapWidth + 'px',
-						'animationDuration': animationDuration,
-						'-webkit-animationDuration': animationDuration,
-						animationPlayState: webviewHide ? 'paused' : animationPlayState,
-						'-webkit-animationPlayState': webviewHide ? 'paused' : animationPlayState,
-						animationDelay: animationDelay,
-						'-webkit-animationDelay': animationDelay
-					}"
-				>{{text}}</text>
-			</view>
-		</view>
-		<view v-if="isShowGetMore" class="uni-noticebar__more uni-cursor-point"
-			@click="clickMore">
-			<text v-if="moreText.length > 0" :style="{ color: moreColor, fontSize: fontSize + 'px' }">{{ moreText }}</text>
-			<uni-icons v-else type="right" :color="moreColor" :size="fontSize * 1.1" />
-		</view>
-		<view class="uni-noticebar-close uni-cursor-point" v-if="isShowClose">
-			<uni-icons type="closeempty" :color="color" :size="fontSize * 1.1" @click="close" />
-		</view>
-	</view>
-</template>
-
-<script>
-	// #ifdef APP-NVUE
-	const dom = weex.requireModule('dom');
-	const animation = weex.requireModule('animation');
-	// #endif
-
-	/**
-	 * NoticeBar 自定义导航栏
-	 * @description 通告栏组件
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=30
-	 * @property {Number} speed 文字滚动的速度,默认100px/秒
-	 * @property {String} text 显示文字
-	 * @property {String} backgroundColor 背景颜色
-	 * @property {String} color 文字颜色
-	 * @property {String} moreColor 查看更多文字的颜色
-	 * @property {String} moreText 设置“查看更多”的文本
-	 * @property {Boolean} single = [true|false] 是否单行
-	 * @property {Boolean} scrollable = [true|false] 是否滚动,为true时,NoticeBar为单行
-	 * @property {Boolean} showIcon = [true|false] 是否显示左侧喇叭图标
-	 * @property {Boolean} showClose = [true|false] 是否显示左侧关闭按钮
-	 * @property {Boolean} showGetMore = [true|false] 是否显示右侧查看更多图标,为true时,NoticeBar为单行
-	 * @event {Function} click 点击 NoticeBar 触发事件
-	 * @event {Function} close 关闭 NoticeBar 触发事件
-	 * @event {Function} getmore 点击”查看更多“时触发事件
-	 */
-
-	export default {
-		name: 'UniNoticeBar',
-		emits: ['click', 'getmore', 'close'],
-		props: {
-			text: {
-				type: String,
-				default: ''
-			},
-			moreText: {
-				type: String,
-				default: ''
-			},
-			backgroundColor: {
-				type: String,
-				default: '#FFF9EA'
-			},
-			speed: {
-				// 默认1s滚动100px
-				type: Number,
-				default: 100
-			},
-			color: {
-				type: String,
-				default: '#FF9A43'
-			},
-			fontSize: {
-				type: Number,
-				default: 14
-			},
-			moreColor: {
-				type: String,
-				default: '#FF9A43'
-			},
-			single: {
-				// 是否单行
-				type: [Boolean, String],
-				default: false
-			},
-			scrollable: {
-				// 是否滚动,添加后控制单行效果取消
-				type: [Boolean, String],
-				default: false
-			},
-			showIcon: {
-				// 是否显示左侧icon
-				type: [Boolean, String],
-				default: false
-			},
-			showGetMore: {
-				// 是否显示右侧查看更多
-				type: [Boolean, String],
-				default: false
-			},
-			showClose: {
-				// 是否显示左侧关闭按钮
-				type: [Boolean, String],
-				default: false
-			}
-		},
-		data() {
-			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
-			const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
-			return {
-				textWidth: 0,
-				boxWidth: 0,
-				wrapWidth: '',
-				webviewHide: false,
-				// #ifdef APP-NVUE
-				stopAnimation: false,
-				// #endif
-				elId: elId,
-				elIdBox: elIdBox,
-				show: true,
-				animationDuration: 'none',
-				animationPlayState: 'paused',
-				animationDelay: '0s'
-			}
-		},
-		computed: {
-			isShowGetMore() {
-				return this.showGetMore === true || this.showGetMore === 'true'
-			},
-			isShowClose() {
-				return (this.showClose === true || this.showClose === 'true') 
-					&& (this.showGetMore === false || this.showGetMore === 'false')
-			}
-		},
-		mounted() {
-			// #ifdef APP-PLUS
-			var pages = getCurrentPages();
-			var page = pages[pages.length - 1];
-			var currentWebview = page.$getAppWebview();
-			currentWebview.addEventListener('hide', () => {
-				this.webviewHide = true
-			})
-			currentWebview.addEventListener('show', () => {
-				this.webviewHide = false
-			})
-			// #endif
-			this.$nextTick(() => {
-				this.initSize()
-			})
-		},
-		// #ifdef APP-NVUE
-		beforeDestroy() {
-			this.stopAnimation = true
-		},
-		// #endif
-		methods: {
-			initSize() {
-				if (this.scrollable) {
-					// #ifndef APP-NVUE
-					let query = [],
-						boxWidth = 0,
-						textWidth = 0;
-					let textQuery = new Promise((resolve, reject) => {
-						uni.createSelectorQuery()
-							// #ifndef MP-ALIPAY
-							.in(this)
-							// #endif
-							.select(`#${this.elId}`)
-							.boundingClientRect()
-							.exec(ret => {
-								this.textWidth = ret[0].width
-								resolve()
-							})
-					})
-					let boxQuery = new Promise((resolve, reject) => {
-						uni.createSelectorQuery()
-							// #ifndef MP-ALIPAY
-							.in(this)
-							// #endif
-							.select(`#${this.elIdBox}`)
-							.boundingClientRect()
-							.exec(ret => {
-								this.boxWidth = ret[0].width
-								resolve()
-							})
-					})
-					query.push(textQuery)
-					query.push(boxQuery)
-					Promise.all(query).then(() => {
-						this.animationDuration = `${this.textWidth / this.speed}s`
-						this.animationDelay = `-${this.boxWidth / this.speed}s`
-						setTimeout(() => {
-							this.animationPlayState = 'running'
-						}, 1000)
-					})
-					// #endif
-					// #ifdef APP-NVUE
-					dom.getComponentRect(this.$refs['animationEle'], (res) => {
-						let winWidth = uni.getSystemInfoSync().windowWidth
-						this.textWidth = res.size.width
-						animation.transition(this.$refs['animationEle'], {
-							styles: {
-								transform: `translateX(-${winWidth}px)`
-							},
-							duration: 0,
-							timingFunction: 'linear',
-							delay: 0
-						}, () => {
-							if (!this.stopAnimation) {
-								animation.transition(this.$refs['animationEle'], {
-									styles: {
-										transform: `translateX(-${this.textWidth}px)`
-									},
-									timingFunction: 'linear',
-									duration: (this.textWidth - winWidth) / this.speed * 1000,
-									delay: 1000
-								}, () => {
-									if (!this.stopAnimation) {
-										this.loopAnimation()
-									}
-								});
-							}
-						});
-					})
-					// #endif
-				}
-				// #ifdef APP-NVUE
-				if (!this.scrollable && (this.single || this.moreText)) {
-					dom.getComponentRect(this.$refs['textBox'], (res) => {
-						this.wrapWidth = res.size.width
-					})
-				}
-				// #endif
-			},
-			loopAnimation() {
-				// #ifdef APP-NVUE
-				animation.transition(this.$refs['animationEle'], {
-					styles: {
-						transform: `translateX(0px)`
-					},
-					duration: 0
-				}, () => {
-					if (!this.stopAnimation) {
-						animation.transition(this.$refs['animationEle'], {
-							styles: {
-								transform: `translateX(-${this.textWidth}px)`
-							},
-							duration: this.textWidth / this.speed * 1000,
-							timingFunction: 'linear',
-							delay: 0
-						}, () => {
-							if (!this.stopAnimation) {
-								this.loopAnimation()
-							}
-						});
-					}
-				});
-				// #endif
-			},
-			clickMore() {
-				this.$emit('getmore')
-			},
-			close() {
-				this.show = false;
-				this.$emit('close')
-			},
-			onClick() {
-				this.$emit('click')
-			}
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	.uni-noticebar {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		width: 100%;
-		box-sizing: border-box;
-		/* #endif */
-		flex-direction: row;
-		align-items: center;
-		padding: 10px 12px;
-		margin-bottom: 10px;
-	}
-
-	.uni-cursor-point {
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-noticebar-close {
-		margin-left: 8px;
-		margin-right: 5px;
-	}
-
-	.uni-noticebar-icon {
-		margin-right: 5px;
-	}
-
-	.uni-noticebar__content-wrapper {
-		flex: 1;
-		flex-direction: column;
-		overflow: hidden;
-	}
-
-	.uni-noticebar__content-wrapper--single {
-		/* #ifndef APP-NVUE */
-		line-height: 18px;
-		/* #endif */
-	}
-
-	.uni-noticebar__content-wrapper--single,
-	.uni-noticebar__content-wrapper--scrollable {
-		flex-direction: row;
-	}
-
-	/* #ifndef APP-NVUE */
-	.uni-noticebar__content-wrapper--scrollable {
-		position: relative;
-	}
-
-	/* #endif */
-
-	.uni-noticebar__content--scrollable {
-		/* #ifdef APP-NVUE */
-		flex: 0;
-		/* #endif */
-		/* #ifndef APP-NVUE */
-		flex: 1;
-		display: block;
-		overflow: hidden;
-		/* #endif */
-	}
-
-	.uni-noticebar__content--single {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		flex: none;
-		width: 100%;
-		justify-content: center;
-		/* #endif */
-	}
-
-	.uni-noticebar__content-text {
-		font-size: 14px;
-		line-height: 18px;
-		/* #ifndef APP-NVUE */
-		word-break: break-all;
-		/* #endif */
-	}
-
-	.uni-noticebar__content-text--single {
-		/* #ifdef APP-NVUE */
-		lines: 1;
-		/* #endif */
-		/* #ifndef APP-NVUE */
-		display: block;
-		width: 100%;
-		white-space: nowrap;
-		/* #endif */
-		overflow: hidden;
-		text-overflow: ellipsis;
-	}
-
-	.uni-noticebar__content-text--scrollable {
-		/* #ifdef APP-NVUE */
-		lines: 1;
-		padding-left: 750rpx;
-		/* #endif */
-		/* #ifndef APP-NVUE */
-		position: absolute;
-		display: block;
-		height: 18px;
-		line-height: 18px;
-		white-space: nowrap;
-		padding-left: 100%;
-		animation: notice 10s 0s linear infinite both;
-		animation-play-state: paused;
-		/* #endif */
-	}
-
-	.uni-noticebar__more {
-		/* #ifndef APP-NVUE */
-		display: inline-flex;
-		/* #endif */
-		flex-direction: row;
-		flex-wrap: nowrap;
-		align-items: center;
-		padding-left: 5px;
-	}
-
-	@keyframes notice {
-		100% {
-			transform: translate3d(-100%, 0, 0);
-		}
-	}
-</style>
+<template>
+	<view v-if="show" class="uni-noticebar" :style="{ backgroundColor }" @click="onClick">
+		<uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound"
+			:color="color" :size="fontSize * 1.5" />
+		<view ref="textBox" class="uni-noticebar__content-wrapper"
+			:class="{
+				'uni-noticebar__content-wrapper--scrollable': scrollable,
+				'uni-noticebar__content-wrapper--single': !scrollable && (single || moreText)
+			}"
+			:style="{ height: scrollable ? fontSize * 1.5 + 'px' : 'auto' }"
+		>
+			<view :id="elIdBox" class="uni-noticebar__content"
+				:class="{
+					'uni-noticebar__content--scrollable': scrollable,
+					'uni-noticebar__content--single': !scrollable && (single || moreText)
+				}"
+			>
+				<text :id="elId" ref="animationEle" class="uni-noticebar__content-text" 
+					:class="{
+						'uni-noticebar__content-text--scrollable': scrollable,
+						'uni-noticebar__content-text--single': !scrollable && (single || showGetMore)
+					}" 
+					:style="{
+						color: color,
+						fontSize: fontSize + 'px',
+						lineHeight: fontSize * 1.5 + 'px',
+						width: wrapWidth + 'px',
+						'animationDuration': animationDuration,
+						'-webkit-animationDuration': animationDuration,
+						animationPlayState: webviewHide ? 'paused' : animationPlayState,
+						'-webkit-animationPlayState': webviewHide ? 'paused' : animationPlayState,
+						animationDelay: animationDelay,
+						'-webkit-animationDelay': animationDelay
+					}"
+				>{{text}}</text>
+			</view>
+		</view>
+		<view v-if="isShowGetMore" class="uni-noticebar__more uni-cursor-point"
+			@click="clickMore">
+			<text v-if="moreText.length > 0" :style="{ color: moreColor, fontSize: fontSize + 'px' }">{{ moreText }}</text>
+			<uni-icons v-else type="right" :color="moreColor" :size="fontSize * 1.1" />
+		</view>
+		<view class="uni-noticebar-close uni-cursor-point" v-if="isShowClose">
+			<uni-icons type="closeempty" :color="color" :size="fontSize * 1.1" @click="close" />
+		</view>
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = weex.requireModule('dom');
+	const animation = weex.requireModule('animation');
+	// #endif
+
+	/**
+	 * NoticeBar 自定义导航栏
+	 * @description 通告栏组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=30
+	 * @property {Number} speed 文字滚动的速度,默认100px/秒
+	 * @property {String} text 显示文字
+	 * @property {String} backgroundColor 背景颜色
+	 * @property {String} color 文字颜色
+	 * @property {String} moreColor 查看更多文字的颜色
+	 * @property {String} moreText 设置“查看更多”的文本
+	 * @property {Boolean} single = [true|false] 是否单行
+	 * @property {Boolean} scrollable = [true|false] 是否滚动,为true时,NoticeBar为单行
+	 * @property {Boolean} showIcon = [true|false] 是否显示左侧喇叭图标
+	 * @property {Boolean} showClose = [true|false] 是否显示左侧关闭按钮
+	 * @property {Boolean} showGetMore = [true|false] 是否显示右侧查看更多图标,为true时,NoticeBar为单行
+	 * @event {Function} click 点击 NoticeBar 触发事件
+	 * @event {Function} close 关闭 NoticeBar 触发事件
+	 * @event {Function} getmore 点击”查看更多“时触发事件
+	 */
+
+	export default {
+		name: 'UniNoticeBar',
+		emits: ['click', 'getmore', 'close'],
+		props: {
+			text: {
+				type: String,
+				default: ''
+			},
+			moreText: {
+				type: String,
+				default: ''
+			},
+			backgroundColor: {
+				type: String,
+				default: '#FFF9EA'
+			},
+			speed: {
+				// 默认1s滚动100px
+				type: Number,
+				default: 100
+			},
+			color: {
+				type: String,
+				default: '#FF9A43'
+			},
+			fontSize: {
+				type: Number,
+				default: 14
+			},
+			moreColor: {
+				type: String,
+				default: '#FF9A43'
+			},
+			single: {
+				// 是否单行
+				type: [Boolean, String],
+				default: false
+			},
+			scrollable: {
+				// 是否滚动,添加后控制单行效果取消
+				type: [Boolean, String],
+				default: false
+			},
+			showIcon: {
+				// 是否显示左侧icon
+				type: [Boolean, String],
+				default: false
+			},
+			showGetMore: {
+				// 是否显示右侧查看更多
+				type: [Boolean, String],
+				default: false
+			},
+			showClose: {
+				// 是否显示左侧关闭按钮
+				type: [Boolean, String],
+				default: false
+			}
+		},
+		data() {
+			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			return {
+				textWidth: 0,
+				boxWidth: 0,
+				wrapWidth: '',
+				webviewHide: false,
+				// #ifdef APP-NVUE
+				stopAnimation: false,
+				// #endif
+				elId: elId,
+				elIdBox: elIdBox,
+				show: true,
+				animationDuration: 'none',
+				animationPlayState: 'paused',
+				animationDelay: '0s'
+			}
+		},
+		computed: {
+			isShowGetMore() {
+				return this.showGetMore === true || this.showGetMore === 'true'
+			},
+			isShowClose() {
+				return (this.showClose === true || this.showClose === 'true') 
+					&& (this.showGetMore === false || this.showGetMore === 'false')
+			}
+		},
+		mounted() {
+			// #ifdef APP-PLUS
+			var pages = getCurrentPages();
+			var page = pages[pages.length - 1];
+			var currentWebview = page.$getAppWebview();
+			currentWebview.addEventListener('hide', () => {
+				this.webviewHide = true
+			})
+			currentWebview.addEventListener('show', () => {
+				this.webviewHide = false
+			})
+			// #endif
+			this.$nextTick(() => {
+				this.initSize()
+			})
+		},
+		// #ifdef APP-NVUE
+		beforeDestroy() {
+			this.stopAnimation = true
+		},
+		// #endif
+		methods: {
+			initSize() {
+				if (this.scrollable) {
+					// #ifndef APP-NVUE
+					let query = [],
+						boxWidth = 0,
+						textWidth = 0;
+					let textQuery = new Promise((resolve, reject) => {
+						uni.createSelectorQuery()
+							// #ifndef MP-ALIPAY
+							.in(this)
+							// #endif
+							.select(`#${this.elId}`)
+							.boundingClientRect()
+							.exec(ret => {
+								this.textWidth = ret[0].width
+								resolve()
+							})
+					})
+					let boxQuery = new Promise((resolve, reject) => {
+						uni.createSelectorQuery()
+							// #ifndef MP-ALIPAY
+							.in(this)
+							// #endif
+							.select(`#${this.elIdBox}`)
+							.boundingClientRect()
+							.exec(ret => {
+								this.boxWidth = ret[0].width
+								resolve()
+							})
+					})
+					query.push(textQuery)
+					query.push(boxQuery)
+					Promise.all(query).then(() => {
+						this.animationDuration = `${this.textWidth / this.speed}s`
+						this.animationDelay = `-${this.boxWidth / this.speed}s`
+						setTimeout(() => {
+							this.animationPlayState = 'running'
+						}, 1000)
+					})
+					// #endif
+					// #ifdef APP-NVUE
+					dom.getComponentRect(this.$refs['animationEle'], (res) => {
+						let winWidth = uni.getSystemInfoSync().windowWidth
+						this.textWidth = res.size.width
+						animation.transition(this.$refs['animationEle'], {
+							styles: {
+								transform: `translateX(-${winWidth}px)`
+							},
+							duration: 0,
+							timingFunction: 'linear',
+							delay: 0
+						}, () => {
+							if (!this.stopAnimation) {
+								animation.transition(this.$refs['animationEle'], {
+									styles: {
+										transform: `translateX(-${this.textWidth}px)`
+									},
+									timingFunction: 'linear',
+									duration: (this.textWidth - winWidth) / this.speed * 1000,
+									delay: 1000
+								}, () => {
+									if (!this.stopAnimation) {
+										this.loopAnimation()
+									}
+								});
+							}
+						});
+					})
+					// #endif
+				}
+				// #ifdef APP-NVUE
+				if (!this.scrollable && (this.single || this.moreText)) {
+					dom.getComponentRect(this.$refs['textBox'], (res) => {
+						this.wrapWidth = res.size.width
+					})
+				}
+				// #endif
+			},
+			loopAnimation() {
+				// #ifdef APP-NVUE
+				animation.transition(this.$refs['animationEle'], {
+					styles: {
+						transform: `translateX(0px)`
+					},
+					duration: 0
+				}, () => {
+					if (!this.stopAnimation) {
+						animation.transition(this.$refs['animationEle'], {
+							styles: {
+								transform: `translateX(-${this.textWidth}px)`
+							},
+							duration: this.textWidth / this.speed * 1000,
+							timingFunction: 'linear',
+							delay: 0
+						}, () => {
+							if (!this.stopAnimation) {
+								this.loopAnimation()
+							}
+						});
+					}
+				});
+				// #endif
+			},
+			clickMore() {
+				this.$emit('getmore')
+			},
+			close() {
+				this.show = false;
+				this.$emit('close')
+			},
+			onClick() {
+				this.$emit('click')
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.uni-noticebar {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		width: 100%;
+		box-sizing: border-box;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		padding: 10px 12px;
+		margin-bottom: 10px;
+	}
+
+	.uni-cursor-point {
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-noticebar-close {
+		margin-left: 8px;
+		margin-right: 5px;
+	}
+
+	.uni-noticebar-icon {
+		margin-right: 5px;
+	}
+
+	.uni-noticebar__content-wrapper {
+		flex: 1;
+		flex-direction: column;
+		overflow: hidden;
+	}
+
+	.uni-noticebar__content-wrapper--single {
+		/* #ifndef APP-NVUE */
+		line-height: 18px;
+		/* #endif */
+	}
+
+	.uni-noticebar__content-wrapper--single,
+	.uni-noticebar__content-wrapper--scrollable {
+		flex-direction: row;
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-noticebar__content-wrapper--scrollable {
+		position: relative;
+	}
+
+	/* #endif */
+
+	.uni-noticebar__content--scrollable {
+		/* #ifdef APP-NVUE */
+		flex: 0;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		flex: 1;
+		display: block;
+		overflow: hidden;
+		/* #endif */
+	}
+
+	.uni-noticebar__content--single {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex: none;
+		width: 100%;
+		justify-content: center;
+		/* #endif */
+	}
+
+	.uni-noticebar__content-text {
+		font-size: 14px;
+		line-height: 18px;
+		/* #ifndef APP-NVUE */
+		word-break: break-all;
+		/* #endif */
+	}
+
+	.uni-noticebar__content-text--single {
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: block;
+		width: 100%;
+		white-space: nowrap;
+		/* #endif */
+		overflow: hidden;
+		text-overflow: ellipsis;
+	}
+
+	.uni-noticebar__content-text--scrollable {
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		padding-left: 750rpx;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		position: absolute;
+		display: block;
+		height: 18px;
+		line-height: 18px;
+		white-space: nowrap;
+		padding-left: 100%;
+		animation: notice 10s 0s linear infinite both;
+		animation-play-state: paused;
+		/* #endif */
+	}
+
+	.uni-noticebar__more {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		/* #endif */
+		flex-direction: row;
+		flex-wrap: nowrap;
+		align-items: center;
+		padding-left: 5px;
+	}
+
+	@keyframes notice {
+		100% {
+			transform: translate3d(-100%, 0, 0);
+		}
+	}
+</style>

+ 221 - 221
uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue

@@ -1,221 +1,221 @@
-<template>
-	<view class="uni-numbox">
-		<view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{background}">
-			<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }" :style="{color}">-</text>
-		</view>
-		<input :disabled="disabled" @focus="_onFocus" @blur="_onBlur" class="uni-numbox__value" type="number"
-			v-model="inputValue" :style="{background, color}" />
-		<view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns" :style="{background}">
-			<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }" :style="{color}">+</text>
-		</view>
-	</view>
-</template>
-<script>
-	/**
-	 * NumberBox 数字输入框
-	 * @description 带加减按钮的数字输入框
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=31
-	 * @property {Number} value 输入框当前值
-	 * @property {Number} min 最小值
-	 * @property {Number} max 最大值
-	 * @property {Number} step 每次点击改变的间隔大小
-	 * @property {String} background 背景色
-	 * @property {String} color 字体颜色(前景色)
-	 * @property {Boolean} disabled = [true|false] 是否为禁用状态
-	 * @event {Function} change 输入框值改变时触发的事件,参数为输入框当前的 value
-	 * @event {Function} focus 输入框聚焦时触发的事件,参数为 event 对象
-	 * @event {Function} blur 输入框失焦时触发的事件,参数为 event 对象
-	 */
-
-	export default {
-		name: "UniNumberBox",
-		emits: ['change', 'input', 'update:modelValue', 'blur', 'focus'],
-		props: {
-			value: {
-				type: [Number, String],
-				default: 1
-			},
-			modelValue: {
-				type: [Number, String],
-				default: 1
-			},
-			min: {
-				type: Number,
-				default: 0
-			},
-			max: {
-				type: Number,
-				default: 100
-			},
-			step: {
-				type: Number,
-				default: 1
-			},
-			background: {
-				type: String,
-				default: '#f5f5f5'
-			},
-			color: {
-				type: String,
-				default: '#333'
-			},
-			disabled: {
-				type: Boolean,
-				default: false
-			}
-		},
-		data() {
-			return {
-				inputValue: 0
-			};
-		},
-		watch: {
-			value(val) {
-				this.inputValue = +val;
-			},
-			modelValue(val) {
-				this.inputValue = +val;
-			}
-		},
-		created() {
-			if (this.value === 1) {
-				this.inputValue = +this.modelValue;
-			}
-			if (this.modelValue === 1) {
-				this.inputValue = +this.value;
-			}
-		},
-		methods: {
-			_calcValue(type) {
-				if (this.disabled) {
-					return;
-				}
-				const scale = this._getDecimalScale();
-				let value = this.inputValue * scale;
-				let step = this.step * scale;
-				if (type === "minus") {
-					value -= step;
-					if (value < (this.min * scale)) {
-						return;
-					}
-					if (value > (this.max * scale)) {
-						value = this.max * scale
-					}
-				}
-
-				if (type === "plus") {
-					value += step;
-					if (value > (this.max * scale)) {
-						return;
-					}
-					if (value < (this.min * scale)) {
-						value = this.min * scale
-					}
-				}
-
-				this.inputValue = (value / scale).toFixed(String(scale).length - 1);
-				this.$emit("change", +this.inputValue);
-				// TODO vue2 兼容
-				this.$emit("input", +this.inputValue);
-				// TODO vue3 兼容
-				this.$emit("update:modelValue", +this.inputValue);
-			},
-			_getDecimalScale() {
-
-				let scale = 1;
-				// 浮点型
-				if (~~this.step !== this.step) {
-					scale = Math.pow(10, String(this.step).split(".")[1].length);
-				}
-				return scale;
-			},
-			_onBlur(event) {
-				this.$emit('blur', event)
-				let value = event.detail.value;
-				if (isNaN(value)) {
-					this.inputValue = this.min;
-					return;
-				}
-				value = +value;
-				if (value > this.max) {
-					value = this.max;
-				} else if (value < this.min) {
-					value = this.min;
-				}
-				const scale = this._getDecimalScale();
-				this.inputValue = value.toFixed(String(scale).length - 1);
-				this.$emit("change", +this.inputValue);
-				this.$emit("input", +this.inputValue);
-				this.$emit("update:modelValue", +this.inputValue);
-			},
-			_onFocus(event) {
-				this.$emit('focus', event)
-			}
-		}
-	};
-</script>
-<style lang="scss" >
-	$box-height: 26px;
-	$bg: #f5f5f5;
-	$br: 2px;
-	$color: #333;
-
-	.uni-numbox {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-	}
-
-	.uni-numbox-btns {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-		align-items: center;
-		justify-content: center;
-		padding: 0 8px;
-		background-color: $bg;
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
-
-	.uni-numbox__value {
-		margin: 0 2px;
-		background-color: $bg;
-		width: 40px;
-		height: $box-height;
-		text-align: center;
-		font-size: 14px;
-		border-left-width: 0;
-		border-right-width: 0;
-		color: $color;
-	}
-
-	.uni-numbox__minus {
-		border-top-left-radius: $br;
-		border-bottom-left-radius: $br;
-	}
-
-	.uni-numbox__plus {
-		border-top-right-radius: $br;
-		border-bottom-right-radius: $br;
-	}
-
-	.uni-numbox--text {
-		// fix nvue
-		line-height: 20px;
-
-		font-size: 20px;
-		font-weight: 300;
-		color: $color;
-	}
-
-	.uni-numbox .uni-numbox--disabled {
-		color: #c0c0c0 !important;
-		/* #ifdef H5 */
-		cursor: not-allowed;
-		/* #endif */
-	}
-</style>
+<template>
+	<view class="uni-numbox">
+		<view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{background}">
+			<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }" :style="{color}">-</text>
+		</view>
+		<input :disabled="disabled" @focus="_onFocus" @blur="_onBlur" class="uni-numbox__value" type="number"
+			v-model="inputValue" :style="{background, color}" />
+		<view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns" :style="{background}">
+			<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }" :style="{color}">+</text>
+		</view>
+	</view>
+</template>
+<script>
+	/**
+	 * NumberBox 数字输入框
+	 * @description 带加减按钮的数字输入框
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=31
+	 * @property {Number} value 输入框当前值
+	 * @property {Number} min 最小值
+	 * @property {Number} max 最大值
+	 * @property {Number} step 每次点击改变的间隔大小
+	 * @property {String} background 背景色
+	 * @property {String} color 字体颜色(前景色)
+	 * @property {Boolean} disabled = [true|false] 是否为禁用状态
+	 * @event {Function} change 输入框值改变时触发的事件,参数为输入框当前的 value
+	 * @event {Function} focus 输入框聚焦时触发的事件,参数为 event 对象
+	 * @event {Function} blur 输入框失焦时触发的事件,参数为 event 对象
+	 */
+
+	export default {
+		name: "UniNumberBox",
+		emits: ['change', 'input', 'update:modelValue', 'blur', 'focus'],
+		props: {
+			value: {
+				type: [Number, String],
+				default: 1
+			},
+			modelValue: {
+				type: [Number, String],
+				default: 1
+			},
+			min: {
+				type: Number,
+				default: 0
+			},
+			max: {
+				type: Number,
+				default: 100
+			},
+			step: {
+				type: Number,
+				default: 1
+			},
+			background: {
+				type: String,
+				default: '#f5f5f5'
+			},
+			color: {
+				type: String,
+				default: '#333'
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				inputValue: 0
+			};
+		},
+		watch: {
+			value(val) {
+				this.inputValue = +val;
+			},
+			modelValue(val) {
+				this.inputValue = +val;
+			}
+		},
+		created() {
+			if (this.value === 1) {
+				this.inputValue = +this.modelValue;
+			}
+			if (this.modelValue === 1) {
+				this.inputValue = +this.value;
+			}
+		},
+		methods: {
+			_calcValue(type) {
+				if (this.disabled) {
+					return;
+				}
+				const scale = this._getDecimalScale();
+				let value = this.inputValue * scale;
+				let step = this.step * scale;
+				if (type === "minus") {
+					value -= step;
+					if (value < (this.min * scale)) {
+						return;
+					}
+					if (value > (this.max * scale)) {
+						value = this.max * scale
+					}
+				}
+
+				if (type === "plus") {
+					value += step;
+					if (value > (this.max * scale)) {
+						return;
+					}
+					if (value < (this.min * scale)) {
+						value = this.min * scale
+					}
+				}
+
+				this.inputValue = (value / scale).toFixed(String(scale).length - 1);
+				this.$emit("change", +this.inputValue);
+				// TODO vue2 兼容
+				this.$emit("input", +this.inputValue);
+				// TODO vue3 兼容
+				this.$emit("update:modelValue", +this.inputValue);
+			},
+			_getDecimalScale() {
+
+				let scale = 1;
+				// 浮点型
+				if (~~this.step !== this.step) {
+					scale = Math.pow(10, String(this.step).split(".")[1].length);
+				}
+				return scale;
+			},
+			_onBlur(event) {
+				this.$emit('blur', event)
+				let value = event.detail.value;
+				if (isNaN(value)) {
+					this.inputValue = this.min;
+					return;
+				}
+				value = +value;
+				if (value > this.max) {
+					value = this.max;
+				} else if (value < this.min) {
+					value = this.min;
+				}
+				const scale = this._getDecimalScale();
+				this.inputValue = value.toFixed(String(scale).length - 1);
+				this.$emit("change", +this.inputValue);
+				this.$emit("input", +this.inputValue);
+				this.$emit("update:modelValue", +this.inputValue);
+			},
+			_onFocus(event) {
+				this.$emit('focus', event)
+			}
+		}
+	};
+</script>
+<style lang="scss" >
+	$box-height: 26px;
+	$bg: #f5f5f5;
+	$br: 2px;
+	$color: #333;
+
+	.uni-numbox {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-numbox-btns {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		padding: 0 8px;
+		background-color: $bg;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-numbox__value {
+		margin: 0 2px;
+		background-color: $bg;
+		width: 40px;
+		height: $box-height;
+		text-align: center;
+		font-size: 14px;
+		border-left-width: 0;
+		border-right-width: 0;
+		color: $color;
+	}
+
+	.uni-numbox__minus {
+		border-top-left-radius: $br;
+		border-bottom-left-radius: $br;
+	}
+
+	.uni-numbox__plus {
+		border-top-right-radius: $br;
+		border-bottom-right-radius: $br;
+	}
+
+	.uni-numbox--text {
+		// fix nvue
+		line-height: 20px;
+
+		font-size: 20px;
+		font-weight: 300;
+		color: $color;
+	}
+
+	.uni-numbox .uni-numbox--disabled {
+		color: #c0c0c0 !important;
+		/* #ifdef H5 */
+		cursor: not-allowed;
+		/* #endif */
+	}
+</style>

+ 15 - 15
uni_modules/uni-pagination/changelog.md

@@ -10,18 +10,18 @@
 ## 1.2.0(2021-11-19)
 ## 1.2.0(2021-11-19)
 - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
 - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
 - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-pagination](https://uniapp.dcloud.io/component/uniui/uni-pagination)
 - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-pagination](https://uniapp.dcloud.io/component/uniui/uni-pagination)
-## 1.1.2(2021-10-08)
-- 修复 current 、value 属性未监听,导致高亮样式失效的 bug
-## 1.1.1(2021-08-20)
-- 新增 支持国际化
-## 1.1.0(2021-07-30)
-- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
-## 1.0.7(2021-05-12)
-- 新增 组件示例地址
-## 1.0.6(2021-04-12)
-- 新增 PC 和 移动端适配不同的 ui 
-## 1.0.5(2021-02-05)
-- 优化 组件引用关系,通过uni_modules引用组件
-
-## 1.0.4(2021-02-05)
-- 调整为uni_modules目录规范
+## 1.1.2(2021-10-08)
+- 修复 current 、value 属性未监听,导致高亮样式失效的 bug
+## 1.1.1(2021-08-20)
+- 新增 支持国际化
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7(2021-05-12)
+- 新增 组件示例地址
+## 1.0.6(2021-04-12)
+- 新增 PC 和 移动端适配不同的 ui 
+## 1.0.5(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.4(2021-02-05)
+- 调整为uni_modules目录规范

+ 4 - 4
uni_modules/uni-pagination/components/uni-pagination/i18n/en.json

@@ -1,5 +1,5 @@
-{
-	"uni-pagination.prevText": "prev",
-	"uni-pagination.nextText": "next",
-	"uni-pagination.piecePerPage": "piece/page"
+{
+	"uni-pagination.prevText": "prev",
+	"uni-pagination.nextText": "next",
+	"uni-pagination.piecePerPage": "piece/page"
 }
 }

+ 4 - 4
uni_modules/uni-pagination/components/uni-pagination/i18n/es.json

@@ -1,5 +1,5 @@
-{
-	"uni-pagination.prevText": "anterior",
-	"uni-pagination.nextText": "prxima",
-	"uni-pagination.piecePerPage": "Art¨ªculo/P¨¢gina"
+{
+	"uni-pagination.prevText": "anterior",
+	"uni-pagination.nextText": "prxima",
+	"uni-pagination.piecePerPage": "Art¨ªculo/P¨¢gina"
 }
 }

+ 4 - 4
uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json

@@ -1,5 +1,5 @@
-{
-	"uni-pagination.prevText": "précédente",
-	"uni-pagination.nextText": "suivante",
-	"uni-pagination.piecePerPage": "Articles/Pages"
+{
+	"uni-pagination.prevText": "précédente",
+	"uni-pagination.nextText": "suivante",
+	"uni-pagination.piecePerPage": "Articles/Pages"
 }
 }

+ 11 - 11
uni_modules/uni-pagination/components/uni-pagination/i18n/index.js

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

+ 4 - 4
uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json

@@ -1,5 +1,5 @@
-{
-	"uni-pagination.prevText": "上一页",
-	"uni-pagination.nextText": "下一页",
-	"uni-pagination.piecePerPage": "条/页"
+{
+	"uni-pagination.prevText": "上一页",
+	"uni-pagination.nextText": "下一页",
+	"uni-pagination.piecePerPage": "条/页"
 }
 }

+ 4 - 4
uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json

@@ -1,5 +1,5 @@
-{
-	"uni-pagination.prevText": "上一頁",
-	"uni-pagination.nextText": "下一頁",
-	"uni-pagination.piecePerPage": "條/頁"
+{
+	"uni-pagination.prevText": "上一頁",
+	"uni-pagination.nextText": "下一頁",
+	"uni-pagination.piecePerPage": "條/頁"
 }
 }

+ 459 - 459
uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue

@@ -1,465 +1,465 @@
-<template>
-	<view class="uni-pagination">
-		<!-- #ifndef MP -->
-		<picker v-if="showPageSize === true || showPageSize === 'true'" class="select-picker" mode="selector"
-			:value="pageSizeIndex" :range="pageSizeRange" @change="pickerChange" @cancel="pickerClick"
-			@click.native="pickerClick">
-			<button type="default" size="mini" :plain="true">
-				<text>{{pageSizeRange[pageSizeIndex]}} {{piecePerPage}}</text>
-				<uni-icons class="select-picker-icon" type="arrowdown" size="12" color="#999"></uni-icons>
-			</button>
-		</picker>
-		<!-- #endif -->
-		<!-- #ifndef APP-NVUE -->
-		<view class="uni-pagination__total is-phone-hide">共 {{ total }} 条</view>
-		<!-- #endif -->
-		<view class="uni-pagination__btn"
-			:class="currentIndex === 1 ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
-			:hover-class="currentIndex === 1 ? '' : 'uni-pagination--hover'" :hover-start-time="20"
-			:hover-stay-time="70" @click="clickLeft">
-			<template v-if="showIcon === true || showIcon === 'true'">
-				<uni-icons color="#666" size="16" type="left" />
-			</template>
-			<template v-else>
-				<text class="uni-pagination__child-btn">{{ prevPageText }}</text>
-			</template>
-		</view>
-		<view class="uni-pagination__num uni-pagination__num-flex-none">
-			<view class="uni-pagination__num-current">
-				<text class="uni-pagination__num-current-text is-pc-hide current-index-text">{{ currentIndex }}</text>
-				<text class="uni-pagination__num-current-text is-pc-hide">/{{ maxPage || 0 }}</text>
-				<!-- #ifndef APP-NVUE -->
-				<view v-for="(item, index) in paper" :key="index" :class="{ 'page--active': item === currentIndex }"
-					class="uni-pagination__num-tag tag--active is-phone-hide" @click.top="selectPage(item, index)">
-					<text>{{ item }}</text>
-				</view>
-				<!-- #endif -->
-
-			</view>
-		</view>
-		<view class="uni-pagination__btn"
-			:class="currentIndex >= maxPage ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
-			:hover-class="currentIndex === maxPage ? '' : 'uni-pagination--hover'" :hover-start-time="20"
-			:hover-stay-time="70" @click="clickRight">
-			<template v-if="showIcon === true || showIcon === 'true'">
-				<uni-icons color="#666" size="16" type="right" />
-			</template>
-			<template v-else>
-				<text class="uni-pagination__child-btn">{{ nextPageText }}</text>
-			</template>
-		</view>
-	</view>
-</template>
-
-<script>
-	/**
-	 * Pagination 分页器
-	 * @description 分页器组件,用于展示页码、请求数据等
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=32
-	 * @property {String} prevText 左侧按钮文字
-	 * @property {String} nextText 右侧按钮文字
-	 * @property {String} piecePerPageText 条/页文字
-	 * @property {Number} current 当前页
-	 * @property {Number} total 数据总量
-	 * @property {Number} pageSize 每页数据量
-	 * @property {Boolean} showIcon = [true|false] 是否以 icon 形式展示按钮
-	 * @property {Boolean} showPageSize = [true|false] 是否展示每页条数
-	 * @property {Array} pageSizeRange = [20, 50, 100, 500] 每页条数选框
-	 * @event {Function} change 点击页码按钮时触发 ,e={type,current} current为当前页,type值为:next/prev,表示点击的是上一页还是下一个
-	 * * @event {Function} pageSizeChange 当前每页条数改变时触发 ,e={pageSize} pageSize 为当前所选的每页条数
-	 */
-
-	import {
-		initVueI18n
-	} from '@dcloudio/uni-i18n'
-	import messages from './i18n/index.js'
-	const {
-		t
-	} = initVueI18n(messages)
-	export default {
-		name: 'UniPagination',
-		emits: ['update:modelValue', 'input', 'change', 'pageSizeChange'],
-		props: {
-			value: {
-				type: [Number, String],
-				default: 1
-			},
-			modelValue: {
-				type: [Number, String],
-				default: 1
-			},
-			prevText: {
-				type: String,
-			},
-			nextText: {
-				type: String,
-			},
-			piecePerPageText: {
-				type: String
-			},
-			current: {
-				type: [Number, String],
-				default: 1
-			},
-			total: {
-				// 数据总量
-				type: [Number, String],
-				default: 0
-			},
-			pageSize: {
-				// 每页数据量
-				type: [Number, String],
-				default: 10
-			},
-			showIcon: {
-				// 是否以 icon 形式展示按钮
-				type: [Boolean, String],
-				default: false
-			},
-			showPageSize: {
-				// 是否以 icon 形式展示按钮
-				type: [Boolean, String],
-				default: false
-			},
-			pagerCount: {
-				type: Number,
-				default: 7
-			},
-			pageSizeRange: {
-				type: Array,
-				default: () => [20, 50, 100, 500]
-			}
-		},
-		data() {
-			return {
-				pageSizeIndex: 0,
-				currentIndex: 1,
-				paperData: [],
-				pickerShow: false
-			}
-		},
-		computed: {
-			piecePerPage() {
-				return this.piecePerPageText || t('uni-pagination.piecePerPage')
-			},
-			prevPageText() {
-				return this.prevText || t('uni-pagination.prevText')
-			},
-			nextPageText() {
-				return this.nextText || t('uni-pagination.nextText')
-			},
-			maxPage() {
-				let maxPage = 1
-				let total = Number(this.total)
-				let pageSize = Number(this.pageSize)
-				if (total && pageSize) {
-					maxPage = Math.ceil(total / pageSize)
-				}
-				return maxPage
-			},
-			paper() {
-				const num = this.currentIndex
-				// TODO 最大页数
-				const pagerCount = this.pagerCount
-				// const total = 181
-				const total = this.total
-				const pageSize = this.pageSize
-				let totalArr = []
-				let showPagerArr = []
-				let pagerNum = Math.ceil(total / pageSize)
-				for (let i = 0; i < pagerNum; i++) {
-					totalArr.push(i + 1)
-				}
-				showPagerArr.push(1)
-				const totalNum = totalArr[totalArr.length - (pagerCount + 1) / 2]
-				totalArr.forEach((item, index) => {
-					if ((pagerCount + 1) / 2 >= num) {
-						if (item < pagerCount + 1 && item > 1) {
-							showPagerArr.push(item)
-						}
-					} else if (num + 2 <= totalNum) {
-						if (item > num - (pagerCount + 1) / 2 && item < num + (pagerCount + 1) / 2) {
-							showPagerArr.push(item)
-						}
-					} else {
-						if ((item > num - (pagerCount + 1) / 2 || pagerNum - pagerCount < item) && item < totalArr[
-								totalArr.length - 1]) {
-							showPagerArr.push(item)
-						}
-					}
-				})
-				if (pagerNum > pagerCount) {
-					if ((pagerCount + 1) / 2 >= num) {
-						showPagerArr[showPagerArr.length - 1] = '...'
-					} else if (num + 2 <= totalNum) {
-						showPagerArr[1] = '...'
-						showPagerArr[showPagerArr.length - 1] = '...'
-					} else {
-						showPagerArr[1] = '...'
-					}
-					showPagerArr.push(totalArr[totalArr.length - 1])
-				} else {
-					if ((pagerCount + 1) / 2 >= num) {} else if (num + 2 <= totalNum) {} else {
-						showPagerArr.shift()
-						showPagerArr.push(totalArr[totalArr.length - 1])
-					}
-				}
-
-				return showPagerArr
-			}
-		},
-		watch: {
-			current: {
-				immediate: true,
-				handler(val, old) {
-					if (val < 1) {
-						this.currentIndex = 1
-					} else {
-						this.currentIndex = val
-					}
-				}
-			},
-			value: {
-				immediate: true,
-				handler(val) {
-					if (Number(this.current) !== 1) return
-					if (val < 1) {
-						this.currentIndex = 1
-					} else {
-						this.currentIndex = val
-					}
-				}
-			},
-			pageSizeIndex(val) {
-				this.$emit('pageSizeChange', this.pageSizeRange[val])
-			}
-		},
-		methods: {
-			pickerChange(e) {
-				this.pageSizeIndex = e.detail.value
-				this.pickerClick()
-			},
-			pickerClick() {
-				// #ifdef H5
-				const body = document.querySelector('body')
-				if (!body) return
-
-				const className = 'uni-pagination-picker-show'
-				this.pickerShow = !this.pickerShow
-
-				if (this.pickerShow) {
-					body.classList.add(className)
-				} else {
-					setTimeout(() => body.classList.remove(className), 300)
-				}
-				// #endif
-			},
-			// 选择标签
-			selectPage(e, index) {
-				if (parseInt(e)) {
-					this.currentIndex = e
-					this.change('current')
-				} else {
-					let pagerNum = Math.ceil(this.total / this.pageSize)
-					// let pagerNum = Math.ceil(181 / this.pageSize)
-					// 上一页
-					if (index <= 1) {
-						if (this.currentIndex - 5 > 1) {
-							this.currentIndex -= 5
-						} else {
-							this.currentIndex = 1
-						}
-						return
-					}
-					// 下一页
-					if (index >= 6) {
-						if (this.currentIndex + 5 > pagerNum) {
-							this.currentIndex = pagerNum
-						} else {
-							this.currentIndex += 5
-						}
-						return
-					}
-				}
-			},
-			clickLeft() {
-				if (Number(this.currentIndex) === 1) {
-					return
-				}
-				this.currentIndex -= 1
-				this.change('prev')
-			},
-			clickRight() {
-				if (Number(this.currentIndex) >= this.maxPage) {
-					return
-				}
-				this.currentIndex += 1
-				this.change('next')
-			},
-			change(e) {
-				this.$emit('input', this.currentIndex)
-				this.$emit('update:modelValue', this.currentIndex)
-				this.$emit('change', {
-					type: e,
-					current: this.currentIndex
-				})
-			}
-		}
-	}
-</script>
-
+<template>
+	<view class="uni-pagination">
+		<!-- #ifndef MP -->
+		<picker v-if="showPageSize === true || showPageSize === 'true'" class="select-picker" mode="selector"
+			:value="pageSizeIndex" :range="pageSizeRange" @change="pickerChange" @cancel="pickerClick"
+			@click.native="pickerClick">
+			<button type="default" size="mini" :plain="true">
+				<text>{{pageSizeRange[pageSizeIndex]}} {{piecePerPage}}</text>
+				<uni-icons class="select-picker-icon" type="arrowdown" size="12" color="#999"></uni-icons>
+			</button>
+		</picker>
+		<!-- #endif -->
+		<!-- #ifndef APP-NVUE -->
+		<view class="uni-pagination__total is-phone-hide">共 {{ total }} 条</view>
+		<!-- #endif -->
+		<view class="uni-pagination__btn"
+			:class="currentIndex === 1 ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
+			:hover-class="currentIndex === 1 ? '' : 'uni-pagination--hover'" :hover-start-time="20"
+			:hover-stay-time="70" @click="clickLeft">
+			<template v-if="showIcon === true || showIcon === 'true'">
+				<uni-icons color="#666" size="16" type="left" />
+			</template>
+			<template v-else>
+				<text class="uni-pagination__child-btn">{{ prevPageText }}</text>
+			</template>
+		</view>
+		<view class="uni-pagination__num uni-pagination__num-flex-none">
+			<view class="uni-pagination__num-current">
+				<text class="uni-pagination__num-current-text is-pc-hide current-index-text">{{ currentIndex }}</text>
+				<text class="uni-pagination__num-current-text is-pc-hide">/{{ maxPage || 0 }}</text>
+				<!-- #ifndef APP-NVUE -->
+				<view v-for="(item, index) in paper" :key="index" :class="{ 'page--active': item === currentIndex }"
+					class="uni-pagination__num-tag tag--active is-phone-hide" @click.top="selectPage(item, index)">
+					<text>{{ item }}</text>
+				</view>
+				<!-- #endif -->
+
+			</view>
+		</view>
+		<view class="uni-pagination__btn"
+			:class="currentIndex >= maxPage ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
+			:hover-class="currentIndex === maxPage ? '' : 'uni-pagination--hover'" :hover-start-time="20"
+			:hover-stay-time="70" @click="clickRight">
+			<template v-if="showIcon === true || showIcon === 'true'">
+				<uni-icons color="#666" size="16" type="right" />
+			</template>
+			<template v-else>
+				<text class="uni-pagination__child-btn">{{ nextPageText }}</text>
+			</template>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Pagination 分页器
+	 * @description 分页器组件,用于展示页码、请求数据等
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=32
+	 * @property {String} prevText 左侧按钮文字
+	 * @property {String} nextText 右侧按钮文字
+	 * @property {String} piecePerPageText 条/页文字
+	 * @property {Number} current 当前页
+	 * @property {Number} total 数据总量
+	 * @property {Number} pageSize 每页数据量
+	 * @property {Boolean} showIcon = [true|false] 是否以 icon 形式展示按钮
+	 * @property {Boolean} showPageSize = [true|false] 是否展示每页条数
+	 * @property {Array} pageSizeRange = [20, 50, 100, 500] 每页条数选框
+	 * @event {Function} change 点击页码按钮时触发 ,e={type,current} current为当前页,type值为:next/prev,表示点击的是上一页还是下一个
+	 * * @event {Function} pageSizeChange 当前每页条数改变时触发 ,e={pageSize} pageSize 为当前所选的每页条数
+	 */
+
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {
+		t
+	} = initVueI18n(messages)
+	export default {
+		name: 'UniPagination',
+		emits: ['update:modelValue', 'input', 'change', 'pageSizeChange'],
+		props: {
+			value: {
+				type: [Number, String],
+				default: 1
+			},
+			modelValue: {
+				type: [Number, String],
+				default: 1
+			},
+			prevText: {
+				type: String,
+			},
+			nextText: {
+				type: String,
+			},
+			piecePerPageText: {
+				type: String
+			},
+			current: {
+				type: [Number, String],
+				default: 1
+			},
+			total: {
+				// 数据总量
+				type: [Number, String],
+				default: 0
+			},
+			pageSize: {
+				// 每页数据量
+				type: [Number, String],
+				default: 10
+			},
+			showIcon: {
+				// 是否以 icon 形式展示按钮
+				type: [Boolean, String],
+				default: false
+			},
+			showPageSize: {
+				// 是否以 icon 形式展示按钮
+				type: [Boolean, String],
+				default: false
+			},
+			pagerCount: {
+				type: Number,
+				default: 7
+			},
+			pageSizeRange: {
+				type: Array,
+				default: () => [20, 50, 100, 500]
+			}
+		},
+		data() {
+			return {
+				pageSizeIndex: 0,
+				currentIndex: 1,
+				paperData: [],
+				pickerShow: false
+			}
+		},
+		computed: {
+			piecePerPage() {
+				return this.piecePerPageText || t('uni-pagination.piecePerPage')
+			},
+			prevPageText() {
+				return this.prevText || t('uni-pagination.prevText')
+			},
+			nextPageText() {
+				return this.nextText || t('uni-pagination.nextText')
+			},
+			maxPage() {
+				let maxPage = 1
+				let total = Number(this.total)
+				let pageSize = Number(this.pageSize)
+				if (total && pageSize) {
+					maxPage = Math.ceil(total / pageSize)
+				}
+				return maxPage
+			},
+			paper() {
+				const num = this.currentIndex
+				// TODO 最大页数
+				const pagerCount = this.pagerCount
+				// const total = 181
+				const total = this.total
+				const pageSize = this.pageSize
+				let totalArr = []
+				let showPagerArr = []
+				let pagerNum = Math.ceil(total / pageSize)
+				for (let i = 0; i < pagerNum; i++) {
+					totalArr.push(i + 1)
+				}
+				showPagerArr.push(1)
+				const totalNum = totalArr[totalArr.length - (pagerCount + 1) / 2]
+				totalArr.forEach((item, index) => {
+					if ((pagerCount + 1) / 2 >= num) {
+						if (item < pagerCount + 1 && item > 1) {
+							showPagerArr.push(item)
+						}
+					} else if (num + 2 <= totalNum) {
+						if (item > num - (pagerCount + 1) / 2 && item < num + (pagerCount + 1) / 2) {
+							showPagerArr.push(item)
+						}
+					} else {
+						if ((item > num - (pagerCount + 1) / 2 || pagerNum - pagerCount < item) && item < totalArr[
+								totalArr.length - 1]) {
+							showPagerArr.push(item)
+						}
+					}
+				})
+				if (pagerNum > pagerCount) {
+					if ((pagerCount + 1) / 2 >= num) {
+						showPagerArr[showPagerArr.length - 1] = '...'
+					} else if (num + 2 <= totalNum) {
+						showPagerArr[1] = '...'
+						showPagerArr[showPagerArr.length - 1] = '...'
+					} else {
+						showPagerArr[1] = '...'
+					}
+					showPagerArr.push(totalArr[totalArr.length - 1])
+				} else {
+					if ((pagerCount + 1) / 2 >= num) {} else if (num + 2 <= totalNum) {} else {
+						showPagerArr.shift()
+						showPagerArr.push(totalArr[totalArr.length - 1])
+					}
+				}
+
+				return showPagerArr
+			}
+		},
+		watch: {
+			current: {
+				immediate: true,
+				handler(val, old) {
+					if (val < 1) {
+						this.currentIndex = 1
+					} else {
+						this.currentIndex = val
+					}
+				}
+			},
+			value: {
+				immediate: true,
+				handler(val) {
+					if (Number(this.current) !== 1) return
+					if (val < 1) {
+						this.currentIndex = 1
+					} else {
+						this.currentIndex = val
+					}
+				}
+			},
+			pageSizeIndex(val) {
+				this.$emit('pageSizeChange', this.pageSizeRange[val])
+			}
+		},
+		methods: {
+			pickerChange(e) {
+				this.pageSizeIndex = e.detail.value
+				this.pickerClick()
+			},
+			pickerClick() {
+				// #ifdef H5
+				const body = document.querySelector('body')
+				if (!body) return
+
+				const className = 'uni-pagination-picker-show'
+				this.pickerShow = !this.pickerShow
+
+				if (this.pickerShow) {
+					body.classList.add(className)
+				} else {
+					setTimeout(() => body.classList.remove(className), 300)
+				}
+				// #endif
+			},
+			// 选择标签
+			selectPage(e, index) {
+				if (parseInt(e)) {
+					this.currentIndex = e
+					this.change('current')
+				} else {
+					let pagerNum = Math.ceil(this.total / this.pageSize)
+					// let pagerNum = Math.ceil(181 / this.pageSize)
+					// 上一页
+					if (index <= 1) {
+						if (this.currentIndex - 5 > 1) {
+							this.currentIndex -= 5
+						} else {
+							this.currentIndex = 1
+						}
+						return
+					}
+					// 下一页
+					if (index >= 6) {
+						if (this.currentIndex + 5 > pagerNum) {
+							this.currentIndex = pagerNum
+						} else {
+							this.currentIndex += 5
+						}
+						return
+					}
+				}
+			},
+			clickLeft() {
+				if (Number(this.currentIndex) === 1) {
+					return
+				}
+				this.currentIndex -= 1
+				this.change('prev')
+			},
+			clickRight() {
+				if (Number(this.currentIndex) >= this.maxPage) {
+					return
+				}
+				this.currentIndex += 1
+				this.change('next')
+			},
+			change(e) {
+				this.$emit('input', this.currentIndex)
+				this.$emit('update:modelValue', this.currentIndex)
+				this.$emit('change', {
+					type: e,
+					current: this.currentIndex
+				})
+			}
+		}
+	}
+</script>
+
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-	$uni-primary: #2979ff !default;
-	.uni-pagination {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		position: relative;
-		overflow: hidden;
-		flex-direction: row;
-		justify-content: center;
-		align-items: center;
-	}
-
-	.uni-pagination__total {
-		font-size: 14px;
-		color: #999;
-		margin-right: 15px;
-	}
-
-	.uni-pagination__btn {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		cursor: pointer;
-		/* #endif */
-		padding: 0 8px;
-		line-height: 30px;
-		font-size: 12px;
-		position: relative;
-		background-color: #F0F0F0;
-		flex-direction: row;
-		justify-content: center;
-		align-items: center;
-		text-align: center;
-		border-radius: 5px;
-		// border-width: 1px;
-		// border-style: solid;
-		// border-color: $uni-border-color;
-	}
-
-	.uni-pagination__child-btn {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		font-size: 12px;
-		position: relative;
-		flex-direction: row;
-		justify-content: center;
-		align-items: center;
-		text-align: center;
-		color: #666;
-		font-size: 12px;
-	}
-
-	.uni-pagination__num {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex: 1;
-		flex-direction: row;
-		justify-content: center;
-		align-items: center;
-		height: 30px;
-		line-height: 30px;
-		font-size: 12px;
-		color: #666;
-		margin: 0 5px;
-	}
-
-	.uni-pagination__num-tag {
-		/* #ifdef H5 */
-		cursor: pointer;
-		min-width: 30px;
-		/* #endif */
-		margin: 0 5px;
-		height: 30px;
-		text-align: center;
-		line-height: 30px;
-		// border: 1px red solid;
-		color: #999;
-		border-radius: 4px;
-		// border-width: 1px;
-		// border-style: solid;
-		// border-color: $uni-border-color;
-	}
-
-	.uni-pagination__num-current {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		/* #endif */
-		flex-direction: row;
-	}
-
-	.uni-pagination__num-current-text {
-		font-size: 15px;
+	$uni-primary: #2979ff !default;
+	.uni-pagination {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		position: relative;
+		overflow: hidden;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-pagination__total {
+		font-size: 14px;
+		color: #999;
+		margin-right: 15px;
+	}
+
+	.uni-pagination__btn {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		cursor: pointer;
+		/* #endif */
+		padding: 0 8px;
+		line-height: 30px;
+		font-size: 12px;
+		position: relative;
+		background-color: #F0F0F0;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		text-align: center;
+		border-radius: 5px;
+		// border-width: 1px;
+		// border-style: solid;
+		// border-color: $uni-border-color;
+	}
+
+	.uni-pagination__child-btn {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		font-size: 12px;
+		position: relative;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		text-align: center;
+		color: #666;
+		font-size: 12px;
+	}
+
+	.uni-pagination__num {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		height: 30px;
+		line-height: 30px;
+		font-size: 12px;
+		color: #666;
+		margin: 0 5px;
+	}
+
+	.uni-pagination__num-tag {
+		/* #ifdef H5 */
+		cursor: pointer;
+		min-width: 30px;
+		/* #endif */
+		margin: 0 5px;
+		height: 30px;
+		text-align: center;
+		line-height: 30px;
+		// border: 1px red solid;
+		color: #999;
+		border-radius: 4px;
+		// border-width: 1px;
+		// border-style: solid;
+		// border-color: $uni-border-color;
+	}
+
+	.uni-pagination__num-current {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-pagination__num-current-text {
+		font-size: 15px;
 	}
 	}
 
 
 	.current-index-text{
 	.current-index-text{
 		color: $uni-primary;
 		color: $uni-primary;
-	}
-
-	.uni-pagination--enabled {
-		color: #333333;
-		opacity: 1;
-	}
-
-	.uni-pagination--disabled {
-		opacity: 0.5;
-		/* #ifdef H5 */
-		cursor: default;
-		/* #endif */
-	}
-
-	.uni-pagination--hover {
-		color: rgba(0, 0, 0, 0.6);
-		background-color: #eee;
-	}
-
-	.tag--active:hover {
-		color: $uni-primary;
-	}
-
-	.page--active {
-		color: #fff;
-		background-color: $uni-primary;
-	}
-
-	.page--active:hover {
-		color: #fff;
-	}
-
-	/* #ifndef APP-NVUE */
-	.is-pc-hide {
-		display: block;
-	}
-
-	.is-phone-hide {
-		display: none;
-	}
-
-	@media screen and (min-width: 450px) {
-		.is-pc-hide {
-			display: none;
-		}
-
-		.is-phone-hide {
-			display: block;
-		}
-
-		.uni-pagination__num-flex-none {
-			flex: none;
-		}
-	}
-
-	/* #endif */
+	}
+
+	.uni-pagination--enabled {
+		color: #333333;
+		opacity: 1;
+	}
+
+	.uni-pagination--disabled {
+		opacity: 0.5;
+		/* #ifdef H5 */
+		cursor: default;
+		/* #endif */
+	}
+
+	.uni-pagination--hover {
+		color: rgba(0, 0, 0, 0.6);
+		background-color: #eee;
+	}
+
+	.tag--active:hover {
+		color: $uni-primary;
+	}
+
+	.page--active {
+		color: #fff;
+		background-color: $uni-primary;
+	}
+
+	.page--active:hover {
+		color: #fff;
+	}
+
+	/* #ifndef APP-NVUE */
+	.is-pc-hide {
+		display: block;
+	}
+
+	.is-phone-hide {
+		display: none;
+	}
+
+	@media screen and (min-width: 450px) {
+		.is-pc-hide {
+			display: none;
+		}
+
+		.is-phone-hide {
+			display: block;
+		}
+
+		.uni-pagination__num-flex-none {
+			flex: none;
+		}
+	}
+
+	/* #endif */
 </style>
 </style>

+ 82 - 82
uni_modules/uni-pagination/package.json

@@ -1,83 +1,83 @@
-{
-  "id": "uni-pagination",
-  "displayName": "uni-pagination 分页器",
-  "version": "1.2.4",
-  "description": "Pagination 分页器组件,用于展示页码、请求数据等。",
-  "keywords": [
-    "uni-ui",
-    "uniui",
-    "分页器",
-    "页码"
-],
-  "repository": "https://github.com/dcloudio/uni-ui",
-  "engines": {
-    "HBuilderX": ""
-  },
-  "directories": {
-    "example": "../../temps/example_temps"
-  },
-"dcloudext": {
-    "sale": {
-      "regular": {
-        "price": "0.00"
-      },
-      "sourcecode": {
-        "price": "0.00"
-      }
-    },
-    "contact": {
-      "qq": ""
-    },
-    "declaration": {
-      "ads": "无",
-      "data": "无",
-      "permissions": "无"
-    },
-    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
-    "type": "component-vue"
-  },
-  "uni_modules": {
-    "dependencies": ["uni-scss","uni-icons"],
-    "encrypt": [],
-    "platforms": {
-      "cloud": {
-        "tcb": "y",
-        "aliyun": "y"
-      },
-      "client": {
-        "App": {
-          "app-vue": "y",
-          "app-nvue": "y"
-        },
-        "H5-mobile": {
-          "Safari": "y",
-          "Android Browser": "y",
-          "微信浏览器(Android)": "y",
-          "QQ浏览器(Android)": "y"
-        },
-        "H5-pc": {
-          "Chrome": "y",
-          "IE": "y",
-          "Edge": "y",
-          "Firefox": "y",
-          "Safari": "y"
-        },
-        "小程序": {
-          "微信": "y",
-          "阿里": "y",
-          "百度": "y",
-          "字节跳动": "y",
-          "QQ": "y"
-        },
-        "快应用": {
-          "华为": "u",
-          "联盟": "u"
-        },
-        "Vue": {
-            "vue2": "y",
-            "vue3": "y"
-        }
-      }
-    }
-  }
+{
+  "id": "uni-pagination",
+  "displayName": "uni-pagination 分页器",
+  "version": "1.2.4",
+  "description": "Pagination 分页器组件,用于展示页码、请求数据等。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "分页器",
+    "页码"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss","uni-icons"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
 }
 }

+ 0 - 0
uni_modules/uni-pagination/readme.md


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