Browse Source

fix: issue问题修复 (#1458)

* fix: marge主分支 (#1)

* doc: calendar 文档修改 (#1410)

* feat: 添加range组件、calendar组件在线文档

* fix: 文档调整

* fix: 重构calendar组件

* feat: 日历组件重构,文档修改,功能完善

* fix: 格式化

* fix: 代码格式化调整。

* fix: 去除无用代码

* fix: 文档调整

* fix:  文档调整

* fix: taro  demo 样式修改

* feat: range组件功能完善,新增 竖向操作,刻度展示。

* fix: 冲突解决

* feat: taro功能新增,兼容处理,文档修改

* feat: 添加range组件,jdt主题色

* fix: 修改组件初始化逻辑

* feat: 新增h5 日期多选功能

* feat: taro版本添加 日期多选功能

* fix: 修复多选,无法选中开头结尾日期问题

* fix: 文档修改,添加en-US 文档

* fix: 文档完善

Co-authored-by: lkjh3214 <13121007159@163.com>
Co-authored-by: love_forever <1039168735@qq.com>

* feat: imagepreview 部分功能补齐 (#1412)

* feat: image新增单元测试

* feat: ellipsis添加单元测试

* feat: imagepreview 添加

* fix: popop单元测试修改

* docs: 添加版本号

* feat: support highlight for JetBrains web-types

* test(imagepreview): edit snap

* fix(image): dts edit import

* docs(input): demo和md国际化文案修改 (#1414)

* fix: 抽离 input  ConfirmTextType

* feat: input、switch国际化

* feat: category、address国际化

* feat: taro升级maxlength问题

* fix: 国际化增加默认字段

* fix: blank

* fix: input组件国际化文案修改

* style: add ellipsis add sass

* docs(elevator): 增加吸顶props

* feat: input组件新增input slot插槽 (#1418)

* fix: 抽离 input  ConfirmTextType

* feat: input、switch国际化

* feat: category、address国际化

* feat: taro升级maxlength问题

* fix: 国际化增加默认字段

* fix: blank

* fix: input组件国际化文案修改

* feat: input组件新增input slot插槽

* release: v3.1.22

* Update README.md

add alipay img

* Update README.md

* docs: changelog 3.1.22

Co-authored-by: lkjh3214 <305624531@qq.com>
Co-authored-by: lkjh3214 <13121007159@163.com>
Co-authored-by: love_forever <1039168735@qq.com>
Co-authored-by: richard1015 <51844712@qq.com>
Co-authored-by: ailululu <912429321@qq.com>
Co-authored-by: snandy <zhouyrt@gmail.com>

* feat: imagepreview重复问题修改

* fix: picker 组件重影问题修改

* fix: 科技样式同步

* feat: picker组件惯性滚动优化

* feat: picker组件惯性滚动优化

* fix: issue问题修噶

* fix: datepicker国际化修噶

Co-authored-by: lkjh3214 <305624531@qq.com>
Co-authored-by: lkjh3214 <13121007159@163.com>
Co-authored-by: love_forever <1039168735@qq.com>
Co-authored-by: richard1015 <51844712@qq.com>
Co-authored-by: ailululu <912429321@qq.com>
Co-authored-by: snandy <zhouyrt@gmail.com>
yangxiaolu1993 3 years ago
parent
commit
d8fc2d3cbf

+ 2 - 2
src/packages/__VUE/comment/components/CmtHeader.vue

@@ -13,7 +13,7 @@
           </view>
 
           <view class="nut-comment-header__user-score">
-            <nut-rate v-model="info.score" icon-size="10" spacing="5" readOnly @change="handleClick" />
+            <nut-rate v-model="info.score" icon-size="10" spacing="5" readonly @change="handleClick" />
           </view>
         </view>
 
@@ -25,7 +25,7 @@
       <view class="nut-comment-header__time" v-if="info.time">{{ info.time }}</view>
     </view>
     <view :class="[`nut-comment-header__${type}-score`]" v-if="type == 'complex'">
-      <nut-rate v-model="info.score" icon-size="12" spacing="3" />
+      <nut-rate v-model="info.score" icon-size="12" spacing="3" readonly />
       <i :class="[`nut-comment-header__${type}-score-i`]"></i>
       <view :class="[`nut-comment-header__${type}-score-size`]">{{ info.size }}</view>
     </view>

+ 356 - 187
src/packages/__VUE/datepicker/doc.en-US.md

@@ -1,226 +1,395 @@
-# Dialog
-
+#  DatePicker
 
 ### Intro
-
-Modal dialog box is displayed in the floating layer to guide users to carry out relevant operations. It is often used for message prompt, message confirmation, or completing specific interactive operations in the current page.
-
-The popup box component supports function call and component call.
-
+    
+Used to select time, support date and time dimensions, usually used with the Popup component.
+    
 ### Install
     
 ```javascript
 import { createApp } from 'vue';
-import { Dialog,Popup,OverLay } from '@nutui/nutui';
+// vue
+import { DatePicker, Picker, Popup, OverLay } from '@nutui/nutui';
+// taro
+import { DatePicker, Picker, Popup, OverLay } from '@nutui/nutui-taro';
 
 const app = createApp();
-app.use(Dialog).use(Popup).use(OverLay)
+app.use(DatePicker);
+app.use(Picker);
+app.use(Popup);
+app.use(OverLay);
 ```
+    
+### Choose Date
+:::demo
 
+```html
+<template>
+  <nut-cell title="Show Chinese" :desc="desc" @click="show = true"></nut-cell>
+  <nut-datepicker
+      v-model="currentDate"
+      v-model:visible="show"
+      :min-date="minDate"
+      :max-date="maxDate"
+      :is-show-chinese="true"
+      @confirm="confirm"
+  ></nut-datepicker> 
+</template>
 
-## Function use
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('2022-05-10');
+      const minDate = new Date(2020, 0, 1),
+      const maxDate = new Date(2025, 10, 1),
+      const currentDate = new Date(2022, 4, 10, 10, 10);
+      const confirm = ({ selectedValue, selectedOptions })=>{
+        desc.value = selectedOptions.map((option) => option.text).join('');
+      }
+      return {
+        currentDate,
+        show,
+        desc,
+        minDate,
+        maxDate,
+        confirm
+      };
+    }
+  };
+</script>
+
+```
+:::
+
+### Choose Month-Day
 
 :::demo
 ```html
 <template>
- <nut-cell-group title="Function Use">
-  <nut-cell title="Title" @click="baseClick"></nut-cell>
-  <nut-cell title="Title" @click="noTitleClick"></nut-cell>
-  <nut-cell title="Title" @click="tipsClick"></nut-cell>
-  <nut-cell title="Title" @click="verticalClick"></nut-cell>
-</nut-cell-group>
+  <nut-cell title="Limit the start and end time" :desc="desc" @click="show = true"></nut-cell>
+  <nut-datepicker
+      v-model="currentDate"
+      type="month-day"
+      title="Choose Time"
+      :min-date="new Date(2022, 0, 1)"
+      :max-date="new Date(2022, 7, 1)"
+      @confirm="confirm"
+      v-model:visible="show"
+  ></nut-datepicker> 
 </template>
-<script lang="ts">
-import { ref } from 'vue';
-import { Dialog } from '@nutui/nutui';
-export default {
-    setup() {
-        const onCancel = () => {
-          console.log('event cancel');
-        };
-        const onOk = () => {
-          console.log('event ok');
-        };
-        const baseClick = (): void => {
-          Dialog({
-            title: 'Basic spring frame',
-            content: 'Function call and component call are supported.',
-            onCancel,
-            onOk
-          });
-        };
-        const noTitleClick = () => {
-          Dialog({
-            content: 'Content',
-            onCancel,
-            onOk
-          });
-        };
-        const tipsClick = () => {
-          Dialog({
-            title: 'Title',
-            content: 'Function call and component call are supported.',
-            noCancelBtn: true,
-            onCancel,
-            onOk
-          });
-        };
-        const verticalClick = () => {
-          Dialog({
-            title: 'Title',
-            content: 'Support vertical arrangement of bottom buttons.',
-            footerDirection: 'vertical',
-            onCancel,
-            onOk
-          });
-        };
-        return {
-          baseClick,
-          noTitleClick,
-          tipsClick,
-          verticalClick
-        };
+
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('05-10');
+      const currentDate = new Date(2022, 4, 10, 10, 10);
+      const confirm = ( { selectedValue, selectedOptions } )=>{
+        desc.value = selectedValue.join('-');
+      }
+      return {
+        show,
+        desc,
+        currentDate,
+        confirm
+      };
     }
-}
+  };
 </script>
 ```
-::: 
+:::
+### Choose DateTime
 
-## Teleport use, mount to the specified element node
+:::demo
 
-``` html
-<nut-dialog teleport="#app" ... />
+```html
+<template>
+  <nut-cell title="Choose Time" :desc="desc" @click="show = true"></nut-cell>
+  <nut-datepicker
+      v-model="currentDate"
+      title="Choose Time"
+      type="datetime"
+      :min-date="minDate"
+      :max-date="maxDate"
+      @confirm="confirm"
+      v-model:visible="show" 
+  ></nut-datepicker> 
+</template>
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('2022-05-10 10:10');
+      const currentDate = new Date(2022, 4, 10, 10, 10);
+      const confirm = ( { selectedValue, selectedOptions } )=>{
+        date = selectedValue.slice(0, 3).join('-');
+        time = selectedValue.slice(3).join(':');
+        desc.value = date + ' ' + time;
+      }
+      return {
+        show,
+        desc,
+        currentDate,
+        minDate: new Date(2020, 0, 1),
+        maxDate: new Date(2025, 10, 1),
+        confirm
+      };
+    }
+  };
+</script>
 ```
+:::
 
-``` javascript
-Dialog({
-  teleport: '#app',
-  ...
-});
-Dialog({
-  teleport: '.demo',
-  ...
-});
+### Choose Time
+:::demo
+```html
+<template>
+  <nut-cell title="Choose Time" :desc="desc" @click="show = true"></nut-cell>
+  <nut-datepicker
+      v-model="currentDate"
+      title="Choose Time"
+      type="time"
+      :min-date="minDate"
+      :max-date="maxDate"
+      @confirm="confirm"
+      v-model:visible="show"
+  ></nut-datepicker>
+</template>
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('10:10:00');
+      const currentDate = new Date(2022, 4, 10, 10, 10);
+      const confirm = ( { selectedValue, selectedOptions } )=>{
+        desc.value = selectedValue.join(':');
+      }
+      return {
+        show,
+        desc,
+        currentDate,
+        minDate: new Date(2020, 0, 1),
+        maxDate: new Date(2025, 10, 1),
+        confirm
+      };
+    }
+  };
+</script>
 ```
+:::
 
-## Function use proxy.&dialog(...)
-
-```javascript
-import { ref } from 'vue';
-import { Dialog } from '@nutui/nutui';
-import { getCurrentInstance } from 'vue';
-
-export default {
-  setup() {
-    const { proxy } = getCurrentInstance();
-    proxy.$dialog({
-      title: 'Basic spring frame',
-      content: 'Function call and component call are supported.'
-    });
-  }
-}
+### Option Formatter
+:::demo
+```html
+<template>
+  <nut-cell title="Choose Time" :desc="desc" @click="show = true"></nut-cell>
+  <nut-datepicker
+      v-model="currentDate"
+      title="Choose Time"
+      type="datetime"
+      :min-date="new Date(2022, 0, 1)"
+      :max-date="new Date(2022, 10, 1)"
+      :formatter="formatter"
+      @confirm="confirm"
+      v-model:visible="show"
+  ><nut-button block type="primary" @click="alwaysFun">Forever</nut-button></nut-datepicker>
+</template>
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('10:10:00');
+      const currentDate = new Date(2022, 4, 10, 10, 10);
+      const confirm = ( { selectedValue, selectedOptions } )=>{
+        date = selectedOptions.slice(1, 3).map((op) => op.text).join('');
+        time = selectedOptions.slice(3).map((op) => op.value).join(':');
+        desc.value = selectedOptions[0].text + 'Year' + date + ' ' + time;
+      }
+      const formatter = (type: string, option) => {
+        switch (type) {
+          case 'year':
+            option.text += '';
+            break;
+          case 'month':
+            option.text += 'Month';
+            break;
+          case 'day':
+            option.text += 'Day';
+            break;
+          case 'hour':
+            option.text += 'Hour';
+            break;
+          case 'minute':
+            option.text += 'Minute';
+            break;
+          default:
+            option.text += '';
+        }
+        return option;
+      };
+      const alwaysFun = () => {
+        show.value = false;
+        desc.value = 'Forever';
+      };
+      return {
+        show,
+        desc,
+        currentDate,
+        confirm,
+        formatter,
+        alwaysFun
+      };
+    }
+  };
+</script>
 ```
+:::
 
+### Option Steps
 
-## Template use
+:::demo
+```html
+<template>
+  <nut-cell title="Choose Time" :desc="desc" @click="show = true"></nut-cell>
+  <nut-datepicker
+      v-model="currentDate"
+      type="time"
+      :minute-step="5"
+      :min-date="minDate"
+      :max-date="maxDate"
+      @confirm="confirm"
+      v-model:visible="show"
+  ></nut-datepicker>
+</template>
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('10:10:00');
+      const currentDate = new Date(2022, 4, 10, 10, 10);
+      const confirm = ( { selectedValue, selectedOptions } )=>{
+        desc.value = selectedValue.join(':');
+      }
+      return {
+        show,
+        desc,
+        minDate: new Date(2020, 0, 1),
+        maxDate: new Date(2025, 10, 1),
+        confirm
+      };
+    }
+  };
+</script>
+```
+:::
 
+### Option Filter
 
 :::demo
 ```html
 <template>
