Explorar el Código

8/6支付界面&优惠券列表,打包测试

Foystor hace 3 años
padre
commit
71b23f7a2f
Se han modificado 100 ficheros con 2194 adiciones y 604 borrados
  1. 0 11
      project.private.config.json
  2. 276 34
      src/pages/coupons/index.vue
  3. 316 19
      src/pages/user_center/confirmPay/index.vue
  4. 4 0
      src/pages/user_center/confirmPay/main.json
  5. 128 24
      src/pages/user_center/discountCard/index.vue
  6. 3 1
      src/pages/user_center/discountCard/main.json
  7. 1 1
      src/pages/user_center/recharge/index.vue
  8. 8 0
      src/requests/coupons.js
  9. 16 0
      src/utils/index.js
  10. 3 0
      src/utils/pay.js
  11. 13 5
      static/vant/action-sheet/index.js
  12. 25 23
      static/vant/action-sheet/index.wxml
  13. 0 0
      static/vant/action-sheet/index.wxss
  14. 53 48
      static/vant/area/index.js
  15. 3 1
      static/vant/area/index.wxml
  16. 8 0
      static/vant/area/index.wxs
  17. 18 28
      static/vant/button/index.js
  18. 11 26
      static/vant/button/index.wxml
  19. 39 0
      static/vant/button/index.wxs
  20. 62 52
      static/vant/calendar/calendar.wxml
  21. 20 2
      static/vant/calendar/components/header/index.js
  22. 10 4
      static/vant/calendar/components/month/index.js
  23. 1 1
      static/vant/calendar/components/month/index.wxml
  24. 6 2
      static/vant/calendar/components/month/index.wxs
  25. 74 22
      static/vant/calendar/index.js
  26. 3 9
      static/vant/calendar/index.wxml
  27. 4 3
      static/vant/calendar/utils.d.ts
  28. 5 0
      static/vant/calendar/utils.js
  29. 1 0
      static/vant/cell-group/index.js
  30. 4 2
      static/vant/cell-group/index.wxml
  31. 1 1
      static/vant/cell-group/index.wxss
  32. 3 1
      static/vant/cell/index.wxml
  33. 17 0
      static/vant/cell/index.wxs
  34. 0 0
      static/vant/cell/index.wxss
  35. 1 0
      static/vant/checkbox-group/index.d.ts
  36. 36 0
      static/vant/checkbox-group/index.js
  37. 3 0
      static/vant/checkbox-group/index.json
  38. 5 0
      static/vant/checkbox-group/index.wxml
  39. 1 0
      static/vant/checkbox-group/index.wxss
  40. 7 6
      static/vant/checkbox/index.js
  41. 13 2
      static/vant/checkbox/index.wxml
  42. 10 10
      static/vant/checkbox/index.wxs
  43. 1 1
      static/vant/checkbox/index.wxss
  44. 3 3
      static/vant/circle/canvas.d.ts
  45. 14 8
      static/vant/circle/index.js
  46. 2 19
      static/vant/col/index.js
  47. 2 1
      static/vant/col/index.wxml
  48. 18 0
      static/vant/col/index.wxs
  49. 6 0
      static/vant/collapse-item/animate.d.ts
  50. 70 0
      static/vant/collapse-item/animate.js
  51. 1 0
      static/vant/collapse-item/index.d.ts
  52. 59 0
      static/vant/collapse-item/index.js
  53. 6 0
      static/vant/collapse-item/index.json
  54. 44 0
      static/vant/collapse-item/index.wxml
  55. 1 0
      static/vant/collapse-item/index.wxss
  56. 1 0
      static/vant/collapse/index.d.ts
  57. 44 0
      static/vant/collapse/index.js
  58. 3 0
      static/vant/collapse/index.json
  59. 3 0
      static/vant/collapse/index.wxml
  60. 1 0
      static/vant/collapse/index.wxss
  61. 7 2
      static/vant/common/component.d.ts
  62. 7 63
      static/vant/common/component.js
  63. 21 0
      static/vant/common/relation.d.ts
  64. 64 0
      static/vant/common/relation.js
  65. 21 9
      static/vant/common/utils.d.ts
  66. 35 17
      static/vant/common/utils.js
  67. 1 1
      static/vant/common/validator.d.ts
  68. 1 0
      static/vant/common/validator.js
  69. 5 0
      static/vant/common/version.d.ts
  70. 21 4
      static/vant/common/version.js
  71. 1 0
      static/vant/config-provider/index.d.ts
  72. 9 0
      static/vant/config-provider/index.js
  73. 3 0
      static/vant/config-provider/index.json
  74. 5 0
      static/vant/config-provider/index.wxml
  75. 29 0
      static/vant/config-provider/index.wxs
  76. 11 12
      static/vant/datetime-picker/index.js
  77. 37 25
      static/vant/definitions/index.d.ts
  78. 11 20
      static/vant/dialog/dialog.d.ts
  79. 9 1
      static/vant/dialog/dialog.js
  80. 31 26
      static/vant/dialog/index.js
  81. 1 1
      static/vant/dialog/index.json
  82. 12 12
      static/vant/dialog/index.wxml
  83. 7 28
      static/vant/divider/index.js
  84. 3 2
      static/vant/divider/index.wxml
  85. 18 0
      static/vant/divider/index.wxs
  86. 1 0
      static/vant/dropdown-item/index.d.ts
  87. 111 0
      static/vant/dropdown-item/index.js
  88. 8 0
      static/vant/dropdown-item/index.json
  89. 48 0
      static/vant/dropdown-item/index.wxml
  90. 1 0
      static/vant/dropdown-item/index.wxss
  91. 5 0
      static/vant/dropdown-item/shared.d.ts
  92. 1 0
      static/vant/dropdown-item/shared.js
  93. 1 0
      static/vant/dropdown-menu/index.d.ts
  94. 112 0
      static/vant/dropdown-menu/index.js
  95. 3 0
      static/vant/dropdown-menu/index.json
  96. 23 0
      static/vant/dropdown-menu/index.wxml
  97. 16 0
      static/vant/dropdown-menu/index.wxs
  98. 1 0
      static/vant/dropdown-menu/index.wxss
  99. 0 10
      static/vant/empty/index.js
  100. 2 1
      static/vant/empty/index.wxml

+ 0 - 11
project.private.config.json

@@ -29,17 +29,6 @@
           "pathName": "pages/user_center/recharge/main",
           "query": "",
           "scene": null
-        },
-        {
-          "name": "pages/user_center/confirmPay/main",
-          "pathName": "pages/user_center/confirmPay/main",
-          "query": "",
-          "scene": null
-        },
-        {
-          "name": "pages/user_center/discountCard/main",
-          "pathName": "pages/user_center/discountCard/main",
-          "scene": null
         }
       ]
     }

+ 276 - 34
src/pages/coupons/index.vue

@@ -1,62 +1,248 @@
 <template>
   <div id="game_record_container">
-    <van-tabs :active="active" @change="" color="#4B3AB0">
+    <van-tabs :active="active" @change="clearShow" color="#4B3AB0" line-width=54px>
       <van-tab title="待领取" name="0">
-        <div class="quan_list" v-if="rec_list.length > 0">
+        <div class="quan_list margin-top-sm" v-if="rec_list.length > 0">
+          <text class="padding-left">共{{rec_list.length}}张</text>
 
-          <div class="quan_container" v-for="(item,index) in rec_list" :key="index">
+          <div v-for="(item,index) in rec_list" :key="index">
+            <div class="quan_container" >
             <van-row gutter="10">
-              <van-col span="14" offset="1">
-                <div class="padding-top-sm">
+              <van-col span="15" offset="1">
+                <div class="padding-top">
                   <text class="title">{{ item.name }}</text>
                 </div>
-                <div>
-                  <text class="subtitle">{{ item.end_time }}之前领取有效</text>
+                <div v-if="item.validity_time.type==0"> 
+                  <text class="subtitle text-sm">{{ item.validity_time.start_time }} 至 {{ item.validity_time.end_time }} 领取有效</text>
+                </div>
+                
+                <div v-if="item.validity_time.type==1">
+                  <text class="subtitle text-sm">{{ item.validity_time.time }} 之前领取有效</text>
                 </div>
+ 
+                <van-row gutter="9"> 
+                  <van-col span="17" >
+                   <!-- 核销券 -->
+                   <view class="padding-tb" v-if="item.type==1">
+                     <text class="time">{{ item.discount.time }}</text>
+                     <text class="time_text" v-if="item.discount.type==0">分钟</text>
+                     <text class="time_text" v-if="item.discount.type==1">次</text>
+                   </view>
+
+                   <!-- 满减券 -->
+                   <view class="padding-tb" v-if="item.type==2">
+                     <text class="time_text">满</text>
+                     <text class="time">{{ item.discount.full }}</text>
+                     <text class="time_text">减</text>
+                     <text class="time">{{ item.discount.reduce }}</text>
+                   </view>
+
+                   <!-- 折扣券 -->
+                   <view class="padding-tb" v-if="item.type==3">
+                     <text class="time_text">打</text>
+                     <text class="time">{{ item.discount.discount*10 }}</text>
+                     <text class="time_text">折</text>
+                   </view>
+
+                   <!-- 随机券 -->
+                   <view class="padding-tb" v-if="item.type==4">
+                     <text class="time_text">随机</text>
+                     <text class="time">{{ item.discount.start }}</text>
+                     <text class="time_text">至</text>
+                     <text class="time">{{ item.discount.end }}</text>
+                     <text class="time_text">元</text>
+                   </view>
+                 </van-col> 
+
+                  <van-col span="7" >
+                    <view class="margin-top-xl" @click="ruleShow(item.coupon_category_id)">
+                      <text class="text-sm text-grey rule">使用规则</text>
+                    </view>
+                  </van-col>  
+               </van-row>
 
-                <view class="padding-tb">
-                  <text class="time">{{ item.play_time }}</text>
-                  <text class="time_text">分钟</text>
-                </view>
               </van-col>
-              <van-col span="5" offset="4" class="" @click="get_ticket(item.coupon_category_id)">
+              <van-col span="5" offset="3" class="" @click="get_ticket(item.coupon_category_id)">
                 <view class="get_ticket_text">领取</view>
               </van-col>
             </van-row>
-          </div>
+           </div>
+                     
+           <!--    描述-->
+           <view v-if="is_ruleShow == item.coupon_category_id">
+             <view class="flex justify-center">
+              <view
+              class="desc"
+              v-html="item.explain"
+              >
 
+             </view>
+            </view>
+          </view>
+         </div>
 
         </div>
-
         <van-empty image="error" description="暂无可领券" v-else/>
       </van-tab>
+
       <van-tab title="已领取" name="1">
-        <div class="quan_list">
+        <div class="quan_list margin-top-sm ">
+          <text class="padding-left">共{{cp_list.length}}张</text>
 
-          <div class="quan_container_gray" v-for="(item,index) in cp_list" :key="index">
+          <div v-for="(item,index) in cp_list" :key="index">
+            <div class="quan_container_get">
             <van-row gutter="10">
-              <van-col span="14" offset="1">
-                <div class="padding-top-sm">
+              <van-col span="15" offset="1">
+                <div class="padding-top">
                   <text class="title">{{ item.name }}</text>
                 </div>
+
                 <div>
-                  <!--                  <text class="subtitle">{{ item.validity_time }}之前领取有效</text>-->
+                  <text class="subtitle text-sm">{{ item.start_time }} 至 {{ item.end_time }} 可使用</text>
                 </div>
+               
+                <van-row gutter="9"> 
+                  <van-col span="17" >
+                    <!-- 核销券 -->
+                    <view class="padding-tb" v-if="item.type==1">
+                      <text class="time">{{ item.time }}</text>
+                      <text class="time_text" v-if="item.discount_type==0">分钟</text>
+                      <text class="time_text" v-if="item.discount_type==1">次</text>
+                    </view>
+
+                    <!-- 满减券 -->
+                    <view class="padding-tb" v-if="item.type==2">
+                      <text class="time_text">满</text>
+                      <text class="time">{{ item.full }}</text>
+                      <text class="time_text">减</text>
+                      <text class="time">{{ item.reduce }}</text>
+                    </view>
+
+                    <!-- 折扣券 -->
+                    <view class="padding-tb" v-if="item.type==3">
+                      <text class="time_text">打</text>
+                      <text class="time">{{ item.discount*10 }}</text>
+                      <text class="time_text">折</text>
+                    </view>
+
+                    <!-- 随机券 -->
+                    <view class="padding-tb" v-if="item.type==4">
+                      <text class="time_text">减</text>
+                      <text class="time">{{ item.random }}</text>
+                      <text class="time_text">元</text>
+                    </view>
+                  </van-col> 
+
+                  <van-col span="7" >
+                    <view class="margin-top-xl" @click="ruleShow(item.coupon_category_id)">
+                      <text class="text-sm text-grey rule">使用规则</text>
+                    </view>
+                  </van-col>  
+                </van-row>
 
-                <view class="padding-tb">
-                  <text class="time">10</text>
-                  <text class="time_text">分钟</text>
-                </view>
               </van-col>
-              <van-col span="5" offset="3">
+              <van-col span="5" offset="2">
                 <view class="get_ticket_text">已领取</view>
               </van-col>
             </van-row>
+            </div>
+
+            <!--    描述-->
+           <view v-if="is_ruleShow == item.coupon_category_id">
+             <view class="flex justify-center">
+              <view
+              class="desc"
+              v-html="item.explain"
+              >
+
+             </view>
+            </view>
+          </view>
+          </div>
+
+
+        </div>
+      </van-tab>
+
+      <van-tab title="已过期" name="2">
+        <div class="quan_list margin-top-sm ">
+          <text class="padding-left">共{{ov_list.length}}张</text>
+
+          <div v-for="(item,index) in ov_list" :key="index">
+            <div class="quan_container_gray">
+            <van-row gutter="10">
+              <van-col span="15" offset="1">
+                <div class="padding-top">
+                  <text class="title">{{ item.name }}</text>
+                </div>
+
+                <div>
+                  <text class="subtitle text-sm">{{ item.start_time }} 至 {{ item.end_time }} 可使用</text>
+                </div>
+              
+               <van-row gutter="9"> 
+                  <van-col span="17" >
+                    <!-- 核销券 -->
+                    <view class="padding-tb" v-if="item.type==1">
+                      <text class="time">{{ item.time }}</text>
+                      <text class="time_text" v-if="item.discount_type==0">分钟</text>
+                      <text class="time_text" v-if="item.discount_type==1">次</text>
+                    </view>
+
+                    <!-- 满减券 -->
+                     <view class="padding-tb" v-if="item.type==2">
+                      <text class="time_text">满</text>
+                      <text class="time">{{ item.full }}</text>
+                      <text class="time_text">减</text>
+                      <text class="time">{{ item.reduce }}</text>
+                    </view>
+
+                    <!-- 折扣券 -->
+                    <view class="padding-tb" v-if="item.type==3">
+                      <text class="time_text">打</text>
+                      <text class="time">{{ item.discount*10 }}</text>
+                      <text class="time_text">折</text>
+                    </view>
+
+                    <!-- 随机券 -->
+                    <view class="padding-tb" v-if="item.type==4">
+                      <text class="time_text">减</text>
+                      <text class="time">{{ item.random }}</text>
+                      <text class="time_text">元</text>
+                    </view>
+                  </van-col> 
+
+                  <van-col span="7" >
+                    <view class="margin-top-xl" @click="ruleShow(item.coupon_category_id)">
+                      <text class="text-sm text-grey rule">使用规则</text>
+                    </view>
+                  </van-col>  
+                </van-row>
+
+              </van-col>
+              <van-col span="5" offset="2">
+                <view class="get_ticket_text">已过期</view>
+              </van-col>
+            </van-row>
+            </div>
+
+             <!--    描述-->
+           <view v-if="is_ruleShow == item.coupon_category_id">
+             <view class="flex justify-center">
+              <view
+              class="desc"
+              v-html="item.explain"
+              >
+
+             </view>
+            </view>
+          </view>
           </div>
 
 
         </div>
       </van-tab>
