浏览代码

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

Drjnigfubo 3 年之前
父节点
当前提交
27a9f9bec0

+ 7 - 4
src/packages/__VUE/audio/demo.vue

@@ -17,6 +17,7 @@
       :muted="muted"
       :autoplay="autoplay"
       :loop="false"
+      @can-play="onCanplay"
       type="none"
       ref="audioDemo"
     >
@@ -124,11 +125,12 @@ export default createDemo({
       console.log('改变进度条', val);
     };
 
+    const onCanplay = (e: Event) => {
+      duration.value = audioDemo.value.second.toFixed();
+    };
+
     onMounted(() => {
       console.log(audioDemo.value);
-      setTimeout(() => {
-        duration.value = audioDemo.value.second.toFixed();
-      }, 500);
     });
 
     return {
@@ -141,7 +143,8 @@ export default createDemo({
       ended,
       duration,
       changeProgress,
-      translate
+      translate,
+      onCanplay
     };
   }
 });

+ 1 - 0
src/packages/__VUE/audio/doc.en-US.md

@@ -234,3 +234,4 @@ export default {
 | ended  | Emitted when audio ended | —— |
 | mute  | Emitted when audio mute | —— |
 | changeProgress  | Emitted when audio progress change | play time(millisecond) |
+| can-play `v3.2.0` | Emitted when the user agent can play the media | `event: Event` |

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

@@ -234,5 +234,6 @@ export default {
 | ended  | 语音播放完成,当loop设置为false时生效 | —— |
 | mute  | 触发静音 | —— |
 | changeProgress  | 当进度条改变时触发 | 返回当前播放时长(单位:毫秒) |
+| can-play `v3.2.0` | 当可以播放媒体文件时触发 | `event: Event` |
 
     

+ 22 - 15
src/packages/__VUE/audio/index.vue

@@ -52,6 +52,7 @@
       :autoplay="autoplay"
       :loop="loop"
       @timeupdate="onTimeupdate"
+      @canplay="onCanplay"
       @ended="audioEnd"
       :muted="hanMuted"
     >
@@ -104,7 +105,7 @@ export default create({
     }
   },
   components: {},
-  emits: ['fastBack', 'play', 'forward', 'ended', 'changeProgress', 'mute'],
+  emits: ['fastBack', 'play', 'forward', 'ended', 'changeProgress', 'mute', 'can-play'],
 
   setup(props, { emit }) {
     const audioRef = ref(null);
@@ -144,20 +145,23 @@ export default create({
       } catch (e) {
         console.log((e as any).message);
       }
+    });
 
-      // 获取当前音频播放时长
-      setTimeout(() => {
-        const audioR = audioRef.value as any;
-        // 自动播放
-        if (props.autoplay) {
-          if (audioR && audioR.paused) {
-            audioR.play();
-          }
+    // audio canplay 事件触发时
+    const onCanplay = (e: Event) => {
+      const audioR = audioRef.value as any;
+      // 自动播放
+      if (props.autoplay) {
+        if (audioR && audioR.paused) {
+          audioR.play();
         }
-        audioData.second = audioR.duration;
-        audioData.duration = formatSeconds(audioR.duration);
-      }, 500);
-    });
+      }
+      // 获取当前音频播放时长
+      audioData.second = audioR.duration;
+      audioData.duration = formatSeconds(audioR.duration);
+
+      emit('can-play', e);
+    };
 
     //播放时间
     const onTimeupdate = (e: any) => {
@@ -166,7 +170,9 @@ export default create({
 
     //后退
     const fastBack = () => {
-      audioData.currentTime--;
+      if (audioData.currentTime > 0) {
+        audioData.currentTime--;
+      }
       (audioRef.value as any).currentTime = audioData.currentTime;
 
       emit('fastBack', audioData.currentTime);
@@ -265,7 +271,8 @@ export default create({
       progressChange,
       audioEnd,
       onTimeupdate,
-      handleMute
+      handleMute,
+      onCanplay
     };
   }
 });

+ 20 - 0
src/packages/__VUE/card/test/__snapshots__/index.spec.ts.snap

@@ -36,6 +36,26 @@ exports[`normal props 1`] = `
 </div>"
 `;
 
+exports[`render prolist , price and origin slot correctly 1`] = `
+"<div class=\\"nut-card\\">
+  <div class=\\"nut-card__left\\"><img src=\\"\\" alt=\\"\\"></div>
+  <div class=\\"nut-card__right\\">
+    <div class=\\"nut-card__right__title\\"></div>Custom prolist<div class=\\"nut-card__right__price\\">Custom priceCustom origin</div>
+    <div class=\\"nut-card__right__other\\">
+      <view class=\\"nut-tag nut-tag--danger\\">
+        <!--v-if-->
+      </view>
+      <view class=\\"nut-tag nut-tag--default nut-tag--plain\\" style=\\"color: rgb(250, 36, 0); background: rgb(255, 255, 255); border: 1px solid rgba(250,36,0,1);\\">
+        <!--v-if-->
+      </view>
+    </div>
+    <div class=\\"nut-card__right__shop\\">
+      <div class=\\"nut-card__right__shop__name\\"></div>
+    </div>
+  </div>
+</div>"
+`;
+
 exports[`render prolist and origin slot correctly 1`] = `
 "<div class=\\"nut-card\\">
   <div class=\\"nut-card__left\\"><img src=\\"\\" alt=\\"\\"></div>

+ 8 - 10
src/packages/__VUE/navbar/index.taro.vue

@@ -1,6 +1,6 @@
 <template>
   <view v-if="fixed && placeholder" class="nut-navbar--placeholder" :style="{ height: navHeight + 'px' }">
-    <view :class="classes" :style="styles" ref="navBarHtml">
+    <view :class="classes" :style="styles" class="navBarHtml">
       <view class="nut-navbar__left" @click="handleLeft">
         <nut-icon v-if="leftShow" color="#979797" name="left"></nut-icon>
         <view v-if="leftText" class="nut-navbar__text">{{ leftText }}</view>
@@ -91,16 +91,14 @@ export default create({
 
     onMounted(() => {
       if (fixed.value && placeholder.value) {
-        setTimeout(async () => {
+        setTimeout(() => {
           const query = Taro.createSelectorQuery();
-          query
-            .select('.navBarHtml')
-            .boundingClientRect((rec: any) => {
-              navHeight.value = rec.height;
-              console.log('navBarHtml', navHeight);
-            })
-            .exec();
-        }, 100);
+          query.select('.navBarHtml').boundingClientRect();
+          query.exec((res) => {
+            navHeight.value = res[0].height;
+            // console.log('navHeight', navHeight.value)
+          });
+        }, 500);
       }
     });
 

+ 1 - 1
src/packages/__VUE/signature/__tests__/signature.spec.ts

@@ -53,5 +53,5 @@ test('props custom-class', async () => {
   const _img = document.createElement('img');
   _img.src = canvas.toDataURL();
   expect(canvas.toDataURL()).not.toBeNull();
-  expect(wrapper.html()).toMatchSnapshot();
+  // expect(wrapper.html()).toMatchSnapshot();
 });

+ 9 - 3
src/packages/__VUE/signature/demo.vue

@@ -2,12 +2,12 @@
   <div class="demo">
     <h2>{{ translate('basic') }}</h2>
     <div>
-      <nut-signature @confirm="confirm" @clear="clear" custom-class="test"></nut-signature>
+      <nut-signature @confirm="confirm" @clear="clear" custom-class="test" @start="start"></nut-signature>
       <p class="demo-tips demo1">{{ translate('tips') }}</p>
     </div>
     <h2>{{ translate('title') }}</h2>
     <div>
-      <nut-signature :lineWidth="lineWidth" :strokeStyle="strokeStyle"></nut-signature>
+      <nut-signature :lineWidth="lineWidth" :strokeStyle="strokeStyle" @end="end"></nut-signature>
     </div>
   </div>
 </template>
@@ -47,7 +47,13 @@ export default createDemo({
     const clear = () => {
       console.log('清除');
     };
-    return { ...state, confirm, clear, translate };
+    const start = () => {
+      console.log('签名开始');
+    };
+    const end = () => {
+      console.log('签名结束');
+    };
+    return { ...state, confirm, clear, translate, start, end };
   }
 });
 </script>

+ 3 - 0
src/packages/__VUE/signature/doc.en-US.md

@@ -130,5 +130,8 @@ export default {
 
 | Event | Description   | Arguments   |
 |----- | ----- | ----- 
+|start `v3.2.0` | signature start callback function (refers to the beginning of a stroke) | none
+|signing `v3.2.0`| the callback function being signed (refers to a stroke in progress) | event
+|end `v3.2.0`| signature end callback function (refers to the end of a stroke) | none
 | confirm | Click the confirm button to trigger the event callback function | Canvas and data URI displayed by signature image
 | clear | Click the re sign button to trigger the event callback function | -

+ 4 - 1
src/packages/__VUE/signature/doc.md

@@ -109,5 +109,8 @@ export default {
 
 | 字段 | 说明 | 回调参数 
 |----- | ----- | ----- 
+| start `v3.2.0` | 签名开始回调函数(指某次笔画的开始) | 无
+| signing `v3.2.0` | 正在签名的回调函数(指某次笔画进行中) | event
+| end `v3.2.0` | 签名结束回调函数(指某次笔画的结束)| 无
 | confirm | 点击确认按钮触发事件回调函数 | canvas和签名图片展示的 data URI
-| clear | 点击重签按钮触发事件回调函数 | 无
+| clear | 点击重签按钮触发事件回调函数 | 无

+ 3 - 0
src/packages/__VUE/signature/doc.taro.md

@@ -75,5 +75,8 @@ setup() {
 
 | 字段 | 说明 | 回调参数 
 |----- | ----- | ----- 
+| start `v3.2.0`| 签名开始回调函数(指某次笔画的开始) | 无
+| signing `v3.2.0`| 正在签名的回调函数(指某次笔画进行中) | event
+| end `v3.2.0`| 签名结束回调函数(指某次笔画的结束)| 无
 | confirm | 点击确认按钮触发事件回调函数 | data URI
 | clear | 点击重签按钮触发事件回调函数 | 无

+ 4 - 1
src/packages/__VUE/signature/index.taro.vue

@@ -48,7 +48,7 @@ export default create({
     }
   },
   components: {},
-  emits: ['confirm', 'clear'],
+  emits: ['start', 'end', 'signing', 'confirm', 'clear'],
 
   setup(props, { emit }) {
     const classes = computed(() => {
@@ -67,6 +67,7 @@ export default create({
 
     const startEventHandler = (event: MouseEvent) => {
       event.preventDefault();
+      emit('start');
       state.ctx.beginPath();
       state.ctx.lineWidth = props.lineWidth;
       state.ctx.strokeStyle = props.strokeStyle;
@@ -76,6 +77,7 @@ export default create({
       event.preventDefault();
 
       let evt = event.changedTouches[0];
+      emit('signing', evt);
       let mouseX = evt.x;
       let mouseY = evt.y;
       state.ctx.lineTo(mouseX, mouseY);
@@ -84,6 +86,7 @@ export default create({
 
     const endEventHandler = (event) => {
       event.preventDefault();
+      emit('end');
     };
     const leaveEventHandler = (event) => {
       event.preventDefault();

+ 4 - 3
src/packages/__VUE/signature/index.vue

@@ -46,7 +46,7 @@ export default create({
     }
   },
   components: {},
-  emits: ['confirm', 'clear'],
+  emits: ['start', 'end', 'signing', 'confirm', 'clear'],
 
   setup(props, { emit }) {
     const canvas: any = ref<HTMLElement | null>(null);
@@ -81,7 +81,7 @@ export default create({
       state.ctx.beginPath();
       state.ctx.lineWidth = props.lineWidth;
       state.ctx.strokeStyle = props.strokeStyle;
-
+      emit('start');
       canvas.value.addEventListener(state.events[1], moveEventHandler, false);
       canvas.value.addEventListener(state.events[2], endEventHandler, false);
       canvas.value.addEventListener(state.events[3], leaveEventHandler, false);
@@ -91,6 +91,7 @@ export default create({
       event.preventDefault();
 
       let evt = state.isSupportTouch ? event.touches[0] : event;
+      emit('signing', evt);
       let coverPos = canvas.value.getBoundingClientRect();
       let mouseX = evt.clientX - coverPos.left;
       let mouseY = evt.clientY - coverPos.top;
@@ -101,7 +102,7 @@ export default create({
 
     const endEventHandler = (event) => {
       event.preventDefault();
-
+      emit('end');
       canvas.value.removeEventListener(state.events[1], moveEventHandler, false);
       canvas.value.removeEventListener(state.events[2], endEventHandler, false);
     };

+ 14 - 2
src/packages/__VUE/uploader/demo.vue

@@ -34,6 +34,8 @@
     <nut-uploader :url="uploadUrl" multiple :before-upload="beforeUpload"> </nut-uploader>
     <h2>{{ translate('title9') }}</h2>
     <nut-uploader :url="uploadUrl" :data="formData" :headers="formData" :with-credentials="true"></nut-uploader>
+    <h2>{{ translate('title13') }}</h2>
+    <nut-uploader :url="uploadUrl" method="put" @before-xhr-upload="beforeXhrUpload"></nut-uploader>
     <h2>{{ translate('title10') }}</h2>
     <nut-uploader :url="uploadUrl" maximum="5" :auto-upload="false" ref="uploadRef"></nut-uploader>
     <br />
@@ -65,7 +67,8 @@ const initTranslate = () =>
       title9: '自定义数据 FormData 、 headers ',
       title10: '选中文件后,通过按钮手动执行上传',
       title11: '执行上传',
-      title12: '禁用状态'
+      title12: '禁用状态',
+      title13: '自定义 xhr 上传方式(before-xhr-upload)'
     },
     'en-US': {
       basic: 'Basic Usage',
@@ -81,7 +84,8 @@ const initTranslate = () =>
       title9: 'Custom data FormData , headers',
       title10: 'Once the file is selected, manually perform the upload via the button',
       title11: 'Perform upload',
-      title12: 'Disabled state'
+      title12: 'Disabled state',
+      title13: 'Customize XHR upload (before-xhr-upload)'
     }
   });
 export default createDemo({
@@ -159,6 +163,13 @@ export default createDemo({
       const f = await new File([blob], fileName);
       return [f];
     };
+    const beforeXhrUpload = (xhr: XMLHttpRequest, options: any) => {
+      if (options.method.toLowerCase() == 'put') {
+        xhr.send(options.sourceFile);
+      } else {
+        xhr.send(options.formData);
+      }
+    };
     const uploadRef = ref<any>(null);
     const submitUpload = () => {
       uploadRef.value.submit();
@@ -166,6 +177,7 @@ export default createDemo({
     return {
       onOversize,
       beforeUpload,
+      beforeXhrUpload,
       onDelete,
       onProgress,
       progressPercentage,

+ 32 - 0
src/packages/__VUE/uploader/doc.en-US.md

@@ -286,6 +286,37 @@ export default {
 </script>
 ```
 :::
+
+### Customize XHR upload(before-xhr-upload)
+
+:::demo
+```html
+<!-- When the upload method is put, upload the source file stream directly -->
+<template>
+  <nut-uploader url="https://xxxx" method="put" @before-xhr-upload="beforeXhrUpload"></nut-uploader>
+</template>
+
+<script lang="ts">
+import { ref } from 'vue';
+export default {
+  setup() {
+      // source file https://github.com/jdf2e/nutui/blob/next/src/packages/__VUE/uploader/uploader.ts#L51
+     const beforeXhrUpload=(xhr:XMLHttpRequest,options:any)=>{
+        if (options.method.toLowerCase() == 'put') {
+          xhr.send(options.sourceFile);
+        }else{
+          xhr.send(options.formData);
+        }
+     }
+     return {
+      beforeXhrUpload
+    };
+  }
+}
+</script>
+```
+:::
+
 ### Once the file is selected, manually perform the upload via the button
     
 :::demo
@@ -352,6 +383,7 @@ export default {
 | disabled          | Whether to disable file upload                                                                                                                   | Boolean                           | false            |
 | timeout           | timeout, in milliseconds                                                                                                                         | Number丨String                    | 1000 * 30        |
 | before-upload     | Hook before reading the file, return false to stop reading the file, can return Promise                                                          | Function                          | null             |
+| before-xhr-upload`v3.2.0` | Customize the method when uploading XHR                                                                                                                                                                          | Function(xhr,option)                          | null             |
 | before-delete     | Hook before delete the file, return false to stop reading the file, can return Promise                                                           | Function(file): boolean 丨Promise | -                |
 
 

+ 33 - 1
src/packages/__VUE/uploader/doc.md

@@ -286,6 +286,37 @@ export default {
 </script>
 ```
 :::
+
+### 自定义上传方式(before-xhr-upload h5支持)
+
+:::demo
+```html
+<!-- 当上传方式为put时,直接上传源文件file流 -->
+<template>
+  <nut-uploader url="https://xxxx" method="put" @before-xhr-upload="beforeXhrUpload"></nut-uploader>
+</template>
+
+<script lang="ts">
+import { ref } from 'vue';
+export default {
+  setup() {
+    // source file https://github.com/jdf2e/nutui/blob/next/src/packages/__VUE/uploader/uploader.ts#L51
+     const beforeXhrUpload=(xhr:XMLHttpRequest,options:any)=>{
+        if (options.method.toLowerCase() == 'put') {
+          xhr.send(options.sourceFile);
+        }else{
+          xhr.send(options.formData);
+        }
+     }
+     return {
+      beforeXhrUpload
+    };
+  }
+}
+</script>
+```
+:::
+
 ### 选中文件后,通过按钮手动执行上传
     
 :::demo
@@ -352,6 +383,7 @@ export default {
 | disabled          | 是否禁用文件上传                                                                                                                                                                       | Boolean                           | false            |
 | timeout           | 超时时间,单位为毫秒                                                                                                                                                                   | Number丨String                    | 1000 * 30        |
 | before-upload     | 上传前的函数需要返回一个`Promise`对象                                                                                                                                                  | Function                          | null             |
+| before-xhr-upload`v3.2.0 小程序暂不支持` | 执行 XHR 上传时,自定义方式                                                                                                                                                                          | Function(xhr,option)                          | null             |
 | before-delete     | 除文件时的回调,返回值为 false 时不移除。支持返回一个 `Promise` 对象,`Promise` 对象 resolve(false) 或 reject 时不移除                                                                 | Function(file): boolean 丨Promise | -                |
 
 
@@ -377,7 +409,7 @@ export default {
 | success         | 上传成功               | {responseText,option,fileItem} |
 | failure         | 上传失败               | {responseText,option,fileItem} |
 | change          | 上传文件改变时的状态   | {fileList,event}               |
-| delete          | 文件删除事件     | {files,fileList,index}               |
+| delete          | 文件删除事件           | {files,fileList,index}         |
 | file-item-click | 文件上传成功后点击触发 | {fileItem}                     |
 
 ### Methods

+ 5 - 0
src/packages/__VUE/uploader/index.vue

@@ -137,6 +137,10 @@ export default create({
       type: Function,
       default: null
     },
+    beforeXhrUpload: {
+      type: Function,
+      default: null
+    },
     beforeDelete: {
       type: Function,
       default: (file: import('./type').FileItem, files: import('./type').FileItem[]) => {
@@ -185,6 +189,7 @@ export default create({
       uploadOption.xhrState = props.xhrState as number;
       uploadOption.headers = props.headers;
       uploadOption.withCredentials = props.withCredentials;
+      uploadOption.beforeXhrUpload = props.beforeXhrUpload;
       try {
         uploadOption.sourceFile = fileItem.formData.get(props.name);
       } catch (error) {}

+ 3 - 2
src/packages/__VUE/uploader/uploader.ts

@@ -14,6 +14,7 @@ export class UploadOptions {
   onProgress?: Function;
   onSuccess?: Function;
   onFailure?: Function;
+  beforeXhrUpload?: Function;
 }
 export class Uploader {
   options: UploadOptions;
@@ -48,8 +49,8 @@ export class Uploader {
         xhr.setRequestHeader(key, value as string);
       }
       options.onStart?.(options);
-      if (options.method.toLowerCase() == 'put') {
-        xhr.send(options.sourceFile);
+      if (options.beforeXhrUpload) {
+        options.beforeXhrUpload(xhr, options);
       } else {
         xhr.send(options.formData);
       }

+ 15 - 15
src/packages/__VUE/watermark/__tests__/watermark.spec.ts

@@ -21,18 +21,18 @@ test('render fullPage props ', async () => {
   expect(wrapper.findAll('.nut-watermark').length).toBe(1);
   expect(wrapper.findAll('.nut-watermark-full-page').length).toBe(1);
 });
-test('should render watermark', () => {
-  const wrapper = mount({
-    components: {
-      'nut-cell': Cell,
-      'nut-watermark': Watermark
-    },
-    template: `
-      <nut-cell>
-        <nut-watermark :fullPage="false" font-color="#fa2c19" content="nut-ui"></nut-watermark>
-      </nut-cell>
-    `,
-    setup() {}
-  });
-  expect(wrapper.html()).toMatchSnapshot();
-});
+// test('should render watermark', () => {
+//   const wrapper = mount({
+//     components: {
+//       'nut-cell': Cell,
+//       'nut-watermark': Watermark
+//     },
+//     template: `
+//       <nut-cell>
+//         <nut-watermark :fullPage="false" font-color="#fa2c19" content="nut-ui"></nut-watermark>
+//       </nut-cell>
+//     `,
+//     setup() {}
+//   });
+//   expect(wrapper.html()).toMatchSnapshot();
+// });

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

@@ -7,8 +7,8 @@
     "miniprogram": {
       "list": [
         {
-          "name": "feedback/pages/notify/index",
-          "pathName": "feedback/pages/notify/index",
+          "name": "business/pages/signature/index",
+          "pathName": "business/pages/signature/index",
           "query": "",
           "launchMode": "default",
           "scene": null

+ 13 - 1
src/sites/mobile-taro/vue/src/business/pages/signature/index.vue

@@ -6,6 +6,9 @@
       :strokeStyle="strokeStyle"
       @confirm="confirm"
       @clear="clear"
+      @start="start"
+      @signing="signing"
+      @end="end"
     />
   </div>
 </template>
@@ -40,7 +43,16 @@ export default {
         }
       });
     };
-    return { ...state, confirm, clear };
+    const start = () => {
+      console.log('签名开始');
+    };
+    const signing = (e) => {
+      console.log('签名进行中', e);
+    };
+    const end = () => {
+      console.log('签名结束');
+    };
+    return { ...state, confirm, clear, start, signing, end };
   }
 };
 </script>