xuqiang hace 4 años
padre
commit
d516dec321
Se han modificado 100 ficheros con 2434 adiciones y 4 borrados
  1. 39 4
      src/App.vue
  2. 1 0
      src/vant/action-sheet/index.d.ts
  3. 62 0
      src/vant/action-sheet/index.js
  4. 8 0
      src/vant/action-sheet/index.json
  5. 67 0
      src/vant/action-sheet/index.wxml
  6. 0 0
      src/vant/action-sheet/index.wxss
  7. 1 0
      src/vant/area/index.d.ts
  8. 223 0
      src/vant/area/index.js
  9. 6 0
      src/vant/area/index.json
  10. 18 0
      src/vant/area/index.wxml
  11. 1 0
      src/vant/area/index.wxss
  12. 1 0
      src/vant/button/index.d.ts
  13. 79 0
      src/vant/button/index.js
  14. 7 0
      src/vant/button/index.json
  15. 68 0
      src/vant/button/index.wxml
  16. 0 0
      src/vant/button/index.wxss
  17. 57 0
      src/vant/calendar/calendar.wxml
  18. 1 0
      src/vant/calendar/components/header/index.d.ts
  19. 16 0
      src/vant/calendar/components/header/index.js
  20. 3 0
      src/vant/calendar/components/header/index.json
  21. 16 0
      src/vant/calendar/components/header/index.wxml
  22. 1 0
      src/vant/calendar/components/header/index.wxss
  23. 1 0
      src/vant/calendar/components/month/index.d.ts
  24. 148 0
      src/vant/calendar/components/month/index.js
  25. 3 0
      src/vant/calendar/components/month/index.json
  26. 39 0
      src/vant/calendar/components/month/index.wxml
  27. 67 0
      src/vant/calendar/components/month/index.wxs
  28. 0 0
      src/vant/calendar/components/month/index.wxss
  29. 1 0
      src/vant/calendar/index.d.ts
  30. 270 0
      src/vant/calendar/index.js
  31. 10 0
      src/vant/calendar/index.json
  32. 31 0
      src/vant/calendar/index.wxml
  33. 37 0
      src/vant/calendar/index.wxs
  34. 1 0
      src/vant/calendar/index.wxss
  35. 17 0
      src/vant/calendar/utils.d.ts
  36. 78 0
      src/vant/calendar/utils.js
  37. 25 0
      src/vant/calendar/utils.wxs
  38. 1 0
      src/vant/card/index.d.ts
  39. 42 0
      src/vant/card/index.js
  40. 6 0
      src/vant/card/index.json
  41. 50 0
      src/vant/card/index.wxml
  42. 0 0
      src/vant/card/index.wxss
  43. 1 0
      src/vant/cell-group/index.d.ts
  44. 10 0
      src/vant/cell-group/index.js
  45. 3 0
      src/vant/cell-group/index.json
  46. 9 0
      src/vant/cell-group/index.wxml
  47. 1 0
      src/vant/cell-group/index.wxss
  48. 1 0
      src/vant/cell/index.d.ts
  49. 32 0
      src/vant/cell/index.js
  50. 6 0
      src/vant/cell/index.json
  51. 45 0
      src/vant/cell/index.wxml
  52. 0 0
      src/vant/cell/index.wxss
  53. 1 0
      src/vant/checkbox-group/index.d.ts
  54. 35 0
      src/vant/checkbox-group/index.js
  55. 3 0
      src/vant/checkbox-group/index.json
  56. 1 0
      src/vant/checkbox-group/index.wxml
  57. 1 0
      src/vant/checkbox-group/index.wxss
  58. 1 0
      src/vant/checkbox/index.d.ts
  59. 74 0
      src/vant/checkbox/index.js
  60. 6 0
      src/vant/checkbox/index.json
  61. 20 0
      src/vant/checkbox/index.wxml
  62. 20 0
      src/vant/checkbox/index.wxs
  63. 1 0
      src/vant/checkbox/index.wxss
  64. 6 0
      src/vant/circle/canvas.d.ts
  65. 43 0
      src/vant/circle/canvas.js
  66. 1 0
      src/vant/circle/index.d.ts
  67. 180 0
      src/vant/circle/index.js
  68. 3 0
      src/vant/circle/index.json
  69. 9 0
      src/vant/circle/index.wxml
  70. 1 0
      src/vant/circle/index.wxss
  71. 1 0
      src/vant/col/index.d.ts
  72. 24 0
      src/vant/col/index.js
  73. 3 0
      src/vant/col/index.json
  74. 8 0
      src/vant/col/index.wxml
  75. 1 0
      src/vant/col/index.wxss
  76. 1 0
      src/vant/collapse-item/index.d.ts
  77. 98 0
      src/vant/collapse-item/index.js
  78. 6 0
      src/vant/collapse-item/index.json
  79. 44 0
      src/vant/collapse-item/index.wxml
  80. 1 0
      src/vant/collapse-item/index.wxss
  81. 1 0
      src/vant/collapse/index.d.ts
  82. 45 0
      src/vant/collapse/index.js
  83. 3 0
      src/vant/collapse/index.json
  84. 3 0
      src/vant/collapse/index.wxml
  85. 1 0
      src/vant/collapse/index.wxss
  86. 7 0
      src/vant/common/color.d.ts
  87. 7 0
      src/vant/common/color.js
  88. 3 0
      src/vant/common/component.d.ts
  89. 101 0
      src/vant/common/component.js
  90. 1 0
      src/vant/common/index.wxss
  91. 1 0
      src/vant/common/style/clearfix.wxss
  92. 1 0
      src/vant/common/style/ellipsis.wxss
  93. 1 0
      src/vant/common/style/hairline.wxss
  94. 0 0
      src/vant/common/style/mixins/clearfix.wxss
  95. 0 0
      src/vant/common/style/mixins/ellipsis.wxss
  96. 0 0
      src/vant/common/style/mixins/hairline.wxss
  97. 0 0
      src/vant/common/style/theme.wxss
  98. 0 0
      src/vant/common/style/var.wxss
  99. 11 0
      src/vant/common/utils.d.ts
  100. 45 0
      src/vant/common/utils.js

+ 39 - 4
src/App.vue