+
     </van-tabs>
     <van-toast id="van-toast"/>
 
@@ -67,8 +253,8 @@
 import Toast from '../../../static/vant/toast/toast';
 
 
-import {couponReceive, getCouponList, getCouponReceiveList} from "../../requests/coupons";
-import {formatValidityTime} from '@/utils/index'
+import {couponReceive, getCouponList, getCouponReceiveList, getOverdueCouponList} from "../../requests/coupons";
+import {timestampTwoNum} from '@/utils/index'
 
 var $this
 export default {
@@ -76,20 +262,36 @@ export default {
   components: {},
   data() {
     return {
-      active: '1',
+      is_ruleShow: 0,
+      active: '0',
       rec_list: [],
       cp_list: [],
+      ov_list:[],
       limit: 10
     }
   },
   methods: {
-    //获取已优惠券列表
+    //获取已领取优惠券列表
     get_coupon_list() {
       getCouponList($this.limit).then((res) => {
         let $res = res.data;
         $this.cp_list = $res.data;
         $this.cp_list.forEach(($val, $index) => {
-          $val['validity_time'] = formatValidityTime($val['validity_time'])
+          $val['end_time'] = timestampTwoNum($val['end_time'])
+          $val['start_time'] = timestampTwoNum($val['start_time'])
+          $val['random'] = parseInt($val['random'])
+        })
+      })
+    },
+    //已过期优惠券列表
+    get_overdue_list() {
+      getOverdueCouponList($this.limit).then((res) => {
+        let $res = res.data;
+        $this.ov_list = $res.data;
+        $this.ov_list.forEach(($val, $index) => {
+          $val['end_time'] = timestampTwoNum($val['end_time'])
+          $val['start_time'] = timestampTwoNum($val['start_time'])
+          $val['random'] = parseInt($val['random'])
         })
       })
     },
@@ -99,7 +301,9 @@ export default {
         let $res = res.data;
         $this.rec_list = $res.data.list;
         $this.rec_list.forEach(($val, $index) => {
-          $val['end_time'] = formatValidityTime($val['end_time'])
+          $val.validity_time['end_time'] = timestampTwoNum($val.validity_time['end_time'])
+          $val.validity_time['start_time'] = timestampTwoNum($val.validity_time['start_time'])
+          $val.validity_time['time'] = timestampTwoNum($val.validity_time['time'])
         })
       })
     },
@@ -113,21 +317,38 @@ export default {
             onClose() {
               $this.get_coupon_list()
               $this.get_rec_coupon_list()
+              $this.get_overdue_list()
             }
           })
         } else {
           Toast.fail($res.errmsg)
         }
       })
+    },
+    //使用规则
+    ruleShow($id){
+      // console.log($id);
+      if ($this.is_ruleShow == $id) {
+        $this.is_ruleShow = 0;
+      } else {
+        $this.is_ruleShow = $id;
+      }
+    },
+    clearShow(){
+      $this.is_ruleShow = 0;
     }
   },
   mounted() {
     $this.get_coupon_list()
     $this.get_rec_coupon_list()
+    $this.get_overdue_list()
   },
   created() {
     $this = this
-  }
+  },
+  onUnload(){
+    $this.is_ruleShow = 0
+  },
 }
 </script>
 
