浏览代码

登录页、我的页面

zhangyuanyuan2022 1 年之前
当前提交
1f3b7bb528
共有 100 个文件被更改,包括 4130 次插入0 次删除
  1. 26 0
      .hbuilderx/launch.json
  2. 23 0
      App.vue
  3. 24 0
      api/apiConfig.js
  4. 35 0
      api/item.js
  5. 47 0
      api/login.js
  6. 20 0
      index.html
  7. 30 0
      main.js
  8. 72 0
      manifest.json
  9. 109 0
      pages.json
  10. 305 0
      pages/component/appUpdate.vue
  11. 4 0
      pages/home/home.scss
  12. 22 0
      pages/home/home.vue
  13. 52 0
      pages/index/index.vue
  14. 42 0
      pages/login/JudeLoginPage.vue
  15. 154 0
      pages/login/login.vue
  16. 124 0
      pages/myCenter/myCenter.scss
  17. 151 0
      pages/myCenter/myCenter.vue
  18. 42 0
      pages/myCenter/setting.vue
  19. 3 0
      pages/newsCenter/newsIndex.scss
  20. 23 0
      pages/newsCenter/newsIndex.vue
  21. 3 0
      pages/typeList/typeList.scss
  22. 23 0
      pages/typeList/typeList.vue
  23. 二进制
      static/login/1.jpg
  24. 二进制
      static/login/AYN.png
  25. 二进制
      static/login/bg3.jpg
  26. 二进制
      static/login/bg4.jpg
  27. 二进制
      static/login/bg5.jpg
  28. 二进制
      static/login/登录bg.jpg
  29. 二进制
      static/myCenter/1.jpg
  30. 二进制
      static/myCenter/2.jpg
  31. 二进制
      static/myCenter/3.jpg
  32. 二进制
      static/myCenter/4.jpg
  33. 二进制
      static/myCenter/5.jpg
  34. 二进制
      static/myCenter/aiDiscern.png
  35. 二进制
      static/myCenter/caigoujuece.png
  36. 二进制
      static/myCenter/companyManager.png
  37. 二进制
      static/myCenter/daicai.png
  38. 二进制
      static/myCenter/daikou.png
  39. 二进制
      static/myCenter/fenxiao.png
  40. 二进制
      static/myCenter/fenxiaozhongxin.png
  41. 二进制
      static/myCenter/jifen.png
  42. 二进制
      static/myCenter/milkPrice.png
  43. 二进制
      static/myCenter/myData.png
  44. 二进制
      static/myCenter/mykefu.png
  45. 二进制
      static/myCenter/niuke.png
  46. 二进制
      static/myCenter/niunaihua.png
  47. 二进制
      static/myCenter/niuxin.png
  48. 二进制
      static/myCenter/piliang.png
  49. 二进制
      static/myCenter/pingan.png
  50. 二进制
      static/myCenter/pingtuan.png
  51. 二进制
      static/myCenter/puhuicundan.png
  52. 二进制
      static/myCenter/qingzhu.png
  53. 二进制
      static/myCenter/suiyicun.png
  54. 二进制
      static/myCenter/video.png
  55. 二进制
      static/myCenter/wodequanyyi.png
  56. 二进制
      static/myCenter/youhuiquan.png
  57. 二进制
      static/myCenter/yudin.png
  58. 二进制
      static/myCenter/yushou.png
  59. 二进制
      static/myCenter/zhangqi.png
  60. 二进制
      static/nav/nav_ico1.png
  61. 二进制
      static/nav/nav_ico10.png
  62. 二进制
      static/nav/nav_ico2.png
  63. 二进制
      static/nav/nav_ico3.png
  64. 二进制
      static/nav/nav_ico4.png
  65. 二进制
      static/nav/nav_ico5.png
  66. 二进制
      static/nav/nav_ico6.png
  67. 二进制
      static/nav/nav_ico7.png
  68. 二进制
      static/nav/nav_ico8.png
  69. 二进制
      static/nav/nav_ico9.png
  70. 二进制
      static/tabBar/fenlei_1.png
  71. 二进制
      static/tabBar/gouwuche.png
  72. 二进制
      static/tabBar/shouye.png
  73. 二进制
      static/tabBar/tabbar/fenlei_1.png
  74. 二进制
      static/tabBar/tabbar/gouwuche.png
  75. 二进制
      static/tabBar/tabbar/shouye.png
  76. 二进制
      static/tabBar/tabbar/wode.png
  77. 二进制
      static/tabBar/wode.png
  78. 27 0
      style/iconfont/iconfont.css
  79. 79 0
      uni.scss
  80. 17 0
      uni_modules/custom-waterfalls-flow/changelog.md
  81. 321 0
      uni_modules/custom-waterfalls-flow/components/custom-waterfalls-flow/custom-waterfalls-flow.vue
  82. 81 0
      uni_modules/custom-waterfalls-flow/package.json
  83. 445 0
      uni_modules/custom-waterfalls-flow/readme.md
  84. 21 0
      uni_modules/uview-ui/LICENSE
  85. 66 0
      uni_modules/uview-ui/README.md
  86. 357 0
      uni_modules/uview-ui/changelog.md
  87. 78 0
      uni_modules/uview-ui/components/u--form/u--form.vue
  88. 47 0
      uni_modules/uview-ui/components/u--image/u--image.vue
  89. 73 0
      uni_modules/uview-ui/components/u--input/u--input.vue
  90. 44 0
      uni_modules/uview-ui/components/u--text/u--text.vue
  91. 48 0
      uni_modules/uview-ui/components/u--textarea/u--textarea.vue
  92. 54 0
      uni_modules/uview-ui/components/u-action-sheet/props.js
  93. 278 0
      uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue
  94. 59 0
      uni_modules/uview-ui/components/u-album/props.js
  95. 259 0
      uni_modules/uview-ui/components/u-album/u-album.vue
  96. 44 0
      uni_modules/uview-ui/components/u-alert/props.js
  97. 243 0
      uni_modules/uview-ui/components/u-alert/u-alert.vue
  98. 52 0
      uni_modules/uview-ui/components/u-avatar-group/props.js
  99. 103 0
      uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue
  100. 0 0
      uni_modules/uview-ui/components/u-avatar/props.js

+ 26 - 0
.hbuilderx/launch.json

@@ -0,0 +1,26 @@
+{
+    // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+    // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version" : "0.0",
+    "configurations" : [
+        {
+        	"app-plus" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"default" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"mp-weixin" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"type" : "uniCloud"
+        },
+        {
+            "playground" : "standard",
+            "type" : "uni-app:app-android"
+        }
+    ]
+}

+ 23 - 0
App.vue

@@ -0,0 +1,23 @@
+<script>
+  import * as initPermission from '@/utils/permission.js'
+	export default {
+		onLaunch: function() {
+      // 拦截器
+      initPermission
+			console.log('App Launch')
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style lang="scss">
+	/*每个页面公共css */
+	@import 'style/iconfont/iconfont.css';
+	// 引入uView基础公共样式
+	@import "@/uni_modules/uview-ui/index.scss";
+</style>

+ 24 - 0
api/apiConfig.js

@@ -0,0 +1,24 @@
+const env = 'production' // 开发环境deveploment  生产环境production
+
+/**
+ * items   : 商品信息相关业务
+ */
+const api = {
+  // 开发环境
+  dev: {
+    items: 'http://items.aiyangniu.net',
+    cow: 'http://cow.aiyangniu.net',
+    user: 'http://account2.aiyangniu.net'
+  },
+  // 生产环境
+  pro: {
+	  items: 'http://items.aiyangniu.cn',
+    cow: 'http://cow.aiyangniu.net',
+    user: 'http://account.aiyangniu.net'
+  }
+}
+
+module.exports = {
+  api: env === 'deveploment' ? api.dev : api.pro,
+  env,
+}

+ 35 - 0
api/item.js

@@ -0,0 +1,35 @@
+/**
+ * 商品相关API
+ */
+import {http} from '@/utils/request';
+import {api} from './apiConfig'
+
+/**
+ * 获取商品sku列表
+ * @param goods_id
+ */
+export function getGoodsList(params) {
+  return http.middleware({
+    url: `${api.cow}/cattleItem/getCattleItemPage`,
+    custom:{
+      isJson:true
+    },
+    params:params,
+    method: 'GET',
+  })
+}
+
+/**
+ * 获取热线上更新json文件
+ * @param uploadUrl
+ */
+export function getUpdateJson(params) {
+  return http.middleware({
+    url: "http://m.aiyangniu.cn/testjson.json?t=" + new Date().valueOf(),
+    custom:{
+      isJson:true
+    },
+    params:params,
+    method: 'GET',
+  })
+}

+ 47 - 0
api/login.js

@@ -0,0 +1,47 @@
+/**
+ * 登录相关API
+ */
+import {http} from '@/utils/request';
+import {api} from './apiConfig'
+
+/**
+ * 登录
+ *
+ */
+export function GetUserToken(params) {
+  return http.middleware({
+    url: `${api.user}/users/login`,
+    custom:{
+      isJson:true
+    },
+    params:params,
+    method: 'POST',
+  })
+}
+/**
+ * 获取用户信息
+ *
+ */
+export function GetUserInfo() {
+  return http.middleware({
+    url: `${api.user}/users/user`,
+    custom:{
+      isJson:true
+    },
+    method: 'GET',
+  })
+}
+/**
+ * 退出登录
+ *
+ */
+export function logout(params) {
+  return http.middleware({
+    url: `${api.user}/users/logout`,
+    custom:{
+      isJson:true
+    },
+    params:params,
+    method: 'GET',
+  })
+}

+ 20 - 0
index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <script>
+      var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+        CSS.supports('top: constant(a)'))
+      document.write(
+        '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+        (coverSupport ? ', viewport-fit=cover' : '') + '" />')
+    </script>
+    <title></title>
+    <!--preload-links-->
+    <!--app-context-->
+  </head>
+  <body>
+    <div id="app"><!--app-html--></div>
+    <script type="module" src="/main.js"></script>
+  </body>
+</html>

+ 30 - 0
main.js

@@ -0,0 +1,30 @@
+import App from './App'
+
+import uView from '@/uni_modules/uview-ui'
+Vue.use(uView)
+
+//进入全局过滤器
+import * as filters from '@/utils/filters.js'
+Object.keys(filters).forEach(key => {
+    Vue.filter(key, filters[key])
+})
+
+// #ifndef VUE3
+import Vue from 'vue'
+Vue.config.productionTip = false
+App.mpType = 'app'
+const app = new Vue({
+    ...App
+})
+app.$mount()
+// #endif
+
+// #ifdef VUE3
+import { createSSRApp } from 'vue'
+export function createApp() {
+  const app = createSSRApp(App)
+  return {
+    app
+  }
+}
+// #endif

+ 72 - 0
manifest.json

@@ -0,0 +1,72 @@
+{
+    "name" : "爱养牛",
+    "appid" : "__UNI__BEC260B",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {},
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {}
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "2"
+}

+ 109 - 0
pages.json

@@ -0,0 +1,109 @@
+{
+	"pages": [
+		//pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+    {
+      "path" : "pages/login/JudeLoginPage",
+      "style" :                                                                                    
+      {
+        "navigationBarTitleText": "",
+        "enablePullDownRefresh": false,
+        "navigationStyle" : "custom"
+      }
+    },
+    {
+    	"path": "pages/home/home",
+			"style": {
+				"navigationStyle": "custom",
+				"enablePullDownRefresh": true,
+				"navigationBarTextStyle": "white"
+			}
+    },
+    {
+    	"path": "pages/login/login",
+    	"style": {
+    		"navigationStyle": "custom",
+    		"enablePullDownRefresh": true,
+    		"navigationBarTextStyle": "white"
+    	}
+    },
+    {
+    	"path" : "pages/myCenter/myCenter",
+    	"style" :                                                                                    
+    	{
+    		"navigationStyle": "custom",
+    		"enablePullDownRefresh": false
+    	}
+    },
+		{
+			"path": "pages/newsCenter/newsIndex",
+			"style": {
+				"navigationStyle": "custom",
+				"enablePullDownRefresh": true,
+				"navigationBarTextStyle": "white"
+			}
+		},
+		{
+			"path": "pages/typeList/typeList",
+			"style": {
+				"navigationStyle": "custom",
+				"enablePullDownRefresh": true,
+				"navigationBarTextStyle": "white"
+			}
+		}
+    ,{
+      "path" : "pages/myCenter/setting",
+      "style" :                                                                                    
+      {
+        "navigationStyle": "custom",
+        "navigationBarTextStyle": "white",
+        "enablePullDownRefresh": false
+      }
+    }
+    ],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "爱养牛",
+		"navigationBarBackgroundColor": "#f6f6f6",
+		"backgroundColor": "#f6f6f6",
+		"backgroundColorTop":"#FFFFFF"
+	},
+	"uniIdRouter": {
+		"loginPage": "pages/login/login"
+	},
+	"tabBar": {
+		"color": "#45474a",
+		"selectedColor": "#00aaff",
+		"borderStyle": "white", 
+		"backgroundColor": "#ffffff",
+		"list": [{
+			"pagePath": "pages/home/home",
+			"iconPath": "static/tabBar/shouye.png",
+			"selectedIconPath": "static/tabBar/tabbar/shouye.png",
+			"text": "首页"
+		},
+		{
+			"pagePath": "pages/typeList/typeList",
+			"iconPath": "static/tabBar/fenlei_1.png",
+			"selectedIconPath": "static/tabBar/tabbar/fenlei_1.png",
+			"text": "分类"
+		},
+    // {
+    // 	"pagePath": "pages/newsCenter/newsIndex",
+    // 	"iconPath": "static/tabBar/xiaoxi.png",
+    // 	"selectedIconPath": "static/tabBar/sel-xiaoxi.png",
+    // 	"text": "牛人慧"
+    // },
+		{
+			"pagePath": "pages/newsCenter/newsIndex",
+			"iconPath": "static/tabBar/gouwuche.png",
+			"selectedIconPath": "static/tabBar/tabbar/gouwuche.png",
+			"text": "购物车"
+		},
+		{
+			"pagePath": "pages/myCenter/myCenter",
+			"iconPath": "static/tabBar/wode.png",
+			"selectedIconPath": "static/tabBar/tabbar/wode.png",
+			"text": "我的"
+		}]
+	}
+}

+ 305 - 0
pages/component/appUpdate.vue

@@ -0,0 +1,305 @@
+<template>
+	<view class="appUpdate">
+		<view>
+			<u-overlay :show="showDownloadState" :opacity="0.7">
+				<view class="warp">
+					<view class="warp_content">
+						<u-line-progress :percentage="parseInt(progressVal)" activeColor="#ff0000"></u-line-progress>
+						<view class="warp_font">{{textLoading2}}</view>
+					</view>
+				</view>
+			</u-overlay>
+		</view>
+	</view>
+</template>
+
+<script>
+	import * as API_item from '@/api/item.js';	
+	export default {
+		props:{
+			
+		},
+		data() {
+			return {
+				showProgress:false,
+				showDownloadState:false,
+				textLoading2:'版本更新中,请稍等...',
+				progressVal: 0,         //进度值
+			}
+		},
+		created() {
+			console.log('页面是读到了');
+			setTimeout(()=>{
+				this.checkUpdate();
+			},20)
+		},
+		methods: {
+			// 版本号对比
+			versionCompare(a, b) {
+				//a>b 返回true
+				console.log('对比版本号了');
+				let res = false;
+				let arrA = a.split(".");
+				let arrB = b.split(".");
+
+				arrA[0] = arrA[0]*1
+				arrA[1] = arrA[1]*1
+				arrA[2] = arrA[2]*1
+
+				arrB[0] = arrB[0]*1
+				arrB[1] = arrB[1]*1
+				arrB[2] = arrB[2]*1
+
+				if (arrA[0] > arrB[0]) {
+					res = true;
+				} else if (arrA[0] == arrB[0] && arrA[1] > arrB[1]) {
+					res = true;
+				}else if(arrA[0] == arrB[0] && arrA[1] == arrB[1] && arrA[2] > arrB[2]){
+					res = true;
+				}
+				return res;
+			},
+
+			// 检查更新
+			checkUpdate(){
+				console.log('开始检查更新了');
+				let _this = this
+				let sys = plus.os.name.toLowerCase();
+				var VERSION
+				plus.runtime.getProperty(plus.runtime.appid, function(inf) {
+					console.log('获取版本号',inf);
+					VERSION = inf.version;
+				})
+				API_item.getUpdateJson().then(function(res){
+					console.log('获取到结果了吗',res);
+					let data = res;
+				    //安装式更新
+					// if (sys == "ios") {                                           
+					//   //版本判断,提示更新
+					//   this.$http.jsonp("http://itunes.apple.com/cn/lookup?id=1232107347")
+					//     .then(
+					//       function(Res) {
+					//         _this.versionCompare(Res.body.results[0].version, VERSION)?  _this.showNeedUpdate('ios',data.isMustUpdate) : void 0
+					//       }
+					//     )
+					// } else 
+					console.log('获取终端机类型',sys);
+					if (sys == "android") {
+						console.log('分别是参数',data.version, VERSION,_this.versionCompare(data.version, VERSION));
+						_this.versionCompare(data.version, VERSION)?  _this.showNeedUpdate('android',data.isMustUpdate,data.packageDown) : void 0
+					}
+				})
+			},
+
+			// 强制更新
+			showNeedUpdate(func,isMust,downUrl){     //isMust 是否必须更新
+				console.log('得强制更新了')
+				let _this = this
+				let connectionStatus = plus.networkinfo.getCurrentType();          //在Ios上获取网络类型正常,但是只能获取app打开之前的网络状态,
+				// 强制退出
+				uni.showModal({
+					title: '更新提示',
+					content: func==='android'?'有新版本,点击更新':'有新版本,点击更新<br><span style="font-size:12px;">(确定后5s自动退出)</span>',
+					confirmText:"立即更新",
+					cancelText:isMust==1?"退出应用":"取消",
+					success:function(res){
+						if (res.confirm) {  //点击了确定更新
+							if(func==='hot'){
+								if(connectionStatus == 2 || connectionStatus == 3){
+									_this.downWgt()
+								}else{
+									_this.$vux.confirm.show({
+										title: '网络提示',
+										content:'您正在使用移动流量,更新大约需20M',
+										confirmText:"打开wifi(免流量)",
+										cancelText:"继续",
+										onCancel () {
+											_this.downWgt()
+										},
+										onConfirm (msg) {
+											_this.openSysSet()
+										
+										}
+									})
+								}
+
+								if(isMust == 1){
+									_this.afterQuit(func) //退出app
+								}
+							}else if(func==='ios'){
+								plus.runtime.openURL("https://itunes.apple.com/cn/app/id1232107347")
+									if(isMust == 1){
+									_this.afterQuit(func) //退出app
+								}
+							}else if(func==='android'){
+								_this.downWgt(downUrl,isMust)
+								
+							}
+						} else if (res.cancel) { //点击了取消
+							if(isMust == 1){
+								if(func === 'ios'){
+									const threadClass = plus.ios.importClass("NSThread");
+									const mainThread = plus.ios.invoke(threadClass, "mainThread");
+									plus.ios.invoke(mainThread, "exit");
+								}else if(func === 'android'){
+									plus.runtime.quit()
+								}
+							}else{
+								void 0
+							}
+						}
+					}
+				})
+			},
+
+			// 下载wgt文件
+			downWgt (downUrl,isMust){
+				console.log('转到下载文件',downUrl,isMust);
+				let _this = this
+				let timer = (new Date).valueOf()
+				let changeTime = 300
+				if(downUrl){
+					// _this.showProgress = true
+					_this.showDownloadState = true
+					var downloader = plus.downloader.createDownload(downUrl)
+					downloader.addEventListener("statechanged", function(dtask,status){
+						console.log('下载得一些状态',dtask,status);
+						if(dtask.state == 4 && status == 200){
+							_this.textLoading2 = "恭喜您,下载成功"
+							uni.showModal({
+								title: '安装提示',
+								content: "下载已完成,是否安装?",
+								confirmText:"立即安装",
+								cancelText:isMust==1?"退出应用":"取消",
+								success:function(res){
+									if (res.confirm) {  //点击了确定更新
+										plus.runtime.openFile(dtask.getFileName());  
+									}else if(res.cancel){
+										if(isMust == 1){
+											plus.runtime.quit()
+										}else{
+											plus.runtime.quit()
+										}
+									}
+								}
+							})
+						}else{
+							switch(dtask.state) {
+								case 1: // 开始
+									_this.textLoading2 = "开始下载..."
+									break;
+								case 2: // 已连接到服务器
+									_this.textLoading2 = "连接到服务器.."
+									break;
+								case 3:    // 已接收到数据
+									let _time = (new Date).valueOf()
+									if(_time-timer>changeTime){
+										timer = _time
+										// _this.showLoading = true
+										_this.progressVal = ((dtask.downloadedSize/dtask.totalSize).toFixed(2)*(100))
+										_this.textLoading2 = "下载更新文件..."
+									}
+									break;
+								case 4:    // 下载完成
+									break;
+							}
+						}
+					})
+					downloader.start();
+				}else if(_this.wgtUrl){
+					var downloader = plus.downloader.createDownload( _this.wgtUrl, {filename:"_doc/update/"}
+					, function(d,status){     //下载完成执行的回调函数
+					if ( status == 200 ) { 
+						// alert("下载wgt成功:"+d.filename);
+						_this.installWgt(d.filename);	// 安装wgt包
+					} else {
+						// console.log("下载wgt失败!");
+						plus.nativeUI.alert("下载wgt失败!");
+					}
+					}
+					)
+					downloader.addEventListener("statechanged", function(dtask,status){
+						if(!dtask){return;}
+						switch(dtask.state) {
+							case 1: // 开始
+								_this.showLoading = true
+								_this.textLoading = "开始下载..."
+							break;
+							case 2: // 已连接到服务器
+							_this.showLoading = true
+								_this.textLoading = "连接到服务器.."
+							break;
+							case 3:    // 已接收到数据
+							let _time = (new Date).valueOf()
+							if(_time-timer>changeTime){
+									timer = _time
+									_this.showLoading = true
+									_this.progressVal = ((dtask.downloadedSize/dtask.totalSize).toFixed(2)*(100))
+									_this.textLoading = "下载更新文件 "+progressVal.substr(0,4)+'%'
+							}
+							break;
+							case 4:    // 下载完成
+							_this.showLoading = false
+							break;
+						}
+					})
+					downloader.start();
+				}else{
+					return false
+				}
+			},
+
+			//打开wifi,用WiFi下载
+			openSysSet(){
+				let sys = plus.os.name.toLowerCase();
+				this.backFromSetWIFI = true
+				if(sys == "ios"){          //操作苹果手机
+					plus.runtime.launchApplication({action:'App-Prefs:root=WIFI'}, function(e){
+					console.log(JSON.stringify(e));
+					}); //WIFI 
+				} else {                  //操作安卓收集
+					var main = plus.android.runtimeMainActivity();
+					var Intent = plus.android.importClass("android.content.Intent");
+					var mIntent = new Intent('android.settings.WIFI_SETTINGS');
+					main.startActivity(mIntent);
+				}
+			},
+
+			// 避免旧版本使用退出
+			afterQuit(func){
+				setTimeout(()=>{
+				if(func==='ios'){
+					const threadClass = plus.ios.importClass("NSThread");
+					const mainThread = plus.ios.invoke(threadClass, "mainThread");
+					plus.ios.invoke(mainThread, "exit");
+				}else if(func==='android'){
+					plus.runtime.quit()
+				}else if(func==='hot'){
+					plus.runtime.quit();
+
+					const threadClass = plus.ios.importClass("NSThread");
+					const mainThread = plus.ios.invoke(threadClass, "mainThread");
+					plus.ios.invoke(mainThread, "exit");
+				}
+				},5000)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+.appUpdate {
+	.warp {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		height: 100%;
+		.warp_content{
+			width: 90%; margin: 0 auto; text-align: center;
+			.warp_font{
+				margin-top: 30rpx; color: #f9f9f9;
+			}
+		}
+	}
+}
+</style>

+ 4 - 0
pages/home/home.scss

@@ -0,0 +1,4 @@
+.homePage{
+	background-color: $uni-bg-color-grey;
+
+}

+ 22 - 0
pages/home/home.vue

@@ -0,0 +1,22 @@
+<template>
+	<view class="homePage">
+		<u-navbar  title="首页" @rightClick="rightClick" :autoBack="true"></u-navbar>
+		<view>123</view>	
+	</view>
+</template>
+<script>
+	import * as API_item from '@/api/item.js';
+	export default {
+		data() {
+			return {
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+@import 'home.scss';
+</style>

+ 52 - 0
pages/index/index.vue

@@ -0,0 +1,52 @@
+<template>
+	<view class="content">
+		<image class="logo" src="/static/logo.png"></image>
+		<view class="text-area">
+			<text class="title">{{title}}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				title: 'Hello'
+			}
+		},
+		onLoad() {
+
+		},
+		methods: {
+
+		}
+	}
+</script>
+
+<style>
+	.content {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.logo {
+		height: 200rpx;
+		width: 200rpx;
+		margin-top: 200rpx;
+		margin-left: auto;
+		margin-right: auto;
+		margin-bottom: 50rpx;
+	}
+
+	.text-area {
+		display: flex;
+		justify-content: center;
+	}
+
+	.title {
+		font-size: 36rpx;
+		color: #8f8f94;
+	}
+</style>

+ 42 - 0
pages/login/JudeLoginPage.vue

@@ -0,0 +1,42 @@
+<template>
+  <view>
+    
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        
+      }
+    },
+    methods: {
+      
+    },
+    created() {
+        console.log('App Launch')
+         // token标志来判断
+        let token= uni.getStorageSync('token');   
+        console.log(token,uni.getStorageSync('userInfo'));
+         if (!token) {
+             console.log('没有token'),
+             //跳到登录页面.relaunch可以打开任何界面
+           uni.reLaunch({
+            url:'/pages/login/login'
+           })
+        } else {
+            console.log('有token')
+            //跳到首页,跳转tabbar界面,必须使用这个方法
+            uni.switchTab({
+                    url: '/pages/home/home'
+                })
+        }   
+        
+    },
+  }
+</script>
+
+<style>
+
+</style>

+ 154 - 0
pages/login/login.vue

@@ -0,0 +1,154 @@
+<template>
+	<view>
+		<view class="bg" :style="{backgroundImage: 'url('+imageURL+')'}">
+      <view class="avatar_class">
+        <u-avatar size="80" :src="src"></u-avatar>
+      </view>
+      <view class="alert_class">欢迎登录</view>
+			<view class="loginBox">
+        <view style="margin-top: 200rpx;">
+          <view style="margin-bottom:60rpx;"> 
+            <u--input class="input_class" v-model="form.username" shape="circle" height='40' prefixIcon='account-fill' label=" " placeholder="请输入用户名" :showAction="false"></u--input>
+            <!--  #ifdef MP-WEIXIN -->
+            <view style="height:20rpx"></view>
+            <!--  #endif -->
+
+            <u--input class="input_class" v-model="form.password" shape="circle" height='40' prefixIcon='lock' type="password" label=" " placeholder="请输入密码" :showAction="false"></u--input>
+          </view>
+          <u-button size="medium" shape='true' :loading="isLoading" type="primary" @tap="login">登录</u-button>
+        </view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+  import * as API_item from '@/api/login.js';
+	export default {
+		data() {
+			return {
+				form: {
+					username: '',
+					password: ''
+				},
+        imageURL:'/static/login/登录bg.jpg',
+        src: '/static/login/1.jpg',
+				isLoading: false,
+			}
+		},
+		methods: {
+		 async login() {
+				const _this = this;
+				_this.isLoading = true;
+        if(!this.form.username){
+          _this.isLoading = false;
+            uni.showToast({		// 提示错误信息
+              title: '请输入用户名',
+              icon:'error',
+              duration: 3000
+            })
+        }if(!this.form.password){
+          _this.isLoading = false;
+            uni.showToast({		// 提示错误信息
+              title: '请输入密码',
+              icon:'error',
+              duration: 3000
+            })
+        }else{
+          API_item.GetUserToken(this.form).then(res=>{
+          	if(res.code == 101){
+              _this.isLoading = false;
+              uni.setStorageSync('token', res.data);
+              uni.showToast({		// 提示错误信息
+                title: '登录成功',
+                icon:'success',
+                duration: 3000
+              })
+              API_item.GetUserInfo().then(e=>{
+                  if(e.code == 101){
+                     uni.setStorageSync('userInfo', e.data);
+                     let url = uni.getStorageSync("URL")
+                     // if(url){
+                     //   uni.navigateTo({								// 跳转到首页
+                     //     url: url
+                     //   })
+                     // }else{
+                       uni.switchTab({								// 跳转到首页
+                         url: '/pages/home/home'
+                       })
+                     // }
+                  }else{
+                     uni.showToast({		// 提示错误信息
+                       title: e.message,
+                       icon:'error',
+                       duration: 3000
+                     })
+                  }
+              })
+            }else{
+              _this.isLoading = false;
+              uni.showToast({		// 提示错误信息
+                title: res.message,
+                icon:'error',
+                duration: 3000
+              })
+            }
+          })
+        }
+      }
+    },
+    getUserInfo(){
+      API_item.GetUserInfo().then(res=>{
+        if(uni.getStorage('token')){
+          if(res.code == 101){
+         // uni.switchTab({								// 跳转到首页
+         //   url: '/pages/home/home'
+         // })
+          }else{
+           
+          }
+        }
+      })
+    }
+  }
+</script>
+
+/*scoped 仅对当前页面生效*/
+<style lang="scss">
+	.bg {
+		width: 100vw;
+		height: 100vh;
+		background-size: 100% 100%;
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+
+    .avatar_class{
+      position: absolute;
+      top:300rpx;
+      z-index: 9;
+    }
+    .alert_class{
+      position: absolute;
+      top:460rpx;
+      z-index: 9;
+      color: rgba(40, 39, 39, 0.7);
+    }
+    .loginBox {
+    	width: 500rpx;
+    	height: 600rpx;
+      position: relative;
+    	background-color: rgba(255, 255, 255, 0.7);
+    	margin: auto;
+    	border-radius: 30rpx;
+    	padding: 30rpx;
+    	margin-top: 350rpx;
+    .input_class{
+         margin-top: 30rpx !important;
+      }
+    }
+	}
+
+</style>
+

+ 124 - 0
pages/myCenter/myCenter.scss

@@ -0,0 +1,124 @@
+.myCenter{
+  background-color: #eeeeee;
+  /* #ifdef H5 */
+  background-size: 100% 431rpx;
+  /* #endif */
+  /* #ifdef MP-WEIXIN */
+  background-size: 100% 430rpx;
+  /* #endif */
+  background-repeat: no-repeat;
+  font-size: 28rpx;
+  .set_class{
+    display: inline-block;
+    float: right;
+    padding: 25rpx;
+    /* #ifdef MP-WEIXIN */
+    margin-top: 140rpx;
+    /* #endif */
+  }
+  .urowClass{
+    padding-top: 130rpx;
+    .imClass{
+      margin-right: 30rpx;
+    }
+    .nameClass{
+      font-size: 30rpx;
+      margin-left: 60rpx;
+    }
+  }
+  .gridClass{
+    margin-top: 60rpx;
+    .bottomText{
+      font-size: 23rpx;
+      color: #313131;
+    }
+  }
+  .menuClass{
+    margin-top:48rpx;
+    padding-top: 40rpx;
+    padding-bottom: 20rpx;
+    height: 200rpx;
+    background-color: #fff;
+    text{
+      font-size: 25rpx;
+    }
+    .title_class{
+      margin-left: 20rpx;margin-top: -20rpx;margin-bottom: 40rpx;
+    }
+    .imgClasses{
+      position: relative;
+      width: 50rpx;
+      height: 50rpx;
+    }
+    .imgClass{
+      position: relative;
+      width: 100rpx;
+      height: 100rpx;
+    }
+    /* #ifdef H5 */
+    .badgeClass{
+      position: absolute;
+      z-index: 99;
+      top:3rpx;
+      right:12rpx;
+    }
+    /* #endif */
+    /* #ifdef MP-WEIXIN */
+    .badgeClass{
+      position: absolute;
+      top:4rpx;
+      left:90rpx;
+      z-index: 99;
+    }
+    /* #endif */
+  }
+  .myPurse{
+    background-color: #fff;
+    width: 100%;
+    margin-top: 15rpx;
+    /* #ifdef MP-WEIXIN */
+    padding-top: 20rpx;
+    height: 80rpx;
+    /* #endif */
+    padding-left: 25rpx;
+    /* #ifdef H5 */
+    height: 100rpx;
+    .img_class{
+      vertical-align:top;
+      display: inline-block;
+      margin-top: 20rpx;
+    }
+    text{
+      display: inline-block;      
+      vertical-align:top;
+      margin-left: 20rpx;
+      margin-top: 25rpx;
+    }
+    /* #endif */
+    /* #ifdef MP-WEIXIN */
+    text{
+      display: inline-block;      
+      vertical-align:top;
+      margin-left: 30rpx;
+    }
+    /* #endif */
+  }
+  .bott{
+    background-color: #fff;
+    margin-top: 15rpx;
+    height:900rpx;
+    width: 100%;
+    .title{
+      padding-left: 20rpx;
+      padding-top: 15rpx;
+    }
+    .tool_class{
+      margin: 10rpx;
+      padding-top:20rpx;
+      .grid-text{
+        font-size: 25rpx;
+        padding: 10rpx 0 20rpx 0rpx;
+      }
+    }
+  }
+}

+ 151 - 0
pages/myCenter/myCenter.vue

@@ -0,0 +1,151 @@
+<template>
+  <view class="myCenter" :style="{backgroundImage: 'url('+imageURL+')'}">
+    <view class="set_class" @click="goSetting">
+      <u-icon name="setting"size="25"></u-icon>
+    </view>
+    <view class="urowClass">
+      <u-row>
+        <u-col span="1" >
+        </u-col>
+        <u-col span="2" >
+          <u-image  src="/static/login/1.jpg" shape="circle" width="140rpx" height="140rpx"></u-image>
+        </u-col>
+        <u-col span="7">
+         <view class="nameClass">王小二</view>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="gridClass">
+      <u-grid :border="false" col="4" >
+        <u-grid-item  v-for="(listItem,listIndex) in list" :key="listIndex">
+          <text>{{listItem.name}}</text>
+          <text class="bottomText">{{listItem.title}}</text>
+        </u-grid-item>
+      </u-grid>
+    </view>
+    <view class="menuClass">
+      <view class="title_class">
+        <u-row>
+          <u-col span="9">我的订单</u-col>
+          <u-col span="3"><view style="text-align: center;">全部订单 ></view></u-col>
+        </u-row>
+      </view>
+      <u-grid :border="false" col="5" >
+        <u-grid-item >
+          <view class="badgeClass"><u-badge bgColor="#D62D4A" value="2" class="badgeClass"></u-badge></view>
+          <image class="imgClass" src="@/static/myCenter/1.jpg" />
+          <text>代付款</text>
+        </u-grid-item>
+        <u-grid-item>
+          <view class="badgeClass"><u-badge bgColor="#D62D4A" value="2" class="badgeClass"></u-badge></view>
+          <image class="imgClass"  src="@/static/myCenter/2.jpg" />
+          <text >待发货</text>
+        </u-grid-item>
+        <u-grid-item >
+          <view class="badgeClass"><u-badge bgColor="#D62D4A" value="2" class="badgeClass"></u-badge></view>
+          <image class="imgClass" src="@/static/myCenter/3.jpg"/>
+          <text >待收货</text>
+        </u-grid-item>
+        <u-grid-item > 
+          <view class="badgeClass"><u-badge bgColor="#D62D4A" value="2" class="badgeClass"></u-badge></view>
+          <image class="imgClass" src="@/static/myCenter/4.jpg"/>
+          <text >待评价</text>
+        </u-grid-item>
+        <u-grid-item>
+          <view class="badgeClass"><u-badge bgColor="#D62D4A" value="2" ></u-badge></view>
+          <image class="imgClass" src="@/static/myCenter/5.jpg"/>
+          <text >售后</text>
+        </u-grid-item>
+      </u-grid>
+    </view>
+    <view class="myPurse">
+      <u-row>
+        <u-col span="1" >
+          <u-image class="img_class" width="30px" height="30px" src="/static/myCenter/pingan.png"></u-image>
+        </u-col>
+        <u-col span="8" >
+          <text>爱养牛钱包</text>
+        </u-col>
+        <u-col span="3">
+         <text >查看余额 ></text>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="bott">
+      <view class="title">必备工具</view>
+      <view class="tool_class">
+        <u-grid :border="false" col="4" >
+          <u-grid-item style="margin-top:15rpx" v-for="(tool,index) in toolList" :key="index">
+            <u-image class="img_class" width="40px" height="40px" :src="tool.src"></u-image>
+            <text class="grid-text">{{tool.name}}</text>
+          </u-grid-item>
+        </u-grid>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+         list: [{
+            name: '2',
+            title: '积分'
+          },
+          {
+            name: '0',
+            title: '优惠券'
+          },
+          {
+            name: '2',
+            title: '购物车'
+          },
+          {
+            name: '24',
+            title: '收藏夹'
+          },
+        ],
+        imageURL:'/static/login/bg5.jpg',
+        toolList:[{
+            src: '/static/myCenter/pingtuan.png',
+            name: '物料预定'
+          },
+          {
+            src: '/static/myCenter/caigoujuece.png',
+            name: '奶款担保'
+          },
+          {
+            src: '/static/myCenter/daikou.png',
+            name: '我的代扣'
+          },
+          {
+            src: '/static/myCenter/jifen.png',
+            name: '我的积分'
+          },
+          {
+            src: '/static/myCenter/milkPrice.png',
+            name: '物料预定'
+          },
+          {
+            src: '/static/myCenter/piliang.png',
+            name: '物料预定'
+          },
+          {
+            src: '/static/myCenter/companyManager.png',
+            name: '物料预定'
+          },
+        ],
+      };
+    },
+    methods:{
+      goSetting(){
+        uni.navigateTo({ url: '/pages/myCenter/setting'})
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  @import 'myCenter.scss';
+</style>

+ 42 - 0
pages/myCenter/setting.vue

@@ -0,0 +1,42 @@
+<template>
+  <view>
+    <u-navbar title="设置" @rightClick="rightClick" :autoBack="true"></u-navbar>
+    <view style="margin-top: 180rpx;">
+      <u-button type="primary" @click="quitLogin">退出登录</u-button>
+    </view>
+  </view>
+</template>
+
+<script>
+  import * as API_item from '@/api/login.js';
+  export default {
+    data() {
+      return {
+        
+      }
+    },
+    methods: {
+      quitLogin(){
+        API_item.logout({}).then(res=>{
+        	if(res.code == 101){
+            uni.showToast({		// 提示错误信息
+              title: '退出成功',
+              icon:'success',
+              duration: 3000
+            })
+            uni.removeStorageSync('token')
+            uni.removeStorageSync('userInfo') 
+            uni.navigateTo({
+              url: "/pages/login/login",
+            });
+          }
+          })
+
+        }
+    }
+  }
+</script>
+
+<style>
+
+</style>

+ 3 - 0
pages/newsCenter/newsIndex.scss

@@ -0,0 +1,3 @@
+.homePage{
+	
+}

文件差异内容过多而无法显示
+ 23 - 0
pages/newsCenter/newsIndex.vue


+ 3 - 0
pages/typeList/typeList.scss

@@ -0,0 +1,3 @@
+.homePage{
+	
+}

文件差异内容过多而无法显示
+ 23 - 0
pages/typeList/typeList.vue


二进制
static/login/1.jpg


二进制
static/login/AYN.png


二进制
static/login/bg3.jpg


二进制
static/login/bg4.jpg


二进制
static/login/bg5.jpg


二进制
static/login/登录bg.jpg


二进制
static/myCenter/1.jpg


二进制
static/myCenter/2.jpg


二进制
static/myCenter/3.jpg


二进制
static/myCenter/4.jpg


二进制
static/myCenter/5.jpg


二进制
static/myCenter/aiDiscern.png


二进制
static/myCenter/caigoujuece.png


二进制
static/myCenter/companyManager.png


二进制
static/myCenter/daicai.png


二进制
static/myCenter/daikou.png


二进制
static/myCenter/fenxiao.png


二进制
static/myCenter/fenxiaozhongxin.png


二进制
static/myCenter/jifen.png


二进制
static/myCenter/milkPrice.png


二进制
static/myCenter/myData.png


二进制
static/myCenter/mykefu.png


二进制
static/myCenter/niuke.png


二进制
static/myCenter/niunaihua.png


二进制
static/myCenter/niuxin.png


二进制
static/myCenter/piliang.png


二进制
static/myCenter/pingan.png


二进制
static/myCenter/pingtuan.png


二进制
static/myCenter/puhuicundan.png


二进制
static/myCenter/qingzhu.png


二进制
static/myCenter/suiyicun.png


二进制
static/myCenter/video.png


二进制
static/myCenter/wodequanyyi.png


二进制
static/myCenter/youhuiquan.png


二进制
static/myCenter/yudin.png


二进制
static/myCenter/yushou.png


二进制
static/myCenter/zhangqi.png


二进制
static/nav/nav_ico1.png


二进制
static/nav/nav_ico10.png


二进制
static/nav/nav_ico2.png


二进制
static/nav/nav_ico3.png


二进制
static/nav/nav_ico4.png


二进制
static/nav/nav_ico5.png


二进制
static/nav/nav_ico6.png


二进制
static/nav/nav_ico7.png


二进制
static/nav/nav_ico8.png


二进制
static/nav/nav_ico9.png


二进制
static/tabBar/fenlei_1.png


二进制
static/tabBar/gouwuche.png


二进制
static/tabBar/shouye.png


二进制
static/tabBar/tabbar/fenlei_1.png


二进制
static/tabBar/tabbar/gouwuche.png


二进制
static/tabBar/tabbar/shouye.png


二进制
static/tabBar/tabbar/wode.png


二进制
static/tabBar/wode.png


+ 27 - 0
style/iconfont/iconfont.css

@@ -0,0 +1,27 @@
+@font-face {
+  font-family: 'iconfont';  /* Project id 3909464 */
+  src: url('https://at.alicdn.com/t/c/font_3909464_ix6c8n4m2.woff2?t=1677131492256') format('woff2'),
+       url('https://at.alicdn.com/t/c/font_3909464_ix6c8n4m2.woff?t=1677131492256') format('woff'),
+       url('https://at.alicdn.com/t/c/font_3909464_ix6c8n4m2.ttf?t=1677131492256') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-sousuo:before {
+  content: "\e86e";
+}
+
+.icon-qrcode-1-copy:before {
+  content: "\e613";
+}
+
+.icon-saoyisao:before {
+  content: "\e685";
+}
+

+ 79 - 0
uni.scss

@@ -0,0 +1,79 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 引入uView样式 */
+@import '@/uni_modules/uview-ui/theme.scss';
+
+/* 颜色变量 */
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f5f5f5;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:12px;
+$uni-font-size-base:14px;
+$uni-font-size-lg:16;
+
+/* 图片尺寸 */
+$uni-img-size-sm:20px;
+$uni-img-size-base:26px;
+$uni-img-size-lg:40px;
+
+/* Border Radius */
+$uni-border-radius-sm: 2px;
+$uni-border-radius-base: 3px;
+$uni-border-radius-lg: 6px;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 5px;
+$uni-spacing-row-base: 10px;
+$uni-spacing-row-lg: 15px;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 4px;
+$uni-spacing-col-base: 8px;
+$uni-spacing-col-lg: 12px;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:20px;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:26px;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:15px;

+ 17 - 0
uni_modules/custom-waterfalls-flow/changelog.md

@@ -0,0 +1,17 @@
+## 1.0.7(2022-05-26)
+1. 优化局部改变数据更新问题,避免重新加载数据,只改变局部
+## 1.0.6(2022-04-18)
+1. 修改tab快速切换时会出现的BUG
+## 1.0.5(2022-04-18)
+1. 修复可能存在数据错误的BUG;
+2. 兼容,今后可以无需调用refresh()就可以更新数据;
+## 1.0.4(2022-04-18)
+1. 修复BUG;
+## 1.0.3(2022-04-15)
+1. 优化代码;
+2. 修改懒加载数据存在的BUG;
+## 1.0.1(2022-03-11)
+1. 增加隐藏图片字段的键名字段hideImageKey,默认hide
+2. 支持在列表中配置hide参数进行隐藏图片
+## 1.0.0(2022-03-09)
+使用最简单的思想实现瀑布流

+ 321 - 0
uni_modules/custom-waterfalls-flow/components/custom-waterfalls-flow/custom-waterfalls-flow.vue

@@ -0,0 +1,321 @@
+<template>
+	<view class="waterfalls-flow">
+		<view v-for="(item,index) in data.column" :key="index" class="waterfalls-flow-column" :id="`waterfalls_flow_column_${index+1}`" :msg="msg" :style="{'width':w,'margin-left':index==0?0:m}">
+			<view :class="['column-value',{'column-value-show':item2.o}]" v-for="(item2,index2) in columnValue(index)" :key="index2" :style="[s1]" @click.stop="wapperClick(item2)">
+				<view class="inner" v-if="data.seat==1">
+					<!-- #ifdef MP-WEIXIN -->
+					<!-- #ifdef VUE2 -->
+					<slot name="slot{{item2.index}}"></slot>
+					<!-- #endif -->
+					<!-- #ifdef VUE3 -->
+					<slot :name="`slot${item2.index}`"></slot>
+					<!-- #endif -->
+					<!-- #endif -->
+					<!-- #ifndef MP-WEIXIN -->
+					<slot v-bind="item2"></slot>
+					<!-- #endif -->
+				</view>
+				<image :class="['img',{'img-hide':item2[hideImageKey]==true||item2[hideImageKey]==1},{'img-error':!item2[data.imageKey]}]" :src="item2[data.imageKey]" mode="widthFix" @load="imgLoad(item2,index+1)" @error="imgError(item2,index+1)" @click.stop="imageClick(item2)"></image>
+				<view class="inner" v-if="data.seat==2">
+					<!-- #ifdef MP-WEIXIN -->
+					<!-- #ifdef VUE2 -->
+					<slot name="slot{{item2.index}}"></slot>
+					<!-- #endif -->
+					<!-- #ifdef VUE3 -->
+					<slot :name="`slot${item2.index}`"></slot>
+					<!-- #endif -->
+					<!-- #endif -->
+					<!-- #ifndef MP-WEIXIN -->
+					<slot v-bind="item2"></slot>
+					<!-- #endif -->
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+<script>
+	export default {
+		props: {
+			value: Array,
+			column: { // 列的数量 
+				type: [String, Number],
+				default: 2
+			},
+			maxColumn: { // 最大列数 
+				type: [String, Number],
+				default: 5
+			},
+			columnSpace: { // 列之间的间距 百分比
+				type: [String, Number],
+				default: 1
+			},
+			imageKey: { // 图片key
+				type: [String],
+				default: 'image'
+			},
+			hideImageKey: { // 隐藏图片key
+				type: [String],
+				default: 'hide'
+			},
+			seat: { // 文本的位置,1图片之上 2图片之下
+				type: [String, Number],
+				default: 2
+			},
+			listStyle: { // 单个展示项的样式:eg:{'background':'red'}
+				type: Object
+			}
+		},
+		data() {
+			return {
+				data: {
+					list: this.value ? this.value : [],
+					column: this.column < 2 ? 2 : this.column,
+					columnSpace: this.columnSpace <= 5 ? this.columnSpace : 5,
+					imageKey: this.imageKey,
+					seat: this.seat
+				},
+				msg: 0,
+				listInitStyle: {
+					'border-radius': '8rpx',
+					'margin-bottom': '20rpx',
+					'background-color': '#fff'
+				},
+				adds: [], //预置数据
+				isLoaded: true,
+				curIndex: 0,
+				isRefresh: true,
+				flag: false,
+				refreshDatas: []
+			}
+		},
+		computed: {
+			// 计算列宽
+			w() {
+				const column_rate = `${100 / this.data.column - (+this.data.columnSpace)}%`;
+				return column_rate;
+			},
+			// 计算margin
+			m() {
+				const column_margin = `${(100-(100 / this.data.column - (+this.data.columnSpace)).toFixed(5)*this.data.column)/(this.data.column-1)}%`;
+				return column_margin;
+			},
+			// list样式
+			s1() {
+				return { ...this.listInitStyle, ...this.listStyle };
+			}
+		},
+		created() {
+			// 初始化
+			this.refresh();
+		},
+		methods: {
+			// 预加载图片
+			loadImages(idx = 0) {
+				let count = 0;
+				const newList = this.data.list.filter((item, index) => index >= idx);
+				for (let i = 0; i < newList.length; i++) {
+					// #ifndef APP-PLUS
+					uni.getImageInfo({
+						src: `${newList[i][this.imageKey]}.jpg`,
+						complete: res => {
+							count++;
+							if (count == newList.length) this.initValue(idx);
+						}
+					})
+					// #endif
+					// #ifdef APP-PLUS
+					plus.io.getImageInfo({
+						src: `${newList[i][this.imageKey]}.jpg`,
+						complete: res => {
+							count++;
+							if (count == newList.length) this.initValue(idx);
+						}
+					})
+					// #endif
+				}
+			},
+			// 刷新
+			refresh() {
+				if (!this.isLoaded) {
+					this.refreshDatas = this.value;
+					return false;
+				};
+				setTimeout(() => {
+					this.refreshDatas = [];
+					this.isRefresh = true;
+					this.adds = [];
+					this.data.list = this.value ? this.value : [];
+					this.data.column = this.column < 2 ? 2 : this.column >= this.maxColumn ? this.maxColumn : this.column;
+					this.data.columnSpace = this.columnSpace <= 5 ? this.columnSpace : 5;
+					this.data.imageKey = this.imageKey;
+					this.data.seat = this.seat;
+					this.curIndex = 0;
+					// 每列的数据初始化
+					for (let i = 1; i <= this.data.column; i++) {
+						this.data[`column_${i}_values`] = [];
+						this.msg++;
+					}
+					this.$nextTick(() => {
+						this.initValue(this.curIndex, 'refresh==>');
+					})
+				}, 1)
+			},
+			columnValue(index) {
+				return this.data[`column_${index+1}_values`];
+			},
+			change(newValue) {
+				for (let i = 0; i < this.data.list.length; i++) {
+					const cv = this.data[`column_${this.data.list[i].column}_values`];
+					for (let j = 0; j < cv.length; j++) {
+						if (newValue[i] && i === cv[j].index) {
+							this.data[`column_${this.data.list[i].column}_values`][j] = Object.assign(cv[j], newValue[i]);
+							this.msg++;
+							break;
+						}
+					}
+				}
+			},
+			getMin(a, s) {
+				let m = a[0][s];
+				let mo = a[0];
+				for (var i = a.length - 1; i >= 0; i--) {
+					if (a[i][s] < m) {
+						m = a[i][s];
+					}
+				}
+				mo = a.filter(i => i[s] == m);
+				return mo[0];
+			},
+			// 计算每列的高度
+			getMinColumnHeight() {
+				return new Promise(resolve => {
+					const heightArr = [];
+					for (let i = 1; i <= this.data.column; i++) {
+						const query = uni.createSelectorQuery().in(this);
+						query.select(`#waterfalls_flow_column_${i}`).boundingClientRect(data => {
+							heightArr.push({ column: i, height: data.height });
+						}).exec(() => {
+							if (this.data.column <= heightArr.length) {
+								resolve(this.getMin(heightArr, 'height'));
+							}
+						});
+					}
+				})
+			},
+			async initValue(i, from) {
+				this.isLoaded = false;
+				if (i >= this.data.list.length || this.refreshDatas.length) {
+					this.msg++;
+					this.loaded();
+					return false;
+				}
+				const minHeightRes = await this.getMinColumnHeight();
+				const c = this.data[`column_${minHeightRes.column}_values`];
+				this.data.list[i].column = minHeightRes.column;
+				c.push({ ...this.data.list[i], cIndex: c.length, index: i, o: 0 });
+				this.msg++;
+			},
+			// 图片加载完成
+			imgLoad(item, c) {
+				const i = item.index;
+				item.o = 1;
+				this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)));
+				this.initValue(i + 1);
+			},
+			// 图片加载失败
+			imgError(item, c) {
+				const i = item.index;
+				item.o = 1;
+				item[this.data.imageKey] = null;
+				this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)));
+				this.initValue(i + 1);
+			},
+			// 渲染结束
+			loaded() {
+				if (this.refreshDatas.length) {
+					this.isLoaded = true;
+					this.refresh();
+					return false;
+				}
+				this.curIndex = this.data.list.length;
+				if (this.adds.length) {
+					this.data.list = this.adds[0];
+					this.adds.splice(0, 1);
+					this.initValue(this.curIndex);
+				} else {
+					if (this.data.list.length) this.$emit('loaded');
+					this.isLoaded = true;
+					this.isRefresh = false;
+				}
+			},
+			// 单项点击事件
+			wapperClick(item) {
+				this.$emit('wapperClick', item);
+			},
+			// 图片点击事件
+			imageClick(item) {
+				this.$emit('imageClick', item);
+			}
+		},
+		watch: {
+			value: {
+				deep: true,
+				handler(newValue, oldValue) {
+					setTimeout(() => {
+						this.$nextTick(() => {
+							if (this.isRefresh) return false;
+							if (this.isLoaded) {
+								// if (newValue.length <= this.curIndex) return this.refresh();
+								if (newValue.length <= this.curIndex) return this.change(newValue);
+								this.data.list = newValue;
+								this.$nextTick(() => {
+									this.initValue(this.curIndex, 'watch==>');
+								})
+							} else {
+								this.adds.push(newValue);
+							}
+						})
+					}, 10)
+				}
+			},
+			column(newValue) {
+				this.refresh();
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.waterfalls-flow {
+		overflow: hidden;
+		width: 97%; margin: 0 auto;
+		&-column {
+			float: left;
+		}
+	}
+
+	.column-value {
+		font-size: 0;
+		overflow: hidden;
+		transition: opacity .4s;
+		opacity: 0;
+
+		&-show {
+			opacity: 1;
+		}
+
+		.inner {
+			font-size: 30rpx;
+		}
+
+		.img {
+			width: 100%;
+			&-hide {
+				display: none;
+			}
+
+			&-error {
+				background: #f2f2f2 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAiAQMAAAAatXkPAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAAIZJREFUCNdlzjEKwkAUBNAfEGyCuYBkLyLuxRYW2SKlV1JSeA2tUiZg4YrLjv9PGsHqNTPMSAQuyAJgRDHSyvBPwtZoSJXakeJI9iuRLGDygdl6V0yKDtyMAeMPZySj8yfD+UapvRPj2JOwkyAooSV5IwdDjPdCPspe8LyTl9IKJvDETKKRv6vnlUasgg0fAAAAAElFTkSuQmCC) no-repeat center center;
+			}
+		}
+	}
+</style>

+ 81 - 0
uni_modules/custom-waterfalls-flow/package.json

@@ -0,0 +1,81 @@
+{
+  "id": "custom-waterfalls-flow",
+  "displayName": "瀑布流 灵活配置 简单易用 兼容vue2vue3小程序、H5、app等多端",
+  "version": "1.0.7",
+  "description": "瀑布流,根据内容自动计算进行流式布局,简单参数配置,实现兼容多端及vue2和vue3的瀑布流布局",
+  "keywords": [
+    "瀑布流",
+    "瀑布流式布局"
+],
+  "repository": "https://gitee.com/my_dear_li_pan/my-uni-modules.git",
+  "engines": {
+    "HBuilderX": "^3.3.11"
+  },
+  "dcloudext": {
+    "category": [
+        "前端组件",
+        "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "插件不采集任何数据",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "u",
+          "Edge": "u",
+          "Firefox": "y",
+          "Safari": "u"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "u",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        }
+      }
+    }
+  }
+}