@@ -1,11 +1,40 @@
 <script>
 export default {
   onLaunch(options) {
+    wx.login({
+      success: res => {
+        console.log(res);
+        this.$http
+          .post("/auth/maLogin", { code: res.code })
+          .then(res => {
+            this.$http.setToken(res.token);
+            this.$store.commit("setSessionKey", res.sessionKey);
+            this.$store
+              .dispatch("getUserInfo")
+              .then(() => {
+                this.globalData.initialize = true;
+                console.log(this.globalData);
+                if (this.globalData.initializeCallback) {
+                  this.globalData.initializeCallback();
+                }
+              })
+              .catch(() => {
+                this.globalData.initialize = true;
+              });
+          })
+          .catch(e => {
+            console.log(e);
+          });
+      }
+    });
+    wx.getSystemInfo({
+      success: res => {
+        console.log(res);
+        this.$store.commit("setSystemInfo", res);
+      }
+    });
+
     // Do something initial when launch.
-    console.log(
-      "App onLaunch, env文件自定义的环境变量VUE_APP_TEST值:",
-      process.env.VUE_APP_TEST
-    );
   },
   onShow(options) {
     // Do something when show.
@@ -26,3 +55,9 @@ export default {
   }
 };
 </script>
+
+<style lang="less" scoped>
+/deep/.van-image {
+  display: block;
+}
+</style>

+ 1 - 0
src/vant/action-sheet/index.d.ts

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

+ 62 - 0
src/vant/action-sheet/index.js

@@ -0,0 +1,62 @@
+import { VantComponent } from '../common/component';
+import { button } from '../mixins/button';
+import { openType } from '../mixins/open-type';
+VantComponent({
+    mixins: [button, openType],
+    props: {
+        show: Boolean,
+        title: String,
+        cancelText: String,
+        description: String,
+        round: {
+            type: Boolean,
+            value: true
+        },
+        zIndex: {
+            type: Number,
+            value: 100
+        },
+        actions: {
+            type: Array,
+            value: []
+        },
+        overlay: {
+            type: Boolean,
+            value: true
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true
+        },
+        closeOnClickAction: {
+            type: Boolean,
+            value: true
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true
+        }
+    },
+    methods: {
+        onSelect(event) {
+            const { index } = event.currentTarget.dataset;
+            const item = this.data.actions[index];
+            if (item && !item.disabled && !item.loading) {
+                this.$emit('select', item);
+                if (this.data.closeOnClickAction) {
+                    this.onClose();
+                }
+            }
+        },
+        onCancel() {
+            this.$emit('cancel');
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClickOverlay() {
+            this.$emit('click-overlay');
+            this.onClose();
+        }
+    }
+});

+ 8 - 0
src/vant/action-sheet/index.json

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

+ 67 - 0
src/vant/action-sheet/index.wxml

@@ -0,0 +1,67 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<van-popup
+  show="{{ show }}"
+  position="bottom"
+  round="{{ round }}"
+  z-index="{{ zIndex }}"
+  overlay="{{ overlay }}"
+  custom-class="van-action-sheet"
+  safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
+  close-on-click-overlay="{{ closeOnClickOverlay }}"
+  bind:close="onClickOverlay"
+>
+  <view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
+    {{ title }}
+    <van-icon
+      name="close"
+      custom-class="van-action-sheet__close"
+      bind:click="onClose"
+    />
+  </view>
+  <view wx:if="{{ description }}" class="van-action-sheet__description">
+    {{ description }}
+  </view>
+  <view wx:if="{{ actions && actions.length }}">
+    <!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
+    <button
+      wx:for="{{ actions }}"
+      wx:key="index"
+      open-type="{{ item.openType }}"
+      style="{{ item.color ? 'color: ' + item.color : '' }}"
+      class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ 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"
+      lang="{{ lang }}"
+      session-from="{{ sessionFrom }}"
+      send-message-title="{{ sendMessageTitle }}"
+      send-message-path="{{ sendMessagePath }}"
+      send-message-img="{{ sendMessageImg }}"
+      show-message-card="{{ showMessageCard }}"
+      app-parameter="{{ appParameter }}"
+    >
+      <block wx:if="{{ !item.loading }}">
+        {{ item.name }}
+        <text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
+      </block>
+      <van-loading wx:else custom-class="van-action-sheet__loading" size="20px" />
+    </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>
+</van-popup>

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


+ 1 - 0
src/vant/area/index.d.ts

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

+ 223 - 0
src/vant/area/index.js

@@ -0,0 +1,223 @@
+import { VantComponent } from '../common/component';
+import { pickerProps } from '../picker/shared';
+const COLUMNSPLACEHOLDERCODE = '000000';
+VantComponent({
+    classes: ['active-class', 'toolbar-class', 'column-class'],
+    props: Object.assign(Object.assign({}, pickerProps), {
+        value: {
+            type: String,
+            observer(value) {
+                this.code = value;
+                this.setValues();
+            }
+        },
+        areaList: {
+            type: Object,
+            value: {},
+            observer: 'setValues'
+        },
+        columnsNum: {
+            type: null,
+            value: 3,
+            observer(value) {
+                this.setData({
+                    displayColumns: this.data.columns.slice(0, +value)
+                });
+            }
+        },
+        columnsPlaceholder: {
+            type: Array,
+            observer(val) {
+                this.setData({
+                    typeToColumnsPlaceholder: {
+                        province: val[0] || '',
+                        city: val[1] || '',
+                        county: val[2] || ''
+                    }
+                });
+            }
+        }
+    }),
+    data: {
+        columns: [{ values: [] }, { values: [] }, { values: [] }],
+        displayColumns: [{ values: [] }, { values: [] }, { values: [] }],
+        typeToColumnsPlaceholder: {}
+    },
+    mounted() {
+        setTimeout(() => {
+            this.setValues();
+        }, 0);
+    },
+    methods: {
+        getPicker() {
+            if (this.picker == null) {
+                this.picker = this.selectComponent('.van-area__picker');
+            }
+            return this.picker;
+        },
+        onCancel(event) {
+            this.emit('cancel', event.detail);
+        },
+        onConfirm(event) {
+            const { index } = event.detail;
+            let { value } = event.detail;
+            value = this.parseOutputValues(value);
+            this.emit('confirm', { value, index });
+        },
+        emit(type, detail) {
+            detail.values = detail.value;
+            delete detail.value;
+            this.$emit(type, detail);
+        },
+        // parse output columns data
+        parseOutputValues(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 = '';
+                }
+                return value;
+            });
+        },
+        onChange(event) {
+            const { index, picker, value } = event.detail;
+            this.code = value[index].code;
+            this.setValues().then(() => {
+                this.$emit('change', {
+                    picker,
+                    values: this.parseOutputValues(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;
+            }
+            const list = this.getConfig(type);
+            result = Object.keys(list).map(code => ({
+                code,
+                name: list[code]
+            }));
+            if (code) {
+                // oversea code
+                if (code[0] === '9' && type === 'city') {
+                    code = '9';
+                }
+                result = result.filter(item => item.code.indexOf(code) === 0);
+            }
+            if (typeToColumnsPlaceholder[type] && result.length) {
+                // set columns placeholder
+                const codeFill =
+                    type === 'province'
+                        ? ''
+                        : type === 'city'
+                        ? COLUMNSPLACEHOLDERCODE.slice(2, 4)
+                        : COLUMNSPLACEHOLDERCODE.slice(4, 6);
+                result.unshift({
+                    code: `${code}${codeFill}`,
+                    name: typeToColumnsPlaceholder[type]
+                });
+            }
+            return result;
+        },
+        getIndex(type, code) {
+            let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
+            const list = this.getList(type, code.slice(0, compareNum - 2));
+            // oversea code
+            if (code[0] === '9' && type === 'province') {
+                compareNum = 1;
+            }
+            code = code.slice(0, compareNum);
+            for (let i = 0; i < list.length; i++) {
+                if (list[i].code.slice(0, compareNum) === code) {
+                    return i;
+                }
+            }
+            return 0;
+        },
+        setValues() {
+            const 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;
+            }
+            const stack = [];
+            const indexes = [];
+            const { columnsNum } = this.data;
+            if (columnsNum >= 1) {
+                stack.push(picker.setColumnValues(0, province, false));
+                indexes.push(this.getIndex('province', code));
+            }
+            if (columnsNum >= 2) {
+                stack.push(picker.setColumnValues(1, city, false));
+                indexes.push(this.getIndex('city', code));
+                if (city.length && code.slice(2, 4) === '00') {
+                    [{ code }] = city;
+                }
+            }
+            if (columnsNum === 3) {
+                stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
+                indexes.push(this.getIndex('county', code));
+            }
+            return Promise.all(stack)
+                .catch(() => {})
+                .then(() => picker.setIndexes(indexes))
+                .catch(() => {});
+        },
+        getValues() {
+            const picker = this.getPicker();
+            return picker ? picker.getValues().filter(value => !!value) : [];
+        },
+        getDetail() {
+            const values = this.getValues();
+            const area = {
+                code: '',
+                country: '',
+                province: '',
+                city: '',
+                county: ''
+            };
+            if (!values.length) {
+                return area;
+            }
+            const names = values.map(item => item.name);
+            area.code = values[values.length - 1].code;
+            if (area.code[0] === '9') {
+                area.country = names[1] || '';
+                area.province = names[2] || '';
+            } else {
+                area.province = names[0] || '';
+                area.city = names[1] || '';
+                area.county = names[2] || '';
+            }
+            return area;
+        },
+        reset(code) {
+            this.code = code || '';
+            return this.setValues();
+        }
+    }
+});

+ 6 - 0
src/vant/area/index.json

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

+ 18 - 0
src/vant/area/index.wxml

@@ -0,0 +1,18 @@
+<van-picker
+  class="van-area__picker"
+  active-class="active-class"
+  toolbar-class="toolbar-class"
+  column-class="column-class"
+  show-toolbar
+  value-key="name"
+  title="{{ title }}"
+  loading="{{ loading }}"
+  columns="{{ displayColumns }}"
+  item-height="{{ itemHeight }}"
+  visible-item-count="{{ visibleItemCount }}"
+  cancel-button-text="{{ cancelButtonText }}"
+  confirm-button-text="{{ confirmButtonText }}"
+  bind:change="onChange"
+  bind:confirm="onConfirm"
+  bind:cancel="onCancel"
+/>

+ 1 - 0
src/vant/area/index.wxss

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

+ 1 - 0
src/vant/button/index.d.ts

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

+ 79 - 0
src/vant/button/index.js

@@ -0,0 +1,79 @@
+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];
+if (canIUseFormFieldButton()) {
+    mixins.push('wx://form-field-button');
+}
+VantComponent({
+    mixins,
+    classes: ['hover-class', 'loading-class'],
+    data: {
+        baseStyle: ''
+    },
+    props: {
+        formType: String,
+        icon: String,
+        classPrefix: {
+            type: String,
+            value: 'van-icon'
+        },
+        plain: Boolean,
+        block: Boolean,
+        round: Boolean,
+        square: Boolean,
+        loading: Boolean,
+        hairline: Boolean,
+        disabled: Boolean,
+        loadingText: String,
+        customStyle: String,
+        loadingType: {
+            type: String,
+            value: 'circular'
+        },
+        type: {
+            type: String,
+            value: 'default'
+        },
+        dataset: null,
+        size: {
+            type: String,
+            value: 'normal'
+        },
+        loadingSize: {
+            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 });
+                }
+            }
+        }
+    },
+    methods: {
+        onClick() {
+            if (!this.data.loading) {
+                this.$emit('click');
+            }
+        },
+        noop() {}
+    }
+});