@@ -139,7 +360,16 @@ export default {
   background-size: 100% 100%;
   width: 340px;
   height: 115px;
-  margin: 10px auto;
+  margin: 3px auto;
+}
+
+.quan_container_get{
+  background-image: url("https://img.shuimuai.com/discount_get.png");
+  background-position: center;
+  background-size: 100% 100%;
+  width: 340px;
+  height: 115px;
+  margin: 3px auto;
 }
 
 .quan_container_gray {
@@ -148,7 +378,7 @@ export default {
   background-size: 100% 100%;
   width: 340px;
   height: 115px;
-  margin: 10px auto;
+  margin: 3px auto;
 }
 
 /*标题*/
@@ -171,7 +401,7 @@ export default {
 
 /*分钟数*/
 .time {
-  font-size: 36px;
+  font-size: 34px;
   font-weight: 400;
   color: #030000;
   line-height: 24px;
@@ -194,6 +424,18 @@ export default {
   margin: 45px 0px;
 }
 
+/*使用规则*/
+.rule{
+  text-decoration: underline;
+}
+
+.desc {
+  width: 320px;
+  font-size: 12px;
+  color: #6B6B6B;
+  line-height: 18px;
+  margin-bottom: 26px
+}
 .quan_list {
 }
 </style>

+ 316 - 19
src/pages/user_center/confirmPay/index.vue

@@ -2,7 +2,7 @@
     <div class=" padding-tb-xl flex padding-left-xl boxVer">
       <view class="upBox">
         <view class="title">
-          <text class="text-sm font">已选商品&emsp;水母星球-{{ data.goods_name }}</text>
+          <text class="text-sm font">已选商品&emsp;水母星球{{ data.goods_name }}</text>
           <br>
         </view>
         <view class="title">
@@ -23,22 +23,23 @@
             </div>
             <!-- <div class="betweenBox"></div> -->
             <div class="flex align-center"  @click="to_discountCard">
-              <text class="text-lg text-red">-¥{{data.reduce}}&nbsp;</text>
+              <text class="text-lg text-red">-¥{{data.reduce - isReduce + add_price}}&nbsp;</text>
               <text class="text-gray rightArrow" :class="'cuIcon-right'"></text>
              </div>
             <br>
         </view>
        
-        <view v-if="data.coupon.length == 0" class="padding-tb">
+        <view v-if="data.coupon.length == 0 & data.discount * 10 !== 10" class="padding-tb">
           <text class="text-lg text-red" style="font-weight: bold;">折扣&emsp;{{ data.discount * 10 }}折</text>
           <br>
         </view>
         <view v-if="data.goods_id < 4" class="padding-tb">
            <label class="radio" @click='radiocon'>
-               <!-- <checkbox id="checkBox" class='round orange' :class="checked?'checked':''" :checked="checked?true:false" @click="setPrice"
-			 	value='1'></checkbox> -->
-                <checkbox  :checked="data.check" id="radios"></checkbox>
-               <text class="text-lg text-orange">&emsp;加购{{ data.add_price }}元,获得有效期增加{{ data.add_month }}个月</text>
+                <!-- <checkbox  :checked="data.check" id="radios"></checkbox> -->
+                <van-checkbox :value="checked" @click="onChange" checked-color="#FF720E">
+                   <text class="text-lg text-orange">加购{{ data.add_price }}元,获得有效期增加{{ data.add_month }}个月</text>
+                </van-checkbox>
+              
            </label>
 
             <br>
@@ -50,7 +51,7 @@
         <view class="flex padding-tb-xl justify-center align-center ">
           <view class="order_price_container">
             <text class="text-sm font">实付(元)&emsp;</text>
-            <text class="mine_min">{{ data.total_price }}</text>
+            <text class="mine_min">{{ data.total_price + isAdd }}</text>
           </view>
         </view>  
         <view class="flex padding-tb justify-center align-center">
@@ -61,35 +62,300 @@
           >立即充值</button>
         </view>
       </view>  
+
+      <!--    充值失败-->
+    <van-popup
+      :show="err_show"
+      @close="close_err_pop"
+      round
+      :close-on-click-overlay="false"
+    >
+      <div class="err_container flex flex-direction align-center justify-around padding-top-xl padding-bottom-sm">
+        <view>
+          <text class="payTitle">
+            充值失败,请再次尝试
+          </text>
+        </view>
+        <img
+          src="https://img.shuimuai.com/web/sign_notimeJfish.png"
+          class="err_img"
+          alt=""
+        >
+        <div class="button_group flex justify-around">
+          <button
+            class="cu-btn bg-gray text-white lg margin-right-lg btnFail"
+            @click="close_err_pop"
+          >取消支付</button>
+          <button
+            class="cu-btn  bg-primary text-white lg btnFail"
+            @click="repay"
+            :disabled="btn_disabled"
+          >再次支付</button>
+        </div>
+      </div>
+    </van-popup>
+
+    <!--    充值成功-->
+    <van-popup
+      :show="success_show"
+      @close="close_success_pop"
+      round
+      :close-on-click-overlay="false"
+    >
+      <div class="err_container flex flex-direction align-center justify-around ext_container padding-top-lg padding-bottom">
+        <img
+          src="https://img.shuimuai.com/web/boyya.png"
+          class="boy_logo"
+          alt=""
+        >
+        <view>
+          <text class="payTitle" v-if="!payment_info.msg">
+            充值成功
+          </text>
+
+          <text class="payTitle" v-if="payment_info.msg">
+            {{payment_info.msg}}
+          </text>
+        </view>
+       
+        <div class="button_group flex justify-around">
+          <!--          <button class="cu-btn bg-gray text-white lg" @click="close_success_pop">以后再填</button>-->
+          <!--          <button class="cu-btn  bg-primary text-white lg" @click="to_write_address">填写地址</button>-->
+          <button
+            class="cu-btn  bg-primary text-white lg"
+            @click="to_index"
+          >充值成功</button>
+        </div>
+      </div>
+    </van-popup>
     </div>
 </template>
 
 <script>
 let $this;
+import pay from '../../../utils/pay.js'
+import { createOrder, deleteOrder } from "../../../requests/orders";
 export default {
   data() {
     return {
-      data: {
-        check: false,
-      },
+      order_confirm: false,
+      err_show: false,
+      success_show: false,
+      checked: false,
+      data: {},
+      isReduce:0,
+      add_price:0,
+      isAdd:0,
+      is_add: Number,
+      //支付信息
+      payment_info: {},
+      //订单编号
+      order_sn: "",
+      btn_disabled: false,
     };
   },
   onLoad(options) {
-    this.data = JSON.parse(options.data);
-    console.log("数据", this.data);
-    $this = this;
+    this.data = JSON.parse(options.data)
+    console.log("数据", this.data)
+    $this = this
+    $this.checked = false
+    $this.isAdd = 0
+    $this.add_price = 0
+    $this.isReduce =0
+    $this.is_add = 0
+  },
+  onUnload(){
+    $this.isAdd = 0
+    $this.add_price = 0
+    $this.isReduce =0
+  },
+  onShow(){
+    pay.$on('cardInfo',res =>{
+      $this.data.coupon = res
+      $this.data.reduce = res.reduce
+      $this.data.total_price = $this.data.price-res.reduce
+
+      if($this.checked==true){
+        if($this.data.coupon.discount){        //打折券
+          $this.isAdd = $this.data.add_price*$this.data.coupon.discount
+          $this.add_price = $this.data.add_price
+          $this.isReduce =  $this.isAdd
+        }else if($this.data.discount){         //没有券,活动打折
+          $this.isAdd = $this.data.add_price*$this.data.discount
+          $this.add_price = $this.data.add_price
+          $this.isReduce =  $this.isAdd
+        }else{                                //其它券
+          $this.isAdd = $this.data.add_price
+          $this.add_price = 0
+          $this.isReduce =  0
+        }
+      }else{
+        $this.isAdd = 0
+        $this.add_price = 0
+        $this.isReduce =  0
+      }
+    })
   },
   methods: {
     to_discountCard() {
       var deliver = JSON.stringify(this.data);
       mpvue.navigateTo({
-        url: "/pages/user_center/discountCard/main?deliver=" + deliver,
+        url: "/pages/user_center/discountCard/main?deliver=" + deliver +"&isAdd=" + $this.add_price,
       });
     },
-    radiocon() {
-      //   $this.check = !$this.check;
-      $this.data.check = !$this.data.check;
-      console.log("用户打勾的是 ", $this.data.check);
+    onChange() {
+      $this.checked = !$this.checked
+      if($this.checked==true){
+        if($this.data.coupon.discount){        //打折券
+          $this.isAdd = $this.data.add_price*$this.data.coupon.discount
+        }else if($this.data.discount){         //没有券,活动打折
+          $this.isAdd = $this.data.add_price*$this.data.discount
+        }else{                                //其它券
+          $this.isAdd = $this.data.add_price
+          $this.add_price = 0
+          $this.isReduce =  0
+        }
+        $this.add_price = $this.data.add_price
+        $this.isReduce =  $this.isAdd
+        $this.is_add = 1
+      }else{
+        $this.isAdd = 0
+        $this.add_price = 0
+        $this.isReduce =  0
+        $this.is_add = 0
+ 
+      }
+    },
+    //关闭确认订单
+    close_order_confirm() {
+      $this.order_confirm = false;
+    },
+    //关闭充值失败窗口
+    close_err_pop() {
+      $this.err_show = false;
+    },
+    //取消充值
+    cancel_recharge() {
+      $this.close_err_pop();
+      deleteOrder($this.order_sn).then(
+        (res) => {
+          let $res = res.data;
+        },
+        (err) => {
+          console.log("删除订单错误", err);
+        }
+      );
+    },
+    // 打开充值成功窗口
+    open_success_window() {
+      $this.success_show = true;
+    },
+    //关闭充值成功窗口
+    close_success_pop() {
+      $this.success_show = false;
+    },
+    //再次付款
+    repay() {
+      $this.btn_disabled = true;
+      let $payment = $this.payment_info;
+      wx.requestPayment({
+        timeStamp: $payment.timeStamp,
+        nonceStr: $payment.nonceStr,
+        package: $payment.package,
+        signType: $payment.signType,
+        paySign: $payment.sign,
+        success(res) {
+          //支付成功
+          console.log("success支付成功调用:", res);
+          //关闭确认订单窗口
+          $this.close_order_confirm();
+          $this.close_success_pop();
+          //打开成功充值窗口
+          $this.open_success_window();
+        },
+        fail(res) {
+          console.log("success支付失败调用:", res);
+
+          $this.cancel_recharge();
+          $this.close_order_confirm();
+          $this.err_show = true;
+        },
+        complete() {
+          $this.btn_disabled = false;
+        },
+      });
+    },
+    // 成功支付
+    success_pay() {
+      $this.btn_disabled = true
+      let $params
+
+      if($this.data.coupon.length!==0){
+         // 支付成功后得回调方法
+        $params = {
+          goods_id: $this.data.goods_id,
+          buy_num: 1,
+          is_add: $this.is_add,
+          coupon_id: $this.data.coupon.coupon_id
+        };
+      }else{
+         $params = {
+           goods_id: $this.data.goods_id,
+           buy_num: 1,
+           is_add: $this.is_add,
+         };
+      }
+      
+      wx.login({
+        success(res1) {
+          console.log("微信登陆", res1.code);
+          let $code = res1.code;
+          $params["js_code"] = $code;
+          createOrder($params).then(
+            (res) => {
+              let $data = res.data;
+              let $payment = $data.data;
+              $this.order_sn = $payment["sn"];
+              $this.payment_info = $payment;
+              wx.requestPayment({
+                timeStamp: $payment.timeStamp,
+                nonceStr: $payment.nonceStr,
+                package: $payment.package,
+                signType: $payment.signType,
+                paySign: $payment.sign,
+                success(res) {
+                  //支付成功
+                  console.log("success", res);
+                  //关闭确认订单窗口
+                  $this.close_order_confirm();
+                  $this.close_success_pop();
+                  //打开成功充值窗口
+                  $this.open_success_window();
+                },
+                fail(res) {
+                  console.log("fail", res);
+                  $this.cancel_recharge();
+                  $this.close_order_confirm();
+                  $this.err_show = true;
+                },
+                complete() {
+                  $this.btn_disabled = false;
+                },
+              });
+            },
+            (err) => {
+              console.log(err);
+            }
+          );
+        },
+      });
+
+      //  接收回调方法后弹出支付成功
+    },
+    to_index() {
+      mpvue.reLaunch({
+        url: "/pages/index/main",
+      });
     },
   },
 };
@@ -135,4 +401,35 @@ export default {
   background-size: 100% 100%;
   margin-right: 11px;
 }
+.order_confirm,
+.err_container {
+  width: 344px;
+  height: 312px;
+}
+.err_img {
+  width: 73px;
+  height: 83px;
+}
+.ext_container {
+  height: 320px;
+  /*background-image: url("https://img.shuimuai.com/web/boyya_bg.png");*/
+  /*background-size: 100% 100%;*/
+  /*background-position: center;*/
+  background-color: rgba(255, 255, 255, 0);
+}
+.boy_logo {
+  width: 136px;
+  height: 150px;
+}
+.btnFail{
+  width: 146px;
+  height: 44px;
+}
+.payTitle {
+  font-size: 18px;
+  font-weight: bold;
+  color: #6B6B6B;
+  line-height: 18px;
+  font-family: Microsoft YaHei;
+}
 </style>

+ 4 - 0
src/pages/user_center/confirmPay/main.json

@@ -1,5 +1,9 @@
 {
     "usingComponents": {
+      "van-checkbox": "../../../../static/vant/checkbox/index",
+      "van-row": "../../../static/vant/row/index",
+      "van-col": "../../../static/vant/col/index",
+      "van-popup": "../../../static/vant/popup/index"
     }
   }
   

+ 128 - 24
src/pages/user_center/discountCard/index.vue

@@ -1,9 +1,9 @@
 <template>
     <div>
         <div class="quan_list">
+          <div  v-for="(item,index) in couponData" :key="index">
+            <div class="quan_container shadow bg-white">
 
-          <div class="quan_container shadow bg-white" v-for="(item,index) in couponData" :key="index">
-            
               <van-row gutter="9">
               <van-col span="12" offset="1">
                 <div class="padding-top-sm">
@@ -20,67 +20,156 @@
               </van-col>
 
               <van-col span="9" offset="1" >
-                  <div class="padding-top-sm text-lg padding-bottom-xl margin-bottom-xs">
+                  <div class="padding-top-sm text-lg padding-bottom-xl margin-bottom-xs" v-if="item.type*1!==3">
                       <view class="subtitle text-bold">可抵扣&nbsp;
                         <text class="text-red">¥{{ item.reduce }}</text>
                       </view>
                  </div>
-                  
+
+                 <div class="padding-top-sm text-lg padding-bottom-xl margin-bottom-xs" v-if="item.type==3">
+                      <view class="subtitle text-bold">可折扣&nbsp;
+                        <text class="text-red">{{ item.discount * 10 }}折</text>
+                      </view>
+                 </div>
               </van-col>
              
-             
                 <div class="cartLeft"></div>
+
                 <van-row gutter="9">
                     <van-col span="12" offset="1">
-                        
-                    </van-col>      
-                    <van-col span="9" offset="1" >
-                      <text class="text-sm text-grey rule">使用规则</text>
+                      <van-radio-group :value="radio" @change="changeCard">
+                        <van-radio :name="item.coupon_id"  icon-size="17px" checked-color="#6858C4"></van-radio>
+                      </van-radio-group>
+                    </van-col>  
+
+                    <van-col span="4" offset="6" >
+                      <text class="text-sm text-grey rule" @click="ruleShow(item.coupon_id)">使用规则</text>
                     </van-col>  
                 </van-row>
              
             </van-row>
-          
-        </div>
+            </div>
 
+             <!--    描述-->
+           <view v-if="is_ruleShow == item.coupon_id">
+             <view class="flex justify-center">
+              <view
+              class="desc"
+              v-html="item.explain"
+              >
 
+             </view>
+            </view>
+          </view>
+          
+          </div>       
         </div>
+        <view class="cu-bar tabbar bg-white shadow foot btmBar">
+           <view class='margin-left'>已优惠
+              <text class="text-xl text-red text-bold">¥{{discount}}</text>
+           </view>
+
+           <button class="cu-btn confirmBtn text-white text-lg margin-right" @click="backPay">确定</button>
+        </view>
     </div>
 </template>
 
 <script>
+let $this
+let add
+import pay from '../../../utils/pay.js'
 import { formatTimeAnother } from "../../../utils/index.js";
 export default {
     data() {
       return {
+        is_ruleShow: 0,
+        is_ruleShow:false,
         couponData: {},
-        deliver:{}
+        deliver:{},
+        radio:'',
+        discount: Number,
       };
     },
     onLoad(options) {
-       let $params = JSON.parse(options.deliver);
-       console.log("参数",$params)
-       this.$fly.get("https://testapi.shuimuai.com/coupon/choose-coupon?price=" +$params.price+"&goods_id=" +$params.goods_id)
+       $this=this
+       let $params = JSON.parse(options.deliver)
+       $this.radio = $params.coupon.coupon_id
+       add = options.isAdd * 1
+       let price = $params.total_price + add
+       this.$fly.get("https://testapi.shuimuai.com/coupon/choose-coupon?price=" + price +"&goods_id=" +$params.goods_id)
            .then((res)=>{
                console.log('优惠券',res.data.data)
-               let $data = res.data.data
-               this.couponData = $data
+               this.couponData = res.data.data
                this.couponData.forEach(($val, $index) => {
                     $val['start_time'] = formatTimeAnother($val['start_time'])
                     $val['end_time'] = formatTimeAnother($val['end_time'])
                     if($val['type']==3){
+                      if( add ==0){
+                         $val["reduce"] = Math.round(($params.price-$params.price*$val["discount"])*100)/100
+                         $val["reduce_dis"] = Math.round(($params.price-$params.price*$val["discount"])*100)/100
+                      }else {
                         $val["reduce"] = Math.round(($params.price-$params.price*$val["discount"])*100)/100
+                        $val["reduce_dis"] = Math.round((($params.price+ add) -($params.price+ add)*$val["discount"])*100)/100
+                      }
+                        
                     }else if($val['type']==2){
                         $val["reduce"] = $val["reduce"]
                     }else if($val['type']==4){
                         $val["reduce"] = $val["random"]
                     }
                })
+               for(let a of $this.couponData){
+                 if(a.coupon_id == $this.radio){
+                   if(a.type==3){
+                    $this.discount= a.reduce_dis
+                   }else{
+                    $this.discount= a.reduce
+                   }
+                 }
+               }
            })
            .catch((err)=>{
                console.log(err)
            })
-  },
+
+    },
+    onUnload(){
+      $this.is_ruleShow = 0
+    },
+    methods: {
+      changeCard(event){
+        // console.log(event)
+         $this.radio = event.mp.detail
+         for(let i of $this.couponData){
+           if(i.coupon_id==$this.radio){
+             if(i.type==3){
+               $this.discount = i.reduce_dis      
+             }else{
+               $this.discount= i.reduce
+             }
+           }
+         }
+      },
+      backPay(){
+         for(let i of $this.couponData){
+            if(i.coupon_id==$this.radio){
+              pay.$emit('cardInfo',i)
+              wx.navigateBack({
+                 delta: 1
+              });
+            }
+         }
+      },
+      //使用规则
+    ruleShow($id){
+      // console.log($id);
+      if ($this.is_ruleShow == $id) {
+        $this.is_ruleShow = 0;
+      } else {
+        $this.is_ruleShow = $id;
+      }
+    },
+    },
 }
 </script>
 
@@ -91,16 +180,31 @@ export default {
   background-size: 100% 100%;
   width: 340px;
   height: 115px;
-  margin: 10px auto;
+  margin: 7px auto;
 }
 .cartLeft{
-width: 85%;
-margin: 10px auto;
-height: 82px;
-border-bottom: 1rpx dashed #a7a8a8;
+  width: 89%;
+  margin: 9px auto;
+  height: 82px;
+  border-bottom: 1rpx dashed #a7a8a8;
 
 }
 .rule{
-    text-decoration: underline;
+  text-decoration: underline;
+}
+.btmBar{
+  height: 65px;
+}
+.confirmBtn{
+  width: 125px;
+  height: 44px;
+  background: #6858C4;
+}
+.desc{
+  width: 330px;
+  font-size: 12px;
+  color: #6B6B6B;
+  line-height: 18px;
+  margin-bottom: 26px
 }
 </style>

+ 3 - 1
src/pages/user_center/discountCard/main.json

@@ -2,6 +2,8 @@
     "usingComponents": {
       "van-row": "../../../static/vant/row/index",
       "van-col": "../../../static/vant/col/index",
-      "van-popup": "../../../static/vant/popup/index"
+      "van-popup": "../../../static/vant/popup/index",
+      "van-radio": "../../../static/vant/radio/index",
+      "van-radio-group": "../../../static/vant/radio-group/index"
     }
   }

+ 1 - 1
src/pages/user_center/recharge/index.vue

@@ -362,7 +362,7 @@ export default {
       }else if($item.coupon.type==4){
           $item["total_price"] = $item.price-$item.coupon.random
       }else{
-          $item["total_price"] = Math.round($item.price*$item.discount*100)/10
+          $item["total_price"] = Math.round($item.price*$item.discount*100)/100
       }
       //减多少
       if($item.coupon.type==3){

+ 8 - 0
src/requests/coupons.js

@@ -18,6 +18,14 @@ export function getCouponList($limit = 0) {
   return fly.post('coupon/coupon-list', $params)
 }
 
+//已过期优惠券列表
+export function getOverdueCouponList($limit = 0) {
+  let $params = {}
+  $params['limit'] = $limit
+  $params['access_token'] = wx.getStorageSync('token')
+  return fly.post('coupon/coupon-expire-list', $params)
+}
+
 //待领取优惠券
 export function couponReceive($id) {
   let $params = {}

+ 16 - 0
src/utils/index.js

@@ -59,6 +59,22 @@ export function formatTimeForSeconds(date) {
   return year + "/" + month + "/" + day + " " + hour + ":" + minute;
 }
 
+export function timestampTwoNum(timestamp) {
+  var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+  var Y = date.getFullYear() + ".";
+  var M =
+       (date.getMonth() + 1 < 10 ?
+            "0" + (date.getMonth() + 1) :
+            date.getMonth() + 1) + ".";
+
+  // (date.getSeconds()  < 10 ? "0" + date.getSeconds() : date.getSeconds())
+  var D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) ;
+  // var h = date.getHours() + ":";
+  // var m = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) ;
+  // var s = (date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds());
+  return (Y + M + D );
+}
+
 export function formatValidityTime(date) {
   if (date.toString().length <= 11) {
     date = date * 1000;

+ 3 - 0
src/utils/pay.js

@@ -0,0 +1,3 @@
+import Vue from 'vue'
+const Pay = new Vue()
+export default Pay

+ 13 - 5
static/vant/action-sheet/index.js

@@ -1,8 +1,7 @@
 import { VantComponent } from '../common/component';
 import { button } from '../mixins/button';
-import { openType } from '../mixins/open-type';
 VantComponent({
-  mixins: [button, openType],
+  mixins: [button],
   props: {
     show: Boolean,
     title: String,
@@ -40,12 +39,21 @@ VantComponent({
   methods: {
     onSelect(event) {
       const { index } = event.currentTarget.dataset;
-      const item = this.data.actions[index];
-      if (item && !item.disabled && !item.loading) {
+      const { actions, closeOnClickAction, canIUseGetUserProfile } = this.data;
+      const item = actions[index];
+      if (item) {
         this.$emit('select', item);
-        if (this.data.closeOnClickAction) {
+        if (closeOnClickAction) {
           this.onClose();
         }
+        if (item.openType === 'getUserInfo' && canIUseGetUserProfile) {
+          wx.getUserProfile({
+            desc: item.getUserProfileDesc || '  ',
+            complete: (userProfile) => {
+              this.$emit('getuserinfo', userProfile);
+            },
+          });
+        }
       }
     },
     onCancel() {

+ 25 - 23
static/vant/action-sheet/index.wxml

@@ -11,15 +11,15 @@
   close-on-click-overlay="{{ closeOnClickOverlay }}"
   bind:close="onClickOverlay"
 >
-  <view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
+  <view wx:if="{{ title }}" class="van-action-sheet__header">
     {{ title }}
     <van-icon
-      name="close"
+      name="cross"
       custom-class="van-action-sheet__close"
       bind:click="onClose"
     />
   </view>
-  <view wx:if="{{ description }}" class="van-action-sheet__description">
+  <view wx:if="{{ description }}" class="van-action-sheet__description van-hairline--bottom">
     {{ description }}
   </view>
   <view wx:if="{{ actions && actions.length }}">
@@ -27,18 +27,18 @@
     <button
       wx:for="{{ actions }}"
       wx:key="index"
-      open-type="{{ item.openType }}"
+      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 }) }} van-hairline--top {{ item.className || '' }}"
+      class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} {{ item.className || '' }}"
       hover-class="van-action-sheet__item--hover"
       data-index="{{ index }}"
-      bind:tap="onSelect"
-      bindgetuserinfo="bindGetUserInfo"
-      bindcontact="bindContact"
-      bindgetphonenumber="bindGetPhoneNumber"
-      binderror="bindError"
-      bindlaunchapp="bindLaunchApp"
-      bindopensetting="bindOpenSetting"
+      bindtap="{{ item.disabled || item.loading ? '' : 'onSelect' }}"
+      bindgetuserinfo="onGetUserInfo"
+      bindcontact="onContact"
+      bindgetphonenumber="onGetPhoneNumber"
+      binderror="onError"
+      bindlaunchapp="onLaunchApp"
+      bindopensetting="onOpenSetting"
       lang="{{ lang }}"
       session-from="{{ sessionFrom }}"
       send-message-title="{{ sendMessageTitle }}"
@@ -49,19 +49,21 @@
     >
       <block wx:if="{{ !item.loading }}">
         {{ item.name }}
-        <text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
+        <view wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</view>
       </block>
-      <van-loading wx:else custom-class="van-action-sheet__loading" size="20px" />
+      <van-loading wx:else custom-class="van-action-sheet__loading" size="22px" />
     </button>
   </view>
   <slot />
-  <view
-    wx:if="{{ cancelText }}"
-    class="van-action-sheet__cancel"
-    hover-class="van-action-sheet__cancel--hover"
-    hover-stay-time="70"
-    bind:tap="onCancel"
-  >
-    {{ cancelText }}
-  </view>
+  <block wx:if="{{ cancelText }}">
+    <view class="van-action-sheet__gap" />
+    <view
+      class="van-action-sheet__cancel"
+      hover-class="van-action-sheet__cancel--hover"
+      hover-stay-time="70"
+      bind:tap="onCancel"
+    >
+      {{ cancelText }}
+    </view>
+  </block>
 </van-popup>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
static/vant/action-sheet/index.wxss


+ 53 - 48
static/vant/area/index.js

@@ -1,7 +1,7 @@
 import { VantComponent } from '../common/component';
 import { pickerProps } from '../picker/shared';
 import { requestAnimationFrame } from '../common/utils';
-const COLUMNSPLACEHOLDERCODE = '000000';
+const EMPTY_CODE = '000000';
 VantComponent({
   classes: ['active-class', 'toolbar-class', 'column-class'],
   props: Object.assign(Object.assign({}, pickerProps), {
@@ -20,11 +20,6 @@ VantComponent({
     columnsNum: {
       type: null,
       value: 3,
-      observer(value) {
-        this.setData({
-          displayColumns: this.data.columns.slice(0, +value),
-        });
-      },
     },
     columnsPlaceholder: {
       type: Array,
@@ -41,7 +36,6 @@ VantComponent({
   }),
   data: {
     columns: [{ values: [] }, { values: [] }, { values: [] }],
-    displayColumns: [{ values: [] }, { values: [] }, { values: [] }],
     typeToColumnsPlaceholder: {},
   },
   mounted() {
@@ -62,7 +56,7 @@ VantComponent({
     onConfirm(event) {
       const { index } = event.detail;
       let { value } = event.detail;
-      value = this.parseOutputValues(value);
+      value = this.parseValues(value);
       this.emit('confirm', { value, index });
     },
     emit(type, detail) {
@@ -70,47 +64,50 @@ VantComponent({
       delete detail.value;
       this.$emit(type, detail);
     },
-    // parse output columns data
-    parseOutputValues(values) {
+    parseValues(values) {
       const { columnsPlaceholder } = this.data;
       return values.map((value, index) => {
-        // save undefined value
-        if (!value) return value;
-        value = JSON.parse(JSON.stringify(value));
-        if (!value.code || value.name === columnsPlaceholder[index]) {
-          value.code = '';
-          value.name = '';
+        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;
-      this.setValues().then(() => {
-        this.$emit('change', {
-          picker,
-          values: this.parseOutputValues(picker.getValues()),
-          index,
-        });
-      });
+      (_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) {
-      const { typeToColumnsPlaceholder } = this.data;
-      let result = [];
       if (type !== 'province' && !code) {
-        return result;
+        return [];
       }
+      const { typeToColumnsPlaceholder } = this.data;
       const list = this.getConfig(type);
-      result = Object.keys(list).map((code) => ({
+      let result = Object.keys(list).map((code) => ({
         code,
         name: list[code],
       }));
-      if (code) {
+      if (code != null) {
         // oversea code
         if (code[0] === '9' && type === 'city') {
           code = '9';
@@ -123,8 +120,8 @@ VantComponent({
           type === 'province'
             ? ''
             : type === 'city'
-            ? COLUMNSPLACEHOLDERCODE.slice(2, 4)
-            : COLUMNSPLACEHOLDERCODE.slice(4, 6);
+            ? EMPTY_CODE.slice(2, 4)
+            : EMPTY_CODE.slice(4, 6);
         result.unshift({
           code: `${code}${codeFill}`,
           name: typeToColumnsPlaceholder[type],
@@ -148,35 +145,25 @@ VantComponent({
       return 0;
     },
     setValues() {
-      const county = this.getConfig('county');
-      let { code } = this;
-      if (!code) {
-        if (this.data.columnsPlaceholder.length) {
-          code = COLUMNSPLACEHOLDERCODE;
-        } else if (Object.keys(county)[0]) {
-          code = Object.keys(county)[0];
-        } else {
-          code = '';
-        }
-      }
-      const province = this.getList('province');
-      const city = this.getList('city', code.slice(0, 2));
       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, province, false));
+        stack.push(picker.setColumnValues(0, provinceList, false));
         indexes.push(this.getIndex('province', code));
       }
       if (columnsNum >= 2) {
-        stack.push(picker.setColumnValues(1, city, false));
+        stack.push(picker.setColumnValues(1, cityList, false));
         indexes.push(this.getIndex('city', code));
-        if (city.length && code.slice(2, 4) === '00') {
-          [{ code }] = city;
+        if (cityList.length && code.slice(2, 4) === '00') {
+          [{ code }] = cityList;
         }
       }
       if (columnsNum === 3) {
@@ -194,9 +181,27 @@ VantComponent({
         .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();
-      return picker ? picker.getValues().filter((value) => !!value) : [];
+      if (!picker) {
+        return [];
+      }
+      return this.parseValues(picker.getValues().filter((value) => !!value));
     },
     getDetail() {
       const values = this.getValues();

+ 3 - 1
static/vant/area/index.wxml

@@ -1,3 +1,5 @@
+<wxs src="./index.wxs" module="computed" />
+
 <van-picker
   class="van-area__picker"
   active-class="active-class"
@@ -7,7 +9,7 @@
   value-key="name"
   title="{{ title }}"
   loading="{{ loading }}"
-  columns="{{ displayColumns }}"
+  columns="{{ computed.displayColumns(columns, columnsNum) }}"
   item-height="{{ itemHeight }}"
   visible-item-count="{{ visibleItemCount }}"
   cancel-button-text="{{ cancelButtonText }}"

+ 8 - 0
static/vant/area/index.wxs

@@ -0,0 +1,8 @@
+/* eslint-disable */
+function displayColumns(columns, columnsNum) {
+  return columns.slice(0, +columnsNum);
+}
+
+module.exports = {
+  displayColumns: displayColumns,
+};

+ 18 - 28
static/vant/button/index.js

@@ -1,8 +1,7 @@
 import { VantComponent } from '../common/component';
 import { button } from '../mixins/button';
-import { openType } from '../mixins/open-type';
 import { canIUseFormFieldButton } from '../common/version';
-const mixins = [button, openType];
+const mixins = [button];
 if (canIUseFormFieldButton()) {
   mixins.push('wx://form-field-button');
 }
@@ -45,35 +44,26 @@ VantComponent({
       type: String,
       value: '20px',
     },
-    color: {
-      type: String,
-      observer(color) {
-        let style = '';
-        if (color) {
-          style += `color: ${this.data.plain ? color : 'white'};`;
-          if (!this.data.plain) {
-            // Use background instead of backgroundColor to make linear-gradient work
-            style += `background: ${color};`;
-          }
-          // hide border when color is linear-gradient
-          if (color.indexOf('gradient') !== -1) {
-            style += 'border: 0;';
-          } else {
-            style += `border-color: ${color};`;
-          }
-        }
-        if (style !== this.data.baseStyle) {
-          this.setData({ baseStyle: style });
-        }
-      },
-    },
+    color: String,
   },
   methods: {
-    onClick() {
-      if (!this.data.loading) {
-        this.$emit('click');
+    onClick(event) {
+      this.$emit('click', event);
+      const {
+        canIUseGetUserProfile,
+        openType,
+        getUserProfileDesc,
+        lang,
+      } = this.data;
+      if (openType === 'getUserInfo' && canIUseGetUserProfile) {
+        wx.getUserProfile({
+          desc: getUserProfileDesc || '  ',
+          lang: lang || 'en',
+          complete: (userProfile) => {
+            this.$emit('getuserinfo', userProfile);
+          },
+        });
       }
     },
-    noop() {},
   },
 });

+ 11 - 26
static/vant/button/index.wxml

@@ -1,4 +1,5 @@
 <wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
 
 <button
   id="{{ id }}"
@@ -7,8 +8,8 @@
   hover-class="van-button--active hover-class"
   lang="{{ lang }}"
   form-type="{{ formType }}"
-  style="{{ baseStyle }} {{ customStyle }}"
-  open-type="{{ disabled ? '' : openType }}"
+  style="{{ computed.rootStyle({ plain, color, customStyle }) }}"
+  open-type="{{ disabled || loading || (canIUseGetUserProfile && openType === 'getUserInfo') ? '' : openType }}"
   business-id="{{ businessId }}"
   session-from="{{ sessionFrom }}"
   send-message-title="{{ sendMessageTitle }}"
@@ -17,20 +18,20 @@
   show-message-card="{{ showMessageCard }}"
   app-parameter="{{ appParameter }}"
   aria-label="{{ ariaLabel }}"
-  bindtap="{{ !disabled ? 'onClick' : 'noop' }}"
-  bindgetuserinfo="bindGetUserInfo"
-  bindcontact="bindContact"
-  bindgetphonenumber="bindGetPhoneNumber"
-  binderror="bindError"
-  bindlaunchapp="bindLaunchApp"
-  bindopensetting="bindOpenSetting"
+  bindtap="{{ disabled || loading ? '' : 'onClick' }}"
+  bindgetuserinfo="onGetUserInfo"
+  bindcontact="onContact"
+  bindgetphonenumber="onGetPhoneNumber"
+  binderror="onError"
+  bindlaunchapp="onLaunchApp"
+  bindopensetting="onOpenSetting"
 >
   <block wx:if="{{ loading }}">
     <van-loading
       custom-class="loading-class"
       size="{{ loadingSize }}"
       type="{{ loadingType }}"
-      color="{{ loadingColor(type,color,plain) }}"
+      color="{{ computed.loadingColor({ type, color, plain }) }}"
     />
     <view wx:if="{{ loadingText }}" class="van-button__loading-text">
       {{ loadingText }}
@@ -50,19 +51,3 @@
     </view>
   </block>
 </button>
-
-
-<wxs module="loadingColor">
-function get(type, color,plain) {
-  if(plain) {
-    return color ? color: '#c9c9c9';
-  }
-
-  if(type === 'default') {
-    return '#c9c9c9';
-  }
-  return 'white';
-}
-
-module.exports = get;
-</wxs>

+ 39 - 0
static/vant/button/index.wxs

@@ -0,0 +1,39 @@
+/* eslint-disable */
+var style = require('../wxs/style.wxs');
+
+function rootStyle(data) {
+  if (!data.color) {
+    return data.customStyle;
+  }
+
+  var properties = {
+    color: data.plain ? data.color : '#fff',
+    background: data.plain ? null : data.color,
+  };
+
+  // hide border when color is linear-gradient
+  if (data.color.indexOf('gradient') !== -1) {
+    properties.border = 0;
+  } else {
+    properties['border-color'] = data.color;
+  }
+
+  return style([properties, data.customStyle]);
+}
+
+function loadingColor(data) {
+  if (data.plain) {
+    return data.color ? data.color : '#c9c9c9';
+  }
+
+  if (data.type === 'default') {
+    return '#c9c9c9';
+  }
+
+  return '#fff';
+}
+
+module.exports = {
+  rootStyle: rootStyle,
+  loadingColor: loadingColor,
+};

+ 62 - 52
static/vant/calendar/calendar.wxml

@@ -1,57 +1,67 @@
-<wxs src="./index.wxs" module="computed"></wxs>
+<view class="van-calendar">
+  <header
+    title="{{ title }}"
+    showTitle="{{ showTitle }}"
+    subtitle="{{ subtitle }}"
+    showSubtitle="{{ showSubtitle }}"
+    firstDayOfWeek="{{ firstDayOfWeek }}"
+  >
+    <slot name="title" slot="title"></slot>
+  </header>
 
-<template name="calendar">
-  <view class="van-calendar">
-    <header
-      title="{{ title }}"
-      showTitle="{{ showTitle }}"
-      subtitle="{{ subtitle }}"
+  <scroll-view
+    class="van-calendar__body"
+    scroll-y
+    scroll-into-view="{{ scrollIntoView }}"
+  >
+    <month
+      wx:for="{{ computed.getMonths(minDate, maxDate) }}"
+      wx:key="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 }}"
-    >
-      <slot name="title" slot="title"></slot>
-    </header>
-
-    <scroll-view class="van-calendar__body" scroll-y scroll-into-view="{{ scrollIntoView }}">
-      <month
-        wx:for="{{ computed.getMonths(minDate, maxDate) }}"
-        wx:key="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 }}"
-        bind:click="onClickDay"
-      />
-    </scroll-view>
+      allowSameDay="{{ allowSameDay }}"
+      showMonthTitle="{{ index !== 0 || !showSubtitle }}"
+      firstDayOfWeek="{{ firstDayOfWeek }}"
+      bind:click="onClickDay"
+    />
+  </scroll-view>
 
-    <view class="van-calendar__footer {{ safeAreaInsetBottom ? 'van-calendar__footer--safe-area-inset-bottom' : '' }}">
-      <slot name="footer"></slot>
-    </view>
+  <view
+    class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
+  >
+    <slot name="footer"></slot>
+  </view>
 
-    <view class="van-calendar__footer {{ safeAreaInsetBottom ? 'van-calendar__footer--safe-area-inset-bottom' : '' }}">
-      <van-button
-        wx:if="{{ showConfirm }}"
-        round
-        block
-        type="danger"
-        color="{{ color }}"
-        custom-class="van-calendar__confirm"
-        disabled="{{ computed.getButtonDisabled(type, currentDate) }}"
-        nativeType="text"
-        bind:click="onConfirm"
-      >
-        {{ computed.getButtonDisabled(type, currentDate) ? confirmDisabledText : confirmText }}
-      </van-button>
-    </view>
+  <view
+    class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}"
+  >
+    <van-button
+      wx:if="{{ showConfirm }}"
+      round
+      block
+      type="danger"
+      color="{{ color }}"
+      custom-class="van-calendar__confirm"
+      disabled="{{ computed.getButtonDisabled(type, currentDate) }}"
+      nativeType="text"
+      bind:click="onConfirm"
+    >
+      {{
+        computed.getButtonDisabled(type, currentDate)
+          ? confirmDisabledText
+          : confirmText
+      }}
+    </van-button>
   </view>
-</template>
+</view>

+ 20 - 2
static/vant/calendar/components/header/index.js

@@ -8,9 +8,27 @@ VantComponent({
     subtitle: String,
     showTitle: Boolean,
     showSubtitle: Boolean,
+    firstDayOfWeek: {
+      type: Number,
+      observer: 'initWeekDay',
+    },
   },
   data: {
-    weekdays: ['日', '一', '二', '三', '四', '五', '六'],
+    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),
+        ],
+      });
+    },
   },
-  methods: {},
 });

+ 10 - 4
static/vant/calendar/components/month/index.js

@@ -25,13 +25,17 @@ VantComponent({
       observer: 'setDays',
     },
     showMark: Boolean,
-    rowHeight: [Number, String],
+    rowHeight: null,
     formatter: {
       type: null,
       observer: 'setDays',
     },
     currentDate: {
-      type: [null, Array],
+      type: null,
+      observer: 'setDays',
+    },
+    firstDayOfWeek: {
+      type: Number,
       observer: 'setDays',
     },
     allowSameDay: Boolean,
@@ -100,11 +104,11 @@ VantComponent({
     getRangeDayType(day) {
       const { currentDate, allowSameDay } = this.data;
       if (!Array.isArray(currentDate)) {
-        return;
+        return '';
       }
       const [startDay, endDay] = currentDate;
       if (!startDay) {
-        return;
+        return '';
       }
       const compareToStart = compareDay(day, startDay);
       if (!endDay) {
@@ -123,6 +127,7 @@ VantComponent({
       if (compareToStart > 0 && compareToEnd < 0) {
         return 'middle';
       }
+      return '';
     },
     getDayType(day) {
       const { type, minDate, maxDate, currentDate } = this.data;
@@ -139,6 +144,7 @@ VantComponent({
       if (type === 'range') {
         return this.getRangeDayType(day);
       }
+      return '';
     },
     getBottomInfo(type) {
       if (this.data.type === 'range') {

+ 1 - 1
static/vant/calendar/components/month/index.wxml

@@ -14,7 +14,7 @@
     <view
       wx:for="{{ days }}"
       wx:key="index"
-      style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color) }}"
+      style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color, firstDayOfWeek) }}"
       class="{{ utils.bem('calendar__day', [item.type]) }} {{ item.className }}"
       data-index="{{ index }}"
       bindtap="onClick"

+ 6 - 2
static/vant/calendar/components/month/index.wxs

@@ -7,9 +7,12 @@ function getMark(date) {
 
 var ROW_HEIGHT = 64;
 
-function getDayStyle(type, index, date, rowHeight, color) {
+function getDayStyle(type, index, date, rowHeight, color, firstDayOfWeek) {
   var style = [];
-  var offset = getDate(date).getDay();
+  var current = getDate(date).getDay() || 7;
+  var offset = current < firstDayOfWeek ? (7 - firstDayOfWeek + current) :
+               current === 7 && firstDayOfWeek === 0 ? 0 :
+               (current - firstDayOfWeek);
 
   if (index === 0) {
     style.push(['margin-left', (100 * offset) / 7 + '%']);
@@ -23,6 +26,7 @@ function getDayStyle(type, index, date, rowHeight, color) {
     if (
       type === 'start' ||
       type === 'end' ||
+      type === 'start-end' ||
       type === 'multiple-selected' ||
       type === 'multiple-middle'
     ) {

+ 74 - 22
static/vant/calendar/index.js

@@ -1,7 +1,9 @@
 import { VantComponent } from '../common/component';
 import {
   ROW_HEIGHT,
+  getPrevDay,
   getNextDay,
+  getToday,
   compareDay,
   copyDates,
   calcDateNum,
@@ -12,6 +14,15 @@ import {
 } 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();
+})();
 VantComponent({
   props: {
     title: {
@@ -34,8 +45,12 @@ VantComponent({
       value: '确定',
     },
     rangePrompt: String,
+    showRangePrompt: {
+      type: Boolean,
+      value: true,
+    },
     defaultDate: {
-      type: [Number, Array],
+      type: null,
       observer(val) {
         this.setData({ currentDate: val });
         this.scrollIntoView();
@@ -50,22 +65,18 @@ VantComponent({
     },
     minDate: {
       type: null,
-      value: Date.now(),
+      value: initialMinDate,
     },
     maxDate: {
       type: null,
-      value: new Date(
-        new Date().getFullYear(),
-        new Date().getMonth() + 6,
-        new Date().getDate()
-      ).getTime(),
+      value: initialMaxDate,
     },
     position: {
       type: String,
       value: 'bottom',
     },
     rowHeight: {
-      type: [Number, String],
+      type: null,
       value: ROW_HEIGHT,
     },
     round: {
@@ -101,9 +112,13 @@ VantComponent({
       value: true,
     },
     maxRange: {
-      type: [Number, String],
+      type: null,
       value: null,
     },
+    firstDayOfWeek: {
+      type: Number,
+      value: 0,
+    },
   },
   data: {
     subtitle: '',
@@ -143,19 +158,46 @@ VantComponent({
         }
       });
     },
-    getInitialDate() {
-      const { type, defaultDate, minDate } = this.data;
+    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 || [];
-        return [
-          startDay || minDate,
-          endDay || getNextDay(new Date(minDate)).getTime(),
-        ];
+        const start = this.limitDateRange(
+          startDay || now,
+          minDate,
+          getPrevDay(maxDate).getTime()
+        );
+        const end = this.limitDateRange(
+          endDay || now,
+          getNextDay(minDate).getTime()
+        );
+        return [start, end];
       }
       if (type === 'multiple') {
-        return defaultDate || [minDate];
+        if (Array.isArray(defaultDate)) {
+          return defaultDate.map((date) => this.limitDateRange(date));
+        }
+        return [this.limitDateRange(now)];
+      }
+      if (!defaultDate || Array.isArray(defaultDate)) {
+        defaultDate = now;
       }
-      return defaultDate || minDate;
+      return this.limitDateRange(defaultDate);
     },
     scrollIntoView() {
       requestAnimationFrame(() => {
@@ -167,6 +209,7 @@ VantComponent({
           minDate,
           maxDate,
         } = this.data;
+        // @ts-ignore
         const targetDate = type === 'single' ? currentDate : currentDate[0];
         const displayed = show || !poppable;
         if (!targetDate || !displayed) {
@@ -198,6 +241,7 @@ VantComponent({
       const { 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);
@@ -213,6 +257,7 @@ VantComponent({
         }
       } else if (type === 'multiple') {
         let selectedIndex;
+        // @ts-ignore
         const selected = currentDate.some((dateItem, index) => {
           const equal = compareDay(dateItem, date) === 0;
           if (equal) {
@@ -221,10 +266,12 @@ VantComponent({
           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 {
@@ -266,12 +313,16 @@ VantComponent({
       this.$emit('select', copyDates(date));
     },
     checkRange(date) {
-      const { maxRange, rangePrompt } = this.data;
+      const { maxRange, rangePrompt, showRangePrompt } = this.data;
       if (maxRange && calcDateNum(date) > maxRange) {
-        Toast({
-          context: this,
-          message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
-        });
+        if (showRangePrompt) {
+          Toast({
+            duration: 0,
+            context: this,
+            message: rangePrompt || `选择天数不能超过 ${maxRange} 天`,
+          });
+        }
+        this.$emit('over-range');
         return false;
       }
       return true;
@@ -284,6 +335,7 @@ VantComponent({
         return;
       }
       wx.nextTick(() => {
+        // @ts-ignore
         this.$emit('confirm', copyDates(this.data.currentDate));
       });
     },

+ 3 - 9
static/vant/calendar/index.wxml

@@ -1,4 +1,5 @@
 <wxs src="./index.wxs" module="computed" />
+<wxs src="../wxs/utils.wxs" module="utils" />
 
 <import src="./calendar.wxml" />
 
@@ -16,16 +17,9 @@
   bind:after-enter="onOpened"
   bind:after-leave="onClosed"
 >
-  <template
-    is="calendar"
-    data="{{ title, subtitle, showTitle, showSubtitle, minDate, maxDate, type, color, showMark, formatter, rowHeight, currentDate, safeAreaInsetBottom, showConfirm, confirmDisabledText, confirmText, scrollIntoView, allowSameDay }}"
-  />
+  <include src="calendar.wxml" />
 </van-popup>
 
-<template
-  wx:else
-  is="calendar"
-  data="{{ title, subtitle, showTitle, showSubtitle, minDate, maxDate, type, color, showMark, formatter, rowHeight, currentDate, safeAreaInsetBottom, showConfirm, confirmDisabledText, confirmText, scrollIntoView, allowSameDay }}"
-/>
+<include wx:else src="calendar.wxml" />
 
 <van-toast id="van-toast" />

+ 4 - 3
static/vant/calendar/utils.d.ts

@@ -3,15 +3,16 @@ export declare function formatMonthTitle(date: Date): string;
 export declare function compareMonth(
   date1: Date | number,
   date2: Date | number
-): 0 | 1 | -1;
+): 1 | -1 | 0;
 export declare function compareDay(
   day1: Date | number,
   day2: Date | number
-): 0 | 1 | -1;
+): 1 | -1 | 0;
 export declare function getDayByOffset(date: Date, offset: number): Date;
 export declare function getPrevDay(date: Date): Date;
 export declare function getNextDay(date: Date): Date;
+export declare function getToday(): Date;
 export declare function calcDateNum(date: [Date, Date]): number;
 export declare function copyDates(dates: Date | Date[]): Date | Date[];
 export declare function getMonthEndDay(year: number, month: number): number;
-export declare function getMonths(minDate: number, maxDate: number): any[];
+export declare function getMonths(minDate: number, maxDate: number): number[];

+ 5 - 0
static/vant/calendar/utils.js

@@ -47,6 +47,11 @@ export function getPrevDay(date) {
 export function getNextDay(date) {
   return getDayByOffset(date, 1);
 }
+export function getToday() {
+  const today = new Date();
+  today.setHours(0, 0, 0, 0);
+  return today;
+}
 export function calcDateNum(date) {
   const day1 = new Date(date[0]).getTime();
   const day2 = new Date(date[1]).getTime();

+ 1 - 0
static/vant/cell-group/index.js

@@ -6,5 +6,6 @@ VantComponent({
       type: Boolean,
       value: true,
     },
+    inset: Boolean,
   },
 });

+ 4 - 2
static/vant/cell-group/index.wxml

@@ -1,9 +1,11 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
 <view
   wx:if="{{ title }}"
-  class="van-cell-group__title"
+  class="{{ utils.bem('cell-group__title', { inset }) }}"
 >
   {{ title }}
 </view>
-<view class="custom-class van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
+<view class="custom-class {{ utils.bem('cell-group', { inset }) }} {{ border ? 'van-hairline--top-bottom' : '' }}">
   <slot />
 </view>

+ 1 - 1
static/vant/cell-group/index.wxss

@@ -1 +1 @@
-@import '../common/index.wxss';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}
+@import '../common/index.wxss';.van-cell-group--inset{margin:0 16px;margin:var(--cell-group-inset-padding,0 16px);border-radius:8px;border-radius:var(--cell-group-inset-border-radius,8px);overflow:hidden}.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}.van-cell-group__title--inset{padding:16px 16px 8px 32px;padding:var(--cell-group-inset-title-padding,16px 16px 8px 32px)}

+ 3 - 1
static/vant/cell/index.wxml

@@ -1,4 +1,5 @@
 <wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
 
 <view
   class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
@@ -16,9 +17,10 @@
   <slot wx:else name="icon" />
 
   <view
-    style="{{ (titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth + ';' : '') + titleStyle }}"
+    style="{{ computed.titleStyle({ titleWidth, titleStyle }) }}"
     class="van-cell__title title-class"
   >
+
     <block wx:if="{{ title }}">{{ title }}</block>
     <slot wx:else name="title" />
 

+ 17 - 0
static/vant/cell/index.wxs

@@ -0,0 +1,17 @@
+/* eslint-disable */
+var style = require('../wxs/style.wxs');
+var addUnit = require('../wxs/add-unit.wxs');
+
+function titleStyle(data) {
+  return style([
+    {
+      'max-width': addUnit(data.titleWidth),
+      'min-width': addUnit(data.titleWidth),
+    },
+    data.titleStyle,
+  ]);
+}
+
+module.exports = {
+  titleStyle: titleStyle,
+};

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
static/vant/cell/index.wxss


+ 1 - 0
static/vant/checkbox-group/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 36 - 0
static/vant/checkbox-group/index.js

@@ -0,0 +1,36 @@
+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,
+      });
+    },
+  },
+});

+ 3 - 0
static/vant/checkbox-group/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 5 - 0
static/vant/checkbox-group/index.wxml

@@ -0,0 +1,5 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<view class="{{ utils.bem('checkbox-group', [{ horizontal: direction === 'horizontal' }]) }}">
+  <slot />
+</view>

+ 1 - 0
static/vant/checkbox-group/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-checkbox-group--horizontal{display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}

+ 7 - 6
static/vant/checkbox/index.js

@@ -1,3 +1,4 @@
+import { useParent } from '../common/relation';
 import { VantComponent } from '../common/component';
 function emit(target, value) {
   target.$emit('input', value);
@@ -5,18 +6,17 @@ function emit(target, value) {
 }
 VantComponent({
   field: true,
-  relation: {
-    name: 'checkbox-group',
-    type: 'ancestor',
-    current: 'checkbox',
-  },
+  relation: useParent('checkbox-group'),
   classes: ['icon-class', 'label-class'],
   props: {
     value: Boolean,
     disabled: Boolean,
     useIconSlot: Boolean,
     checkedColor: String,
-    labelPosition: String,
+    labelPosition: {
+      type: String,
+      value: 'right',
+    },
     labelDisabled: Boolean,
     shape: {
       type: String,
@@ -29,6 +29,7 @@ VantComponent({
   },
   data: {
     parentDisabled: false,
+    direction: 'vertical',
   },
   methods: {
     emitChange(value) {

+ 13 - 2
static/vant/checkbox/index.wxml

@@ -1,7 +1,14 @@
 <wxs src="../wxs/utils.wxs" module="utils" />
 <wxs src="./index.wxs" module="computed" />
 
-<view class="van-checkbox custom-class">
+<view class="{{ utils.bem('checkbox', [{ horizontal: direction === 'horizontal' }]) }} custom-class">
+  <view
+    wx:if="{{ labelPosition === 'left' }}"
+    class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
+    bindtap="onClickLabel"
+  >
+    <slot />
+  </view>
   <view class="van-checkbox__icon-wrap" bindtap="toggle">
     <slot wx:if="{{ useIconSlot }}" name="icon" />
     <van-icon
@@ -14,7 +21,11 @@
       custom-style="line-height: 1.25em;"
     />
   </view>
-  <view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}" bindtap="onClickLabel">
+  <view
+    wx:if="{{ labelPosition === 'right' }}"
+    class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
+    bindtap="onClickLabel"
+  >
     <slot />
   </view>
 </view>

+ 10 - 10
static/vant/checkbox/index.wxs

@@ -1,20 +1,20 @@
 /* eslint-disable */
-var utils = require('../wxs/utils.wxs');
+var style = require('../wxs/style.wxs');
+var addUnit = require('../wxs/add-unit.wxs');
 
 function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) {
-  var styles = [['font-size', utils.addUnit(iconSize)]];
+  var styles = {
+    'font-size': addUnit(iconSize),
+  };
+
   if (checkedColor && value && !disabled && !parentDisabled) {
-    styles.push(['border-color', checkedColor]);
-    styles.push(['background-color', checkedColor]);
+    styles['border-color'] = checkedColor;
+    styles['background-color'] = checkedColor;
   }
 
-  return styles
-    .map(function(item) {
-      return item.join(':');
-    })
-    .join(';');
+  return style(styles);
 }
 
 module.exports = {
-  iconStyle: iconStyle
+  iconStyle: iconStyle,
 };

+ 1 - 1
static/vant/checkbox/index.wxss

@@ -1 +1 @@
-@import '../common/index.wxss';.van-checkbox{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px;line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;font-size:20px;font-size:var(--checkbox-size,20px);border:1px solid #c8c9cc;border:1px solid var(--checkbox-border-color,#c8c9cc);transition-duration:.2s;transition-duration:var(--checkbox-transition-duration,.2s)}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--checkbox-checked-icon-color,#1989fa)}.van-checkbox__icon--disabled{background-color:#ebedf0;background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c8c9cc;color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;margin-left:10px;margin-left:var(--checkbox-label-margin,10px);color:#323233;color:var(--checkbox-label-color,#323233)}.van-checkbox__label--left{float:left;margin:0 10px 0 0;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:#c8c9cc;color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
+@import '../common/index.wxss';.van-checkbox{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox--horizontal{margin-right:12px}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px;line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;font-size:20px;font-size:var(--checkbox-size,20px);border:1px solid #c8c9cc;border:1px solid var(--checkbox-border-color,#c8c9cc);transition-duration:.2s;transition-duration:var(--checkbox-transition-duration,.2s)}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--checkbox-checked-icon-color,#1989fa)}.van-checkbox__icon--disabled{background-color:#ebedf0;background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c8c9cc;color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;margin-left:10px;margin-left:var(--checkbox-label-margin,10px);color:#323233;color:var(--checkbox-label-color,#323233)}.van-checkbox__label--left{float:left;margin:0 10px 0 0;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:#c8c9cc;color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}

+ 3 - 3
static/vant/circle/canvas.d.ts

@@ -1,6 +1,6 @@
-/// <reference types="wechat-miniprogram" />
+/// <reference types="miniprogram-api-typings" />
 declare type CanvasContext = WechatMiniprogram.CanvasContext;
 export declare function adaptor(
-  ctx: CanvasRenderingContext2D
-): CanvasContext & CanvasRenderingContext2D;
+  ctx: CanvasContext & Record<string, unknown>
+): CanvasContext;
 export {};

+ 14 - 8
static/vant/circle/index.js

@@ -1,6 +1,8 @@
-import { VantComponent } from '../common/component';
-import { isObj } from '../common/utils';
 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);
@@ -37,7 +39,7 @@ VantComponent({
       value: WHITE,
     },
     color: {
-      type: [String, Object],
+      type: null,
       value: BLUE,
       observer() {
         this.setHoverColor().then(() => {
@@ -64,11 +66,11 @@ VantComponent({
   methods: {
     getContext() {
       const { type, size } = this.data;
-      if (type === '') {
+      if (type === '' || !canIUseCanvas2d()) {
         const ctx = wx.createCanvasContext('van-circle', this);
         return Promise.resolve(ctx);
       }
-      const dpr = wx.getSystemInfoSync().pixelRatio;
+      const dpr = getSystemInfoSync().pixelRatio;
       return new Promise((resolve) => {
         wx.createSelectorQuery()
           .in(this)
@@ -154,10 +156,14 @@ VantComponent({
       this.currentValue = this.currentValue || 0;
       this.interval = setInterval(() => {
         if (this.currentValue !== value) {
-          if (this.currentValue < value) {
-            this.currentValue += STEP;
+          if (Math.abs(this.currentValue - value) < STEP) {
+            this.currentValue = value;
           } else {
-            this.currentValue -= STEP;
+            if (this.currentValue < value) {
+              this.currentValue += STEP;
+            } else {
+              this.currentValue -= STEP;
+            }
           }
           this.drawCircle(this.currentValue);
         } else {

+ 2 - 19
static/vant/col/index.js

@@ -1,26 +1,9 @@
+import { useParent } from '../common/relation';
 import { VantComponent } from '../common/component';
 VantComponent({
-  relation: {
-    name: 'row',
-    type: 'ancestor',
-    current: 'col',
-  },
+  relation: useParent('row'),
   props: {
     span: Number,
     offset: Number,
   },
-  data: {
-    viewStyle: '',
-  },
-  methods: {
-    setGutter(gutter) {
-      const padding = `${gutter / 2}px`;
-      const viewStyle = gutter
-        ? `padding-left: ${padding}; padding-right: ${padding};`
-        : '';
-      if (viewStyle !== this.data.viewStyle) {
-        this.setData({ viewStyle });
-      }
-    },
-  },
 });

+ 2 - 1
static/vant/col/index.wxml

@@ -1,8 +1,9 @@
 <wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
 
 <view
   class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
-  style="{{ viewStyle }}"
+  style="{{ computed.rootStyle({ gutter }) }}"
 >
   <slot />
 </view>

+ 18 - 0
static/vant/col/index.wxs

@@ -0,0 +1,18 @@
+/* eslint-disable */
+var style = require('../wxs/style.wxs');
+var addUnit = require('../wxs/add-unit.wxs');
+
+function rootStyle(data) {
+  if (!data.gutter) {
+    return '';
+  }
+
+  return style({
+    'padding-right': addUnit(data.gutter / 2),
+    'padding-left': addUnit(data.gutter / 2),
+  });
+}
+
+module.exports = {
+  rootStyle: rootStyle,
+};

+ 6 - 0
static/vant/collapse-item/animate.d.ts

@@ -0,0 +1,6 @@
+/// <reference types="miniprogram-api-typings" />
+export declare function setContentAnimate(
+  context: WechatMiniprogram.Component.TrivialInstance,
+  expanded: boolean,
+  mounted: boolean
+): void;

+ 70 - 0
static/vant/collapse-item/animate.js

@@ -0,0 +1,70 @@
+import { canIUseAnimate } from '../common/version';
+import { getRect } from '../common/utils';
+function useAnimate(context, expanded, mounted, height) {
+  const selector = '.van-collapse-item__wrapper';
+  if (expanded) {
+    context.animate(
+      selector,
+      [
+        { height: 0, ease: 'ease-in-out', offset: 0 },
+        { height: `${height}px`, ease: 'ease-in-out', offset: 1 },
+        { height: `auto`, ease: 'ease-in-out', offset: 1 },
+      ],
+      mounted ? 300 : 0,
+      () => {
+        context.clearAnimation(selector);
+      }
+    );
+    return;
+  }
+  context.animate(
+    selector,
+    [
+      { height: `${height}px`, ease: 'ease-in-out', offset: 0 },
+      { height: 0, ease: 'ease-in-out', offset: 1 },
+    ],
+    300,
+    () => {
+      context.clearAnimation(selector);
+    }
+  );
+}
+function useAnimation(context, expanded, mounted, height) {
+  const animation = wx.createAnimation({
+    duration: 0,
+    timingFunction: 'ease-in-out',
+  });
+  if (expanded) {
+    if (height === 0) {
+      animation.height('auto').top(1).step();
+    } else {
+      animation
+        .height(height)
+        .top(1)
+        .step({
+          duration: mounted ? 300 : 1,
+        })
+        .height('auto')
+        .step();
+    }
+    context.setData({
+      animation: animation.export(),
+    });
+    return;
+  }
+  animation.height(height).top(0).step({ duration: 1 }).height(0).step({
+    duration: 300,
+  });
+  context.setData({
+    animation: animation.export(),
+  });
+}
+export function setContentAnimate(context, expanded, mounted) {
+  getRect(context, '.van-collapse-item__content')
+    .then((rect) => rect.height)
+    .then((height) => {
+      canIUseAnimate()
+        ? useAnimate(context, expanded, mounted, height)
+        : useAnimation(context, expanded, mounted, height);
+    });
+}

+ 1 - 0
static/vant/collapse-item/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 59 - 0
static/vant/collapse-item/index.js

@@ -0,0 +1,59 @@
+import { VantComponent } from '../common/component';
+import { useParent } from '../common/relation';
+import { setContentAnimate } from './animate';
+VantComponent({
+  classes: ['title-class', 'content-class'],
+  relation: useParent('collapse'),
+  props: {
+    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);
+    },
+  },
+});

+ 6 - 0
static/vant/collapse-item/index.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-cell": "../cell/index"
+  }
+}

+ 44 - 0
static/vant/collapse-item/index.wxml

@@ -0,0 +1,44 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<view class="van-collapse-item custom-class {{ index !== 0 ? 'van-hairline--top' : '' }}">
+  <van-cell
+    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"
+    bind:click="onClick"
+  >
+    <slot
+      name="title"
+      slot="title"
+    />
+    <slot
+      name="icon"
+      slot="icon"
+    />
+    <slot name="value" />
+    <slot
+      name="right-icon"
+      slot="right-icon"
+    />
+  </van-cell>
+  <view
+    class="{{ utils.bem('collapse-item__wrapper') }}"
+    style="height: 0;"
+    animation="{{ animation }}"
+  >
+    <view
+      class="van-collapse-item__content content-class"
+    >
+      <slot />
+    </view>
+  </view>
+</view>

+ 1 - 0
static/vant/collapse-item/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;transition:-webkit-transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s),-webkit-transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c8c9cc!important;color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important;background-color:var(--white,#fff)!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__content{padding:15px;padding:var(--collapse-item-content-padding,15px);color:#969799;color:var(--collapse-item-content-text-color,#969799);font-size:13px;font-size:var(--collapse-item-content-font-size,13px);line-height:1.5;line-height:var(--collapse-item-content-line-height,1.5);background-color:#fff;background-color:var(--collapse-item-content-background-color,#fff)}

+ 1 - 0
static/vant/collapse/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 44 - 0
static/vant/collapse/index.js

@@ -0,0 +1,44 @@
+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);
+    },
+  },
+});

+ 3 - 0
static/vant/collapse/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 3 - 0
static/vant/collapse/index.wxml

@@ -0,0 +1,3 @@
+<view class="custom-class van-collapse {{ border ? 'van-hairline--top-bottom' : '' }}">
+  <slot />
+</view>

+ 1 - 0
static/vant/collapse/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';

+ 7 - 2
static/vant/common/component.d.ts

@@ -1,3 +1,8 @@
-import { VantComponentOptions, CombinedComponentInstance } from '../definitions/index';
-declare function VantComponent<Data, Props, Methods>(vantOptions?: VantComponentOptions<Data, Props, Methods, CombinedComponentInstance<Data, Props, Methods>>): void;
+/// <reference types="miniprogram-api-typings" />
+import { VantComponentOptions } from '../definitions/index';
+declare function VantComponent<
+  Data extends WechatMiniprogram.Component.DataOption,
+  Props extends WechatMiniprogram.Component.PropertyOption,
+  Methods extends WechatMiniprogram.Component.MethodOption
+>(vantOptions: VantComponentOptions<Data, Props, Methods>): void;
 export { VantComponent };

+ 7 - 63
static/vant/common/component.js

@@ -1,23 +1,4 @@
 import { basic } from '../mixins/basic';
-const relationFunctions = {
-  ancestor: {
-    linked(parent) {
-      this.parent = parent;
-    },
-    unlinked() {
-      this.parent = null;
-    },
-  },
-  descendant: {
-    linked(child) {
-      this.children = this.children || [];
-      this.children.push(child);
-    },
-    unlinked(child) {
-      this.children = (this.children || []).filter((it) => it !== child);
-    },
-  },
-};
 function mapKeys(source, target, map) {
   Object.keys(map).forEach((key) => {
     if (source[key]) {
@@ -25,37 +6,7 @@ function mapKeys(source, target, map) {
     }
   });
 }
-function makeRelation(options, vantOptions, relation) {
-  const { type, name, linked, unlinked, linkChanged } = relation;
-  const { beforeCreate, destroyed } = vantOptions;
-  if (type === 'descendant') {
-    options.created = function () {
-      beforeCreate && beforeCreate.bind(this)();
-      this.children = this.children || [];
-    };
-    options.detached = function () {
-      this.children = [];
-      destroyed && destroyed.bind(this)();
-    };
-  }
-  options.relations = Object.assign(options.relations || {}, {
-    [`../${name}/index`]: {
-      type,
-      linked(node) {
-        relationFunctions[type].linked.bind(this)(node);
-        linked && linked.bind(this)(node);
-      },
-      linkChanged(node) {
-        linkChanged && linkChanged.bind(this)(node);
-      },
-      unlinked(node) {
-        relationFunctions[type].unlinked.bind(this)(node);
-        unlinked && unlinked.bind(this)(node);
-      },
-    },
-  });
-}
-function VantComponent(vantOptions = {}) {
+function VantComponent(vantOptions) {
   const options = {};
   mapKeys(vantOptions, options, {
     data: 'data',
@@ -65,32 +16,25 @@ function VantComponent(vantOptions = {}) {
     beforeCreate: 'created',
     created: 'attached',
     mounted: 'ready',
-    relations: 'relations',
     destroyed: 'detached',
     classes: 'externalClasses',
   });
-  const { relation } = vantOptions;
-  if (relation) {
-    makeRelation(options, vantOptions, relation);
-  }
   // add default externalClasses
   options.externalClasses = options.externalClasses || [];
   options.externalClasses.push('custom-class');
   // add default behaviors
   options.behaviors = options.behaviors || [];
   options.behaviors.push(basic);
+  // add relations
+  const { relation } = vantOptions;
+  if (relation) {
+    options.relations = relation.relations;
+    options.behaviors.push(relation.mixin);
+  }
   // map field to form-field behavior
   if (vantOptions.field) {
     options.behaviors.push('wx://form-field');
   }
-  if (options.properties) {
-    Object.keys(options.properties).forEach((name) => {
-      if (Array.isArray(options.properties[name])) {
-        // miniprogram do not allow multi type
-        options.properties[name] = null;
-      }
-    });
-  }
   // add default options
   options.options = {
     multipleSlots: true,

+ 21 - 0
static/vant/common/relation.d.ts

@@ -0,0 +1,21 @@
+/// <reference types="miniprogram-api-typings" />
+declare type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
+export declare function useParent(
+  name: string,
+  onEffect?: (this: TrivialInstance) => void
+): {
+  relations: {
+    [x: string]: WechatMiniprogram.Component.RelationOption;
+  };
+  mixin: string;
+};
+export declare function useChildren(
+  name: string,
+  onEffect?: (this: TrivialInstance, target: TrivialInstance) => void
+): {
+  relations: {
+    [x: string]: WechatMiniprogram.Component.RelationOption;
+  };
+  mixin: string;
+};
+export {};

+ 64 - 0
static/vant/common/relation.js

@@ -0,0 +1,64 @@
+export function useParent(name, onEffect) {
+  const path = `../${name}/index`;
+  return {
+    relations: {
+      [path]: {
+        type: 'ancestor',
+        linked() {
+          onEffect && onEffect.call(this);
+        },
+        linkChanged() {
+          onEffect && onEffect.call(this);
+        },
+        unlinked() {
+          onEffect && onEffect.call(this);
+        },
+      },
+    },
+    mixin: Behavior({
+      created() {
+        Object.defineProperty(this, 'parent', {
+          get: () => this.getRelationNodes(path)[0],
+        });
+        Object.defineProperty(this, 'index', {
+          // @ts-ignore
+          get: () => {
+            var _a, _b;
+            return (_b =
+              (_a = this.parent) === null || _a === void 0
+                ? void 0
+                : _a.children) === null || _b === void 0
+              ? void 0
+              : _b.indexOf(this);
+          },
+        });
+      },
+    }),
+  };
+}
+export function useChildren(name, onEffect) {
+  const path = `../${name}/index`;
+  return {
+    relations: {
+      [path]: {
+        type: 'descendant',
+        linked(target) {
+          onEffect && onEffect.call(this, target);
+        },
+        linkChanged(target) {
+          onEffect && onEffect.call(this, target);
+        },
+        unlinked(target) {
+          onEffect && onEffect.call(this, target);
+        },
+      },
+    },
+    mixin: Behavior({
+      created() {
+        Object.defineProperty(this, 'children', {
+          get: () => this.getRelationNodes(path) || [],
+        });
+      },
+    }),
+  };
+}

+ 21 - 9
static/vant/common/utils.d.ts

@@ -1,19 +1,31 @@
-/// <reference types="wechat-miniprogram" />
-export declare function isDef(value: any): boolean;
-export declare function isObj(x: any): boolean;
+/// <reference types="miniprogram-api-typings" />
+export { isDef } from './validator';
 export declare function range(num: number, min: number, max: number): number;
-export declare function nextTick(fn: Function): void;
-export declare function getSystemInfoSync(): WechatMiniprogram.GetSystemInfoSyncResult;
+export declare function nextTick(cb: (...args: any[]) => void): void;
+export declare function getSystemInfoSync(): WechatMiniprogram.SystemInfo;
 export declare function addUnit(value?: string | number): string | undefined;
 export declare function requestAnimationFrame(
-  cb: Function
-): void | WechatMiniprogram.NodesRef;
+  cb: () => void
+): number | WechatMiniprogram.NodesRef;
 export declare function pickExclude(obj: unknown, keys: string[]): {};
 export declare function getRect(
-  this: WechatMiniprogram.Component.TrivialInstance,
+  context: WechatMiniprogram.Component.TrivialInstance,
   selector: string
 ): Promise<WechatMiniprogram.BoundingClientRectCallbackResult>;
 export declare function getAllRect(
-  this: WechatMiniprogram.Component.TrivialInstance,
+  context: WechatMiniprogram.Component.TrivialInstance,
   selector: string
 ): Promise<WechatMiniprogram.BoundingClientRectCallbackResult[]>;
+export declare function groupSetData(
+  context: WechatMiniprogram.Component.TrivialInstance,
+  cb: () => void
+): void;
+export declare function toPromise(
+  promiseLike: Promise<unknown> | unknown
+): Promise<unknown>;
+export declare function getCurrentPage<T>(): T &
+  WechatMiniprogram.OptionalInterface<WechatMiniprogram.Page.ILifetime> &
+  WechatMiniprogram.Page.InstanceProperties &
+  WechatMiniprogram.Page.InstanceMethods<WechatMiniprogram.IAnyObject> &
+  WechatMiniprogram.Page.Data<WechatMiniprogram.IAnyObject> &
+  WechatMiniprogram.IAnyObject;

+ 35 - 17
static/vant/common/utils.js

@@ -1,18 +1,17 @@
-import { isNumber, isPlainObject } from './validator';
-export function isDef(value) {
-  return value !== undefined && value !== null;
-}
-export function isObj(x) {
-  const type = typeof x;
-  return x !== null && (type === 'object' || type === 'function');
-}
+import { isDef, isNumber, isPlainObject, isPromise } from './validator';
+import { canIUseGroupSetData, canIUseNextTick } from './version';
+export { isDef } from './validator';
 export function range(num, min, max) {
   return Math.min(Math.max(num, min), max);
 }
-export function nextTick(fn) {
-  setTimeout(() => {
-    fn();
-  }, 1000 / 30);
+export function nextTick(cb) {
+  if (canIUseNextTick()) {
+    wx.nextTick(cb);
+  } else {
+    setTimeout(() => {
+      cb();
+    }, 1000 / 30);
+  }
 }
 let systemInfo;
 export function getSystemInfoSync() {
@@ -31,7 +30,9 @@ export function addUnit(value) {
 export function requestAnimationFrame(cb) {
   const systemInfo = getSystemInfoSync();
   if (systemInfo.platform === 'devtools') {
-    return nextTick(cb);
+    return setTimeout(() => {
+      cb();
+    }, 1000 / 30);
   }
   return wx
     .createSelectorQuery()
@@ -52,21 +53,38 @@ export function pickExclude(obj, keys) {
     return prev;
   }, {});
 }
-export function getRect(selector) {
+export function getRect(context, selector) {
   return new Promise((resolve) => {
     wx.createSelectorQuery()
-      .in(this)
+      .in(context)
       .select(selector)
       .boundingClientRect()
       .exec((rect = []) => resolve(rect[0]));
   });
 }
-export function getAllRect(selector) {
+export function getAllRect(context, selector) {
   return new Promise((resolve) => {
     wx.createSelectorQuery()
-      .in(this)
+      .in(context)
       .selectAll(selector)
       .boundingClientRect()
       .exec((rect = []) => resolve(rect[0]));
   });
 }
+export function groupSetData(context, cb) {
+  if (canIUseGroupSetData()) {
+    context.groupSetData(cb);
+  } else {
+    cb();
+  }
+}
+export function toPromise(promiseLike) {
+  if (isPromise(promiseLike)) {
+    return promiseLike;
+  }
+  return Promise.resolve(promiseLike);
+}
+export function getCurrentPage() {
+  const pages = getCurrentPages();
+  return pages[pages.length - 1];
+}

+ 1 - 1
static/vant/common/validator.d.ts

@@ -3,7 +3,7 @@ export declare function isPlainObject(
   val: unknown
 ): val is Record<string, unknown>;
 export declare function isPromise<T = unknown>(val: unknown): val is Promise<T>;
-export declare function isDef(value: any): boolean;
+export declare function isDef(value: unknown): boolean;
 export declare function isObj(x: unknown): x is Record<string, unknown>;
 export declare function isNumber(value: string): boolean;
 export declare function isBoolean(value: unknown): value is boolean;

+ 1 - 0
static/vant/common/validator.js

@@ -1,3 +1,4 @@
+// eslint-disable-next-line @typescript-eslint/ban-types
 export function isFunction(val) {
   return typeof val === 'function';
 }

+ 5 - 0
static/vant/common/version.d.ts

@@ -1,2 +1,7 @@
 export declare function canIUseModel(): boolean;
 export declare function canIUseFormFieldButton(): boolean;
+export declare function canIUseAnimate(): boolean;
+export declare function canIUseGroupSetData(): boolean;
+export declare function canIUseNextTick(): boolean;
+export declare function canIUseCanvas2d(): boolean;
+export declare function canIUseGetUserProfile(): boolean;

+ 21 - 4
static/vant/common/version.js

@@ -21,11 +21,28 @@ function compareVersion(v1, v2) {
   }
   return 0;
 }
-export function canIUseModel() {
+function gte(version) {
   const system = getSystemInfoSync();
-  return compareVersion(system.SDKVersion, '2.9.3') >= 0;
+  return compareVersion(system.SDKVersion, version) >= 0;
+}
+export function canIUseModel() {
+  return gte('2.9.3');
 }
 export function canIUseFormFieldButton() {
-  const system = getSystemInfoSync();
-  return compareVersion(system.SDKVersion, '2.10.3') >= 0;
+  return gte('2.10.3');
+}
+export function canIUseAnimate() {
+  return gte('2.9.0');
+}
+export function canIUseGroupSetData() {
+  return gte('2.4.0');
+}
+export function canIUseNextTick() {
+  return wx.canIUse('nextTick');
+}
+export function canIUseCanvas2d() {
+  return gte('2.9.0');
+}
+export function canIUseGetUserProfile() {
+  return !!wx.getUserProfile;
 }

+ 1 - 0
static/vant/config-provider/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 9 - 0
static/vant/config-provider/index.js

@@ -0,0 +1,9 @@
+import { VantComponent } from '../common/component';
+VantComponent({
+  props: {
+    themeVars: {
+      type: Object,
+      value: {},
+    },
+  },
+});

+ 3 - 0
static/vant/config-provider/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 5 - 0
static/vant/config-provider/index.wxml

@@ -0,0 +1,5 @@
+<wxs src="./index.wxs" module="computed" />
+
+<view class="van-config-provider" style="{{ computed.mapThemeVarsToCSSVars(themeVars) }}">
+  <slot />
+</view>

+ 29 - 0
static/vant/config-provider/index.wxs

@@ -0,0 +1,29 @@
+/* eslint-disable */
+var object = require('../wxs/object.wxs');
+var style = require('../wxs/style.wxs');
+
+function kebabCase(word) {
+  var newWord = word
+    .replace(getRegExp("[A-Z]", 'g'), function (i) {
+      return '-' + i;
+    })
+    .toLowerCase()
+    .replace(getRegExp("^-"), '');
+
+  return newWord;
+}
+
+function mapThemeVarsToCSSVars(themeVars) {
+  var cssVars = {};
+  object.keys(themeVars).forEach(function (key) {
+    var cssVarsKey = '--' + kebabCase(key);
+    cssVars[cssVarsKey] = themeVars[key];
+  });
+
+  return style(cssVars);
+}
+
+module.exports = {
+  kebabCase: kebabCase,
+  mapThemeVarsToCSSVars: mapThemeVarsToCSSVars,
+};

+ 11 - 12
static/vant/datetime-picker/index.js

@@ -1,5 +1,5 @@
 import { VantComponent } from '../common/component';
-import { isDef } from '../common/utils';
+import { isDef } from '../common/validator';
 import { pickerProps } from '../picker/shared';
 const currentYear = new Date().getFullYear();
 function isValidDate(date) {
@@ -20,7 +20,9 @@ function times(n, iteratee) {
   return result;
 }
 function getTrueValue(formattedValue) {
-  if (!formattedValue) return;
+  if (formattedValue === undefined) {
+    formattedValue = '1';
+  }
   while (isNaN(parseInt(formattedValue, 10))) {
     formattedValue = formattedValue.slice(1);
   }
@@ -29,7 +31,7 @@ function getTrueValue(formattedValue) {
 function getMonthEndDay(year, month) {
   return 32 - new Date(year, month - 1, 32).getDate();
 }
-const defaultFormatter = (_, value) => value;
+const defaultFormatter = (type, value) => value;
 VantComponent({
   classes: ['active-class', 'toolbar-class', 'column-class'],
   props: Object.assign(Object.assign({}, pickerProps), {
@@ -91,13 +93,11 @@ VantComponent({
       const { data } = this;
       const val = this.correctValue(data.value);
       const isEqual = val === data.innerValue;
-      if (!isEqual) {
-        this.updateColumnValue(val).then(() => {
+      this.updateColumnValue(val).then(() => {
+        if (!isEqual) {
           this.$emit('input', val);
-        });
-      } else {
-        this.updateColumns();
-      }
+        }
+      });
     },
     getPicker() {
       if (this.picker == null) {
@@ -120,9 +120,8 @@ VantComponent({
       const { filter } = this.data;
       const results = this.getRanges().map(({ type, range }) => {
         let values = times(range[1] - range[0] + 1, (index) => {
-          let value = range[0] + index;
-          value = type === 'year' ? `${value}` : padZero(value);
-          return value;
+          const value = range[0] + index;
+          return type === 'year' ? `${value}` : padZero(value);
         });
         if (filter) {
           values = filter(type, values);

+ 37 - 25
static/vant/definitions/index.d.ts

@@ -1,31 +1,43 @@
-/// <reference types="wechat-miniprogram" />
-import { Weapp } from './weapp';
-declare type RecordToAny<T> = {
-  [K in keyof T]: any;
-};
-export declare type CombinedComponentInstance<Data, Props, Methods> = Methods &
-  WechatMiniprogram.Component.TrivialInstance &
-  Weapp.FormField & {
-    data: Data & RecordToAny<Props>;
-  };
-export interface VantComponentOptions<Data, Props, Methods, Instance> {
+/// <reference types="miniprogram-api-typings" />
+interface VantComponentInstance {
+  parent: WechatMiniprogram.Component.TrivialInstance;
+  children: WechatMiniprogram.Component.TrivialInstance[];
+  index: number;
+  $emit: (
+    name: string,
+    detail?: unknown,
+    options?: WechatMiniprogram.Component.TriggerEventOption
+  ) => void;
+}
+export declare type VantComponentOptions<
+  Data extends WechatMiniprogram.Component.DataOption,
+  Props extends WechatMiniprogram.Component.PropertyOption,
+  Methods extends WechatMiniprogram.Component.MethodOption
+> = {
   data?: Data;
   field?: boolean;
   classes?: string[];
   mixins?: string[];
-  props?: Props & Weapp.PropertyOption;
-  relation?: Weapp.RelationOption<Instance> & {
-    type: 'ancestor' | 'descendant';
-    name: string;
-    current: string;
+  props?: Props;
+  relation?: {
+    relations: Record<string, WechatMiniprogram.Component.RelationOption>;
+    mixin: string;
   };
-  relations?: {
-    [componentName: string]: Weapp.RelationOption<Instance>;
-  };
-  methods?: Methods & Weapp.MethodOption<Instance>;
-  beforeCreate?: (this: Instance) => void;
-  created?: (this: Instance) => void;
-  mounted?: (this: Instance) => void;
-  destroyed?: (this: Instance) => void;
-}
+  methods?: Methods;
+  beforeCreate?: () => void;
+  created?: () => void;
+  mounted?: () => void;
+  destroyed?: () => void;
+} & ThisType<
+  VantComponentInstance &
+    WechatMiniprogram.Component.Instance<
+      Data & {
+        name: string;
+        value: any;
+      } & Record<string, any>,
+      Props,
+      Methods
+    > &
+    Record<string, any>
+>;
 export {};

+ 11 - 20
static/vant/dialog/dialog.d.ts

@@ -1,9 +1,10 @@
-/// <reference types="wechat-miniprogram" />
-declare type DialogOptions = {
+/// <reference types="miniprogram-api-typings" />
+export declare type Action = 'confirm' | 'cancel' | 'overlay';
+interface DialogOptions {
   lang?: string;
   show?: boolean;
   title?: string;
-  width?: string | number;
+  width?: string | number | null;
   zIndex?: number;
   theme?: string;
   context?:
@@ -16,7 +17,11 @@ declare type DialogOptions = {
   className?: string;
   customStyle?: string;
   transition?: string;
+  /**
+   * @deprecated use beforeClose instead
+   */
   asyncClose?: boolean;
+  beforeClose?: null | ((action: Action) => Promise<void> | void);
   businessId?: number;
   sessionFrom?: string;
   overlayStyle?: string;
@@ -32,31 +37,17 @@ declare type DialogOptions = {
   showCancelButton?: boolean;
   closeOnClickOverlay?: boolean;
   confirmButtonOpenType?: string;
-};
+}
 declare const Dialog: {
   (options: DialogOptions): Promise<
     WechatMiniprogram.Component.TrivialInstance
   >;
   alert(
     options: DialogOptions
-  ): Promise<
-    WechatMiniprogram.Component.Instance<
-      Record<string, any>,
-      Record<string, any>,
-      Record<string, any>,
-      Record<string, any>
-    >
-  >;
+  ): Promise<WechatMiniprogram.Component.TrivialInstance>;
   confirm(
     options: DialogOptions
-  ): Promise<
-    WechatMiniprogram.Component.Instance<
-      Record<string, any>,
-      Record<string, any>,
-      Record<string, any>,
-      Record<string, any>
-    >
-  >;
+  ): Promise<WechatMiniprogram.Component.TrivialInstance>;
   close(): void;
   stopLoading(): void;
   currentOptions: DialogOptions;

+ 9 - 1
static/vant/dialog/dialog.js

@@ -10,6 +10,7 @@ const defaultOptions = {
   selector: '#van-dialog',
   className: '',
   asyncClose: false,
+  beforeClose: null,
   transition: 'scale',
   customStyle: '',
   messageAlign: '',
@@ -35,7 +36,14 @@ const Dialog = (options) => {
     delete options.selector;
     if (dialog) {
       dialog.setData(
-        Object.assign({ onCancel: reject, onConfirm: resolve }, options)
+        Object.assign(
+          {
+            callback: (action, instance) => {
+              action === 'confirm' ? resolve(instance) : reject(instance);
+            },
+          },
+          options
+        )
       );
       wx.nextTick(() => {
         dialog.setData({ show: true });

+ 31 - 26
static/vant/dialog/index.js

@@ -1,9 +1,9 @@
 import { VantComponent } from '../common/component';
 import { button } from '../mixins/button';
-import { openType } from '../mixins/open-type';
 import { GRAY, RED } from '../common/color';
+import { toPromise } from '../common/utils';
 VantComponent({
-  mixins: [button, openType],
+  mixins: [button],
   props: {
     show: {
       type: Boolean,
@@ -22,6 +22,7 @@ VantComponent({
     customStyle: String,
     asyncClose: Boolean,
     messageAlign: String,
+    beforeClose: null,
     overlayStyle: String,
     useTitleSlot: Boolean,
     showCancelButton: Boolean,
@@ -66,6 +67,7 @@ VantComponent({
       confirm: false,
       cancel: false,
     },
+    callback: () => {},
   },
   methods: {
     onConfirm() {
@@ -75,19 +77,16 @@ VantComponent({
       this.handleAction('cancel');
     },
     onClickOverlay() {
-      this.onClose('overlay');
-    },
-    handleAction(action) {
-      if (this.data.asyncClose) {
-        this.setData({
-          [`loading.${action}`]: true,
-        });
-      }
-      this.onClose(action);
-    },
-    close() {
-      this.setData({
-        show: false,
+      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() {
@@ -98,18 +97,24 @@ VantComponent({
         },
       });
     },
-    onClose(action) {
-      if (!this.data.asyncClose) {
-        this.close();
-      }
-      this.$emit('close', action);
-      // 把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
+    handleAction(action) {
       this.$emit(action, { dialog: this });
-      const callback = this.data[
-        action === 'confirm' ? 'onConfirm' : 'onCancel'
-      ];
-      if (callback) {
-        callback(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();
+          }
+        });
       }
     },
   },

+ 1 - 1
static/vant/dialog/index.json

@@ -3,7 +3,7 @@
   "usingComponents": {
     "van-popup": "../popup/index",
     "van-button": "../button/index",
-    "van-goods-action": "../goods-action//index",
+    "van-goods-action": "../goods-action/index",
     "van-goods-action-button": "../goods-action-button/index"
   }
 }

+ 12 - 12
static/vant/dialog/index.wxml

@@ -58,12 +58,12 @@
       app-parameter="{{ appParameter }}"
 
       bind:click="onConfirm"
-      bindgetuserinfo="bindGetUserInfo"
-      bindcontact="bindContact"
-      bindgetphonenumber="bindGetPhoneNumber"
-      binderror="bindError"
-      bindlaunchapp="bindLaunchApp"
-      bindopensetting="bindOpenSetting"
+      bindgetuserinfo="onGetUserInfo"
+      bindcontact="onContact"
+      bindgetphonenumber="onGetPhoneNumber"
+      binderror="onError"
+      bindlaunchapp="onLaunchApp"
+      bindopensetting="onOpenSetting"
     >
       {{ confirmButtonText }}
     </van-goods-action-button>
@@ -100,12 +100,12 @@
       app-parameter="{{ appParameter }}"
 
       bind:click="onConfirm"
-      bindgetuserinfo="bindGetUserInfo"
-      bindcontact="bindContact"
-      bindgetphonenumber="bindGetPhoneNumber"
-      binderror="bindError"
-      bindlaunchapp="bindLaunchApp"
-      bindopensetting="bindOpenSetting"
+      bindgetuserinfo="onGetUserInfo"
+      bindcontact="onContact"
+      bindgetphonenumber="onGetPhoneNumber"
+      binderror="onError"
+      bindlaunchapp="onLaunchApp"
+      bindopensetting="onOpenSetting"
     >
       {{ confirmButtonText }}
     </van-button>

+ 7 - 28
static/vant/divider/index.js

@@ -1,33 +1,12 @@
 import { VantComponent } from '../common/component';
 VantComponent({
   props: {
-    dashed: {
-      type: Boolean,
-      value: false,
-    },
-    hairline: {
-      type: Boolean,
-      value: false,
-    },
-    contentPosition: {
-      type: String,
-      value: '',
-    },
-    fontSize: {
-      type: Number,
-      value: '',
-    },
-    borderColor: {
-      type: String,
-      value: '',
-    },
-    textColor: {
-      type: String,
-      value: '',
-    },
-    customStyle: {
-      type: String,
-      value: '',
-    },
+    dashed: Boolean,
+    hairline: Boolean,
+    contentPosition: String,
+    fontSize: String,
+    borderColor: String,
+    textColor: String,
+    customStyle: String,
   },
 });

+ 3 - 2
static/vant/divider/index.wxml

@@ -1,8 +1,9 @@
 <wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
 
 <view
-  class="custom-class {{ utils.bem('divider', [{dashed, hairline}, contentPosition]) }}"
-  style="{{ borderColor  ? 'border-color: ' + borderColor + ';' : '' }}{{ textColor ? 'color: ' + textColor + ';' : '' }} {{ fontSize ? 'font-size: ' + fontSize + 'px;' : '' }} {{ customStyle }}"
+  class="custom-class {{ utils.bem('divider', [{ dashed, hairline }, contentPosition]) }}"
+  style="{{ computed.rootStyle({ borderColor, textColor, fontSize, customStyle }) }}"
 >
   <slot />
 </view>

+ 18 - 0
static/vant/divider/index.wxs

@@ -0,0 +1,18 @@
+/* eslint-disable */
+var style = require('../wxs/style.wxs');
+var addUnit = require('../wxs/add-unit.wxs');
+
+function rootStyle(data) {
+  return style([
+    {
+      'border-color': data.borderColor,
+      color: data.textColor,
+      'font-size': addUnit(data.fontSize),
+    },
+    data.customStyle,
+  ]);
+}
+
+module.exports = {
+  rootStyle: rootStyle,
+};

+ 1 - 0
static/vant/dropdown-item/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 111 - 0
static/vant/dropdown-item/index.js

@@ -0,0 +1,111 @@
+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();
+      }
+    },
+  },
+});

+ 8 - 0
static/vant/dropdown-item/index.json

@@ -0,0 +1,8 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-popup": "../popup/index",
+    "van-cell": "../cell/index",
+    "van-icon": "../icon/index"
+  }
+}

+ 48 - 0
static/vant/dropdown-item/index.wxml

@@ -0,0 +1,48 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<view
+  wx: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 }}"
+    bind:enter="onOpen"
+    bind:leave="onClose"
+    bind:close="toggle"
+    bind:after-enter="onOpened"
+    bind:after-leave="onClosed"
+  >
+    <van-cell
+      wx:for="{{ options }}"
+      wx:key="value"
+      data-option="{{ item }}"
+      class="{{ utils.bem('dropdown-item__option', { active: item.value === value } ) }}"
+      clickable
+      icon="{{ item.icon }}"
+      bind:tap="onOptionTap"
+    >
+      <view
+        slot="title"
+        class="van-dropdown-item__title"
+        style="{{ item.value === value  ? 'color:' + activeColor : '' }}"
+      >
+        {{ item.text }}
+      </view>
+      <van-icon
+        wx:if="{{ item.value === value }}"
+        name="success"
+        class="van-dropdown-item__icon"
+        color="{{ activeColor }}"
+      />
+    </van-cell>
+
+    <slot />
+  </van-popup>
+</view>

+ 1 - 0
static/vant/dropdown-item/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-dropdown-item{position:fixed;right:0;left:0;overflow:hidden}.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:#ee0a24;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}

+ 5 - 0
static/vant/dropdown-item/shared.d.ts

@@ -0,0 +1,5 @@
+export interface Option {
+  text: string;
+  value: string | number;
+  icon: string;
+}

+ 1 - 0
static/vant/dropdown-item/shared.js

@@ -0,0 +1 @@
+export {};

+ 1 - 0
static/vant/dropdown-menu/index.d.ts

@@ -0,0 +1 @@
+export {};

+ 112 - 0
static/vant/dropdown-menu/index.js

@@ -0,0 +1,112 @@
+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);
+      }
+    },
+  },
+});

+ 3 - 0
static/vant/dropdown-menu/index.json

@@ -0,0 +1,3 @@
+{
+  "component": true
+}

+ 23 - 0
static/vant/dropdown-menu/index.wxml

@@ -0,0 +1,23 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
+
+<view class="van-dropdown-menu van-dropdown-menu--top-bottom">
+  <view
+    wx:for="{{ itemListData }}"
+    wx:key="index"
+    data-index="{{ index }}"
+    class="{{ utils.bem('dropdown-menu__item', { disabled: item.disabled }) }}"
+    bind:tap="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 />
+</view>

+ 16 - 0
static/vant/dropdown-menu/index.wxs

@@ -0,0 +1,16 @@
+/* eslint-disable */
+function displayTitle(item) {
+  if (item.title) {
+    return item.title;
+  }
+
+  var match = item.options.filter(function(option) {
+    return option.value === item.value;
+  });
+  var displayTitle = match.length ? match[0].text : '';
+  return displayTitle;
+}
+
+module.exports = {
+  displayTitle: displayTitle
+};

+ 1 - 0
static/vant/dropdown-menu/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-dropdown-menu{display:-webkit-flex;display:flex;box-shadow:0 2px 12px rgba(100,101,102,.12);-webkit-user-select:none;user-select:none;height:50px;height:var(--dropdown-menu-height,50px);background-color:#fff;background-color:var(--dropdown-menu-background-color,#fff)}.van-dropdown-menu__item{display:-webkit-flex;display:flex;-webkit-flex:1;flex:1;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;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:#969799;color:var(--dropdown-menu-title-disabled-text-color,#969799)}.van-dropdown-menu__title{position:relative;box-sizing:border-box;max-width:100%;padding:0 8px;padding:var(--dropdown-menu-title-padding,0 8px);color:#323233;color:var(--dropdown-menu-title-text-color,#323233);font-size:15px;font-size:var(--dropdown-menu-title-font-size,15px);line-height:18px;line-height:var(--dropdown-menu-title-line-height,18px)}.van-dropdown-menu__title:after{position:absolute;top:50%;right:-4px;margin-top:-5px;border-color:transparent transparent currentcolor currentcolor;border-style:solid;border-width:3px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:.8;content:""}.van-dropdown-menu__title--active{color:#ee0a24;color:var(--dropdown-menu-title-active-text-color,#ee0a24)}.van-dropdown-menu__title--down:after{margin-top:-1px;-webkit-transform:rotate(135deg);transform:rotate(135deg)}

+ 0 - 10
static/vant/empty/index.js

@@ -1,5 +1,4 @@
 import { VantComponent } from '../common/component';
-const PRESETS = ['error', 'search', 'default', 'network'];
 VantComponent({
   props: {
     description: String,
@@ -8,13 +7,4 @@ VantComponent({
       value: 'default',
     },
   },
-  created() {
-    if (PRESETS.indexOf(this.data.image) !== -1) {
-      this.setData({
-        imageUrl: `https://img.yzcdn.cn/vant/empty-image-${this.data.image}.png`,
-      });
-    } else {
-      this.setData({ imageUrl: this.data.image });
-    }
-  },
 });

+ 2 - 1
static/vant/empty/index.wxml

@@ -1,11 +1,12 @@
 <wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
 
 <view class="custom-class van-empty">
   <view class="van-empty__image">
     <slot name="image"></slot>
   </view>
   <view class="van-empty__image">
-    <image wx:if="{{ imageUrl }}" class="van-empty__image__img" src="{{ imageUrl }}" />
+    <image wx:if="{{ image }}" class="van-empty__image__img" src="{{ computed.imageUrl(image) }}" />
   </view>
 
   <view class="van-empty__description">

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio