JXDS18FUJT 1 jaar geleden
bovenliggende
commit
7deda2a40d
99 gewijzigde bestanden met toevoegingen van 8114 en 206 verwijderingen
  1. 8 1
      src/App.vue
  2. 1 1
      src/api/request.ts
  3. 9 3
      src/custom-tab-bar/index.js
  4. 40 8
      src/pages.json
  5. 1 1
      src/pages/createReferCode/index.vue
  6. 16 16
      src/pages/forecast/index.vue
  7. 1 170
      src/pages/future/index.vue
  8. 195 0
      src/pages/future1/index.vue
  9. 195 0
      src/pages/future2/index.vue
  10. 195 0
      src/pages/future3/index.vue
  11. 3 3
      src/pages/home/index.vue
  12. 184 0
      src/pages/myfuture/index.vue
  13. 2 1
      src/pages/user/index.vue
  14. 43 0
      src/store/index.ts
  15. 111 0
      src/wxcomponents/vant/action-sheet/index.vue
  16. 234 0
      src/wxcomponents/vant/area/index.vue
  17. 90 0
      src/wxcomponents/vant/button/index.vue
  18. 37 0
      src/wxcomponents/vant/calendar/calendar.vue
  19. 64 0
      src/wxcomponents/vant/calendar/components/header/index.vue
  20. 192 0
      src/wxcomponents/vant/calendar/components/month/index.vue
  21. 365 0
      src/wxcomponents/vant/calendar/index.vue
  22. 105 0
      src/wxcomponents/vant/card/index.vue
  23. 28 0
      src/wxcomponents/vant/cell-group/index.vue
  24. 74 0
      src/wxcomponents/vant/cell/index.vue
  25. 50 0
      src/wxcomponents/vant/checkbox-group/index.vue
  26. 102 0
      src/wxcomponents/vant/checkbox/index.vue
  27. 211 0
      src/wxcomponents/vant/circle/index.vue
  28. 23 0
      src/wxcomponents/vant/col/index.vue
  29. 86 0
      src/wxcomponents/vant/collapse-item/index.vue
  30. 60 0
      src/wxcomponents/vant/collapse/index.vue
  31. 1 0
      src/wxcomponents/vant/common/index.css
  32. 1 0
      src/wxcomponents/vant/common/style/clearfix.css
  33. 1 0
      src/wxcomponents/vant/common/style/ellipsis.css
  34. 1 0
      src/wxcomponents/vant/common/style/hairline.css
  35. 0 0
      src/wxcomponents/vant/common/style/mixins/clearfix.css
  36. 0 0
      src/wxcomponents/vant/common/style/mixins/ellipsis.css
  37. 0 0
      src/wxcomponents/vant/common/style/mixins/hairline.css
  38. 0 0
      src/wxcomponents/vant/common/style/var.css
  39. 23 0
      src/wxcomponents/vant/config-provider/index.vue
  40. 115 0
      src/wxcomponents/vant/count-down/index.vue
  41. 309 0
      src/wxcomponents/vant/datetime-picker/index.vue
  42. 167 0
      src/wxcomponents/vant/dialog/index.vue
  43. 28 0
      src/wxcomponents/vant/divider/index.vue
  44. 129 0
      src/wxcomponents/vant/dropdown-item/index.vue
  45. 134 0
      src/wxcomponents/vant/dropdown-menu/index.vue
  46. 42 0
      src/wxcomponents/vant/empty/index.vue
  47. 149 0
      src/wxcomponents/vant/field/index.vue
  48. 15 0
      src/wxcomponents/vant/field/input.vue
  49. 15 0
      src/wxcomponents/vant/field/textarea.vue
  50. 53 0
      src/wxcomponents/vant/goods-action-button/index.vue
  51. 44 0
      src/wxcomponents/vant/goods-action-icon/index.vue
  52. 29 0
      src/wxcomponents/vant/goods-action/index.vue
  53. 82 0
      src/wxcomponents/vant/grid-item/index.vue
  54. 69 0
      src/wxcomponents/vant/grid/index.vue
  55. 35 0
      src/wxcomponents/vant/icon/index.vue
  56. 86 0
      src/wxcomponents/vant/image/index.vue
  57. 44 0
      src/wxcomponents/vant/index-anchor/index.vue
  58. 266 0
      src/wxcomponents/vant/index-bar/index.vue
  59. 20 0
      src/wxcomponents/vant/info/index.vue
  60. 33 0
      src/wxcomponents/vant/loading/index.vue
  61. 99 0
      src/wxcomponents/vant/nav-bar/index.vue
  62. 150 0
      src/wxcomponents/vant/notice-bar/index.vue
  63. 84 0
      src/wxcomponents/vant/notify/index.vue
  64. 1 1
      src/wxcomponents/vant/notify/notify.js
  65. 45 0
      src/wxcomponents/vant/overlay/index.vue
  66. 34 0
      src/wxcomponents/vant/panel/index.vue
  67. 134 0
      src/wxcomponents/vant/picker-column/index.vue
  68. 165 0
      src/wxcomponents/vant/picker/index.vue
  69. 25 0
      src/wxcomponents/vant/picker/toolbar.vue
  70. 106 0
      src/wxcomponents/vant/popup/index.vue
  71. 69 0
      src/wxcomponents/vant/progress/index.vue
  72. 36 0
      src/wxcomponents/vant/radio-group/index.vue
  73. 91 0
      src/wxcomponents/vant/radio/index.vue
  74. 98 0
      src/wxcomponents/vant/rate/index.vue
  75. 37 0
      src/wxcomponents/vant/row/index.vue
  76. 118 0
      src/wxcomponents/vant/search/index.vue
  77. 94 0
      src/wxcomponents/vant/share-sheet/index.vue
  78. 36 0
      src/wxcomponents/vant/share-sheet/options.vue
  79. 49 0
      src/wxcomponents/vant/sidebar-item/index.vue
  80. 48 0
      src/wxcomponents/vant/sidebar/index.vue
  81. 69 0
      src/wxcomponents/vant/skeleton/index.vue
  82. 219 0
      src/wxcomponents/vant/slider/index.vue
  83. 203 0
      src/wxcomponents/vant/stepper/index.vue
  84. 12 0
      src/wxcomponents/vant/steps/index-status.wxs
  85. 63 0
      src/wxcomponents/vant/steps/index.vue
  86. 134 0
      src/wxcomponents/vant/sticky/index.vue
  87. 98 0
      src/wxcomponents/vant/submit-bar/index.vue
  88. 155 0
      src/wxcomponents/vant/swipe-cell/index.vue
  89. 54 0
      src/wxcomponents/vant/switch/index.vue
  90. 70 0
      src/wxcomponents/vant/tab/index.vue
  91. 83 0
      src/wxcomponents/vant/tabbar-item/index.vue
  92. 81 0
      src/wxcomponents/vant/tabbar/index.vue
  93. 309 0
      src/wxcomponents/vant/tabs/index.vue
  94. 38 0
      src/wxcomponents/vant/tag/index.vue
  95. 64 0
      src/wxcomponents/vant/toast/index.vue
  96. 27 0
      src/wxcomponents/vant/transition/index.vue
  97. 97 0
      src/wxcomponents/vant/tree-select/index.vue
  98. 202 0
      src/wxcomponents/vant/uploader/index.vue
  99. 1 1
      src/wxcomponents/vant/wxs/array.wxs

+ 8 - 1
src/App.vue

@@ -1,10 +1,14 @@
 <script lang="ts">
 import Vue from 'vue';
+import store from './store'
+import api from '@/api'
 export default Vue.extend({
     mpType: 'app',
     onLaunch() {
         uni.setStorageSync("NODE_ENV", process.env.NODE_ENV);
-        console.log('App Launch')
+        api.openApi.openApiSystemDictDataConfigKey('IS_BAZI').then(res=>{
+            store.commit('SET_BAZIISPAY',res.data.data)
+        })
     },
     onShow() {
         console.log('App Show')
@@ -30,6 +34,9 @@ view {
 .hidden{
     display: none !important;
 }
+.block{
+    display: block !important;
+}
 /*每个页面公共css */
 /* .primary-bg-light-blue {
     background-color: #BFE2F4;

+ 1 - 1
src/api/request.ts

@@ -2,7 +2,7 @@ import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
 import axiosAdapterUniapp from 'axios-adapter-uniapp'
 import { config } from "vue/types/umd";
 const request = axios.create({
-    baseURL: process.env.NODE_ENV === "production" ? "https://xpgx.zzxcx.net/prod-api/" : "https://107j18o08.vicp.fun/",
+    baseURL: process.env.NODE_ENV === "production" ? "https://xpgx.zzxcx.net/prod-api/" : "https://xpgx1.zzxcx.net/stage-api/",
 
 
 });

+ 9 - 3
src/custom-tab-bar/index.js

@@ -28,7 +28,13 @@ Component({
 		],
 		list: [
 		{
-			"pagePath": "/pages/future/index",
+			"pagePath": "/pages/home/index",
+			"iconPath": "/static/icon/主页空心@2x.png",
+			"selectedIconPath": "/static/icon/主页实心@2x.png",
+			"text": "主页"
+		},
+		{
+			"pagePath": "/pages/myfuture/index",
 			"iconPath": "/static/icon/排盘空心@2x.png",
 			"selectedIconPath": "/static/icon/排盘实心@2x.png",
 			"text": "人生报告"
@@ -73,9 +79,9 @@ Component({
 			const data = e.currentTarget.dataset
 			const url = data.path
 			
-			if(url=='/pages/future/index'){
+			if(url=='/pages/myfuture/index'){
 				wx.navigateTo({
-					url:'/pages/future/index'
+					url:'/pages/myfuture/index'
 				})
 				return
 

+ 40 - 8
src/pages.json

@@ -1,17 +1,40 @@
 {
 	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/home/index",
+			"style": {
+				"navigationBarTitleText": "首页"
+			}
+		},
 		{
 			"path": "pages/future/index",
 			"style": {
-				"navigationBarTitleText": "人生报告"
+				"navigationBarTitleText": ""
+			
 			}
 		},
 		{
-			"path": "pages/home/index",
+			"path": "pages/future1/index",
 			"style": {
-				"navigationBarTitleText": "首页"
+				"navigationBarTitleText": ""
+			
+			}
+		},
+		{
+			"path": "pages/future2/index",
+			"style": {
+				"navigationBarTitleText": ""
+			
+			}
+		},
+		{
+			"path": "pages/future3/index",
+			"style": {
+				"navigationBarTitleText": ""
+			
 			}
 		},
+	
 		{
 			"path": "pages/user/index",
 			"style": {
@@ -53,20 +76,29 @@
 			"style": {
 				"navigationBarTitleText": "推广码"
 			}
+		},
+		{
+			"path": "pages/myfuture/index",
+			"style": {
+				"navigationBarTitleText": "人生报告",
+				"usingComponents":{
+					"custom-tab-bar":"./../../custom-tab-bar/index"
+				}
+			}
 		}
 	],
 	"tabBar": {
-		"custom": false,
+		"custom": true,
 		"color": "#3D3D3D",
 		"selectedColor": "#B08A4A",
 		"borderStyle": "white",
 		"backgroundColor": "#ffffff",
 		"list": [
 			{
-				"pagePath": "pages/future/index",
-				"iconPath": "static/icon/排盘空心@2x.png",
-				"selectedIconPath": "static/icon/排盘实心@2x.png",
-				"text": "人生报告"
+				"pagePath": "pages/home/index",
+				"iconPath": "static/icon/主页空心@2x.png",
+				"selectedIconPath": "static/icon/主页实心@2x.png",
+				"text": "主页"
 			},
 			{
 				"pagePath": "pages/user/index",

+ 1 - 1
src/pages/createReferCode/index.vue

@@ -45,7 +45,7 @@ export default {
         let userInfo = uni.getStorageSync('userInfo')
         return {
             title:'人生报告',
-            url:"/pages/future/index?punionId="+userInfo.unionId
+            url:"/pages/myfuture/index?punionId="+userInfo.unionId
         }
 
     }

+ 16 - 16
src/pages/forecast/index.vue

@@ -24,7 +24,7 @@
 
         </view>
         <!-- <button @click="pay">支付</button> -->
-        <view class="categorys" :class="{'hidden':baZiIsPay!='1'}">
+        <view class="categorys" :class="{'block':baZiIsPay!='-1'}">
             <view style="width:100%">
                 <view class="categorys-item" :key="index" v-for="(item, index) in categorys">
                     <view :data-theme="theme" @click="() => {
@@ -165,7 +165,7 @@
                 </view>
             </view>
 
-            <view id="grtd" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="grtd" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>个</text><text>人</text><text>特</text><text>点</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -189,7 +189,7 @@
             </view>
             <view style="width: 100%;height: 35rpx;"></view>
 
-            <view id="cyfx" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="cyfx" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>财</text><text>运</text><text>分</text><text>析</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -213,7 +213,7 @@
                     :src="'https://ndata.zzxcx.net/xpgx-xcx/forecast/reportBg/bg_' + theme + '_bottom@2x.png'" />
             </view>
             <view style="width: 100%;height: 35rpx;"></view>
-            <view id="hyqg" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="hyqg" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>婚</text><text>姻</text><text>情</text><text>感</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -237,7 +237,7 @@
                 <img mode="widthFix" class="imgFooter"
                     :src="'https://ndata.zzxcx.net/xpgx-xcx/forecast/reportBg/bg_' + theme + '_bottom@2x.png'" />
             </view>
-            <view id="zngx" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="zngx" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>子</text><text>女</text><text>关</text><text>系</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -262,7 +262,7 @@
                     :src="'https://ndata.zzxcx.net/xpgx-xcx/forecast/reportBg/bg_' + theme + '_bottom@2x.png'" />
             </view>
             <view style="width: 100%;height: 35rpx;"></view>
-            <view id="wxpy" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="wxpy" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>五</text><text>行</text><text>评</text><text>语</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -284,7 +284,7 @@
             </view>
 
             <view style="width: 100%;height: 35rpx;"></view>
-            <!-- <view id="csph" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <!-- <view id="csph" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>潮</text><text>湿</text><text>平</text><text>衡</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -302,7 +302,7 @@
             </view> -->
 
             <view style="width: 100%;height: 35rpx;"></view>
-            <view id="xysz" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="xysz" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>喜</text><text>用</text><text>数</text><text>字</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -351,7 +351,7 @@
             </view>
 
             <view style="width: 100%;height: 35rpx;"></view>
-            <view id="gjpq" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="gjpq" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>格</text><text>局</text><text>脾</text><text>气</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -376,7 +376,7 @@
             </view>
 
             <view style="width: 100%;height: 35rpx;"></view>
-            <view id="cgpy" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="cgpy" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>称</text><text>骨</text><text>评</text><text>语</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -406,7 +406,7 @@
             </view>
 
             <view style="width: 100%;height: 35rpx;"></view>
-            <view id="jkyf" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="jkyf" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>健</text><text>康</text><text>预</text><text>防</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -433,7 +433,7 @@
             </view>
 
             <view style="width: 100%;height: 35rpx;"></view>
-            <view id="xyfw" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="xyfw" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>喜</text><text>用</text><text>方</text><text>位</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -458,7 +458,7 @@
             </view>
 
             <view style="width: 100%;height: 35rpx;"></view>
-            <view id="mzgr" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="mzgr" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>命</text><text>中</text><text>贵</text><text>人</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -481,7 +481,7 @@
                     :src="'https://ndata.zzxcx.net/xpgx-xcx/forecast/reportBg/bg_' + theme + '_bottom@2x.png'" />
             </view>
             <view style="width: 100%;height: 35rpx;"></view>
-            <view id="tjhy" class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view id="tjhy" class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>推</text><text>荐</text><text>行</text><text>业</text></view>
                 <img mode="widthFix" class="imgHeader"
@@ -504,7 +504,7 @@
             </view>
 
 
-            <!-- <view class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <!-- <view class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>十</text><text>神</text><text>评</text><text>语</text></view>
                 <img mode="widthFix" class="imgHeader" :src="'https://ndata.zzxcx.net/xpgx-xcx/forecast/reportBg/bg_'+theme+'_top@2x.png'" />
@@ -533,7 +533,7 @@
                 <img mode="widthFix" class="imgFooter" :src="'https://ndata.zzxcx.net/xpgx-xcx/forecast/reportBg/bg_'+theme+'_bottom@2x.png'" />
             </view> -->
             <!-- <view style="width: 100%;height: 35rpx;"></view>
-            <view class="result" :class="{'hidden':baZiIsPay!='1'}">
+            <view class="result" :class="{'block':baZiIsPay!='-1'}">
                 <img mode="widthFix" class="imgCircle" src="https://ndata.zzxcx.net/xpgx-xcx/forecast/circle.png">
                 <view :data-theme="theme" class="imgTitle"><text>五</text><text>行</text><text>评</text><text>语</text></view>
                 <img mode="widthFix" class="imgHeader" :src="'https://ndata.zzxcx.net/xpgx-xcx/forecast/reportBg/bg_'+theme+'_top@2x.png'" />

File diff suppressed because it is too large
+ 1 - 170
src/pages/future/index.vue


File diff suppressed because it is too large
+ 195 - 0
src/pages/future1/index.vue


File diff suppressed because it is too large
+ 195 - 0
src/pages/future2/index.vue


File diff suppressed because it is too large
+ 195 - 0
src/pages/future3/index.vue


+ 3 - 3
src/pages/home/index.vue

@@ -22,10 +22,10 @@
                 <navigator url="/pages/terminology/index"><img mode="widthFix" class="w-full"
                         src="https://ndata.zzxcx.net/xpgx-xcx/home/item2@2x.png"></navigator>
             </div>
-            <div class="item">
+            <!-- <div class="item">
                 <navigator url="/pages/future/index"><img mode="widthFix" class="w-full"
                         src="https://ndata.zzxcx.net/xpgx-xcx/home/item3@2x.png"></navigator>
-            </div>
+            </div> -->
         </div>
 
 
@@ -130,7 +130,7 @@ export default {
 
 .page {
     width: 100vw;
-
+    min-height:100vh ;
     background-color: #F6ECDB;
 }
 

File diff suppressed because it is too large
+ 184 - 0
src/pages/myfuture/index.vue


File diff suppressed because it is too large
+ 2 - 1
src/pages/user/index.vue


+ 43 - 0
src/store/index.ts

@@ -0,0 +1,43 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+Vue.use(Vuex)
+//自定义getters
+
+//自定义getters
+const store = new Vuex.Store({
+
+    state: {
+        
+        count: 0,
+        school: '清华大学',
+        baZiIsPay:'0'
+    },
+    getters: {
+        // 返回处理后的state值
+        getValue(state) {
+            return state.count + '!'
+        },
+        // 返回调用自身getters处理后的state值
+        getGetters(state, getters) {
+            return state.school + getters.getValue
+        },
+        // 接受外部传参后处理的值(在通过方法访问时,每次都会去进行调用,而不会缓存结果)
+        getParam(state) {
+            return (param: string) => {
+                return state.school + param
+            }
+        }
+    },
+    mutations: {
+        SET_BAZIISPAY(state,baZiIsPay:string){
+            state.baZiIsPay = baZiIsPay
+            // console.log(state)
+            return state
+
+        }
+        
+    },
+    actions: {},
+    modules: {}
+})
+export default store

+ 111 - 0
src/wxcomponents/vant/action-sheet/index.vue

@@ -0,0 +1,111 @@
+<template>
+<uni-shadow-root class="vant-action-sheet-index"><van-popup :show="show" position="bottom" :round="round" :z-index="zIndex" :overlay="overlay" custom-class="van-action-sheet" :safe-area-inset-bottom="safeAreaInsetBottom" :close-on-click-overlay="closeOnClickOverlay" @close="onClickOverlay">
+  <view v-if="title" class="van-action-sheet__header">
+    {{ title }}
+    <van-icon name="cross" custom-class="van-action-sheet__close" @click="onClose"></van-icon>
+  </view>
+  <view v-if="description" class="van-action-sheet__description van-hairline--bottom">
+    {{ description }}
+  </view>
+  <view v-if="actions && actions.length">
+    
+    <button v-for="(item,index) in (actions)" :key="item.index" :open-type="item.disabled || item.loading || (canIUseGetUserProfile && item.openType === 'getUserInfo') ? '' : item.openType" :style="item.color ? 'color: ' + item.color : ''" :class="(utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }))+' '+(item.className || '')" hover-class="van-action-sheet__item--hover" :data-index="index" @click="_$self[(item.disabled || item.loading ? '' : 'onSelect')||'_$noop']($event)" @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">
+      <block v-if="(!item.loading)">
+        {{ item.name }}
+        <view v-if="item.subname" class="van-action-sheet__subname">{{ item.subname }}</view>
+      </block>
+      <van-loading v-else custom-class="van-action-sheet__loading" size="22px"></van-loading>
+    </button>
+  </view>
+  <slot></slot>
+  <block v-if="cancelText">
+    <view class="van-action-sheet__gap"></view>
+    <view class="van-action-sheet__cancel" hover-class="van-action-sheet__cancel--hover" hover-stay-time="70" @click="onCancel">
+      {{ cancelText }}
+    </view>
+  </block>
+</van-popup></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+import VanPopup from '../popup/index.vue'
+import VanLoading from '../loading/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon,'van-popup': VanPopup,'van-loading': VanLoading}}
+
+global['__wxRoute'] = 'vant/action-sheet/index'
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+VantComponent({
+    mixins: [button],
+    props: {
+        show: Boolean,
+        title: String,
+        cancelText: String,
+        description: String,
+        round: {
+            type: Boolean,
+            value: true,
+        },
+        zIndex: {
+            type: Number,
+            value: 100,
+        },
+        actions: {
+            type: Array,
+            value: [],
+        },
+        overlay: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickAction: {
+            type: Boolean,
+            value: true,
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    methods: {
+        onSelect(event) {
+            const { index } = event.currentTarget.dataset;
+            const { actions, closeOnClickAction, canIUseGetUserProfile } = this.data;
+            const item = actions[index];
+            if (item) {
+                this.$emit('select', item);
+                if (closeOnClickAction) {
+                    this.onClose();
+                }
+                if (item.openType === 'getUserInfo' && canIUseGetUserProfile) {
+                    wx.getUserProfile({
+                        desc: item.getUserProfileDesc || '  ',
+                        complete: (userProfile) => {
+                            this.$emit('getuserinfo', userProfile);
+                        },
+                    });
+                }
+            }
+        },
+        onCancel() {
+            this.$emit('cancel');
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClickOverlay() {
+            this.$emit('click-overlay');
+            this.onClose();
+        },
+    },
+});
+export default global['__wxComponents']['vant/action-sheet/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-action-sheet{color:var(--action-sheet-item-text-color,#323233);max-height:var(--action-sheet-max-height,90%)!important}.van-action-sheet__cancel,.van-action-sheet__item{background-color:var(--action-sheet-item-background,#fff);font-size:var(--action-sheet-item-font-size,16px);line-height:var(--action-sheet-item-line-height,22px);padding:14px 16px;text-align:center}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5}.van-action-sheet__cancel:after,.van-action-sheet__item:after{border-width:0}.van-action-sheet__cancel{color:var(--action-sheet-cancel-text-color,#646566)}.van-action-sheet__gap{background-color:var(--action-sheet-cancel-padding-color,#f7f8fa);display:block;height:var(--action-sheet-cancel-padding-top,8px)}.van-action-sheet__item--disabled{color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{color:var(--action-sheet-subname-color,#969799);font-size:var(--action-sheet-subname-font-size,12px);line-height:var(--action-sheet-subname-line-height,20px);margin-top:var(--padding-xs,8px)}.van-action-sheet__header{font-size:var(--action-sheet-header-font-size,16px);font-weight:var(--font-weight-bold,500);line-height:var(--action-sheet-header-height,48px);text-align:center}.van-action-sheet__description{color:var(--action-sheet-description-color,#969799);font-size:var(--action-sheet-description-font-size,14px);line-height:var(--action-sheet-description-line-height,20px);padding:20px var(--padding-md,16px);text-align:center}.van-action-sheet__close{color:var(--action-sheet-close-icon-color,#c8c9cc);font-size:var(--action-sheet-close-icon-size,22px)!important;line-height:inherit!important;padding:var(--action-sheet-close-icon-padding,0 16px);position:absolute!important;right:0;top:0}.van-action-sheet__loading{display:flex!important}
+</style>

+ 234 - 0
src/wxcomponents/vant/area/index.vue

@@ -0,0 +1,234 @@
+<template>
+<uni-shadow-root class="vant-area-index"><van-picker class="van-area__picker" active-class="active-class" toolbar-class="toolbar-class" column-class="column-class" :show-toolbar="showToolbar" value-key="name" :title="title" :loading="loading" :columns="computed.displayColumns(columns, columnsNum)" :item-height="itemHeight" :visible-item-count="visibleItemCount" :cancel-button-text="cancelButtonText" :confirm-button-text="confirmButtonText" @change="onChange" @confirm="onConfirm" @cancel="onCancel"></van-picker></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanPicker from '../picker/index.vue'
+global['__wxVueOptions'] = {components:{'van-picker': VanPicker}}
+
+global['__wxRoute'] = 'vant/area/index'
+import { VantComponent } from '../common/component';
+import { pickerProps } from '../picker/shared';
+import { requestAnimationFrame } from '../common/utils';
+const EMPTY_CODE = '000000';
+VantComponent({
+    classes: ['active-class', 'toolbar-class', 'column-class'],
+    props: Object.assign(Object.assign({}, pickerProps), { showToolbar: {
+            type: Boolean,
+            value: true,
+        }, value: {
+            type: String,
+            observer(value) {
+                this.code = value;
+                this.setValues();
+            },
+        }, areaList: {
+            type: Object,
+            value: {},
+            observer: 'setValues',
+        }, columnsNum: {
+            type: null,
+            value: 3,
+        }, columnsPlaceholder: {
+            type: Array,
+            observer(val) {
+                this.setData({
+                    typeToColumnsPlaceholder: {
+                        province: val[0] || '',
+                        city: val[1] || '',
+                        county: val[2] || '',
+                    },
+                });
+            },
+        } }),
+    data: {
+        columns: [{ values: [] }, { values: [] }, { values: [] }],
+        typeToColumnsPlaceholder: {},
+    },
+    mounted() {
+        requestAnimationFrame(() => {
+            this.setValues();
+        });
+    },
+    methods: {
+        getPicker() {
+            if (this.picker == null) {
+                this.picker = this.selectComponent('.van-area__picker');
+            }
+            return this.picker;
+        },
+        onCancel(event) {
+            this.emit('cancel', event.detail);
+        },
+        onConfirm(event) {
+            const { index } = event.detail;
+            let { value } = event.detail;
+            value = this.parseValues(value);
+            this.emit('confirm', { value, index });
+        },
+        emit(type, detail) {
+            detail.values = detail.value;
+            delete detail.value;
+            this.$emit(type, detail);
+        },
+        parseValues(values) {
+            const { columnsPlaceholder } = this.data;
+            return values.map((value, index) => {
+                if (value &&
+                    (!value.code || value.name === columnsPlaceholder[index])) {
+                    return Object.assign(Object.assign({}, value), { code: '', name: '' });
+                }
+                return value;
+            });
+        },
+        onChange(event) {
+            var _a;
+            const { index, picker, value } = event.detail;
+            this.code = value[index].code;
+            (_a = this.setValues()) === null || _a === void 0 ? void 0 : _a.then(() => {
+                this.$emit('change', {
+                    picker,
+                    values: this.parseValues(picker.getValues()),
+                    index,
+                });
+            });
+        },
+        getConfig(type) {
+            const { areaList } = this.data;
+            return (areaList && areaList[`${type}_list`]) || {};
+        },
+        getList(type, code) {
+            if (type !== 'province' && !code) {
+                return [];
+            }
+            const { typeToColumnsPlaceholder } = this.data;
+            const list = this.getConfig(type);
+            let result = Object.keys(list).map((code) => ({
+                code,
+                name: list[code],
+            }));
+            if (code != null) {
+                // oversea code
+                if (code[0] === '9' && type === 'city') {
+                    code = '9';
+                }
+                result = result.filter((item) => item.code.indexOf(code) === 0);
+            }
+            if (typeToColumnsPlaceholder[type] && result.length) {
+                // set columns placeholder
+                const codeFill = type === 'province'
+                    ? ''
+                    : type === 'city'
+                        ? EMPTY_CODE.slice(2, 4)
+                        : EMPTY_CODE.slice(4, 6);
+                result.unshift({
+                    code: `${code}${codeFill}`,
+                    name: typeToColumnsPlaceholder[type],
+                });
+            }
+            return result;
+        },
+        getIndex(type, code) {
+            let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
+            const list = this.getList(type, code.slice(0, compareNum - 2));
+            // oversea code
+            if (code[0] === '9' && type === 'province') {
+                compareNum = 1;
+            }
+            code = code.slice(0, compareNum);
+            for (let i = 0; i < list.length; i++) {
+                if (list[i].code.slice(0, compareNum) === code) {
+                    return i;
+                }
+            }
+            return 0;
+        },
+        setValues() {
+            const picker = this.getPicker();
+            if (!picker) {
+                return;
+            }
+            let code = this.code || this.getDefaultCode();
+            const provinceList = this.getList('province');
+            const cityList = this.getList('city', code.slice(0, 2));
+            const stack = [];
+            const indexes = [];
+            const { columnsNum } = this.data;
+            if (columnsNum >= 1) {
+                stack.push(picker.setColumnValues(0, provinceList, false));
+                indexes.push(this.getIndex('province', code));
+            }
+            if (columnsNum >= 2) {
+                stack.push(picker.setColumnValues(1, cityList, false));
+                indexes.push(this.getIndex('city', code));
+                if (cityList.length && code.slice(2, 4) === '00') {
+                    [{ code }] = cityList;
+                }
+            }
+            if (columnsNum === 3) {
+                stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
+                indexes.push(this.getIndex('county', code));
+            }
+            return Promise.all(stack)
+                .catch(() => { })
+                .then(() => picker.setIndexes(indexes))
+                .catch(() => { });
+        },
+        getDefaultCode() {
+            const { columnsPlaceholder } = this.data;
+            if (columnsPlaceholder.length) {
+                return EMPTY_CODE;
+            }
+            const countyCodes = Object.keys(this.getConfig('county'));
+            if (countyCodes[0]) {
+                return countyCodes[0];
+            }
+            const cityCodes = Object.keys(this.getConfig('city'));
+            if (cityCodes[0]) {
+                return cityCodes[0];
+            }
+            return '';
+        },
+        getValues() {
+            const picker = this.getPicker();
+            if (!picker) {
+                return [];
+            }
+            return this.parseValues(picker.getValues().filter((value) => !!value));
+        },
+        getDetail() {
+            const values = this.getValues();
+            const area = {
+                code: '',
+                country: '',
+                province: '',
+                city: '',
+                county: '',
+            };
+            if (!values.length) {
+                return area;
+            }
+            const names = values.map((item) => item.name);
+            area.code = values[values.length - 1].code;
+            if (area.code[0] === '9') {
+                area.country = names[1] || '';
+                area.province = names[2] || '';
+            }
+            else {
+                area.province = names[0] || '';
+                area.city = names[1] || '';
+                area.county = names[2] || '';
+            }
+            return area;
+        },
+        reset(code) {
+            this.code = code || '';
+            return this.setValues();
+        },
+    },
+});
+export default global['__wxComponents']['vant/area/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';
+</style>

File diff suppressed because it is too large
+ 90 - 0
src/wxcomponents/vant/button/index.vue


+ 37 - 0
src/wxcomponents/vant/calendar/calendar.vue

@@ -0,0 +1,37 @@
+<template>
+<uni-shadow-root class="vant-calendar-calendar"><view class="van-calendar">
+  <header :title="title" :showTitle="showTitle" :subtitle="subtitle" :showSubtitle="showSubtitle" :firstDayOfWeek="firstDayOfWeek" @click-subtitle="onClickSubtitle">
+    <slot name="title" slot="title"></slot>
+  </header>
+
+  <scroll-view class="van-calendar__body" scroll-y :scroll-into-view="scrollIntoView">
+    <month v-for="(item,index) in (computed.getMonths(minDate, maxDate))" :key="item.index" :id="'month'+(index)" class="month" :data-date="item" :date="item" :type="type" :color="color" :minDate="minDate" :maxDate="maxDate" :showMark="showMark" :formatter="formatter" :rowHeight="rowHeight" :currentDate="currentDate" :showSubtitle="showSubtitle" :allowSameDay="allowSameDay" :showMonthTitle="index !== 0 || !showSubtitle" :firstDayOfWeek="firstDayOfWeek" @click="onClickDay"></month>
+  </scroll-view>
+
+  <view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
+    <slot name="footer"></slot>
+  </view>
+
+  <view :class="utils.bem('calendar__footer', { safeAreaInsetBottom })">
+    <van-button v-if="showConfirm" round block type="danger" :color="color" custom-class="van-calendar__confirm" :disabled="computed.getButtonDisabled(type, currentDate)" nativeType="text" @click="onConfirm">
+      {{
+        computed.getButtonDisabled(type, currentDate)
+          ? confirmDisabledText
+          : confirmText
+      }}
+    </van-button>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/calendar/calendar'
+
+Component({})
+
+export default global['__wxComponents']['vant/calendar/calendar']
+</script>
+<style platform="mp-weixin">
+
+</style>

+ 64 - 0
src/wxcomponents/vant/calendar/components/header/index.vue

@@ -0,0 +1,64 @@
+<template>
+<uni-shadow-root class="vant-calendar-components-header-index"><view class="van-calendar__header">
+  <block v-if="showTitle">
+    <view class="van-calendar__header-title"><slot name="title"></slot></view>
+    <view class="van-calendar__header-title">{{ title }}</view>
+  </block>
+
+  <view v-if="showSubtitle" class="van-calendar__header-subtitle" @click="onClickSubtitle">
+    {{ subtitle }}
+  </view>
+
+  <view class="van-calendar__weekdays">
+    <view v-for="(item,index) in (weekdays)" :key="item.index" class="van-calendar__weekday">
+      {{ item }}
+    </view>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/calendar/components/header/index'
+import { VantComponent } from '../../../common/component';
+VantComponent({
+    props: {
+        title: {
+            type: String,
+            value: '日期选择',
+        },
+        subtitle: String,
+        showTitle: Boolean,
+        showSubtitle: Boolean,
+        firstDayOfWeek: {
+            type: Number,
+            observer: 'initWeekDay',
+        },
+    },
+    data: {
+        weekdays: [],
+    },
+    created() {
+        this.initWeekDay();
+    },
+    methods: {
+        initWeekDay() {
+            const defaultWeeks = ['日', '一', '二', '三', '四', '五', '六'];
+            const firstDayOfWeek = this.data.firstDayOfWeek || 0;
+            this.setData({
+                weekdays: [
+                    ...defaultWeeks.slice(firstDayOfWeek, 7),
+                    ...defaultWeeks.slice(0, firstDayOfWeek),
+                ],
+            });
+        },
+        onClickSubtitle(event) {
+            this.$emit('click-subtitle', event);
+        },
+    },
+});
+export default global['__wxComponents']['vant/calendar/components/header/index']
+</script>
+<style platform="mp-weixin">
+@import '../../../common/index.css';.van-calendar__header{box-shadow:var(--calendar-header-box-shadow,0 2px 10px hsla(220,1%,50%,.16));flex-shrink:0}.van-calendar__header-subtitle,.van-calendar__header-title{font-weight:var(--font-weight-bold,500);height:var(--calendar-header-title-height,44px);line-height:var(--calendar-header-title-height,44px);text-align:center}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:flex}.van-calendar__weekday{flex:1;font-size:var(--calendar-weekdays-font-size,12px);line-height:var(--calendar-weekdays-height,30px);text-align:center}
+</style>

File diff suppressed because it is too large
+ 192 - 0
src/wxcomponents/vant/calendar/components/month/index.vue


+ 365 - 0
src/wxcomponents/vant/calendar/index.vue

@@ -0,0 +1,365 @@
+<template>
+<uni-shadow-root class="vant-calendar-index"><van-popup v-if="poppable" :custom-class="'van-calendar__popup--'+(position)" close-icon-class="van-calendar__close-icon" :show="show" :round="round" :position="position" :closeable="showTitle || showSubtitle" :close-on-click-overlay="closeOnClickOverlay" @enter="onOpen" @close="onClose" @after-enter="onOpened" @after-leave="onClosed">
+  <include src="./calendar.wxml"></include>
+</van-popup>
+
+<include v-else src="./calendar.wxml"></include>
+
+<van-toast id="van-toast"></van-toast></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs><wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+const __wxTemplateComponentProps = {}
+import __wxTemplateComponent0 from './calendar.vue'
+
+import Header from './components/header/index.vue'
+import Month from './components/month/index.vue'
+import VanButton from '../button/index.vue'
+import VanPopup from '../popup/index.vue'
+import VanToast from '../toast/index.vue'
+global['__wxVueOptions'] = {components:{'header': Header,'month': Month,'van-button': VanButton,'van-popup': VanPopup,'van-toast': VanToast,}}
+
+global['__wxRoute'] = 'vant/calendar/index'
+import { VantComponent } from '../common/component';
+import { ROW_HEIGHT, getPrevDay, getNextDay, getToday, compareDay, copyDates, calcDateNum, formatMonthTitle, compareMonth, getMonths, getDayByOffset, } from './utils';
+import Toast from '../toast/toast';
+import { requestAnimationFrame } from '../common/utils';
+const initialMinDate = getToday().getTime();
+const initialMaxDate = (() => {
+    const now = getToday();
+    return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()).getTime();
+})();
+const getTime = (date) => date instanceof Date ? date.getTime() : date;
+VantComponent({
+    props: {
+        title: {
+            type: String,
+            value: '日期选择',
+        },
+        color: String,
+        show: {
+            type: Boolean,
+            observer(val) {
+                if (val) {
+                    this.initRect();
+                    this.scrollIntoView();
+                }
+            },
+        },
+        formatter: null,
+        confirmText: {
+            type: String,
+            value: '确定',
+        },
+        confirmDisabledText: {
+            type: String,
+            value: '确定',
+        },
+        rangePrompt: String,
+        showRangePrompt: {
+            type: Boolean,
+            value: true,
+        },
+        defaultDate: {
+            type: null,
+            observer(val) {
+                this.setData({ currentDate: val });
+                this.scrollIntoView();
+            },
+        },
+        allowSameDay: Boolean,
+        type: {
+            type: String,
+            value: 'single',
+            observer: 'reset',
+        },
+        minDate: {
+            type: Number,
+            value: initialMinDate,
+        },
+        maxDate: {
+            type: Number,
+            value: initialMaxDate,
+        },
+        position: {
+            type: String,
+            value: 'bottom',
+        },
+        rowHeight: {
+            type: null,
+            value: ROW_HEIGHT,
+        },
+        round: {
+            type: Boolean,
+            value: true,
+        },
+        poppable: {
+            type: Boolean,
+            value: true,
+        },
+        showMark: {
+            type: Boolean,
+            value: true,
+        },
+        showTitle: {
+            type: Boolean,
+            value: true,
+        },
+        showConfirm: {
+            type: Boolean,
+            value: true,
+        },
+        showSubtitle: {
+            type: Boolean,
+            value: true,
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true,
+        },
+        maxRange: {
+            type: null,
+            value: null,
+        },
+        firstDayOfWeek: {
+            type: Number,
+            value: 0,
+        },
+        readonly: Boolean,
+    },
+    data: {
+        subtitle: '',
+        currentDate: null,
+        scrollIntoView: '',
+    },
+    created() {
+        this.setData({
+            currentDate: this.getInitialDate(this.data.defaultDate),
+        });
+    },
+    mounted() {
+        if (this.data.show || !this.data.poppable) {
+            this.initRect();
+            this.scrollIntoView();
+        }
+    },
+    methods: {
+        reset() {
+            this.setData({ currentDate: this.getInitialDate() });
+            this.scrollIntoView();
+        },
+        initRect() {
+            if (this.contentObserver != null) {
+                this.contentObserver.disconnect();
+            }
+            const contentObserver = this.createIntersectionObserver({
+                thresholds: [0, 0.1, 0.9, 1],
+                observeAll: true,
+            });
+            this.contentObserver = contentObserver;
+            contentObserver.relativeTo('.van-calendar__body');
+            contentObserver.observe('.month', (res) => {
+                if (res.boundingClientRect.top <= res.relativeRect.top) {
+                    // @ts-ignore
+                    this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
+                }
+            });
+        },
+        limitDateRange(date, minDate = null, maxDate = null) {
+            minDate = minDate || this.data.minDate;
+            maxDate = maxDate || this.data.maxDate;
+            if (compareDay(date, minDate) === -1) {
+                return minDate;
+            }
+            if (compareDay(date, maxDate) === 1) {
+                return maxDate;
+            }
+            return date;
+        },
+        getInitialDate(defaultDate = null) {
+            const { type, minDate, maxDate } = this.data;
+            const now = getToday().getTime();
+            if (type === 'range') {
+                if (!Array.isArray(defaultDate)) {
+                    defaultDate = [];
+                }
+                const [startDay, endDay] = defaultDate || [];
+                const start = this.limitDateRange(startDay || now, minDate, getPrevDay(new Date(maxDate)).getTime());
+                const end = this.limitDateRange(endDay || now, getNextDay(new Date(minDate)).getTime());
+                return [start, end];
+            }
+            if (type === 'multiple') {
+                if (Array.isArray(defaultDate)) {
+                    return defaultDate.map((date) => this.limitDateRange(date));
+                }
+                return [this.limitDateRange(now)];
+            }
+            if (!defaultDate || Array.isArray(defaultDate)) {
+                defaultDate = now;
+            }
+            return this.limitDateRange(defaultDate);
+        },
+        scrollIntoView() {
+            requestAnimationFrame(() => {
+                const { currentDate, type, show, poppable, minDate, maxDate } = this.data;
+                // @ts-ignore
+                const targetDate = type === 'single' ? currentDate : currentDate[0];
+                const displayed = show || !poppable;
+                if (!targetDate || !displayed) {
+                    return;
+                }
+                const months = getMonths(minDate, maxDate);
+                months.some((month, index) => {
+                    if (compareMonth(month, targetDate) === 0) {
+                        this.setData({ scrollIntoView: `month${index}` });
+                        return true;
+                    }
+                    return false;
+                });
+            });
+        },
+        onOpen() {
+            this.$emit('open');
+        },
+        onOpened() {
+            this.$emit('opened');
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClosed() {
+            this.$emit('closed');
+        },
+        onClickDay(event) {
+            if (this.data.readonly) {
+                return;
+            }
+            let { date } = event.detail;
+            const { type, currentDate, allowSameDay } = this.data;
+            if (type === 'range') {
+                // @ts-ignore
+                const [startDay, endDay] = currentDate;
+                if (startDay && !endDay) {
+                    const compareToStart = compareDay(date, startDay);
+                    if (compareToStart === 1) {
+                        const { days } = this.selectComponent('.month').data;
+                        days.some((day, index) => {
+                            const isDisabled = day.type === 'disabled' &&
+                                getTime(startDay) < getTime(day.date) &&
+                                getTime(day.date) < getTime(date);
+                            if (isDisabled) {
+                                ({ date } = days[index - 1]);
+                            }
+                            return isDisabled;
+                        });
+                        this.select([startDay, date], true);
+                    }
+                    else if (compareToStart === -1) {
+                        this.select([date, null]);
+                    }
+                    else if (allowSameDay) {
+                        this.select([date, date]);
+                    }
+                }
+                else {
+                    this.select([date, null]);
+                }
+            }
+            else if (type === 'multiple') {
+                let selectedIndex;
+                // @ts-ignore
+                const selected = currentDate.some((dateItem, index) => {
+                    const equal = compareDay(dateItem, date) === 0;
+                    if (equal) {
+                        selectedIndex = index;
+                    }
+                    return equal;
+                });
+                if (selected) {
+                    // @ts-ignore
+                    const cancelDate = currentDate.splice(selectedIndex, 1);
+                    this.setData({ currentDate });
+                    this.unselect(cancelDate);
+                }
+                else {
+                    // @ts-ignore
+                    this.select([...currentDate, date]);
+                }
+            }
+            else {
+                this.select(date, true);
+            }
+        },
+        unselect(dateArray) {
+            const date = dateArray[0];
+            if (date) {
+                this.$emit('unselect', copyDates(date));
+            }
+        },
+        select(date, complete) {
+            if (complete && this.data.type === 'range') {
+                const valid = this.checkRange(date);
+                if (!valid) {
+                    // auto selected to max range if showConfirm
+                    if (this.data.showConfirm) {
+                        this.emit([
+                            date[0],
+                            getDayByOffset(date[0], this.data.maxRange - 1),
+                        ]);
+                    }
+                    else {
+                        this.emit(date);
+                    }
+                    return;
+                }
+            }
+            this.emit(date);
+            if (complete && !this.data.showConfirm) {
+                this.onConfirm();
+            }
+        },
+        emit(date) {
+            this.setData({
+                currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
+            });
+            this.$emit('select', copyDates(date));
+        },
+        checkRange(date) {
+            const { maxRange, rangePrompt, showRangePrompt } = this.data;
+            if (maxRange && calcDateNum(date) > maxRange) {
+                if (showRangePrompt) {
+                    Toast({
+                        context: this,
+                        message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
+                    });
+                }
+                this.$emit('over-range');
+                return false;
+            }
+            return true;
+        },
+        onConfirm() {
+            if (this.data.type === 'range' &&
+                !this.checkRange(this.data.currentDate)) {
+                return;
+            }
+            wx.nextTick(() => {
+                // @ts-ignore
+                this.$emit('confirm', copyDates(this.data.currentDate));
+            });
+        },
+        onClickSubtitle(event) {
+            this.$emit('click-subtitle', event);
+        },
+    },
+});
+export default global['__wxComponents']['vant/calendar/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-calendar{background-color:var(--calendar-background-color,#fff);display:flex;flex-direction:column;height:var(--calendar-height,100%)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:var(--calendar-popup-height,80%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-overflow-scrolling:touch;flex:1;overflow:auto}.van-calendar__footer{flex-shrink:0;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:var(--calendar-confirm-button-height,36px)!important;line-height:var(--calendar-confirm-button-line-height,34px)!important;margin:var(--calendar-confirm-button-margin,7px 0)!important}
+</style>

+ 105 - 0
src/wxcomponents/vant/card/index.vue

@@ -0,0 +1,105 @@
+<template>
+<uni-shadow-root class="vant-card-index"><view class="custom-class van-card">
+  <view :class="utils.bem('card__header', { center: centered })">
+    <view class="van-card__thumb" @click="onClickThumb">
+      <image v-if="thumb" :src="thumb" :mode="thumbMode" :lazy-load="lazyLoad" class="van-card__img thumb-class"></image>
+      <slot v-else name="thumb"></slot>
+      <van-tag v-if="tag" mark type="danger" custom-class="van-card__tag">
+        {{ tag }}
+      </van-tag>
+      <slot v-else name="tag"></slot>
+    </view>
+
+    <view :class="'van-card__content '+(utils.bem('card__content', { center: centered }))">
+      <view>
+        <view v-if="title" class="van-card__title title-class">{{ title }}</view>
+        <slot v-else name="title"></slot>
+
+        <view v-if="desc" class="van-card__desc desc-class">{{ desc }}</view>
+        <slot v-else name="desc"></slot>
+
+        <slot name="tags"></slot>
+      </view>
+
+      <view class="van-card__bottom">
+        <slot name="price-top"></slot>
+        <view v-if="price || price === 0" class="van-card__price price-class">
+          <text>{{ currency }}</text>
+          <text class="van-card__price-integer">{{ integerStr }}</text>
+          <text class="van-card__price-decimal">{{ decimalStr }}</text>
+        </view>
+        <slot v-else name="price"></slot>
+        <view v-if="originPrice || originPrice === 0" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
+        <slot v-else name="origin-price"></slot>
+        <view v-if="num" class="van-card__num num-class">x {{ num }}</view>
+        <slot v-else name="num"></slot>
+        <slot name="bottom"></slot>
+      </view>
+    </view>
+  </view>
+
+  <view class="van-card__footer">
+    <slot name="footer"></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanTag from '../tag/index.vue'
+global['__wxVueOptions'] = {components:{'van-tag': VanTag}}
+
+global['__wxRoute'] = 'vant/card/index'
+import { link } from '../mixins/link';
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: [
+        'num-class',
+        'desc-class',
+        'thumb-class',
+        'title-class',
+        'price-class',
+        'origin-price-class',
+    ],
+    mixins: [link],
+    props: {
+        tag: String,
+        num: String,
+        desc: String,
+        thumb: String,
+        title: String,
+        price: {
+            type: String,
+            observer: 'updatePrice',
+        },
+        centered: Boolean,
+        lazyLoad: Boolean,
+        thumbLink: String,
+        originPrice: String,
+        thumbMode: {
+            type: String,
+            value: 'aspectFit',
+        },
+        currency: {
+            type: String,
+            value: '¥',
+        },
+    },
+    methods: {
+        updatePrice() {
+            const { price } = this.data;
+            const priceArr = price.toString().split('.');
+            this.setData({
+                integerStr: priceArr[0],
+                decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
+            });
+        },
+        onClickThumb() {
+            this.jumpLink('thumbLink');
+        },
+    },
+});
+export default global['__wxComponents']['vant/card/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-card{background-color:var(--card-background-color,#fafafa);box-sizing:border-box;color:var(--card-text-color,#323233);font-size:var(--card-font-size,12px);padding:var(--card-padding,8px 16px);position:relative}.van-card__header{display:flex}.van-card__header--center{align-items:center;justify-content:center}.van-card__thumb{flex:none;height:var(--card-thumb-size,88px);margin-right:var(--padding-xs,8px);position:relative;width:var(--card-thumb-size,88px)}.van-card__thumb:empty{display:none}.van-card__img{border-radius:8px;height:100%;width:100%}.van-card__content{display:flex;flex:1;flex-direction:column;justify-content:space-between;min-height:var(--card-thumb-size,88px);min-width:0;position:relative}.van-card__content--center{justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:var(--card-title-line-height,16px)}.van-card__desc{color:var(--card-desc-color,#646566);line-height:var(--card-desc-line-height,20px)}.van-card__bottom{line-height:20px}.van-card__price{color:var(--card-price-color,#ee0a24);display:inline-block;font-size:var(--card-price-font-size,12px);font-weight:700}.van-card__price-integer{font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{color:var(--card-origin-price-color,#646566);display:inline-block;font-size:var(--card-origin-price-font-size,10px);margin-left:5px;text-decoration:line-through}.van-card__num{float:right}.van-card__tag{left:0;position:absolute!important;top:2px}.van-card__footer{flex:none;text-align:right;width:100%}
+</style>

+ 28 - 0
src/wxcomponents/vant/cell-group/index.vue

@@ -0,0 +1,28 @@
+<template>
+<uni-shadow-root class="vant-cell-group-index"><view v-if="title" :class="utils.bem('cell-group__title', { inset })">
+  {{ title }}
+</view>
+<view :class="'custom-class '+(utils.bem('cell-group', { inset }))+' '+(border ? 'van-hairline--top-bottom' : '')">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/cell-group/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        title: String,
+        border: {
+            type: Boolean,
+            value: true,
+        },
+        inset: Boolean,
+    },
+});
+export default global['__wxComponents']['vant/cell-group/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-cell-group--inset{border-radius:var(--cell-group-inset-border-radius,8px);margin:var(--cell-group-inset-padding,0 16px);overflow:hidden}.van-cell-group__title{color:var(--cell-group-title-color,#969799);font-size:var(--cell-group-title-font-size,14px);line-height:var(--cell-group-title-line-height,16px);padding:var(--cell-group-title-padding,16px 16px 8px)}.van-cell-group__title--inset{padding:var(--cell-group-inset-title-padding,16px 16px 8px 32px)}
+</style>

File diff suppressed because it is too large
+ 74 - 0
src/wxcomponents/vant/cell/index.vue


+ 50 - 0
src/wxcomponents/vant/checkbox-group/index.vue

@@ -0,0 +1,50 @@
+<template>
+<uni-shadow-root class="vant-checkbox-group-index"><view :class="utils.bem('checkbox-group', [{ horizontal: direction === 'horizontal' }])">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/checkbox-group/index'
+import { useChildren } from '../common/relation';
+import { VantComponent } from '../common/component';
+VantComponent({
+    field: true,
+    relation: useChildren('checkbox', function (target) {
+        this.updateChild(target);
+    }),
+    props: {
+        max: Number,
+        value: {
+            type: Array,
+            observer: 'updateChildren',
+        },
+        disabled: {
+            type: Boolean,
+            observer: 'updateChildren',
+        },
+        direction: {
+            type: String,
+            value: 'vertical',
+        },
+    },
+    methods: {
+        updateChildren() {
+            this.children.forEach((child) => this.updateChild(child));
+        },
+        updateChild(child) {
+            const { value, disabled, direction } = this.data;
+            child.setData({
+                value: value.indexOf(child.data.name) !== -1,
+                parentDisabled: disabled,
+                direction,
+            });
+        },
+    },
+});
+export default global['__wxComponents']['vant/checkbox-group/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-checkbox-group--horizontal{display:flex;flex-wrap:wrap}
+</style>

+ 102 - 0
src/wxcomponents/vant/checkbox/index.vue

@@ -0,0 +1,102 @@
+<template>
+<uni-shadow-root class="vant-checkbox-index"><view :class="(utils.bem('checkbox', [{ horizontal: direction === 'horizontal' }]))+' custom-class'">
+  <view v-if="labelPosition === 'left'" :class="'label-class '+(utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]))" @click="onClickLabel">
+    <slot></slot>
+  </view>
+  <view class="van-checkbox__icon-wrap" @click="toggle">
+    <slot v-if="useIconSlot" name="icon"></slot>
+    <van-icon v-else name="success" size="0.8em" :class="utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }])" :style="computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize)" custom-class="icon-class" custom-style="line-height: 1.25em;"></van-icon>
+  </view>
+  <view v-if="labelPosition === 'right'" :class="'label-class '+(utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]))" @click="onClickLabel">
+    <slot></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/checkbox/index'
+import { useParent } from '../common/relation';
+import { VantComponent } from '../common/component';
+function emit(target, value) {
+    target.$emit('input', value);
+    target.$emit('change', value);
+}
+VantComponent({
+    field: true,
+    relation: useParent('checkbox-group'),
+    classes: ['icon-class', 'label-class'],
+    props: {
+        value: Boolean,
+        disabled: Boolean,
+        useIconSlot: Boolean,
+        checkedColor: String,
+        labelPosition: {
+            type: String,
+            value: 'right',
+        },
+        labelDisabled: Boolean,
+        shape: {
+            type: String,
+            value: 'round',
+        },
+        iconSize: {
+            type: null,
+            value: 20,
+        },
+    },
+    data: {
+        parentDisabled: false,
+        direction: 'vertical',
+    },
+    methods: {
+        emitChange(value) {
+            if (this.parent) {
+                this.setParentValue(this.parent, value);
+            }
+            else {
+                emit(this, value);
+            }
+        },
+        toggle() {
+            const { parentDisabled, disabled, value } = this.data;
+            if (!disabled && !parentDisabled) {
+                this.emitChange(!value);
+            }
+        },
+        onClickLabel() {
+            const { labelDisabled, parentDisabled, disabled, value } = this.data;
+            if (!disabled && !labelDisabled && !parentDisabled) {
+                this.emitChange(!value);
+            }
+        },
+        setParentValue(parent, value) {
+            const parentValue = parent.data.value.slice();
+            const { name } = this.data;
+            const { max } = parent.data;
+            if (value) {
+                if (max && parentValue.length >= max) {
+                    return;
+                }
+                if (parentValue.indexOf(name) === -1) {
+                    parentValue.push(name);
+                    emit(parent, parentValue);
+                }
+            }
+            else {
+                const index = parentValue.indexOf(name);
+                if (index !== -1) {
+                    parentValue.splice(index, 1);
+                    emit(parent, parentValue);
+                }
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/checkbox/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-checkbox{align-items:center;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox--horizontal{margin-right:12px}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{flex:none}.van-checkbox__icon{align-items:center;border:1px solid var(--checkbox-border-color,#c8c9cc);box-sizing:border-box;color:transparent;display:flex;font-size:var(--checkbox-size,20px);height:1em;justify-content:center;text-align:center;transition-duration:var(--checkbox-transition-duration,.2s);transition-property:color,border-color,background-color;width:1em}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:var(--checkbox-checked-icon-color,#1989fa);color:#fff}.van-checkbox__icon--disabled{background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;color:var(--checkbox-label-color,#323233);padding-left:var(--checkbox-label-margin,10px)}.van-checkbox__label--left{float:left;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
+</style>

+ 211 - 0
src/wxcomponents/vant/circle/index.vue

@@ -0,0 +1,211 @@
+<template>
+<uni-shadow-root class="vant-circle-index"><view class="van-circle">
+  <canvas class="van-circle__canvas" :type="type" :style="'width: '+(utils.addUnit(size))+';height:'+(utils.addUnit(size))" id="van-circle" canvas-id="van-circle"></canvas>
+  <view v-if="(!text)" class="van-circle__text">
+    <slot></slot>
+  </view>
+  <cover-view v-else class="van-circle__text">{{ text }}</cover-view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/circle/index'
+import { BLUE, WHITE } from '../common/color';
+import { VantComponent } from '../common/component';
+import { getSystemInfoSync } from '../common/utils';
+import { isObj } from '../common/validator';
+import { canIUseCanvas2d } from '../common/version';
+import { adaptor } from './canvas';
+function format(rate) {
+    return Math.min(Math.max(rate, 0), 100);
+}
+const PERIMETER = 2 * Math.PI;
+const BEGIN_ANGLE = -Math.PI / 2;
+const STEP = 1;
+VantComponent({
+    props: {
+        text: String,
+        lineCap: {
+            type: String,
+            value: 'round',
+        },
+        value: {
+            type: Number,
+            value: 0,
+            observer: 'reRender',
+        },
+        speed: {
+            type: Number,
+            value: 50,
+        },
+        size: {
+            type: Number,
+            value: 100,
+            observer() {
+                this.drawCircle(this.currentValue);
+            },
+        },
+        fill: String,
+        layerColor: {
+            type: String,
+            value: WHITE,
+        },
+        color: {
+            type: null,
+            value: BLUE,
+            observer() {
+                this.setHoverColor().then(() => {
+                    this.drawCircle(this.currentValue);
+                });
+            },
+        },
+        type: {
+            type: String,
+            value: '',
+        },
+        strokeWidth: {
+            type: Number,
+            value: 4,
+        },
+        clockwise: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    data: {
+        hoverColor: BLUE,
+    },
+    methods: {
+        getContext() {
+            const { type, size } = this.data;
+            if (type === '' || !canIUseCanvas2d()) {
+                const ctx = wx.createCanvasContext('van-circle', this);
+                return Promise.resolve(ctx);
+            }
+            const dpr = getSystemInfoSync().pixelRatio;
+            return new Promise((resolve) => {
+                wx.createSelectorQuery()
+                    .in(this)
+                    .select('#van-circle')
+                    .node()
+                    .exec((res) => {
+                    const canvas = res[0].node;
+                    const ctx = canvas.getContext(type);
+                    if (!this.inited) {
+                        this.inited = true;
+                        canvas.width = size * dpr;
+                        canvas.height = size * dpr;
+                        ctx.scale(dpr, dpr);
+                    }
+                    resolve(adaptor(ctx));
+                });
+            });
+        },
+        setHoverColor() {
+            const { color, size } = this.data;
+            if (isObj(color)) {
+                return this.getContext().then((context) => {
+                    const LinearColor = context.createLinearGradient(size, 0, 0, 0);
+                    Object.keys(color)
+                        .sort((a, b) => parseFloat(a) - parseFloat(b))
+                        .map((key) => LinearColor.addColorStop(parseFloat(key) / 100, color[key]));
+                    this.hoverColor = LinearColor;
+                });
+            }
+            this.hoverColor = color;
+            return Promise.resolve();
+        },
+        presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
+            const { strokeWidth, lineCap, clockwise, size } = this.data;
+            const position = size / 2;
+            const radius = position - strokeWidth / 2;
+            context.setStrokeStyle(strokeStyle);
+            context.setLineWidth(strokeWidth);
+            context.setLineCap(lineCap);
+            context.beginPath();
+            context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
+            context.stroke();
+            if (fill) {
+                context.setFillStyle(fill);
+                context.fill();
+            }
+        },
+        renderLayerCircle(context) {
+            const { layerColor, fill } = this.data;
+            this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
+        },
+        renderHoverCircle(context, formatValue) {
+            const { clockwise } = this.data;
+            // 结束角度
+            const progress = PERIMETER * (formatValue / 100);
+            const endAngle = clockwise
+                ? BEGIN_ANGLE + progress
+                : 3 * Math.PI - (BEGIN_ANGLE + progress);
+            this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
+        },
+        drawCircle(currentValue) {
+            const { size } = this.data;
+            this.getContext().then((context) => {
+                context.clearRect(0, 0, size, size);
+                this.renderLayerCircle(context);
+                const formatValue = format(currentValue);
+                if (formatValue !== 0) {
+                    this.renderHoverCircle(context, formatValue);
+                }
+                context.draw();
+            });
+        },
+        reRender() {
+            // tofector 动画暂时没有想到好的解决方案
+            const { value, speed } = this.data;
+            if (speed <= 0 || speed > 1000) {
+                this.drawCircle(value);
+                return;
+            }
+            this.clearMockInterval();
+            this.currentValue = this.currentValue || 0;
+            const run = () => {
+                this.interval = setTimeout(() => {
+                    if (this.currentValue !== value) {
+                        if (Math.abs(this.currentValue - value) < STEP) {
+                            this.currentValue = value;
+                        }
+                        else if (this.currentValue < value) {
+                            this.currentValue += STEP;
+                        }
+                        else {
+                            this.currentValue -= STEP;
+                        }
+                        this.drawCircle(this.currentValue);
+                        run();
+                    }
+                    else {
+                        this.clearMockInterval();
+                    }
+                }, 1000 / speed);
+            };
+            run();
+        },
+        clearMockInterval() {
+            if (this.interval) {
+                clearTimeout(this.interval);
+                this.interval = null;
+            }
+        },
+    },
+    mounted() {
+        this.currentValue = this.data.value;
+        this.setHoverColor().then(() => {
+            this.drawCircle(this.currentValue);
+        });
+    },
+    destroyed() {
+        this.clearMockInterval();
+    },
+});
+export default global['__wxComponents']['vant/circle/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-circle{display:inline-block;position:relative;text-align:center}.van-circle__text{color:var(--circle-text-color,#323233);left:0;position:absolute;top:50%;transform:translateY(-50%);width:100%}
+</style>

+ 23 - 0
src/wxcomponents/vant/col/index.vue

@@ -0,0 +1,23 @@
+<template>
+<uni-shadow-root class="vant-col-index"><view :class="'custom-class '+(utils.bem('col', [span]))+' '+(offset ? 'van-col--offset-' + offset : '')" :style="computed.rootStyle({ gutter })">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/col/index'
+import { useParent } from '../common/relation';
+import { VantComponent } from '../common/component';
+VantComponent({
+    relation: useParent('row'),
+    props: {
+        span: Number,
+        offset: Number,
+    },
+});
+export default global['__wxComponents']['vant/col/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-col{box-sizing:border-box;float:left}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%}
+</style>

+ 86 - 0
src/wxcomponents/vant/collapse-item/index.vue

@@ -0,0 +1,86 @@
+<template>
+<uni-shadow-root class="vant-collapse-item-index"><view :class="'van-collapse-item custom-class '+(index !== 0 ? 'van-hairline--top' : '')">
+  <van-cell :size="size" :title="title" title-class="title-class" :icon="icon" :value="value" :label="label" :is-link="isLink" :clickable="clickable" :border="border && expanded" :class="utils.bem('collapse-item__title', { disabled, expanded })" right-icon-class="van-cell__right-icon" custom-class="van-cell" hover-class="van-cell--hover" @click="onClick">
+    <slot name="title" slot="title"></slot>
+    <slot name="icon" slot="icon"></slot>
+    <slot name="value"></slot>
+    <slot name="right-icon" slot="right-icon"></slot>
+  </van-cell>
+  <view :class="utils.bem('collapse-item__wrapper')" style="height: 0;" :animation="animation">
+    <view class="van-collapse-item__content content-class">
+      <slot></slot>
+    </view>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanCell from '../cell/index.vue'
+global['__wxVueOptions'] = {components:{'van-cell': VanCell}}
+
+global['__wxRoute'] = 'vant/collapse-item/index'
+import { VantComponent } from '../common/component';
+import { useParent } from '../common/relation';
+import { setContentAnimate } from './animate';
+VantComponent({
+    classes: ['title-class', 'content-class'],
+    relation: useParent('collapse'),
+    props: {
+        size: String,
+        name: null,
+        title: null,
+        value: null,
+        icon: String,
+        label: String,
+        disabled: Boolean,
+        clickable: Boolean,
+        border: {
+            type: Boolean,
+            value: true,
+        },
+        isLink: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    data: {
+        expanded: false,
+    },
+    mounted() {
+        this.updateExpanded();
+        this.mounted = true;
+    },
+    methods: {
+        updateExpanded() {
+            if (!this.parent) {
+                return;
+            }
+            const { value, accordion } = this.parent.data;
+            const { children = [] } = this.parent;
+            const { name } = this.data;
+            const index = children.indexOf(this);
+            const currentName = name == null ? index : name;
+            const expanded = accordion
+                ? value === currentName
+                : (value || []).some((name) => name === currentName);
+            if (expanded !== this.data.expanded) {
+                setContentAnimate(this, expanded, this.mounted);
+            }
+            this.setData({ index, expanded });
+        },
+        onClick() {
+            if (this.data.disabled) {
+                return;
+            }
+            const { name, expanded } = this.data;
+            const index = this.parent.children.indexOf(this);
+            const currentName = name == null ? index : name;
+            this.parent.switch(currentName, !expanded);
+        },
+    },
+});
+export default global['__wxComponents']['vant/collapse-item/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-collapse-item__title .van-cell__right-icon{transform:rotate(90deg);transition:transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__content{background-color:var(--collapse-item-content-background-color,#fff);color:var(--collapse-item-content-text-color,#969799);font-size:var(--collapse-item-content-font-size,13px);line-height:var(--collapse-item-content-line-height,1.5);padding:var(--collapse-item-content-padding,15px)}
+</style>

+ 60 - 0
src/wxcomponents/vant/collapse/index.vue

@@ -0,0 +1,60 @@
+<template>
+<uni-shadow-root class="vant-collapse-index"><view :class="'custom-class van-collapse '+(border ? 'van-hairline--top-bottom' : '')">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/collapse/index'
+import { VantComponent } from '../common/component';
+import { useChildren } from '../common/relation';
+VantComponent({
+    relation: useChildren('collapse-item'),
+    props: {
+        value: {
+            type: null,
+            observer: 'updateExpanded',
+        },
+        accordion: {
+            type: Boolean,
+            observer: 'updateExpanded',
+        },
+        border: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    methods: {
+        updateExpanded() {
+            this.children.forEach((child) => {
+                child.updateExpanded();
+            });
+        },
+        switch(name, expanded) {
+            const { accordion, value } = this.data;
+            const changeItem = name;
+            if (!accordion) {
+                name = expanded
+                    ? (value || []).concat(name)
+                    : (value || []).filter((activeName) => activeName !== name);
+            }
+            else {
+                name = expanded ? name : '';
+            }
+            if (expanded) {
+                this.$emit('open', changeItem);
+            }
+            else {
+                this.$emit('close', changeItem);
+            }
+            this.$emit('change', name);
+            this.$emit('input', name);
+        },
+    },
+});
+export default global['__wxComponents']['vant/collapse/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';
+</style>

+ 1 - 0
src/wxcomponents/vant/common/index.css

@@ -0,0 +1 @@
+.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{clear:both;content:"";display:table}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}

+ 1 - 0
src/wxcomponents/vant/common/style/clearfix.css

@@ -0,0 +1 @@
+.van-clearfix:after{clear:both;content:"";display:table}

+ 1 - 0
src/wxcomponents/vant/common/style/ellipsis.css

@@ -0,0 +1 @@
+.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}

+ 1 - 0
src/wxcomponents/vant/common/style/hairline.css

@@ -0,0 +1 @@
+.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}

+ 0 - 0
src/wxcomponents/vant/common/style/mixins/clearfix.css


+ 0 - 0
src/wxcomponents/vant/common/style/mixins/ellipsis.css


+ 0 - 0
src/wxcomponents/vant/common/style/mixins/hairline.css


+ 0 - 0
src/wxcomponents/vant/common/style/var.css


+ 23 - 0
src/wxcomponents/vant/config-provider/index.vue

@@ -0,0 +1,23 @@
+<template>
+<uni-shadow-root class="vant-config-provider-index"><view class="van-config-provider" :style="computed.mapThemeVarsToCSSVars(themeVars)">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/config-provider/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        themeVars: {
+            type: Object,
+            value: {},
+        },
+    },
+});
+export default global['__wxComponents']['vant/config-provider/index']
+</script>
+<style platform="mp-weixin">
+
+</style>

+ 115 - 0
src/wxcomponents/vant/count-down/index.vue

@@ -0,0 +1,115 @@
+<template>
+<uni-shadow-root class="vant-count-down-index"><view class="van-count-down">
+  <slot v-if="useSlot"></slot>
+  <block v-else>{{ formattedTime }}</block>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/count-down/index'
+import { VantComponent } from '../common/component';
+import { isSameSecond, parseFormat, parseTimeData } from './utils';
+function simpleTick(fn) {
+    return setTimeout(fn, 30);
+}
+VantComponent({
+    props: {
+        useSlot: Boolean,
+        millisecond: Boolean,
+        time: {
+            type: Number,
+            observer: 'reset',
+        },
+        format: {
+            type: String,
+            value: 'HH:mm:ss',
+        },
+        autoStart: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    data: {
+        timeData: parseTimeData(0),
+        formattedTime: '0',
+    },
+    destroyed() {
+        clearTimeout(this.tid);
+        this.tid = null;
+    },
+    methods: {
+        // 开始
+        start() {
+            if (this.counting) {
+                return;
+            }
+            this.counting = true;
+            this.endTime = Date.now() + this.remain;
+            this.tick();
+        },
+        // 暂停
+        pause() {
+            this.counting = false;
+            clearTimeout(this.tid);
+        },
+        // 重置
+        reset() {
+            this.pause();
+            this.remain = this.data.time;
+            this.setRemain(this.remain);
+            if (this.data.autoStart) {
+                this.start();
+            }
+        },
+        tick() {
+            if (this.data.millisecond) {
+                this.microTick();
+            }
+            else {
+                this.macroTick();
+            }
+        },
+        microTick() {
+            this.tid = simpleTick(() => {
+                this.setRemain(this.getRemain());
+                if (this.remain !== 0) {
+                    this.microTick();
+                }
+            });
+        },
+        macroTick() {
+            this.tid = simpleTick(() => {
+                const remain = this.getRemain();
+                if (!isSameSecond(remain, this.remain) || remain === 0) {
+                    this.setRemain(remain);
+                }
+                if (this.remain !== 0) {
+                    this.macroTick();
+                }
+            });
+        },
+        getRemain() {
+            return Math.max(this.endTime - Date.now(), 0);
+        },
+        setRemain(remain) {
+            this.remain = remain;
+            const timeData = parseTimeData(remain);
+            if (this.data.useSlot) {
+                this.$emit('change', timeData);
+            }
+            this.setData({
+                formattedTime: parseFormat(this.data.format, timeData),
+            });
+            if (remain === 0) {
+                this.pause();
+                this.$emit('finish');
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/count-down/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-count-down{color:var(--count-down-text-color,#323233);font-size:var(--count-down-font-size,14px);line-height:var(--count-down-line-height,20px)}
+</style>

+ 309 - 0
src/wxcomponents/vant/datetime-picker/index.vue

@@ -0,0 +1,309 @@
+<template>
+<uni-shadow-root class="vant-datetime-picker-index"><van-picker class="van-datetime-picker" active-class="active-class" toolbar-class="toolbar-class" column-class="column-class" :title="title" :columns="columns" :item-height="itemHeight" :show-toolbar="showToolbar" :visible-item-count="visibleItemCount" :confirm-button-text="confirmButtonText" :cancel-button-text="cancelButtonText" @change="onChange" @confirm="onConfirm" @cancel="onCancel"></van-picker></uni-shadow-root>
+</template>
+
+<script>
+import VanPicker from '../picker/index.vue'
+global['__wxVueOptions'] = {components:{'van-picker': VanPicker}}
+
+global['__wxRoute'] = 'vant/datetime-picker/index'
+import { VantComponent } from '../common/component';
+import { isDef } from '../common/validator';
+import { pickerProps } from '../picker/shared';
+const currentYear = new Date().getFullYear();
+function isValidDate(date) {
+    return isDef(date) && !isNaN(new Date(date).getTime());
+}
+function range(num, min, max) {
+    return Math.min(Math.max(num, min), max);
+}
+function padZero(val) {
+    return `00${val}`.slice(-2);
+}
+function times(n, iteratee) {
+    let index = -1;
+    const result = Array(n < 0 ? 0 : n);
+    while (++index < n) {
+        result[index] = iteratee(index);
+    }
+    return result;
+}
+function getTrueValue(formattedValue) {
+    if (formattedValue === undefined) {
+        formattedValue = '1';
+    }
+    while (isNaN(parseInt(formattedValue, 10))) {
+        formattedValue = formattedValue.slice(1);
+    }
+    return parseInt(formattedValue, 10);
+}
+function getMonthEndDay(year, month) {
+    return 32 - new Date(year, month - 1, 32).getDate();
+}
+const defaultFormatter = (type, value) => value;
+VantComponent({
+    classes: ['active-class', 'toolbar-class', 'column-class'],
+    props: Object.assign(Object.assign({}, pickerProps), { value: {
+            type: null,
+            observer: 'updateValue',
+        }, filter: null, type: {
+            type: String,
+            value: 'datetime',
+            observer: 'updateValue',
+        }, showToolbar: {
+            type: Boolean,
+            value: true,
+        }, formatter: {
+            type: null,
+            value: defaultFormatter,
+        }, minDate: {
+            type: Number,
+            value: new Date(currentYear - 10, 0, 1).getTime(),
+            observer: 'updateValue',
+        }, maxDate: {
+            type: Number,
+            value: new Date(currentYear + 10, 11, 31).getTime(),
+            observer: 'updateValue',
+        }, minHour: {
+            type: Number,
+            value: 0,
+            observer: 'updateValue',
+        }, maxHour: {
+            type: Number,
+            value: 23,
+            observer: 'updateValue',
+        }, minMinute: {
+            type: Number,
+            value: 0,
+            observer: 'updateValue',
+        }, maxMinute: {
+            type: Number,
+            value: 59,
+            observer: 'updateValue',
+        } }),
+    data: {
+        innerValue: Date.now(),
+        columns: [],
+    },
+    methods: {
+        updateValue() {
+            const { data } = this;
+            const val = this.correctValue(data.value);
+            const isEqual = val === data.innerValue;
+            this.updateColumnValue(val).then(() => {
+                if (!isEqual) {
+                    this.$emit('input', val);
+                }
+            });
+        },
+        getPicker() {
+            if (this.picker == null) {
+                this.picker = this.selectComponent('.van-datetime-picker');
+                const { picker } = this;
+                const { setColumnValues } = picker;
+                picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]);
+            }
+            return this.picker;
+        },
+        updateColumns() {
+            const { formatter = defaultFormatter } = this.data;
+            const results = this.getOriginColumns().map((column) => ({
+                values: column.values.map((value) => formatter(column.type, value)),
+            }));
+            return this.set({ columns: results });
+        },
+        getOriginColumns() {
+            const { filter } = this.data;
+            const results = this.getRanges().map(({ type, range }) => {
+                let values = times(range[1] - range[0] + 1, (index) => {
+                    const value = range[0] + index;
+                    return type === 'year' ? `${value}` : padZero(value);
+                });
+                if (filter) {
+                    values = filter(type, values);
+                }
+                return { type, values };
+            });
+            return results;
+        },
+        getRanges() {
+            const { data } = this;
+            if (data.type === 'time') {
+                return [
+                    {
+                        type: 'hour',
+                        range: [data.minHour, data.maxHour],
+                    },
+                    {
+                        type: 'minute',
+                        range: [data.minMinute, data.maxMinute],
+                    },
+                ];
+            }
+            const { maxYear, maxDate, maxMonth, maxHour, maxMinute, } = this.getBoundary('max', data.innerValue);
+            const { minYear, minDate, minMonth, minHour, minMinute, } = this.getBoundary('min', data.innerValue);
+            const result = [
+                {
+                    type: 'year',
+                    range: [minYear, maxYear],
+                },
+                {
+                    type: 'month',
+                    range: [minMonth, maxMonth],
+                },
+                {
+                    type: 'day',
+                    range: [minDate, maxDate],
+                },
+                {
+                    type: 'hour',
+                    range: [minHour, maxHour],
+                },
+                {
+                    type: 'minute',
+                    range: [minMinute, maxMinute],
+                },
+            ];
+            if (data.type === 'date')
+                result.splice(3, 2);
+            if (data.type === 'year-month')
+                result.splice(2, 3);
+            return result;
+        },
+        correctValue(value) {
+            const { data } = this;
+            // validate value
+            const isDateType = data.type !== 'time';
+            if (isDateType && !isValidDate(value)) {
+                value = data.minDate;
+            }
+            else if (!isDateType && !value) {
+                const { minHour } = data;
+                value = `${padZero(minHour)}:00`;
+            }
+            // time type
+            if (!isDateType) {
+                let [hour, minute] = value.split(':');
+                hour = padZero(range(hour, data.minHour, data.maxHour));
+                minute = padZero(range(minute, data.minMinute, data.maxMinute));
+                return `${hour}:${minute}`;
+            }
+            // date type
+            value = Math.max(value, data.minDate);
+            value = Math.min(value, data.maxDate);
+            return value;
+        },
+        getBoundary(type, innerValue) {
+            const value = new Date(innerValue);
+            const boundary = new Date(this.data[`${type}Date`]);
+            const year = boundary.getFullYear();
+            let month = 1;
+            let date = 1;
+            let hour = 0;
+            let minute = 0;
+            if (type === 'max') {
+                month = 12;
+                date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
+                hour = 23;
+                minute = 59;
+            }
+            if (value.getFullYear() === year) {
+                month = boundary.getMonth() + 1;
+                if (value.getMonth() + 1 === month) {
+                    date = boundary.getDate();
+                    if (value.getDate() === date) {
+                        hour = boundary.getHours();
+                        if (value.getHours() === hour) {
+                            minute = boundary.getMinutes();
+                        }
+                    }
+                }
+            }
+            return {
+                [`${type}Year`]: year,
+                [`${type}Month`]: month,
+                [`${type}Date`]: date,
+                [`${type}Hour`]: hour,
+                [`${type}Minute`]: minute,
+            };
+        },
+        onCancel() {
+            this.$emit('cancel');
+        },
+        onConfirm() {
+            this.$emit('confirm', this.data.innerValue);
+        },
+        onChange() {
+            const { data } = this;
+            let value;
+            const picker = this.getPicker();
+            const originColumns = this.getOriginColumns();
+            if (data.type === 'time') {
+                const indexes = picker.getIndexes();
+                value = `${+originColumns[0].values[indexes[0]]}:${+originColumns[1]
+                    .values[indexes[1]]}`;
+            }
+            else {
+                const indexes = picker.getIndexes();
+                const values = indexes.map((value, index) => originColumns[index].values[value]);
+                const year = getTrueValue(values[0]);
+                const month = getTrueValue(values[1]);
+                const maxDate = getMonthEndDay(year, month);
+                let date = getTrueValue(values[2]);
+                if (data.type === 'year-month') {
+                    date = 1;
+                }
+                date = date > maxDate ? maxDate : date;
+                let hour = 0;
+                let minute = 0;
+                if (data.type === 'datetime') {
+                    hour = getTrueValue(values[3]);
+                    minute = getTrueValue(values[4]);
+                }
+                value = new Date(year, month - 1, date, hour, minute);
+            }
+            value = this.correctValue(value);
+            this.updateColumnValue(value).then(() => {
+                this.$emit('input', value);
+                this.$emit('change', picker);
+            });
+        },
+        updateColumnValue(value) {
+            let values = [];
+            const { type } = this.data;
+            const formatter = this.data.formatter || defaultFormatter;
+            const picker = this.getPicker();
+            if (type === 'time') {
+                const pair = value.split(':');
+                values = [formatter('hour', pair[0]), formatter('minute', pair[1])];
+            }
+            else {
+                const date = new Date(value);
+                values = [
+                    formatter('year', `${date.getFullYear()}`),
+                    formatter('month', padZero(date.getMonth() + 1)),
+                ];
+                if (type === 'date') {
+                    values.push(formatter('day', padZero(date.getDate())));
+                }
+                if (type === 'datetime') {
+                    values.push(formatter('day', padZero(date.getDate())), formatter('hour', padZero(date.getHours())), formatter('minute', padZero(date.getMinutes())));
+                }
+            }
+            return this.set({ innerValue: value })
+                .then(() => this.updateColumns())
+                .then(() => picker.setValues(values));
+        },
+    },
+    created() {
+        const innerValue = this.correctValue(this.data.value);
+        this.updateColumnValue(innerValue).then(() => {
+            this.$emit('input', innerValue);
+        });
+    },
+});
+export default global['__wxComponents']['vant/datetime-picker/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';
+</style>

+ 167 - 0
src/wxcomponents/vant/dialog/index.vue

@@ -0,0 +1,167 @@
+<template>
+<uni-shadow-root class="vant-dialog-index"><van-popup :show="show" :z-index="zIndex" :overlay="overlay" :transition="transition" :custom-class="'van-dialog van-dialog--'+(theme)+' '+(className)" :custom-style="'width: '+(utils.addUnit(width))+';'+(customStyle)" :overlay-style="overlayStyle" :close-on-click-overlay="closeOnClickOverlay" @close="onClickOverlay">
+  <view v-if="title || useTitleSlot" :class="utils.bem('dialog__header', { isolated: !(message || useSlot) })">
+    <slot v-if="useTitleSlot" name="title"></slot>
+    <block v-else-if="title">{{ title }}</block>
+  </view>
+
+  <slot v-if="useSlot"></slot>
+  <view v-else-if="message" :class="utils.bem('dialog__message', [theme, messageAlign, { hasTitle: title }])">
+    <text class="van-dialog__message-text">{{ message }}</text>
+  </view>
+
+  <van-goods-action v-if="theme === 'round-button'" custom-class="van-dialog__footer--round-button">
+    <van-goods-action-button v-if="showCancelButton" size="large" :loading="loading.cancel" class="van-dialog__button van-hairline--right" custom-class="van-dialog__cancel" :custom-style="'color: '+(cancelButtonColor)" @click="onCancel">
+      {{ cancelButtonText }}
+    </van-goods-action-button>
+    <van-goods-action-button v-if="showConfirmButton" size="large" class="van-dialog__button" :loading="loading.confirm" custom-class="van-dialog__confirm" :custom-style="'color: '+(confirmButtonColor)" :open-type="confirmButtonOpenType" :lang="lang" :business-id="businessId" :session-from="sessionFrom" :send-message-title="sendMessageTitle" :send-message-path="sendMessagePath" :send-message-img="sendMessageImg" :show-message-card="showMessageCard" :app-parameter="appParameter" @click="onConfirm" @getuserinfo="onGetUserInfo" @contact="onContact" @getphonenumber="onGetPhoneNumber" @error="onError" @launchapp="onLaunchApp" @opensetting="onOpenSetting">
+      {{ confirmButtonText }}
+    </van-goods-action-button>
+  </van-goods-action>
+
+  <view v-else class="van-hairline--top van-dialog__footer">
+    <van-button v-if="showCancelButton" size="large" :loading="loading.cancel" class="van-dialog__button van-hairline--right" custom-class="van-dialog__cancel" :custom-style="'color: '+(cancelButtonColor)" @click="onCancel">
+      {{ cancelButtonText }}
+    </van-button>
+    <van-button v-if="showConfirmButton" size="large" class="van-dialog__button" :loading="loading.confirm" custom-class="van-dialog__confirm" :custom-style="'color: '+(confirmButtonColor)" :open-type="confirmButtonOpenType" :lang="lang" :business-id="businessId" :session-from="sessionFrom" :send-message-title="sendMessageTitle" :send-message-path="sendMessagePath" :send-message-img="sendMessageImg" :show-message-card="showMessageCard" :app-parameter="appParameter" @click="onConfirm" @getuserinfo="onGetUserInfo" @contact="onContact" @getphonenumber="onGetPhoneNumber" @error="onError" @launchapp="onLaunchApp" @opensetting="onOpenSetting">
+      {{ confirmButtonText }}
+    </van-button>
+  </view>
+</van-popup></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanPopup from '../popup/index.vue'
+import VanButton from '../button/index.vue'
+import VanGoodsAction from '../goods-action/index.vue'
+import VanGoodsActionButton from '../goods-action-button/index.vue'
+global['__wxVueOptions'] = {components:{'van-popup': VanPopup,'van-button': VanButton,'van-goods-action': VanGoodsAction,'van-goods-action-button': VanGoodsActionButton}}
+
+global['__wxRoute'] = 'vant/dialog/index'
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+import { GRAY, RED } from '../common/color';
+import { toPromise } from '../common/utils';
+VantComponent({
+    mixins: [button],
+    props: {
+        show: {
+            type: Boolean,
+            observer(show) {
+                !show && this.stopLoading();
+            },
+        },
+        title: String,
+        message: String,
+        theme: {
+            type: String,
+            value: 'default',
+        },
+        useSlot: Boolean,
+        className: String,
+        customStyle: String,
+        asyncClose: Boolean,
+        messageAlign: String,
+        beforeClose: null,
+        overlayStyle: String,
+        useTitleSlot: Boolean,
+        showCancelButton: Boolean,
+        closeOnClickOverlay: Boolean,
+        confirmButtonOpenType: String,
+        width: null,
+        zIndex: {
+            type: Number,
+            value: 2000,
+        },
+        confirmButtonText: {
+            type: String,
+            value: '确认',
+        },
+        cancelButtonText: {
+            type: String,
+            value: '取消',
+        },
+        confirmButtonColor: {
+            type: String,
+            value: RED,
+        },
+        cancelButtonColor: {
+            type: String,
+            value: GRAY,
+        },
+        showConfirmButton: {
+            type: Boolean,
+            value: true,
+        },
+        overlay: {
+            type: Boolean,
+            value: true,
+        },
+        transition: {
+            type: String,
+            value: 'scale',
+        },
+    },
+    data: {
+        loading: {
+            confirm: false,
+            cancel: false,
+        },
+        callback: (() => { }),
+    },
+    methods: {
+        onConfirm() {
+            this.handleAction('confirm');
+        },
+        onCancel() {
+            this.handleAction('cancel');
+        },
+        onClickOverlay() {
+            this.close('overlay');
+        },
+        close(action) {
+            this.setData({ show: false });
+            wx.nextTick(() => {
+                this.$emit('close', action);
+                const { callback } = this.data;
+                if (callback) {
+                    callback(action, this);
+                }
+            });
+        },
+        stopLoading() {
+            this.setData({
+                loading: {
+                    confirm: false,
+                    cancel: false,
+                },
+            });
+        },
+        handleAction(action) {
+            this.$emit(action, { dialog: this });
+            const { asyncClose, beforeClose } = this.data;
+            if (!asyncClose && !beforeClose) {
+                this.close(action);
+                return;
+            }
+            this.setData({
+                [`loading.${action}`]: true,
+            });
+            if (beforeClose) {
+                toPromise(beforeClose(action)).then((value) => {
+                    if (value) {
+                        this.close(action);
+                    }
+                    else {
+                        this.stopLoading();
+                    }
+                });
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/dialog/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-dialog{background-color:var(--dialog-background-color,#fff);border-radius:var(--dialog-border-radius,16px);font-size:var(--dialog-font-size,16px);overflow:hidden;top:45%!important;width:var(--dialog-width,320px)}@media (max-width:321px){.van-dialog{width:var(--dialog-small-screen-width,90%)}}.van-dialog__header{font-weight:var(--dialog-header-font-weight,500);line-height:var(--dialog-header-line-height,24px);padding-top:var(--dialog-header-padding-top,24px);text-align:center}.van-dialog__header--isolated{padding:var(--dialog-header-isolated-padding,24px 0)}.van-dialog__message{-webkit-overflow-scrolling:touch;font-size:var(--dialog-message-font-size,14px);line-height:var(--dialog-message-line-height,20px);max-height:var(--dialog-message-max-height,60vh);overflow-y:auto;padding:var(--dialog-message-padding,24px);text-align:center}.van-dialog__message-text{word-wrap:break-word}.van-dialog__message--hasTitle{color:var(--dialog-has-title-message-text-color,#646566);padding-top:var(--dialog-has-title-message-padding-top,8px)}.van-dialog__message--round-button{color:#323233;padding-bottom:16px}.van-dialog__message--left{text-align:left}.van-dialog__message--right{text-align:right}.van-dialog__footer{display:flex}.van-dialog__footer--round-button{padding:8px 24px 16px!important;position:relative!important}.van-dialog__button{flex:1}.van-dialog__cancel,.van-dialog__confirm{border:0!important}.van-dialog-bounce-enter{opacity:0;transform:translate3d(-50%,-50%,0) scale(.7)}.van-dialog-bounce-leave-active{opacity:0;transform:translate3d(-50%,-50%,0) scale(.9)}
+</style>

+ 28 - 0
src/wxcomponents/vant/divider/index.vue

@@ -0,0 +1,28 @@
+<template>
+<uni-shadow-root class="vant-divider-index"><view :class="'custom-class '+(utils.bem('divider', [{ dashed, hairline }, contentPosition]))" :style="computed.rootStyle({ borderColor, textColor, fontSize, customStyle })">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxVueOptions'] = {components:{}}
+
+global['__wxRoute'] = 'vant/divider/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        dashed: Boolean,
+        hairline: Boolean,
+        contentPosition: String,
+        fontSize: String,
+        borderColor: String,
+        textColor: String,
+        customStyle: String,
+    },
+});
+export default global['__wxComponents']['vant/divider/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-divider{align-items:center;border:0 solid var(--divider-border-color,#ebedf0);color:var(--divider-text-color,#969799);display:flex;font-size:var(--divider-font-size,14px);line-height:var(--divider-line-height,24px);margin:var(--divider-margin,16px 0)}.van-divider:after,.van-divider:before{border-color:inherit;border-style:inherit;border-width:1px 0 0;box-sizing:border-box;display:block;flex:1;height:1px}.van-divider:before{content:""}.van-divider--hairline:after,.van-divider--hairline:before{transform:scaleY(.5)}.van-divider--dashed{border-style:dashed}.van-divider--center:before,.van-divider--left:before,.van-divider--right:before{margin-right:var(--divider-content-padding,16px)}.van-divider--center:after,.van-divider--left:after,.van-divider--right:after{content:"";margin-left:var(--divider-content-padding,16px)}.van-divider--left:before{max-width:var(--divider-content-left-width,10%)}.van-divider--right:after{max-width:var(--divider-content-right-width,10%)}
+</style>

+ 129 - 0
src/wxcomponents/vant/dropdown-item/index.vue

@@ -0,0 +1,129 @@
+<template>
+<uni-shadow-root class="vant-dropdown-item-index"><view v-if="showWrapper" :class="utils.bem('dropdown-item', direction)" :style="wrapperStyle">
+  <van-popup :show="showPopup" :custom-style="'position: absolute;'+(popupStyle)" overlay-style="position: absolute;" :overlay="overlay" :position="direction === 'down' ? 'top' : 'bottom'" :duration="transition ? duration : 0" :close-on-click-overlay="closeOnClickOverlay" @enter="onOpen" @leave="onClose" @close="toggle" @after-enter="onOpened" @after-leave="onClosed">
+    <van-cell v-for="(item,index) in (options)" :key="item.value" :data-option="item" :class="utils.bem('dropdown-item__option', { active: item.value === value } )" clickable :icon="item.icon" @click.native="onOptionTap">
+      <view slot="title" class="van-dropdown-item__title" :style="item.value === value  ? 'color:' + activeColor : ''">
+        {{ item.text }}
+      </view>
+      <van-icon v-if="item.value === value" name="success" class="van-dropdown-item__icon" :color="activeColor"></van-icon>
+    </van-cell>
+
+    <slot></slot>
+  </van-popup>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanPopup from '../popup/index.vue'
+import VanCell from '../cell/index.vue'
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-popup': VanPopup,'van-cell': VanCell,'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/dropdown-item/index'
+import { useParent } from '../common/relation';
+import { VantComponent } from '../common/component';
+VantComponent({
+    field: true,
+    relation: useParent('dropdown-menu', function () {
+        this.updateDataFromParent();
+    }),
+    props: {
+        value: {
+            type: null,
+            observer: 'rerender',
+        },
+        title: {
+            type: String,
+            observer: 'rerender',
+        },
+        disabled: Boolean,
+        titleClass: {
+            type: String,
+            observer: 'rerender',
+        },
+        options: {
+            type: Array,
+            value: [],
+            observer: 'rerender',
+        },
+        popupStyle: String,
+    },
+    data: {
+        transition: true,
+        showPopup: false,
+        showWrapper: false,
+        displayTitle: '',
+    },
+    methods: {
+        rerender() {
+            wx.nextTick(() => {
+                var _a;
+                (_a = this.parent) === null || _a === void 0 ? void 0 : _a.updateItemListData();
+            });
+        },
+        updateDataFromParent() {
+            if (this.parent) {
+                const { overlay, duration, activeColor, closeOnClickOverlay, direction, } = this.parent.data;
+                this.setData({
+                    overlay,
+                    duration,
+                    activeColor,
+                    closeOnClickOverlay,
+                    direction,
+                });
+            }
+        },
+        onOpen() {
+            this.$emit('open');
+        },
+        onOpened() {
+            this.$emit('opened');
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClosed() {
+            this.$emit('closed');
+            this.setData({ showWrapper: false });
+        },
+        onOptionTap(event) {
+            const { option } = event.currentTarget.dataset;
+            const { value } = option;
+            const shouldEmitChange = this.data.value !== value;
+            this.setData({ showPopup: false, value });
+            this.$emit('close');
+            this.rerender();
+            if (shouldEmitChange) {
+                this.$emit('change', value);
+            }
+        },
+        toggle(show, options = {}) {
+            var _a;
+            const { showPopup } = this.data;
+            if (typeof show !== 'boolean') {
+                show = !showPopup;
+            }
+            if (show === showPopup) {
+                return;
+            }
+            this.setData({
+                transition: !options.immediate,
+                showPopup: show,
+            });
+            if (show) {
+                (_a = this.parent) === null || _a === void 0 ? void 0 : _a.getChildWrapperStyle().then((wrapperStyle) => {
+                    this.setData({ wrapperStyle, showWrapper: true });
+                    this.rerender();
+                });
+            }
+            else {
+                this.rerender();
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/dropdown-item/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-dropdown-item{left:0;overflow:hidden;position:fixed;right:0}.van-dropdown-item__option{text-align:left}.van-dropdown-item__option--active .van-dropdown-item__icon,.van-dropdown-item__option--active .van-dropdown-item__title{color:var(--dropdown-menu-option-active-color,#ee0a24)}.van-dropdown-item--up{top:0}.van-dropdown-item--down{bottom:0}.van-dropdown-item__icon{display:block;line-height:inherit}
+</style>

+ 134 - 0
src/wxcomponents/vant/dropdown-menu/index.vue

@@ -0,0 +1,134 @@
+<template>
+<uni-shadow-root class="vant-dropdown-menu-index"><view class="van-dropdown-menu van-dropdown-menu--top-bottom custom-class">
+  <view v-for="(item,index) in (itemListData)" :key="item.index" :data-index="index" :class="utils.bem('dropdown-menu__item', { disabled: item.disabled })" @click="onTitleTap">
+    <view :class="(item.titleClass)+' '+(utils.bem('dropdown-menu__title', { active: item.showPopup, down: item.showPopup === (direction === 'down') }))" :style="item.showPopup ? 'color:' + activeColor : ''">
+      <view class="van-ellipsis">
+        {{ computed.displayTitle(item) }}
+      </view>
+    </view>
+  </view>
+
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/dropdown-menu/index'
+import { VantComponent } from '../common/component';
+import { useChildren } from '../common/relation';
+import { addUnit, getRect, getSystemInfoSync } from '../common/utils';
+let ARRAY = [];
+VantComponent({
+    field: true,
+    relation: useChildren('dropdown-item', function () {
+        this.updateItemListData();
+    }),
+    props: {
+        activeColor: {
+            type: String,
+            observer: 'updateChildrenData',
+        },
+        overlay: {
+            type: Boolean,
+            value: true,
+            observer: 'updateChildrenData',
+        },
+        zIndex: {
+            type: Number,
+            value: 10,
+        },
+        duration: {
+            type: Number,
+            value: 200,
+            observer: 'updateChildrenData',
+        },
+        direction: {
+            type: String,
+            value: 'down',
+            observer: 'updateChildrenData',
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true,
+            observer: 'updateChildrenData',
+        },
+        closeOnClickOutside: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    data: {
+        itemListData: [],
+    },
+    beforeCreate() {
+        const { windowHeight } = getSystemInfoSync();
+        this.windowHeight = windowHeight;
+        ARRAY.push(this);
+    },
+    destroyed() {
+        ARRAY = ARRAY.filter((item) => item !== this);
+    },
+    methods: {
+        updateItemListData() {
+            this.setData({
+                itemListData: this.children.map((child) => child.data),
+            });
+        },
+        updateChildrenData() {
+            this.children.forEach((child) => {
+                child.updateDataFromParent();
+            });
+        },
+        toggleItem(active) {
+            this.children.forEach((item, index) => {
+                const { showPopup } = item.data;
+                if (index === active) {
+                    item.toggle();
+                }
+                else if (showPopup) {
+                    item.toggle(false, { immediate: true });
+                }
+            });
+        },
+        close() {
+            this.children.forEach((child) => {
+                child.toggle(false, { immediate: true });
+            });
+        },
+        getChildWrapperStyle() {
+            const { zIndex, direction } = this.data;
+            return getRect(this, '.van-dropdown-menu').then((rect) => {
+                const { top = 0, bottom = 0 } = rect;
+                const offset = direction === 'down' ? bottom : this.windowHeight - top;
+                let wrapperStyle = `z-index: ${zIndex};`;
+                if (direction === 'down') {
+                    wrapperStyle += `top: ${addUnit(offset)};`;
+                }
+                else {
+                    wrapperStyle += `bottom: ${addUnit(offset)};`;
+                }
+                return wrapperStyle;
+            });
+        },
+        onTitleTap(event) {
+            const { index } = event.currentTarget.dataset;
+            const child = this.children[index];
+            if (!child.data.disabled) {
+                ARRAY.forEach((menuItem) => {
+                    if (menuItem &&
+                        menuItem.data.closeOnClickOutside &&
+                        menuItem !== this) {
+                        menuItem.close();
+                    }
+                });
+                this.toggleItem(index);
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/dropdown-menu/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-dropdown-menu{background-color:var(--dropdown-menu-background-color,#fff);box-shadow:var(--dropdown-menu-box-shadow,0 2px 12px hsla(210,1%,40%,.12));display:flex;height:var(--dropdown-menu-height,50px);-webkit-user-select:none;user-select:none}.van-dropdown-menu__item{align-items:center;display:flex;flex:1;justify-content:center;min-width:0}.van-dropdown-menu__item:active{opacity:.7}.van-dropdown-menu__item--disabled:active{opacity:1}.van-dropdown-menu__item--disabled .van-dropdown-menu__title{color:var(--dropdown-menu-title-disabled-text-color,#969799)}.van-dropdown-menu__title{box-sizing:border-box;color:var(--dropdown-menu-title-text-color,#323233);font-size:var(--dropdown-menu-title-font-size,15px);line-height:var(--dropdown-menu-title-line-height,18px);max-width:100%;padding:var(--dropdown-menu-title-padding,0 8px);position:relative}.van-dropdown-menu__title:after{border-color:transparent transparent currentcolor currentcolor;border-style:solid;border-width:3px;content:"";margin-top:-5px;opacity:.8;position:absolute;right:-4px;top:50%;transform:rotate(-45deg)}.van-dropdown-menu__title--active{color:var(--dropdown-menu-title-active-text-color,#ee0a24)}.van-dropdown-menu__title--down:after{margin-top:-1px;transform:rotate(135deg)}
+</style>

+ 42 - 0
src/wxcomponents/vant/empty/index.vue

@@ -0,0 +1,42 @@
+<template>
+<uni-shadow-root class="vant-empty-index"><view class="custom-class van-empty">
+  <view class="van-empty__image">
+    <slot name="image"></slot>
+  </view>
+  <view class="van-empty__image">
+    <image v-if="image" class="van-empty__image__img" :src="computed.imageUrl(image)"></image>
+  </view>
+
+  <view class="van-empty__description">
+    <slot name="description"></slot>
+  </view>
+  <view class="van-empty__description">
+    {{ description }}
+  </view>
+
+  <view class="van-empty__bottom">
+    <slot></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxVueOptions'] = {components:{}}
+
+global['__wxRoute'] = 'vant/empty/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        description: String,
+        image: {
+            type: String,
+            value: 'default',
+        },
+    },
+});
+export default global['__wxComponents']['vant/empty/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-empty{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center;padding:32px 0}.van-empty__image{height:160px;width:160px}.van-empty__image:empty{display:none}.van-empty__image__img{height:100%;width:100%}.van-empty__image:not(:empty)+.van-empty__image{display:none}.van-empty__description{color:#969799;font-size:14px;line-height:20px;margin-top:16px;padding:0 60px}.van-empty__description:empty,.van-empty__description:not(:empty)+.van-empty__description{display:none}.van-empty__bottom{margin-top:24px}
+</style>

File diff suppressed because it is too large
+ 149 - 0
src/wxcomponents/vant/field/index.vue


+ 15 - 0
src/wxcomponents/vant/field/input.vue

@@ -0,0 +1,15 @@
+<template>
+<uni-shadow-root class="vant-field-input"><input :class="(utils.bem('field__control', [inputAlign, { disabled, error }]))+' input-class'" :type="type" :focus="focus" :cursor="cursor" :value="innerValue" :auto-focus="autoFocus" :disabled="disabled || readonly" :maxlength="maxlength" :placeholder="placeholder" :placeholder-style="placeholderStyle" :placeholder-class="utils.bem('field__placeholder', { error })" :confirm-type="confirmType" :confirm-hold="confirmHold" :hold-keyboard="holdKeyboard" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" :selection-end="selectionEnd" :selection-start="selectionStart" :always-embed="alwaysEmbed" :password="password || type === 'password'" @input="onInput" @click="onClickInput" @blur="onBlur" @focus="onFocus" @confirm="onConfirm" @keyboardheightchange="onKeyboardHeightChange"></input></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/field/input'
+
+Component({})
+
+export default global['__wxComponents']['vant/field/input']
+</script>
+<style platform="mp-weixin">
+
+</style>

+ 15 - 0
src/wxcomponents/vant/field/textarea.vue

@@ -0,0 +1,15 @@
+<template>
+<uni-shadow-root class="vant-field-textarea"><textarea :class="(utils.bem('field__control', [inputAlign, type, { disabled, error }]))+' input-class'" :fixed="fixed" :focus="focus" :cursor="cursor" :value="innerValue" :auto-focus="autoFocus" :disabled="disabled || readonly" :maxlength="maxlength" :placeholder="placeholder" :placeholder-style="placeholderStyle" :placeholder-class="utils.bem('field__placeholder', { error, disabled })" :auto-height="(!!autosize)" :style="computed.inputStyle(autosize)" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" :show-confirm-bar="showConfirmBar" :hold-keyboard="holdKeyboard" :selection-end="selectionEnd" :selection-start="selectionStart" :disable-default-padding="disableDefaultPadding" @input="onInput" @click="onClickInput" @blur="onBlur" @focus="onFocus" @confirm="onConfirm" @linechange="onLineChange" @keyboardheightchange="onKeyboardHeightChange"></textarea></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/field/textarea'
+
+Component({})
+
+export default global['__wxComponents']['vant/field/textarea']
+</script>
+<style platform="mp-weixin">
+
+</style>

+ 53 - 0
src/wxcomponents/vant/goods-action-button/index.vue

@@ -0,0 +1,53 @@
+<template>
+<uni-shadow-root class="vant-goods-action-button-index"><van-button :id="id" :lang="lang" :type="type" :color="color" :plain="plain" :loading="loading" :disabled="disabled" :open-type="openType" :class="utils.bem('goods-action-button', [type, { first: isFirst, last: isLast, plain: plain }])" custom-class="van-goods-action-button__inner" :business-id="businessId" :session-from="sessionFrom" :app-parameter="appParameter" :send-message-img="sendMessageImg" :send-message-path="sendMessagePath" :show-message-card="showMessageCard" :send-message-title="sendMessageTitle" @click="onClick" @error="onError" @contact="onContact" @opensetting="onOpenSetting" @getuserinfo="onGetUserInfo" @getphonenumber="onGetPhoneNumber" @launchapp="onLaunchApp">
+  {{ text }}
+  <slot></slot>
+</van-button></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanButton from '../button/index.vue'
+global['__wxVueOptions'] = {components:{'van-button': VanButton}}
+
+global['__wxRoute'] = 'vant/goods-action-button/index'
+import { VantComponent } from '../common/component';
+import { useParent } from '../common/relation';
+import { button } from '../mixins/button';
+import { link } from '../mixins/link';
+VantComponent({
+    mixins: [link, button],
+    relation: useParent('goods-action'),
+    props: {
+        text: String,
+        color: String,
+        loading: Boolean,
+        disabled: Boolean,
+        plain: Boolean,
+        type: {
+            type: String,
+            value: 'danger',
+        },
+    },
+    methods: {
+        onClick(event) {
+            this.$emit('click', event.detail);
+            this.jumpLink();
+        },
+        updateStyle() {
+            if (this.parent == null) {
+                return;
+            }
+            const { index } = this;
+            const { children = [] } = this.parent;
+            this.setData({
+                isFirst: index === 0,
+                isLast: index === children.length - 1,
+            });
+        },
+    },
+});
+export default global['__wxComponents']['vant/goods-action-button/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.vant-goods-action-button-index{flex:1}.van-goods-action-button{--button-warning-background-color:var(--goods-action-button-warning-color,linear-gradient(to right,#ffd01e,#ff8917));--button-danger-background-color:var(--goods-action-button-danger-color,linear-gradient(to right,#ff6034,#ee0a24));--button-default-height:var(--goods-action-button-height,40px);--button-line-height:var(--goods-action-button-line-height,20px);--button-plain-background-color:var(--goods-action-button-plain-color,#fff);--button-border-width:0;display:block}.van-goods-action-button--first{--button-border-radius:999px 0 0 var(--goods-action-button-border-radius,999px);margin-left:5px}.van-goods-action-button--last{--button-border-radius:0 999px var(--goods-action-button-border-radius,999px) 0;margin-right:5px}.van-goods-action-button--first.van-goods-action-button--last{--button-border-radius:var(--goods-action-button-border-radius,999px)}.van-goods-action-button--plain{--button-border-width:1px}.van-goods-action-button__inner{font-weight:var(--font-weight-bold,500)!important;width:100%}@media (max-width:321px){.van-goods-action-button{font-size:13px}}
+</style>

+ 44 - 0
src/wxcomponents/vant/goods-action-icon/index.vue

@@ -0,0 +1,44 @@
+<template>
+<uni-shadow-root class="vant-goods-action-icon-index"><van-button square :id="id" size="large" :lang="lang" :loading="loading" :disabled="disabled" :open-type="openType" :business-id="businessId" custom-class="van-goods-action-icon" :session-from="sessionFrom" :app-parameter="appParameter" :send-message-img="sendMessageImg" :send-message-path="sendMessagePath" :show-message-card="showMessageCard" :send-message-title="sendMessageTitle" @click="onClick" @error="onError" @contact="onContact" @opensetting="onOpenSetting" @getuserinfo="onGetUserInfo" @getphonenumber="onGetPhoneNumber" @launchapp="onLaunchApp">
+  <van-icon v-if="icon" :name="icon" :dot="dot" :info="info" :class-prefix="classPrefix" class="van-goods-action-icon__icon" custom-class="icon-class"></van-icon>
+  <slot v-else name="icon"></slot>
+  <text class="text-class">{{ text }}</text>
+</van-button></uni-shadow-root>
+</template>
+
+<script>
+import VanIcon from '../icon/index.vue'
+import VanButton from '../button/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon,'van-button': VanButton}}
+
+global['__wxRoute'] = 'vant/goods-action-icon/index'
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+import { link } from '../mixins/link';
+VantComponent({
+    classes: ['icon-class', 'text-class'],
+    mixins: [link, button],
+    props: {
+        text: String,
+        dot: Boolean,
+        info: String,
+        icon: String,
+        classPrefix: {
+            type: String,
+            value: 'van-icon',
+        },
+        disabled: Boolean,
+        loading: Boolean,
+    },
+    methods: {
+        onClick(event) {
+            this.$emit('click', event.detail);
+            this.jumpLink();
+        },
+    },
+});
+export default global['__wxComponents']['vant/goods-action-icon/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-goods-action-icon{border:none!important;color:var(--goods-action-icon-text-color,#646566)!important;display:flex!important;flex-direction:column;font-size:var(--goods-action-icon-font-size,10px)!important;height:var(--goods-action-icon-height,50px)!important;justify-content:center!important;line-height:1!important;min-width:var(--goods-action-icon-width,48px)}.van-goods-action-icon__icon{color:var(--goods-action-icon-color,#323233);display:flex;font-size:var(--goods-action-icon-size,18px);margin:0 auto 5px}
+</style>

+ 29 - 0
src/wxcomponents/vant/goods-action/index.vue

@@ -0,0 +1,29 @@
+<template>
+<uni-shadow-root class="vant-goods-action-index"><view :class="'custom-class '+(utils.bem('goods-action', { safe: safeAreaInsetBottom }))">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/goods-action/index'
+import { VantComponent } from '../common/component';
+import { useChildren } from '../common/relation';
+VantComponent({
+    relation: useChildren('goods-action-button', function () {
+        this.children.forEach((item) => {
+            item.updateStyle();
+        });
+    }),
+    props: {
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+    },
+});
+export default global['__wxComponents']['vant/goods-action/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-goods-action{align-items:center;background-color:var(--goods-action-background-color,#fff);bottom:0;box-sizing:initial;display:flex;height:var(--goods-action-height,50px);left:0;position:fixed;right:0}.van-goods-action--safe{padding-bottom:env(safe-area-inset-bottom)}
+</style>

+ 82 - 0
src/wxcomponents/vant/grid-item/index.vue

@@ -0,0 +1,82 @@
+<template>
+<uni-shadow-root class="vant-grid-item-index"><view :class="'custom-class '+(utils.bem('grid-item', { square }))" :style="computed.wrapperStyle({ square, gutter, columnNum, index })" @click="onClick">
+  <view :class="'content-class '+(utils.bem('grid-item__content', [direction, { center, square, reverse, clickable, surround: border && gutter }]))+' '+(border ? 'van-hairline--surround' : '')" :style="computed.contentStyle({ square, gutter })">
+    <block v-if="useSlot">
+      <slot></slot>
+    </block>
+    <block v-else>
+      <view class="van-grid-item__icon icon-class">
+        <van-icon v-if="icon" :name="icon" :color="iconColor" :class-prefix="iconPrefix" :dot="dot" :info="badge || info" :size="iconSize"></van-icon>
+        <slot v-else name="icon"></slot>
+      </view>
+      <view class="van-grid-item__text text-class">
+        <text v-if="text">{{ text }}</text>
+        <slot v-else name="text"></slot>
+      </view>
+    </block>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/grid-item/index'
+import { VantComponent } from '../common/component';
+import { useParent } from '../common/relation';
+import { link } from '../mixins/link';
+VantComponent({
+    relation: useParent('grid'),
+    classes: ['content-class', 'icon-class', 'text-class'],
+    mixins: [link],
+    props: {
+        icon: String,
+        iconColor: String,
+        iconPrefix: {
+            type: String,
+            value: 'van-icon',
+        },
+        dot: Boolean,
+        info: null,
+        badge: null,
+        text: String,
+        useSlot: Boolean,
+    },
+    data: {
+        viewStyle: '',
+    },
+    mounted() {
+        this.updateStyle();
+    },
+    methods: {
+        updateStyle() {
+            if (!this.parent) {
+                return;
+            }
+            const { data, children } = this.parent;
+            const { columnNum, border, square, gutter, clickable, center, direction, reverse, iconSize, } = data;
+            this.setData({
+                center,
+                border,
+                square,
+                gutter,
+                clickable,
+                direction,
+                reverse,
+                iconSize,
+                index: children.indexOf(this),
+                columnNum,
+            });
+        },
+        onClick() {
+            this.$emit('click');
+            this.jumpLink();
+        },
+    },
+});
+export default global['__wxComponents']['vant/grid-item/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-grid-item{box-sizing:border-box;float:left;position:relative}.van-grid-item--square{height:0}.van-grid-item__content{background-color:var(--grid-item-content-background-color,#fff);box-sizing:border-box;display:flex;flex-direction:column;height:100%;padding:var(--grid-item-content-padding,16px 8px)}.van-grid-item__content:after{border-width:0 1px 1px 0;z-index:1}.van-grid-item__content--surround:after{border-width:1px}.van-grid-item__content--center{align-items:center;justify-content:center}.van-grid-item__content--square{left:0;position:absolute;right:0;top:0}.van-grid-item__content--horizontal{flex-direction:row}.van-grid-item__content--horizontal .van-grid-item__text{margin:0 0 0 8px}.van-grid-item__content--reverse{flex-direction:column-reverse}.van-grid-item__content--reverse .van-grid-item__text{margin:0 0 8px}.van-grid-item__content--horizontal.van-grid-item__content--reverse{flex-direction:row-reverse}.van-grid-item__content--horizontal.van-grid-item__content--reverse .van-grid-item__text{margin:0 8px 0 0}.van-grid-item__content--clickable:active{background-color:var(--grid-item-content-active-color,#f2f3f5)}.van-grid-item__icon{align-items:center;display:flex;font-size:var(--grid-item-icon-size,26px);height:var(--grid-item-icon-size,26px)}.van-grid-item__text{word-wrap:break-word;color:var(--grid-item-text-color,#646566);font-size:var(--grid-item-text-font-size,12px)}.van-grid-item__icon+.van-grid-item__text{margin-top:8px}
+</style>

+ 69 - 0
src/wxcomponents/vant/grid/index.vue

@@ -0,0 +1,69 @@
+<template>
+<uni-shadow-root class="vant-grid-index"><view :class="'van-grid custom-class '+(border && !gutter ? 'van-hairline--top' : '')" :style="computed.rootStyle({ gutter })">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/grid/index'
+import { VantComponent } from '../common/component';
+import { useChildren } from '../common/relation';
+VantComponent({
+    relation: useChildren('grid-item'),
+    props: {
+        square: {
+            type: Boolean,
+            observer: 'updateChildren',
+        },
+        gutter: {
+            type: null,
+            value: 0,
+            observer: 'updateChildren',
+        },
+        clickable: {
+            type: Boolean,
+            observer: 'updateChildren',
+        },
+        columnNum: {
+            type: Number,
+            value: 4,
+            observer: 'updateChildren',
+        },
+        center: {
+            type: Boolean,
+            value: true,
+            observer: 'updateChildren',
+        },
+        border: {
+            type: Boolean,
+            value: true,
+            observer: 'updateChildren',
+        },
+        direction: {
+            type: String,
+            observer: 'updateChildren',
+        },
+        iconSize: {
+            type: String,
+            observer: 'updateChildren',
+        },
+        reverse: {
+            type: Boolean,
+            value: false,
+            observer: 'updateChildren',
+        },
+    },
+    methods: {
+        updateChildren() {
+            this.children.forEach((child) => {
+                child.updateStyle();
+            });
+        },
+    },
+});
+export default global['__wxComponents']['vant/grid/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-grid{box-sizing:border-box;overflow:hidden;position:relative}
+</style>

File diff suppressed because it is too large
+ 35 - 0
src/wxcomponents/vant/icon/index.vue


+ 86 - 0
src/wxcomponents/vant/image/index.vue

@@ -0,0 +1,86 @@
+<template>
+<uni-shadow-root class="vant-image-index"><view :style="computed.rootStyle({ width, height, radius })" :class="'custom-class '+(utils.bem('image', { round }))" @click="onClick">
+  <image v-if="(!error)" :src="src" :mode="computed.mode(fit)" :lazy-load="lazyLoad" class="image-class van-image__img" :show-menu-by-longpress="showMenuByLongpress" @load="onImageLoad" @error="onImageError"></image>
+
+  <view v-if="loading && showLoading" class="loading-class van-image__loading">
+    <slot v-if="useLoadingSlot" name="loading"></slot>
+    <van-icon v-else name="photo" custom-class="van-image__loading-icon"></van-icon>
+  </view>
+  <view v-if="error && showError" class="error-class van-image__error">
+    <slot v-if="useErrorSlot" name="error"></slot>
+    <van-icon v-else name="photo-fail" custom-class="van-image__error-icon"></van-icon>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+import VanLoading from '../loading/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon,'van-loading': VanLoading}}
+
+global['__wxRoute'] = 'vant/image/index'
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+VantComponent({
+    mixins: [button],
+    classes: ['custom-class', 'loading-class', 'error-class', 'image-class'],
+    props: {
+        src: {
+            type: String,
+            observer() {
+                this.setData({
+                    error: false,
+                    loading: true,
+                });
+            },
+        },
+        round: Boolean,
+        width: null,
+        height: null,
+        radius: null,
+        lazyLoad: Boolean,
+        useErrorSlot: Boolean,
+        useLoadingSlot: Boolean,
+        showMenuByLongpress: Boolean,
+        fit: {
+            type: String,
+            value: 'fill',
+        },
+        showError: {
+            type: Boolean,
+            value: true,
+        },
+        showLoading: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    data: {
+        error: false,
+        loading: true,
+        viewStyle: '',
+    },
+    methods: {
+        onImageLoad(event) {
+            this.setData({
+                loading: false,
+            });
+            this.$emit('load', event.detail);
+        },
+        onImageError(event) {
+            this.setData({
+                loading: false,
+                error: true,
+            });
+            this.$emit('error', event.detail);
+        },
+        onClick(event) {
+            this.$emit('click', event.detail);
+        },
+    },
+});
+export default global['__wxComponents']['vant/image/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-image{display:inline-block;position:relative}.van-image--round{border-radius:50%;overflow:hidden}.van-image--round .van-image__img{border-radius:inherit}.van-image__error,.van-image__img,.van-image__loading{display:block;height:100%;width:100%}.van-image__error,.van-image__loading{align-items:center;background-color:var(--image-placeholder-background-color,#f7f8fa);color:var(--image-placeholder-text-color,#969799);display:flex;flex-direction:column;font-size:var(--image-placeholder-font-size,14px);justify-content:center;left:0;position:absolute;top:0}.van-image__loading-icon{color:var(--image-loading-icon-color,#dcdee0);font-size:var(--image-loading-icon-size,32px)!important}.van-image__error-icon{color:var(--image-error-icon-color,#dcdee0);font-size:var(--image-error-icon-size,32px)!important}
+</style>

+ 44 - 0
src/wxcomponents/vant/index-anchor/index.vue

@@ -0,0 +1,44 @@
+<template>
+<uni-shadow-root class="vant-index-anchor-index"><view class="van-index-anchor-wrapper" :style="wrapperStyle">
+  <view :class="'van-index-anchor '+(active ? 'van-index-anchor--active van-hairline--bottom' : '')" :style="anchorStyle">
+    <slot v-if="useSlot"></slot>
+    <block v-else>
+      <text>{{ index }}</text>
+    </block>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/index-anchor/index'
+import { getRect } from '../common/utils';
+import { VantComponent } from '../common/component';
+import { useParent } from '../common/relation';
+VantComponent({
+    relation: useParent('index-bar'),
+    props: {
+        useSlot: Boolean,
+        index: null,
+    },
+    data: {
+        active: false,
+        wrapperStyle: '',
+        anchorStyle: '',
+    },
+    methods: {
+        scrollIntoView(scrollTop) {
+            getRect(this, '.van-index-anchor-wrapper').then((rect) => {
+                wx.pageScrollTo({
+                    duration: 0,
+                    scrollTop: scrollTop + rect.top - this.parent.data.stickyOffsetTop,
+                });
+            });
+        },
+    },
+});
+export default global['__wxComponents']['vant/index-anchor/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-index-anchor{background-color:var(--index-anchor-background-color,transparent);color:var(--index-anchor-text-color,#323233);font-size:var(--index-anchor-font-size,14px);font-weight:var(--index-anchor-font-weight,500);line-height:var(--index-anchor-line-height,32px);padding:var(--index-anchor-padding,0 16px)}.van-index-anchor--active{background-color:var(--index-anchor-active-background-color,#fff);color:var(--index-anchor-active-text-color,#07c160);left:0;right:0}
+</style>

+ 266 - 0
src/wxcomponents/vant/index-bar/index.vue

@@ -0,0 +1,266 @@
+<template>
+<uni-shadow-root class="vant-index-bar-index"><view class="van-index-bar">
+  <slot></slot>
+
+  <view v-if="showSidebar" class="van-index-bar__sidebar" @click.stop.prevent="onClick" @touchmove.stop.prevent="onTouchMove" @touchend.stop.prevent="onTouchStop" @touchcancel.stop.prevent="onTouchStop">
+    <view v-for="(item,index) in (indexList)" :key="item.index" class="van-index-bar__index" :style="'z-index: '+(zIndex + 1)+'; color: '+(activeAnchorIndex === index ? highlightColor : '')" :data-index="index">
+      {{ item }}
+    </view>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/index-bar/index'
+import { GREEN } from '../common/color';
+import { VantComponent } from '../common/component';
+import { useChildren } from '../common/relation';
+import { getRect, isDef } from '../common/utils';
+import { pageScrollMixin } from '../mixins/page-scroll';
+const indexList = () => {
+    const indexList = [];
+    const charCodeOfA = 'A'.charCodeAt(0);
+    for (let i = 0; i < 26; i++) {
+        indexList.push(String.fromCharCode(charCodeOfA + i));
+    }
+    return indexList;
+};
+VantComponent({
+    relation: useChildren('index-anchor', function () {
+        this.updateData();
+    }),
+    props: {
+        sticky: {
+            type: Boolean,
+            value: true,
+        },
+        zIndex: {
+            type: Number,
+            value: 1,
+        },
+        highlightColor: {
+            type: String,
+            value: GREEN,
+        },
+        stickyOffsetTop: {
+            type: Number,
+            value: 0,
+        },
+        indexList: {
+            type: Array,
+            value: indexList(),
+        },
+    },
+    mixins: [
+        pageScrollMixin(function (event) {
+            this.scrollTop = (event === null || event === void 0 ? void 0 : event.scrollTop) || 0;
+            this.onScroll();
+        }),
+    ],
+    data: {
+        activeAnchorIndex: null,
+        showSidebar: false,
+    },
+    created() {
+        this.scrollTop = 0;
+    },
+    methods: {
+        updateData() {
+            wx.nextTick(() => {
+                if (this.timer != null) {
+                    clearTimeout(this.timer);
+                }
+                this.timer = setTimeout(() => {
+                    this.setData({
+                        showSidebar: !!this.children.length,
+                    });
+                    this.setRect().then(() => {
+                        this.onScroll();
+                    });
+                }, 0);
+            });
+        },
+        setRect() {
+            return Promise.all([
+                this.setAnchorsRect(),
+                this.setListRect(),
+                this.setSiderbarRect(),
+            ]);
+        },
+        setAnchorsRect() {
+            return Promise.all(this.children.map((anchor) => getRect(anchor, '.van-index-anchor-wrapper').then((rect) => {
+                Object.assign(anchor, {
+                    height: rect.height,
+                    top: rect.top + this.scrollTop,
+                });
+            })));
+        },
+        setListRect() {
+            return getRect(this, '.van-index-bar').then((rect) => {
+                if (!isDef(rect)) {
+                    return;
+                }
+                Object.assign(this, {
+                    height: rect.height,
+                    top: rect.top + this.scrollTop,
+                });
+            });
+        },
+        setSiderbarRect() {
+            return getRect(this, '.van-index-bar__sidebar').then((res) => {
+                if (!isDef(res)) {
+                    return;
+                }
+                this.sidebar = {
+                    height: res.height,
+                    top: res.top,
+                };
+            });
+        },
+        setDiffData({ target, data }) {
+            const diffData = {};
+            Object.keys(data).forEach((key) => {
+                if (target.data[key] !== data[key]) {
+                    diffData[key] = data[key];
+                }
+            });
+            if (Object.keys(diffData).length) {
+                target.setData(diffData);
+            }
+        },
+        getAnchorRect(anchor) {
+            return getRect(anchor, '.van-index-anchor-wrapper').then((rect) => ({
+                height: rect.height,
+                top: rect.top,
+            }));
+        },
+        getActiveAnchorIndex() {
+            const { children, scrollTop } = this;
+            const { sticky, stickyOffsetTop } = this.data;
+            for (let i = this.children.length - 1; i >= 0; i--) {
+                const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
+                const reachTop = sticky ? preAnchorHeight + stickyOffsetTop : 0;
+                if (reachTop + scrollTop >= children[i].top) {
+                    return i;
+                }
+            }
+            return -1;
+        },
+        onScroll() {
+            const { children = [], scrollTop } = this;
+            if (!children.length) {
+                return;
+            }
+            const { sticky, stickyOffsetTop, zIndex, highlightColor } = this.data;
+            const active = this.getActiveAnchorIndex();
+            this.setDiffData({
+                target: this,
+                data: {
+                    activeAnchorIndex: active,
+                },
+            });
+            if (sticky) {
+                let isActiveAnchorSticky = false;
+                if (active !== -1) {
+                    isActiveAnchorSticky =
+                        children[active].top <= stickyOffsetTop + scrollTop;
+                }
+                children.forEach((item, index) => {
+                    if (index === active) {
+                        let wrapperStyle = '';
+                        let anchorStyle = `
+              color: ${highlightColor};
+            `;
+                        if (isActiveAnchorSticky) {
+                            wrapperStyle = `
+                height: ${children[index].height}px;
+              `;
+                            anchorStyle = `
+                position: fixed;
+                top: ${stickyOffsetTop}px;
+                z-index: ${zIndex};
+                color: ${highlightColor};
+              `;
+                        }
+                        this.setDiffData({
+                            target: item,
+                            data: {
+                                active: true,
+                                anchorStyle,
+                                wrapperStyle,
+                            },
+                        });
+                    }
+                    else if (index === active - 1) {
+                        const currentAnchor = children[index];
+                        const currentOffsetTop = currentAnchor.top;
+                        const targetOffsetTop = index === children.length - 1
+                            ? this.top
+                            : children[index + 1].top;
+                        const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
+                        const translateY = parentOffsetHeight - currentAnchor.height;
+                        const anchorStyle = `
+              position: relative;
+              transform: translate3d(0, ${translateY}px, 0);
+              z-index: ${zIndex};
+              color: ${highlightColor};
+            `;
+                        this.setDiffData({
+                            target: item,
+                            data: {
+                                active: true,
+                                anchorStyle,
+                            },
+                        });
+                    }
+                    else {
+                        this.setDiffData({
+                            target: item,
+                            data: {
+                                active: false,
+                                anchorStyle: '',
+                                wrapperStyle: '',
+                            },
+                        });
+                    }
+                });
+            }
+        },
+        onClick(event) {
+            this.scrollToAnchor(event.target.dataset.index);
+        },
+        onTouchMove(event) {
+            const sidebarLength = this.children.length;
+            const touch = event.touches[0];
+            const itemHeight = this.sidebar.height / sidebarLength;
+            let index = Math.floor((touch.clientY - this.sidebar.top) / itemHeight);
+            if (index < 0) {
+                index = 0;
+            }
+            else if (index > sidebarLength - 1) {
+                index = sidebarLength - 1;
+            }
+            this.scrollToAnchor(index);
+        },
+        onTouchStop() {
+            this.scrollToAnchorIndex = null;
+        },
+        scrollToAnchor(index) {
+            if (typeof index !== 'number' || this.scrollToAnchorIndex === index) {
+                return;
+            }
+            this.scrollToAnchorIndex = index;
+            const anchor = this.children.find((item) => item.data.index === this.data.indexList[index]);
+            if (anchor) {
+                anchor.scrollIntoView(this.scrollTop);
+                this.$emit('select', anchor.data.index);
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/index-bar/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-index-bar{position:relative}.van-index-bar__sidebar{display:flex;flex-direction:column;position:fixed;right:0;text-align:center;top:50%;transform:translateY(-50%);-webkit-user-select:none;user-select:none}.van-index-bar__index{font-size:var(--index-bar-index-font-size,10px);font-weight:500;line-height:var(--index-bar-index-line-height,14px);padding:0 var(--padding-base,4px) 0 var(--padding-md,16px)}
+</style>

+ 20 - 0
src/wxcomponents/vant/info/index.vue

@@ -0,0 +1,20 @@
+<template>
+<uni-shadow-root class="vant-info-index"><view v-if="info !== null && info !== '' || dot" :class="'van-info '+(utils.bem('info', { dot }))+' custom-class'" :style="customStyle">{{ dot ? '' : info }}</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/info/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        dot: Boolean,
+        info: null,
+        customStyle: String,
+    },
+});
+export default global['__wxComponents']['vant/info/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-info{align-items:center;background-color:var(--info-background-color,#ee0a24);border:var(--info-border-width,1px) solid #fff;border-radius:var(--info-size,16px);box-sizing:border-box;color:var(--info-color,#fff);display:inline-flex;font-family:var(--info-font-family,-apple-system-font,Helvetica Neue,Arial,sans-serif);font-size:var(--info-font-size,12px);font-weight:var(--info-font-weight,500);height:var(--info-size,16px);justify-content:center;min-width:var(--info-size,16px);padding:var(--info-padding,0 3px);position:absolute;right:0;top:0;transform:translate(50%,-50%);transform-origin:100%;white-space:nowrap}.van-info--dot{background-color:var(--info-dot-color,#ee0a24);border-radius:100%;height:var(--info-dot-size,8px);min-width:0;width:var(--info-dot-size,8px)}
+</style>

File diff suppressed because it is too large
+ 33 - 0
src/wxcomponents/vant/loading/index.vue


+ 99 - 0
src/wxcomponents/vant/nav-bar/index.vue

@@ -0,0 +1,99 @@
+<template>
+<uni-shadow-root class="vant-nav-bar-index"><view v-if="fixed && placeholder" :style="'height: '+(height)+'px;'"></view>
+
+<view :class="(utils.bem('nav-bar', { fixed }))+' custom-class '+(border ? 'van-hairline--bottom' : '')" :style="(computed.barStyle({ zIndex, statusBarHeight, safeAreaInsetTop }))+'; '+(customStyle)">
+  <view class="van-nav-bar__content">
+    <view class="van-nav-bar__left" @click="onClickLeft">
+      <block v-if="leftArrow || leftText">
+        <van-icon v-if="leftArrow" size="16px" name="arrow-left" custom-class="van-nav-bar__arrow"></van-icon>
+        <view v-if="leftText" class="van-nav-bar__text" hover-class="van-nav-bar__text--hover" hover-stay-time="70">{{ leftText }}</view>
+      </block>
+      <slot v-else name="left"></slot>
+    </view>
+    <view class="van-nav-bar__title title-class van-ellipsis">
+      <block v-if="title">{{ title }}</block>
+      <slot v-else name="title"></slot>
+    </view>
+    <view class="van-nav-bar__right" @click="onClickRight">
+      <view v-if="rightText" class="van-nav-bar__text" hover-class="van-nav-bar__text--hover" hover-stay-time="70">{{ rightText }}</view>
+      <slot v-else name="right"></slot>
+    </view>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/nav-bar/index'
+import { VantComponent } from '../common/component';
+import { getRect, getSystemInfoSync } from '../common/utils';
+VantComponent({
+    classes: ['title-class'],
+    props: {
+        title: String,
+        fixed: {
+            type: Boolean,
+            observer: 'setHeight',
+        },
+        placeholder: {
+            type: Boolean,
+            observer: 'setHeight',
+        },
+        leftText: String,
+        rightText: String,
+        customStyle: String,
+        leftArrow: Boolean,
+        border: {
+            type: Boolean,
+            value: true,
+        },
+        zIndex: {
+            type: Number,
+            value: 1,
+        },
+        safeAreaInsetTop: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    data: {
+        height: 46,
+    },
+    created() {
+        const { statusBarHeight } = getSystemInfoSync();
+        this.setData({
+            statusBarHeight,
+            height: 46 + statusBarHeight,
+        });
+    },
+    mounted() {
+        this.setHeight();
+    },
+    methods: {
+        onClickLeft() {
+            this.$emit('click-left');
+        },
+        onClickRight() {
+            this.$emit('click-right');
+        },
+        setHeight() {
+            if (!this.data.fixed || !this.data.placeholder) {
+                return;
+            }
+            wx.nextTick(() => {
+                getRect(this, '.van-nav-bar').then((res) => {
+                    if (res && 'height' in res) {
+                        this.setData({ height: res.height });
+                    }
+                });
+            });
+        },
+    },
+});
+export default global['__wxComponents']['vant/nav-bar/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-nav-bar{background-color:var(--nav-bar-background-color,#fff);height:var(--nav-bar-height,46px);line-height:var(--nav-bar-height,46px);position:relative;text-align:center;-webkit-user-select:none;user-select:none}.van-nav-bar__content{height:100%;position:relative}.van-nav-bar__text{color:var(--nav-bar-text-color,#1989fa);display:inline-block;margin:0 calc(var(--padding-md, 16px)*-1);padding:0 var(--padding-md,16px);vertical-align:middle}.van-nav-bar__text--hover{background-color:#f2f3f5}.van-nav-bar__arrow{color:var(--nav-bar-icon-color,#1989fa)!important;font-size:var(--nav-bar-arrow-size,16px)!important;vertical-align:middle}.van-nav-bar__arrow+.van-nav-bar__text{margin-left:-20px;padding-left:25px}.van-nav-bar--fixed{left:0;position:fixed;top:0;width:100%}.van-nav-bar__title{color:var(--nav-bar-title-text-color,#323233);font-size:var(--nav-bar-title-font-size,16px);font-weight:var(--font-weight-bold,500);margin:0 auto;max-width:60%}.van-nav-bar__left,.van-nav-bar__right{align-items:center;bottom:0;display:flex;font-size:var(--font-size-md,14px);position:absolute;top:0}.van-nav-bar__left{left:var(--padding-md,16px)}.van-nav-bar__right{right:var(--padding-md,16px)}
+</style>

+ 150 - 0
src/wxcomponents/vant/notice-bar/index.vue

@@ -0,0 +1,150 @@
+<template>
+<uni-shadow-root class="vant-notice-bar-index"><view v-if="show" :class="'custom-class '+(utils.bem('notice-bar', { withicon: mode, wrapable }))" :style="computed.rootStyle({ color, backgroundColor, background })" @click="onClick">
+  <van-icon v-if="leftIcon" :name="leftIcon" class="van-notice-bar__left-icon"></van-icon>
+  <slot v-else name="left-icon"></slot>
+
+  <view class="van-notice-bar__wrap">
+    <view :class="'van-notice-bar__content '+(scrollable === false && !wrapable ? 'van-ellipsis' : '')" :animation="animationData">
+      {{ text }}
+      <slot v-if="(!text)"></slot>
+    </view>
+  </view>
+
+  <van-icon v-if="mode === 'closeable'" class="van-notice-bar__right-icon" name="cross" @click.native.stop.prevent="onClickIcon"></van-icon>
+  <navigator v-else-if="mode === 'link'" :url="url" :open-type="openType">
+    <van-icon class="van-notice-bar__right-icon" name="arrow"></van-icon>
+  </navigator>
+  <slot v-else name="right-icon"></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/notice-bar/index'
+import { VantComponent } from '../common/component';
+import { getRect, requestAnimationFrame } from '../common/utils';
+VantComponent({
+    props: {
+        text: {
+            type: String,
+            value: '',
+            observer: 'init',
+        },
+        mode: {
+            type: String,
+            value: '',
+        },
+        url: {
+            type: String,
+            value: '',
+        },
+        openType: {
+            type: String,
+            value: 'navigate',
+        },
+        delay: {
+            type: Number,
+            value: 1,
+        },
+        speed: {
+            type: Number,
+            value: 60,
+            observer: 'init',
+        },
+        scrollable: null,
+        leftIcon: {
+            type: String,
+            value: '',
+        },
+        color: String,
+        backgroundColor: String,
+        background: String,
+        wrapable: Boolean,
+    },
+    data: {
+        show: true,
+    },
+    created() {
+        this.resetAnimation = wx.createAnimation({
+            duration: 0,
+            timingFunction: 'linear',
+        });
+    },
+    destroyed() {
+        this.timer && clearTimeout(this.timer);
+    },
+    mounted() {
+        this.init();
+    },
+    methods: {
+        init() {
+            requestAnimationFrame(() => {
+                Promise.all([
+                    getRect(this, '.van-notice-bar__content'),
+                    getRect(this, '.van-notice-bar__wrap'),
+                ]).then((rects) => {
+                    const [contentRect, wrapRect] = rects;
+                    const { speed, scrollable, delay } = this.data;
+                    if (contentRect == null ||
+                        wrapRect == null ||
+                        !contentRect.width ||
+                        !wrapRect.width ||
+                        scrollable === false) {
+                        return;
+                    }
+                    if (scrollable || wrapRect.width < contentRect.width) {
+                        const duration = ((wrapRect.width + contentRect.width) / speed) * 1000;
+                        this.wrapWidth = wrapRect.width;
+                        this.contentWidth = contentRect.width;
+                        this.duration = duration;
+                        this.animation = wx.createAnimation({
+                            duration,
+                            timingFunction: 'linear',
+                            delay,
+                        });
+                        this.scroll(true);
+                    }
+                });
+            });
+        },
+        scroll(isInit = false) {
+            this.timer && clearTimeout(this.timer);
+            this.timer = null;
+            this.setData({
+                animationData: this.resetAnimation
+                    .translateX(isInit ? 0 : this.wrapWidth)
+                    .step()
+                    .export(),
+            });
+            requestAnimationFrame(() => {
+                this.setData({
+                    animationData: this.animation
+                        .translateX(-this.contentWidth)
+                        .step()
+                        .export(),
+                });
+            });
+            this.timer = setTimeout(() => {
+                this.scroll();
+            }, this.duration);
+        },
+        onClickIcon(event) {
+            if (this.data.mode === 'closeable') {
+                this.timer && clearTimeout(this.timer);
+                this.timer = null;
+                this.setData({ show: false });
+                this.$emit('close', event.detail);
+            }
+        },
+        onClick(event) {
+            this.$emit('click', event);
+        },
+    },
+});
+export default global['__wxComponents']['vant/notice-bar/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-notice-bar{align-items:center;background-color:var(--notice-bar-background-color,#fffbe8);color:var(--notice-bar-text-color,#ed6a0c);display:flex;font-size:var(--notice-bar-font-size,14px);height:var(--notice-bar-height,40px);line-height:var(--notice-bar-line-height,24px);padding:var(--notice-bar-padding,0 16px)}.van-notice-bar--withicon{padding-right:40px;position:relative}.van-notice-bar--wrapable{height:auto;padding:var(--notice-bar-wrapable-padding,8px 16px)}.van-notice-bar--wrapable .van-notice-bar__wrap{height:auto}.van-notice-bar--wrapable .van-notice-bar__content{position:relative;white-space:normal}.van-notice-bar__left-icon{align-items:center;display:flex;margin-right:4px;vertical-align:middle}.van-notice-bar__left-icon,.van-notice-bar__right-icon{font-size:var(--notice-bar-icon-size,16px);min-width:var(--notice-bar-icon-min-width,22px)}.van-notice-bar__right-icon{position:absolute;right:15px;top:10px}.van-notice-bar__wrap{flex:1;height:var(--notice-bar-line-height,24px);overflow:hidden;position:relative}.van-notice-bar__content{position:absolute;white-space:nowrap}.van-notice-bar__content.van-ellipsis{max-width:100%}
+</style>

+ 84 - 0
src/wxcomponents/vant/notify/index.vue

@@ -0,0 +1,84 @@
+<template>
+<uni-shadow-root class="vant-notify-index"><van-transition name="slide-down" :show="show" custom-class="van-notify__container" :custom-style="computed.rootStyle({ zIndex, top })" @click.native="onTap">
+  <view :class="'van-notify van-notify--'+(type)" :style="computed.notifyStyle({ background, color })">
+    <view v-if="safeAreaInsetTop" :style="'height: '+(statusBarHeight)+'px'"></view>
+    <text>{{ message }}</text>
+  </view>
+</van-transition></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanTransition from '../transition/index.vue'
+global['__wxVueOptions'] = {components:{'van-transition': VanTransition}}
+
+global['__wxRoute'] = 'vant/notify/index'
+import { VantComponent } from '../common/component';
+import { WHITE } from '../common/color';
+import { getSystemInfoSync } from '../common/utils';
+VantComponent({
+    props: {
+        message: String,
+        background: String,
+        type: {
+            type: String,
+            value: 'danger',
+        },
+        color: {
+            type: String,
+            value: WHITE,
+        },
+        duration: {
+            type: Number,
+            value: 3000,
+        },
+        zIndex: {
+            type: Number,
+            value: 110,
+        },
+        safeAreaInsetTop: {
+            type: Boolean,
+            value: false,
+        },
+        top: null,
+    },
+    data: {
+        show: false,
+        onOpened: null,
+        onClose: null,
+        onClick: null,
+    },
+    created() {
+        const { statusBarHeight } = getSystemInfoSync();
+        this.setData({ statusBarHeight });
+    },
+    methods: {
+        showNotify() {
+            const { duration, onOpened } = this.data;
+            clearTimeout(this.timer);
+            this.setData({ show: true });
+            wx.nextTick(onOpened);
+            if (duration > 0 && duration !== Infinity) {
+                this.timer = setTimeout(() => {
+                    this.hide();
+                }, duration);
+            }
+        },
+        hide() {
+            const { onClose } = this.data;
+            clearTimeout(this.timer);
+            this.setData({ show: false });
+            wx.nextTick(onClose);
+        },
+        onTap(event) {
+            const { onClick } = this.data;
+            if (onClick) {
+                onClick(event.detail);
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/notify/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-notify{word-wrap:break-word;font-size:var(--notify-font-size,14px);line-height:var(--notify-line-height,20px);padding:var(--notify-padding,6px 15px);text-align:center}.van-notify__container{box-sizing:border-box;left:0;position:fixed;top:0;width:100%}.van-notify--primary{background-color:var(--notify-primary-background-color,#1989fa)}.van-notify--success{background-color:var(--notify-success-background-color,#07c160)}.van-notify--danger{background-color:var(--notify-danger-background-color,#ee0a24)}.van-notify--warning{background-color:var(--notify-warning-background-color,#ff976a)}
+</style>

+ 1 - 1
src/wxcomponents/vant/notify/notify.js

@@ -31,7 +31,7 @@ export default function Notify(options) {
     delete options.selector;
     if (notify) {
         notify.setData(options);
-        notify.show();
+        notify.showNotify();
         return notify;
     }
     console.warn('未找到 van-notify 节点,请确认 selector 及 context 是否正确');

+ 45 - 0
src/wxcomponents/vant/overlay/index.vue

@@ -0,0 +1,45 @@
+<template>
+<uni-shadow-root class="vant-overlay-index"><van-transition v-if="lockScroll" :show="show" custom-class="van-overlay" :custom-style="'z-index: '+(zIndex)+'; '+(customStyle)" :duration="duration" @click.native="onClick" @touchmove.native.stop.prevent="noop">
+  <slot></slot>
+</van-transition>
+<van-transition v-else :show="show" custom-class="van-overlay" :custom-style="'z-index: '+(zIndex)+'; '+(customStyle)" :duration="duration" @click.native="onClick">
+  <slot></slot>
+</van-transition></uni-shadow-root>
+</template>
+
+<script>
+import VanTransition from '../transition/index.vue'
+global['__wxVueOptions'] = {components:{'van-transition': VanTransition}}
+
+global['__wxRoute'] = 'vant/overlay/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        show: Boolean,
+        customStyle: String,
+        duration: {
+            type: null,
+            value: 300,
+        },
+        zIndex: {
+            type: Number,
+            value: 1,
+        },
+        lockScroll: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    methods: {
+        onClick() {
+            this.$emit('click');
+        },
+        // for prevent touchmove
+        noop() { },
+    },
+});
+export default global['__wxComponents']['vant/overlay/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-overlay{background-color:var(--overlay-background-color,rgba(0,0,0,.7));height:100%;left:0;position:fixed;top:0;width:100%}
+</style>

+ 34 - 0
src/wxcomponents/vant/panel/index.vue

@@ -0,0 +1,34 @@
+<template>
+<uni-shadow-root class="vant-panel-index"><view class="van-panel van-hairline--top-bottom custom-class">
+  <van-cell v-if="title || desc || status" :title="title" :label="desc" :value="status" custom-class="header-class" value-class="van-panel__header-value"></van-cell>
+  <slot v-else name="header"></slot>
+
+  <view class="van-panel__content">
+    <slot></slot>
+  </view>
+
+  <view class="van-panel__footer van-hairline--top footer-class">
+    <slot name="footer"></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+import VanCell from '../cell/index.vue'
+global['__wxVueOptions'] = {components:{'van-cell': VanCell}}
+
+global['__wxRoute'] = 'vant/panel/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: ['header-class', 'footer-class'],
+    props: {
+        desc: String,
+        title: String,
+        status: String,
+    },
+});
+export default global['__wxComponents']['vant/panel/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-panel{background:var(--panel-background-color,#fff)}.van-panel__header-value{color:var(--panel-header-value-color,#ee0a24)}.van-panel__footer{padding:var(--panel-footer-padding,8px 16px)}.van-panel__footer:empty{display:none}
+</style>

+ 134 - 0
src/wxcomponents/vant/picker-column/index.vue

@@ -0,0 +1,134 @@
+<template>
+<uni-shadow-root class="vant-picker-column-index"><view class="van-picker-column custom-class" :style="computed.rootStyle({ itemHeight, visibleItemCount })" @touchstart="onTouchStart" @touchmove.stop.prevent="onTouchMove" @touchend="onTouchEnd" @touchcancel="onTouchEnd">
+  <view :style="computed.wrapperStyle({ offset, itemHeight, visibleItemCount, duration })">
+    <view v-for="(option,index) in (options)" :key="option.index" :data-index="index" :style="'height: '+(itemHeight)+'px'" :class="'van-ellipsis '+(utils.bem('picker-column__item', { disabled: option && option.disabled, selected: index === currentIndex }))+' '+(index === currentIndex ? 'active-class' : '')" @click="onClickItem">{{ computed.optionText(option, valueKey) }}</view>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/picker-column/index'
+import { VantComponent } from '../common/component';
+import { range } from '../common/utils';
+import { isObj } from '../common/validator';
+const DEFAULT_DURATION = 200;
+VantComponent({
+    classes: ['active-class'],
+    props: {
+        valueKey: String,
+        className: String,
+        itemHeight: Number,
+        visibleItemCount: Number,
+        initialOptions: {
+            type: Array,
+            value: [],
+        },
+        defaultIndex: {
+            type: Number,
+            value: 0,
+            observer(value) {
+                this.setIndex(value);
+            },
+        },
+    },
+    data: {
+        startY: 0,
+        offset: 0,
+        duration: 0,
+        startOffset: 0,
+        options: [],
+        currentIndex: 0,
+    },
+    created() {
+        const { defaultIndex, initialOptions } = this.data;
+        this.set({
+            currentIndex: defaultIndex,
+            options: initialOptions,
+        }).then(() => {
+            this.setIndex(defaultIndex);
+        });
+    },
+    methods: {
+        getCount() {
+            return this.data.options.length;
+        },
+        onTouchStart(event) {
+            this.setData({
+                startY: event.touches[0].clientY,
+                startOffset: this.data.offset,
+                duration: 0,
+            });
+        },
+        onTouchMove(event) {
+            const { data } = this;
+            const deltaY = event.touches[0].clientY - data.startY;
+            this.setData({
+                offset: range(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight),
+            });
+        },
+        onTouchEnd() {
+            const { data } = this;
+            if (data.offset !== data.startOffset) {
+                this.setData({ duration: DEFAULT_DURATION });
+                const index = range(Math.round(-data.offset / data.itemHeight), 0, this.getCount() - 1);
+                this.setIndex(index, true);
+            }
+        },
+        onClickItem(event) {
+            const { index } = event.currentTarget.dataset;
+            this.setIndex(index, true);
+        },
+        adjustIndex(index) {
+            const { data } = this;
+            const count = this.getCount();
+            index = range(index, 0, count);
+            for (let i = index; i < count; i++) {
+                if (!this.isDisabled(data.options[i]))
+                    return i;
+            }
+            for (let i = index - 1; i >= 0; i--) {
+                if (!this.isDisabled(data.options[i]))
+                    return i;
+            }
+        },
+        isDisabled(option) {
+            return isObj(option) && option.disabled;
+        },
+        getOptionText(option) {
+            const { data } = this;
+            return isObj(option) && data.valueKey in option
+                ? option[data.valueKey]
+                : option;
+        },
+        setIndex(index, userAction) {
+            const { data } = this;
+            index = this.adjustIndex(index) || 0;
+            const offset = -index * data.itemHeight;
+            if (index !== data.currentIndex) {
+                return this.set({ offset, currentIndex: index }).then(() => {
+                    userAction && this.$emit('change', index);
+                });
+            }
+            return this.set({ offset });
+        },
+        setValue(value) {
+            const { options } = this.data;
+            for (let i = 0; i < options.length; i++) {
+                if (this.getOptionText(options[i]) === value) {
+                    return this.setIndex(i);
+                }
+            }
+            return Promise.resolve();
+        },
+        getValue() {
+            const { data } = this;
+            return data.options[data.currentIndex];
+        },
+    },
+});
+export default global['__wxComponents']['vant/picker-column/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-picker-column{color:var(--picker-option-text-color,#000);font-size:var(--picker-option-font-size,16px);overflow:hidden;text-align:center}.van-picker-column__item{padding:0 5px}.van-picker-column__item--selected{color:var(--picker-option-selected-text-color,#323233);font-weight:var(--font-weight-bold,500)}.van-picker-column__item--disabled{opacity:var(--picker-option-disabled-opacity,.3)}
+</style>

+ 165 - 0
src/wxcomponents/vant/picker/index.vue

@@ -0,0 +1,165 @@
+<template>
+<uni-shadow-root class="vant-picker-index"><view class="van-picker custom-class">
+  <include v-if="toolbarPosition === 'top'" src="./toolbar.wxml"></include>
+
+  <view v-if="loading" class="van-picker__loading">
+    <loading color="#1989fa"></loading>
+  </view>
+
+  <view class="van-picker__columns" :style="computed.columnsStyle({ itemHeight, visibleItemCount })" @touchmove.stop.prevent="noop">
+    <picker-column v-for="(item,index) in (computed.columns(columns))" :key="item.index" class="van-picker__column" :data-index="index" custom-class="column-class" :value-key="valueKey" :initial-options="item.values" :default-index="item.defaultIndex || defaultIndex" :item-height="itemHeight" :visible-item-count="visibleItemCount" active-class="active-class" @change="onChange"></picker-column>
+    <view class="van-picker__mask" :style="computed.maskStyle({ itemHeight, visibleItemCount })"></view>
+    <view class="van-picker__frame van-hairline--top-bottom" :style="computed.frameStyle({ itemHeight })"></view>
+  </view>
+
+  <include v-if="toolbarPosition === 'bottom'" src="./toolbar.wxml"></include>
+</view></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import PickerColumn from '../picker-column/index.vue'
+import Loading from '../loading/index.vue'
+global['__wxVueOptions'] = {components:{'picker-column': PickerColumn,'loading': Loading}}
+
+global['__wxRoute'] = 'vant/picker/index'
+import { VantComponent } from '../common/component';
+import { pickerProps } from './shared';
+VantComponent({
+    classes: ['active-class', 'toolbar-class', 'column-class'],
+    props: Object.assign(Object.assign({}, pickerProps), { valueKey: {
+            type: String,
+            value: 'text',
+        }, toolbarPosition: {
+            type: String,
+            value: 'top',
+        }, defaultIndex: {
+            type: Number,
+            value: 0,
+        }, columns: {
+            type: Array,
+            value: [],
+            observer(columns = []) {
+                this.simple = columns.length && !columns[0].values;
+                if (Array.isArray(this.children) && this.children.length) {
+                    this.setColumns().catch(() => { });
+                }
+            },
+        } }),
+    beforeCreate() {
+        Object.defineProperty(this, 'children', {
+            get: () => this.selectAllComponents('.van-picker__column') || [],
+        });
+    },
+    methods: {
+        noop() { },
+        setColumns() {
+            const { data } = this;
+            const columns = this.simple ? [{ values: data.columns }] : data.columns;
+            const stack = columns.map((column, index) => this.setColumnValues(index, column.values));
+            return Promise.all(stack);
+        },
+        emit(event) {
+            const { type } = event.currentTarget.dataset;
+            if (this.simple) {
+                this.$emit(type, {
+                    value: this.getColumnValue(0),
+                    index: this.getColumnIndex(0),
+                });
+            }
+            else {
+                this.$emit(type, {
+                    value: this.getValues(),
+                    index: this.getIndexes(),
+                });
+            }
+        },
+        onChange(event) {
+            if (this.simple) {
+                this.$emit('change', {
+                    picker: this,
+                    value: this.getColumnValue(0),
+                    index: this.getColumnIndex(0),
+                });
+            }
+            else {
+                this.$emit('change', {
+                    picker: this,
+                    value: this.getValues(),
+                    index: event.currentTarget.dataset.index,
+                });
+            }
+        },
+        // get column instance by index
+        getColumn(index) {
+            return this.children[index];
+        },
+        // get column value by index
+        getColumnValue(index) {
+            const column = this.getColumn(index);
+            return column && column.getValue();
+        },
+        // set column value by index
+        setColumnValue(index, value) {
+            const column = this.getColumn(index);
+            if (column == null) {
+                return Promise.reject(new Error('setColumnValue: 对应列不存在'));
+            }
+            return column.setValue(value);
+        },
+        // get column option index by column index
+        getColumnIndex(columnIndex) {
+            return (this.getColumn(columnIndex) || {}).data.currentIndex;
+        },
+        // set column option index by column index
+        setColumnIndex(columnIndex, optionIndex) {
+            const column = this.getColumn(columnIndex);
+            if (column == null) {
+                return Promise.reject(new Error('setColumnIndex: 对应列不存在'));
+            }
+            return column.setIndex(optionIndex);
+        },
+        // get options of column by index
+        getColumnValues(index) {
+            return (this.children[index] || {}).data.options;
+        },
+        // set options of column by index
+        setColumnValues(index, options, needReset = true) {
+            const column = this.children[index];
+            if (column == null) {
+                return Promise.reject(new Error('setColumnValues: 对应列不存在'));
+            }
+            const isSame = JSON.stringify(column.data.options) === JSON.stringify(options);
+            if (isSame) {
+                return Promise.resolve();
+            }
+            return column.set({ options }).then(() => {
+                if (needReset) {
+                    column.setIndex(0);
+                }
+            });
+        },
+        // get values of all columns
+        getValues() {
+            return this.children.map((child) => child.getValue());
+        },
+        // set values of all columns
+        setValues(values) {
+            const stack = values.map((value, index) => this.setColumnValue(index, value));
+            return Promise.all(stack);
+        },
+        // get indexes of all columns
+        getIndexes() {
+            return this.children.map((child) => child.data.currentIndex);
+        },
+        // set indexes of all columns
+        setIndexes(indexes) {
+            const stack = indexes.map((optionIndex, columnIndex) => this.setColumnIndex(columnIndex, optionIndex));
+            return Promise.all(stack);
+        },
+    },
+});
+export default global['__wxComponents']['vant/picker/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-picker{-webkit-text-size-adjust:100%;background-color:var(--picker-background-color,#fff);overflow:hidden;position:relative;-webkit-user-select:none;user-select:none}.van-picker__toolbar{display:flex;height:var(--picker-toolbar-height,44px);justify-content:space-between;line-height:var(--picker-toolbar-height,44px)}.van-picker__cancel,.van-picker__confirm{font-size:var(--picker-action-font-size,14px);padding:var(--picker-action-padding,0 16px)}.van-picker__cancel--hover,.van-picker__confirm--hover{opacity:.7}.van-picker__confirm{color:var(--picker-confirm-action-color,#576b95)}.van-picker__cancel{color:var(--picker-cancel-action-color,#969799)}.van-picker__title{font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);max-width:50%;text-align:center}.van-picker__columns{display:flex;position:relative}.van-picker__column{flex:1 1;width:0}.van-picker__loading{align-items:center;background-color:var(--picker-loading-mask-color,hsla(0,0%,100%,.9));bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0;z-index:4}.van-picker__mask{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-image:linear-gradient(180deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4)),linear-gradient(0deg,hsla(0,0%,100%,.9),hsla(0,0%,100%,.4));background-position:top,bottom;background-repeat:no-repeat;height:100%;left:0;top:0;width:100%;z-index:2}.van-picker__frame,.van-picker__mask{pointer-events:none;position:absolute}.van-picker__frame{left:16px;right:16px;top:50%;transform:translateY(-50%);z-index:1}
+</style>

+ 25 - 0
src/wxcomponents/vant/picker/toolbar.vue

@@ -0,0 +1,25 @@
+<template>
+<uni-shadow-root class="vant-picker-toolbar"><view v-if="showToolbar" class="van-picker__toolbar toolbar-class">
+  <view class="van-picker__cancel" hover-class="van-picker__cancel--hover" hover-stay-time="70" data-type="cancel" @click="emit">
+    {{ cancelButtonText }}
+  </view>
+  <view v-if="title" class="van-picker__title van-ellipsis">{{
+    title
+  }}</view>
+  <view class="van-picker__confirm" hover-class="van-picker__confirm--hover" hover-stay-time="70" data-type="confirm" @click="emit">
+    {{ confirmButtonText }}
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/picker/toolbar'
+
+Component({})
+
+export default global['__wxComponents']['vant/picker/toolbar']
+</script>
+<style platform="mp-weixin">
+
+</style>

File diff suppressed because it is too large
+ 106 - 0
src/wxcomponents/vant/popup/index.vue


+ 69 - 0
src/wxcomponents/vant/progress/index.vue

@@ -0,0 +1,69 @@
+<template>
+<uni-shadow-root class="vant-progress-index"><view class="van-progress custom-class" :style="computed.rootStyle({ strokeWidth, trackColor })">
+  <view class="van-progress__portion" :style="computed.portionStyle({ percentage, inactive, color })">
+    <view v-if="showPivot && computed.pivotText(pivotText, percentage)" :style="computed.pivotStyle({ textColor, pivotColor, inactive, color, right })" class="van-progress__pivot">
+      {{ computed.pivotText(pivotText, percentage) }}
+    </view>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/progress/index'
+import { VantComponent } from '../common/component';
+import { BLUE } from '../common/color';
+import { getRect } from '../common/utils';
+VantComponent({
+    props: {
+        inactive: Boolean,
+        percentage: {
+            type: Number,
+            observer: 'setLeft',
+        },
+        pivotText: String,
+        pivotColor: String,
+        trackColor: String,
+        showPivot: {
+            type: Boolean,
+            value: true,
+        },
+        color: {
+            type: String,
+            value: BLUE,
+        },
+        textColor: {
+            type: String,
+            value: '#fff',
+        },
+        strokeWidth: {
+            type: null,
+            value: 4,
+        },
+    },
+    data: {
+        right: 0,
+    },
+    mounted() {
+        this.setLeft();
+    },
+    methods: {
+        setLeft() {
+            Promise.all([
+                getRect(this, '.van-progress'),
+                getRect(this, '.van-progress__pivot'),
+            ]).then(([portion, pivot]) => {
+                if (portion && pivot) {
+                    this.setData({
+                        right: (pivot.width * (this.data.percentage - 100)) / 100,
+                    });
+                }
+            });
+        },
+    },
+});
+export default global['__wxComponents']['vant/progress/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-progress{background:var(--progress-background-color,#ebedf0);border-radius:var(--progress-height,4px);height:var(--progress-height,4px);position:relative}.van-progress__portion{background:var(--progress-color,#1989fa);border-radius:inherit;height:100%;left:0;position:absolute}.van-progress__pivot{background-color:var(--progress-pivot-background-color,#1989fa);border-radius:1em;box-sizing:border-box;color:var(--progress-pivot-text-color,#fff);font-size:var(--progress-pivot-font-size,10px);line-height:var(--progress-pivot-line-height,1.6);min-width:3.6em;padding:var(--progress-pivot-padding,0 5px);position:absolute;text-align:center;top:50%;transform:translateY(-50%);word-break:keep-all}
+</style>

+ 36 - 0
src/wxcomponents/vant/radio-group/index.vue

@@ -0,0 +1,36 @@
+<template>
+<uni-shadow-root class="vant-radio-group-index"><view :class="utils.bem('radio-group', [direction])">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/radio-group/index'
+import { VantComponent } from '../common/component';
+import { useChildren } from '../common/relation';
+VantComponent({
+    field: true,
+    relation: useChildren('radio'),
+    props: {
+        value: {
+            type: null,
+            observer: 'updateChildren',
+        },
+        direction: String,
+        disabled: {
+            type: Boolean,
+            observer: 'updateChildren',
+        },
+    },
+    methods: {
+        updateChildren() {
+            this.children.forEach((child) => child.updateFromParent());
+        },
+    },
+});
+export default global['__wxComponents']['vant/radio-group/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-radio-group--horizontal{display:flex;flex-wrap:wrap}
+</style>

+ 91 - 0
src/wxcomponents/vant/radio/index.vue

@@ -0,0 +1,91 @@
+<template>
+<uni-shadow-root class="vant-radio-index"><view :class="(utils.bem('radio', [direction]))+' custom-class'">
+  <view v-if="labelPosition === 'left'" :class="(utils.bem('radio__label', [labelPosition, { disabled: disabled || parentDisabled }]))+' label-class'" @click="onClickLabel">
+    <slot></slot>
+  </view>
+  <view class="van-radio__icon-wrap" :style="'font-size: '+(utils.addUnit(iconSize))" @click="onChange">
+    <slot v-if="useIconSlot" name="icon"></slot>
+    <van-icon v-else name="success" :class="utils.bem('radio__icon', [shape, { disabled: disabled || parentDisabled, checked: value === name }])" :style="computed.iconStyle({ iconSize, checkedColor, disabled, parentDisabled, value, name })" custom-class="icon-class" :custom-style="computed.iconCustomStyle({ iconSize })"></van-icon>
+  </view>
+  <view v-if="labelPosition === 'right'" :class="'label-class '+(utils.bem('radio__label', [labelPosition, { disabled: disabled || parentDisabled }]))" @click="onClickLabel">
+    <slot></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/radio/index'
+import { canIUseModel } from '../common/version';
+import { VantComponent } from '../common/component';
+import { useParent } from '../common/relation';
+VantComponent({
+    field: true,
+    relation: useParent('radio-group', function () {
+        this.updateFromParent();
+    }),
+    classes: ['icon-class', 'label-class'],
+    props: {
+        name: null,
+        value: null,
+        disabled: Boolean,
+        useIconSlot: Boolean,
+        checkedColor: String,
+        labelPosition: {
+            type: String,
+            value: 'right',
+        },
+        labelDisabled: Boolean,
+        shape: {
+            type: String,
+            value: 'round',
+        },
+        iconSize: {
+            type: null,
+            value: 20,
+        },
+    },
+    data: {
+        direction: '',
+        parentDisabled: false,
+    },
+    methods: {
+        updateFromParent() {
+            if (!this.parent) {
+                return;
+            }
+            const { value, disabled: parentDisabled, direction } = this.parent.data;
+            this.setData({
+                value,
+                direction,
+                parentDisabled,
+            });
+        },
+        emitChange(value) {
+            const instance = this.parent || this;
+            instance.$emit('input', value);
+            instance.$emit('change', value);
+            if (canIUseModel()) {
+                instance.setData({ value });
+            }
+        },
+        onChange() {
+            if (!this.data.disabled && !this.data.parentDisabled) {
+                this.emitChange(this.data.name);
+            }
+        },
+        onClickLabel() {
+            const { disabled, parentDisabled, labelDisabled, name } = this.data;
+            if (!(disabled || parentDisabled) && !labelDisabled) {
+                this.emitChange(name);
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/radio/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-radio{align-items:center;display:flex;overflow:hidden;-webkit-user-select:none;user-select:none}.van-radio__icon-wrap{flex:none}.van-radio--horizontal{margin-right:var(--padding-sm,12px)}.van-radio__icon{align-items:center;border:1px solid var(--radio-border-color,#c8c9cc);box-sizing:border-box;color:transparent;display:flex;font-size:var(--radio-size,20px);height:1em;justify-content:center;text-align:center;transition-duration:var(--radio-transition-duration,.2s);transition-property:color,border-color,background-color;width:1em}.van-radio__icon--round{border-radius:100%}.van-radio__icon--checked{background-color:var(--radio-checked-icon-color,#1989fa);border-color:var(--radio-checked-icon-color,#1989fa);color:#fff}.van-radio__icon--disabled{background-color:var(--radio-disabled-background-color,#ebedf0);border-color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__icon--disabled.van-radio__icon--checked{color:var(--radio-disabled-icon-color,#c8c9cc)}.van-radio__label{word-wrap:break-word;color:var(--radio-label-color,#323233);line-height:var(--radio-size,20px);padding-left:var(--radio-label-margin,10px)}.van-radio__label--left{float:left;margin:0 var(--radio-label-margin,10px) 0 0}.van-radio__label--disabled{color:var(--radio-disabled-label-color,#c8c9cc)}.van-radio__label:empty{margin:0}
+</style>

+ 98 - 0
src/wxcomponents/vant/rate/index.vue

@@ -0,0 +1,98 @@
+<template>
+<uni-shadow-root class="vant-rate-index"><view :class="(utils.bem('rate'))+' custom-class'" @touchmove="onTouchMove">
+  <view v-for="(item,index) in (innerCountArray)" :key="item.index" :class="utils.bem('rate__item')" :style="style({ paddingRight: index !== count - 1 ? utils.addUnit(gutter) : null })">
+    <van-icon :name="index + 1 <= innerValue ? icon : voidIcon" :class="utils.bem('rate__icon', [{ disabled, full: index + 1 <= innerValue }])" :style="style({ fontSize: utils.addUnit(size) })" custom-class="icon-class" :data-score="index" :color="disabled ? disabledColor : index + 1 <= innerValue ? color : voidColor" @click="onSelect"></van-icon>
+
+    <van-icon v-if="allowHalf" :name="index + 0.5 <= innerValue ? icon : voidIcon" :class="utils.bem('rate__icon', ['half', { disabled, full: index + 0.5 <= innerValue }])" :style="style({ fontSize: utils.addUnit(size) })" custom-class="icon-class" :data-score="index - 0.5" :color="disabled ? disabledColor : index + 0.5 <= innerValue ? color : voidColor" @click="onSelect"></van-icon>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="../wxs/style.wxs" module="style"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/rate/index'
+import { getAllRect } from '../common/utils';
+import { VantComponent } from '../common/component';
+import { canIUseModel } from '../common/version';
+VantComponent({
+    field: true,
+    classes: ['icon-class'],
+    props: {
+        value: {
+            type: Number,
+            observer(value) {
+                if (value !== this.data.innerValue) {
+                    this.setData({ innerValue: value });
+                }
+            },
+        },
+        readonly: Boolean,
+        disabled: Boolean,
+        allowHalf: Boolean,
+        size: null,
+        icon: {
+            type: String,
+            value: 'star',
+        },
+        voidIcon: {
+            type: String,
+            value: 'star-o',
+        },
+        color: String,
+        voidColor: String,
+        disabledColor: String,
+        count: {
+            type: Number,
+            value: 5,
+            observer(value) {
+                this.setData({ innerCountArray: Array.from({ length: value }) });
+            },
+        },
+        gutter: null,
+        touchable: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    data: {
+        innerValue: 0,
+        innerCountArray: Array.from({ length: 5 }),
+    },
+    methods: {
+        onSelect(event) {
+            const { data } = this;
+            const { score } = event.currentTarget.dataset;
+            if (!data.disabled && !data.readonly) {
+                this.setData({ innerValue: score + 1 });
+                if (canIUseModel()) {
+                    this.setData({ value: score + 1 });
+                }
+                wx.nextTick(() => {
+                    this.$emit('input', score + 1);
+                    this.$emit('change', score + 1);
+                });
+            }
+        },
+        onTouchMove(event) {
+            const { touchable } = this.data;
+            if (!touchable)
+                return;
+            const { clientX } = event.touches[0];
+            getAllRect(this, '.van-rate__icon').then((list) => {
+                const target = list
+                    .sort((cur, next) => cur.dataset.score - next.dataset.score)
+                    .find((item) => clientX >= item.left && clientX <= item.right);
+                if (target != null) {
+                    this.onSelect(Object.assign(Object.assign({}, event), { currentTarget: target }));
+                }
+            });
+        },
+    },
+});
+export default global['__wxComponents']['vant/rate/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-rate{display:inline-flex;-webkit-user-select:none;user-select:none}.van-rate__item{padding:0 var(--rate-horizontal-padding,2px);position:relative}.van-rate__item:not(:last-child){padding-right:var(--rate-icon-gutter,4px)}.van-rate__icon{color:var(--rate-icon-void-color,#c8c9cc);display:block;font-size:var(--rate-icon-size,20px);height:1em}.van-rate__icon--half{left:var(--rate-horizontal-padding,2px);overflow:hidden;position:absolute;top:0;width:.5em}.van-rate__icon--full,.van-rate__icon--half{color:var(--rate-icon-full-color,#ee0a24)}.van-rate__icon--disabled{color:var(--rate-icon-disabled-color,#c8c9cc)}
+</style>

+ 37 - 0
src/wxcomponents/vant/row/index.vue

@@ -0,0 +1,37 @@
+<template>
+<uni-shadow-root class="vant-row-index"><view class="van-row custom-class" :style="computed.rootStyle({ gutter })">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/row/index'
+import { VantComponent } from '../common/component';
+import { useChildren } from '../common/relation';
+VantComponent({
+    relation: useChildren('col', function (target) {
+        const { gutter } = this.data;
+        if (gutter) {
+            target.setData({ gutter });
+        }
+    }),
+    props: {
+        gutter: {
+            type: Number,
+            observer: 'setGutter',
+        },
+    },
+    methods: {
+        setGutter() {
+            this.children.forEach((col) => {
+                col.setData(this.data);
+            });
+        },
+    },
+});
+export default global['__wxComponents']['vant/row/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-row:after{clear:both;content:"";display:table}
+</style>

+ 118 - 0
src/wxcomponents/vant/search/index.vue

@@ -0,0 +1,118 @@
+<template>
+<uni-shadow-root class="vant-search-index"><view :class="(utils.bem('search', { withaction: showAction || useActionSlot }))+' custom-class'" :style="'background: '+(background)">
+  <view :class="utils.bem('search__content', [shape])">
+    <view class="van-search__label" v-if="label">{{ label }}</view>
+    <slot v-else name="label"></slot>
+
+    <van-field type="search" :left-icon="(!useLeftIconSlot ? leftIcon : '')" :right-icon="(!useRightIconSlot ? rightIcon : '')" :focus="focus" :error="error" :border="false" confirm-type="search" class="van-search__field field-class" :value="value" :disabled="disabled" :readonly="readonly" :clearable="clearable" :clear-trigger="clearTrigger" :clear-icon="clearIcon" :maxlength="maxlength" :input-align="inputAlign" input-class="input-class" :placeholder="placeholder" :placeholder-style="placeholderStyle" custom-style="padding: 5px 10px 5px 0; background-color: transparent;" @blur="onBlur" @focus="onFocus" @change="onChange" @confirm="onSearch" @clear="onClear" @click-input="onClickInput">
+      <slot v-if="useLeftIconSlot" name="left-icon" slot="left-icon"></slot>
+      <slot v-if="useRightIconSlot" name="right-icon" slot="right-icon"></slot>
+    </van-field>
+  </view>
+
+  <view v-if="showAction || useActionSlot" class="van-search__action" hover-class="van-search__action--hover" hover-stay-time="70">
+    <slot v-if="useActionSlot" name="action"></slot>
+    <view v-else @click="onCancel" class="cancel-class">{{ actionText }}</view>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanField from '../field/index.vue'
+global['__wxVueOptions'] = {components:{'van-field': VanField}}
+
+global['__wxRoute'] = 'vant/search/index'
+import { VantComponent } from '../common/component';
+import { canIUseModel } from '../common/version';
+VantComponent({
+    field: true,
+    classes: ['field-class', 'input-class', 'cancel-class'],
+    props: {
+        label: String,
+        focus: Boolean,
+        error: Boolean,
+        disabled: Boolean,
+        readonly: Boolean,
+        inputAlign: String,
+        showAction: Boolean,
+        useActionSlot: Boolean,
+        useLeftIconSlot: Boolean,
+        useRightIconSlot: Boolean,
+        leftIcon: {
+            type: String,
+            value: 'search',
+        },
+        rightIcon: String,
+        placeholder: String,
+        placeholderStyle: String,
+        actionText: {
+            type: String,
+            value: '取消',
+        },
+        background: {
+            type: String,
+            value: '#ffffff',
+        },
+        maxlength: {
+            type: Number,
+            value: -1,
+        },
+        shape: {
+            type: String,
+            value: 'square',
+        },
+        clearable: {
+            type: Boolean,
+            value: true,
+        },
+        clearTrigger: {
+            type: String,
+            value: 'focus',
+        },
+        clearIcon: {
+            type: String,
+            value: 'clear',
+        },
+    },
+    methods: {
+        onChange(event) {
+            if (canIUseModel()) {
+                this.setData({ value: event.detail });
+            }
+            this.$emit('change', event.detail);
+        },
+        onCancel() {
+            /**
+             * 修复修改输入框值时,输入框失焦和赋值同时触发,赋值失效
+             * https://github.com/youzan/@vant/weapp/issues/1768
+             */
+            setTimeout(() => {
+                if (canIUseModel()) {
+                    this.setData({ value: '' });
+                }
+                this.$emit('cancel');
+                this.$emit('change', '');
+            }, 200);
+        },
+        onSearch(event) {
+            this.$emit('search', event.detail);
+        },
+        onFocus(event) {
+            this.$emit('focus', event.detail);
+        },
+        onBlur(event) {
+            this.$emit('blur', event.detail);
+        },
+        onClear(event) {
+            this.$emit('clear', event.detail);
+        },
+        onClickInput(event) {
+            this.$emit('click-input', event.detail);
+        },
+    },
+});
+export default global['__wxComponents']['vant/search/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-search{align-items:center;box-sizing:border-box;display:flex;padding:var(--search-padding,10px 12px)}.van-search__content{background-color:var(--search-background-color,#f7f8fa);border-radius:2px;display:flex;flex:1;padding-left:var(--padding-sm,12px)}.van-search__content--round{border-radius:999px}.van-search__label{color:var(--search-label-color,#323233);font-size:var(--search-label-font-size,14px);line-height:var(--search-input-height,34px);padding:var(--search-label-padding,0 5px)}.van-search__field{flex:1}.van-search__field__left-icon{color:var(--search-left-icon-color,#969799)}.van-search--withaction{padding-right:0}.van-search__action{color:var(--search-action-text-color,#323233);font-size:var(--search-action-font-size,14px);line-height:var(--search-input-height,34px);padding:var(--search-action-padding,0 8px)}.van-search__action--hover{background-color:#f2f3f5}
+</style>

+ 94 - 0
src/wxcomponents/vant/share-sheet/index.vue

@@ -0,0 +1,94 @@
+<template>
+<uni-shadow-root class="vant-share-sheet-index"><van-popup round class="van-share-sheet" :show="show" position="bottom" :overlay="overlay" :duration="duration" :z-index="zIndex" :overlay-style="overlayStyle" :close-on-click-overlay="closeOnClickOverlay" :safe-area-inset-bottom="safeAreaInsetBottom" @close="onClose" @click-overlay="onClickOverlay">
+  <view class="van-share-sheet__header">
+    <view class="van-share-sheet__title">
+      <slot name="title"></slot>
+    </view>
+    <view v-if="title" class="van-share-sheet__title">{{ title }}</view>
+
+    <view class="van-share-sheet__description">
+      <slot name="description"></slot>
+    </view>
+    <view v-if="description" class="van-share-sheet__description">
+      {{ description }}
+    </view>
+  </view>
+
+  <block v-if="computed.isMulti(options)">
+    <options v-for="(item,index) in (options)" :key="item.index" :show-border="index !== 0" :options="item" @select="onSelect"></options>
+  </block>
+
+  <options v-else :options="options" @select="onSelect"></options>
+
+  <button type="button" class="van-share-sheet__cancel" @click="onCancel">
+    {{ cancelText }}
+  </button>
+</van-popup></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanPopup from '../popup/index.vue'
+import Options from './options.vue'
+global['__wxVueOptions'] = {components:{'van-popup': VanPopup,'options': Options}}
+
+global['__wxRoute'] = 'vant/share-sheet/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        // whether to show popup
+        show: Boolean,
+        // overlay custom style
+        overlayStyle: String,
+        // z-index
+        zIndex: {
+            type: Number,
+            value: 100,
+        },
+        title: String,
+        cancelText: {
+            type: String,
+            value: '取消',
+        },
+        description: String,
+        options: {
+            type: Array,
+            value: [],
+        },
+        overlay: {
+            type: Boolean,
+            value: true,
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true,
+        },
+        duration: {
+            type: null,
+            value: 300,
+        },
+    },
+    methods: {
+        onClickOverlay() {
+            this.$emit('click-overlay');
+        },
+        onCancel() {
+            this.onClose();
+            this.$emit('cancel');
+        },
+        onSelect(event) {
+            this.$emit('select', event.detail);
+        },
+        onClose() {
+            this.$emit('close');
+        },
+    },
+});
+export default global['__wxComponents']['vant/share-sheet/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-share-sheet__header{padding:12px 16px 4px;text-align:center}.van-share-sheet__title{color:#323233;font-size:14px;font-weight:400;line-height:20px;margin-top:8px}.van-share-sheet__title:empty,.van-share-sheet__title:not(:empty)+.van-share-sheet__title{display:none}.van-share-sheet__description{color:#969799;display:block;font-size:12px;line-height:16px;margin-top:8px}.van-share-sheet__description:empty,.van-share-sheet__description:not(:empty)+.van-share-sheet__description{display:none}.van-share-sheet__cancel{background:#fff;border:none;box-sizing:initial;display:block;font-size:16px;height:auto;line-height:48px;padding:0;text-align:center;width:100%}.van-share-sheet__cancel:before{background-color:#f7f8fa;content:" ";display:block;height:8px}.van-share-sheet__cancel:after{display:none}.van-share-sheet__cancel:active{background-color:#f2f3f5}
+</style>

+ 36 - 0
src/wxcomponents/vant/share-sheet/options.vue

@@ -0,0 +1,36 @@
+<template>
+<uni-shadow-root class="vant-share-sheet-options"><view :class="utils.bem('share-sheet__options', { border: showBorder })">
+  <view v-for="(item,index) in (options)" :key="item.index" class="van-share-sheet__option" :data-index="index" @click="onSelect">
+    <button class="van-share-sheet__button" :open-type="item.openType">
+      <image :src="computed.getIconURL(item.icon)" class="van-share-sheet__icon"></image> 
+      <view v-if="item.name" class="van-share-sheet__name">{{ item.name }}</view>
+      <view v-if="item.description" class="van-share-sheet__option-description">
+        {{ item.description }}
+      </view>
+    </button>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./options.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/share-sheet/options'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        options: Array,
+        showBorder: Boolean,
+    },
+    methods: {
+        onSelect(event) {
+            const { index } = event.currentTarget.dataset;
+            const option = this.data.options[index];
+            this.$emit('select', Object.assign(Object.assign({}, option), { index }));
+        },
+    },
+});
+export default global['__wxComponents']['vant/share-sheet/options']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-share-sheet__options{-webkit-overflow-scrolling:touch;display:flex;overflow-x:auto;overflow-y:visible;padding:16px 0 16px 8px;position:relative}.van-share-sheet__options--border:before{border-top:1px solid #ebedf0;box-sizing:border-box;content:" ";left:16px;pointer-events:none;position:absolute;right:0;top:0;transform:scaleY(.5);transform-origin:center}.van-share-sheet__options::-webkit-scrollbar{height:0}.van-share-sheet__option{align-items:center;display:flex;flex-direction:column;-webkit-user-select:none;user-select:none}.van-share-sheet__option:active{opacity:.7}.van-share-sheet__button{background-color:initial;border:0;height:auto;line-height:inherit;padding:0}.van-share-sheet__button:after{border:0}.van-share-sheet__icon{height:48px;margin:0 16px;width:48px}.van-share-sheet__name{color:#646566;font-size:12px;margin-top:8px;padding:0 4px}.van-share-sheet__option-description{color:#c8c9cc;font-size:12px;padding:0 4px}
+</style>

+ 49 - 0
src/wxcomponents/vant/sidebar-item/index.vue

@@ -0,0 +1,49 @@
+<template>
+<uni-shadow-root class="vant-sidebar-item-index"><view :class="(utils.bem('sidebar-item', { selected, disabled }))+' '+(selected ? 'active-class' : '')+' '+(disabled ? 'disabled-class' : '')+' custom-class'" hover-class="van-sidebar-item--hover" hover-stay-time="70" @click="onClick">
+  <view class="van-sidebar-item__text">
+    <van-info v-if="badge != null || info !== null || dot" :dot="dot" :info="badge != null ? badge : info"></van-info>
+    <view v-if="title">{{ title }}</view>
+    <slot v-else name="title"></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanInfo from '../info/index.vue'
+global['__wxVueOptions'] = {components:{'van-info': VanInfo}}
+
+global['__wxRoute'] = 'vant/sidebar-item/index'
+import { VantComponent } from '../common/component';
+import { useParent } from '../common/relation';
+VantComponent({
+    classes: ['active-class', 'disabled-class'],
+    relation: useParent('sidebar'),
+    props: {
+        dot: Boolean,
+        badge: null,
+        info: null,
+        title: String,
+        disabled: Boolean,
+    },
+    methods: {
+        onClick() {
+            const { parent } = this;
+            if (!parent || this.data.disabled) {
+                return;
+            }
+            const index = parent.children.indexOf(this);
+            parent.setActive(index).then(() => {
+                this.$emit('click', index);
+                parent.$emit('change', index);
+            });
+        },
+        setActive(selected) {
+            return this.setData({ selected });
+        },
+    },
+});
+export default global['__wxComponents']['vant/sidebar-item/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-sidebar-item{background-color:var(--sidebar-background-color,#f7f8fa);border-left:3px solid transparent;box-sizing:border-box;color:var(--sidebar-text-color,#323233);display:block;font-size:var(--sidebar-font-size,14px);line-height:var(--sidebar-line-height,20px);overflow:hidden;padding:var(--sidebar-padding,20px 12px 20px 8px);-webkit-user-select:none;user-select:none}.van-sidebar-item__text{display:inline-block;position:relative;word-break:break-all}.van-sidebar-item--hover:not(.van-sidebar-item--disabled){background-color:var(--sidebar-active-color,#f2f3f5)}.van-sidebar-item:after{border-bottom-width:1px}.van-sidebar-item--selected{border-color:var(--sidebar-selected-border-color,#ee0a24);color:var(--sidebar-selected-text-color,#323233);font-weight:var(--sidebar-selected-font-weight,500)}.van-sidebar-item--selected:after{border-right-width:1px}.van-sidebar-item--selected,.van-sidebar-item--selected.van-sidebar-item--hover{background-color:var(--sidebar-selected-background-color,#fff)}.van-sidebar-item--disabled{color:var(--sidebar-disabled-text-color,#c8c9cc)}
+</style>

+ 48 - 0
src/wxcomponents/vant/sidebar/index.vue

@@ -0,0 +1,48 @@
+<template>
+<uni-shadow-root class="vant-sidebar-index"><view class="van-sidebar custom-class">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/sidebar/index'
+import { VantComponent } from '../common/component';
+import { useChildren } from '../common/relation';
+VantComponent({
+    relation: useChildren('sidebar-item', function () {
+        this.setActive(this.data.activeKey);
+    }),
+    props: {
+        activeKey: {
+            type: Number,
+            value: 0,
+            observer: 'setActive',
+        },
+    },
+    beforeCreate() {
+        this.currentActive = -1;
+    },
+    methods: {
+        setActive(activeKey) {
+            const { children, currentActive } = this;
+            if (!children.length) {
+                return Promise.resolve();
+            }
+            this.currentActive = activeKey;
+            const stack = [];
+            if (currentActive !== activeKey && children[currentActive]) {
+                stack.push(children[currentActive].setActive(false));
+            }
+            if (children[activeKey]) {
+                stack.push(children[activeKey].setActive(true));
+            }
+            return Promise.all(stack);
+        },
+    },
+});
+export default global['__wxComponents']['vant/sidebar/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-sidebar{width:var(--sidebar-width,80px)}
+</style>

+ 69 - 0
src/wxcomponents/vant/skeleton/index.vue

@@ -0,0 +1,69 @@
+<template>
+<uni-shadow-root class="vant-skeleton-index"><view v-if="loading" :class="'custom-class '+(utils.bem('skeleton', [{animate}]))">
+  <view v-if="avatar" :class="'avatar-class '+(utils.bem('skeleton__avatar', [avatarShape]))" :style="'width:' + avatarSize + ';height:' + avatarSize"></view>
+  <view :class="utils.bem('skeleton__content')">
+    <view v-if="title" :class="'title-class '+(utils.bem('skeleton__title'))" :style="'width:' + titleWidth"></view>
+    <view v-for="(item,index) in (rowArray)" :key="item.index" :class="'row-class '+(utils.bem('skeleton__row'))" :style="'width:' + (isArray ? rowWidth[index] : rowWidth)"></view>
+  </view>
+</view>
+<view v-else :class="utils.bem('skeleton__content')">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxVueOptions'] = {components:{}}
+
+global['__wxRoute'] = 'vant/skeleton/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: ['avatar-class', 'title-class', 'row-class'],
+    props: {
+        row: {
+            type: Number,
+            value: 0,
+            observer(value) {
+                this.setData({ rowArray: Array.from({ length: value }) });
+            },
+        },
+        title: Boolean,
+        avatar: Boolean,
+        loading: {
+            type: Boolean,
+            value: true,
+        },
+        animate: {
+            type: Boolean,
+            value: true,
+        },
+        avatarSize: {
+            type: String,
+            value: '32px',
+        },
+        avatarShape: {
+            type: String,
+            value: 'round',
+        },
+        titleWidth: {
+            type: String,
+            value: '40%',
+        },
+        rowWidth: {
+            type: null,
+            value: '100%',
+            observer(val) {
+                this.setData({ isArray: val instanceof Array });
+            },
+        },
+    },
+    data: {
+        isArray: false,
+        rowArray: [],
+    },
+});
+export default global['__wxComponents']['vant/skeleton/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-skeleton{box-sizing:border-box;display:flex;padding:var(--skeleton-padding,0 16px);width:100%}.van-skeleton__avatar{background-color:var(--skeleton-avatar-background-color,#f2f3f5);flex-shrink:0;margin-right:var(--padding-md,16px)}.van-skeleton__avatar--round{border-radius:100%}.van-skeleton__content{flex:1}.van-skeleton__avatar+.van-skeleton__content{padding-top:var(--padding-xs,8px)}.van-skeleton__row,.van-skeleton__title{background-color:var(--skeleton-row-background-color,#f2f3f5);height:var(--skeleton-row-height,16px)}.van-skeleton__title{margin:0}.van-skeleton__row:not(:first-child){margin-top:var(--skeleton-row-margin-top,12px)}.van-skeleton__title+.van-skeleton__row{margin-top:20px}.van-skeleton--animate{animation:van-skeleton-blink 1.2s ease-in-out infinite}@keyframes van-skeleton-blink{50%{opacity:.6}}
+</style>

+ 219 - 0
src/wxcomponents/vant/slider/index.vue

@@ -0,0 +1,219 @@
+<template>
+<uni-shadow-root class="vant-slider-index"><view :class="'custom-class '+(utils.bem('slider', { disabled, vertical }))" :style="wrapperStyle" @click="onClick">
+  <view :class="utils.bem('slider__bar')" :style="(barStyle)+'; '+(style({ backgroundColor: activeColor }))">
+    <view v-if="range" :class="utils.bem('slider__button-wrapper-left')" :data-index="0" @touchstart="onTouchStart" @touchmove.stop.prevent="onTouchMove" @touchend="onTouchEnd" @touchcancel="onTouchEnd">
+      <slot v-if="useButtonSlot" name="left-button"></slot>
+      <view v-else :class="utils.bem('slider__button')"></view>
+    </view>
+    <view v-if="range" :class="utils.bem('slider__button-wrapper-right')" :data-index="1" @touchstart="onTouchStart" @touchmove.stop.prevent="onTouchMove" @touchend="onTouchEnd" @touchcancel="onTouchEnd">
+      <slot v-if="useButtonSlot" name="right-button"></slot>
+      <view v-else :class="utils.bem('slider__button')"></view>
+    </view>
+
+    <view v-if="(!range)" :class="utils.bem('slider__button-wrapper')" @touchstart="onTouchStart" @touchmove.stop.prevent="onTouchMove" @touchend="onTouchEnd" @touchcancel="onTouchEnd">
+      <slot v-if="useButtonSlot" name="button"></slot>
+      <view v-else :class="utils.bem('slider__button')"></view>
+    </view>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="../wxs/style.wxs" module="style"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/slider/index'
+import { VantComponent } from '../common/component';
+import { touch } from '../mixins/touch';
+import { canIUseModel } from '../common/version';
+import { getRect, addUnit } from '../common/utils';
+VantComponent({
+    mixins: [touch],
+    props: {
+        range: Boolean,
+        disabled: Boolean,
+        useButtonSlot: Boolean,
+        activeColor: String,
+        inactiveColor: String,
+        max: {
+            type: Number,
+            value: 100,
+        },
+        min: {
+            type: Number,
+            value: 0,
+        },
+        step: {
+            type: Number,
+            value: 1,
+        },
+        value: {
+            type: null,
+            value: 0,
+            observer(val) {
+                if (val !== this.value) {
+                    this.updateValue(val);
+                }
+            },
+        },
+        vertical: Boolean,
+        barHeight: null,
+    },
+    created() {
+        this.updateValue(this.data.value);
+    },
+    methods: {
+        onTouchStart(event) {
+            if (this.data.disabled)
+                return;
+            const { index } = event.currentTarget.dataset;
+            if (typeof index === 'number') {
+                this.buttonIndex = index;
+            }
+            this.touchStart(event);
+            this.startValue = this.format(this.value);
+            this.newValue = this.value;
+            if (this.isRange(this.newValue)) {
+                this.startValue = this.newValue.map((val) => this.format(val));
+            }
+            else {
+                this.startValue = this.format(this.newValue);
+            }
+            this.dragStatus = 'start';
+        },
+        onTouchMove(event) {
+            if (this.data.disabled)
+                return;
+            if (this.dragStatus === 'start') {
+                this.$emit('drag-start');
+            }
+            this.touchMove(event);
+            this.dragStatus = 'draging';
+            getRect(this, '.van-slider').then((rect) => {
+                const { vertical } = this.data;
+                const delta = vertical ? this.deltaY : this.deltaX;
+                const total = vertical ? rect.height : rect.width;
+                const diff = (delta / total) * this.getRange();
+                if (this.isRange(this.startValue)) {
+                    this.newValue[this.buttonIndex] =
+                        this.startValue[this.buttonIndex] + diff;
+                }
+                else {
+                    this.newValue = this.startValue + diff;
+                }
+                this.updateValue(this.newValue, false, true);
+            });
+        },
+        onTouchEnd() {
+            if (this.data.disabled)
+                return;
+            if (this.dragStatus === 'draging') {
+                this.updateValue(this.newValue, true);
+                this.$emit('drag-end');
+            }
+        },
+        onClick(event) {
+            if (this.data.disabled)
+                return;
+            const { min } = this.data;
+            getRect(this, '.van-slider').then((rect) => {
+                const { vertical } = this.data;
+                const touch = event.touches[0];
+                const delta = vertical
+                    ? touch.clientY - rect.top
+                    : touch.clientX - rect.left;
+                const total = vertical ? rect.height : rect.width;
+                const value = Number(min) + (delta / total) * this.getRange();
+                if (this.isRange(this.value)) {
+                    const [left, right] = this.value;
+                    const middle = (left + right) / 2;
+                    if (value <= middle) {
+                        this.updateValue([value, right], true);
+                    }
+                    else {
+                        this.updateValue([left, value], true);
+                    }
+                }
+                else {
+                    this.updateValue(value, true);
+                }
+            });
+        },
+        isRange(val) {
+            const { range } = this.data;
+            return range && Array.isArray(val);
+        },
+        handleOverlap(value) {
+            if (value[0] > value[1]) {
+                return value.slice(0).reverse();
+            }
+            return value;
+        },
+        updateValue(value, end, drag) {
+            if (this.isRange(value)) {
+                value = this.handleOverlap(value).map((val) => this.format(val));
+            }
+            else {
+                value = this.format(value);
+            }
+            this.value = value;
+            const { vertical } = this.data;
+            const mainAxis = vertical ? 'height' : 'width';
+            this.setData({
+                wrapperStyle: `
+          background: ${this.data.inactiveColor || ''};
+          ${vertical ? 'width' : 'height'}: ${addUnit(this.data.barHeight) || ''};
+        `,
+                barStyle: `
+          ${mainAxis}: ${this.calcMainAxis()};
+          left: ${vertical ? 0 : this.calcOffset()};
+          top: ${vertical ? this.calcOffset() : 0};
+          ${drag ? 'transition: none;' : ''}
+        `,
+            });
+            if (drag) {
+                this.$emit('drag', { value });
+            }
+            if (end) {
+                this.$emit('change', value);
+            }
+            if ((drag || end) && canIUseModel()) {
+                this.setData({ value });
+            }
+        },
+        getScope() {
+            return Number(this.data.max) - Number(this.data.min);
+        },
+        getRange() {
+            const { max, min } = this.data;
+            return max - min;
+        },
+        // 计算选中条的长度百分比
+        calcMainAxis() {
+            const { value } = this;
+            const { min } = this.data;
+            const scope = this.getScope();
+            if (this.isRange(value)) {
+                return `${((value[1] - value[0]) * 100) / scope}%`;
+            }
+            return `${((value - Number(min)) * 100) / scope}%`;
+        },
+        // 计算选中条的开始位置的偏移量
+        calcOffset() {
+            const { value } = this;
+            const { min } = this.data;
+            const scope = this.getScope();
+            if (this.isRange(value)) {
+                return `${((value[0] - Number(min)) * 100) / scope}%`;
+            }
+            return '0%';
+        },
+        format(value) {
+            const { max, min, step } = this.data;
+            return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
+        },
+    },
+});
+export default global['__wxComponents']['vant/slider/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-slider{background-color:var(--slider-inactive-background-color,#ebedf0);border-radius:999px;height:var(--slider-bar-height,2px);position:relative}.van-slider:before{bottom:calc(var(--padding-xs, 8px)*-1);content:"";left:0;position:absolute;right:0;top:calc(var(--padding-xs, 8px)*-1)}.van-slider__bar{background-color:var(--slider-active-background-color,#1989fa);border-radius:inherit;height:100%;position:relative;transition:all .2s;width:100%}.van-slider__button{background-color:var(--slider-button-background-color,#fff);border-radius:var(--slider-button-border-radius,50%);box-shadow:var(--slider-button-box-shadow,0 1px 2px rgba(0,0,0,.5));height:var(--slider-button-height,24px);width:var(--slider-button-width,24px)}.van-slider__button-wrapper,.van-slider__button-wrapper-right{position:absolute;right:0;top:50%;transform:translate3d(50%,-50%,0)}.van-slider__button-wrapper-left{left:0;position:absolute;top:50%;transform:translate3d(-50%,-50%,0)}.van-slider--disabled{opacity:var(--slider-disabled-opacity,.5)}.van-slider--vertical{display:inline-block;height:100%;width:var(--slider-bar-height,2px)}.van-slider--vertical .van-slider__button-wrapper,.van-slider--vertical .van-slider__button-wrapper-right{bottom:0;right:50%;top:auto;transform:translate3d(50%,50%,0)}.van-slider--vertical .van-slider__button-wrapper-left{left:auto;right:50%;top:0;transform:translate3d(50%,-50%,0)}.van-slider--vertical:before{bottom:0;left:-8px;right:-8px;top:0}
+</style>

File diff suppressed because it is too large
+ 203 - 0
src/wxcomponents/vant/stepper/index.vue


+ 12 - 0
src/wxcomponents/vant/steps/index-status.wxs

@@ -0,0 +1,12 @@
+
+function get(index, active) {
+  if (index < active) {
+    return 'finish';
+  } else if (index === active) {
+    return 'process';
+  }
+
+  return 'inactive';
+}
+
+module.exports = get;

File diff suppressed because it is too large
+ 63 - 0
src/wxcomponents/vant/steps/index.vue


+ 134 - 0
src/wxcomponents/vant/sticky/index.vue

@@ -0,0 +1,134 @@
+<template>
+<uni-shadow-root class="vant-sticky-index"><view class="custom-class van-sticky" :style="computed.containerStyle({ fixed, height, zIndex })">
+  <view :class="utils.bem('sticky-wrap', { fixed })" :style="computed.wrapStyle({ fixed, offsetTop, transform, zIndex })">
+    <slot></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/sticky/index'
+import { getRect } from '../common/utils';
+import { VantComponent } from '../common/component';
+import { isDef } from '../common/validator';
+import { pageScrollMixin } from '../mixins/page-scroll';
+const ROOT_ELEMENT = '.van-sticky';
+VantComponent({
+    props: {
+        zIndex: {
+            type: Number,
+            value: 99,
+        },
+        offsetTop: {
+            type: Number,
+            value: 0,
+            observer: 'onScroll',
+        },
+        disabled: {
+            type: Boolean,
+            observer: 'onScroll',
+        },
+        container: {
+            type: null,
+            observer: 'onScroll',
+        },
+        scrollTop: {
+            type: null,
+            observer(val) {
+                this.onScroll({ scrollTop: val });
+            },
+        },
+    },
+    mixins: [
+        pageScrollMixin(function (event) {
+            if (this.data.scrollTop != null) {
+                return;
+            }
+            this.onScroll(event);
+        }),
+    ],
+    data: {
+        height: 0,
+        fixed: false,
+        transform: 0,
+    },
+    mounted() {
+        this.onScroll();
+    },
+    methods: {
+        onScroll({ scrollTop } = {}) {
+            const { container, offsetTop, disabled } = this.data;
+            if (disabled) {
+                this.setDataAfterDiff({
+                    fixed: false,
+                    transform: 0,
+                });
+                return;
+            }
+            this.scrollTop = scrollTop || this.scrollTop;
+            if (typeof container === 'function') {
+                Promise.all([
+                    getRect(this, ROOT_ELEMENT),
+                    this.getContainerRect(),
+                ]).then(([root, container]) => {
+                    if (offsetTop + root.height > container.height + container.top) {
+                        this.setDataAfterDiff({
+                            fixed: false,
+                            transform: container.height - root.height,
+                        });
+                    }
+                    else if (offsetTop >= root.top) {
+                        this.setDataAfterDiff({
+                            fixed: true,
+                            height: root.height,
+                            transform: 0,
+                        });
+                    }
+                    else {
+                        this.setDataAfterDiff({ fixed: false, transform: 0 });
+                    }
+                });
+                return;
+            }
+            getRect(this, ROOT_ELEMENT).then((root) => {
+                if (!isDef(root)) {
+                    return;
+                }
+                if (offsetTop >= root.top) {
+                    this.setDataAfterDiff({ fixed: true, height: root.height });
+                    this.transform = 0;
+                }
+                else {
+                    this.setDataAfterDiff({ fixed: false });
+                }
+            });
+        },
+        setDataAfterDiff(data) {
+            wx.nextTick(() => {
+                const diff = Object.keys(data).reduce((prev, key) => {
+                    if (data[key] !== this.data[key]) {
+                        prev[key] = data[key];
+                    }
+                    return prev;
+                }, {});
+                if (Object.keys(diff).length > 0) {
+                    this.setData(diff);
+                }
+                this.$emit('scroll', {
+                    scrollTop: this.scrollTop,
+                    isFixed: data.fixed || this.data.fixed,
+                });
+            });
+        },
+        getContainerRect() {
+            const nodesRef = this.data.container();
+            return new Promise((resolve) => nodesRef.boundingClientRect(resolve).exec());
+        },
+    },
+});
+export default global['__wxComponents']['vant/sticky/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-sticky{position:relative}.van-sticky-wrap--fixed{left:0;position:fixed;right:0}
+</style>

+ 98 - 0
src/wxcomponents/vant/submit-bar/index.vue

@@ -0,0 +1,98 @@
+<template>
+<uni-shadow-root class="vant-submit-bar-index"><view class="van-submit-bar custom-class">
+  <slot name="top"></slot>
+
+  <view class="van-submit-bar__tip">
+    <van-icon v-if="tipIcon" size="12px" :name="tipIcon" custom-class="van-submit-bar__tip-icon"></van-icon>
+    <view v-if="hasTip" class="van-submit-bar__tip-text">
+      {{ tip }}
+    </view>
+    <slot name="tip"></slot>
+  </view>
+
+  <view class="bar-class van-submit-bar__bar">
+    <slot></slot>
+    <view v-if="hasPrice" class="van-submit-bar__text">
+      <text>{{ label || '合计:' }}</text>
+      <text class="van-submit-bar__price price-class">
+        <text class="van-submit-bar__currency">{{ currency }} </text>
+        <text class="van-submit-bar__price-integer">{{ integerStr }}</text><text>{{decimalStr}}</text>
+      </text>
+      <text class="van-submit-bar__suffix-label">{{ suffixLabel }}</text>
+    </view>
+    <van-button round :type="buttonType" :loading="loading" :disabled="disabled" class="van-submit-bar__button" custom-class="button-class" custom-style="width: 100%;" @click="onSubmit">
+      {{ loading ? '' : buttonText }}
+    </van-button>
+  </view>
+
+  <view v-if="safeAreaInsetBottom" class="van-submit-bar__safe"></view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanButton from '../button/index.vue'
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-button': VanButton,'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/submit-bar/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: ['bar-class', 'price-class', 'button-class'],
+    props: {
+        tip: {
+            type: null,
+            observer: 'updateTip',
+        },
+        tipIcon: String,
+        type: Number,
+        price: {
+            type: null,
+            observer: 'updatePrice',
+        },
+        label: String,
+        loading: Boolean,
+        disabled: Boolean,
+        buttonText: String,
+        currency: {
+            type: String,
+            value: '¥',
+        },
+        buttonType: {
+            type: String,
+            value: 'danger',
+        },
+        decimalLength: {
+            type: Number,
+            value: 2,
+            observer: 'updatePrice',
+        },
+        suffixLabel: String,
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    methods: {
+        updatePrice() {
+            const { price, decimalLength } = this.data;
+            const priceStrArr = typeof price === 'number' &&
+                (price / 100).toFixed(decimalLength).split('.');
+            this.setData({
+                hasPrice: typeof price === 'number',
+                integerStr: priceStrArr && priceStrArr[0],
+                decimalStr: decimalLength && priceStrArr ? `.${priceStrArr[1]}` : '',
+            });
+        },
+        updateTip() {
+            this.setData({ hasTip: typeof this.data.tip === 'string' });
+        },
+        onSubmit(event) {
+            this.$emit('submit', event.detail);
+        },
+    },
+});
+export default global['__wxComponents']['vant/submit-bar/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-submit-bar{background-color:var(--submit-bar-background-color,#fff);bottom:0;left:0;position:fixed;-webkit-user-select:none;user-select:none;width:100%;z-index:var(--submit-bar-z-index,100)}.van-submit-bar__tip{background-color:var(--submit-bar-tip-background-color,#fff7cc);color:var(--submit-bar-tip-color,#f56723);font-size:var(--submit-bar-tip-font-size,12px);line-height:var(--submit-bar-tip-line-height,1.5);padding:var(--submit-bar-tip-padding,10px)}.van-submit-bar__tip:empty{display:none}.van-submit-bar__tip-icon{margin-right:4px;vertical-align:middle}.van-submit-bar__tip-text{display:inline;vertical-align:middle}.van-submit-bar__bar{align-items:center;background-color:var(--submit-bar-background-color,#fff);display:flex;font-size:var(--submit-bar-text-font-size,14px);height:var(--submit-bar-height,50px);justify-content:flex-end;padding:var(--submit-bar-padding,0 16px)}.van-submit-bar__safe{height:constant(safe-area-inset-bottom);height:env(safe-area-inset-bottom)}.van-submit-bar__text{color:var(--submit-bar-text-color,#323233);flex:1;font-weight:var(--font-weight-bold,500);padding-right:var(--padding-sm,12px);text-align:right}.van-submit-bar__price{color:var(--submit-bar-price-color,#ee0a24);font-size:var(--submit-bar-price-font-size,12px);font-weight:var(--font-weight-bold,500)}.van-submit-bar__price-integer{font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif;font-size:20px}.van-submit-bar__currency{font-size:var(--submit-bar-currency-font-size,12px)}.van-submit-bar__suffix-label{margin-left:5px}.van-submit-bar__button{--button-default-height:var(--submit-bar-button-height,40px)!important;--button-line-height:var(--submit-bar-button-height,40px)!important;font-weight:var(--font-weight-bold,500);width:var(--submit-bar-button-width,110px)}
+</style>

+ 155 - 0
src/wxcomponents/vant/swipe-cell/index.vue

@@ -0,0 +1,155 @@
+<template>
+<uni-shadow-root class="vant-swipe-cell-index"><view class="van-swipe-cell custom-class" data-key="cell" @click.stop.prevent="onClick" @touchstart="startDrag" @touchmove.stop.prevent="_$self[(catchMove ? 'noop' : '')||'_$noop']($event)" @touchmove.capture="onDrag" @touchend="endDrag" @touchcancel="endDrag">
+  <view :style="wrapperStyle">
+    <view v-if="leftWidth" class="van-swipe-cell__left" data-key="left" @click.stop.prevent="onClick">
+      <slot name="left"></slot>
+    </view>
+    <slot></slot>
+    <view v-if="rightWidth" class="van-swipe-cell__right" data-key="right" @click.stop.prevent="onClick">
+      <slot name="right"></slot>
+    </view>
+  </view>
+</view></uni-shadow-root>
+</template>
+
+<script>
+
+global['__wxRoute'] = 'vant/swipe-cell/index'
+import { VantComponent } from '../common/component';
+import { touch } from '../mixins/touch';
+import { range } from '../common/utils';
+const THRESHOLD = 0.3;
+let ARRAY = [];
+VantComponent({
+    props: {
+        disabled: Boolean,
+        leftWidth: {
+            type: Number,
+            value: 0,
+            observer(leftWidth = 0) {
+                if (this.offset > 0) {
+                    this.swipeMove(leftWidth);
+                }
+            },
+        },
+        rightWidth: {
+            type: Number,
+            value: 0,
+            observer(rightWidth = 0) {
+                if (this.offset < 0) {
+                    this.swipeMove(-rightWidth);
+                }
+            },
+        },
+        asyncClose: Boolean,
+        name: {
+            type: null,
+            value: '',
+        },
+    },
+    mixins: [touch],
+    data: {
+        catchMove: false,
+        wrapperStyle: '',
+    },
+    created() {
+        this.offset = 0;
+        ARRAY.push(this);
+    },
+    destroyed() {
+        ARRAY = ARRAY.filter((item) => item !== this);
+    },
+    methods: {
+        open(position) {
+            const { leftWidth, rightWidth } = this.data;
+            const offset = position === 'left' ? leftWidth : -rightWidth;
+            this.swipeMove(offset);
+            this.$emit('open', {
+                position,
+                name: this.data.name,
+            });
+        },
+        close() {
+            this.swipeMove(0);
+        },
+        swipeMove(offset = 0) {
+            this.offset = range(offset, -this.data.rightWidth, this.data.leftWidth);
+            const transform = `translate3d(${this.offset}px, 0, 0)`;
+            const transition = this.dragging
+                ? 'none'
+                : 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
+            this.setData({
+                wrapperStyle: `
+        -webkit-transform: ${transform};
+        -webkit-transition: ${transition};
+        transform: ${transform};
+        transition: ${transition};
+      `,
+            });
+        },
+        swipeLeaveTransition() {
+            const { leftWidth, rightWidth } = this.data;
+            const { offset } = this;
+            if (rightWidth > 0 && -offset > rightWidth * THRESHOLD) {
+                this.open('right');
+            }
+            else if (leftWidth > 0 && offset > leftWidth * THRESHOLD) {
+                this.open('left');
+            }
+            else {
+                this.swipeMove(0);
+            }
+            this.setData({ catchMove: false });
+        },
+        startDrag(event) {
+            if (this.data.disabled) {
+                return;
+            }
+            this.startOffset = this.offset;
+            this.touchStart(event);
+        },
+        noop() { },
+        onDrag(event) {
+            if (this.data.disabled) {
+                return;
+            }
+            this.touchMove(event);
+            if (this.direction !== 'horizontal') {
+                return;
+            }
+            this.dragging = true;
+            ARRAY.filter((item) => item !== this && item.offset !== 0).forEach((item) => item.close());
+            this.setData({ catchMove: true });
+            this.swipeMove(this.startOffset + this.deltaX);
+        },
+        endDrag() {
+            if (this.data.disabled) {
+                return;
+            }
+            this.dragging = false;
+            this.swipeLeaveTransition();
+        },
+        onClick(event) {
+            const { key: position = 'outside' } = event.currentTarget.dataset;
+            this.$emit('click', position);
+            if (!this.offset) {
+                return;
+            }
+            if (this.data.asyncClose) {
+                this.$emit('close', {
+                    position,
+                    instance: this,
+                    name: this.data.name,
+                });
+            }
+            else {
+                this.swipeMove(0);
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/swipe-cell/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-swipe-cell{overflow:hidden;position:relative}.van-swipe-cell__left,.van-swipe-cell__right{height:100%;position:absolute;top:0}.van-swipe-cell__left{left:0;transform:translate3d(-100%,0,0)}.van-swipe-cell__right{right:0;transform:translate3d(100%,0,0)}
+</style>

+ 54 - 0
src/wxcomponents/vant/switch/index.vue

@@ -0,0 +1,54 @@
+<template>
+<uni-shadow-root class="vant-switch-index"><view :class="(utils.bem('switch', { on: checked === activeValue, disabled }))+' custom-class'" :style="computed.rootStyle({ size, checked, activeColor, inactiveColor, activeValue })" @click="onClick">
+  <view class="van-switch__node node-class">
+    <van-loading v-if="loading" :color="computed.loadingColor({ checked, activeColor, inactiveColor, activeValue })" custom-class="van-switch__loading"></van-loading>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanLoading from '../loading/index.vue'
+global['__wxVueOptions'] = {components:{'van-loading': VanLoading}}
+
+global['__wxRoute'] = 'vant/switch/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    field: true,
+    classes: ['node-class'],
+    props: {
+        checked: null,
+        loading: Boolean,
+        disabled: Boolean,
+        activeColor: String,
+        inactiveColor: String,
+        size: {
+            type: String,
+            value: '30',
+        },
+        activeValue: {
+            type: null,
+            value: true,
+        },
+        inactiveValue: {
+            type: null,
+            value: false,
+        },
+    },
+    methods: {
+        onClick() {
+            const { activeValue, inactiveValue, disabled, loading } = this.data;
+            if (disabled || loading) {
+                return;
+            }
+            const checked = this.data.checked === activeValue;
+            const value = checked ? inactiveValue : activeValue;
+            this.$emit('input', value);
+            this.$emit('change', value);
+        },
+    },
+});
+export default global['__wxComponents']['vant/switch/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-switch{background-color:var(--switch-background-color,#fff);border:var(--switch-border,1px solid rgba(0,0,0,.1));border-radius:var(--switch-node-size,1em);box-sizing:initial;display:inline-block;height:var(--switch-height,1em);position:relative;transition:background-color var(--switch-transition-duration,.3s);width:var(--switch-width,2em)}.van-switch__node{background-color:var(--switch-node-background-color,#fff);border-radius:100%;box-shadow:var(--switch-node-box-shadow,0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05));height:var(--switch-node-size,1em);left:0;position:absolute;top:0;transition:var(--switch-transition-duration,.3s) cubic-bezier(.3,1.05,.4,1.05);width:var(--switch-node-size,1em);z-index:var(--switch-node-z-index,1)}.van-switch__loading{height:50%;left:25%;position:absolute!important;top:25%;width:50%}.van-switch--on{background-color:var(--switch-on-background-color,#1989fa)}.van-switch--on .van-switch__node{transform:translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)))}.van-switch--disabled{opacity:var(--switch-disabled-opacity,.4)}
+</style>

+ 70 - 0
src/wxcomponents/vant/tab/index.vue

@@ -0,0 +1,70 @@
+<template>
+<uni-shadow-root class="vant-tab-index"><view :class="'custom-class '+(utils.bem('tab__pane', { active, inactive: !active }))" :style="shouldShow ? '' : 'display: none;'">
+  <slot v-if="shouldRender"></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/tab/index'
+import { useParent } from '../common/relation';
+import { VantComponent } from '../common/component';
+VantComponent({
+    relation: useParent('tabs'),
+    props: {
+        dot: {
+            type: Boolean,
+            observer: 'update',
+        },
+        info: {
+            type: null,
+            observer: 'update',
+        },
+        title: {
+            type: String,
+            observer: 'update',
+        },
+        disabled: {
+            type: Boolean,
+            observer: 'update',
+        },
+        titleStyle: {
+            type: String,
+            observer: 'update',
+        },
+        name: {
+            type: null,
+            value: '',
+        },
+    },
+    data: {
+        active: false,
+    },
+    methods: {
+        getComputedName() {
+            if (this.data.name !== '') {
+                return this.data.name;
+            }
+            return this.index;
+        },
+        updateRender(active, parent) {
+            const { data: parentData } = parent;
+            this.inited = this.inited || active;
+            this.setData({
+                active,
+                shouldRender: this.inited || !parentData.lazyRender,
+                shouldShow: active || parentData.animated,
+            });
+        },
+        update() {
+            if (this.parent) {
+                this.parent.updateTabs();
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/tab/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.vant-tab-index{box-sizing:border-box;flex-shrink:0;width:100%}.van-tab__pane{-webkit-overflow-scrolling:touch;box-sizing:border-box;overflow-y:auto}.van-tab__pane--active{height:auto}.van-tab__pane--inactive{height:0;overflow:visible}
+</style>

+ 83 - 0
src/wxcomponents/vant/tabbar-item/index.vue

@@ -0,0 +1,83 @@
+<template>
+<uni-shadow-root class="vant-tabbar-item-index"><view :class="(utils.bem('tabbar-item', { active }))+' custom-class'" :style="'color: '+(active ? activeColor : inactiveColor)" @click="onClick">
+  <view class="van-tabbar-item__icon">
+    <van-icon v-if="icon" :name="icon" :class-prefix="iconPrefix" custom-class="van-tabbar-item__icon__inner"></van-icon>
+    <block v-else>
+      <slot v-if="active" name="icon-active"></slot>
+      <slot v-else name="icon"></slot>
+    </block>
+    <van-info :dot="dot" :info="info" custom-class="van-tabbar-item__info"></van-info>
+  </view>
+  <view class="van-tabbar-item__text">
+    <slot></slot>
+  </view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+import VanInfo from '../info/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon,'van-info': VanInfo}}
+
+global['__wxRoute'] = 'vant/tabbar-item/index'
+import { VantComponent } from '../common/component';
+import { useParent } from '../common/relation';
+VantComponent({
+    props: {
+        info: null,
+        name: null,
+        icon: String,
+        dot: Boolean,
+        iconPrefix: {
+            type: String,
+            value: 'van-icon',
+        },
+    },
+    relation: useParent('tabbar'),
+    data: {
+        active: false,
+        activeColor: '',
+        inactiveColor: '',
+    },
+    methods: {
+        onClick() {
+            const { parent } = this;
+            if (parent) {
+                const index = parent.children.indexOf(this);
+                const active = this.data.name || index;
+                if (active !== this.data.active) {
+                    parent.$emit('change', active);
+                }
+            }
+            this.$emit('click');
+        },
+        updateFromParent() {
+            const { parent } = this;
+            if (!parent) {
+                return;
+            }
+            const index = parent.children.indexOf(this);
+            const parentData = parent.data;
+            const { data } = this;
+            const active = (data.name || index) === parentData.active;
+            const patch = {};
+            if (active !== data.active) {
+                patch.active = active;
+            }
+            if (parentData.activeColor !== data.activeColor) {
+                patch.activeColor = parentData.activeColor;
+            }
+            if (parentData.inactiveColor !== data.inactiveColor) {
+                patch.inactiveColor = parentData.inactiveColor;
+            }
+            if (Object.keys(patch).length > 0) {
+                this.setData(patch);
+            }
+        },
+    },
+});
+export default global['__wxComponents']['vant/tabbar-item/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.vant-tabbar-item-index{flex:1}.van-tabbar-item{align-items:center;color:var(--tabbar-item-text-color,#646566);display:flex;flex-direction:column;font-size:var(--tabbar-item-font-size,12px);height:100%;justify-content:center;line-height:var(--tabbar-item-line-height,1)}.van-tabbar-item__icon{font-size:var(--tabbar-item-icon-size,22px);margin-bottom:var(--tabbar-item-margin-bottom,4px);position:relative}.van-tabbar-item__icon__inner{display:block;min-width:1em}.van-tabbar-item--active{color:var(--tabbar-item-active-color,#1989fa)}.van-tabbar-item__info{margin-top:2px}
+</style>

+ 81 - 0
src/wxcomponents/vant/tabbar/index.vue

@@ -0,0 +1,81 @@
+<template>
+<uni-shadow-root class="vant-tabbar-index"><view :class="(border ? 'van-hairline--top-bottom' : '')+' '+(utils.bem('tabbar', { fixed, safe: safeAreaInsetBottom }))+' custom-class'" :style="zIndex ? 'z-index: ' + zIndex : ''">
+  <slot></slot>
+</view>
+
+<view v-if="fixed && placeholder" :style="'height: '+(height)+'px;'"></view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/tabbar/index'
+import { VantComponent } from '../common/component';
+import { useChildren } from '../common/relation';
+import { getRect } from '../common/utils';
+VantComponent({
+    relation: useChildren('tabbar-item', function () {
+        this.updateChildren();
+    }),
+    props: {
+        active: {
+            type: null,
+            observer: 'updateChildren',
+        },
+        activeColor: {
+            type: String,
+            observer: 'updateChildren',
+        },
+        inactiveColor: {
+            type: String,
+            observer: 'updateChildren',
+        },
+        fixed: {
+            type: Boolean,
+            value: true,
+            observer: 'setHeight',
+        },
+        placeholder: {
+            type: Boolean,
+            observer: 'setHeight',
+        },
+        border: {
+            type: Boolean,
+            value: true,
+        },
+        zIndex: {
+            type: Number,
+            value: 1,
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    data: {
+        height: 50,
+    },
+    methods: {
+        updateChildren() {
+            const { children } = this;
+            if (!Array.isArray(children) || !children.length) {
+                return;
+            }
+            children.forEach((child) => child.updateFromParent());
+        },
+        setHeight() {
+            if (!this.data.fixed || !this.data.placeholder) {
+                return;
+            }
+            wx.nextTick(() => {
+                getRect(this, '.van-tabbar').then((res) => {
+                    this.setData({ height: res.height });
+                });
+            });
+        },
+    },
+});
+export default global['__wxComponents']['vant/tabbar/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-tabbar{background-color:var(--tabbar-background-color,#fff);box-sizing:initial;display:flex;height:var(--tabbar-height,50px);width:100%}.van-tabbar--fixed{bottom:0;left:0;position:fixed}.van-tabbar--safe{padding-bottom:env(safe-area-inset-bottom)}
+</style>

File diff suppressed because it is too large
+ 309 - 0
src/wxcomponents/vant/tabs/index.vue


+ 38 - 0
src/wxcomponents/vant/tag/index.vue

@@ -0,0 +1,38 @@
+<template>
+<uni-shadow-root class="vant-tag-index"><view :class="'custom-class '+(utils.bem('tag', [type, size, { mark, plain, round }]))" :style="computed.rootStyle({ plain, color, textColor })">
+  <slot></slot>
+  <van-icon v-if="closeable" name="cross" custom-class="van-tag__close" @click="onClose"></van-icon>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="computed"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon}}
+
+global['__wxRoute'] = 'vant/tag/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        size: String,
+        mark: Boolean,
+        color: String,
+        plain: Boolean,
+        round: Boolean,
+        textColor: String,
+        type: {
+            type: String,
+            value: 'default',
+        },
+        closeable: Boolean,
+    },
+    methods: {
+        onClose() {
+            this.$emit('close');
+        },
+    },
+});
+export default global['__wxComponents']['vant/tag/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-tag{align-items:center;border-radius:var(--tag-border-radius,2px);color:var(--tag-text-color,#fff);display:inline-flex;font-size:var(--tag-font-size,12px);line-height:var(--tag-line-height,16px);padding:var(--tag-padding,0 4px);position:relative}.van-tag--default{background-color:var(--tag-default-color,#969799)}.van-tag--default.van-tag--plain{color:var(--tag-default-color,#969799)}.van-tag--danger{background-color:var(--tag-danger-color,#ee0a24)}.van-tag--danger.van-tag--plain{color:var(--tag-danger-color,#ee0a24)}.van-tag--primary{background-color:var(--tag-primary-color,#1989fa)}.van-tag--primary.van-tag--plain{color:var(--tag-primary-color,#1989fa)}.van-tag--success{background-color:var(--tag-success-color,#07c160)}.van-tag--success.van-tag--plain{color:var(--tag-success-color,#07c160)}.van-tag--warning{background-color:var(--tag-warning-color,#ff976a)}.van-tag--warning.van-tag--plain{color:var(--tag-warning-color,#ff976a)}.van-tag--plain{background-color:var(--tag-plain-background-color,#fff)}.van-tag--plain:before{border:1px solid;border-radius:inherit;bottom:0;content:"";left:0;pointer-events:none;position:absolute;right:0;top:0}.van-tag--medium{padding:var(--tag-medium-padding,2px 6px)}.van-tag--large{border-radius:var(--tag-large-border-radius,4px);font-size:var(--tag-large-font-size,14px);padding:var(--tag-large-padding,4px 8px)}.van-tag--mark{border-radius:0 var(--tag-round-border-radius,var(--tag-round-border-radius,999px)) var(--tag-round-border-radius,var(--tag-round-border-radius,999px)) 0}.van-tag--mark:after{content:"";display:block;width:2px}.van-tag--round{border-radius:var(--tag-round-border-radius,999px)}.van-tag__close{margin-left:2px;min-width:1em}
+</style>

+ 64 - 0
src/wxcomponents/vant/toast/index.vue

@@ -0,0 +1,64 @@
+<template>
+<uni-shadow-root class="vant-toast-index"><van-overlay v-if="mask || forbidClick" :show="show" :z-index="zIndex" :custom-style="mask ? '' : 'background-color: transparent;'"></van-overlay>
+<van-transition :show="show" :custom-style="'z-index: '+(zIndex)" custom-class="van-toast__container">
+  <view :class="'van-toast van-toast--'+((type === 'text' || type === 'html') ? 'text' : 'icon')+' van-toast--'+(position)" @touchmove.stop.prevent="noop">
+    
+    <text v-if="type === 'text'">{{ message }}</text>
+
+    
+    <rich-text v-else-if="type === 'html'" :nodes="message"></rich-text>
+
+    
+    <block v-else>
+      <van-loading v-if="type === 'loading'" color="white" :type="loadingType" custom-class="van-toast__loading"></van-loading>
+      <van-icon v-else class="van-toast__icon" :name="type"></van-icon>
+      <text v-if="message" class="van-toast__text">{{ message }}</text>
+    </block>
+
+    <slot></slot>
+  </view>
+</van-transition></uni-shadow-root>
+</template>
+
+<script>
+import VanIcon from '../icon/index.vue'
+import VanLoading from '../loading/index.vue'
+import VanOverlay from '../overlay/index.vue'
+import VanTransition from '../transition/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon,'van-loading': VanLoading,'van-overlay': VanOverlay,'van-transition': VanTransition}}
+
+global['__wxRoute'] = 'vant/toast/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        show: Boolean,
+        mask: Boolean,
+        message: String,
+        forbidClick: Boolean,
+        zIndex: {
+            type: Number,
+            value: 1000,
+        },
+        type: {
+            type: String,
+            value: 'text',
+        },
+        loadingType: {
+            type: String,
+            value: 'circular',
+        },
+        position: {
+            type: String,
+            value: 'middle',
+        },
+    },
+    methods: {
+        // for prevent touchmove
+        noop() { },
+    },
+});
+export default global['__wxComponents']['vant/toast/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-toast{word-wrap:break-word;align-items:center;background-color:var(--toast-background-color,rgba(0,0,0,.7));border-radius:var(--toast-border-radius,8px);box-sizing:initial;color:var(--toast-text-color,#fff);display:flex;flex-direction:column;font-size:var(--toast-font-size,14px);justify-content:center;line-height:var(--toast-line-height,20px);white-space:pre-wrap}.van-toast__container{left:50%;max-width:var(--toast-max-width,70%);position:fixed;top:50%;transform:translate(-50%,-50%);width:-webkit-fit-content;width:fit-content}.van-toast--text{min-width:var(--toast-text-min-width,96px);padding:var(--toast-text-padding,8px 12px)}.van-toast--icon{min-height:var(--toast-default-min-height,88px);padding:var(--toast-default-padding,16px);width:var(--toast-default-width,88px)}.van-toast--icon .van-toast__icon{font-size:var(--toast-icon-size,36px)}.van-toast--icon .van-toast__text{padding-top:8px}.van-toast__loading{margin:10px 0}.van-toast--top{transform:translateY(-30vh)}.van-toast--bottom{transform:translateY(30vh)}
+</style>

+ 27 - 0
src/wxcomponents/vant/transition/index.vue

@@ -0,0 +1,27 @@
+<template>
+<uni-shadow-root class="vant-transition-index"><view v-if="inited" :class="'van-transition custom-class '+(classes)" :style="computed.rootStyle({ currentDuration, display, customStyle })" @transitionend="onTransitionEnd">
+  <slot></slot>
+</view></uni-shadow-root>
+</template>
+<wxs src="./index.wxs" module="computed"></wxs>
+<script>
+
+global['__wxRoute'] = 'vant/transition/index'
+import { VantComponent } from '../common/component';
+import { transition } from '../mixins/transition';
+VantComponent({
+    classes: [
+        'enter-class',
+        'enter-active-class',
+        'enter-to-class',
+        'leave-class',
+        'leave-active-class',
+        'leave-to-class',
+    ],
+    mixins: [transition(true)],
+});
+export default global['__wxComponents']['vant/transition/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-transition{transition-timing-function:ease}.van-fade-enter-active,.van-fade-leave-active{transition-property:opacity}.van-fade-enter,.van-fade-leave-to{opacity:0}.van-fade-down-enter-active,.van-fade-down-leave-active,.van-fade-left-enter-active,.van-fade-left-leave-active,.van-fade-right-enter-active,.van-fade-right-leave-active,.van-fade-up-enter-active,.van-fade-up-leave-active{transition-property:opacity,transform}.van-fade-up-enter,.van-fade-up-leave-to{opacity:0;transform:translate3d(0,100%,0)}.van-fade-down-enter,.van-fade-down-leave-to{opacity:0;transform:translate3d(0,-100%,0)}.van-fade-left-enter,.van-fade-left-leave-to{opacity:0;transform:translate3d(-100%,0,0)}.van-fade-right-enter,.van-fade-right-leave-to{opacity:0;transform:translate3d(100%,0,0)}.van-slide-down-enter-active,.van-slide-down-leave-active,.van-slide-left-enter-active,.van-slide-left-leave-active,.van-slide-right-enter-active,.van-slide-right-leave-active,.van-slide-up-enter-active,.van-slide-up-leave-active{transition-property:transform}.van-slide-up-enter,.van-slide-up-leave-to{transform:translate3d(0,100%,0)}.van-slide-down-enter,.van-slide-down-leave-to{transform:translate3d(0,-100%,0)}.van-slide-left-enter,.van-slide-left-leave-to{transform:translate3d(-100%,0,0)}.van-slide-right-enter,.van-slide-right-leave-to{transform:translate3d(100%,0,0)}
+</style>

+ 97 - 0
src/wxcomponents/vant/tree-select/index.vue

@@ -0,0 +1,97 @@
+<template>
+<uni-shadow-root class="vant-tree-select-index"><view class="van-tree-select" :style="'height: '+(utils.addUnit(height))">
+  <scroll-view scroll-y class="van-tree-select__nav">
+    <van-sidebar :active-key="mainActiveIndex" @change="onClickNav" custom-class="van-tree-select__nav__inner">
+      <van-sidebar-item v-for="(item,index) in (items)" :key="item.index" custom-class="main-item-class" active-class="main-active-class" disabled-class="main-disabled-class" :badge="item.badge" :dot="item.dot" :title="item.text" :disabled="item.disabled"></van-sidebar-item>
+    </van-sidebar>
+  </scroll-view>
+  <scroll-view scroll-y class="van-tree-select__content">
+    <slot name="content"></slot>
+    <view v-for="(item,index) in (subItems)" :key="item.id" :class="'van-ellipsis content-item-class '+(utils.bem('tree-select__item', { active: wxs.isActive(activeId, item.id), disabled: item.disabled }))+' '+(wxs.isActive(activeId, item.id) ? 'content-active-class' : '')+' '+(item.disabled ? 'content-disabled-class' : '')" :data-item="item" @click="onSelectItem">
+      {{ item.text }}
+      <van-icon v-if="wxs.isActive(activeId, item.id)" :name="selectedIcon" size="16px" class="van-tree-select__selected"></van-icon>
+    </view>
+  </scroll-view>
+</view></uni-shadow-root>
+</template>
+<wxs src="../wxs/utils.wxs" module="utils"></wxs><wxs src="./index.wxs" module="wxs"></wxs>
+<script>
+import VanIcon from '../icon/index.vue'
+import VanSidebar from '../sidebar/index.vue'
+import VanSidebarItem from '../sidebar-item/index.vue'
+global['__wxVueOptions'] = {components:{'van-icon': VanIcon,'van-sidebar': VanSidebar,'van-sidebar-item': VanSidebarItem}}
+
+global['__wxRoute'] = 'vant/tree-select/index'
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: [
+        'main-item-class',
+        'content-item-class',
+        'main-active-class',
+        'content-active-class',
+        'main-disabled-class',
+        'content-disabled-class',
+    ],
+    props: {
+        items: {
+            type: Array,
+            observer: 'updateSubItems',
+        },
+        activeId: null,
+        mainActiveIndex: {
+            type: Number,
+            value: 0,
+            observer: 'updateSubItems',
+        },
+        height: {
+            type: null,
+            value: 300,
+        },
+        max: {
+            type: Number,
+            value: Infinity,
+        },
+        selectedIcon: {
+            type: String,
+            value: 'success',
+        },
+    },
+    data: {
+        subItems: [],
+    },
+    methods: {
+        // 当一个子项被选择时
+        onSelectItem(event) {
+            const { item } = event.currentTarget.dataset;
+            const isArray = Array.isArray(this.data.activeId);
+            // 判断有没有超出右侧选择的最大数
+            const isOverMax = isArray && this.data.activeId.length >= this.data.max;
+            // 判断该项有没有被选中, 如果有被选中,则忽视是否超出的条件
+            const isSelected = isArray
+                ? this.data.activeId.indexOf(item.id) > -1
+                : this.data.activeId === item.id;
+            if (!item.disabled && (!isOverMax || isSelected)) {
+                this.$emit('click-item', item);
+            }
+        },
+        // 当一个导航被点击时
+        onClickNav(event) {
+            const index = event.detail;
+            const item = this.data.items[index];
+            if (!item.disabled) {
+                this.$emit('click-nav', { index });
+            }
+        },
+        // 更新子项列表
+        updateSubItems() {
+            const { items, mainActiveIndex } = this.data;
+            const { children = [] } = items[mainActiveIndex] || {};
+            this.setData({ subItems: children });
+        },
+    },
+});
+export default global['__wxComponents']['vant/tree-select/index']
+</script>
+<style platform="mp-weixin">
+@import '../common/index.css';.van-tree-select{display:flex;font-size:var(--tree-select-font-size,14px);position:relative;-webkit-user-select:none;user-select:none}.van-tree-select__nav{--sidebar-padding:12px 8px 12px 12px;background-color:var(--tree-select-nav-background-color,#f7f8fa);flex:1}.van-tree-select__nav__inner{height:100%;width:100%!important}.van-tree-select__content{background-color:var(--tree-select-content-background-color,#fff);flex:2}.van-tree-select__item{font-weight:700;line-height:var(--tree-select-item-height,44px);padding:0 32px 0 var(--padding-md,16px);position:relative}.van-tree-select__item--active{color:var(--tree-select-item-active-color,#ee0a24)}.van-tree-select__item--disabled{color:var(--tree-select-item-disabled-color,#c8c9cc)}.van-tree-select__selected{position:absolute;right:var(--padding-md,16px);top:50%;transform:translateY(-50%)}
+</style>

File diff suppressed because it is too large
+ 202 - 0
src/wxcomponents/vant/uploader/index.vue


+ 1 - 1
src/wxcomponents/vant/wxs/array.wxs

@@ -1,5 +1,5 @@
 function isArray(array) {
-  return array && array.constructor === 'Array';
+  return array && (array.constructor === 'Array' || (typeof Array !== 'undefined' && Array.isArray(array)));
 }
 
 module.exports.isArray = isArray;

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