+ 7 - 0
src/vant/button/index.json

@@ -0,0 +1,7 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-icon": "../icon/index",
+    "van-loading": "../loading/index"
+  }
+}

+ 68 - 0
src/vant/button/index.wxml

@@ -0,0 +1,68 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<button
+  id="{{ id }}"
+  data-detail="{{ dataset }}"
+  class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
+  hover-class="van-button--active hover-class"
+  lang="{{ lang }}"
+  form-type="{{ formType }}"
+  style="{{ baseStyle }} {{ customStyle }}"
+  open-type="{{ disabled ? '' : openType }}"
+  business-id="{{ businessId }}"
+  session-from="{{ sessionFrom }}"
+  send-message-title="{{ sendMessageTitle }}"
+  send-message-path="{{ sendMessagePath }}"
+  send-message-img="{{ sendMessageImg }}"
+  show-message-card="{{ showMessageCard }}"
+  app-parameter="{{ appParameter }}"
+  aria-label="{{ ariaLabel }}"
+  bindtap="{{ !disabled ? 'onClick' : 'noop' }}"
+  bindgetuserinfo="bindGetUserInfo"
+  bindcontact="bindContact"
+  bindgetphonenumber="bindGetPhoneNumber"
+  binderror="bindError"
+  bindlaunchapp="bindLaunchApp"
+  bindopensetting="bindOpenSetting"
+>
+  <block wx:if="{{ loading }}">
+    <van-loading
+      custom-class="loading-class"
+      size="{{ loadingSize }}"
+      type="{{ loadingType }}"
+      color="{{ loadingColor(type,color,plain) }}"
+    />
+    <view wx:if="{{ loadingText }}" class="van-button__loading-text">
+      {{ loadingText }}
+    </view>
+  </block>
+  <block wx:else>
+    <van-icon
+      wx:if="{{ icon }}"
+      size="1.2em"
+      name="{{ icon }}"
+      class-prefix="{{ classPrefix }}"
+      class="van-button__icon"
+      custom-style="line-height: inherit;"
+    />
+    <view class="van-button__text">
+      <slot />
+    </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>

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


+ 57 - 0
src/vant/calendar/calendar.wxml

@@ -0,0 +1,57 @@
+<wxs src="./index.wxs" module="computed"></wxs>
+
+<template name="calendar">
+  <view class="van-calendar">
+    <header
+      title="{{ title }}"
+      showTitle="{{ showTitle }}"
+      subtitle="{{ subtitle }}"
+      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>
+
+    <view class="van-calendar__footer {{ safeAreaInsetBottom ? 'van-calendar__footer--safe-area-inset-bottom' : '' }}">
+      <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>
+</template>

+ 1 - 0
src/vant/calendar/components/header/index.d.ts

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

+ 16 - 0
src/vant/calendar/components/header/index.js

@@ -0,0 +1,16 @@
+import { VantComponent } from '../../../common/component';
+VantComponent({
+    props: {
+        title: {
+            type: String,
+            value: '日期选择'
+        },
+        subtitle: String,
+        showTitle: Boolean,
+        showSubtitle: Boolean
+    },
+    data: {
+        weekdays: ['日', '一', '二', '三', '四', '五', '六']
+    },
+    methods: {}
+});

+ 3 - 0
src/vant/calendar/components/header/index.json

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

+ 16 - 0
src/vant/calendar/components/header/index.wxml

@@ -0,0 +1,16 @@
+<view class="van-calendar__header">
+  <block wx:if="{{ showTitle }}">
+    <view class="van-calendar__header-title"><slot name="title"></slot></view>
+    <view class="van-calendar__header-title">{{ title }}</view>
+  </block>
+
+  <view wx:if="{{ showSubtitle }}" class="van-calendar__header-subtitle">
+    {{ subtitle }}
+  </view>
+
+  <view class="van-calendar__weekdays">
+    <view wx:for="{{ weekdays }}" wx:key="index" class="van-calendar__weekday">
+      {{ item }}
+    </view>
+  </view>
+</view>

+ 1 - 0
src/vant/calendar/components/header/index.wxss

@@ -0,0 +1 @@
+@import '../../../common/index.wxss';.van-calendar__header{-webkit-flex-shrink:0;flex-shrink:0;box-shadow:0 2px 10px rgba(125,126,128,.16);box-shadow:var(--calendar-header-box-shadow,0 2px 10px rgba(125,126,128,.16))}.van-calendar__header-subtitle,.van-calendar__header-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:-webkit-flex;display:flex}.van-calendar__weekday{-webkit-flex:1;flex:1;text-align:center;font-size:12px;font-size:var(--calendar-weekdays-font-size,12px);line-height:30px;line-height:var(--calendar-weekdays-height,30px)}

+ 1 - 0
src/vant/calendar/components/month/index.d.ts

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

+ 148 - 0
src/vant/calendar/components/month/index.js

@@ -0,0 +1,148 @@
+import { VantComponent } from '../../../common/component';
+import { getMonthEndDay, compareDay, getPrevDay, getNextDay } from '../../utils';
+VantComponent({
+    props: {
+        date: {
+            type: null,
+            observer: 'setDays'
+        },
+        type: {
+            type: String,
+            observer: 'setDays'
+        },
+        color: String,
+        minDate: {
+            type: null,
+            observer: 'setDays'
+        },
+        maxDate: {
+            type: null,
+            observer: 'setDays'
+        },
+        showMark: Boolean,
+        rowHeight: [Number, String],
+        formatter: {
+            type: null,
+            observer: 'setDays'
+        },
+        currentDate: {
+            type: [null, Array],
+            observer: 'setDays'
+        },
+        allowSameDay: Boolean,
+        showSubtitle: Boolean,
+        showMonthTitle: Boolean
+    },
+    data: {
+        visible: true,
+        days: []
+    },
+    methods: {
+        onClick(event) {
+            const { index } = event.currentTarget.dataset;
+            const item = this.data.days[index];
+            if (item.type !== 'disabled') {
+                this.$emit('click', item);
+            }
+        },
+        setDays() {
+            const days = [];
+            const startDate = new Date(this.data.date);
+            const year = startDate.getFullYear();
+            const month = startDate.getMonth();
+            const totalDay = getMonthEndDay(startDate.getFullYear(), startDate.getMonth() + 1);
+            for (let day = 1; day <= totalDay; day++) {
+                const date = new Date(year, month, day);
+                const type = this.getDayType(date);
+                let config = {
+                    date,
+                    type,
+                    text: day,
+                    bottomInfo: this.getBottomInfo(type)
+                };
+                if (this.data.formatter) {
+                    config = this.data.formatter(config);
+                }
+                days.push(config);
+            }
+            this.setData({ days });
+        },
+        getMultipleDayType(day) {
+            const { currentDate } = this.data;
+            if (!Array.isArray(currentDate)) {
+                return '';
+            }
+            const isSelected = date => currentDate.some(item => compareDay(item, date) === 0);
+            if (isSelected(day)) {
+                const prevDay = getPrevDay(day);
+                const nextDay = getNextDay(day);
+                const prevSelected = isSelected(prevDay);
+                const nextSelected = isSelected(nextDay);
+                if (prevSelected && nextSelected) {
+                    return 'multiple-middle';
+                }
+                if (prevSelected) {
+                    return 'end';
+                }
+                return nextSelected ? 'start' : 'multiple-selected';
+            }
+            return '';
+        },
+        getRangeDayType(day) {
+            const { currentDate, allowSameDay } = this.data;
+            if (!Array.isArray(currentDate)) {
+                return;
+            }
+            const [startDay, endDay] = currentDate;
+            if (!startDay) {
+                return;
+            }
+            const compareToStart = compareDay(day, startDay);
+            if (!endDay) {
+                return compareToStart === 0 ? 'start' : '';
+            }
+            const compareToEnd = compareDay(day, endDay);
+            if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
+                return 'start-end';
+            }
+            if (compareToStart === 0) {
+                return 'start';
+            }
+            if (compareToEnd === 0) {
+                return 'end';
+            }
+            if (compareToStart > 0 && compareToEnd < 0) {
+                return 'middle';
+            }
+        },
+        getDayType(day) {
+            const { type, minDate, maxDate, currentDate } = this.data;
+            if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
+                return 'disabled';
+            }
+            if (type === 'single') {
+                return compareDay(day, currentDate) === 0 ? 'selected' : '';
+            }
+            if (type === 'multiple') {
+                return this.getMultipleDayType(day);
+            }
+            /* istanbul ignore else */
+            if (type === 'range') {
+                return this.getRangeDayType(day);
+            }
+        },
+        getBottomInfo(type) {
+            if (this.data.type === 'range') {
+                if (type === 'start') {
+                    return '开始';
+                }
+                if (type === 'end') {
+                    return '结束';
+                }
+                if (type === 'start-end') {
+                    return '开始/结束';
+                }
+            }
+        }
+    }
+});