-  <nut-cell-group title="Template use">
-    <nut-cell title="Template use" @click="componentClick"></nut-cell>
-    <nut-dialog
-      teleport="#app"
-      title="Template use"
-      content="Function call and template call are supported."
-      v-model:visible="visible"
-    >
-    </nut-dialog>
-    <nut-cell title="Bottom button vertical use" @click="componentvVrticalClick"></nut-cell>
-    <nut-dialog
-      footer-direction="vertical"
-      teleport="#app"
-      title="Template use"
-      content="Function call and template call are supported."
-      v-model:visible="visible1"
-    >
-    </nut-dialog>
-  </nut-cell-group>
+  <nut-cell title="Choose Time" :desc="desc" @click="show = true"></nut-cell>
+  <nut-datepicker
+      v-model="currentDate"
+      title="Choose Time"
+      type="datehour"
+      :min-date="minDate"
+      :max-date="maxDate"
+      :filter="filter"
+      :formatter="formatter"
+      @confirm="confirm"
+      v-model:visible="show"
+  ></nut-datepicker>
 </template>
-<script lang="ts">
-import { ref } from 'vue';
-export default {
-  setup() {
-    const visible = ref(false);
-    const visible1 = ref(false);
-    const componentClick = () => {
-      visible.value = true;
-    };
-    const componentvVrticalClick = () => {
-      visible1.value = true;
-    };
-    return { visible,visible1,componentClick,componentvVrticalClick };
-  }
-}
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('2022-05-10 00');
+      const currentDate = new Date(2022, 4, 10, 0, 0);
+      const formatter = (type: string, option) => {
+        switch (type) {
+          case 'year':
+            option.text += 'Year';
+            break;
+          case 'month':
+            option.text += 'Month';
+            break;
+          case 'day':
+            option.text += 'Day';
+            break;
+          case 'hour':
+            option.text += 'Hour';
+            break;
+          default:
+            option.text += '';
+        }
+        return option;
+      };
+
+      const filter = (type: string, options) => {
+        if (type == 'hour') {
+          return options.filter((option) => Number(option.value) % 6 === 0);
+        }
+        return options;
+      };
+      const confirm = ( { selectedValue, selectedOptions } )=>{
+        descList[index].value = selectedOptions.map((option) => option.text).join('');
+      }
+      return {
+        show,
+        desc,
+        minDate: new Date(2020, 0, 1),
+        maxDate: new Date(2025, 10, 1),
+        confirm,
+        formatter,
+        filter
+      };
+    }
+  };
 </script>
 ```
 :::
 
 ## API
-| Attribute           | Description                                                                    | Type             | Default              |
-|---------------------|--------------------------------------------------------------------------------|------------------|----------------------|
-| title               | Title                                                                          | String           | -                    |
-| id                  | Identifier, share one instance at the same time, default to multiple instances | String or Number | new Date().getTime() |
-| content             | Content, support HTML                                                          | String           | -                    |
-| teleport            | Specifies a target element where Dialog will be mounted                        | String           | "body"               |
-| closeOnClickOverlay | Whether to close when overlay is clicked                                       | Boolean          | false                |
-| noFooter            | Hide bottom button bar                                                         | Boolean          | false                |
-| noOkBtn             | Hide OK button                                                                 | Boolean          | false                |
-| noCancelBtn         | Hide cancel button                                                             | Boolean          | false                |
-| cancelText          | Cancel button text                                                             | String           | "Cancel"             |
-| okText              | OK button text                                                                 | String           | "Confirm"            |
-| cancelAutoClose     | Click Cancel to close the popup                                                | Boolean          | true                 |
-| textAlign           | Text alignment direction, the optional value is the same as css text-align     | String           | "center"             |
-| closeOnPopstate     | Whether to close when popstate                                                 | Boolean          | false                |
-| onUpdate            | Update                                                                         | Boolean          | false                |
-| onOk                | Emitted when the confirm button is clicked                                     | Function         | -                    |
-| onCancel            | Emitted when the cancel button is clicked                                      | Function         | -                    |
-| onClosed            | Emitted when Dialog is closed                                                  | Function         | -                    |
-
-
-## Props
-
-| Attribute              | Description                                                                                               | Type    | Default    |
-|------------------------|-----------------------------------------------------------------------------------------------------------|---------|------------|
-| title                  | Title                                                                                                     | String  | -          |
-| content                | Content, support HTML                                                                                     | String  | -          |
-| teleport               | Specifies a target element where Dialog will be mounted                                                   | String  | "body"     |
-| close-on-click-overlay | Whether to close when overlay is clicked                                                                  | Boolean | false      |
-| no-footer              | Hide bottom button bar                                                                                    | Boolean | false      |
-| no-ok-btn              | Hide OK button                                                                                            | Boolean | false      |
-| no-cancel-btn          | Hide cancel button                                                                                        | Boolean | false      |
-| cancel-text            | Cancel button text                                                                                        | String  | "Cancel"   |
-| ok-text                | OK button text                                                                                            | String  | "Confirm"  |
-| cancel-auto-close      | Click Cancel to close the popup                                                                           | Boolean | true       |
-| text-align             | Text alignment direction, the optional value is the same as css text-align                                | String  | "center"   |
-| close-on-popstate      | Whether to close when popstate                                                                            | Boolean | false      |
-| lock-scroll            | Whether to lock background scroll                                                                         | Boolean | false      |
-| footer-direction       | The bottom button uses the horizontal and vertical directions. Optional values ​​are horizontal and vertical. | string  | horizontal |
-
-## Events
-
-| Event  | Description                                | Type     | Default |
-|--------|--------------------------------------------|----------|---------|
-| ok     | Emitted when the confirm button is clicked | Function | -       |
-| cancel | Emitted when the cancel button is clicked  | Function | -       |
-| closed | Emitted when Dialog is closed              | Function | -       |
-
-
-## Slots
-
-| Name    | Description    |
-|---------|----------------|
-| header  | Custom title   |
-| default | Custom default |
-| footer  | Custom footer  |
+    
+### Props
+    
+| Attribute         | Description                             | Type   | Default           |
+|-----------------|---------------------------------------------------|---------|----------|
+| v-model         | Default Date                                            | Date    | `null`   |
+| v-model:visible | Is Show                    | Boolean | `false`  |
+| type            | Can be set to date time year-month month-day datehour | String  | `'date'` |
+| minute-step     | Option minute step                                        | Number  | `1`      |
+| is-show-chinese | Show Chinese                                  | Boolean | `false`  |
+| min-date        | Start date                                         | Date    | `Ten years ago on January 1` |
+| max-date        | End date                                          | Date    | `Ten years later on December 31` |
+| formatter `v3.1.18`  | Option text formatter                                          | (type: string, option: PickerOption) => PickerOption    |  |
+| filter  `v3.1.18`  | Option filter                                         | (type: string, option: PickerOption) => PickerOption[]    |  |
+| title           | Title                                          | String  | `null`   |
+| 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   |
+
+### Events
+
+| Event | Description           | Arguments     |
+|---------|--------------------|--------------|
+| confirm | Emitted when click confirm button. | 	{ selectedValue, selectedOptions } |
+| close   | Emitted when click close button.       | 	{ selectedValue, selectedOptions } |
+| change   |  Emitted when current option changed.       | { columnIndex, selectedValue, selectedOptions } |
+
+### Slots
+
+| Event | Description           |
+|--------|----------------|
+| default  | Custom content bottom columns |
+| top  | Custom content top columns |

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

@@ -9,14 +9,15 @@
 ```javascript
 import { createApp } from 'vue';
 // vue
