Browse Source

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

Drjnigfubo 3 years ago
parent
commit
38d590022c

+ 1 - 1
project.config.json

@@ -44,7 +44,7 @@
   },
   "compileType": "miniprogram",
   "libVersion": "2.24.4",
-  "appid": "wx9ac45039b7813c7d",
+  "appid": "wxf2b976b67dab3882",
   "projectname": "nutui",
   "condition": {},
   "editorSetting": {

+ 1 - 0
src/packages/__VUE/datepicker/demo.vue

@@ -40,6 +40,7 @@
       "
       v-model:visible="show"
       :is-show-chinese="true"
+      :threeDimensional="false"
     ></nut-datepicker>
     <!-- 选择月日 -->
     <nut-datepicker

+ 2 - 0
src/packages/__VUE/datepicker/doc.en-US.md

@@ -32,6 +32,7 @@ app.use(OverLay);
       :min-date="minDate"
       :max-date="maxDate"
       :is-show-chinese="true"
+      :three-dimensional="false"
       @confirm="confirm"
   ></nut-datepicker> 
 </template>
@@ -378,6 +379,7 @@ app.use(OverLay);
 | ok-text           | Text of confirm button                                      | String  | confirm   |
 | cancel-text           | Text of cancel button                                          | String  | cancel   |
 | three-dimensional  `v3.1.23`          | Turn on 3D effects               | Boolean  | true   |
+| swipe-duration `v3.2.2`          | Duration of the momentum animation        | Number、String  | 1000   |
 
 ### Events
 

+ 3 - 1
src/packages/__VUE/datepicker/doc.md

@@ -33,6 +33,7 @@ app.use(OverLay);
       :min-date="minDate"
       :max-date="maxDate"
       :is-show-chinese="true"
+      :three-dimensional="false"
       @confirm="confirm"
   ></nut-datepicker> 
 </template>
@@ -387,7 +388,8 @@ DatetimePicker 通过 type 属性来定义需要选择的时间类型。将 type
 | title           | 设置标题                                          | String  | `null`   |
 | ok-text           | 确定按钮文案                                          | String  | 确定   |
 | cancel-text           | 取消按钮文案                                          | String  | 取消   |
-| three-dimensional`小程序不支持` `v3.1.23`          | 是否开启3D效果               | Boolean  | true   |
+| three-dimensional `v3.1.23`          | 是否开启3D效果               | Boolean  | true   |
+| swipe-duration `v3.2.2`          | 惯性滚动时长               | Number、String  | 1000    |
 
 ### Events
     

+ 12 - 1
src/packages/__VUE/datepicker/index.taro.vue

@@ -10,6 +10,8 @@
     :title="title"
     @confirm="confirm"
     :isWrapTeleport="isWrapTeleport"
+    :threeDimensional="threeDimensional"
+    :swipeDuration="swipeDuration"
   >
     <template #top>
       <slot name="top"></slot>
@@ -86,6 +88,16 @@ export default create({
       type: Function as PropType<import('./type').Formatter>,
       default: null
     },
+    // 是否开启3D效果
+    threeDimensional: {
+      type: Boolean,
+      default: true
+    },
+    // 惯性滚动 时长
+    swipeDuration: {
+      type: [Number, String],
+      default: 1000
+    },
     filter: Function as PropType<import('./type').Filter>
   },
   emits: ['click', 'update:visible', 'change', 'confirm', 'update:moduleValue'],
@@ -137,7 +149,6 @@ export default create({
           }
         }
       }
-
       return {
         [`${type}Year`]: year,
         [`${type}Month`]: month,

+ 6 - 0
src/packages/__VUE/datepicker/index.vue

@@ -11,6 +11,7 @@
     @confirm="confirm"
     :isWrapTeleport="isWrapTeleport"
     :threeDimensional="threeDimensional"
+    :swipeDuration="swipeDuration"
   >
     <template #top>
       <slot name="top"></slot>
@@ -93,6 +94,11 @@ export default create({
       type: Boolean,
       default: true
     },
+    // 惯性滚动 时长
+    swipeDuration: {
+      type: [Number, String],
+      default: 1000
+    },
     filter: Function as PropType<import('./type').Filter>
   },
   emits: ['click', 'update:visible', 'change', 'confirm', 'update:moduleValue'],

+ 14 - 43
src/packages/__VUE/picker/ColumnTaro.vue

@@ -18,20 +18,12 @@
           {{ item.text }}
         </view>
         <!-- 平铺 -->
-        <view
-          class="nut-picker-roller-item-tile"
-          ref="listbox"
-          :id="'listbox' + refRandomId"
-          v-if="item && item.text && !threeDimensional"
-        >
+        <view class="nut-picker-roller-item-tile" v-if="item && item.text && !threeDimensional">
           {{ item.text }}
         </view>
       </template>
     </view>
     <view class="nut-picker-roller-mask"></view>
-    <view class="nut-picker-content" ref="listbox" :id="'listbox' + refRandomId" v-if="threeDimensional">
-      <view class="nut-picker-list-panel" ref="list" :id="'list' + refRandomId" :style="touchTileStyle"> </view>
-    </view>
   </view>
 </template>
 <script lang="ts">
@@ -48,6 +40,10 @@ export default create({
     // 当前选中项
     value: [String, Number],
     columnsType: String,
+    lineSpacing: {
+      type: Number,
+      default: 36
+    },
     itemShow: {
       type: Boolean,
       default: false
@@ -89,7 +85,6 @@ export default create({
       currIndex: 1,
       transformY: 0,
       scrollDistance: 0,
-      lineSpacing: 36,
       rotation: 20,
       timer: null
     });
@@ -97,7 +92,6 @@ export default create({
     const roller = ref(null);
     const list = ref(null);
     const listitem = ref(null);
-    const listbox = ref(null);
 
     const moving = ref(false); // 是否处于滚动中
     const touchDeg = ref(0);
@@ -223,13 +217,13 @@ export default create({
         if (updateMove > 0) {
           updateMove = 0;
         }
-        if (updateMove < -(props.column.length - 1) * state.lineSpacing) {
-          updateMove = -(props.column.length - 1) * state.lineSpacing;
+        if (updateMove < -(props.column.length - 1) * props.lineSpacing) {
+          updateMove = -(props.column.length - 1) * props.lineSpacing;
         }
 
         // 设置滚动距离为lineSpacing的倍数值
-        let endMove = Math.round(updateMove / state.lineSpacing) * state.lineSpacing;
-        let deg = `${(Math.abs(Math.round(endMove / state.lineSpacing)) + 1) * state.rotation}deg`;
+        let endMove = Math.round(updateMove / props.lineSpacing) * props.lineSpacing;
+        let deg = `${(Math.abs(Math.round(endMove / props.lineSpacing)) + 1) * state.rotation}deg`;
         setTransform(endMove, type, time, deg);
 
         // let t = time ? time / 2 : 0;
@@ -237,10 +231,10 @@ export default create({
         //   setChooseValue();
         // }, t);
 
-        state.currIndex = Math.abs(Math.round(endMove / state.lineSpacing)) + 1;
+        state.currIndex = Math.abs(Math.round(endMove / props.lineSpacing)) + 1;
       } else {
         let deg = 0;
-        let currentDeg = (-updateMove / state.lineSpacing + 1) * state.rotation;
+        let currentDeg = (-updateMove / props.lineSpacing + 1) * state.rotation;
 
         // picker 滚动的最大角度
         const maxDeg = (props.column.length + 1) * state.rotation;
@@ -250,7 +244,7 @@ export default create({
 
         if (minDeg < deg && deg < maxDeg) {
           setTransform(updateMove, null, undefined, deg + 'deg');
-          state.currIndex = Math.abs(Math.round(updateMove / state.lineSpacing)) + 1;
+          state.currIndex = Math.abs(Math.round(updateMove / props.lineSpacing)) + 1;
         }
       }
     };
@@ -264,7 +258,7 @@ export default create({
       let index = column.findIndex((columnItem) => columnItem.value == props.value);
 
       state.currIndex = index === -1 ? 1 : (index as number) + 1;
-      let move = index === -1 ? 0 : (index as number) * state.lineSpacing;
+      let move = index === -1 ? 0 : (index as number) * props.lineSpacing;
       type && setChooseValue();
       setMove(-move);
     };
@@ -287,12 +281,6 @@ export default create({
       setChooseValue();
     };
 
-    const getReference = async () => {
-      const refe = await useTaroRect(listbox, Taro);
-      state.lineSpacing = refe.height ? refe.height : 36;
-      modifyStatus(true);
-    };
-
     watch(
       () => props.column,
       (val) => {
@@ -307,20 +295,6 @@ export default create({
     );
 
     watch(
-      () => props.itemShow,
-      (val) => {
-        if (val) {
-          setTimeout(() => {
-            getReference();
-          }, 200);
-        }
-      },
-      {
-        deep: true
-      }
-    );
-
-    watch(
       () => props.value,
       (val) => {
         state.transformY = 0;
@@ -332,9 +306,7 @@ export default create({
     );
 
     onMounted(() => {
-      setTimeout(() => {
-        getReference();
-      }, 200);
+      modifyStatus(false);
     });
 
     const refRandomId = Math.random().toString(36).slice(-8);
@@ -349,7 +321,6 @@ export default create({
       roller,
       list,
       listitem,
-      listbox,
       onTouchStart,
       onTouchMove,
       onTouchEnd,

+ 3 - 0
src/packages/__VUE/picker/demo.vue

@@ -88,6 +88,7 @@
     ></nut-cell>
     <nut-picker
       v-model:visible="showCascader"
+      v-model="selectedCascader"
       :columns="cascaderColumns"
       :title="translate('chooseCity')"
       @confirm="(options) => confirm('cascader', options)"
@@ -145,6 +146,7 @@ export default createDemo({
   setup() {
     const selectedValue = ref(['ZheJiang']);
     const selectedTime = ref(['Wednesday', 'Afternoon']);
+    const selectedCascader = ref(['FuJian', 'FuZhou', 'TaiJiang']);
     const asyncValue = ref<string[]>([]);
     const columsNum = ref([]);
     const columns = computed(() => [
@@ -392,6 +394,7 @@ export default createDemo({
       alwaysFun,
       translate,
       selectedTime,
+      selectedCascader,
       columsNum,
       showTile,
       showJK,

+ 3 - 1
src/packages/__VUE/picker/doc.en-US.md

@@ -224,6 +224,7 @@ Use the children field of the Columns attribute to cascade options
   <nut-cell title="Choose City" :desc="desc" @click="()=>{show=true}"></nut-cell>
   <nut-picker
     v-model:visible="show"
+    v-model="selectedCascader"
     :columns="cascaderColumns"
     title="Choose City"
     @confirm="confirm"
@@ -236,6 +237,7 @@ Use the children field of the Columns attribute to cascade options
     setup(props) {
       const show = ref(false);
       const desc = ref('');
+      const selectedCascader = ref(['FuJian', 'FuZhou','TaiJiang']);
       const cascaderColumns = ref([
         {
           text: 'ZheJiang',
@@ -290,7 +292,7 @@ Use the children field of the Columns attribute to cascade options
         console.log(selectedValue);
       };
 
-      return {show,desc,cascaderColumns,change, confirm};
+      return {show,desc,selectedCascader,cascaderColumns,change, confirm};
     }
   };
 </script>

+ 3 - 1
src/packages/__VUE/picker/doc.md

@@ -231,6 +231,7 @@ columns 属性可以通过二维数组的形式配置多列选择。
   <nut-cell title="请选择城市" :desc="desc" @click="()=>{show=true}"></nut-cell>
   <nut-picker
     v-model:visible="show"
+    v-model="selectedCascader"
     :columns="cascaderColumns"
     title="城市选择"
     @confirm="confirm"
@@ -243,6 +244,7 @@ columns 属性可以通过二维数组的形式配置多列选择。
     setup(props) {
       const show = ref(false);
       const desc = ref('');
+      const selectedCascader = ref(['FuJian', 'FuZhou','TaiJiang']);
       const cascaderColumns = ref([
         {
           text: '浙江',
@@ -297,7 +299,7 @@ columns 属性可以通过二维数组的形式配置多列选择。
         console.log(selectedValue);
       };
 
-      return {show,desc,cascaderColumns,change, confirm};
+      return {show,desc,selectedCascader,cascaderColumns,change, confirm};
     }
   };
 </script>

+ 31 - 6
src/packages/__VUE/picker/index.taro.vue

@@ -20,7 +20,7 @@
       </view>
       <slot name="top"></slot>
       <view class="nut-picker__column">
-        <view class="nut-picker__hairline"></view>
+        <view class="nut-picker__hairline" ref="pickerline" :id="'pickerline' + refRandomId"></view>
         <view class="nut-picker__columnitem" v-for="(column, columnIndex) in columnsList" :key="columnIndex">
           <nut-picker-column
             :ref="swipeRef"
@@ -31,6 +31,7 @@
             :value="defaultValues[columnIndex]"
             :threeDimensional="threeDimensional"
             :swipeDuration="swipeDuration"
+            :lineSpacing="lineSpacing"
             @change="
               (option) => {
                 changeHandler(columnIndex, option);
@@ -48,6 +49,8 @@ import { ref, onMounted, onBeforeUnmount, reactive, watch, computed, toRaw, toRe
 import { createComponent } from '@/packages/utils/create';
 import { popupProps } from '../popup/index.taro.vue';
 import column from './ColumnTaro.vue';
+import { useTaroRect } from '@/packages/utils/useTaroRect';
+import Taro from '@tarojs/taro';
 const { componentName, create, translate } = createComponent('picker');
 export default create({
   components: {
@@ -96,9 +99,12 @@ export default create({
   setup(props, { emit }) {
     const state = reactive({
       show: false,
-      formattedColumns: props.columns as import('./types').PickerOption[]
+      formattedColumns: props.columns as import('./types').PickerOption[],
+      lineSpacing: 36
     });
 
+    const pickerline = ref(null);
+
     // 选中项
     let defaultValues = ref<(number | string)[]>(props.modelValue);
 
@@ -235,8 +241,20 @@ export default create({
       emit('update:visible', false);
     };
 
+    const refRandomId = Math.random().toString(36).slice(-8);
+
+    const getReference = async () => {
+      const refe = await useTaroRect(pickerline, Taro);
+      state.lineSpacing = refe.height ? refe.height : 36;
+    };
+
     onMounted(() => {
-      if (props.visible) state.show = props.visible;
+      if (props.visible) {
+        setTimeout(() => {
+          getReference();
+        }, 200);
+        state.show = props.visible;
+      }
     });
 
     onBeforeUnmount(() => {
@@ -269,8 +287,13 @@ export default create({
       () => props.visible,
       (val) => {
         state.show = val;
-        console.log(defaultValues.value);
-        if (val) pickerColumn.value = [];
+        if (val) {
+          setTimeout(() => {
+            getReference();
+          }, 200);
+
+          pickerColumn.value = [];
+        }
       }
     );
 
@@ -293,7 +316,9 @@ export default create({
       defaultValues,
       translate,
       pickerColumn,
-      swipeRef
+      swipeRef,
+      refRandomId,
+      pickerline
     };
   }
 });

+ 12 - 0
src/packages/__VUE/searchbar/__tests__/searchbar.spec.ts

@@ -141,6 +141,17 @@ test('clear event test', async () => {
   expect(clear.exists()).toBe(true);
 });
 
+test('custom clear icon', async () => {
+  const wrapper = mount(SearchBar, {
+    props: {
+      clearIcon: 'close',
+      modelValue: 'test'
+    }
+  });
+  const input = wrapper.find('.nut-searchbar__input-clear i');
+  expect(input.classes()).toContain('nut-icon-close');
+});
+
 test('slot test', () => {
   const wrapper = mount(SearchBar, {
     props: { modelValue: '' },
@@ -163,5 +174,6 @@ test('slot test', () => {
       }
     }
   });
+
   expect(wrapper.html()).toMatchSnapshot();
 });

+ 17 - 5
src/packages/__VUE/searchbar/demo.vue

@@ -1,7 +1,8 @@
 <template>
   <div class="demo full">
     <h2>{{ translate('basic1') }}</h2>
-    <nut-searchbar v-model="searchValue" :label="translate('word1')"> </nut-searchbar>
+    <nut-searchbar v-model="searchValue" :label="translate('word1')" :focus-style="{ border: '1px solid red' }">
+    </nut-searchbar>
 
     <h2>{{ translate('basic2') }}</h2>
     <nut-searchbar v-model="searchValue1" @search="search"> </nut-searchbar>
@@ -26,6 +27,9 @@
     >
     </nut-searchbar>
 
+    <h2>{{ translate('basic7') }}</h2>
+    <nut-searchbar v-model="searchValue6" :clear-icon="icon2"> </nut-searchbar>
+
     <h2>{{ translate('basic6') }}</h2>
     <nut-searchbar v-model="searchValue5" @click-right-icon="clickRightIcon">
       <template v-slot:leftout>
@@ -59,6 +63,7 @@ const initTranslate = () =>
       basic4: '右侧添加搜索文字',
       basic5: '更改输入框内部及外部的背景样式',
       basic6: '显示全部 icon',
+      basic7: '自定义清除按钮 icon',
       word1: '标签',
       word2: '搜索',
       title3: '标题3'
@@ -70,6 +75,7 @@ const initTranslate = () =>
       basic4: 'Add search text to the right',
       basic5: 'Change the background style inside and outside the input box',
       basic6: 'Show all icons',
+      basic7: 'custom clear button icons',
       word1: 'label',
       word2: 'search'
     }
@@ -77,6 +83,9 @@ const initTranslate = () =>
 export default createDemo({
   props: {},
   setup() {
+    const icon = 'close';
+    const icon2 =
+      'https://img10.360buyimg.com/imagetools/jfs/t1/170133/30/22902/10546/61833626E32d7ccde/a7c373ba30de9a89.png';
     initTranslate();
     const state = reactive({
       searchValue: '',
@@ -84,24 +93,27 @@ export default createDemo({
       searchValue2: '',
       searchValue3: '',
       searchValue4: '',
-      searchValue5: ''
+      searchValue5: '',
+      searchValue6: ''
     });
 
-    const search = function (e: any) {
+    const search = function () {
       Toast.text('搜索触发');
     };
 
     const clickLeft = function () {
       Toast.text('点击回退按钮');
     };
-    const clickLeftIcon = function (a: string, b: any) {
+    const clickLeftIcon = function (a: string, b: Event) {
       console.log(a, b);
     };
-    const clickRightIcon = function (a: string, b: any) {
+    const clickRightIcon = function (a: string, b: Event) {
       console.log(a, b);
     };
 
     return {
+      icon,
+      icon2,
       clickLeft,
       clickLeftIcon,
       clickRightIcon,

+ 30 - 1
src/packages/__VUE/searchbar/doc.md

@@ -129,7 +129,7 @@ app.use(SearchBar).use(Icon);
 :::demo
 ```html
 <template>
-  <nut-searchbar v-model="searchValue4" background="linear-gradient(to right, #9866F0, #EB4D50)" input-background="#fff"> </nut-searchbar>
+  <nut-searchbar v-model="searchValue" background="linear-gradient(to right, #9866F0, #EB4D50)" input-background="#fff"> </nut-searchbar>
 </template>
 <script lang="ts">
   import { toRefs, reactive } from 'vue';
@@ -147,6 +147,33 @@ app.use(SearchBar).use(Icon);
 </script>
 ```
 :::
+
+### 自定义清除按钮 icon
+:::demo
+```html
+<template>
+  <nut-searchbar v-model="searchValue" :clear-icon="icon"> </nut-searchbar>
+</template>
+<script lang="ts">
+  import { toRefs, reactive } from 'vue';
+  export default {
+    setup() {
+      const state = reactive({
+        searchValue: ""
+      });
+      const icon =
+      'https://img10.360buyimg.com/imagetools/jfs/t1/170133/30/22902/10546/61833626E32d7ccde/a7c373ba30de9a89.png';
+
+      return {
+        ...toRefs(state),
+        icon
+      };
+    }
+  };
+</script>
+```
+:::
+
 ### 显示全部 icon
 :::demo
 ```html
@@ -195,11 +222,13 @@ app.use(SearchBar).use(Icon);
 | input-type    | 输入框类型   | String | 'text'      |
 | placeholder        | 输入框默认暗纹  | String | '请输入'   |
 | clearable          | 是否展示清除按钮 | Boolean | true     |
+| close-icon `v3.2.2`     | 自定义关闭图标 | String | 'circle-close'   |
 | background      | 输入框外部背景 | String |   '#fff'   |
 | input-background   | 输入框内部背景 | String |   '#f7f7f7'   |
 | confirm-type   | 键盘右下角按钮的文字(`仅支持小程序`),仅在`type='text'`时生效,可选值 `send`:发送、`search`:搜索、`next`:下一个、`go`:前往、`done`:完成 | String |   `done`   |
 | input-background   | 输入框内部背景 | String |   '#f7f7f7'   |
 | autofocus `v3.1.21` | 是否自动聚焦 | boolean | false |
+| focus-style `v3.2.2` | 聚焦时搜索框样式 | Object | - |
 | disabled `v3.1.21` | 是否禁用输入框 | boolean | false |
 | readonly `v3.1.21`| 输入框只读 | boolean | false |
 | input-align `v3.1.21`| 对齐方式,可选`center` `right` | string | `left` |

+ 2 - 0
src/packages/__VUE/searchbar/index.scss

@@ -26,6 +26,7 @@
   padding: $searchbar-padding;
   background: $searchbar-background;
   box-sizing: border-box;
+
   &__search-label {
     padding: 0 5px;
     color: #323233;
@@ -40,6 +41,7 @@
     border-radius: $searchbar-input-border-radius;
     box-shadow: $searchbar-input-box-shadow;
     background: $searchbar-input-background;
+    box-sizing: border-box;
 
     .nut-searchbar__input-inner {
       display: flex;

+ 33 - 13
src/packages/__VUE/searchbar/index.taro.vue

@@ -3,7 +3,7 @@
     <view v-if="$slots.leftout" class="nut-searchbar__search-icon nut-searchbar__left-search-icon">
       <slot name="leftout"></slot>
     </view>
-    <view class="nut-searchbar__search-input" :style="inputSearchbarStyle">
+    <view class="nut-searchbar__search-input" :style="{ ...inputSearchbarStyle, ...focusCss }">
       <view v-if="$slots.leftin" class="nut-searchbar__search-icon nut-searchbar__iptleft-search-icon">
         <slot name="leftin"></slot>
       </view>
@@ -24,11 +24,16 @@
             @focus="valueFocus"
             @blur="valueBlur"
             @confirm="handleSubmit"
-            :style="styleSearchbar"
+            :style="(styleSearchbar as CSSProperties)"
           />
         </form>
-        <view @click="handleClear" class="nut-searchbar__input-clear" v-if="clearable" v-show="modelValue.length > 0">
-          <nut-icon name="circle-close" size="12" color="#555"></nut-icon>
+        <view
+          @click="handleClear"
+          class="nut-searchbar__input-clear"
+          v-if="clearable"
+          v-show="(modelValue as string).length > 0"
+        >
+          <nut-icon :name="clearIcon" size="12" color="#555"></nut-icon>
         </view>
       </view>
       <view v-if="$slots.rightin" class="nut-searchbar__search-icon nut-searchbar__iptright-sarch-icon">
@@ -42,13 +47,13 @@
 </template>
 
 <script lang="ts">
-import { toRefs, reactive, computed, ref, onMounted, PropType } from 'vue';
+import { toRefs, reactive, computed, ref, onMounted, PropType, Ref, CSSProperties } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 const { create, translate } = createComponent('searchbar');
-interface Events {
-  eventName: 'change' | 'focus' | 'blur' | 'clear' | 'update:modelValue';
-  params: (string | number | Event)[];
-}
+// interface Events {
+//   eventName: 'change' | 'focus' | 'blur' | 'clear' | 'update:modelValue';
+//   params: (string | number | Event)[];
+// }
 export type confirmTextType = 'send' | 'search' | 'next' | 'go' | 'done';
 
 export default create({
@@ -73,6 +78,10 @@ export default create({
       type: Boolean,
       default: true
     },
+    clearIcon: {
+      type: String,
+      default: 'circle-close'
+    },
     background: {
       type: String,
       default: ''
@@ -89,6 +98,11 @@ export default create({
       type: Boolean,
       default: false
     },
+    focusStyle: {
+      type: Object,
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      default: () => {}
+    },
     disabled: {
       type: Boolean,
       default: false
@@ -142,10 +156,12 @@ export default create({
       emit('change', val, event);
     };
 
+    const focusCss = ref({});
     const valueFocus = (event: Event) => {
       const input = event.target as HTMLInputElement;
       let value = input.value;
       state.active = true;
+      focusCss.value = props.focusStyle;
       emit('focus', value, event);
     };
 
@@ -159,6 +175,7 @@ export default create({
       if (props.maxLength && value.length > Number(props.maxLength)) {
         value = value.slice(0, Number(props.maxLength));
       }
+      focusCss.value = {};
       emit('blur', value, event);
     };
 
@@ -184,15 +201,17 @@ export default create({
       emit('click-right-icon', props.modelValue, event);
     };
 
-    const styleSearchbar: any = computed(() => {
+    const styleSearchbar = computed(() => {
       return {
-        'text-align': props.inputAlign
+        style: {
+          textAlign: props.inputAlign
+        }
       };
     });
-    const inputsearch: any = ref(null);
+    const inputsearch: Ref<HTMLElement | null> = ref(null);
     onMounted(() => {
       if (props.autofocus) {
-        inputsearch.value.focus();
+        (inputsearch.value as HTMLElement).focus();
       }
     });
     return {
@@ -205,6 +224,7 @@ export default create({
       handleSubmit,
       searchbarStyle,
       inputSearchbarStyle,
+      focusCss,
       translate,
       clickInput,
       leftIconClick,

+ 31 - 14
src/packages/__VUE/searchbar/index.vue

@@ -4,7 +4,7 @@
     <view v-if="$slots.leftout" class="nut-searchbar__search-icon nut-searchbar__left-search-icon">
       <slot name="leftout"></slot>
     </view>
-    <view class="nut-searchbar__search-input" :style="inputSearchbarStyle">
+    <view class="nut-searchbar__search-input" :style="{ ...inputSearchbarStyle, ...focusCss }">
       <view
         v-if="$slots.leftin"
         class="nut-searchbar__search-icon nut-searchbar__iptleft-search-icon"
@@ -27,11 +27,16 @@
             @input="valueChange"
             @focus="valueFocus"
             @blur="valueBlur"
-            :style="styleSearchbar"
+            :style="(styleSearchbar as CSSProperties)"
           />
         </form>
-        <view @click="handleClear" class="nut-searchbar__input-clear" v-if="clearable" v-show="modelValue.length > 0">
-          <nut-icon name="circle-close" size="12" color="#555"></nut-icon>
+        <view
+          @click="handleClear"
+          class="nut-searchbar__input-clear"
+          v-if="clearable"
+          v-show="(modelValue as string).length > 0"
+        >
+          <nut-icon :name="clearIcon" size="12" color="#555"></nut-icon>
         </view>
       </view>
       <view
@@ -49,14 +54,13 @@
 </template>
 
 <script lang="ts">
-import { toRefs, reactive, computed, onMounted, ref } from 'vue';
+import { toRefs, reactive, computed, onMounted, ref, Ref, CSSProperties } from 'vue';
 import { createComponent } from '@/packages/utils/create';
-import { nextTick } from '@tarojs/taro';
 const { create, translate } = createComponent('searchbar');
-interface Events {
-  eventName: 'change' | 'focus' | 'blur' | 'clear' | 'update:modelValue';
-  params: (string | number | Event)[];
-}
+// interface Events {
+//   eventName: 'change' | 'focus' | 'blur' | 'clear' | 'update:modelValue';
+//   params: (string | number | Event)[];
+// }
 export default create({
   props: {
     modelValue: {
@@ -83,6 +87,10 @@ export default create({
       type: Boolean,
       default: true
     },
+    clearIcon: {
+      type: String,
+      default: 'circle-close'
+    },
     background: {
       type: String,
       default: ''
@@ -91,6 +99,11 @@ export default create({
       type: String,
       default: ''
     },
+    focusStyle: {
+      type: Object,
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      default: () => {}
+    },
     autofocus: {
       type: Boolean,
       default: false
@@ -148,10 +161,12 @@ export default create({
       emit('change', val, event);
     };
 
+    const focusCss = ref({});
     const valueFocus = (event: Event) => {
       const input = event.target as HTMLInputElement;
       let value = input.value;
       state.active = true;
+      focusCss.value = props.focusStyle;
       emit('focus', value, event);
     };
 
@@ -165,6 +180,7 @@ export default create({
       if (props.maxLength && value.length > Number(props.maxLength)) {
         value = value.slice(0, Number(props.maxLength));
       }
+      focusCss.value = {};
       emit('blur', value, event);
     };
 
@@ -190,15 +206,15 @@ export default create({
       emit('click-right-icon', props.modelValue, event);
     };
 
-    const styleSearchbar: any = computed(() => {
+    const styleSearchbar = computed(() => {
       return {
-        'text-align': props.inputAlign
+        textAlign: props.inputAlign
       };
     });
-    const inputsearch: any = ref(null);
+    const inputsearch: Ref<HTMLElement | null> = ref(null);
     onMounted(() => {
       if (props.autofocus) {
-        inputsearch.value.focus();
+        (inputsearch.value as HTMLElement).focus();
       }
     });
 
@@ -212,6 +228,7 @@ export default create({
       handleSubmit,
       searchbarStyle,
       inputSearchbarStyle,
+      focusCss,
       translate,
       clickInput,
       leftIconClick,

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

@@ -42,10 +42,13 @@
     color: $textarea-text-color;
     text-align: left;
     background-color: transparent;
-    border: 0;
+    border: none;
     resize: none;
     line-height: 20px;
   }
+  &__ali {
+    line-height: 17px;
+  }
   .cpoyText {
     position: absolute;
     top: -999999px;

+ 19 - 7
src/packages/__VUE/textarea/index.taro.vue

@@ -6,7 +6,7 @@
     <textarea
       v-else
       ref="textareaRef"
-      class="nut-textarea__textarea"
+      :class="['nut-textarea__textarea', env == 'ALIPAY' && 'nut-textarea__ali']"
       :style="styles"
       :rows="rows"
       :disabled="disabled"
@@ -89,7 +89,6 @@ export default create({
       return {
         textAlign: props.textAlign,
         height: props.autosize ? heightSet.value : 'null'
-        // resize: props.autosize ? 'vertical' : 'none'
       };
     });
 
@@ -121,9 +120,7 @@ export default create({
       if (props.disabled) return;
       if (props.readonly) return;
       const input = event.target as HTMLInputElement;
-
       let value = input.value;
-
       emitChange(value, event);
       emit('blur', event);
     };
@@ -179,10 +176,9 @@ export default create({
 
     const getRefHeight = () => {
       const query = Taro.createSelectorQuery();
-      // const query = Taro.createSelectorQuery();
       query.selectAll('.nut-textarea__textarea').boundingClientRect();
       let uid = textareaRef.value ? textareaRef.value.uid : '0';
-      query.exec((res) => {
+      query.exec((res: any) => {
         if (res[0] && textareaRef.value) {
           let _item: any = Array.from(res[0]).filter((item: any) => item.id == uid);
           textareaHeight.value = _item[0]['height'] || 20;
@@ -192,10 +188,25 @@ export default create({
       });
     };
 
+    const getRefWidth = () => {
+      const query = Taro.createSelectorQuery();
+      query.select('.nut-textarea__textarea').boundingClientRect();
+      query.exec((res: any) => {
+        if (res[0] && textareaRef.value) {
+          copyTxtStyle.value.width = res[0]['width'] + 'px';
+        }
+      });
+    };
+    const env = Taro.getEnv();
     onMounted(() => {
       if (props.autosize) {
         eventCenter.once((getCurrentInstanceTaro() as any).router.onReady, () => {
-          getRefHeight();
+          if (Taro.getEnv() === 'ALIPAY') {
+            getRefWidth();
+            copyHeight();
+          } else {
+            getRefHeight();
+          }
           // setTimeout(() => {
           //   nextTick(getContentHeight);
           // }, 300);
@@ -204,6 +215,7 @@ export default create({
     });
 
     return {
+      env,
       textareaRef,
       classes,
       styles,

+ 1 - 0
src/sites/mobile-taro/vue/src/dentry/pages/datepicker/index.vue

@@ -25,6 +25,7 @@
         }
       "
       v-model:visible="show"
+      :threeDimensional="false"
       :is-show-chinese="true"
     ></nut-datepicker>
     <!-- 选择月日 -->

+ 8 - 2
src/sites/mobile-taro/vue/src/dentry/pages/picker/index.vue

@@ -68,6 +68,7 @@
       "
     ></nut-cell>
     <nut-picker
+      v-model="selectedTime"
       v-model:visible="showMultiple"
       :columns="multipleColumns"
       title="城市选择"
@@ -86,6 +87,7 @@
       "
     ></nut-cell>
     <nut-picker
+      v-model="selectedCascader"
       v-model:visible="showCascader"
       :columns="cascaderColumns"
       title="城市选择"
@@ -129,7 +131,7 @@
       <nut-button block type="primary" @click="alwaysFun">永远有效</nut-button></nut-picker
     >
 
-    <h2>异步获取</h2>
+    <!-- <h2>异步获取</h2>
     <nut-cell
       title="异步获取"
       :desc="effect"
@@ -145,7 +147,7 @@
       title="异步获取"
       @confirm="(options) => confirm('effect', options)"
       @change="portChange"
-    ></nut-picker>
+    ></nut-picker> -->
   </div>
 </template>
 <script lang="ts">
@@ -155,6 +157,8 @@ export default {
   props: {},
   setup() {
     const selectedValue = ref(['ZheJiang']);
+    const selectedTime = ref(['Wednesday', 'Afternoon']);
+    const selectedCascader = ref(['FuJian', 'FuZhou', 'TaiJiang']);
     const asyncValue = ref<string[]>([]);
     const columsNum = ref([]);
     const columns = ref([
@@ -361,6 +365,8 @@ export default {
     };
     return {
       selectedValue,
+      selectedTime,
+      selectedCascader,
       asyncValue,
       columns,
       show,

+ 10 - 2
src/sites/mobile-taro/vue/src/dentry/pages/searchbar/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="demo full">
     <h2>基础用法</h2>
-    <nut-searchbar v-model="searchValue"> </nut-searchbar>
+    <nut-searchbar v-model="searchValue" :focus-style="{ border: '1px solid red' }"> </nut-searchbar>
 
     <h2>搜索事件监听</h2>
     <nut-searchbar v-model="searchValue1" @search="search"> </nut-searchbar>
@@ -26,6 +26,9 @@
     >
     </nut-searchbar>
 
+    <h2>自定义清除按钮 icon</h2>
+    <nut-searchbar v-model="searchValue6" :clear-icon="icon"> </nut-searchbar>
+
     <h2>显示全部 icon</h2>
     <nut-searchbar v-model="searchValue5">
       <template v-slot:leftout>
@@ -49,6 +52,9 @@ import { toRefs, reactive } from 'vue';
 export default {
   props: {},
   setup() {
+    const icon =
+      'https://img10.360buyimg.com/imagetools/jfs/t1/170133/30/22902/10546/61833626E32d7ccde/a7c373ba30de9a89.png';
+
     const state = reactive({
       searchValue: '',
       searchValue1: '',
@@ -56,10 +62,11 @@ export default {
       searchValue3: '',
       searchValue4: '',
       searchValue5: '',
+      searchValue6: '',
       confirmType: 'search'
     });
 
-    const search = function (e: any) {
+    const search = function () {
       console.log('搜索触发');
     };
 
@@ -68,6 +75,7 @@ export default {
     };
 
     return {
+      icon,
       clickLeft,
       search,
       ...toRefs(state)