+ 3 - 0
src/vant/calendar/components/month/index.json

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

+ 39 - 0
src/vant/calendar/components/month/index.wxml

@@ -0,0 +1,39 @@
+<wxs src="./index.wxs" module="computed"></wxs>
+<wxs src="../../../wxs/utils.wxs" module="utils" />
+
+<view class="van-calendar__month" style="{{ computed.getMonthStyle(visible, date, rowHeight) }}">
+  <view wx:if="{{ showMonthTitle }}" class="van-calendar__month-title">
+    {{ computed.formatMonthTitle(date) }}
+  </view>
+
+  <view wx:if="{{ visible }}" class="van-calendar__days">
+    <view wx:if="{{ showMark }}" class="van-calendar__month-mark">
+      {{ computed.getMark(date) }}
+    </view>
+
+    <view
+      wx:for="{{ days }}"
+      wx:key="index"
+      style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color) }}"
+      class="{{ utils.bem('calendar__day', [item.type]) }} {{ item.className }}"
+      data-index="{{ index }}"
+      bindtap="onClick"
+    >
+      <view wx:if="{{ item.type === 'selected' }}" class="van-calendar__selected-day" style="background: {{ color }}">
+        <view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
+        {{ item.text }}
+        <view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
+          {{ item.bottomInfo }}
+        </view>
+      </view>
+
+      <view wx:else>
+        <view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
+        {{ item.text }}
+        <view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
+          {{ item.bottomInfo }}
+        </view>
+      </view>
+    </view>
+  </view>
+</view>

+ 67 - 0
src/vant/calendar/components/month/index.wxs

@@ -0,0 +1,67 @@
+/* eslint-disable */
+var utils = require('../../utils.wxs');
+
+function getMark(date) {
+  return getDate(date).getMonth() + 1;
+}
+
+var ROW_HEIGHT = 64;
+
+function getDayStyle(type, index, date, rowHeight, color) {
+  var style = [];
+  var offset = getDate(date).getDay();
+
+  if (index === 0) {
+    style.push(['margin-left', (100 * offset) / 7 + '%']);
+  }
+
+  if (rowHeight !== ROW_HEIGHT) {
+    style.push(['height', rowHeight + 'px']);
+  }
+
+  if (color) {
+    if (
+      type === 'start' ||
+      type === 'end' ||
+      type === 'multiple-selected' ||
+      type === 'multiple-middle'
+    ) {
+      style.push(['background', color]);
+    } else if (type === 'middle') {
+      style.push(['color', color]);
+    }
+  }
+
+  return style
+    .map(function(item) {
+      return item.join(':');
+    })
+    .join(';');
+}
+
+function formatMonthTitle(date) {
+  date = getDate(date);
+  return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
+}
+
+function getMonthStyle(visible, date, rowHeight) {
+  if (!visible) {
+    date = getDate(date);
+
+    var totalDay = utils.getMonthEndDay(
+      date.getFullYear(),
+      date.getMonth() + 1
+    );
+    var offset = getDate(date).getDay();
+    var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
+
+    return 'padding-bottom:' + padding + 'px';
+  }
+}
+
+module.exports = {
+  getMark: getMark,
+  getDayStyle: getDayStyle,
+  formatMonthTitle: formatMonthTitle,
+  getMonthStyle: getMonthStyle
+};

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
src/vant/calendar/components/month/index.wxss


+ 1 - 0
src/vant/calendar/index.d.ts

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

+ 270 - 0
src/vant/calendar/index.js

@@ -0,0 +1,270 @@
+import { VantComponent } from '../common/component';
+import {
+    ROW_HEIGHT,
+    getNextDay,
+    compareDay,
+    copyDates,
+    calcDateNum,
+    formatMonthTitle,
+    compareMonth,
+    getMonths,
+    getDayByOffset
+} from './utils';
+import Toast from '../toast/toast';
+VantComponent({
+    props: {
+        title: {
+            type: String,
+            value: '日期选择'
+        },
+        color: String,
+        show: {
+            type: Boolean,
+            observer(val) {
+                if (val) {
+                    this.initRect();
+                    this.scrollIntoView();
+                }
+            }
+        },
+        formatter: null,
+        confirmText: {
+            type: String,
+            value: '确定'
+        },
+        rangePrompt: String,
+        defaultDate: {
+            type: [Number, Array],
+            observer(val) {
+                this.setData({ currentDate: val });
+                this.scrollIntoView();
+            }
+        },
+        allowSameDay: Boolean,
+        confirmDisabledText: String,
+        type: {
+            type: String,
+            value: 'single',
+            observer: 'reset'
+        },
+        minDate: {
+            type: null,
+            value: Date.now()
+        },
+        maxDate: {
+            type: null,
+            value: new Date(new Date().getFullYear(), new Date().getMonth() + 6, new Date().getDate()).getTime()
+        },
+        position: {
+            type: String,
+            value: 'bottom'
+        },
+        rowHeight: {
+            type: [Number, String],
+            value: ROW_HEIGHT
+        },
+        round: {
+            type: Boolean,
+            value: true
+        },
+        poppable: {
+            type: Boolean,
+            value: true
+        },
+        showMark: {
+            type: Boolean,
+            value: true
+        },
+        showTitle: {
+            type: Boolean,
+            value: true
+        },
+        showConfirm: {
+            type: Boolean,
+            value: true
+        },
+        showSubtitle: {
+            type: Boolean,
+            value: true
+        },
+        safeAreaInsetBottom: {
+            type: Boolean,
+            value: true
+        },
+        closeOnClickOverlay: {
+            type: Boolean,
+            value: true
+        },
+        maxRange: {
+            type: [Number, String],
+            value: null
+        }
+    },
+    data: {
+        subtitle: '',
+        currentDate: null,
+        scrollIntoView: ''
+    },
+    created() {
+        this.setData({
+            currentDate: this.getInitialDate()
+        });
+    },
+    mounted() {
+        if (this.data.show || !this.data.poppable) {
+            this.initRect();
+            this.scrollIntoView();
+        }
+    },
+    methods: {
+        reset() {
+            this.setData({ currentDate: this.getInitialDate() });
+            this.scrollIntoView();
+        },
+        initRect() {
+            if (this.contentObserver != null) {
+                this.contentObserver.disconnect();
+            }
+            const contentObserver = this.createIntersectionObserver({
+                thresholds: [0, 0.1, 0.9, 1],
+                observeAll: true
+            });
+            this.contentObserver = contentObserver;
+            contentObserver.relativeTo('.van-calendar__body');
+            contentObserver.observe('.month', res => {
+                if (res.boundingClientRect.top <= res.relativeRect.top) {
+                    // @ts-ignore
+                    this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
+                }
+            });
+        },
+        getInitialDate() {
+            const { type, defaultDate, minDate } = this.data;
+            if (type === 'range') {
+                const [startDay, endDay] = defaultDate || [];
+                return [startDay || minDate, endDay || getNextDay(new Date(minDate)).getTime()];
+            }
+            if (type === 'multiple') {
+                return defaultDate || [minDate];
+            }
+            return defaultDate || minDate;
+        },
+        scrollIntoView() {
+            setTimeout(() => {
+                const { currentDate, type, show, poppable, minDate, maxDate } = this.data;
+                const targetDate = type === 'single' ? currentDate : currentDate[0];
+                const displayed = show || !poppable;
+                if (!targetDate || !displayed) {
+                    return;
+                }
+                const months = getMonths(minDate, maxDate);
+                months.some((month, index) => {
+                    if (compareMonth(month, targetDate) === 0) {
+                        this.setData({ scrollIntoView: `month${index}` });
+                        return true;
+                    }
+                    return false;
+                });
+            }, 100);
+        },
+        onOpen() {
+            this.$emit('open');
+        },
+        onOpened() {
+            this.$emit('opened');
+        },
+        onClose() {
+            this.$emit('close');
+        },
+        onClosed() {
+            this.$emit('closed');
+        },
+        onClickDay(event) {
+            const { date } = event.detail;
+            const { type, currentDate, allowSameDay } = this.data;
+            if (type === 'range') {
+                const [startDay, endDay] = currentDate;
+                if (startDay && !endDay) {
+                    const compareToStart = compareDay(date, startDay);
+                    if (compareToStart === 1) {
+                        this.select([startDay, date], true);
+                    } else if (compareToStart === -1) {
+                        this.select([date, null]);
+                    } else if (allowSameDay) {
+                        this.select([date, date]);
+                    }
+                } else {
+                    this.select([date, null]);
+                }
+            } else if (type === 'multiple') {
+                let selectedIndex;
+                const selected = currentDate.some((dateItem, index) => {
+                    const equal = compareDay(dateItem, date) === 0;
+                    if (equal) {
+                        selectedIndex = index;
+                    }
+                    return equal;
+                });
+                if (selected) {
+                    const cancelDate = currentDate.splice(selectedIndex, 1);
+                    this.setData({ currentDate });
+                    this.unselect(cancelDate);
+                } else {
+                    this.select([...currentDate, date]);
+                }
+            } else {
+                this.select(date, true);
+            }
+        },
+        unselect(dateArray) {
+            const date = dateArray[0];
+            if (date) {
+                this.$emit('unselect', copyDates(date));
+            }
+        },
+        select(date, complete) {
+            if (complete && this.data.type === 'range') {
+                const valid = this.checkRange(date);
+                if (!valid) {
+                    // auto selected to max range if showConfirm
+                    if (this.data.showConfirm) {
+                        this.emit([date[0], getDayByOffset(date[0], this.data.maxRange - 1)]);
+                    } else {
+                        this.emit(date);
+                    }
+                    return;
+                }
+            }
+            this.emit(date);
+            if (complete && !this.data.showConfirm) {
+                this.onConfirm();
+            }
+        },
+        emit(date) {
+            const getTime = date => (date instanceof Date ? date.getTime() : date);
+            this.setData({
+                currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date)
+            });
+            this.$emit('select', copyDates(date));
+        },
+        checkRange(date) {
+            const { maxRange, rangePrompt } = this.data;
+            if (maxRange && calcDateNum(date) > maxRange) {
+                Toast({
+                    context: this,
+                    message: rangePrompt || `选择天数不能超过 ${maxRange} 天`
+                });
+                return false;
+            }
+            return true;
+        },
+        onConfirm() {
+            if (this.data.type === 'range' && !this.checkRange(this.data.currentDate)) {
+                return;
+            }
+            wx.nextTick(() => {
+                this.$emit('confirm', copyDates(this.data.currentDate));
+            });
+        }
+    }
+});

+ 10 - 0
src/vant/calendar/index.json

@@ -0,0 +1,10 @@
+{
+  "component": true,
+  "usingComponents": {
+    "header": "./components/header/index",
+    "month": "./components/month/index",
+    "van-button": "../button/index",
+    "van-popup": "../popup/index",
+    "van-toast": "../toast/index"
+  }
+}

+ 31 - 0
src/vant/calendar/index.wxml

@@ -0,0 +1,31 @@
+<wxs src="./index.wxs" module="computed" />
+
+<import src="./calendar.wxml" />
+
+<van-popup
+  wx:if="{{ poppable }}"
+  custom-class="van-calendar__popup--{{ position }}"
+  close-icon-class="van-calendar__close-icon"
+  show="{{ show }}"
+  round="{{ round }}"
+  position="{{ position }}"
+  closeable="{{ showTitle || showSubtitle }}"
+  close-on-click-overlay="{{ closeOnClickOverlay }}"
+  bind:enter="onOpen"
+  bind:close="onClose"
+  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 }}"
+  />
+</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 }}"
+/>
+
+<van-toast id="van-toast" />

+ 37 - 0
src/vant/calendar/index.wxs

@@ -0,0 +1,37 @@
+/* eslint-disable */
+var utils = require('./utils.wxs');
+
+function getMonths(minDate, maxDate) {
+  var months = [];
+  var cursor = getDate(minDate);
+
+  cursor.setDate(1);
+
+  do {
+    months.push(cursor.getTime());
+    cursor.setMonth(cursor.getMonth() + 1);
+  } while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
+
+  return months;
+}
+
+function getButtonDisabled(type, currentDate) {
+  if (currentDate == null) {
+    return true;
+  }
+
+  if (type === 'range') {
+    return !currentDate[0] || !currentDate[1];
+  }
+
+  if (type === 'multiple') {
+    return !currentDate.length;
+  }
+
+  return !currentDate;
+}
+
+module.exports = {
+  getMonths: getMonths,
+  getButtonDisabled: getButtonDisabled
+};

+ 1 - 0
src/vant/calendar/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-calendar{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;height:100%;height:var(--calendar-height,100%);background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:80%;height:var(--calendar-popup-height,80%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-flex:1;flex:1;overflow:auto;-webkit-overflow-scrolling:touch}.van-calendar__footer{-webkit-flex-shrink:0;flex-shrink:0;padding:0 16px;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:36px!important;height:var(--calendar-confirm-button-height,36px)!important;margin:7px 0!important;margin:var(--calendar-confirm-button-margin,7px 0)!important;line-height:34px!important;line-height:var(--calendar-confirm-button-line-height,34px)!important}

+ 17 - 0
src/vant/calendar/utils.d.ts

@@ -0,0 +1,17 @@
+export declare const ROW_HEIGHT = 64;
+export declare function formatMonthTitle(date: Date): string;
+export declare function compareMonth(
+  date1: Date | number,
+  date2: Date | number
+): 0 | 1 | -1;
+export declare function compareDay(
+  day1: Date | number,
+  day2: Date | number
+): 0 | 1 | -1;
+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 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[];

+ 78 - 0
src/vant/calendar/utils.js

@@ -0,0 +1,78 @@
+export const ROW_HEIGHT = 64;
+export function formatMonthTitle(date) {
+    if (!(date instanceof Date)) {
+        date = new Date(date);
+    }
+    return `${date.getFullYear()}年${date.getMonth() + 1}月`;
+}
+export function compareMonth(date1, date2) {
+    if (!(date1 instanceof Date)) {
+        date1 = new Date(date1);
+    }
+    if (!(date2 instanceof Date)) {
+        date2 = new Date(date2);
+    }
+    const year1 = date1.getFullYear();
+    const year2 = date2.getFullYear();
+    const month1 = date1.getMonth();
+    const month2 = date2.getMonth();
+    if (year1 === year2) {
+        return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
+    }
+    return year1 > year2 ? 1 : -1;
+}
+export function compareDay(day1, day2) {
+    if (!(day1 instanceof Date)) {
+        day1 = new Date(day1);
+    }
+    if (!(day2 instanceof Date)) {
+        day2 = new Date(day2);
+    }
+    const compareMonthResult = compareMonth(day1, day2);
+    if (compareMonthResult === 0) {
+        const date1 = day1.getDate();
+        const date2 = day2.getDate();
+        return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
+    }
+    return compareMonthResult;
+}
+export function getDayByOffset(date, offset) {
+    date = new Date(date);
+    date.setDate(date.getDate() + offset);
+    return date;
+}
+export function getPrevDay(date) {
+    return getDayByOffset(date, -1);
+}
+export function getNextDay(date) {
+    return getDayByOffset(date, 1);
+}
+export function calcDateNum(date) {
+    const day1 = new Date(date[0]).getTime();
+    const day2 = new Date(date[1]).getTime();
+    return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
+}
+export function copyDates(dates) {
+    if (Array.isArray(dates)) {
+        return dates.map(date => {
+            if (date === null) {
+                return date;
+            }
+            return new Date(date);
+        });
+    }
+    return new Date(dates);
+}
+export function getMonthEndDay(year, month) {
+    return 32 - new Date(year, month - 1, 32).getDate();
+}
+export function getMonths(minDate, maxDate) {
+    const months = [];
+    const cursor = new Date(minDate);
+    cursor.setDate(1);
+    do {
+        months.push(cursor.getTime());
+        cursor.setMonth(cursor.getMonth() + 1);
+    } while (compareMonth(cursor, maxDate) !== 1);
+    return months;
+}

+ 25 - 0
src/vant/calendar/utils.wxs

@@ -0,0 +1,25 @@
+/* eslint-disable */
+function getMonthEndDay(year, month) {
+  return 32 -  getDate(year, month - 1, 32).getDate();
+}
+
+function compareMonth(date1, date2) {
+  date1 = getDate(date1);
+  date2 = getDate(date2);
+
+  var year1 = date1.getFullYear();
+  var year2 = date2.getFullYear();
+  var month1 = date1.getMonth();
+  var month2 = date2.getMonth();
+
+  if (year1 === year2) {
+    return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
+  }
+
+  return year1 > year2 ? 1 : -1;
+}
+
+module.exports = {
+  getMonthEndDay: getMonthEndDay,
+  compareMonth: compareMonth
+};

+ 1 - 0
src/vant/card/index.d.ts

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

+ 42 - 0
src/vant/card/index.js

@@ -0,0 +1,42 @@
+import { link } from '../mixins/link';
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: ['num-class', 'desc-class', 'thumb-class', 'title-class', 'price-class', 'origin-price-class'],
+    mixins: [link],
+    props: {
+        tag: String,
+        num: String,
+        desc: String,
+        thumb: String,
+        title: String,
+        price: {
+            type: String,
+            observer: 'updatePrice'
+        },
+        centered: Boolean,
+        lazyLoad: Boolean,
+        thumbLink: String,
+        originPrice: String,
+        thumbMode: {
+            type: String,
+            value: 'aspectFit'
+        },
+        currency: {
+            type: String,
+            value: '¥'
+        }
+    },
+    methods: {
+        updatePrice() {
+            const { price } = this.data;
+            const priceArr = price.toString().split('.');
+            this.setData({
+                integerStr: priceArr[0],
+                decimalStr: priceArr[1] ? `.${priceArr[1]}` : ''
+            });
+        },
+        onClickThumb() {
+            this.jumpLink('thumbLink');
+        }
+    }
+});