+ 445 - 0
uni_modules/custom-waterfalls-flow/readme.md

@@ -0,0 +1,445 @@
+- <a href="#c1" title="概要">概要</a>
+- <a href="#c2" title="支持的平台">支持的平台</a>
+- <a href="#c3" title="使用方式">使用方式</a>
+- <a href="#c4" title="属性说明">属性说明</a>
+- <a href="#c5" title="事件说明">事件说明</a>
+- <a href="#c6" title="组件方法">组件方法</a>
+- <a href="#c7" title="refresh的使用示例">refresh的使用示例</a>
+- <a href="#c8" title="隐藏单项图片示例">隐藏单项图片示例</a>
+- <a href="#c9" title="完整示例">完整示例</a>
+- <a href="#c10" title="温馨提示">温馨提示</a>
+- <a href="#c11" title="关注我,不迷路">关注我,不迷路</a>
+- <a href="#c12" title="个人作品展示">个人作品展示</a>
+ 
+<div id="c1"></div>
+
+#### 概要
+
+custom-waterfalls-flow是一个瀑布流插件,灵活配置、简单易用、兼容多端、同时兼容vue2和vue3。
+
+最近在做项目的时候需要用到瀑布流,于是在插件市场找了一些,下载量最高的是用了定位来做的,我认为瀑布流可以不用定位去实现,于是我就自己写了该插件。经过反复的测试优化,最终搞定!
+
+**设置列数:** 瀑布流的列数可以通过参数直接控制,实时监听,随改随生效。列数最小为2,最大默认为5,可以通过maxColumn参数去控制最大列数,理论上可以设置无限大,具体值自己拿捏。
+
+**更新数据:** 瀑布流的每项数据,可以直接通过修改value,随改随生效,这样可以实现加载更多数据。已经渲染过的数据不会再次渲染,每次只会渲染新增的数据,这样避免了数据越多渲染越慢的情况。可以调用组件的```refresh()```方法进行数据刷新,注意vue2和vue3中调用子组件的方法有区别,也会在下面进行说明。
+
+**展示方式:** 瀑布流可以是纯图片,可以使用插槽自定义文字描述,微信小程序与app、h5使用会有些区别,也会在下面具体说明。内容高度及排序都不用担心,会根据每项的内容高度自动计算。
+
+**实现思路:** 通过配置列数,先渲染出每列,再计算每列的高度,最小的那列就加入一条数据进行渲染,然后再重复计算每列,高度小的加入数据...其实思路是很简单的。
+
+uniapp插件市场地址:[https://ext.dcloud.net.cn/plugin?id=7594](https://ext.dcloud.net.cn/plugin?id=7594)
+
+<div id="c2"></div>
+
+#### 支持的平台
+
+H5、app、微信小程序(这三个平台经过反复测试优化,兼容vue2和vue3)。
+
+百度小程序:由于插槽不能循环渲染的限制,只支持纯图片瀑布流。
+
+其他小程序:暂未测试,需要的可以自己测试和修改,思路肯定是没错的,主要是兼容插槽的问题。
+
+nvue:暂不支持,后期可能会支持,目前需要的可以自己修改源码。
+
+<div id="c3"></div>
+
+#### 使用方式
+
+**1、导入插件**
+
+该组件符合uni_modules规范,使用Hbuilderx导入插件,导入到项目根目录中的uni_modules文件夹中。
+
+**2、template中使用**
+
+uni_modules规范在项目页面中直接使用,不需要单独引入注册组件。
+
+***纯图片瀑布流使用***
+
+```
+<template>
+	<custom-waterfalls-flow :value="data.list"></custom-waterfalls-flow>
+</template>
+```
+
+***微信小程序自定义内容使用***
+
+微信小程序没有动态模板,使用for循环的方式进行渲染。
+
+```
+<template>
+	<custom-waterfalls-flow :value="data.list">
+		<view class="item" v-for="(item,index) in data.list" :key="index" slot="slot{{index}}">
+			<view class="title">{{item.title}}</view>
+			<view class="desc">{{item.desc}}</view>
+		</view>
+	</custom-waterfalls-flow>
+</template>
+```
+
+***h5、app端自定义内容使用***
+
+使用作用域插槽实现
+
+```
+<template>
+	<custom-waterfalls-flow :value="data.list">
+		<template v-slot:default="item">
+			<view class="item">
+				<view class="title">{{item.title}}</view>
+				<view class="desc">{{item.desc}}</view>
+			</view>
+		</template>
+	</custom-waterfalls-flow>
+</template>
+```
+
+***小程序、h5、app等多端自定义内容使用***
+
+条件渲染-多端同时兼容
+
+```
+<template>
+	<custom-waterfalls-flow :value="data.list">
+		<!-- #ifdef MP-WEIXIN -->
+		<view class="item" v-for="(item,index) in data.list" :key="index" slot="slot{{index}}">
+			<view class="title">{{item.title}}</view>
+			<view class="desc">{{item.desc}}</view>
+		</view>
+		<!-- #endif -->
+		<!-- #ifndef MP-WEIXIN -->
+		<template v-slot:default="item">
+			<view class="item">
+				<view class="title">{{item.title}}</view>
+				<view class="desc">{{item.desc}}</view>
+			</view>
+		</template>
+		<!-- #endif -->
+	</custom-waterfalls-flow>
+</template>
+```
+
+<div id="c4"></div>
+
+#### 属性说明
+
+参数|说明|类型|是否必填|可选值|默认值
+-|-|-|-|-|-|
+value|渲染的列表|Array|是|-|-
+column|列数|Number|否|2-maxColumn|2
+maxColumn|最大列数|Number|否|>2|5
+columnSpace|列之间的间距(单位是百分比)|Number|否|-|2
+imageKey|列表中的图片字段的键名|String|否|-|image
+hideImageKey|隐藏图片字段的键名|String|否|-|hide
+seat|自定义文字的位置,1-图片上方,2-图片下方|Number|否|1/2|2
+listStyle|单个展示项的样式|Object|否|示例:```{'background':'red'}```|-
+
+<div id="c5"></div>
+
+#### 事件说明
+
+事件名称|说明|回调参数
+-|-|-|
+@loaded|图片加载完成事件|-
+@wapperClick|单项点击事件|单项对应参数
+@imageClick|图片点击事件|单项对应参数
+
+<div id="c6"></div>
+
+#### 组件方法
+
+事件名称|说明|参数|使用场景
+-|-|-|-
+refresh|刷新数据,数据初始化,vue2中使用:```this.$refs.waterfallsFlowRef.refresh();```;vue3中使用:```const waterfallsFlowRef = ref(null);waterfallsFlowRef.value.refresh();```|-|下拉刷新等
+
+<div id="c7"></div>
+
+#### refresh的使用示例
+
+***vue2中使用***
+
+```
+<template>
+    <view>
+        <button class="btn" type="default" @click="reset()">刷新数据</button>
+    	<custom-waterfalls-flow ref="waterfallsFlowRef" :value="data.list"></custom-waterfalls-flow>
+    </view>
+</template>
+<script>
+	export default {
+	    data() {
+			return {
+				data:{
+					list: [
+						{ image: 'https://via.placeholder.com/200x500.png/ff0000', title: '我是标题1', desc: '描述描述描述描述描述描述描述描述1' }, 
+						{ image: 'https://via.placeholder.com/200x200.png/2878ff', title: '我是标题2', desc: '描述描述描述描述描述描述描述描述2' }
+					]
+				}
+			}
+		},
+		reset(){
+			this.data.list = [{ image: 'https://via.placeholder.com/200x500.png/ff0000', title: '我是标题1', desc: '描述描述描述描述描述描述描述描述1' }]
+			this.$refs.waterfallsFlowRef.refresh();
+		}
+	}
+</script>
+```
+
+***vue3中使用***
+
+```
+<template>
+    <view>
+        <button class="btn" type="default" @click="reset()">刷新数据</button>
+    	<custom-waterfalls-flow ref="waterfallsFlowRef" :value="data.list"></custom-waterfalls-flow>
+    </view>
+</template>
+<script setup>
+	import { reactive, ref } from 'vue';
+	const data = reactive({
+		list: [
+			{ image: 'https://via.placeholder.com/200x500.png/ff0000', title: '我是标题1', desc: '描述描述描述描述描述描述描述描述1' }, 
+			{ image: 'https://via.placeholder.com/200x200.png/2878ff', title: '我是标题2', desc: '描述描述描述描述描述描述描述描述2' }
+		]
+	});
+	const waterfallsFlowRef = ref(null);
+	function reset(){
+		data.list = [{ image: 'https://via.placeholder.com/200x500.png/ff0000', title: '我是标题1', desc: '描述描述描述描述描述描述描述描述1' }]
+		waterfallsFlowRef.value.refresh();
+	}
+</script>
+```
+
+<div id="c8"></div>
+
+#### 隐藏单项图片示例
+
+在数据列表中配置```hide:true```或者```hide:1```,就可以达到不显示图片的效果。支持使用参数hideImageKey自定义键名称,那就使用:```定义的键名称:true```或者```定义的键名称:1```。
+
+```
+<template>
+	<custom-waterfalls-flow :value="data.list">
+		<!-- #ifdef MP-WEIXIN -->
+		<view class="item" v-for="(item,index) in data.list" :key="index" slot="slot{{index}}">
+			<view class="title">{{item.title}}</view>
+			<view class="desc">{{item.desc}}</view>
+		</view>
+		<!-- #endif -->
+		<!-- #ifndef MP-WEIXIN -->
+		<template v-slot:default="item">
+			<view class="item">
+				<view class="title">{{item.title}}</view>
+				<view class="desc">{{item.desc}}</view>
+			</view>
+		</template>
+		<!-- #endif -->
+	</custom-waterfalls-flow>
+</template>
+<script setup>
+	import { reactive, ref } from 'vue';
+	const data = reactive({
+		list: [
+			{ image: 'https://via.placeholder.com/200x500.png/ff0000',
+			hide:1,title: '我是标题1', desc: '描述描述描述描述描述描述描述描述1' }, 
+			{ image: 'https://via.placeholder.com/200x200.png/2878ff', title: '我是标题2', desc: '描述描述描述描述描述描述描述描述2' }
+		]
+	});
+</script>
+```
+
+<div id="c9"></div>
+
+#### 完整示例
+
+```
+<template>
+	<view style="padding: 0 10rpx;">
+		<view class="handle">
+			<button class="btn" type="default" @click="add()">增加数据</button>
+			<button class="btn" type="default" @click="changeColumn(1)">+列数({{column}})</button>
+			<button class="btn" type="default" @click="changeColumn(0)">-列数({{column}})</button>
+			<button class="btn" type="default" @click="reset()">刷新数据</button>
+		</view>
+		<custom-waterfalls-flow ref="waterfallsFlowRef" :value="data.list" :column="column" :columnSpace="1.5" :seat="2" @wapperClick="wapperClick" @imageClick="imageClick" @loaded="loaded">
+			<!-- #ifdef MP-WEIXIN -->
+			<view class="item" v-for="(item,index) in data.list" :key="index" slot="slot{{index}}">
+				<view class="title">{{item.title}}</view>
+				<view class="desc">{{item.desc}}</view>
+			</view>
+			<!-- #endif -->
+			<!-- #ifndef MP-WEIXIN -->
+			<template v-slot:default="item">
+				<view class="item">
+					<view class="title">{{item.title}}</view>
+					<view class="desc">{{item.desc}}</view>
+				</view>
+			</template>
+			<!-- #endif -->
+		</custom-waterfalls-flow>
+	</view>
+</template>
+<script setup>
+	// #ifdef VUE3
+	import { reactive, ref, onMounted } from 'vue';
+	const data = reactive({
+		list: [{ image: 'https://via.placeholder.com/200x500.png/ff0000', title: '我是标题1', desc: '描述描述描述描述描述描述描述描述1' }, 
+					{ image: 'https://via.placeholder.com/200x200.png/2878ff', title: '我是标题2', desc: '描述描述描述描述描述描述描述描述2' }, 
+					{ image: 'https://via.placeholder.com/200x100.png/FFB6C1', title: '我是标题3', desc: '描述描述描述描述描述描述描述描述3' }, 
+					{ image: 'https://via.placeholder.com/200x300.png/9400D3', title: '我是标题4', desc: '描述描述描述描述描述描述描述描述4' }, 
+					{ image: 'https://via.placeholder.com/100x240.png/B0E0E6', title: '我是标题5', desc: '描述描述描述描述描述描述描述描述5' }, 
+					{ image: 'https://via.placeholder.com/140x280.png/7FFFAA', title: '我是标题6', desc: '描述描述描述描述描述描述描述描述6' }, 
+					{ image: 'https://via.placeholder.com/40x60.png/EEE8AA', title: '我是标题7', desc: '描述描述描述描述描述描述描述描述7' }]
+	});
+	const column = ref(3);
+
+	function add() {
+		const newArr = [{ image: 'https://via.placeholder.com/58x100.png/FF7F50', title: '我是标题8', desc: '描述描述描述描述描述描述描述描述8' }, 
+				{ image: 'https://via.placeholder.com/59x100.png/C0C0C0', title: '我是标题9', desc: '描述描述描述描述描述描述描述描述9' }, 
+				{ image: 'https://via.placeholder.com/60x100.png/FAEBD7', title: '我是标题10', desc: '描述描述描述描述描述描述描述描述10' }];
+		data.list = data.list.concat(newArr);
+	}
+
+	function changeColumn(h) {
+		column.value = !h ? column.value - 1 : column.value + 1;
+	}
+
+	function loaded() {
+		console.log('加载完成')
+	}
+
+	function wapperClick(item) {
+		console.log('单项点击事件', item)
+	}
+
+	function imageClick(item) {
+		console.log('图片点击事件', item)
+	}
+	const waterfallsFlowRef = ref(null);
+
+	function reset() {
+		data.list = [{ image: 'https://via.placeholder.com/200x500.png/ff0000', title: '我是标题1', desc: '描述描述描述描述描述描述描述描述1' }]
+		waterfallsFlowRef.value.refresh();
+	}
+	// #endif
+</script>
+<script>
+	// #ifdef VUE2
+	export default {
+		data() {
+			return {
+				data: {
+					list: [{ image: 'https://via.placeholder.com/200x500.png/ff0000', title: '我是标题1', desc: '描述描述描述描述描述描述描述描述1' }, 
+					{ image: 'https://via.placeholder.com/200x200.png/2878ff', title: '我是标题2', desc: '描述描述描述描述描述描述描述描述2' }, 
+					{ image: 'https://via.placeholder.com/200x100.png/FFB6C1', title: '我是标题3', desc: '描述描述描述描述描述描述描述描述3' }, 
+					{ image: 'https://via.placeholder.com/200x300.png/9400D3', title: '我是标题4', desc: '描述描述描述描述描述描述描述描述4' }, 
+					{ image: 'https://via.placeholder.com/100x240.png/B0E0E6', title: '我是标题5', desc: '描述描述描述描述描述描述描述描述5' }, 
+					{ image: 'https://via.placeholder.com/140x280.png/7FFFAA', title: '我是标题6', desc: '描述描述描述描述描述描述描述描述6' }, 
+					{ image: 'https://via.placeholder.com/40x60.png/EEE8AA', title: '我是标题7', desc: '描述描述描述描述描述描述描述描述7' }]
+				},
+				column: 3
+			}
+		},
+		methods: {
+			add() {
+				const newArr = [{ image: 'https://via.placeholder.com/58x100.png/FF7F50', title: '我是标题8', desc: '描述描述描述描述描述描述描述描述8' }, 
+				{ image: 'https://via.placeholder.com/59x100.png/C0C0C0', title: '我是标题9', desc: '描述描述描述描述描述描述描述描述9' }, 
+				{ image: 'https://via.placeholder.com/60x100.png/FAEBD7', title: '我是标题10', desc: '描述描述描述描述描述描述描述描述10' }]
+				this.data.list = this.data.list.concat(newArr);
+			},
+			changeColumn(h) {
+				this.column = !h ? this.column - 1 : this.column + 1;
+			},
+			loaded() {
+				console.log('加载完成')
+			},
+			wapperClick(item) {
+				console.log('单项点击事件', item)
+			},
+			imageClick(item) {
+				console.log('图片点击事件', item)
+			},
+			reset() {
+				this.data.list = [{ image: 'https://via.placeholder.com/200x500.png/ff0000', title: '我是标题1', desc: '描述描述描述描述描述描述描述描述1' }]
+				this.$refs.waterfallsFlowRef.refresh();
+			}
+		}
+	}
+	// #endif
+</script>
+<style>
+	page {
+		background-color: #f2f5f9;
+	}
+</style>
+<style lang="scss" scoped>
+	.handle {
+		display: flex;
+		flex-direction: row;
+		flex-wrap: wrap;
+		margin-bottom: 20rpx;
+		padding: 10rpx;
+
+		.btn {
+			margin: 20rpx 10rpx;
+			padding: 0 20rpx;
+			background: #2878FF;
+			font-size: 28rpx;
+			color: #fff;
+
+			&::after {
+				border: 0;
+			}
+		}
+	}
+
+	.item {
+		padding: 10rpx 10rpx 20rpx;
+
+		.title {
+			line-height: 48rpx;
+			font-size: 28rpx;
+			color: #222;
+		}
+
+		.desc {
+			font-size: 24rpx;
+			color: #666;
+		}
+	}
+</style>
+```
+
+<div id="c10"></div>
+
+#### 温馨提示
+
+1、该插件反复测试过微信小程序、h5、app-vue三个端,vue2和vue3都兼容,其他端可能需要测试改进。
+
+2、该插件的使用hbuilderx版本最好升级到较新版本,我开发的版本是hbuilderx3.3.11.20220209。
+
+3、对此插件或相关问题有好的建议,可以直接在评论区进行讨论。
+
+4、希望遇到问题不要喷,也不要骂人,其实这种心情我能理解,写该插件也不是一时半会就完成了的,所以希望互相理解。只要有问题,我会第一时间回复解决。
+
+5、对此插件有任何问题的可以在下方留言,我会第一时间回复和解决问题。还可以加QQ群进行前端技术交流 568984539,加群备注‘地区-名字-技术类型’。
+
+#### 最后我想说:认为该插件对你有帮助的,记得收藏、好评,这样可以帮助到更多人哟!
+
+---
+
+<div id="c11"></div>
+
+#### 关注我,不迷路
+
+如果任何疑问的可以在评论区留言,还可以加QQ群交流:568984539,加群备注‘地区-名字-技术类型’。
+
+更多前端等相关知识可关注我个人博客:https://blog.csdn.net/qq_42961150?spm=1011.2124.3001.5343
+
+<div id="c12"></div>
+
+#### 个人作品展示
+
+uniapp+vue3.2+unicloud开发微信小程序:**皮皮虎去水印**。
+
+关注下方公众号:【**全网免费网盘资源**】、【**美团外卖饿了么天天领红包**】、【**去水印**】
+
+![image](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-bb657efd-fece-483e-a715-5daea480fde8/6e029310-aec8-46e9-9883-1c88dc1925ad.jpg)

+ 21 - 0
uni_modules/uview-ui/LICENSE

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

+ 66 - 0
uni_modules/uview-ui/README.md

@@ -0,0 +1,66 @@
+<p align="center">
+    <img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
+</p>
+<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView 2.0</h3>
+<h3 align="center">多平台快速开发的UI框架</h3>
+
+[![stars](https://img.shields.io/github/stars/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0)
+[![forks](https://img.shields.io/github/forks/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0)
+[![issues](https://img.shields.io/github/issues/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0/issues)
+[![Website](https://img.shields.io/badge/uView-up-blue?style=flat-square)](https://uviewui.com)
+[![release](https://img.shields.io/github/v/release/umicro/uView2.0?style=flat-square)](https://gitee.com/umicro/uView2.0/releases)
+[![license](https://img.shields.io/github/license/umicro/uView2.0?style=flat-square)](https://en.wikipedia.org/wiki/MIT_License)
+
+## 说明
+
+uView UI,是[uni-app](https://uniapp.dcloud.io/)全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
+
+## [官方文档:https://uviewui.com](https://uviewui.com)
+
+
+## 预览
+
+您可以通过**微信**扫码,查看最佳的演示效果。
+<br>
+<br>
+<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
+
+
+## 链接
+
+- [官方文档](https://www.uviewui.com/)
+- [更新日志](https://www.uviewui.com/components/changelog.html)
+- [升级指南](https://www.uviewui.com/components/changeGuide.html)
+- [关于我们](https://www.uviewui.com/cooperation/about.html)
+
+## 交流反馈
+
+欢迎加入我们的QQ群交流反馈:[点此跳转](https://www.uviewui.com/components/addQQGroup.html)
+
+## 关于PR
+
+> 我们非常乐意接受各位的优质PR,但在此之前我希望您了解uView2.0是一个需要兼容多个平台的(小程序、h5、ios app、android app)包括nvue页面、vue页面。
+> 所以希望在您修复bug并提交之前尽可能的去这些平台测试一下兼容性。最好能携带测试截图以方便审核。非常感谢!
+
+## 安装
+
+#### **uni-app插件市场链接** —— [https://ext.dcloud.net.cn/plugin?id=1593](https://ext.dcloud.net.cn/plugin?id=1593)
+
+请通过[官网安装文档](https://www.uviewui.com/components/install.html)了解更详细的内容
+
+## 快速上手
+
+请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
+
+## 使用方法
+配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。
+
+```html
+<template>
+	<u-button text="按钮"></u-button>
+</template>
+```
+
+## 版权信息
+uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。
+

+ 357 - 0
uni_modules/uview-ui/changelog.md

@@ -0,0 +1,357 @@
+## 2.0.34(2022-09-25)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. `u-input`、`u-textarea`增加`ignoreCompositionEvent`属性
+2. 修复`route`方法调用可能报错的问题
+3. 修复`u-no-network`组件`z-index`无效的问题
+4. 修复`textarea`组件在h5上confirmType=""报错的问题
+5. `u-rate`适配`nvue`
+6. 优化验证手机号码的正则表达式(根据工信部发布的《电信网编号计划(2017年版)》进行修改。)
+7. `form-item`添加`labelPosition`属性
+8. `u-calendar`修复`maxDate`设置为当前日期,并且当前时间大于08:00时无法显示日期列表的问题 (#724)
+9. `u-radio`增加一个默认插槽用于自定义修改label内容 (#680)
+10. 修复`timeFormat`函数在safari重的兼容性问题 (#664)
+## 2.0.33(2022-06-17)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复`loadmore`组件`lineColor`类型错误问题
+2. 修复`u-parse`组件`imgtap`、`linktap`不生效问题
+## 2.0.32(2022-06-16)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+1. `u-loadmore`新增自定义颜色、虚/实线
+2. 修复`u-swiper-action`组件部分平台不能上下滑动的问题
+3. 修复`u-list`回弹问题
+4. 修复`notice-bar`组件动画在低端安卓机可能会抖动的问题
+5. `u-loading-page`添加控制图标大小的属性`iconSize`
+6. 修复`u-tooltip`组件`color`参数不生效的问题
+7. 修复`u--input`组件使用`blur`事件输出为`undefined`的bug
+8. `u-code-input`组件新增键盘弹起时,是否自动上推页面参数`adjustPosition`
+9. 修复`image`组件`load`事件无回调对象问题
+10. 修复`button`组件`loadingSize`设置无效问题
+10. 其他修复
+## 2.0.31(2022-04-19)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复`upload`在`vue`页面上传成功后没有成功标志的问题
+2. 解决演示项目中微信小程序模拟上传图片一直出于上传中问题
+3. 修复`u-code-input`组件在`nvue`页面编译到`app`平台上光标异常问题(`app`去除此功能)
+4. 修复`actionSheet`组件标题关闭按钮点击事件名称错误的问题
+5. 其他修复
+## 2.0.30(2022-04-04)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. `u-rate`增加`readonly`属性
+2. `tabs`滑块支持设置背景图片
+3. 修复`u-subsection` `mode`为`subsection`时,滑块样式不正确的问题
+4. `u-code-input`添加光标效果动画
+5. 修复`popup`的`open`事件不触发
+6. 修复`u-flex-column`无效的问题
+7. 修复`u-datetime-picker`索引在特定场合异常问题
+8. 修复`u-datetime-picker`最小时间字符串模板错误问题
+9. `u-swiper`添加`m3u8`验证
+10. `u-swiper`修改判断image和video逻辑
+11. 修复`swiper`无法使用本地图片问题,增加`type`参数
+12. 修复`u-row-notice`格式错误问题
+13. 修复`u-switch`组件当`unit`为`rpx`时,`nodeStyle`消失的问题
+14. 修复`datetime-picker`组件`showToolbar`与`visibleItemCount`属性无效的问题
+15. 修复`upload`组件条件编译位置判断错误,导致`previewImage`属性设置为`false`时,整个组件都会被隐藏的问题
+16. 修复`u-checkbox-group`设置`shape`属性无效的问题
+17. 修复`u-upload`的`capture`传入字符串的时候不生效的问题
+18. 修复`u-action-sheet`组件,关闭事件逻辑错误的问题
+19. 修复`u-list`触顶事件的触发错误的问题
+20. 修复`u-text`只有手机号可拨打的问题
+21. 修复`u-textarea`不能换行的问题
+22. 其他修复
+## 2.0.29(2022-03-13)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复`u--text`组件设置`decoration`属性未生效的问题
+2. 修复`u-datetime-picker`使用`formatter`后返回值不正确
+3. 修复`u-datetime-picker` `intercept` 可能为undefined
+4. 修复已设置单位 uni..config.unit = 'rpx'时,线型指示器 `transform` 的位置翻倍,导致指示器超出宽度
+5. 修复mixin中bem方法生成的类名在支付宝和字节小程序中失效
+6. 修复默认值传值为空的时候,打开`u-datetime-picker`报错,不能选中第一列时间的bug
+7. 修复`u-datetime-picker`使用`formatter`后返回值不正确
+8. 修复`u-image`组件`loading`无效果的问题
+9. 修复`config.unit`属性设为`rpx`时,导航栏占用高度不足导致塌陷的问题
+10. 修复`u-datetime-picker`组件`itemHeight`无效问题
+11. 其他修复
+## 2.0.28(2022-02-22)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. search组件新增searchIconSize属性
+2. 兼容Safari/Webkit中传入时间格式如2022-02-17 12:00:56
+3. 修复text value.js 判断日期出format错误问题
+4. priceFormat格式化金额出现精度错误
+5. priceFormat在部分情况下出现精度损失问题
+6. 优化表单rules提示
+7. 修复avatar组件src为空时,展示状态不对
+8. 其他修复
+## 2.0.27(2022-01-28)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1.样式修复
+## 2.0.26(2022-01-28)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1.样式修复
+## 2.0.25(2022-01-27)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复text组件mode=price时,可能会导致精度错误的问题
+2. 添加$u.setConfig()方法,可设置uView内置的config, props, zIndex, color属性,详见:[修改uView内置配置方案](https://uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE)
+3. 优化form组件在errorType=toast时,如果输入错误页面会有抖动的问题
+4. 修复$u.addUnit()对配置默认单位可能无效的问题
+## 2.0.24(2022-01-25)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复swiper在current指定非0时缩放有误
+2. 修复u-icon添加stop属性的时候报错
+3. 优化遗留的通过正则判断rpx单位的问题
+4. 优化Layout布局 vue使用gutter时,会超出固定区域
+5. 优化search组件高度单位问题(rpx -> px)
+6. 修复u-image slot 加载和错误的图片失去了高度
+7. 修复u-index-list中footer插槽与header插槽存在性判断错误
+8. 修复部分机型下u-popup关闭时会闪烁
+9. 修复u-image在nvue-app下失去宽高
+10. 修复u-popup运行报错
+11. 修复u-tooltip报错
+12. 修复box-sizing在app下的警告
+13. 修复u-navbar在小程序中报运行时错误
+14. 其他修复
+## 2.0.23(2022-01-24)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复image组件在hx3.3.9的nvue下可能会显示异常的问题
+2. 修复col组件gutter参数带rpx单位处理不正确的问题
+3. 修复text组件单行时无法显示省略号的问题
+4. navbar添加titleStyle参数
+5. 升级到hx3.3.9可消除nvue下控制台样式警告的问题
+## 2.0.22(2022-01-19)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. $u.page()方法优化,避免在特殊场景可能报错的问题
+2. picker组件添加immediateChange参数
+3. 新增$u.pages()方法
+## 2.0.21(2022-01-19)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 优化:form组件在用户设置rules的时候提示用户model必传
+2. 优化遗留的通过正则判断rpx单位的问题
+3. 修复微信小程序环境中tabbar组件开启safeAreaInsetBottom属性后,placeholder高度填充不正确
+4. 修复swiper在current指定非0时缩放有误
+5. 修复u-icon添加stop属性的时候报错
+6. 修复upload组件在accept=all的时候没有作用
+7. 修复在text组件mode为phone时call属性无效的问题
+8. 处理u-form clearValidate方法
+9. 其他修复
+## 2.0.20(2022-01-14)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复calendar默认会选择一个日期,如果直接点确定的话,无法取到值的问题
+2. 修复Slider缺少disabled props 还有注释
+3. 修复u-notice-bar点击事件无法拿到index索引值的问题
+4. 修复u-collapse-item在vue文件下,app端自定义插槽不生效的问题
+5. 优化头像为空时显示默认头像 
+6. 修复图片地址赋值后判断加载状态为完成问题
+7. 修复日历滚动到默认日期月份区域
+8. search组件暴露点击左边icon事件
+9. 修复u-form clearValidate方法不生效
+10. upload h5端增加返回文件参数(文件的name参数)
+11. 处理upload选择文件后url为blob类型无法预览的问题
+12. u-code-input 修复输入框没有往左移出一半屏幕
+13. 修复Upload上传 disabled为true时,控制台报hoverClass类型错误
+14. 临时处理ios app下grid点击坍塌问题
+15. 其他修复
+## 2.0.19(2021-12-29)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 优化微信小程序包体积可在微信中预览,请升级HbuilderX3.3.4,同时在“运行->运行到小程序模拟器”中勾选“运行时是否压缩代码”
+2. 优化微信小程序setData性能,处理某些方法如$u.route()无法在模板中使用的问题
+3. navbar添加autoBack参数
+4. 允许avatar组件的事件冒泡
+5. 修复cell组件报错问题
+6. 其他修复
+## 2.0.18(2021-12-28)
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复app端编译报错问题
+2. 重新处理微信小程序端setData过大的性能问题
+3. 修复边框问题
+4. 修复最大最小月份不大于0则没有数据出现的问题
+5. 修复SwipeAction微信小程序端无法上下滑动问题
+6. 修复input的placeholder在小程序端默认显示为true问题
+7. 修复divider组件click事件无效问题
+8. 修复u-code-input maxlength 属性值为 String 类型时显示异常
+9. 修复当 grid只有 1到2时 在小程序端algin设置无效的问题
+10. 处理form-item的label为top时,取消错误提示的左边距
+11. 其他修复
+## 2.0.17(2021-12-26)
+## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 解决HBuilderX3.3.3.20211225版本导致的样式问题
+2. calendar日历添加monthNum参数
+3. navbar添加center slot
+## 2.0.16(2021-12-25)
+## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 解决微信小程序setData性能问题
+2. 修复count-down组件change事件不触发问题
+## 2.0.15(2021-12-21)
+## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复Cell单元格titleWidth无效
+2. 修复cheakbox组件ischecked不更新
+3. 修复keyboard是否显示"."按键默认值问题
+4. 修复number-keyboard是否显示键盘的"."符号问题
+5. 修复Input输入框 readonly无效
+6. 修复u-avatar 导致打包app、H5时候报错问题
+7. 修复Upload上传deletable无效
+8. 修复upload当设置maxSize时无效的问题
+9. 修复tabs lineWidth传入带单位的字符串的时候偏移量计算错误问题
+10. 修复rate组件在有padding的view内,显示的星星位置和可触摸区域不匹配,无法正常选中星星
+## 2.0.13(2021-12-14)
+## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复配置默认单位为rpx可能会导致自定义导航栏高度异常的问题
+## 2.0.12(2021-12-14)
+## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复tabs组件在vue环境下划线消失的问题
+2. 修复upload组件在安卓小程序无法选择视频的问题
+3. 添加uni.$u.config.unit配置,用于配置参数默认单位,详见:[默认单位配置](https://www.uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE)
+4. 修复textarea组件在没绑定v-model时,字符统计不生效问题
+5. 修复nvue下控制是否出现滚动条失效问题
+## 2.0.11(2021-12-13)
+## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. text组件align参数无效的问题
+2. subsection组件添加keyName参数
+3. upload组件无法判断[Object file]类型的问题
+4. 处理notify层级过低问题
+5. codeInput组件添加disabledDot参数
+6. 处理actionSheet组件round参数无效的问题
+7. calendar组件添加round参数用于控制圆角值
+8. 处理swipeAction组件在vue环境下默认被打开的问题
+9. button组件的throttleTime节流参数无效的问题
+10. 解决u-notify手动关闭方法close()无效的问题
+11. input组件readonly不生效问题
+12. tag组件type参数为info不生效问题
+## 2.0.10(2021-12-08)
+## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复button sendMessagePath属性不生效
+2. 修复DatetimePicker选择器title无效
+3. 修复u-toast设置loading=true不生效
+4. 修复u-text金额模式传0报错
+5. 修复u-toast组件的icon属性配置不生效
+6. button的icon在特殊场景下的颜色优化
+7. IndexList优化,增加#
+## 2.0.9(2021-12-01)
+## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 优化swiper的height支持100%值(仅vue有效),修复嵌入视频时click事件无法触发的问题
+2. 优化tabs组件对list值为空的判断,或者动态变化list时重新计算相关尺寸的问题
+3. 优化datetime-picker组件逻辑,让其后续打开的默认值为上一次的选中值,需要通过v-model绑定值才有效
+4. 修复upload内嵌在其他组件中,选择图片可能不会换行的问题
+## 2.0.8(2021-12-01)
+## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复toast的position参数无效问题
+2. 处理input在ios nvue上无法获得焦点的问题
+3. avatar-group组件添加extraValue参数,让剩余展示数量可手动控制
+4. tabs组件添加keyName参数用于配置从对象中读取的键名
+5. 处理text组件名字脱敏默认配置无效的问题
+6. 处理picker组件item文本太长换行问题
+## 2.0.7(2021-11-30)
+## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 修复radio和checkbox动态改变v-model无效的问题。
+2. 优化form规则validator在微信小程序用法
+3. 修复backtop组件mode参数在微信小程序无效的问题
+4. 处理Album的previewFullImage属性无效的问题
+5. 处理u-datetime-picker组件mode='time'在选择改变时间时,控制台报错的问题
+## 2.0.6(2021-11-27)
+## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. 处理tag组件在vue下边框无效的问题。
+2. 处理popup组件圆角参数可能无效的问题。
+3. 处理tabs组件lineColor参数可能无效的问题。
+4. propgress组件在值很小时,显示异常的问题。
+## 2.0.5(2021-11-25)
+## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. calendar在vue下显示异常问题。 
+2. form组件labelPosition和errorType参数无效的问题
+3. input组件inputAlign无效的问题
+4. 其他一些修复
+## 2.0.4(2021-11-23)
+## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+0. input组件缺失@confirm事件,以及subfix和prefix无效问题
+1. component.scss文件样式在vue下干扰全局布局问题
+2. 修复subsection在vue环境下表现异常的问题
+3. tag组件的bgColor等参数无效的问题
+4. upload组件不换行的问题
+5. 其他的一些修复处理
+## 2.0.3(2021-11-16)
+## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. uView2.0已实现全面兼容nvue
+2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升
+3. 目前uView2.0为公测阶段,相关细节可能会有变动
+4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html)
+5. 处理modal的confirm回调事件拼写错误问题
+6. 处理input组件@input事件参数错误问题
+7. 其他一些修复
+## 2.0.2(2021-11-16)
+## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. uView2.0已实现全面兼容nvue
+2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升
+3. 目前uView2.0为公测阶段,相关细节可能会有变动
+4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html)
+5. 修复input组件formatter参数缺失问题
+6. 优化loading-icon组件的scss写法问题,防止不兼容新版本scss
+## 2.0.0(2020-11-15)
+## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
+
+# uView2.0重磅发布,利剑出鞘,一统江湖
+
+1. uView2.0已实现全面兼容nvue
+2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升
+3. 目前uView2.0为公测阶段,相关细节可能会有变动
+4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html)
+5. 修复input组件formatter参数缺失问题
+
+

+ 78 - 0
uni_modules/uview-ui/components/u--form/u--form.vue

@@ -0,0 +1,78 @@
+<template>
+	<uvForm
+		ref="uForm"
+		:model="model"
+		:rules="rules"
+		:errorType="errorType"
+		:borderBottom="borderBottom"
+		:labelPosition="labelPosition"
+		:labelWidth="labelWidth"
+		:labelAlign="labelAlign"
+		:labelStyle="labelStyle"
+		:customStyle="customStyle"
+	>
+		<slot />
+	</uvForm>
+</template>
+
+<script>
+	/**
+	 * 此组件存在的理由是,在nvue下,u-form被uni-app官方占用了,u-form在nvue中相当于form组件
+	 * 所以在nvue下,取名为u--form,内部其实还是u-form.vue,只不过做一层中转
+	 */
+	import uvForm from '../u-form/u-form.vue';
+	import props from '../u-form/props.js'
+	export default {
+		// #ifdef MP-WEIXIN
+		name: 'u-form',
+		// #endif
+		// #ifndef MP-WEIXIN
+		name: 'u--form',
+		// #endif
+		mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
+		components: {
+			uvForm
+		},
+		created() {
+			this.children = []
+		},
+		methods: {
+			// 手动设置校验的规则,如果规则中有函数的话,微信小程序中会过滤掉,所以只能手动调用设置规则
+			setRules(rules) {
+				this.$refs.uForm.setRules(rules)
+			},
+			validate() {
+				/**
+				 * 在微信小程序中,通过this.$parent拿到的父组件是u--form,而不是其内嵌的u-form
+				 * 导致在u-form组件中,拿不到对应的children数组,从而校验无效,所以这里每次调用u-form组件中的
+				 * 对应方法的时候,在小程序中都先将u--form的children赋值给u-form中的children
+				 */
+				// #ifdef MP-WEIXIN
+				this.setMpData()
+				// #endif
+				return this.$refs.uForm.validate()
+			},
+			validateField(value, callback) {
+				// #ifdef MP-WEIXIN
+				this.setMpData()
+				// #endif
+				return this.$refs.uForm.validateField(value, callback)
+			},
+			resetFields() {
+				// #ifdef MP-WEIXIN
+				this.setMpData()
+				// #endif
+				return this.$refs.uForm.resetFields()
+			},
+			clearValidate(props) {
+				// #ifdef MP-WEIXIN
+				this.setMpData()
+				// #endif
+				return this.$refs.uForm.clearValidate(props)
+			},
+			setMpData() {
+				this.$refs.uForm.children = this.children
+			}
+		},
+	}
+</script>

+ 47 - 0
uni_modules/uview-ui/components/u--image/u--image.vue

@@ -0,0 +1,47 @@
+<template>
+	<uvImage 
+		:src="src"
+		:mode="mode"
+		:width="width"
+		:height="height"
+		:shape="shape"
+		:radius="radius"
+		:lazyLoad="lazyLoad"
+		:showMenuByLongpress="showMenuByLongpress"
+		:loadingIcon="loadingIcon"
+		:errorIcon="errorIcon"
+		:showLoading="showLoading"
+		:showError="showError"
+		:fade="fade"
+		:webp="webp"
+		:duration="duration"
+		:bgColor="bgColor"
+		:customStyle="customStyle"
+		@click="$emit('click')"
+		@error="$emit('error')"
+		@load="$emit('load')"
+	>
+		<template v-slot:loading>
+			<slot name="loading"></slot>
+		</template>
+		<template v-slot:error>
+			<slot name="error"></slot>
+		</template>
+	</uvImage>
+</template>
+
+<script>
+	/**
+	 * 此组件存在的理由是,在nvue下,u-image被uni-app官方占用了,u-image在nvue中相当于image组件
+	 * 所以在nvue下,取名为u--image,内部其实还是u-iamge.vue,只不过做一层中转
+	 */
+	import uvImage from '../u-image/u-image.vue';
+	import props from '../u-image/props.js';
+	export default {
+		name: 'u--image',
+		mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
+		components: {
+			uvImage
+		},
+	}
+</script>

+ 73 - 0
uni_modules/uview-ui/components/u--input/u--input.vue

@@ -0,0 +1,73 @@
+<template>
+	<uvInput 
+		:value="value"
+		:type="type"
+		:fixed="fixed"
+		:disabled="disabled"
+		:disabledColor="disabledColor"
+		:clearable="clearable"
+		:password="password"
+		:maxlength="maxlength"
+		:placeholder="placeholder"
+		:placeholderClass="placeholderClass"
+		:placeholderStyle="placeholderStyle"
+		:showWordLimit="showWordLimit"
+		:confirmType="confirmType"
+		:confirmHold="confirmHold"
+		:holdKeyboard="holdKeyboard"
+		:focus="focus"
+		:autoBlur="autoBlur"
+		:disableDefaultPadding="disableDefaultPadding"
+		:cursor="cursor"
+		:cursorSpacing="cursorSpacing"
+		:selectionStart="selectionStart"
+		:selectionEnd="selectionEnd"
+		:adjustPosition="adjustPosition"
+		:inputAlign="inputAlign"
+		:fontSize="fontSize"
+		:color="color"
+		:prefixIcon="prefixIcon"
+		:suffixIcon="suffixIcon"
+		:suffixIconStyle="suffixIconStyle"
+		:prefixIconStyle="prefixIconStyle"
+		:border="border"
+		:readonly="readonly"
+		:shape="shape"
+		:customStyle="customStyle"
+		:formatter="formatter"
+		:ignoreCompositionEvent="ignoreCompositionEvent"
+		@focus="$emit('focus')"
+		@blur="e => $emit('blur', e)"
+		@keyboardheightchange="$emit('keyboardheightchange')"
+		@change="e => $emit('change', e)"
+		@input="e => $emit('input', e)"
+		@confirm="e => $emit('confirm', e)"
+		@clear="$emit('clear')"
+		@click="$emit('click')"
+	>
+		<!-- #ifdef MP -->
+		<slot name="prefix"></slot>
+		<slot name="suffix"></slot>
+		<!-- #endif -->
+		<!-- #ifndef MP -->
+		<slot name="prefix" slot="prefix"></slot>
+		<slot name="suffix" slot="suffix"></slot>
+		<!-- #endif -->
+	</uvInput>
+</template>
+
+<script>
+	/**
+	 * 此组件存在的理由是,在nvue下,u-input被uni-app官方占用了,u-input在nvue中相当于input组件
+	 * 所以在nvue下,取名为u--input,内部其实还是u-input.vue,只不过做一层中转
+	 */
+	import uvInput from '../u-input/u-input.vue';
+	import props from '../u-input/props.js'
+	export default {
+		name: 'u--input',
+		mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
+		components: {
+			uvInput
+		},
+	}
+</script>

+ 44 - 0
uni_modules/uview-ui/components/u--text/u--text.vue

@@ -0,0 +1,44 @@
+<template>
+    <uvText
+        :type="type"
+        :show="show"
+        :text="text"
+        :prefixIcon="prefixIcon"
+        :suffixIcon="suffixIcon"
+        :mode="mode"
+        :href="href"
+        :format="format"
+        :call="call"
+        :openType="openType"
+        :bold="bold"
+        :block="block"
+        :lines="lines"
+        :color="color"
+		:decoration="decoration"
+        :size="size"
+        :iconStyle="iconStyle"
+        :margin="margin"
+        :lineHeight="lineHeight"
+        :align="align"
+        :wordWrap="wordWrap"
+        :customStyle="customStyle"
+        @click="$emit('click')"
+    ></uvText>
+</template>
+
+<script>
+/**
+ * 此组件存在的理由是,在nvue下,u-text被uni-app官方占用了,u-text在nvue中相当于input组件
+ * 所以在nvue下,取名为u--input,内部其实还是u-text.vue,只不过做一层中转
+ * 不使用v-bind="$attrs",而是分开独立写传参,是因为微信小程序不支持此写法
+ */
+import uvText from "../u-text/u-text.vue";
+import props from "../u-text/props.js";
+export default {
+    name: "u--text",
+    mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
+    components: {
+        uvText,
+    },
+};
+</script>

+ 48 - 0
uni_modules/uview-ui/components/u--textarea/u--textarea.vue

@@ -0,0 +1,48 @@
+<template>
+	<uvTextarea
+		:value="value"
+		:placeholder="placeholder"
+		:height="height"
+		:confirmType="confirmType"
+		:disabled="disabled"
+		:count="count"
+		:focus="focus"
+		:autoHeight="autoHeight"
+		:fixed="fixed"
+		:cursorSpacing="cursorSpacing"
+		:cursor="cursor"
+		:showConfirmBar="showConfirmBar"
+		:selectionStart="selectionStart"
+		:selectionEnd="selectionEnd"
+		:adjustPosition="adjustPosition"
+		:disableDefaultPadding="disableDefaultPadding"
+		:holdKeyboard="holdKeyboard"
+		:maxlength="maxlength"
+		:border="border"
+		:customStyle="customStyle"
+		:formatter="formatter"
+		:ignoreCompositionEvent="ignoreCompositionEvent"
+		@focus="e => $emit('focus')"
+		@blur="e => $emit('blur')"
+		@linechange="e => $emit('linechange', e)"
+		@confirm="e => $emit('confirm')"
+		@input="e => $emit('input', e)"
+		@keyboardheightchange="e => $emit('keyboardheightchange')"
+	></uvTextarea>
+</template>
+
+<script>
+	/**
+	 * 此组件存在的理由是,在nvue下,u--textarea被uni-app官方占用了,u-textarea在nvue中相当于textarea组件
+	 * 所以在nvue下,取名为u--textarea,内部其实还是u-textarea.vue,只不过做一层中转
+	 */
+	import uvTextarea from '../u-textarea/u-textarea.vue';
+	import props from '../u-textarea/props.js'
+	export default {
+		name: 'u--textarea',
+		mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
+		components: {
+			uvTextarea
+		},
+	}
+</script>

+ 54 - 0
uni_modules/uview-ui/components/u-action-sheet/props.js

@@ -0,0 +1,54 @@
+export default {
+    props: {
+        // 操作菜单是否展示 (默认false)
+        show: {
+            type: Boolean,
+            default: uni.$u.props.actionSheet.show
+        },
+        // 标题
+        title: {
+            type: String,
+            default: uni.$u.props.actionSheet.title
+        },
+        // 选项上方的描述信息
+        description: {
+            type: String,
+            default: uni.$u.props.actionSheet.description
+        },
+        // 数据
+        actions: {
+            type: Array,
+            default: uni.$u.props.actionSheet.actions
+        },
+        // 取消按钮的文字,不为空时显示按钮
+        cancelText: {
+            type: String,
+            default: uni.$u.props.actionSheet.cancelText
+        },
+        // 点击某个菜单项时是否关闭弹窗
+        closeOnClickAction: {
+            type: Boolean,
+            default: uni.$u.props.actionSheet.closeOnClickAction
+        },
+        // 处理底部安全区(默认true)
+        safeAreaInsetBottom: {
+            type: Boolean,
+            default: uni.$u.props.actionSheet.safeAreaInsetBottom
+        },
+        // 小程序的打开方式
+        openType: {
+            type: String,
+            default: uni.$u.props.actionSheet.openType
+        },
+        // 点击遮罩是否允许关闭 (默认true)
+        closeOnClickOverlay: {
+            type: Boolean,
+            default: uni.$u.props.actionSheet.closeOnClickOverlay
+        },
+        // 圆角值
+        round: {
+            type: [Boolean, String, Number],
+            default: uni.$u.props.actionSheet.round
+        }
+    }
+}

+ 278 - 0
uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue

@@ -0,0 +1,278 @@
+
+<template>
+	<u-popup
+	    :show="show"
+	    mode="bottom"
+	    @close="closeHandler"
+	    :safeAreaInsetBottom="safeAreaInsetBottom"
+	    :round="round"
+	>
+		<view class="u-action-sheet">
+			<view
+			    class="u-action-sheet__header"
+			    v-if="title"
+			>
+				<text class="u-action-sheet__header__title u-line-1">{{title}}</text>
+				<view
+				    class="u-action-sheet__header__icon-wrap"
+				    @tap.stop="cancel"
+				>
+					<u-icon
+					    name="close"
+					    size="17"
+					    color="#c8c9cc"
+					    bold
+					></u-icon>
+				</view>
+			</view>
+			<text
+			    class="u-action-sheet__description"
+				:style="[{
+					marginTop: `${title && description ? 0 : '18px'}`
+				}]"
+			    v-if="description"
+			>{{description}}</text>
+			<slot>
+				<u-line v-if="description"></u-line>
+				<view class="u-action-sheet__item-wrap">
+					<template v-for="(item, index) in actions">
+						<!-- #ifdef MP -->
+						<button
+						    :key="index"
+						    class="u-reset-button"
+						    :openType="item.openType"
+						    @getuserinfo="onGetUserInfo"
+						    @contact="onContact"
+						    @getphonenumber="onGetPhoneNumber"
+						    @error="onError"
+						    @launchapp="onLaunchApp"
+						    @opensetting="onOpenSetting"
+						    :lang="lang"
+						    :session-from="sessionFrom"
+						    :send-message-title="sendMessageTitle"
+						    :send-message-path="sendMessagePath"
+						    :send-message-img="sendMessageImg"
+						    :show-message-card="showMessageCard"
+						    :app-parameter="appParameter"
+						    @tap="selectHandler(index)"
+						    :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
+						>
+							<!-- #endif -->
+							<view
+							    class="u-action-sheet__item-wrap__item"
+							    @tap.stop="selectHandler(index)"
+							    :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
+							    :hover-stay-time="150"
+							>
+								<template v-if="!item.loading">
+									<text
+									    class="u-action-sheet__item-wrap__item__name"
+									    :style="[itemStyle(index)]"
+									>{{ item.name }}</text>
+									<text
+									    v-if="item.subname"
+									    class="u-action-sheet__item-wrap__item__subname"
+									>{{ item.subname }}</text>
+								</template>
+								<u-loading-icon
+								    v-else
+								    custom-class="van-action-sheet__loading"
+								    size="18"
+								    mode="circle"
+								/>
+							</view>
+							<!-- #ifdef MP -->
+						</button>
+						<!-- #endif -->
+						<u-line v-if="index !== actions.length - 1"></u-line>
+					</template>
+				</view>
+			</slot>
+			<u-gap
+			    bgColor="#eaeaec"
+			    height="6"
+			    v-if="cancelText"
+			></u-gap>
+			<view hover-class="u-action-sheet--hover">
+				<text
+				    @touchmove.stop.prevent
+				    :hover-stay-time="150"
+				    v-if="cancelText"
+				    class="u-action-sheet__cancel-text"
+				    @tap="cancel"
+				>{{cancelText}}</text>
+			</view>
+		</view>
+	</u-popup>
+</template>
+
+<script>
+	import openType from '../../libs/mixin/openType'
+	import button from '../../libs/mixin/button'
+	import props from './props.js';
+	/**
+	 * ActionSheet 操作菜单
+	 * @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。
+	 * @tutorial https://www.uviewui.com/components/actionSheet.html
+	 * 
+	 * @property {Boolean}			show				操作菜单是否展示 (默认 false )
+	 * @property {String}			title				操作菜单标题
+	 * @property {String}			description			选项上方的描述信息
+	 * @property {Array<Object>}	actions				按钮的文字数组,见官方文档示例
+	 * @property {String}			cancelText			取消按钮的提示文字,不为空时显示按钮
+	 * @property {Boolean}			closeOnClickAction	点击某个菜单项时是否关闭弹窗 (默认 true )
+	 * @property {Boolean}			safeAreaInsetBottom	处理底部安全区 (默认 true )
+	 * @property {String}			openType			小程序的打开方式 (contact | launchApp | getUserInfo | openSetting |getPhoneNumber |error )
+	 * @property {Boolean}			closeOnClickOverlay	点击遮罩是否允许关闭  (默认 true )
+	 * @property {Number|String}	round				圆角值,默认无圆角  (默认 0 )
+	 * @property {String}			lang				指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文
+	 * @property {String}			sessionFrom			会话来源,openType="contact"时有效
+	 * @property {String}			sendMessageTitle	会话内消息卡片标题,openType="contact"时有效
+	 * @property {String}			sendMessagePath		会话内消息卡片点击跳转小程序路径,openType="contact"时有效
+	 * @property {String}			sendMessageImg		会话内消息卡片图片,openType="contact"时有效
+	 * @property {Boolean}			showMessageCard		是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 (默认 false )
+	 * @property {String}			appParameter		打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效
+	 * 
+	 * @event {Function} select			点击ActionSheet列表项时触发 
+	 * @event {Function} close			点击取消按钮时触发
+	 * @event {Function} getuserinfo	用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效
+	 * @event {Function} contact		客服消息回调,openType="contact"时有效
+	 * @event {Function} getphonenumber	获取用户手机号回调,openType="getPhoneNumber"时有效
+	 * @event {Function} error			当使用开放能力时,发生错误的回调,openType="error"时有效
+	 * @event {Function} launchapp		打开 APP 成功的回调,openType="launchApp"时有效
+	 * @event {Function} opensetting	在打开授权设置页后回调,openType="openSetting"时有效
+	 * @example <u-action-sheet :actions="list" :title="title" :show="show"></u-action-sheet>
+	 */
+	export default {
+		name: "u-action-sheet",
+		// 一些props参数和methods方法,通过mixin混入,因为其他文件也会用到
+		mixins: [openType, button, uni.$u.mixin, props],
+		data() {
+			return {
+
+			}
+		},
+		computed: {
+			// 操作项目的样式
+			itemStyle() {
+				return (index) => {
+					let style = {};
+					if (this.actions[index].color) style.color = this.actions[index].color
+					if (this.actions[index].fontSize) style.fontSize = uni.$u.addUnit(this.actions[index].fontSize)
+					// 选项被禁用的样式
+					if (this.actions[index].disabled) style.color = '#c0c4cc'
+					return style;
+				}
+			},
+		},
+		methods: {
+			closeHandler() {
+				// 允许点击遮罩关闭时,才发出close事件
+				if(this.closeOnClickOverlay) {
+					this.$emit('close')
+				}
+			},
+			// 点击取消按钮
+			cancel() {
+				this.$emit('close')
+			},
+			selectHandler(index) {
+				const item = this.actions[index]
+				if (item && !item.disabled && !item.loading) {
+					this.$emit('select', item)
+					if (this.closeOnClickAction) {
+						this.$emit('close')
+					}
+				}
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import "../../libs/css/components.scss";
+	$u-action-sheet-reset-button-width:100% !default;
+	$u-action-sheet-title-font-size: 16px !default;
+	$u-action-sheet-title-padding: 12px 30px !default;
+	$u-action-sheet-title-color: $u-main-color !default;
+	$u-action-sheet-header-icon-wrap-right:15px !default;
+	$u-action-sheet-header-icon-wrap-top:15px !default;
+	$u-action-sheet-description-font-size:13px !default;
+	$u-action-sheet-description-color:14px !default;
+	$u-action-sheet-description-margin: 18px 15px !default;
+	$u-action-sheet-item-wrap-item-padding:15px !default;
+	$u-action-sheet-item-wrap-name-font-size:16px !default;
+	$u-action-sheet-item-wrap-subname-font-size:13px !default;
+	$u-action-sheet-item-wrap-subname-color: #c0c4cc !default;
+	$u-action-sheet-item-wrap-subname-margin-top:10px !default;
+	$u-action-sheet-cancel-text-font-size:16px !default;
+	$u-action-sheet-cancel-text-color:$u-content-color !default;
+	$u-action-sheet-cancel-text-font-size:15px !default;
+	$u-action-sheet-cancel-text-hover-background-color:rgb(242, 243, 245) !default;
+
+	.u-reset-button {
+		width: $u-action-sheet-reset-button-width;
+	}
+
+	.u-action-sheet {
+		text-align: center;
+		&__header {
+			position: relative;
+			padding: $u-action-sheet-title-padding;
+			&__title {
+				font-size: $u-action-sheet-title-font-size;
+				color: $u-action-sheet-title-color;
+				font-weight: bold;
+				text-align: center;
+			}
+
+			&__icon-wrap {
+				position: absolute;
+				right: $u-action-sheet-header-icon-wrap-right;
+				top: $u-action-sheet-header-icon-wrap-top;
+			}
+		}
+
+		&__description {
+			font-size: $u-action-sheet-description-font-size;
+			color: $u-tips-color;
+			margin: $u-action-sheet-description-margin;
+			text-align: center;
+		}
+
+		&__item-wrap {
+
+			&__item {
+				padding: $u-action-sheet-item-wrap-item-padding;
+				@include flex;
+				align-items: center;
+				justify-content: center;
+				flex-direction: column;
+
+				&__name {
+					font-size: $u-action-sheet-item-wrap-name-font-size;
+					color: $u-main-color;
+					text-align: center;
+				}
+
+				&__subname {
+					font-size: $u-action-sheet-item-wrap-subname-font-size;
+					color: $u-action-sheet-item-wrap-subname-color;
+					margin-top: $u-action-sheet-item-wrap-subname-margin-top;
+					text-align: center;
+				}
+			}
+		}
+
+		&__cancel-text {
+			font-size: $u-action-sheet-cancel-text-font-size;
+			color: $u-action-sheet-cancel-text-color;
+			text-align: center;
+			padding: $u-action-sheet-cancel-text-font-size;
+		}
+
+		&--hover {
+			background-color: $u-action-sheet-cancel-text-hover-background-color;
+		}
+	}
+</style>

+ 59 - 0
uni_modules/uview-ui/components/u-album/props.js

@@ -0,0 +1,59 @@
+export default {
+    props: {
+        // 图片地址,Array<String>|Array<Object>形式
+        urls: {
+            type: Array,
+            default: uni.$u.props.album.urls
+        },
+        // 指定从数组的对象元素中读取哪个属性作为图片地址
+        keyName: {
+            type: String,
+            default: uni.$u.props.album.keyName
+        },
+        // 单图时,图片长边的长度
+        singleSize: {
+            type: [String, Number],
+            default: uni.$u.props.album.singleSize
+        },
+        // 多图时,图片边长
+        multipleSize: {
+            type: [String, Number],
+            default: uni.$u.props.album.multipleSize
+        },
+        // 多图时,图片水平和垂直之间的间隔
+        space: {
+            type: [String, Number],
+            default: uni.$u.props.album.space
+        },
+        // 单图时,图片缩放裁剪的模式
+        singleMode: {
+            type: String,
+            default: uni.$u.props.album.singleMode
+        },
+        // 多图时,图片缩放裁剪的模式
+        multipleMode: {
+            type: String,
+            default: uni.$u.props.album.multipleMode
+        },
+        // 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量
+        maxCount: {
+            type: [String, Number],
+            default: uni.$u.props.album.maxCount
+        },
+        // 是否可以预览图片
+        previewFullImage: {
+            type: Boolean,
+            default: uni.$u.props.album.previewFullImage
+        },
+        // 每行展示图片数量,如设置,singleSize和multipleSize将会无效
+        rowCount: {
+            type: [String, Number],
+            default: uni.$u.props.album.rowCount
+        },
+        // 超出maxCount时是否显示查看更多的提示
+        showMore: {
+            type: Boolean,
+            default: uni.$u.props.album.showMore
+        }
+    }
+}

+ 259 - 0
uni_modules/uview-ui/components/u-album/u-album.vue

@@ -0,0 +1,259 @@
+<template>
+    <view class="u-album">
+        <view
+            class="u-album__row"
+            ref="u-album__row"
+            v-for="(arr, index) in showUrls"
+            :forComputedUse="albumWidth"
+            :key="index"
+        >
+            <view
+                class="u-album__row__wrapper"
+                v-for="(item, index1) in arr"
+                :key="index1"
+                :style="[imageStyle(index + 1, index1 + 1)]"
+                @tap="previewFullImage ? onPreviewTap(getSrc(item)) : ''"
+            >
+                <image
+                    :src="getSrc(item)"
+                    :mode="
+                        urls.length === 1
+                            ? imageHeight > 0
+                                ? singleMode
+                                : 'widthFix'
+                            : multipleMode
+                    "
+                    :style="[
+                        {
+                            width: imageWidth,
+                            height: imageHeight
+                        }
+                    ]"
+                ></image>
+                <view
+                    v-if="
+                        showMore &&
+                        urls.length > rowCount * showUrls.length &&
+                        index === showUrls.length - 1 &&
+                        index1 === showUrls[showUrls.length - 1].length - 1
+                    "
+                    class="u-album__row__wrapper__text"
+                >
+                    <u--text
+                        :text="`+${urls.length - maxCount}`"
+                        color="#fff"
+                        :size="multipleSize * 0.3"
+                        align="center"
+                        customStyle="justify-content: center"
+                    ></u--text>
+                </view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+import props from './props.js'
+// #ifdef APP-NVUE
+// 由于weex为阿里的KPI业绩考核的产物,所以不支持百分比单位,这里需要通过dom查询组件的宽度
+const dom = uni.requireNativePlugin('dom')
+// #endif
+
+/**
+ * Album 相册
+ * @description 本组件提供一个类似相册的功能,让开发者开发起来更加得心应手。减少重复的模板代码
+ * @tutorial https://www.uviewui.com/components/album.html
+ *
+ * @property {Array}           urls             图片地址列表 Array<String>|Array<Object>形式
+ * @property {String}          keyName          指定从数组的对象元素中读取哪个属性作为图片地址
+ * @property {String | Number} singleSize       单图时,图片长边的长度  (默认 180 )
+ * @property {String | Number} multipleSize     多图时,图片边长 (默认 70 )
+ * @property {String | Number} space            多图时,图片水平和垂直之间的间隔 (默认 6 )
+ * @property {String}          singleMode       单图时,图片缩放裁剪的模式 (默认 'scaleToFill' )
+ * @property {String}          multipleMode     多图时,图片缩放裁剪的模式 (默认 'aspectFill' )
+ * @property {String | Number} maxCount         取消按钮的提示文字 (默认 9 )
+ * @property {Boolean}         previewFullImage 是否可以预览图片 (默认 true )
+ * @property {String | Number} rowCount         每行展示图片数量,如设置,singleSize和multipleSize将会无效	(默认 3 )
+ * @property {Boolean}         showMore         超出maxCount时是否显示查看更多的提示 (默认 true )
+ *
+ * @event    {Function}        albumWidth       某些特殊的情况下,需要让文字与相册的宽度相等,这里事件的形式对外发送  (回调参数 width )
+ * @example <u-album :urls="urls2" @albumWidth="width => albumWidth = width" multipleSize="68" ></u-album>
+ */
+export default {
+    name: 'u-album',
+    mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
+    data() {
+        return {
+            // 单图的宽度
+            singleWidth: 0,
+            // 单图的高度
+            singleHeight: 0,
+            // 单图时,如果无法获取图片的尺寸信息,让图片宽度默认为容器的一定百分比
+            singlePercent: 0.6
+        }
+    },
+    watch: {
+        urls: {
+            immediate: true,
+            handler(newVal) {
+                if (newVal.length === 1) {
+                    this.getImageRect()
+                }
+            }
+        }
+    },
+    computed: {
+        imageStyle() {
+            return (index1, index2) => {
+                const { space, rowCount, multipleSize, urls } = this,
+                    { addUnit, addStyle } = uni.$u,
+                    rowLen = this.showUrls.length,
+                    allLen = this.urls.length
+                const style = {
+                    marginRight: addUnit(space),
+                    marginBottom: addUnit(space)
+                }
+                // 如果为最后一行,则每个图片都无需下边框
+                if (index1 === rowLen) style.marginBottom = 0
+                // 每行的最右边一张和总长度的最后一张无需右边框
+                if (
+                    index2 === rowCount ||
+                    (index1 === rowLen &&
+                        index2 === this.showUrls[index1 - 1].length)
+                )
+                    style.marginRight = 0
+                return style
+            }
+        },
+        // 将数组划分为二维数组
+        showUrls() {
+            const arr = []
+            this.urls.map((item, index) => {
+                // 限制最大展示数量
+                if (index + 1 <= this.maxCount) {
+                    // 计算该元素为第几个素组内
+                    const itemIndex = Math.floor(index / this.rowCount)
+                    // 判断对应的索引是否存在
+                    if (!arr[itemIndex]) {
+                        arr[itemIndex] = []
+                    }
+                    arr[itemIndex].push(item)
+                }
+            })
+            return arr
+        },
+        imageWidth() {
+            return uni.$u.addUnit(
+                this.urls.length === 1 ? this.singleWidth : this.multipleSize
+            )
+        },
+        imageHeight() {
+            return uni.$u.addUnit(
+                this.urls.length === 1 ? this.singleHeight : this.multipleSize
+            )
+        },
+        // 此变量无实际用途,仅仅是为了利用computed特性,让其在urls长度等变化时,重新计算图片的宽度
+        // 因为用户在某些特殊的情况下,需要让文字与相册的宽度相等,所以这里事件的形式对外发送
+        albumWidth() {
+            let width = 0
+            if (this.urls.length === 1) {
+                width = this.singleWidth
+            } else {
+                width =
+                    this.showUrls[0].length * this.multipleSize +
+                    this.space * (this.showUrls[0].length - 1)
+            }
+            this.$emit('albumWidth', width)
+            return width
+        }
+    },
+    methods: {
+        // 预览图片
+        onPreviewTap(url) {
+            const urls = this.urls.map((item) => {
+                return this.getSrc(item)
+            })
+            uni.previewImage({
+                current: url,
+                urls
+            })
+        },
+        // 获取图片的路径
+        getSrc(item) {
+            return uni.$u.test.object(item)
+                ? (this.keyName && item[this.keyName]) || item.src
+                : item
+        },
+        // 单图时,获取图片的尺寸
+        // 在小程序中,需要将网络图片的的域名添加到小程序的download域名才可能获取尺寸
+        // 在没有添加的情况下,让单图宽度默认为盒子的一定宽度(singlePercent)
+        getImageRect() {
+            const src = this.getSrc(this.urls[0])
+            uni.getImageInfo({
+                src,
+                success: (res) => {
+                    // 判断图片横向还是竖向展示方式
+                    const isHorizotal = res.width >= res.height
+                    this.singleWidth = isHorizotal
+                        ? this.singleSize
+                        : (res.width / res.height) * this.singleSize
+                    this.singleHeight = !isHorizotal
+                        ? this.singleSize
+                        : (res.height / res.width) * this.singleWidth
+                },
+                fail: () => {
+                    this.getComponentWidth()
+                }
+            })
+        },
+        // 获取组件的宽度
+        async getComponentWidth() {
+            // 延时一定时间,以获取dom尺寸
+            await uni.$u.sleep(30)
+            // #ifndef APP-NVUE
+            this.$uGetRect('.u-album__row').then((size) => {
+                this.singleWidth = size.width * this.singlePercent
+            })
+            // #endif
+
+            // #ifdef APP-NVUE
+            // 这里ref="u-album__row"所在的标签为通过for循环出来,导致this.$refs['u-album__row']是一个数组
+            const ref = this.$refs['u-album__row'][0]
+            ref &&
+                dom.getComponentRect(ref, (res) => {
+                    this.singleWidth = res.size.width * this.singlePercent
+                })
+            // #endif
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../libs/css/components.scss';
+
+.u-album {
+    @include flex(column);
+
+    &__row {
+        @include flex(row);
+        flex-wrap: wrap;
+
+        &__wrapper {
+            position: relative;
+
+            &__text {
+                position: absolute;
+                top: 0;
+                left: 0;
+                right: 0;
+                bottom: 0;
+                background-color: rgba(0, 0, 0, 0.3);
+                @include flex(row);
+                justify-content: center;
+                align-items: center;
+            }
+        }
+    }
+}
+</style>

+ 44 - 0
uni_modules/uview-ui/components/u-alert/props.js

@@ -0,0 +1,44 @@
+export default {
+    props: {
+        // 显示文字
+        title: {
+            type: String,
+            default: uni.$u.props.alert.title
+        },
+        // 主题,success/warning/info/error
+        type: {
+            type: String,
+            default: uni.$u.props.alert.type
+        },
+        // 辅助性文字
+        description: {
+            type: String,
+            default: uni.$u.props.alert.description
+        },
+        // 是否可关闭
+        closable: {
+            type: Boolean,
+            default: uni.$u.props.alert.closable
+        },
+        // 是否显示图标
+        showIcon: {
+            type: Boolean,
+            default: uni.$u.props.alert.showIcon
+        },
+        // 浅或深色调,light-浅色,dark-深色
+        effect: {
+            type: String,
+            default: uni.$u.props.alert.effect
+        },
+        // 文字是否居中
+        center: {
+            type: Boolean,
+            default: uni.$u.props.alert.center
+        },
+        // 字体大小
+        fontSize: {
+            type: [String, Number],
+            default: uni.$u.props.alert.fontSize
+        }
+    }
+}

+ 243 - 0
uni_modules/uview-ui/components/u-alert/u-alert.vue

@@ -0,0 +1,243 @@
+<template>
+	<u-transition
+	    mode="fade"
+	    :show="show"
+	>
+		<view
+		    class="u-alert"
+		    :class="[`u-alert--${type}--${effect}`]"
+		    @tap.stop="clickHandler"
+		    :style="[$u.addStyle(customStyle)]"
+		>
+			<view
+			    class="u-alert__icon"
+			    v-if="showIcon"
+			>
+				<u-icon
+				    :name="iconName"
+				    size="18"
+				    :color="iconColor"
+				></u-icon>
+			</view>
+			<view
+			    class="u-alert__content"
+			    :style="[{
+					paddingRight: closable ? '20px' : 0
+				}]"
+			>
+				<text
+				    class="u-alert__content__title"
+				    v-if="title"
+					:style="[{
+						fontSize: $u.addUnit(fontSize),
+						textAlign: center ? 'center' : 'left'
+					}]"
+				    :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
+				>{{ title }}</text>
+				<text
+				    class="u-alert__content__desc"
+					v-if="description"
+					:style="[{
+						fontSize: $u.addUnit(fontSize),
+						textAlign: center ? 'center' : 'left'
+					}]"
+				    :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
+				>{{ description }}</text>
+			</view>
+			<view
+			    class="u-alert__close"
+			    v-if="closable"
+			    @tap.stop="closeHandler"
+			>
+				<u-icon
+				    name="close"
+				    :color="iconColor"
+				    size="15"
+				></u-icon>
+			</view>
+		</view>
+	</u-transition>
+</template>
+
+<script>
+	import props from './props.js';
+	/**
+	 * Alert  警告提示
+	 * @description 警告提示,展现需要关注的信息。
+	 * @tutorial https://www.uviewui.com/components/alertTips.html
+	 * 
+	 * @property {String}			title       显示的文字 
+	 * @property {String}			type        使用预设的颜色  (默认 'warning' )
+	 * @property {String}			description 辅助性文字,颜色比title浅一点,字号也小一点,可选  
+	 * @property {Boolean}			closable    关闭按钮(默认为叉号icon图标)  (默认 false )
+	 * @property {Boolean}			showIcon    是否显示左边的辅助图标   ( 默认 false )
+	 * @property {String}			effect      多图时,图片缩放裁剪的模式  (默认 'light' )
+	 * @property {Boolean}			center		文字是否居中  (默认 false )
+	 * @property {String | Number}	fontSize    字体大小  (默认 14 )
+	 * @property {Object}			customStyle	定义需要用到的外部样式
+	 * @event    {Function}        click       点击组件时触发
+	 * @example  <u-alert :title="title"  type = "warning" :closable="closable" :description = "description"></u-alert>
+	 */
+	export default {
+		name: 'u-alert',
+		mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
+		data() {
+			return {
+				show: true
+			}
+		},
+		computed: {
+			iconColor() {
+				return this.effect === 'light' ? this.type : '#fff'
+			},
+			// 不同主题对应不同的图标
+			iconName() {
+				switch (this.type) {
+					case 'success':
+						return 'checkmark-circle-fill';
+						break;
+					case 'error':
+						return 'close-circle-fill';
+						break;
+					case 'warning':
+						return 'error-circle-fill';
+						break;
+					case 'info':
+						return 'info-circle-fill';
+						break;
+					case 'primary':
+						return 'more-circle-fill';
+						break;
+					default: 
+						return 'error-circle-fill';
+				}
+			}
+		},
+		methods: {
+			// 点击内容
+			clickHandler() {
+				this.$emit('click')
+			},
+			// 点击关闭按钮
+			closeHandler() {
+				this.show = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import "../../libs/css/components.scss";
+
+	.u-alert {
+		position: relative;
+		background-color: $u-primary;
+		padding: 8px 10px;
+		@include flex(row);
+		align-items: center;
+		border-top-left-radius: 4px;
+		border-top-right-radius: 4px;
+		border-bottom-left-radius: 4px;
+		border-bottom-right-radius: 4px;
+
+		&--primary--dark {
+			background-color: $u-primary;
+		}
+
+		&--primary--light {
+			background-color: #ecf5ff;
+		}
+
+		&--error--dark {
+			background-color: $u-error;
+		}
+
+		&--error--light {
+			background-color: #FEF0F0;
+		}
+
+		&--success--dark {
+			background-color: $u-success;
+		}
+
+		&--success--light {
+			background-color: #f5fff0;
+		}
+
+		&--warning--dark {
+			background-color: $u-warning;
+		}
+
+		&--warning--light {
+			background-color: #FDF6EC;
+		}
+
+		&--info--dark {
+			background-color: $u-info;
+		}
+
+		&--info--light {
+			background-color: #f4f4f5;
+		}
+
+		&__icon {
+			margin-right: 5px;
+		}
+
+		&__content {
+			@include flex(column);
+			flex: 1;
+
+			&__title {
+				color: $u-main-color;
+				font-size: 14px;
+				font-weight: bold;
+				color: #fff;
+				margin-bottom: 2px;
+			}
+
+			&__desc {
+				color: $u-main-color;
+				font-size: 14px;
+				flex-wrap: wrap;
+				color: #fff;
+			}
+		}
+
+		&__title--dark,
+		&__desc--dark {
+			color: #FFFFFF;
+		}
+
+		&__text--primary--light,
+		&__text--primary--light {
+			color: $u-primary;
+		}
+
+		&__text--success--light,
+		&__text--success--light {
+			color: $u-success;
+		}
+
+		&__text--warning--light,
+		&__text--warning--light {
+			color: $u-warning;
+		}
+
+		&__text--error--light,
+		&__text--error--light {
+			color: $u-error;
+		}
+
+		&__text--info--light,
+		&__text--info--light {
+			color: $u-info;
+		}
+
+		&__close {
+			position: absolute;
+			top: 11px;
+			right: 10px;
+		}
+	}
+</style>

+ 52 - 0
uni_modules/uview-ui/components/u-avatar-group/props.js

@@ -0,0 +1,52 @@
+export default {
+    props: {
+        // 头像图片组
+        urls: {
+            type: Array,
+            default: uni.$u.props.avatarGroup.urls
+        },
+        // 最多展示的头像数量
+        maxCount: {
+            type: [String, Number],
+            default: uni.$u.props.avatarGroup.maxCount
+        },
+        // 头像形状
+        shape: {
+            type: String,
+            default: uni.$u.props.avatarGroup.shape
+        },
+        // 图片裁剪模式
+        mode: {
+            type: String,
+            default: uni.$u.props.avatarGroup.mode
+        },
+        // 超出maxCount时是否显示查看更多的提示
+        showMore: {
+            type: Boolean,
+            default: uni.$u.props.avatarGroup.showMore
+        },
+        // 头像大小
+        size: {
+            type: [String, Number],
+            default: uni.$u.props.avatarGroup.size
+        },
+        // 指定从数组的对象元素中读取哪个属性作为图片地址
+        keyName: {
+            type: String,
+            default: uni.$u.props.avatarGroup.keyName
+        },
+		// 头像之间的遮挡比例
+        gap: {
+            type: [String, Number],
+            validator(value) {
+                return value >= 0 && value <= 1
+            },
+            default: uni.$u.props.avatarGroup.gap
+        },
+		// 需额外显示的值
+		extraValue: {
+			type: [Number, String],
+			default: uni.$u.props.avatarGroup.extraValue
+		}
+    }
+}

+ 103 - 0
uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue

@@ -0,0 +1,103 @@
+<template>
+	<view class="u-avatar-group">
+		<view
+		    class="u-avatar-group__item"
+		    v-for="(item, index) in showUrl"
+		    :key="index"
+		    :style="{
+				marginLeft: index === 0 ? 0 : $u.addUnit(-size * gap)
+			}"
+		>
+			<u-avatar
+			    :size="size"
+			    :shape="shape"
+			    :mode="mode"
+			    :src="$u.test.object(item) ? keyName && item[keyName] || item.url : item"
+			></u-avatar>
+			<view
+			    class="u-avatar-group__item__show-more"
+			    v-if="showMore && index === showUrl.length - 1 && (urls.length > maxCount || extraValue > 0)"
+				@tap="clickHandler"
+			>
+				<u--text
+				    color="#ffffff"
+				    :size="size * 0.4"
+				    :text="`+${extraValue || urls.length - showUrl.length}`"
+					align="center"
+					customStyle="justify-content: center"
+				></u--text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import props from './props.js';
+	/**
+	 * AvatarGroup  头像组
+	 * @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
+	 * @tutorial https://www.uviewui.com/components/avatar.html
+	 * 
+	 * @property {Array}           urls     头像图片组 (默认 [] )
+	 * @property {String | Number} maxCount 最多展示的头像数量 ( 默认 5 )
+	 * @property {String}          shape    头像形状( 'circle' (默认) | 'square' )
+	 * @property {String}          mode     图片裁剪模式(默认 'scaleToFill' )
+	 * @property {Boolean}         showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
+	 * @property {String | Number} size      头像大小 (默认 40 )
+	 * @property {String}          keyName  指定从数组的对象元素中读取哪个属性作为图片地址 
+	 * @property {String | Number} gap      头像之间的遮挡比例(0.4代表遮挡40%)  (默认 0.5 )
+	 * @property {String | Number} extraValue  需额外显示的值
+	 * @event    {Function}        showMore 头像组更多点击
+	 * @example  <u-avatar-group:urls="urls" size="35" gap="0.4" ></u-avatar-group:urls=>
+	 */
+	export default {
+		name: 'u-avatar-group',
+		mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
+		data() {
+			return {
+
+			}
+		},
+		computed: {
+			showUrl() {
+				return this.urls.slice(0, this.maxCount)
+			}
+		},
+		methods: {
+			clickHandler() {
+				this.$emit('showMore')
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import "../../libs/css/components.scss";
+
+	.u-avatar-group {
+		@include flex;
+
+		&__item {
+			margin-left: -10px;
+			position: relative;
+
+			&--no-indent {
+				// 如果你想质疑作者不会使用:first-child,说明你太年轻,因为nvue不支持
+				margin-left: 0;
+			}
+
+			&__show-more {
+				position: absolute;
+				top: 0;
+				bottom: 0;
+				left: 0;
+				right: 0;
+				background-color: rgba(0, 0, 0, 0.3);
+				@include flex;
+				align-items: center;
+				justify-content: center;
+				border-radius: 100px;
+			}
+		}
+	}
+</style>

+ 0 - 0
uni_modules/uview-ui/components/u-avatar/props.js


部分文件因为文件数量过多而无法显示