ソースを参照

Merge branch 'next' of https://github.com/jdf2e/nutui into next

Ymm0008 4 年 前
コミット
b4b615c880
30 ファイル変更1138 行追加46 行削除
  1. 0 1
      .husky/pre-commit
  2. 1 1
      package.json
  3. 4 0
      src/config.json
  4. 3 0
      src/packages/__VUE/calendar/index.scss
  5. 124 0
      src/packages/__VUE/calendar/index.taro.vue
  6. 3 0
      src/packages/__VUE/calendaritem/index.scss
  7. 4 5
      src/packages/__VUE/calendaritem/index.vue
  8. 1 0
      src/packages/__VUE/cell/index.taro.vue
  9. 1 0
      src/packages/__VUE/checkbox/index.taro.vue
  10. 3 0
      src/packages/__VUE/input/index.scss
  11. 191 0
      src/packages/__VUE/input/index.taro.vue
  12. 5 2
      src/packages/__VUE/radio/index.taro.vue
  13. 16 0
      src/packages/__VUE/shortpassword/index.scss
  14. 167 0
      src/packages/__VUE/shortpassword/index.taro.vue
  15. 1 5
      src/packages/__VUE/steps/index.taro.vue
  16. 3 12
      src/packages/__VUE/swiper/index.taro.vue
  17. 1 0
      src/packages/__VUE/textarea/index.scss
  18. 132 0
      src/packages/__VUE/textarea/index.taro.vue
  19. 3 3
      src/shims-vue.d.ts
  20. 4 1
      src/sites/mobile-taro/vue/config/index.js
  21. 4 0
      src/sites/mobile-taro/vue/src/app.config.ts
  22. 3 0
      src/sites/mobile-taro/vue/src/pages/calendar/index.config.ts
  23. 166 0
      src/sites/mobile-taro/vue/src/pages/calendar/index.vue
  24. 3 0
      src/sites/mobile-taro/vue/src/pages/input/index.config.ts
  25. 107 0
      src/sites/mobile-taro/vue/src/pages/input/index.vue
  26. 1 1
      src/sites/mobile-taro/vue/src/pages/radio/index.vue
  27. 112 0
      src/sites/mobile-taro/vue/src/pages/shortpassword/index.vue
  28. 31 15
      src/sites/mobile-taro/vue/src/pages/swiper/index.vue
  29. 3 0
      src/sites/mobile-taro/vue/src/pages/textarea/index.config.ts
  30. 41 0
      src/sites/mobile-taro/vue/src/pages/textarea/index.vue

+ 0 - 1
.husky/pre-commit

@@ -3,4 +3,3 @@
 
 node ./jd/verifymail.js
 yarn lint-staged
-yarn test

+ 1 - 1
package.json

@@ -91,7 +91,7 @@
     "husky": "^6.0.0",
     "jest": "^26.6.3",
     "lint-staged": "^10.5.0",
-    "prettier": "^1.19.1",
+    "prettier": "^2.0.0",
     "standard-version": "^9.3.0",
     "transliteration": "^2.2.0",
     "ts-jest": "^26.5.5",

+ 4 - 0
src/config.json

@@ -520,6 +520,7 @@
         },
         {
           "name": "Input",
+          "taro": true,
           "sort": 2,
           "cName": "输入框",
           "type": "component",
@@ -550,6 +551,7 @@
         },
         {
           "version": "3.0.0",
+          "taro": true,
           "name": "Calendar",
           "type": "component",
           "cName": "日历",
@@ -571,6 +573,7 @@
         {
           "version": "3.0.0",
           "name": "ShortPassword",
+          "taro": true,
           "type": "component",
           "cName": "短密码",
           "desc": "短密码组件",
@@ -580,6 +583,7 @@
         },
         {
           "version": "3.0.0",
+          "taro": true,
           "name": "TextArea",
           "type": "component",
           "cName": "文本域",

+ 3 - 0
src/packages/__VUE/calendar/index.scss

@@ -186,3 +186,6 @@
     }
   }
 }
+.nut-calendar-taro {
+  height: 65vh;
+}

+ 124 - 0
src/packages/__VUE/calendar/index.taro.vue

@@ -0,0 +1,124 @@
+<template>
+  <nut-popup
+    v-if="poppable"
+    v-model:visible="visible"
+    position="bottom"
+    round
+    :closeable="true"
+    @click-overlay="closePopup"
+    @click-close-icon="closePopup"
+  >
+    <nut-calendar-item
+      props
+      ref="calendarRef"
+      :type="type"
+      :is-auto-back-fill="isAutoBackFill"
+      :poppable="poppable"
+      :title="title"
+      :default-value="defaultValue"
+      :start-date="startDate"
+      :end-date="endDate"
+      @update="update"
+      @close="close"
+      @choose="choose"
+    >
+    </nut-calendar-item>
+  </nut-popup>
+
+  <nut-calendar-item
+    v-else
+    :type="type"
+    :is-auto-back-fill="isAutoBackFill"
+    :poppable="poppable"
+    :title="title"
+    :default-value="defaultValue"
+    :start-date="startDate"
+    :end-date="endDate"
+    @close="close"
+    @choose="choose"
+  >
+  </nut-calendar-item>
+</template>
+<script lang="ts">
+import { PropType, ref } from 'vue';
+import { createComponent } from '@/packages/utils/create';
+const { create } = createComponent('calendar');
+import Popup from '@/packages/__VUE/popup/index.taro.vue';
+import CalendarItem from '@/packages/__VUE/calendaritem/index.vue';
+import Utils from '@/packages/utils/date';
+type InputDate = string | string[];
+export default create({
+  children: [CalendarItem, Popup],
+  props: {
+    type: {
+      type: String,
+      default: 'one'
+    },
+    isAutoBackFill: {
+      type: Boolean,
+      default: false
+    },
+    poppable: {
+      type: Boolean,
+      default: true
+    },
+    visible: {
+      type: Boolean,
+      default: true
+    },
+    title: {
+      type: String,
+      default: '日历选择'
+    },
+    defaultValue: {
+      type: String as PropType<InputDate>
+    },
+    startDate: {
+      type: String,
+      default: Utils.getDay(0)
+    },
+    endDate: {
+      type: String,
+      default: Utils.getDay(365)
+    }
+  },
+  emits: ['choose', 'close', 'update:visible'],
+  setup(props, { emit }) {
+    // element refs
+    const calendarRef = ref<null | HTMLElement>(null);
+
+    // methods
+    const update = () => {
+      emit('update:visible', false);
+    };
+
+    const close = () => {
+      emit('close');
+      emit('update:visible', false);
+    };
+
+    const choose = (param: string) => {
+      close();
+      emit('choose', param);
+    };
+
+    const closePopup = () => {
+      close();
+    };
+
+    return {
+      closePopup,
+      update,
+      close,
+      choose,
+      calendarRef
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+.popup-box {
+  height: 518px;
+}
+</style>

+ 3 - 0
src/packages/__VUE/calendaritem/index.scss

@@ -190,3 +190,6 @@
     }
   }
 }
+.nut-calendar-taro {
+  height: 65vh;
+}

+ 4 - 5
src/packages/__VUE/calendaritem/index.vue

@@ -1,6 +1,6 @@
 <template>
   <view
-    class="nut-calendar"
+    class="nut-calendar nut-calendar-taro"
     :class="{
       'nut-calendar-tile': !poppable,
       'nut-calendar-nofooter': isAutoBackFill
@@ -493,9 +493,8 @@ export default create({
       requestAniFrame(() => {
         if (weeksPanel?.value && monthsPanel?.value) {
           const top = weeksPanel?.value.getBoundingClientRect().bottom;
-          const monthsDoms = monthsPanel.value.querySelectorAll(
-            '.calendar-month'
-          );
+          const monthsDoms =
+            monthsPanel.value.getElementsByClassName('.calendar-month');
           for (let i = 0; i < monthsDoms.length; i++) {
             if (
               monthsDoms[i].getBoundingClientRect().top <= top &&
@@ -635,7 +634,7 @@ export default create({
     //监听 默认值更改
     watch(
       () => props.defaultValue,
-      val => {
+      (val) => {
         if (val) {
           resetRender();
         }

+ 1 - 0
src/packages/__VUE/cell/index.taro.vue

@@ -39,6 +39,7 @@ import { useRouter } from 'vue-router';
 import CellGroup from '../cellgroup/index.vue';
 const { componentName, create } = createComponent('cell');
 export default create({
+  children: [CellGroup],
   props: {
     title: { type: String, default: '' },
     subTitle: { type: String, default: '' },

+ 1 - 0
src/packages/__VUE/checkbox/index.taro.vue

@@ -6,6 +6,7 @@ import nutIcon from '../icon/index.taro.vue';
 import nutCheckboxGroup from '../checkboxgroup/index.vue';
 
 export default create({
+  children: [nutCheckboxGroup],
   components: {
     nutIcon,
     nutCheckboxGroup

+ 3 - 0
src/packages/__VUE/input/index.scss

@@ -17,6 +17,7 @@
     overflow: hidden;
     display: inline-block;
     text-align: left;
+    display: flex;
     .label-string {
       overflow: hidden;
       white-space: nowrap;
@@ -41,5 +42,7 @@
   }
   &-require {
     color: $primary-color;
+    display: inline-block;
+    margin-right: 5px;
   }
 }

+ 191 - 0
src/packages/__VUE/input/index.taro.vue

@@ -0,0 +1,191 @@
+<template>
+  <view :class="classes">
+    <view class="nut-input-label">
+      <view class="nut-input-require" v-if="requireShow">*</view>
+      <view v-if="label" class="label-string">{{ label }}</view>
+    </view>
+    <view v-if="readonly">
+      {{ modelValue }}
+    </view>
+    <input
+      v-else
+      class="input-text"
+      :style="styles"
+      :type="type"
+      :maxlength="maxLength"
+      :placeholder="placeholder"
+      :disabled="disabled"
+      :readonly="readonly"
+      :value="modelValue"
+      @input="valueChange"
+      @focus="valueFocus"
+      @blur="valueBlur"
+    />
+    <view
+      @click="handleClear"
+      class="nut-textinput-clear"
+      v-if="clearable && !readonly"
+      v-show="active && modelValue.length > 0"
+    >
+      <nut-icon name="close-little" size="12px"></nut-icon>
+    </view>
+  </view>
+</template>
+<script lang="ts">
+import { ref, computed } from 'vue';
+import { createComponent } from '@/packages/utils/create';
+function trimExtraChar(value: string, char: string, regExp: RegExp) {
+  const index = value.indexOf(char);
+
+  if (index === -1) {
+    return value;
+  }
+
+  if (char === '-' && index !== 0) {
+    return value.slice(0, index);
+  }
+
+  return value.slice(0, index + 1) + value.slice(index).replace(regExp, '');
+}
+
+function formatNumber(value: string, allowDot = true, allowMinus = true) {
+  if (allowDot) {
+    value = trimExtraChar(value, '.', /\./g);
+  } else {
+    value = value.replace(/\./g, '');
+  }
+
+  if (allowMinus) {
+    value = trimExtraChar(value, '-', /-/g);
+  } else {
+    value = value.replace(/-/, '');
+  }
+
+  const regExp = allowDot ? /[^-0-9.]/g : /[^-0-9]/g;
+
+  return value.replace(regExp, '');
+}
+
+const { componentName, create } = createComponent('input');
+interface Events {
+  eventName: 'change' | 'focus' | 'blur' | 'clear' | 'update:modelValue';
+  params: (string | number | Event)[];
+}
+export default create({
+  props: {
+    type: {
+      type: String,
+      default: 'text'
+    },
+    modelValue: {
+      type: [String, Number],
+      default: ''
+    },
+    placeholder: {
+      type: String,
+      default: '请输入信息'
+    },
+    label: {
+      type: String,
+      default: ''
+    },
+    requireShow: {
+      type: Boolean,
+      default: false
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    readonly: {
+      type: Boolean,
+      default: false
+    },
+    textAlign: {
+      type: String,
+      default: 'left'
+    },
+    maxLength: {
+      type: [String, Number],
+      default: '99999999'
+    },
+    clearable: {
+      type: Boolean,
+      default: true
+    }
+  },
+
+  emits: ['change', 'update:modelValue', 'blur', 'focus', 'clear'],
+
+  setup(props, { emit }) {
+    const active = ref(false);
+
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true,
+        [`${prefixCls}-disabled`]: props.disabled
+      };
+    });
+
+    const styles = computed(() => {
+      return {
+        textAlign: props.textAlign
+      };
+    });
+
+    const valueChange = (event: Event) => {
+      const input = event.target as HTMLInputElement;
+      let val = input.value;
+
+      if (props.maxLength && val.length > Number(props.maxLength)) {
+        val = val.slice(0, Number(props.maxLength));
+      }
+      if (props.type === 'digit') {
+        val = formatNumber(val, true);
+      }
+      if (props.type === 'number') {
+        val = formatNumber(val, false);
+      }
+      emit('change', val, event);
+      emit('update:modelValue', val, event);
+    };
+
+    const valueFocus = (event: Event) => {
+      const input = event.target as HTMLInputElement;
+      let value = input.value;
+      active.value = true;
+      emit('focus', value, event);
+    };
+
+    const valueBlur = (event: Event) => {
+      setTimeout(() => {
+        active.value = false;
+      }, 0);
+
+      const input = event.target as HTMLInputElement;
+      let value = input.value;
+      emit('blur', value, event);
+    };
+
+    const handleClear = (event: Event) => {
+      emit('change', '', event);
+      emit('update:modelValue', '', event);
+    };
+
+    return {
+      active,
+      classes,
+      styles,
+      valueChange,
+      valueFocus,
+      valueBlur,
+      handleClear
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 5 - 2
src/packages/__VUE/radio/index.taro.vue

@@ -1,12 +1,15 @@
 <script lang="ts">
 import { computed, h, inject } from 'vue';
+import nutIcon from '@/packages/__VUE/icon/index.taro.vue';
+import radiogroup from '@/packages/__VUE/radiogroup/index.vue';
 import { createComponent } from '../../utils/create';
-import nutIcon from '../icon/index.taro.vue';
-import radiogroup from '../radiogroup/index.vue';
 const { componentName, create } = createComponent('radio');
 
 export default create({
   children: [radiogroup],
+  components: {
+    'nut-radiogroup': radiogroup
+  },
   props: {
     disabled: {
       type: Boolean,

+ 16 - 0
src/packages/__VUE/shortpassword/index.scss

@@ -12,6 +12,13 @@
   font-size: $font-size-1;
   color: $text-color;
 }
+.nut-shortpsdWx-subtitle {
+  display: block;
+  margin-top: 12px;
+  line-height: 1;
+  font-size: $font-size-1;
+  color: $text-color;
+}
 
 .nut-input-w {
   padding: 24px 0 10px 0;
@@ -28,6 +35,14 @@
     padding: 0 12px;
     opacity: 0;
   }
+  .nut-inputWx-real {
+    width: 247px;
+    height: 41px;
+    padding: 0 12px;
+    opacity: 0;
+    position: relative;
+    z-index: 2;
+  }
 }
 
 .nut-popup {
@@ -83,6 +98,7 @@
     line-height: 1;
     font-size: $font-size-1;
     color: $shortpsd-forget;
+    display: flex;
   }
 }
 

+ 167 - 0
src/packages/__VUE/shortpassword/index.taro.vue

@@ -0,0 +1,167 @@
+<template>
+  <view>
+    <nut-popup
+      :style="{
+        padding: '32px 24px 28px 24px',
+        borderRadius: '12px',
+        textAlign: 'center'
+      }"
+      v-model:visible="show"
+      :closeable="true"
+      @click-close-icon="closeIcon"
+      :close-on-click-overlay="closeOnClickOverlay"
+      @click-overlay="close"
+    >
+      <view class="nut-shortpsd-title">{{ title }}</view>
+      <view class="nut-shortpsdWx-subtitle">{{ desc }}</view>
+      <view class="nut-input-w">
+        <input
+          ref="realpwd"
+          class="nut-inputWx-real"
+          type="number"
+          :maxlength="length"
+          v-model="realInput"
+          @input="changeValue"
+        />
+        <view class="nut-shortpsd-fake">
+          <view
+            class="nut-shortpsd-li"
+            v-for="(sublen, index) in new Array(comLen)"
+            v-bind:key="index"
+          >
+            <view
+              class="nut-shortpsd-icon"
+              v-if="realInput.length > index"
+            ></view>
+          </view>
+        </view>
+      </view>
+      <view class="nut-shortpsd-message">
+        <view class="nut-shortpsd-error">{{ errorMsg }}</view>
+        <view class="nut-shortpsd-forget" @click="onTips" v-if="tips">
+          <nut-icon class="icon" size="11px" name="tips"></nut-icon>
+          <view>{{ tips }}</view>
+        </view>
+      </view>
+      <view v-if="!noButton" class="nut-shortpsd-footer">
+        <view class="nut-shortpsd-cancle" @click="close">取消</view>
+        <view class="nut-shortpsd-sure" @click="sureClick">确认</view>
+      </view>
+    </nut-popup>
+  </view>
+</template>
+<script lang="ts">
+import { ref, computed, watch } from 'vue';
+import { createComponent } from '@/packages/utils/create';
+const { create } = createComponent('shortpassword');
+import Taro from '@tarojs/taro';
+export default create({
+  props: {
+    title: {
+      type: String,
+      default: '请输入密码'
+    },
+    desc: {
+      type: String,
+      default: '您使用了虚拟资产,请进行验证'
+    },
+    tips: {
+      type: String,
+      default: '忘记密码'
+    },
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    modelValue: {
+      type: String,
+      default: ''
+    },
+    errorMsg: {
+      type: String,
+      default: ''
+    },
+    noButton: {
+      type: Boolean,
+      default: true
+    },
+    closeOnClickOverlay: {
+      type: Boolean,
+      default: true
+    },
+    length: {
+      type: [String, Number], //4~6
+      default: 6
+    }
+  },
+  emits: [
+    'update:modelValue',
+    'update:visible',
+    'complete',
+    'change',
+    'ok',
+    'tips',
+    'close',
+    'cancel'
+  ],
+  setup(props, { emit }) {
+    const realInput = ref(props.modelValue);
+    const realpwd = ref();
+    const comLen = computed(() => range(Number(props.length)));
+    const show = ref(props.visible);
+    // 方法
+    function sureClick() {
+      emit('ok', realInput.value);
+    }
+    watch(
+      () => props.visible,
+      (value) => {
+        show.value = value;
+      }
+    );
+    function changeValue(e: Event) {
+      const input = e.target as HTMLInputElement;
+      let val = input.value;
+      if (val.length > comLen.value) {
+        val = val.slice(0, comLen.value);
+        realInput.value = val;
+      }
+      if (realInput.value.length === comLen.value) {
+        emit('complete', val);
+      }
+      emit('change', val);
+      emit('update:modelValue', val);
+    }
+    function close() {
+      emit('update:visible', false);
+      emit('cancel');
+    }
+    function closeIcon() {
+      emit('update:visible', false);
+      emit('close');
+    }
+    function range(val: number) {
+      return Math.min(Math.max(4, val), 6);
+    }
+    function onTips() {
+      emit('tips');
+    }
+    return {
+      comLen,
+      sureClick,
+      realInput,
+      realpwd,
+      range,
+      changeValue,
+      close,
+      onTips,
+      show,
+      closeIcon
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 1 - 5
src/packages/__VUE/steps/index.taro.vue

@@ -1,15 +1,11 @@
 <script lang="ts">
 import { provide, computed, reactive, h, ComponentInternalInstance } from 'vue';
 import Step from '../step/index.vue';
-import Icon from '../icon/index.taro.vue';
 import { createComponent } from '../../utils/create';
 const { create, componentName } = createComponent('steps');
 
 export default create({
-  components: {
-    [Step.name]: Step,
-    [Icon.name]: Icon
-  },
+  children: [Step],
   props: {
     direction: {
       type: String,

+ 3 - 12
src/packages/__VUE/swiper/index.taro.vue

@@ -1,6 +1,6 @@
 <template>
   <swiper
-    class="test-h"
+    class="nut-swiper"
     indicator-color="#999"
     indicator-active-color="#333"
     vertical
@@ -8,25 +8,16 @@
     indicator-dots
     autoplay
   >
-    <swiper-item>
-      <view class="demo-text-1">1</view>
-    </swiper-item>
-    <swiper-item>
-      <view class="demo-text-2">2</view>
-    </swiper-item>
-    <swiper-item>
-      <view class="demo-text-3">3</view>
-    </swiper-item>
   </swiper>
 </template>
 
 <script lang="ts">
 import Taro from '@tarojs/taro';
 import { createComponent } from '@/packages/utils/create';
-import { useTouch } from './use-touch';
-import { useExpose } from '@/packages/utils/useExpose/index';
 const { create, componentName } = createComponent('swiper');
 // import swiperItem from '@/packages/__VUE/swiperitem/index.vue';
+// console.log(Taro)
+// console.log(Taro.createSelectorQuery)
 export default create({
   // children: [swiperItem],
   props: {},

+ 1 - 0
src/packages/__VUE/textarea/index.scss

@@ -1,6 +1,7 @@
 .nut-textarea {
   position: relative;
   width: 100%;
+  box-sizing: border-box;
   display: flex;
   background: $white;
   font-size: $textarea-font;

+ 132 - 0
src/packages/__VUE/textarea/index.taro.vue

@@ -0,0 +1,132 @@
+<template>
+  <view :class="classes">
+    <view v-if="readonly" class="nut-textarea__textarea">
+      {{ modelValue }}
+    </view>
+    <textarea
+      v-else
+      class="nut-textarea__textarea"
+      :style="styles"
+      :rows="rows"
+      :disabled="disabled"
+      :readonly="readonly"
+      :value="modelValue"
+      @input="change"
+      @blur="blur"
+      @focus="focus"
+      :maxlength="maxLength"
+      :placeholder="placeholder"
+    />
+    <view class="nut-textarea__limit" v-if="limitShow">
+      {{ modelValue.length }}/{{ maxLength }}</view
+    >
+  </view>
+</template>
+<script lang="ts">
+import { computed } from 'vue';
+import { createComponent } from '@/packages/utils/create';
+
+const { componentName, create } = createComponent('textarea');
+
+export default create({
+  props: {
+    modelValue: {
+      type: [String, Number],
+      default: ''
+    },
+    textAlign: {
+      type: String,
+      default: 'left'
+    },
+    limitShow: {
+      type: Boolean,
+      default: false
+    },
+    maxLength: {
+      type: [String, Number],
+      default: ''
+    },
+    rows: {
+      type: [String, Number],
+      default: ''
+    },
+    placeholder: {
+      type: String,
+      default: '请输入内容'
+    },
+    readonly: {
+      type: Boolean,
+      default: false
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    autosize: {
+      type: Boolean,
+      default: false
+    }
+  },
+
+  emits: ['update:modelValue', 'change', 'blur', 'focus'],
+
+  setup(props, { emit }) {
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true,
+        [`${prefixCls}--disabled`]: props.disabled
+      };
+    });
+
+    const styles = computed(() => {
+      return {
+        textAlign: props.textAlign,
+        resize: props.autosize ? 'vertical' : 'none'
+      };
+    });
+
+    const emitChange = (value: string, event: Event) => {
+      if (props.maxLength && value.length > Number(props.maxLength)) {
+        value = value.substring(0, Number(props.maxLength));
+      }
+      emit('change', value, event);
+      emit('update:modelValue', value, event);
+    };
+
+    const change = (event: Event) => {
+      const input = event.target as HTMLInputElement;
+      emitChange(input.value, event);
+    };
+
+    const focus = (event: Event) => {
+      if (props.disabled) return;
+      if (props.readonly) return;
+      emit('focus', event);
+    };
+
+    const blur = (event: Event) => {
+      if (props.disabled) return;
+      if (props.readonly) return;
+      const input = event.target as HTMLInputElement;
+
+      let value = input.value;
+
+      emitChange(value, event);
+      emit('blur', event);
+    };
+
+    return {
+      classes,
+      styles,
+      change,
+      focus,
+      blur
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 3 - 3
src/shims-vue.d.ts

@@ -1,5 +1,5 @@
 declare module '*.vue' {
-  import type { DefineComponent } from 'vue'
-  const component: DefineComponent<{}, {}, any>
-  export default component
+  import type { DefineComponent } from 'vue';
+  const component: DefineComponent<{}, {}, any>;
+  export default component;
 }

+ 4 - 1
src/sites/mobile-taro/vue/config/index.js

@@ -20,6 +20,9 @@ const config = {
     )
   },
   defineConstants: {},
+  runtime: {
+    enableSizeAPIs: true
+  },
   copy: {
     patterns: [],
     options: {}
@@ -65,7 +68,7 @@ const config = {
   }
 };
 
-module.exports = function(merge) {
+module.exports = function (merge) {
   if (process.env.NODE_ENV === 'development') {
     return merge({}, config, require('./dev'));
   }

+ 4 - 0
src/sites/mobile-taro/vue/src/app.config.ts

@@ -1,6 +1,10 @@
 export default {
   pages: [
     'pages/collapse/index',
+    'pages/shortpassword/index',
+    'pages/textarea/index',
+    'pages/calendar/index',
+    'pages/input/index',
     'pages/swiper/index',
     'pages/actionsheet/index',
     'pages/popup/index',

+ 3 - 0
src/sites/mobile-taro/vue/src/pages/calendar/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+  navigationBarTitleText: 'Calendar'
+};

+ 166 - 0
src/sites/mobile-taro/vue/src/pages/calendar/index.vue

@@ -0,0 +1,166 @@
+<template>
+  <div class="demo">
+    <h2>基础用法</h2>
+    <div>
+      <nut-cell
+        :show-icon="true"
+        title="选择单个日期"
+        :desc="date ? `${date} ${dateWeek}` : '请选择'"
+        @click="openSwitch('isVisible')"
+      >
+      </nut-cell>
+      <nut-calendar
+        v-model:visible="isVisible"
+        :default-value="date"
+        @close="closeSwitch('isVisible')"
+        @choose="setChooseValue"
+        :start-date="`2019-10-11`"
+        :end-date="`2022-11-11`"
+      >
+      </nut-calendar>
+    </div>
+
+    <div>
+      <nut-cell
+        :show-icon="true"
+        title="选择日期区间"
+        :desc="date1 ? `${date1[0]}至${date1[1]}` : '请选择'"
+        @click="openSwitch1('isVisible1')"
+      >
+      </nut-cell>
+      <nut-calendar
+        v-model:visible="isVisible1"
+        :default-value="date1"
+        type="range"
+        :start-date="`2019-12-22`"
+        :end-date="`2021-01-08`"
+        @close="closeSwitch1('isVisible1')"
+        @choose="setChooseValue1"
+      >
+      </nut-calendar>
+    </div>
+
+    <h2>自定义日历-自动回填</h2>
+    <div>
+      <nut-cell
+        :show-icon="true"
+        title="选择日期"
+        :desc="date3 ? date3 : '请选择'"
+        @click="openSwitch3('isVisible3')"
+      >
+      </nut-cell>
+      <nut-calendar
+        v-model:visible="isVisible3"
+        @close="closeSwitch3('isVisible3')"
+        @choose="setChooseValue3"
+        :default-value="date3"
+        :start-date="null"
+        :end-date="null"
+        :is-auto-back-fill="true"
+      >
+      </nut-calendar>
+    </div>
+
+    <h2>平铺展示</h2>
+    <div class="test-calendar-wrapper">
+      <nut-calendar
+        :poppable="false"
+        :default-value="date2"
+        :is-auto-back-fill="true"
+        @choose="setChooseValue2"
+      >
+      </nut-calendar>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { reactive, toRefs } from 'vue';
+
+interface TestCalendarState {
+  isVisible: boolean;
+  date: string;
+  dateWeek: string;
+  isVisible1: boolean;
+  date1: string[];
+  date2: string;
+  isVisible3: boolean;
+  date3: string;
+}
+export default {
+  props: {},
+  setup() {
+    const state: TestCalendarState = reactive({
+      isVisible: false,
+      date: '',
+      dateWeek: '',
+
+      isVisible1: false,
+      date1: ['2019-12-23', '2019-12-26'],
+
+      date2: '2020-07-08',
+
+      isVisible3: false,
+      date3: ''
+    });
+    const openSwitch = (param: string) => {
+      state.isVisible = true;
+    };
+    const openSwitch1 = (param: string) => {
+      state.isVisible1 = true;
+    };
+    const openSwitch3 = (param: string) => {
+      state.isVisible3 = true;
+    };
+    const closeSwitch = (param: string) => {
+      state.isVisible = false;
+    };
+    const closeSwitch1 = (param: string) => {
+      state.isVisible1 = false;
+    };
+    const closeSwitch3 = (param: string) => {
+      state.isVisible3 = false;
+    };
+    const setChooseValue = (param: string) => {
+      state.date = param[3];
+      state.dateWeek = param[4];
+    };
+
+    const setChooseValue1 = (param: string) => {
+      state.date1 = [...[param[0][3], param[1][3]]];
+    };
+
+    const setChooseValue2 = (param: string) => {
+      state.date2 = param[3];
+      console.log(state.date2);
+    };
+
+    const setChooseValue3 = (param: string) => {
+      state.date3 = param[3];
+    };
+
+    return {
+      ...toRefs(state),
+      openSwitch,
+      openSwitch1,
+      openSwitch3,
+      closeSwitch,
+      closeSwitch1,
+      closeSwitch3,
+      setChooseValue,
+      setChooseValue1,
+      setChooseValue2,
+      setChooseValue3
+    };
+  }
+};
+</script>
+
+<style lang="scss">
+.test-calendar-wrapper {
+  display: flex;
+  width: 100%;
+  height: 613px;
+  overflow: hidden;
+}
+</style>

+ 3 - 0
src/sites/mobile-taro/vue/src/pages/input/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+  navigationBarTitleText: 'Input'
+};

+ 107 - 0
src/sites/mobile-taro/vue/src/pages/input/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="demo full">
+    <h2>基础用法</h2>
+    <nut-input
+      v-model="state.val1"
+      @change="change"
+      @focus="focus"
+      @blur="blur"
+      label="文本(异步)"
+    />
+    <nut-input
+      placeholder="请输入文本"
+      @change="change"
+      v-model="state.val0"
+      :require-show="true"
+      label="文本"
+      @clear="clear"
+    />
+    <h2>禁用输入框</h2>
+    <nut-input
+      v-model="state.val2"
+      @change="change"
+      :disabled="true"
+      label="文本"
+    />
+    <nut-input
+      v-model="state.val3"
+      @change="change"
+      :readonly="true"
+      label="文本"
+    />
+    <h2>限制输入长度</h2>
+    <nut-input
+      v-model="state.val4"
+      @change="change"
+      max-length="7"
+      label="限制7"
+    />
+    <h2>自定义类型</h2>
+    <nut-input
+      v-model="state.val7"
+      @change="change"
+      type="password"
+      label="密码"
+    />
+    <nut-input
+      v-model="state.val5"
+      @change="change"
+      type="number"
+      label="整数"
+    />
+    <nut-input
+      v-model="state.val6"
+      @change="change"
+      type="digit"
+      placeholder="支持小数点的输入"
+      label="数字"
+    />
+  </div>
+</template>
+
+<script lang="ts">
+import { reactive } from 'vue';
+
+export default {
+  props: {},
+
+  setup() {
+    const state = reactive({
+      val0: '',
+      val1: '初始数据',
+      val2: '禁止修改',
+      val3: 'readonly 只读',
+      val4: '',
+      val5: '',
+      val6: '',
+      val7: '',
+      val8: '文案'
+    });
+    setTimeout(function () {
+      state.val1 = '异步数据';
+    }, 2000);
+    const change = (value: string | number, event: Event) => {
+      console.log('change: ', value, event);
+    };
+    const focus = (value: string | number, event: Event) => {
+      console.log('focus:', value, event);
+    };
+    const blur = (value: string | number, event: Event) => {
+      console.log('blur:', value, event);
+    };
+    const clear = (value: string | number) => {
+      console.log('clear:', value);
+    };
+
+    return {
+      state,
+      change,
+      blur,
+      clear,
+      focus
+    };
+  }
+};
+</script>
+
+<style lang="scss"></style>

+ 1 - 1
src/sites/mobile-taro/vue/src/pages/radio/index.vue

@@ -98,4 +98,4 @@ export default {
 };
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss"></style>

+ 112 - 0
src/sites/mobile-taro/vue/src/pages/shortpassword/index.vue

@@ -0,0 +1,112 @@
+<template>
+  <div class="demo">
+    <nut-shortpassword
+      v-model="state.value"
+      v-model:visible="state.visible"
+      :no-button="state.noButton"
+      :length="state.length"
+      :error-msg="state.errorMsg"
+      @change="methods.onChange"
+      @complete="methods.onComplete"
+      @ok="methods.onOk"
+      @tips="methods.onTips"
+      @close="methods.close"
+      @cancel="methods.cancel"
+    >
+    </nut-shortpassword>
+    <nut-cell
+      title="基础用法"
+      is-link
+      @click="
+        state.visible = true;
+        state.noButton = true;
+        state.length = 6;
+        state.errorMsg = '';
+      "
+    ></nut-cell>
+    <nut-cell
+      title="显示按钮组"
+      is-link
+      @click="
+        state.visible = true;
+        state.noButton = false;
+        state.length = 6;
+        state.errorMsg = '';
+      "
+    ></nut-cell>
+    <nut-cell
+      title="自定义密码长度4"
+      is-link
+      @click="
+        state.visible = true;
+        state.noButton = true;
+        state.length = 4;
+        state.errorMsg = '';
+      "
+    ></nut-cell>
+    <nut-cell
+      title="忘记密码提示语事件回调"
+      is-link
+      @click="
+        state.visible = true;
+        state.length = 6;
+        state.errorMsg = '';
+        state.noButton = true;
+      "
+    ></nut-cell>
+    <nut-cell
+      title="错误提示语"
+      is-link
+      @click="
+        state.visible = true;
+        state.length = 6;
+        state.noButton = true;
+        state.errorMsg = '请输入正确密码';
+      "
+    ></nut-cell>
+  </div>
+</template>
+
+<script lang="ts">
+import { reactive, getCurrentInstance } from 'vue';
+export default {
+  setup() {
+    // let { proxy } = getCurrentInstance() as any;
+
+    const state = reactive({
+      visible: false,
+      noButton: true,
+      value: '',
+      errorMsg: '',
+      length: 6
+    });
+    const methods = {
+      onChange(val: string) {
+        console.log(val);
+
+        // val && proxy.$toast.text(val);
+      },
+      onOk(val: string) {
+        // val && proxy.$toast.text(val);
+        state.visible = false;
+      },
+
+      onComplete() {},
+      onTips() {
+        // proxy.$toast.text('执行忘记密码逻辑');
+      },
+      close() {
+        // proxy.$toast.text('点击icon关闭弹窗');
+      },
+      cancel() {
+        // proxy.$toast.text('点击取消按钮关闭弹窗');
+      }
+    };
+
+    return {
+      state,
+      methods
+    };
+  }
+};
+</script>

+ 31 - 15
src/sites/mobile-taro/vue/src/pages/swiper/index.vue

@@ -1,26 +1,23 @@
 <template>
   <div class="demo">
     <h2>基本用法</h2>
-    <view class="demo-box">
-      <nut-swiper
-        :init-page="page"
-        :pagination-visible="true"
-        pagination-color="#426543"
-      >
-        <nut-swiper-item v-for="item in list" :key="item">
+    <view class="demo-box1" id="test">
+      <nut-swiper>
+        1111
+        <!-- <nut-swiper-item v-for="item in list" :key="item">
           <img :src="item" alt="" />
-        </nut-swiper-item>
+        </nut-swiper-item> -->
       </nut-swiper>
     </view>
-    <h2>自定义大小</h2>
+    <!-- <h2>自定义大小</h2>
     <view class="demo-box">
       <nut-swiper :init-page="page2" :loop="false" width="300">
         <nut-swiper-item v-for="item in list" :key="item">
           <img :src="item" alt="" />
         </nut-swiper-item>
       </nut-swiper>
-    </view>
-    <h2>自定义指示器</h2>
+    </view> -->
+    <!-- <h2>自定义指示器</h2>
     <view class="demo-box">
       <nut-swiper :init-page="page3" :loop="true" @change="change">
         <nut-swiper-item v-for="item in list" :key="item">
@@ -30,8 +27,8 @@
           <div class="page"> {{ current }}/4 </div>
         </template>
       </nut-swiper>
-    </view>
-    <h2>垂直方向</h2>
+    </view> -->
+    <!-- <h2>垂直方向</h2>
     <view class="demo-box">
       <nut-swiper
         :init-page="page4"
@@ -46,12 +43,14 @@
           <img :src="item" alt="" />
         </nut-swiper-item>
       </nut-swiper>
-    </view>
+    </view> -->
   </div>
 </template>
 
 <script lang="ts">
-import { reactive, toRefs } from 'vue';
+import { reactive, toRefs, onMounted } from 'vue';
+import Taro, { nextTick, eventCenter, getCurrentInstance } from '@tarojs/taro';
+
 export default {
   props: {},
   setup() {
@@ -71,6 +70,23 @@ export default {
     const change = (index: number) => {
       state.current = index + 1;
     };
+    onMounted(() => {
+      eventCenter.once(
+        (getCurrentInstance() as any).router.onReady,
+        async () => {
+          // const query = Taro.createSelectorQuery()
+          const query = document.querySelector('#test') as any;
+          const res = await query.getBoundingClientRect();
+          console.log(res);
+          // console.log(document.querySelector('#test'))
+          // console.log(query)
+          // query.select('#test').boundingClientRect()
+          // query.exec(res => {
+          // })
+          // console.log('onReady')
+        }
+      );
+    });
     return {
       ...toRefs(state),
       change

+ 3 - 0
src/sites/mobile-taro/vue/src/pages/textarea/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+  navigationBarTitleText: 'Textarea'
+};

+ 41 - 0
src/sites/mobile-taro/vue/src/pages/textarea/index.vue

@@ -0,0 +1,41 @@
+<template>
+  <div class="demo full">
+    <h2>基础用法</h2>
+    <nut-textarea v-model="value" />
+    <h2>显示字数统计</h2>
+    <nut-textarea v-model="value2" limit-show max-length="20" />
+    <h2>高度自定义,拉伸</h2>
+    <nut-textarea v-model="value3" rows="10" autosize />
+    <h2>只读状态</h2>
+    <nut-textarea readonly model-value="textarea只读状态" />
+    <h2>禁用</h2>
+    <nut-textarea
+      disabled
+      model-value="textarea禁用状态"
+      limit-show
+      max-length="20"
+    />
+  </div>
+</template>
+
+<script lang="ts">
+import { ref } from 'vue';
+
+export default {
+  props: {},
+
+  setup() {
+    const value = ref('');
+    const value2 = ref('');
+    const value3 = ref('');
+
+    return {
+      value,
+      value2,
+      value3
+    };
+  }
+};
+</script>
+
+<style lang="scss"></style>