+ 6 - 0
src/vant/card/index.json

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

+ 50 - 0
src/vant/card/index.wxml

@@ -0,0 +1,50 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<view class="custom-class van-card">
+  <view class="{{ utils.bem('card__header', { center: centered }) }}">
+    <view class="van-card__thumb" bind:tap="onClickThumb">
+      <image
+        wx:if="{{ thumb }}"
+        src="{{ thumb }}"
+        mode="{{ thumbMode }}"
+        lazy-load="{{ lazyLoad }}"
+        class="van-card__img thumb-class"
+      />
+      <slot name="thumb" />
+      <van-tag
+        wx:if="{{ tag }}"
+        mark
+        type="danger"
+        custom-class="van-card__tag"
+      >
+        {{ tag }}
+      </van-tag>
+    </view>
+
+    <view class="van-card__content {{ utils.bem('card__content', { center: centered }) }}">
+      <view>
+        <view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
+        <slot wx:else name="title" />
+
+        <view wx:if="{{ desc }}" class="van-card__desc desc-class">{{ desc }}</view>
+        <slot wx:else name="desc" />
+
+        <slot name="tags" />
+      </view>
+
+      <view class="van-card__bottom">
+        <slot name="price-top" />
+        <view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }}<text class="van-card__price-integer">{{ integerStr }}</text><text class="van-card__price-decimal">{{ decimalStr }}</text></view>
+        <slot wx:else name="price" />
+        <view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
+        <view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
+        <slot wx:else  name="num" />
+        <slot name="bottom" />
+      </view>
+    </view>
+  </view>
+
+  <view class="van-card__footer">
+    <slot name="footer" />
+  </view>
+</view>

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


+ 1 - 0
src/vant/cell-group/index.d.ts

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

+ 10 - 0
src/vant/cell-group/index.js

@@ -0,0 +1,10 @@
+import { VantComponent } from '../common/component';
+VantComponent({
+    props: {
+        title: String,
+        border: {
+            type: Boolean,
+            value: true
+        }
+    }
+});

+ 3 - 0
src/vant/cell-group/index.json

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

+ 9 - 0
src/vant/cell-group/index.wxml

@@ -0,0 +1,9 @@
+<view
+  wx:if="{{ title }}"
+  class="van-cell-group__title"
+>
+  {{ title }}
+</view>
+<view class="custom-class van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
+  <slot />
+</view>

+ 1 - 0
src/vant/cell-group/index.wxss

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

+ 1 - 0
src/vant/cell/index.d.ts

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

+ 32 - 0
src/vant/cell/index.js

@@ -0,0 +1,32 @@
+import { link } from '../mixins/link';
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: ['title-class', 'label-class', 'value-class', 'right-icon-class', 'hover-class'],
+    mixins: [link],
+    props: {
+        title: null,
+        value: null,
+        icon: String,
+        size: String,
+        label: String,
+        center: Boolean,
+        isLink: Boolean,
+        required: Boolean,
+        clickable: Boolean,
+        titleWidth: String,
+        customStyle: String,
+        arrowDirection: String,
+        useLabelSlot: Boolean,
+        border: {
+            type: Boolean,
+            value: true
+        },
+        titleStyle: String
+    },
+    methods: {
+        onClick(event) {
+            this.$emit('click', event.detail);
+            this.jumpLink();
+        }
+    }
+});

+ 6 - 0
src/vant/cell/index.json

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

+ 45 - 0
src/vant/cell/index.wxml

@@ -0,0 +1,45 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<view
+  class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
+  hover-class="van-cell--hover hover-class"
+  hover-stay-time="70"
+  style="{{ customStyle }}"
+  bind:tap="onClick"
+>
+  <van-icon
+    wx:if="{{ icon }}"
+    name="{{ icon }}"
+    class="van-cell__left-icon-wrap"
+    custom-class="van-cell__left-icon"
+  />
+  <slot wx:else name="icon" />
+
+  <view
+    style="{{ (titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth + ';' : '') + titleStyle }}"
+    class="van-cell__title title-class"
+  >
+    <block wx:if="{{ title }}">{{ title }}</block>
+    <slot wx:else name="title" />
+
+    <view wx:if="{{ label || useLabelSlot }}" class="van-cell__label label-class">
+      <slot wx:if="{{ useLabelSlot }}" name="label" />
+      <block wx:elif="{{ label }}">{{ label }}</block>
+    </view>
+  </view>
+
+  <view class="van-cell__value value-class">
+    <block wx:if="{{ value || value === 0 }}">{{ value }}</block>
+    <slot wx:else />
+  </view>
+
+  <van-icon
+    wx:if="{{ isLink }}"
+    name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
+    class="van-cell__right-icon-wrap right-icon-class"
+    custom-class="van-cell__right-icon"
+  />
+  <slot wx:else name="right-icon" />
+
+  <slot name="extra" />
+</view>

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


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

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

+ 35 - 0
src/vant/checkbox-group/index.js

@@ -0,0 +1,35 @@
+import { VantComponent } from '../common/component';
+VantComponent({
+    field: true,
+    relation: {
+        name: 'checkbox',
+        type: 'descendant',
+        current: 'checkbox-group',
+        linked(target) {
+            this.updateChild(target);
+        }
+    },
+    props: {
+        max: Number,
+        value: {
+            type: Array,
+            observer: 'updateChildren'
+        },
+        disabled: {
+            type: Boolean,
+            observer: 'updateChildren'
+        }
+    },
+    methods: {
+        updateChildren() {
+            (this.children || []).forEach(child => this.updateChild(child));
+        },
+        updateChild(child) {
+            const { value, disabled } = this.data;
+            child.setData({
+                value: value.indexOf(child.data.name) !== -1,
+                parentDisabled: disabled
+            });
+        }
+    }
+});

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

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

+ 1 - 0
src/vant/checkbox-group/index.wxml

@@ -0,0 +1 @@
+<slot />

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

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

+ 1 - 0
src/vant/checkbox/index.d.ts

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

+ 74 - 0
src/vant/checkbox/index.js