-import { DatePicker, Picker, Popup } from '@nutui/nutui';
+import { DatePicker, Picker, Popup, OverLay } from '@nutui/nutui';
 // taro
-import { DatePicker, Picker, Popup } from '@nutui/nutui-taro';
+import { DatePicker, Picker, Popup, OverLay } from '@nutui/nutui-taro';
 
 const app = createApp();
 app.use(DatePicker);
 app.use(Picker);
 app.use(Popup);
+app.use(OverLay);
 ```
     
 ## 代码演示
@@ -227,7 +228,7 @@ DatetimePicker 通过 type 属性来定义需要选择的时间类型。将 type
             option.text += '月';
             break;
           case 'day':
-            option.text += '';
+            option.text += '';
             break;
           case 'hour':
             option.text += '时';
@@ -386,6 +387,7 @@ DatetimePicker 通过 type 属性来定义需要选择的时间类型。将 type
 | title           | 设置标题                                          | String  | `null`   |
 | ok-text           | 确定按钮文案                                          | String  | 确定   |
 | cancel-text           | 取消按钮文案                                          | String  | 取消   |
+| three-dimensional`小程序不支持` `v3.1.23`          | 是否开启3D效果               | Boolean  | true   |
 
 ### Events
     

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

@@ -10,6 +10,7 @@
     :title="title"
     @confirm="confirm"
     :isWrapTeleport="isWrapTeleport"
+    :threeDimensional="threeDimensional"
   >
     <slot></slot>
   </nut-picker>
@@ -84,6 +85,11 @@ export default create({
       type: Function as PropType<import('./type').Formatter>,
       default: null
     },
+    // 是否开启3D效果
+    threeDimensional: {
+      type: Boolean,
+      default: true
+    },
     filter: Function as PropType<import('./type').Filter>
   },
   emits: ['click', 'update:visible', 'change', 'confirm', 'update:moduleValue'],

+ 37 - 18
src/packages/__VUE/picker/Column.vue

@@ -1,21 +1,31 @@
 <template>
   <view class="nut-picker__list" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd">
-    <view class="nut-picker-roller" ref="roller" :style="touchRollerStyle" @transitionend="stopMomentum">
+    <view
+      class="nut-picker-roller"
+      ref="roller"
+      :style="threeDimensional ? touchRollerStyle : touchTileStyle"
+      @transitionend="stopMomentum"
+    >
       <template v-for="(item, index) in column" :key="item.value ? item.value : index">
+        <!-- 3D 效果 -->
         <view
           class="nut-picker-roller-item"
           :class="{ 'nut-picker-roller-item-hidden': isHidden(index + 1) }"
           :style="setRollerStyle(index + 1)"
-          v-if="item && item.text"
+          v-if="item && item.text && threeDimensional"
         >
           {{ item.text }}
         </view>
+        <!-- 平铺 -->
+        <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"
-      ><view class="nut-picker-list-panel" ref="list" :style="touchListStyle"></view
+    <!-- 3D 效果 时使用 -->
+    <view class="nut-picker-content" v-if="threeDimensional"
+      ><view class="nut-picker-list-panel" ref="list" :style="touchTileStyle"></view
     ></view>
   </view>
 </template>
@@ -42,6 +52,11 @@ export default create({
     readonly: {
       type: Boolean,
       default: false
+    },
+    // 是否开启3D效果
+    threeDimensional: {
+      type: Boolean,
+      default: true
     }
   },
 
@@ -70,7 +85,6 @@ export default create({
 
     const roller = ref(null);
     const list = ref(null);
-    const listItem = ref(null);
 
     const moving = ref(false); // 是否处于滚动中
     const touchDeg = ref(0);
@@ -89,7 +103,7 @@ export default create({
       };
     });
 
-    const touchListStyle = computed(() => {
+    const touchTileStyle = computed(() => {
       return {
         transition: `transform ${touchTime.value}ms cubic-bezier(0.17, 0.89, 0.45, 1)`,
         transform: `translate3d(0, ${state.scrollDistance}px, 0)`
@@ -104,7 +118,11 @@ export default create({
       touch.start(event);
 
       if (moving.value) {
-        const { transform } = window.getComputedStyle(list.value as any);
+        let dom = list.value as any;
+        if (!props.threeDimensional) {
+          dom = roller.value as any;
+        }
+        const { transform } = window.getComputedStyle(dom);
         state.scrollDistance = +transform.slice(7, transform.length - 1).split(', ')[5];
       }
 
@@ -127,10 +145,10 @@ export default create({
 
       setMove(move);
 
-      if (now - (state.touchParams as TouchParams).startTime > INERTIA_TIME) {
-        (state.touchParams as TouchParams).startTime = now;
-        state.touchParams.startY = (state.touchParams as TouchParams).lastY;
-      }
+      // if (now - (state.touchParams as TouchParams).startTime > INERTIA_TIME) {
+      //   (state.touchParams as TouchParams).startTime = now;
+      //   state.touchParams.startY = (state.touchParams as TouchParams).lastY;
+      // }
     };
 
     const onTouchEnd = (event: TouchEvent) => {
@@ -207,17 +225,19 @@ export default create({
 
         state.currIndex = Math.abs(Math.round(endMove / state.lineSpacing)) + 1;
       } else {
-        let deg = '0deg';
+        let deg = 0;
         let currentDeg = (-updateMove / state.lineSpacing + 1) * state.rotation;
 
         // picker 滚动的最大角度
         const maxDeg = (props.column.length + 1) * state.rotation;
         const minDeg = 0;
 
-        deg = Math.min(Math.max(currentDeg, minDeg), maxDeg) + 'deg';
+        deg = Math.min(Math.max(currentDeg, minDeg), maxDeg);
 
-        setTransform(updateMove, null, undefined, deg);
-        state.currIndex = Math.abs(Math.round(updateMove / state.lineSpacing)) + 1;
+        if (minDeg < deg && deg < maxDeg) {
+          setTransform(updateMove, null, undefined, deg + 'deg');
+          state.currIndex = Math.abs(Math.round(updateMove / state.lineSpacing)) + 1;
+        }
       }
     };
 
@@ -288,12 +308,11 @@ export default create({
       isHidden,
       roller,
       list,
-      listItem,
       onTouchStart,
       onTouchMove,
       onTouchEnd,
       touchRollerStyle,
-      touchListStyle,
+      touchTileStyle,
       setMove,
       stopMomentum
     };

+ 19 - 11
src/packages/__VUE/picker/ColumnTaro.vue

@@ -1,6 +1,7 @@
 <template>
   <view class="nut-picker__list" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd">
-    <view class="nut-picker-roller" ref="roller" :style="touchRollerStyle" @transitionend="stopMomentum">
+    <view class="nut-picker-roller" ref="roller" :style="touchTileStyle" @transitionend="stopMomentum">
+      <!-- 3D 效果 -->
       <view
         class="nut-picker-roller-item"
         :class="{ 'nut-picker-roller-item-hidden': isHidden(index + 1) }"
@@ -42,6 +43,11 @@ export default create({
     readonly: {
       type: Boolean,
       default: false
+    },
+    // 是否开启3D效果
+    threeDimensional: {
+      type: Boolean,
+      default: true
     }
   },
 
@@ -89,7 +95,7 @@ export default create({
       };
     });
 
-    const touchRollerStyle = computed(() => {
+    const touchTileStyle = computed(() => {
       return {
         transition: `transform ${touchTime.value}ms cubic-bezier(0.17, 0.89, 0.45, 1)`,
         transform: `rotate3d(1, 0, 0, ${touchDeg.value})`
@@ -126,10 +132,10 @@ export default create({
 
       setMove(move);
 
-      if (now - (state.touchParams as TouchParams).startTime > INERTIA_TIME) {
-        (state.touchParams as TouchParams).startTime = now;
-        state.touchParams.startY = (state.touchParams as TouchParams).lastY;
-      }
+      // if (now - (state.touchParams as TouchParams).startTime > INERTIA_TIME) {
+      //   (state.touchParams as TouchParams).startTime = now;
+      //   state.touchParams.startY = (state.touchParams as TouchParams).lastY;
+      // }
     };
 
     const onTouchEnd = (event: TouchEvent) => {
@@ -205,17 +211,19 @@ export default create({
 
         state.currIndex = Math.abs(Math.round(endMove / state.lineSpacing)) + 1;
       } else {
-        let deg = '0deg';
+        let deg = 0;
         let currentDeg = (-updateMove / state.lineSpacing + 1) * state.rotation;
 
         // picker 滚动的最大角度
         const maxDeg = (props.column.length + 1) * state.rotation;
         const minDeg = 0;
 
-        deg = Math.min(Math.max(currentDeg, minDeg), maxDeg) + 'deg';
+        deg = Math.min(Math.max(currentDeg, minDeg), maxDeg);
 
-        setTransform(updateMove, null, undefined, deg);
-        state.currIndex = Math.abs(Math.round(updateMove / state.lineSpacing)) + 1;
+        if (minDeg < deg && deg < maxDeg) {
+          setTransform(updateMove, null, undefined, deg + 'deg');
+          state.currIndex = Math.abs(Math.round(updateMove / state.lineSpacing)) + 1;
+        }
       }
     };
 
@@ -303,7 +311,7 @@ export default create({
       onTouchStart,
       onTouchMove,
       onTouchEnd,
-      touchRollerStyle,
+      touchTileStyle,
       touchListStyle,
       setMove,
       refRandomId,

+ 7 - 1
src/packages/__VUE/picker/demo.vue

@@ -126,6 +126,7 @@ export default createDemo({
     const selectedValue = ref(['ZheJiang']);
     const selectedTime = ref(['Wednesday', 'Afternoon']);
     const asyncValue = ref<string[]>([]);
+    const columsNum = ref([]);
     const columns = computed(() => [
       { text: translate('nanJing'), value: 'NanJing' },
       { text: translate('wuXi'), value: 'WuXi' },
@@ -253,6 +254,10 @@ export default createDemo({
     };
 
     onMounted(() => {
+      for (let i = 1; i < 60; i++) {
+        columsNum.value.push({ text: i, value: i });
+      }
+
       setTimeout(() => {
         asyncColumns.value = [
           { text: translate('nanJing'), value: 'NanJing' },
@@ -299,7 +304,8 @@ export default createDemo({
       showEffect,
       alwaysFun,
       translate,
-      selectedTime
+      selectedTime,
+      columsNum
     };
   }
 });

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

@@ -1,6 +1,6 @@
 # Picker
 
-### 介绍
+### Intro
 
 The picker component is usually used with Popup Component.
 
@@ -381,6 +381,7 @@ Slots are arranged at the bottom and top respectively for custom Settings
 | title                  | Toolbar title                   | String  | -      |
 | cancel-text            | Text of cancel button               | String  | cancel   |
 | ok-text                | Text of confirm button               | String  | confirm   |
+| three-dimensional `v3.1.23`          | Turn on 3D effects      | Boolean  | true   |
 
 ### Data Structure of Columns
 

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

@@ -385,6 +385,7 @@ Picker 组件在底部和顶部分别设置了插槽,可进行自定义设置
 | title                  | 设置标题                   | String  | -      |
 | cancel-text            | 取消按钮文案               | String  | 取消   |
 | ok-text                | 确定按钮文案               | String  | 确定   |
+| three-dimensional`小程序不支持` `v3.1.23`          | 是否开启3D效果               | Boolean  | true   |
 
 ### Columns 数据结构
 

+ 9 - 0
src/packages/__VUE/picker/index.scss

@@ -97,6 +97,15 @@
         opacity: 0;
       }
     }
+
+    &-item-tile {
+      display: block;
+      width: 100%;
+      height: $picker-item-height;
+      line-height: $picker-item-height;
+      color: $picker-item-text-color;
+      font-size: $picker-item-text-font-size;
+    }
   }
 
   &-roller-mask {

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

@@ -28,6 +28,7 @@
             :readonly="readonly"
             :columnsType="columnsType"
             :value="defaultValues[columnIndex]"
+            :threeDimensional="threeDimensional"
             @change="
               (option) => {
                 changeHandler(columnIndex, option);
@@ -77,6 +78,11 @@ export default create({
     readonly: {
       type: Boolean,
       default: false
+    },
+    // 是否开启3D效果
+    threeDimensional: {
+      type: Boolean,
+      default: false
     }
   },
   emits: ['close', 'change', 'confirm', 'update:visible', 'update:modelValue'],

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

@@ -31,6 +31,7 @@
             :readonly="readonly"
             :columnsType="columnsType"
             :value="defaultValues[columnIndex]"
+            :threeDimensional="threeDimensional"
             @change="
               (option) => {
                 changeHandler(columnIndex, option);
@@ -82,6 +83,11 @@ export default create({
     readonly: {
       type: Boolean,
       default: false
+    },
+    // 是否开启3D效果
+    threeDimensional: {
+      type: Boolean,
+      default: true
     }
   },
   emits: ['close', 'change', 'confirm', 'update:visible', 'update:modelValue'],

+ 1 - 1
src/sites/mobile-taro/vue/project.private.config.json

@@ -54,5 +54,5 @@
       ]
     }
   },
-  "projectname": "%40nutui%2Fnutui-taro-mobile"
+  "projectname": "NutUI-Taro"
 }

+ 3 - 1
src/sites/mobile-taro/vue/src/app.config.ts

@@ -86,7 +86,8 @@ const subPackages = [
       'pages/collapse/index',
       'pages/table/index',
       'pages/animate/index',
-      'pages/ellipsis/index'
+      'pages/ellipsis/index',
+      'pages/watermark/index'
     ]
   },
   {
@@ -105,6 +106,7 @@ const subPackages = [
     ]
   }
 ];
+
 export default {
   pages: ['pages/index/index'],
   subPackages,

+ 54 - 107
src/sites/mobile-taro/vue/src/dentry/pages/cascader/index.vue

@@ -2,121 +2,68 @@
   <div class="demo">
     <h2>基础用法</h2>
 
-    <nut-form>
-      <nut-form-item label="选择地址">
-        <input
-          class="nut-input-text"
-          @click="demo1.visible = true"
-          :value="demo1.value"
-          readonly
-          placeholder="请选择地址"
-          type="text"
-        />
-        <nut-cascader
-          title="地址选择"
-          v-model:visible="demo1.visible"
-          v-model="demo1.value"
-          @change="events.change"
-          @pathChange="events.pathChange"
-          :options="demo1.options"
-        ></nut-cascader>
-      </nut-form-item>
-    </nut-form>
+    <nut-cell title="选择地址" :desc="demo1.value.toString() || '请选择地址'" @click="demo1.visible = true"> </nut-cell>
+    <nut-cascader
+      title="地址选择"
+      v-model:visible="demo1.visible"
+      v-model="demo1.value"
+      @change="events.change"
+      @pathChange="events.pathChange"
+      :options="demo1.options"
+    ></nut-cascader>
 
     <h2>自定义属性名称</h2>
-    <nut-form>
-      <nut-form-item label="选择地址">
-        <input
-          class="nut-input-text"
-          @click="demo2.visible = true"
-          :value="demo2.value"
-          readonly
-          placeholder="请选择地址"
-          type="text"
-        />
-        <nut-cascader
-          title="地址选择"
-          v-model:visible="demo2.visible"
-          v-model="demo2.value"
-          labelKey="text"
-          @change="events.change"
-          @pathChange="events.pathChange"
-          valueKey="text"
-          childrenKey="items"
-          :options="demo2.options"
-        ></nut-cascader>
-      </nut-form-item>
-    </nut-form>
+
+    <nut-cell title="选择地址" :desc="demo2.value.toString() || '请选择地址'" @click="demo2.visible = true"> </nut-cell>
+    <nut-cascader
+      title="地址选择"
+      v-model:visible="demo2.visible"
+      v-model="demo2.value"
+      labelKey="text"
+      @change="events.change"
+      @pathChange="events.pathChange"
+      valueKey="text"
+      childrenKey="items"
+      :options="demo2.options"
+    ></nut-cascader>
 
     <h2>动态加载</h2>
-    <nut-form>
-      <nut-form-item label="选择地址">
-        <input
-          class="nut-input-text"
-          @click="demo3.visible = true"
-          :value="demo3.value"
-          readonly
-          placeholder="请选择地址"
-          type="text"
-        />
-        <nut-cascader
-          title="地址选择"
-          v-model:visible="demo3.visible"
-          v-model="demo3.value"
-          @change="events.change"
-          @pathChange="events.pathChange"
-          lazy
-          :lazyLoad="demo3.lazyLoad"
-        ></nut-cascader>
-      </nut-form-item>
-    </nut-form>
+    <nut-cell title="选择地址" :desc="demo3.value.toString() || '请选择地址'" @click="demo3.visible = true"> </nut-cell>
+    <nut-cascader
+      title="地址选择"
+      v-model:visible="demo3.visible"
+      v-model="demo3.value"
+      @change="events.change"
+      @pathChange="events.pathChange"
+      lazy
+      :lazyLoad="demo3.lazyLoad"
+    ></nut-cascader>
 
     <h2>部分数据动态加载</h2>
-    <nut-form>
-      <nut-form-item label="选择地址">
-        <input
-          class="nut-input-text"
-          @click="demo4.visible = true"
-          :value="demo4.value"
-          readonly
-          placeholder="请选择地址"
-          type="text"
-        />
-        <nut-cascader
-          title="地址选择"
-          v-model:visible="demo4.visible"
-          v-model="demo4.value"
-          @change="events.change"
-          @pathChange="events.pathChange"
-          :options="demo4.options"
-          lazy
-          :lazyLoad="demo4.lazyLoad"
-        ></nut-cascader>
-      </nut-form-item>
-    </nut-form>
+
+    <nut-cell title="选择地址" :desc="demo4.value.toString() || '请选择地址'" @click="demo4.visible = true"> </nut-cell>
+    <nut-cascader
+      title="地址选择"
+      v-model:visible="demo4.visible"
+      v-model="demo4.value"
+      @change="events.change"
+      @pathChange="events.pathChange"
+      :options="demo4.options"
+      lazy
+      :lazyLoad="demo4.lazyLoad"
+    ></nut-cascader>
 
     <h2>自动转换</h2>
-    <nut-form>
-      <nut-form-item label="选择地址">
-        <input
-          class="nut-input-text"
-          @click="demo5.visible = true"
-          :value="demo5.value"
-          readonly
-          placeholder="请选择地址"
-          type="text"
-        />
-        <nut-cascader
-          title="地址选择"
-          v-model:visible="demo5.visible"
-          v-model="demo5.value"
-          @change="events.change"
-          @pathChange="events.pathChange"
-          :options="demo5.options"
-          :convertConfig="demo5.convertConfig"
-        ></nut-cascader>
-      </nut-form-item>
-    </nut-form>
+    <nut-cell title="选择地址" :desc="demo5.value.toString() || '请选择地址'" @click="demo5.visible = true"> </nut-cell>
+    <nut-cascader
+      title="地址选择"
+      v-model:visible="demo5.visible"
+      v-model="demo5.value"
+      @change="events.change"
+      @pathChange="events.pathChange"
+      :options="demo5.options"
+      :convertConfig="demo5.convertConfig"
+    ></nut-cascader>
   </div>
 </template>
 

+ 6 - 2
src/sites/mobile-taro/vue/src/dentry/pages/input/index.vue

@@ -11,8 +11,12 @@
     <nut-input label="手机号" v-model="state.tel" type="tel" />
 
     <h2>禁用和只读</h2>
-    <nut-input v-model="state.readonly" readonly label="文本" placeholder="输入框只读" />
-    <nut-input v-model="state.disabled" disabled label="文本" placeholder="输入框已禁用" />
+    <nut-form>
+      <nut-form-item>
+        <nut-input v-model="state.readonly" readonly label="文本" placeholder="输入框只读" />
+        <!-- <nut-input v-model="state.disabled" disabled label="文本" placeholder="输入框已禁用" /> -->
+      </nut-form-item>
+    </nut-form>
 
     <h2>显示图标</h2>
     <nut-input v-model="state.showIcon" label="文本" left-icon="dongdong" right-icon="ask2" placeholder="显示图标" />

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

@@ -10,9 +10,10 @@
         }
       "
     ></nut-cell>
+
     <nut-picker
       v-model:visible="show"
-      :columns="columsNum"
+      :columns="columns"
       title="城市选择"
       @change="change"
       @confirm="(options) => confirm('index', options)"