@@ -0,0 +1,74 @@
+import { VantComponent } from '../common/component';
+function emit(target, value) {
+    target.$emit('input', value);
+    target.$emit('change', value);
+}
+VantComponent({
+    field: true,
+    relation: {
+        name: 'checkbox-group',
+        type: 'ancestor',
+        current: 'checkbox'
+    },
+    classes: ['icon-class', 'label-class'],
+    props: {
+        value: Boolean,
+        disabled: Boolean,
+        useIconSlot: Boolean,
+        checkedColor: String,
+        labelPosition: String,
+        labelDisabled: Boolean,
+        shape: {
+            type: String,
+            value: 'round'
+        },
+        iconSize: {
+            type: null,
+            value: 20
+        }
+    },
+    data: {
+        parentDisabled: false
+    },
+    methods: {
+        emitChange(value) {
+            if (this.parent) {
+                this.setParentValue(this.parent, value);
+            } else {
+                emit(this, value);
+            }
+        },
+        toggle() {
+            const { parentDisabled, disabled, value } = this.data;
+            if (!disabled && !parentDisabled) {
+                this.emitChange(!value);
+            }
+        },
+        onClickLabel() {
+            const { labelDisabled, parentDisabled, disabled, value } = this.data;
+            if (!disabled && !labelDisabled && !parentDisabled) {
+                this.emitChange(!value);
+            }
+        },
+        setParentValue(parent, value) {
+            const parentValue = parent.data.value.slice();
+            const { name } = this.data;
+            const { max } = parent.data;
+            if (value) {
+                if (max && parentValue.length >= max) {
+                    return;
+                }
+                if (parentValue.indexOf(name) === -1) {
+                    parentValue.push(name);
+                    emit(parent, parentValue);
+                }
+            } else {
+                const index = parentValue.indexOf(name);
+                if (index !== -1) {
+                    parentValue.splice(index, 1);
+                    emit(parent, parentValue);
+                }
+            }
+        }
+    }
+});

+ 6 - 0
src/vant/checkbox/index.json

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

+ 20 - 0
src/vant/checkbox/index.wxml

@@ -0,0 +1,20 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
+
+<view class="van-checkbox custom-class">
+  <view class="van-checkbox__icon-wrap" bindtap="toggle">
+    <slot wx:if="{{ useIconSlot }}" name="icon" />
+    <van-icon
+      wx:else
+      name="success"
+      size="0.8em"
+      class="{{ utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }]) }}"
+      style="{{ computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) }}"
+      custom-class="icon-class"
+      custom-style="line-height: 1.25em;"
+    />
+  </view>
+  <view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}" bindtap="onClickLabel">
+    <slot />
+  </view>
+</view>

+ 20 - 0
src/vant/checkbox/index.wxs

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

+ 1 - 0
src/vant/checkbox/index.wxss

@@ -0,0 +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}

+ 6 - 0
src/vant/circle/canvas.d.ts

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

+ 43 - 0
src/vant/circle/canvas.js

@@ -0,0 +1,43 @@
+export function adaptor(ctx) {
+    // @ts-ignore
+    return Object.assign(ctx, {
+        setStrokeStyle(val) {
+            ctx.strokeStyle = val;
+        },
+        setLineWidth(val) {
+            ctx.lineWidth = val;
+        },
+        setLineCap(val) {
+            ctx.lineCap = val;
+        },
+        setFillStyle(val) {
+            ctx.fillStyle = val;
+        },
+        setFontSize(val) {
+            ctx.font = String(val);
+        },
+        setGlobalAlpha(val) {
+            ctx.globalAlpha = val;
+        },
+        setLineJoin(val) {
+            ctx.lineJoin = val;
+        },
+        setTextAlign(val) {
+            ctx.textAlign = val;
+        },
+        setMiterLimit(val) {
+            ctx.miterLimit = val;
+        },
+        setShadow(offsetX, offsetY, blur, color) {
+            ctx.shadowOffsetX = offsetX;
+            ctx.shadowOffsetY = offsetY;
+            ctx.shadowBlur = blur;
+            ctx.shadowColor = color;
+        },
+        setTextBaseline(val) {
+            ctx.textBaseline = val;
+        },
+        createCircularGradient() {},
+        draw() {}
+    });
+}

+ 1 - 0
src/vant/circle/index.d.ts

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

+ 180 - 0
src/vant/circle/index.js

@@ -0,0 +1,180 @@
+import { VantComponent } from '../common/component';
+import { isObj } from '../common/utils';
+import { BLUE, WHITE } from '../common/color';
+import { adaptor } from './canvas';
+function format(rate) {
+    return Math.min(Math.max(rate, 0), 100);
+}
+const PERIMETER = 2 * Math.PI;
+const BEGIN_ANGLE = -Math.PI / 2;
+const STEP = 1;
+VantComponent({
+    props: {
+        text: String,
+        lineCap: {
+            type: String,
+            value: 'round'
+        },
+        value: {
+            type: Number,
+            value: 0,
+            observer: 'reRender'
+        },
+        speed: {
+            type: Number,
+            value: 50
+        },
+        size: {
+            type: Number,
+            value: 100,
+            observer() {
+                this.drawCircle(this.currentValue);
+            }
+        },
+        fill: String,
+        layerColor: {
+            type: String,
+            value: WHITE
+        },
+        color: {
+            type: [String, Object],
+            value: BLUE,
+            observer() {
+                this.setHoverColor().then(() => {
+                    this.drawCircle(this.currentValue);
+                });
+            }
+        },
+        type: {
+            type: String,
+            value: ''
+        },
+        strokeWidth: {
+            type: Number,
+            value: 4
+        },
+        clockwise: {
+            type: Boolean,
+            value: true
+        }
+    },
+    data: {
+        hoverColor: BLUE
+    },
+    methods: {
+        getContext() {
+            const { type, size } = this.data;
+            if (type === '') {
+                const ctx = wx.createCanvasContext('van-circle', this);
+                return Promise.resolve(ctx);
+            }
+            const dpr = wx.getSystemInfoSync().pixelRatio;
+            return new Promise(resolve => {
+                wx.createSelectorQuery()
+                    .in(this)
+                    .select('#van-circle')
+                    .node()
+                    .exec(res => {
+                        const canvas = res[0].node;
+                        const ctx = canvas.getContext(type);
+                        if (!this.inited) {
+                            this.inited = true;
+                            canvas.width = size * dpr;
+                            canvas.height = size * dpr;
+                            ctx.scale(dpr, dpr);
+                        }
+                        resolve(adaptor(ctx));
+                    });
+            });
+        },
+        setHoverColor() {
+            const { color, size } = this.data;
+            if (isObj(color)) {
+                return this.getContext().then(context => {
+                    const LinearColor = context.createLinearGradient(size, 0, 0, 0);
+                    Object.keys(color)
+                        .sort((a, b) => parseFloat(a) - parseFloat(b))
+                        .map(key => LinearColor.addColorStop(parseFloat(key) / 100, color[key]));
+                    this.hoverColor = LinearColor;
+                });
+            }
+            this.hoverColor = color;
+            return Promise.resolve();
+        },
+        presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
+            const { strokeWidth, lineCap, clockwise, size } = this.data;
+            const position = size / 2;
+            const radius = position - strokeWidth / 2;
+            context.setStrokeStyle(strokeStyle);
+            context.setLineWidth(strokeWidth);
+            context.setLineCap(lineCap);
+            context.beginPath();
+            context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
+            context.stroke();
+            if (fill) {
+                context.setFillStyle(fill);
+                context.fill();
+            }
+        },
+        renderLayerCircle(context) {
+            const { layerColor, fill } = this.data;
+            this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
+        },
+        renderHoverCircle(context, formatValue) {
+            const { clockwise } = this.data;
+            // 结束角度
+            const progress = PERIMETER * (formatValue / 100);
+            const endAngle = clockwise ? BEGIN_ANGLE + progress : 3 * Math.PI - (BEGIN_ANGLE + progress);
+            this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
+        },
+        drawCircle(currentValue) {
+            const { size } = this.data;
+            this.getContext().then(context => {
+                context.clearRect(0, 0, size, size);
+                this.renderLayerCircle(context);
+                const formatValue = format(currentValue);
+                if (formatValue !== 0) {
+                    this.renderHoverCircle(context, formatValue);
+                }
+                context.draw();
+            });
+        },
+        reRender() {
+            // tofector 动画暂时没有想到好的解决方案
+            const { value, speed } = this.data;
+            if (speed <= 0 || speed > 1000) {
+                this.drawCircle(value);
+                return;
+            }
+            this.clearInterval();
+            this.currentValue = this.currentValue || 0;
+            this.interval = setInterval(() => {
+                if (this.currentValue !== value) {
+                    if (this.currentValue < value) {
+                        this.currentValue += STEP;
+                    } else {
+                        this.currentValue -= STEP;
+                    }
+                    this.drawCircle(this.currentValue);
+                } else {
+                    this.clearInterval();
+                }
+            }, 1000 / speed);
+        },
+        clearInterval() {
+            if (this.interval) {
+                clearInterval(this.interval);
+                this.interval = null;
+            }
+        }
+    },
+    mounted() {
+        this.currentValue = this.data.value;
+        this.setHoverColor().then(() => {
+            this.drawCircle(this.currentValue);
+        });
+    },
+    destroyed() {
+        this.clearInterval();
+    }
+});

+ 3 - 0
src/vant/circle/index.json

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

+ 9 - 0
src/vant/circle/index.wxml

@@ -0,0 +1,9 @@
+<wxs src="../wxs/utils.wxs" module="utils" />
+
+<view class="van-circle">
+  <canvas class="van-circle__canvas" type="{{ type }}" style="width: {{ utils.addUnit(size) }};height:{{ utils.addUnit(size) }}" id="van-circle" canvas-id="van-circle"></canvas>
+  <view wx:if="{{ !text }}" class="van-circle__text">
+    <slot></slot>
+  </view>
+  <cover-view wx:else class="van-circle__text">{{ text }}</cover-view>
+</view>

+ 1 - 0
src/vant/circle/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-circle{position:relative;display:inline-block;text-align:center}.van-circle__text{position:absolute;top:50%;left:0;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#323233;color:var(--circle-text-color,#323233)}

+ 1 - 0
src/vant/col/index.d.ts

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

+ 24 - 0
src/vant/col/index.js

@@ -0,0 +1,24 @@
+import { VantComponent } from '../common/component';
+VantComponent({
+    relation: {
+        name: 'row',
+        type: 'ancestor',
+        current: 'col'
+    },
+    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 });
+            }
+        }
+    }
+});

+ 3 - 0
src/vant/col/index.json

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

+ 8 - 0
src/vant/col/index.wxml

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

+ 1 - 0
src/vant/col/index.wxss

@@ -0,0 +1 @@
+@import '../common/index.wxss';.van-col{float:left;box-sizing:border-box}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%}

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

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

+ 98 - 0
src/vant/collapse-item/index.js

@@ -0,0 +1,98 @@
+import { VantComponent } from '../common/component';
+VantComponent({
+    classes: ['title-class', 'content-class'],
+    relation: {
+        name: 'collapse',
+        type: 'ancestor',
+        current: 'collapse-item'
+    },
+    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
+    },
+    created() {
+        this.animation = wx.createAnimation({
+            duration: 0,
+            timingFunction: 'ease-in-out'
+        });
+    },
+    mounted() {
+        this.updateExpanded();
+        this.inited = true;
+    },
+    methods: {
+        updateExpanded() {
+            if (!this.parent) {
+                return Promise.resolve();
+            }
+            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) {
+                this.updateStyle(expanded);
+            }
+            this.setData({ index, expanded });
+        },
+        updateStyle(expanded) {
+            const { inited } = this;
+            this.getRect('.van-collapse-item__content')
+                .then(rect => rect.height)
+                .then(height => {
+                    const { animation } = this;
+                    if (expanded) {
+                        animation
+                            .height(height)
+                            .top(1)
+                            .step({
+                                duration: inited ? 300 : 1
+                            })
+                            .height('auto')
+                            .step();
+                        this.setData({
+                            animation: animation.export()
+                        });
+                        return;
+                    }
+                    animation
+                        .height(height)
+                        .top(0)
+                        .step({ duration: 1 })
+                        .height(0)
+                        .step({
+                            duration: 300
+                        });
+                    this.setData({
+                        animation: animation.export()
+                    });
+                });
+        },
+        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
src/vant/collapse-item/index.json

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

+ 44 - 0
src/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
src/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
src/vant/collapse/index.d.ts

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

+ 45 - 0
src/vant/collapse/index.js

@@ -0,0 +1,45 @@
+import { VantComponent } from '../common/component';
+VantComponent({
+    relation: {
+        name: 'collapse-item',
+        type: 'descendant',
+        current: 'collapse'
+    },
+    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
src/vant/collapse/index.json

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

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

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

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

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

+ 7 - 0
src/vant/common/color.d.ts

@@ -0,0 +1,7 @@
+export declare const RED = "#ee0a24";
+export declare const BLUE = "#1989fa";
+export declare const WHITE = "#fff";
+export declare const GREEN = "#07c160";
+export declare const ORANGE = "#ff976a";
+export declare const GRAY = "#323233";
+export declare const GRAY_DARK = "#969799";

+ 7 - 0
src/vant/common/color.js

@@ -0,0 +1,7 @@
+export const RED = '#ee0a24';
+export const BLUE = '#1989fa';
+export const WHITE = '#fff';
+export const GREEN = '#07c160';
+export const ORANGE = '#ff976a';
+export const GRAY = '#323233';
+export const GRAY_DARK = '#969799';

+ 3 - 0
src/vant/common/component.d.ts

@@ -0,0 +1,3 @@
+import { VantComponentOptions, CombinedComponentInstance } from '../definitions/index';
+declare function VantComponent<Data, Props, Methods>(vantOptions?: VantComponentOptions<Data, Props, Methods, CombinedComponentInstance<Data, Props, Methods>>): void;
+export { VantComponent };

+ 101 - 0
src/vant/common/component.js

@@ -0,0 +1,101 @@
+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]) {
+            target[map[key]] = source[key];
+        }
+    });
+}
+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 = {}) {
+    const options = {};
+    mapKeys(vantOptions, options, {
+        data: 'data',
+        props: 'properties',
+        mixins: 'behaviors',
+        methods: 'methods',
+        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);
+    // 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,
+        addGlobalClass: true
+    };
+    Component(options);
+}
+export { VantComponent };

+ 1 - 0
src/vant/common/index.wxss

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

+ 1 - 0
src/vant/common/style/clearfix.wxss

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

+ 1 - 0
src/vant/common/style/ellipsis.wxss

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

+ 1 - 0
src/vant/common/style/hairline.wxss

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

+ 0 - 0
src/vant/common/style/mixins/clearfix.wxss


+ 0 - 0
src/vant/common/style/mixins/ellipsis.wxss


+ 0 - 0
src/vant/common/style/mixins/hairline.wxss


+ 0 - 0
src/vant/common/style/theme.wxss


+ 0 - 0
src/vant/common/style/var.wxss


+ 11 - 0
src/vant/common/utils.d.ts

@@ -0,0 +1,11 @@
+/// <reference types="miniprogram-api-typings" />
+export declare function isDef(value: any): boolean;
+export declare function isObj(x: any): boolean;
+export declare function isNumber(value: any): boolean;
+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 addUnit(value?: string | number): string | undefined;
+export declare function requestAnimationFrame(
+  cb: Function
+): void | WechatMiniprogram.NodesRef;

+ 45 - 0
src/vant/common/utils.js

@@ -0,0 +1,45 @@
+export function isDef(value) {
+    return value !== undefined && value !== null;
+}
+export function isObj(x) {
+    const type = typeof x;
+    return x !== null && (type === 'object' || type === 'function');
+}
+export function isNumber(value) {
+    return /^\d+(\.\d+)?$/.test(value);
+}
+export function range(num, min, max) {
+    return Math.min(Math.max(num, min), max);
+}
+export function nextTick(fn) {
+    setTimeout(() => {
+        fn();
+    }, 1000 / 30);
+}
+let systemInfo = null;
+export function getSystemInfoSync() {
+    if (systemInfo == null) {
+        systemInfo = wx.getSystemInfoSync();
+    }
+    return systemInfo;
+}
+export function addUnit(value) {
+    if (!isDef(value)) {
+        return undefined;
+    }
+    value = String(value);
+    return isNumber(value) ? `${value}px` : value;
+}
+export function requestAnimationFrame(cb) {
+    const systemInfo = getSystemInfoSync();
+    if (systemInfo.platform === 'devtools') {
+        return nextTick(cb);
+    }
+    return wx
+        .createSelectorQuery()
+        .selectViewport()
+        .boundingClientRect()
+        .exec(() => {
+            cb();
+        });
+}

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