Browse Source

feat merge

shenqistart 5 years ago
parent
commit
d32cc292f5

+ 9 - 0
src/config.json

@@ -613,6 +613,15 @@
       "sort": "0",
       "showDemo": true,
       "author": "wangyue"
+    },
+    {
+      "name": "Drag",
+      "chnName": "拖拽",
+      "desc": "实现可拖拽的任意元素",
+      "type": "component",
+      "sort": "5",
+      "showDemo": true,
+      "author": "张宇"
     }
   ]
 }

+ 4 - 2
src/nutui.js

@@ -119,7 +119,8 @@ import "./packages/subsidenavbar/subsidenavbar.scss";
 import SideNavBarItem from "./packages/sidenavbaritem/index.js";
 import "./packages/sidenavbaritem/sidenavbaritem.scss";
 import Qart from "./packages/qart/index.js";
-import "./packages/qart/qart.scss";
+import Drag from "./packages/drag/index.js";
+import "./packages/drag/drag.scss";
 
 const packages = {
   Cell,
@@ -180,7 +181,8 @@ const packages = {
   SideNavBar: SideNavBar,
   SubSideNavBar: SubSideNavBar,
   SideNavBarItem: SideNavBarItem,
-  Qart: Qart
+  Qart: Qart,
+  Drag: Drag
 };
 
 const components = {};

+ 80 - 0
src/packages/drag/demo.vue

@@ -0,0 +1,80 @@
+<template>
+  <div class="demo-list">
+    <nut-noticebar :closeMode="true" v-if="!isMobile"
+      >此 Demo 仅能在移动端浏览器体验,建议在 Android 或 iOS 设备上体验。
+    </nut-noticebar>
+    <h4>基本用法</h4>
+    <nut-drag @click.native="click" :style="{ top: '100px', left: '8px' }">
+      <div class="touch-dom">可点击,可拖拽</div>
+    </nut-drag>
+    <h4 :style="{ top: '150px' }">限制拖拽方向</h4>
+    <nut-drag direction="x" :style="{ top: '200px', left: '8px' }">
+      <div class="touch-dom">只能在X轴拖动</div>
+    </nut-drag>
+    <h4 :style="{ top: '250px' }">自动吸边</h4>
+    <nut-drag
+      direction="x"
+      :attract="true"
+      :style="{ top: '300px', left: '8px' }"
+    >
+      <div class="touch-dom">拖动我</div>
+    </nut-drag>
+    <h4 :style="{ top: '350px' }">限制拖动边界</h4>
+    <div class="drag-boundary"></div>
+    <nut-drag
+      :boundary="{ top: 401, left: 9, bottom: bottom(), right: right() }"
+      :attract="true"
+      :style="{ top: '400px', left: '8px' }"
+    >
+      <div class="touch-dom">拖动我</div>
+    </nut-drag>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  data() {
+    return {};
+  },
+  methods: {
+    right() {
+      return document.documentElement.clientWidth - 300 - 9;
+    },
+    bottom() {
+      return document.documentElement.clientHeight - 601;
+    },
+    click() {
+      this.$toast.text("点击了拖拽元素");
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.nut-drag {
+  position: absolute;
+  cursor: pointer;
+  user-select: none;
+}
+.touch-dom {
+  height: 30px;
+  padding: 10px;
+  line-height: 30px;
+  text-align: center;
+  color: #fff;
+  background: red;
+  overflow: hidden;
+}
+h4 {
+  position: absolute;
+}
+.drag-boundary {
+  position: absolute;
+  top: 400px;
+  left: 8px;
+  width: 300px;
+  height: 200px;
+  border: 1px solid red;
+}
+</style>

+ 59 - 0
src/packages/drag/doc.md

@@ -0,0 +1,59 @@
+# Drag 拖拽
+实现可拖拽的任意元素
+
+## 基本用法
+```html
+<nut-drag @click.native="click">
+  <div class="touch-dom">可点击,可拖拽</div>
+</nut-drag>
+<script>
+export default {
+  methods: {
+    click() {
+      this.$toast.text("点击了拖拽元素");
+    },
+  },
+};
+</script>
+```
+## 限制拖拽方向
+```html
+<nut-drag direction="x">
+  <div class="touch-dom">只能在X轴拖动</div>
+</nut-drag>
+```
+## 自动吸边
+```html
+<nut-drag direction="x" :attract="true">
+  <div class="touch-dom">拖动我</div>
+</nut-drag>
+```
+## 限制拖拽边界
+```html
+<nut-drag
+  :boundary="{ top: 401, left: 9, bottom: bottom(), right: right() }"
+  :attract="true"
+>
+  <div class="touch-dom">拖动我</div>
+</nut-drag>
+<script>
+export default {
+  methods: {
+    right() {
+      return document.documentElement.clientWidth - 300 - 9;
+    },
+    bottom() {
+      return document.documentElement.clientHeight - 601;
+    },
+  },
+};
+</script>
+```
+## Prop
+
+| 字段      | 说明                                              | 类型           | 默认值                              |
+| :-------- | :------------------------------------------------ | :------------- | :---------------------------------- |
+| attract   | 是否开启自动吸边                                  | Boolean        | false                                |
+| direction | 拖拽元素的拖拽方向限制,**x**/**y**/**all**三选一 | String         | 'all'                               |
+| z-index   | 拖拽元素的堆叠顺序                                | Number, String | 11                                  |
+| boundary  | 拖拽元素的拖拽边界                                | Object         | {top: 0,left: 0,right: 0,bottom: 0} |

+ 9 - 0
src/packages/drag/drag.scss

@@ -0,0 +1,9 @@
+.nut-drag {
+  position: fixed;
+  display: inline-block;
+  top: 0;
+  right: 0;
+  z-index: 9997 !important;
+  width: fit-content;
+  height: fit-content;
+}

+ 206 - 0
src/packages/drag/drag.vue

@@ -0,0 +1,206 @@
+<template>
+  <div class="nut-drag" @touchstart="touchStart($event)">
+    <slot></slot>
+  </div>
+</template>
+<script>
+import requestAniFrame from "../../utils/raf.js";
+/**
+ * @module drag
+ * @description 拖拽组件,用于页面中需要拖拽的元素
+ * @vue-prop {Boolean} [attract=false] - 拖拽元素是否需要自动吸边
+ * @vue-prop {String} [direction='all'] - 拖拽元素的拖拽方向
+ * @vue-prop {Number | String} [zIndex=11] - 拖拽元素的堆叠顺序
+ * @vue-prop {Object} [boundary={top: 0,left: 0,right: 0,bottom: 0}] - 拖拽元素的拖拽边界
+ * @vue-data {Number} elWidth 拖拽元素的宽度
+ * @vue-data {Number} elHeight 拖拽元素的高度
+ * @vue-data {Number} screenWidth 屏幕的宽度
+ * @vue-data {Number} screenHeight 屏幕的高度
+ * @vue-data {Number} startTop 拖拽元素距离顶部的距离
+ * @vue-data {Number} startLeft 拖拽元素距离左侧的距离
+ * @vue-data {Object} position 鼠标点击的位置,包含距离x轴和y轴的距离
+ */
+export default {
+  name: "nut-drag",
+  props: {
+    attract: {
+      type: Boolean,
+      default: false,
+    },
+    direction: {
+      type: String,
+      default: "all",
+    },
+    zIndex: {
+      type: [Number, String],
+      default: 11,
+    },
+    boundary: {
+      type: Object,
+      default: function() {
+        return {
+          top: 0,
+          left: 0,
+          right: 0,
+          bottom: 0,
+        };
+      },
+    },
+  },
+  data() {
+    return {
+      elWidth: 0,
+      elHeight: 0,
+      screenWidth: 0,
+      screenHeight: 0,
+      startTop: 0,
+      startLeft: 0,
+      position: { x: 0, y: 0 },
+    };
+  },
+  methods: {
+    /**
+     * 获取拖拽元素的属性和屏幕的宽高,初始化拖拽元素的位置
+     */
+    getElementInfo() {
+      const el = this.$el;
+      const domElem = document.documentElement;
+      this.elWidth = el.offsetWidth;
+      this.elHeight = el.offsetHeight;
+      this.screenWidth = domElem.clientWidth;
+      this.screenHeight = domElem.clientHeight;
+      el.style.zIndex = this.zIndex;
+      if (this.boundary.left) {
+        el.style.left = this.boundary.left + "px";
+      } else {
+        el.style.right = this.boundary.right + "px";
+      }
+      if (this.boundary.top) {
+        el.style.top = this.boundary.top + "px";
+      } else {
+        el.style.bottom = this.boundary.bottom + "px";
+      }
+    },
+    touchStart(e) {
+      const target = e.currentTarget;
+      this.startTop = target.offsetTop; // 元素距离顶部的距离
+      this.startLeft = target.offsetLeft; // 元素距离左侧的距离
+      this.position.x = e.touches[0].clientX; // 鼠标点击的x轴的距离
+      this.position.y = e.touches[0].clientY; // 鼠标点击的y轴的距离
+      this.$el.addEventListener("touchmove", this.touchMove, false);
+      this.$el.addEventListener("touchend", this.touchEnd, false);
+    },
+    touchMove(e) {
+      e.preventDefault();
+      const target = e.currentTarget;
+      if (e.targetTouches.length == 1) {
+        const touch = e.targetTouches[0];
+        this.nx = touch.clientX - this.position.x;
+        this.ny = touch.clientY - this.position.y;
+        this.xPum = this.startLeft + this.nx;
+        this.yPum = this.startTop + this.ny;
+        const rightLocation =
+          this.screenWidth - this.elWidth - this.boundary.right;
+        // 限制左右拖拽边界
+        if (Math.abs(this.xPum) > rightLocation) {
+          this.xPum = rightLocation;
+        } else if (this.xPum <= this.boundary.left) {
+          this.xPum = this.boundary.left;
+        }
+        // 限制上下拖拽边界
+        if (this.yPum < this.boundary.top) {
+          this.yPum = this.boundary.top;
+        } else if (
+          this.yPum >
+          this.screenHeight - this.elHeight - this.boundary.bottom
+        ) {
+          this.yPum = this.screenHeight - this.elHeight - this.boundary.bottom;
+        }
+        if (this.direction != "y") {
+          target.style.left = this.xPum + "px";
+        }
+        if (this.direction != "x") {
+          target.style.top = this.yPum + "px";
+        }
+      }
+    },
+    touchEnd(e) {
+      const target = e.currentTarget;
+      const touch = e.changedTouches[0];
+      let currX = touch.clientX;
+      const rightLocation =
+        this.screenWidth - this.elWidth - this.boundary.right;
+      if (currX > rightLocation) {
+        currX = rightLocation;
+        // console.log('往右划出边界');
+      } else if (currX < this.boundary.left) {
+        currX = this.boundary.left;
+        // console.log('往左划出边界');
+      } else {
+        currX =
+          currX < this.screenWidth / 2 ? this.boundary.left : rightLocation;
+        // console.log('在边界内滑动');
+      }
+      if (this.direction != "y" && this.attract) {
+        if (currX < this.screenWidth / 2) {
+          this.goLeft(target);
+        } else {
+          this.goRight(target, rightLocation);
+        }
+      }
+      if (this.direction != "x") {
+        target.style.top = this.yPum + "px";
+      }
+    },
+    goLeft(target) {
+      if (this.boundary.left) {
+        if (target.style.left.split("px")[0] > this.boundary.left) {
+          target.style.left = target.style.left.split("px")[0] - 10 + "px";
+          requestAniFrame(() => {
+            this.goLeft(target);
+          });
+        } else {
+          target.style.left = `${this.boundary.left}px`;
+        }
+      } else {
+        if (target.style.left.split("px")[0] > 10) {
+          target.style.left = target.style.left.split("px")[0] - 10 + "px";
+          requestAniFrame(() => {
+            this.goLeft(target);
+          });
+        } else {
+          target.style.left = "0px";
+        }
+      }
+    },
+    goRight(target, rightLocation) {
+      if (rightLocation - parseInt(target.style.left.split("px")[0]) > 10) {
+        target.style.left =
+          parseInt(target.style.left.split("px")[0]) + 10 + "px";
+        requestAniFrame(() => {
+          this.goRight(target, rightLocation);
+        });
+      } else {
+        target.style.left = rightLocation + "px";
+      }
+    },
+  },
+  mounted() {
+    this.getElementInfo();
+  },
+  activated() {
+    if (this.keepAlive) {
+      this.keepAlive = false;
+    }
+  },
+  deactivated() {
+    this.keepAlive = true;
+    this.$el.removeEventListener("touchmove", this.handleScroll, false);
+    this.$el.removeEventListener("touchend", this.handleScroll, false);
+  },
+  destroyed() {
+    this.$el.removeEventListener("touchmove", this.handleScroll, false);
+    this.$el.removeEventListener("touchend", this.handleScroll, false);
+  },
+};
+</script>

+ 8 - 0
src/packages/drag/index.js

@@ -0,0 +1,8 @@
+import Drag from './drag.vue';
+import './drag.scss';
+
+Drag.install = function(Vue) {
+  Vue.component(Drag.name, Drag);
+};
+
+export default Drag

+ 3 - 8
src/packages/leftslip/doc.md

@@ -104,16 +104,11 @@ export default {
 };
 ```
 
-## Prop
+## slot
 
 | 字段           | 说明                 | 类型    | 默认值 |
 | -------------- | -------------------- | ------- | ------ |
-| slot:slip-main | 列表主内容自定义区域 | html    | -      |
-| slot:slipbtns  | 左滑按钮自定义区域   | html    | -      |
-| onlyDelBtn     | 设置单一删除按钮     | Boolean | false  |
+| slip-main | 列表主内容自定义区域 | html    | -      |
+| slipbtns  | 左滑按钮自定义区域   | html    | -      |
 
-## Event
 
-| 字段      | 说明                       | 回调参数 |
-| --------- | -------------------------- | -------- |
-| oneDelete | 单一删除按钮模式下删除事件 | 无       |

+ 7 - 0
src/packages/sidenavbar/__test__/sidenavbar.spec.js

@@ -0,0 +1,7 @@
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import SideNavBar from '../sidenavbar.vue';
+
+describe('SideNavBar.vue', () => {
+    
+});

+ 106 - 8
src/packages/sidenavbar/demo.vue

@@ -1,12 +1,87 @@
 <template>
+  <div class="demo-list">
+    <h4>基本用法</h4>
     <div>
-        <nut-sidenavbar>
-          <nut-subsidenavbar>
-            <nut-sidenavbaritem key="1" title="云存储"></nut-sidenavbaritem>
-            <nut-sidenavbaritem key="2" title="弹性云计算"></nut-sidenavbaritem>
-          </nut-subsidenavbar>
-        </nut-sidenavbar>
+        <nut-cell :is-link="true" :show-icon="true" @click.native="showNav">
+            <span slot="title">
+                <label>右侧</label>
+            </span>
+        </nut-cell>
+        <nut-popup
+            position="right"
+            v-model="show1"
+            :style="{ width, height }"
+        >
+            <nut-sidenavbar :show="show1">
+                <nut-subsidenavbar title="图像理解" ikey="3" :open="false">
+                    <nut-sidenavbaritem ikey="4" title="菜品识别"></nut-sidenavbaritem>
+                    <nut-sidenavbaritem ikey="5" title="拍照购"></nut-sidenavbaritem>
+                </nut-subsidenavbar>
+                <nut-subsidenavbar title="自然语言处理" ikey="12">
+                    <nut-sidenavbaritem ikey="13" title="词法分析"></nut-sidenavbaritem>
+                    <nut-sidenavbaritem ikey="14" title="句法分析"></nut-sidenavbaritem>
+                </nut-subsidenavbar>
+            </nut-sidenavbar>
+        </nut-popup>
     </div>
+    <div>
+        <nut-cell :is-link="true" :show-icon="true" @click.native="showNav2">
+            <span slot="title">
+                <label>左侧</label>
+            </span>
+        </nut-cell>
+        <nut-popup
+            position="left"
+            v-model="show2"
+            :style="{ width, height }"
+        >
+            <nut-sidenavbar>
+                <nut-subsidenavbar title="图像理解" ikey="3" :open="false">
+                    <nut-sidenavbaritem ikey="4" title="菜品识别"></nut-sidenavbaritem>
+                    <nut-sidenavbaritem ikey="5" title="拍照购"></nut-sidenavbaritem>
+                </nut-subsidenavbar>
+                <nut-subsidenavbar title="自然语言处理" ikey="12">
+                    <nut-sidenavbaritem ikey="13" title="词法分析"></nut-sidenavbaritem>
+                    <nut-sidenavbaritem ikey="14" title="句法分析"></nut-sidenavbaritem>
+                </nut-subsidenavbar>
+            </nut-sidenavbar>
+        </nut-popup>
+    </div>
+    <h4>导航嵌套(建议最多三层),点击第一条回调</h4>
+    <div>
+        <nut-cell :is-link="true" :show-icon="true" @click.native="showNav3">
+            <span slot="title">
+                <label>显示</label>
+            </span>
+        </nut-cell>
+        <nut-popup
+            position="right"
+            v-model="show3"
+            :style="{ width, height }"
+        >
+            <nut-sidenavbar :show="show3">
+                <nut-sidenavbaritem ikey="1" title="人脸识别" @click="handleClick('人脸识别')"></nut-sidenavbaritem>
+                <nut-sidenavbaritem ikey="2" title="云存自然语言处理"></nut-sidenavbaritem>
+                <nut-subsidenavbar title="图像理解" ikey="3" :open="false">
+                    <nut-sidenavbaritem ikey="4" title="菜品识别"></nut-sidenavbaritem>
+                    <nut-sidenavbaritem ikey="5" title="拍照购"></nut-sidenavbaritem>
+                </nut-subsidenavbar>
+                <nut-subsidenavbar title="智能城市AI" ikey="6">
+                    <nut-sidenavbaritem ikey="7" title="企业风险预警模型"></nut-sidenavbaritem>
+                    <nut-sidenavbaritem ikey="8" title="水质量检测"></nut-sidenavbaritem>
+                    <nut-subsidenavbar title="人体识别" ikey="9">
+                        <nut-sidenavbaritem ikey="10" title="人体检测"></nut-sidenavbaritem>
+                        <nut-sidenavbaritem ikey="11" title="细粒度人像分割"></nut-sidenavbaritem>
+                    </nut-subsidenavbar>
+                </nut-subsidenavbar>
+                <nut-subsidenavbar title="自然语言处理" ikey="12">
+                    <nut-sidenavbaritem ikey="13" title="词法分析"></nut-sidenavbaritem>
+                    <nut-sidenavbaritem ikey="14" title="句法分析"></nut-sidenavbaritem>
+                </nut-subsidenavbar>
+            </nut-sidenavbar>
+        </nut-popup>
+    </div>
+  </div>
 </template>
 
 <script>
@@ -15,10 +90,33 @@ export default {
 
   },
   data() {
-    return {};
+    return {
+        show1: false,
+        show2: false,
+        show3: false,
+        width: '80%',
+        height: '100%'
+    };
   },
   methods: {
-      
+    showNav() {
+        this.show1 = true
+        this.show2 = false
+        this.show3 = false
+    },
+    showNav2() {
+        this.show1 = false
+        this.show2 = true
+        this.show3 = false
+    },
+    showNav3() {
+        this.show1 = false
+        this.show2 = false
+        this.show3 = true
+    },
+    handleClick(str) {
+        alert(str)
+    }
   }
 };
 </script>

+ 109 - 0
src/packages/sidenavbar/doc.md

@@ -0,0 +1,109 @@
+# SideNavBar 侧边栏导航
+
+侧边栏导航
+
+## 基础用法
+
+```html
+<nut-popup
+    position="right"
+    v-model="show1"
+    :style="{ width, height }"
+>
+    <nut-sidenavbar :show="show1">
+        <nut-subsidenavbar title="图像理解" ikey="3" :open="false">
+            <nut-sidenavbaritem ikey="4" title="菜品识别"></nut-sidenavbaritem>
+            <nut-sidenavbaritem ikey="5" title="拍照购"></nut-sidenavbaritem>
+        </nut-subsidenavbar>
+        <nut-subsidenavbar title="自然语言处理" ikey="12">
+            <nut-sidenavbaritem ikey="13" title="词法分析"></nut-sidenavbaritem>
+            <nut-sidenavbaritem ikey="14" title="句法分析"></nut-sidenavbaritem>
+        </nut-subsidenavbar>
+    </nut-sidenavbar>
+</nut-popup>
+```
+
+## 嵌套(建议最多三层)
+```html
+<nut-popup
+    position="right"
+    v-model="show3"
+    :style="{ width, height }"
+>
+    <nut-sidenavbar :show="show3">
+        <nut-sidenavbaritem ikey="1" title="人脸识别" @click="handleClick('人脸识别')"></nut-sidenavbaritem>
+        <nut-sidenavbaritem ikey="2" title="云存自然语言处理"></nut-sidenavbaritem>
+        <nut-subsidenavbar title="图像理解" ikey="3" :open="false">
+            <nut-sidenavbaritem ikey="4" title="菜品识别"></nut-sidenavbaritem>
+            <nut-sidenavbaritem ikey="5" title="拍照购"></nut-sidenavbaritem>
+        </nut-subsidenavbar>
+        <nut-subsidenavbar title="智能城市AI" ikey="6">
+            <nut-sidenavbaritem ikey="7" title="企业风险预警模型"></nut-sidenavbaritem>
+            <nut-sidenavbaritem ikey="8" title="水质量检测"></nut-sidenavbaritem>
+            <nut-subsidenavbar title="人体识别" ikey="9">
+                <nut-sidenavbaritem ikey="10" title="人体检测"></nut-sidenavbaritem>
+                <nut-sidenavbaritem ikey="11" title="细粒度人像分割"></nut-sidenavbaritem>
+            </nut-subsidenavbar>
+        </nut-subsidenavbar>
+        <nut-subsidenavbar title="自然语言处理" ikey="12">
+            <nut-sidenavbaritem ikey="13" title="词法分析"></nut-sidenavbaritem>
+            <nut-sidenavbaritem ikey="14" title="句法分析"></nut-sidenavbaritem>
+        </nut-subsidenavbar>
+    </nut-sidenavbar>
+</nut-popup>
+```
+
+```javascript
+export default {
+  data() {
+    return {
+        show1: false,
+        show3: false,
+        width: '80%',
+        height: '100%'
+    };
+  },
+  methods: {
+    showNav() {
+        this.show1 = true
+        this.show3 = false
+    },
+    showNav3() {
+        this.show1 = false
+        this.show3 = true
+    },
+    handleClick(str) {
+        alert(str)
+    }
+  }
+};
+```
+
+## SideNavBar
+
+| 字段 | 说明 | 类型 | 默认值
+| ----- | ----- | ----- | -----
+| offset | 导航缩进宽度 | Number/String | 15
+
+## SubSideNavBar
+| 字段 | 说明 | 类型 | 默认值
+| ----- | ----- | ----- | -----
+| title | 导航标题 | String | ''
+| ikey | 导航唯一标识 | String/Number | ''
+| open | 导航是否默认展开 | Boolean | true
+
+## SubSideNavBar Event
+| 字段 | 说明 | 回调参数
+| ----- | ----- | -----
+| titleClick | 导航点击 | 无
+
+## SideNavBarItem
+| 字段 | 说明 | 类型 | 默认值
+| ----- | ----- | ----- | -----
+| title | 导航标题 | String | ''
+| ikey | 导航唯一标识 | String/Number | ''
+
+## SideNavBarItem Event
+| 字段 | 说明 | 回调参数
+| ----- | ----- | -----
+| click | 导航点击 | 无

+ 27 - 26
src/packages/sidenavbar/sidenavbar.vue

@@ -1,46 +1,47 @@
 <template>
     <div class="nut-sidenavbar">
-        <nut-popup
-            :position="position"
-            v-model="show"
-            :style="{ width, height }"
-        >
-            <div class="sidenavbar-content">
-                <div class="sidenavbar-list">
-                    <slot></slot>
-                </div>
+        <div class="sidenavbar-content">
+            <div class="sidenavbar-list">
+                <slot></slot>
             </div>
-        </nut-popup>
+        </div>
     </div>
 </template>
 <script>
 export default {
     name:'nut-sidenavbar',
     props: {
-        show:{
-            type: Boolean,
-            default: true
-        },
-        position:{
-            type: String,
-            default: 'right'
-        },
-        width:{
+        offset:{
             type:[String,Number],
-            default: '80%'
-        },
-        height:{
-            type:[String,Number],
-            default: '100%'
+            default:15
+        }
+    },
+    mounted() {
+        let slots = this.$slots.default;
+        if(slots) {
+            slots = slots.filter(item => item.elm.nodeType !== 3).map(item => {
+                return item.elm
+            })
+            
+            this.setPaddingLeft(slots)
         }
     },
     data() {
         return {
-            
+            count: 1
         };
     },
     methods: {
-
+        setPaddingLeft(nodeList, level = 1) {
+            for(let i = 0; i < nodeList.length; i++) {
+                let item = nodeList[i];
+                item.children[0].style.paddingLeft = this.offset * level + 'px'
+                if(item.className !== 'nut-sidenavbaritem') {
+                    this.setPaddingLeft(Array.from(item.children[1].children), ++this.count)
+                }
+            }
+            this.count = 1;
+        }
     }
 }
 </script>

+ 5 - 6
src/packages/sidenavbaritem/sidenavbaritem.scss

@@ -1,9 +1,8 @@
 .nut-sidenavbaritem{
-    li{
-        .sub-sidenavbar-item-item{
-            line-height: 40px;
-            padding: 0 50px;
-            color: #9b9ea0;
-        }
+    height: 40px;
+    line-height: 40px;
+    .item-title{
+        color: $title-color;
+        background-color: #fff;
     }
 }

+ 11 - 16
src/packages/sidenavbaritem/sidenavbaritem.vue

@@ -1,32 +1,27 @@
 <template>
-    <div class="nut-sidenavbaritem">     
-        <li>
-            <a href="javascript:;" class="item-title sub-sidenavbar-item-item">
-                {{ title }}
-            </a>
-        </li>
+    <div class="nut-sidenavbaritem" @click.stop="handleClick" :ikey="ikey"> 
+        <a href="javascript:;" class="item-title">
+            {{ title }}
+        </a>
     </div>
 </template>
 <script>
 export default {
     name:'nut-sidenavbaritem',
     props: {
-        disabled: {
-            type: Boolean,
-            default: true
-        },
         title: {
             type: String,
             default: ''
+        },
+        ikey: {
+            type: String,
+            default: ''
         }
     },
-    data() {
-        return {
-            
-        };
-    },
     methods: {
-
+        handleClick() {
+            this.$emit('click');
+        }
     }
 }
 </script>

+ 19 - 31
src/packages/subsidenavbar/subsidenavbar.scss

@@ -1,4 +1,8 @@
 .nut-subsidenavbar{
+    display: grid;
+    float: left;
+    width: 100%;
+    position: relative;
     .item-title{
         display: block;
         width: 100%;
@@ -8,44 +12,28 @@
         text-overflow: ellipsis;
         white-space: nowrap;
         box-sizing: border-box;
-        border-bottom: 1px solid #f8f8f8;
+        border-bottom: 1px solid $light-color;
+        color: $title-color;
+        font-size: $font-size-large;
+        background-color: $light-color;
+        .sidenavbar-title{
+            line-height: 40px;
+            color: $title-color;
+        }
     }
     .sidenavbar-icon{
         position: absolute;
         top: 50%;
         right: 20px;
         transform: translateY(-50%);
-    }
-    .sidenavbar-title{
-        font-size: 16px;
-        line-height: 40px;
-        height: 40px;
-    }
-    .sidenavbar-item{
-        float: left;
-        width: 100%;
-        position: relative;
-        border-bottom: 1px solid #f8f8f8;
-        background-color: #f8f8f8;
-        .sidenavbar-item-title{
-            padding: 0 18px;
-            .sidenavbar-title{
-                color: #333;
-            }
-        }
-        .sub-sidenavbar-box{
-            background-color: #fefefe;
-            .sub-sidenavbar-list{
-                .sub-sidenavbar-item{
-                    width: 100%;
-                    .sub-sidenavbar-item-title{
-                        padding: 0 34px;
-                        .sub-sidenavbar-title{
-                            color: #333;
-                        }
-                    }
-                }
+        i{
+            transition: transform $animation-duration $ease-in-out;
+            &.up{
+                transform: rotate(-180deg);
             }
         }
     }
+    .sub-sidenavbar-list{
+        width: 100%;
+    }
 }

+ 30 - 30
src/packages/subsidenavbar/subsidenavbar.vue

@@ -1,31 +1,14 @@
 <template>
-    <div class="nut-subsidenavbar">
-        <div class="sidenavbar-item">
-            <div class="item-title sidenavbar-item-title">
-                <a href="javascript:;" class="sidenavbar-title">
-                    云产品
-                </a>
-                <span class="sidenavbar-icon">
-                    <nut-icon type="down"></nut-icon>
-                </span>
-            </div>
-            <div class="sub-sidenavbar-box">
-                <div class="sub-sidenavbar-list">
-                    <div class="sub-sidenavbar-item">
-                        <div class="item-title sub-sidenavbar-item-title">
-                            <a href="javascript:;" class="sidenavbar-title sub-sidenavbar-title">
-                                弹性运算
-                            </a>
-                            <span class="sidenavbar-icon">
-                                <nut-icon type="down"></nut-icon>
-                            </span>
-                        </div>
-                        <ul class="three-sidenavbar-list">
-                            <slot></slot>
-                        </ul>
-                    </div>
-                </div>
-            </div>
+    <div class="nut-subsidenavbar sidenavbar-item" :ikey="ikey">
+        <div class="item-title" @click.stop="handleClick">
+            <a href="javascript:;" class="sidenavbar-title">{{ title }}</a>
+            <span class="sidenavbar-icon"><nut-icon type="down" :class="direction"></nut-icon></span>
+        </div>
+        <div class="sub-sidenavbar-list" 
+            :class="!direction ? 'nutFadeIn' : 'nutFadeOut'"
+            :style="{height: !direction ? 'auto' : 0}" 
+            >
+            <slot></slot>
         </div>
     </div>
 </template>
@@ -33,15 +16,32 @@
 export default {
     name:'nut-subsidenavbar',
     props: {
-        
+        title: {
+            type: String,
+            default: ''
+        },
+        ikey: {
+            type: [String, Number],
+            default: ''
+        },
+        open: {
+            type: Boolean,
+            default: true
+        }
     },
     data() {
         return {
-            
+            direction: ''
         };
     },
+    mounted() {
+        this.direction = this.open ? '' : 'up';
+    },
     methods: {
-
+        handleClick() {
+            this.$emit('titleClick');
+            this.direction = !this.direction ? 'up' : ''
+        }
     }
 }
 </script>

+ 125 - 53
src/packages/video/demo.vue

@@ -25,74 +25,146 @@
             <nut-video :sources="sources" :options="options5"></nut-video>
         </div>
         <h4>设置视频为背景图</h4>
-        <p>当设置视频为背景图时需要将 muted 静音、 disabled 禁止操作、loop 循环播放、autoplay 自动播放设置为 true,移动端需要设置 playsinline 行内展示(兼容安卓用)</p>
+        <p>当设置视频为背景图时需要将 muted 静音、 disabled 禁止操作、loop 循环播放、autoplay 自动播放设置为 true,移动端需要设置
+            playsinline 行内展示(兼容安卓用)</p>
         <div class="video-con">
             <nut-video :sources="sources" :options="options6"></nut-video>
         </div>
+        <h4>视频切换</h4>
+        <p>播放上一个、下一个视频</p>
+        <div class="video-con" ref="changeVideo">
+            <nut-video :sources="sources1" :options="options"></nut-video>
+        </div>
+
+        <button @click="prevVideo">播放上一个</button> <button @click="nextVideo">播放下一个</button>
     </div>
 </template>
 
 <script>
-export default {
-    components: {},
-    data() {
-        return {
-            sources: [
-                {
-                    src:
-                        'https://storage.jd.com/about/big-final.mp4?Expires=3730193075&AccessKey=3LoYX1dQWa6ZXzQl&Signature=ViMFjz%2BOkBxS%2FY1rjtUVqbopbJI%3D',
-                    type: 'video/mp4'
-                }
-            ],
+    export default {
+        components: {},
+        data() {
+            return {
+                sources: [
+                    {
+                        src:
+                            'https://storage.jd.com/about/big-final.mp4?Expires=3730193075&AccessKey=3LoYX1dQWa6ZXzQl&Signature=ViMFjz%2BOkBxS%2FY1rjtUVqbopbJI%3D',
+                        type: 'video/mp4'
+                    }
+                ],
+                sources1: [
+                    {
+                        src: 'https://storage.jd.com/about/big-final.mp4?Expires=3730193075&AccessKey=3LoYX1dQWa6ZXzQl&Signature=ViMFjz%2BOkBxS%2FY1rjtUVqbopbJI%3D',
+                        type: 'video/mp4'
+                    }
+                ],
+                videoId: 'videoid',
+                options: {
+                    controls: true
+                },
+                options2: {
+                    autoplay: true,
+                    muted: true,
+                    volume: 0.6,
+                    poster: ''
+                },
+                options3: {
+                    controls: true,
+                    muted: true
+                },
+                options4: {
+                    controls: true,
+                    poster: 'https://img10.360buyimg.com/ling/s640x356_jfs/t1/96045/31/13848/43886/5e5e35ffE68170c74/861a6394e38810f0.png'
+                },
+                options5: {
+                    playsinline: true,
+                    controls: true
+                },
+                options6: {
+                    autoplay: true,
+                    volume: 0.6,
+                    poster: '',
+                    muted: true,
+                    disabled: true,
+                    playsinline: true,
+                    loop: true
+                },
 
-            options: {
-                controls: true,
+            };
+        },
+        methods: {
+            play(elm) {
+                console.log('play', elm);
             },
-            options2: {
-                autoplay: true,
-                volume: 0.6,
-                poster: '',
+            pause(e) {
+                console.log('pause');
             },
-            options3: {
-                controls: true,
-                muted: true
+            playend(e) {
+                alert('播放结束');
             },
-            options4: {
-                controls: true,
-                poster: 'https://img10.360buyimg.com/ling/s640x356_jfs/t1/96045/31/13848/43886/5e5e35ffE68170c74/861a6394e38810f0.png',
+            testPlay(e) {
+                console.log('play', elm);
             },
-            options5: {
-                playsinline: true,
-                controls: true,
+            changeVideo() {
+                this.sources1 = [
+                    {
+                        src: 'http://vjs.zencdn.net/v/oceans.mp4',
+                        type: 'video/mp4'
+                    }
+                ]
+
+                let videoElement = document.getElementById("testvideo").getElementsByTagName('video')[0];
+                videoElement.pause();
+                videoElement.removeAttribute('src');
+                videoElement.src = this.sources1.src;
+                videoElement.load();
             },
-            options6: {
-                autoplay: true,
-                volume: 0.6,
-                poster: '',
-                muted: true,
-                disabled: true,
-                playsinline: true,
-                loop: true
+            prevVideo() {
+                let videoCon = this.$refs.changeVideo
+                let player = videoCon.getElementsByTagName('video')[0];
+
+                this.sources1 = [
+                    {
+                        src: 'https://storage.jd.com/about/big-final.mp4?Expires=3730193075&AccessKey=3LoYX1dQWa6ZXzQl&Signature=ViMFjz%2BOkBxS%2FY1rjtUVqbopbJI%3D',
+                        type: 'video/mp4'
+                    }
+                ]
+                this.$nextTick(() => {
+                    player.load()
+                })
+
             },
-           
-        };
-    },
-    methods: {
-        play(elm){
-            console.log('play',elm)
-        },
-        pause(e){
-            console.log('pause')
-        },
-        playend(e){
-            alert('播放结束')
+            nextVideo() {
+                let videoCon = this.$refs.changeVideo
+                let player = videoCon.getElementsByTagName('video')[0];
+
+                this.sources1 = [
+                    {
+                        src: 'http://vjs.zencdn.net/v/oceans.mp4',
+                        type: 'video/mp4'
+                    }
+                ]
+                this.$nextTick(() => {
+                    player.load()
+                })
+
+            }
         }
-    }
-};
+    };
 </script>
 
 <style lang="scss" scoped>
-.nut-video{
-    height:200px;
-}
-</style>
+    .nut-video {
+        height: 200px;
+    }
+
+    button {
+        margin: 5px 10px 5px 0;
+        background: #f0250f;
+        border: 1px solid #f0250f;
+        height: 32px;
+        border-radius: 4px;
+        color: #fff;
+        font-size: 14px;
+    }
+</style>

+ 73 - 17
src/packages/video/doc.md

@@ -14,7 +14,6 @@
 
 ```javascript
 export default {
-  methods: {
     data() {
         return {
             sources: [
@@ -27,6 +26,7 @@ export default {
             options: {
                 controls: true
             },
+		}
     },
     methods: {
         play(elm){
@@ -39,7 +39,7 @@ export default {
             alert('播放结束')
         }
     }
-  }
+  
 };
 ```
 
@@ -53,7 +53,7 @@ autoplay 属性设置视频自动播放
 
 ```javascript
 export default {
-  methods: {
+  
     data() {
         return {
             options2: {
@@ -61,9 +61,9 @@ export default {
                 volume: 0.6,
                 poster: ''
             },
-
+		}
     },
-  }
+  
 };
 ```
 
@@ -77,16 +77,15 @@ muted 属性设置视频初始化静音
 
 ```javascript
 export default {
-  methods: {
     data() {
         return {
             options3: {
                 controls: true,
                 muted: true
             },
-
+		}
     },
-  }
+  
 };
 ```
 
@@ -100,16 +99,14 @@ poster 属性设置视频海报
 
 ```javascript
 export default {
-  methods: {
     data() {
         return {
             options4: {
                 controls: true,
                 poster: 'https://img10.360buyimg.com/ling/s640x356_jfs/t1/96045/31/13848/43886/5e5e35ffE68170c74/861a6394e38810f0.png',
             },
-
+		}
     },
-  }
 };
 ```
 
@@ -123,16 +120,14 @@ playsinline 属性设置移动端视频行内播放,阻止新打开页面播
 
 ```javascript
 export default {
-  methods: {
     data() {
         return {
             options5: {
                 playsinline: true,
                 controls: true,
             },
-
+		}
     },
-  }
 };
 ```
 
@@ -146,7 +141,6 @@ export default {
 
 ```javascript
 export default {
-  methods: {
     data() {
         return {
             options6: {
@@ -158,12 +152,74 @@ export default {
                 playsinline: true,
                 loop: true
             },
+		}
+    }
+};
+```
 
-    },
-  }
+## 视频切换
+
+播放上一个、下一个视频
+
+```html
+  	<div class="video-con" ref="changeVideo">
+		<nut-video :sources="sources1" :options="options"></nut-video>
+	</div>
+```
+
+```javascript
+export default {
+    data() {
+        return {
+            sources1: [
+                {
+                    src: 'https://storage.jd.com/about/big-final.mp4?Expires=3730193075&AccessKey=3LoYX1dQWa6ZXzQl&Signature=ViMFjz%2BOkBxS%2FY1rjtUVqbopbJI%3D',
+                    type: 'video/mp4'
+                }
+            ],
+            options: {
+                controls: true
+            },
+
+    	},
+  	}
+	methods: {
+        prevVideo() {
+			let videoCon = this.$refs.changeVideo
+			let player = videoCon.getElementsByTagName('video')[0];
+			//改变视频源
+			this.sources1 = [
+				{
+					src: 'https://storage.jd.com/about/big-final.mp4?Expires=3730193075&AccessKey=3LoYX1dQWa6ZXzQl&Signature=ViMFjz%2BOkBxS%2FY1rjtUVqbopbJI%3D',
+					type: 'video/mp4'
+				}
+			]
+			this.$nextTick(() => {
+				player.load()
+			})
+
+		},
+		nextVideo() {
+			let videoCon = this.$refs.changeVideo
+			let player = videoCon.getElementsByTagName('video')[0];
+			//改变视频源
+			this.sources1 = [
+				{
+					src: 'http://vjs.zencdn.net/v/oceans.mp4',
+					type: 'video/mp4'
+				}
+			]
+			this.$nextTick(() => {
+				player.load()
+			})
+
+		}
+    }
 };
 ```
 
+
+
 ## Prop
 
 | 字段                | 说明                                       | 类型    | 默认值   |

+ 197 - 206
src/packages/video/video.vue

@@ -1,16 +1,7 @@
 <template>
     <div class="nut-video" ref="videocon">
-        <video
-            ref="video"
-            class="nut-videoplayer"
-            type="video/mp4"
-            :muted="options.muted"
-            :autoplay="options.autoplay"
-            :loop="options.loop"
-            :poster="options.poster"
-            :controls="options.controls"
-            @error="handleError"
-        >
+        <video ref="video" class="nut-videoplayer" type="video/mp4" :muted="options.muted" :autoplay="options.autoplay"
+            :loop="options.loop" :poster="options.poster" :controls="options.controls" @error="handleError">
             <source v-for="source in sources" :src="source.src" :type="source.type" :key="source.src" />
         </video>
         <div class="playing-mask" @click="play"></div>
@@ -38,209 +29,209 @@
     </div>
 </template>
 <script>
-import {throttle} from '../../utils/throttle';
-export default {
-    name: 'nut-video',
-    props: {
-        src: '',
-        playsinline: {
-            type: Boolean,
-            default: false
-        },
-        sources: Array,
-        options: {
-            type: Object,
-            default() {
-                return {
-                    autoplay: false, //是否自动播放
-                    volume: 0.5,
-                    poster: '',
-                    loop: false,
-                    controls: true,
-                    muted: false, //是否静音
-                    disabled: false, //禁止操作
-                    playsinline: false //行内展示
-                };
-            },
-            required: true
-        }
-    },
-    data() {
-        return {
-            videoElm: null,
-            initial: true, //控制封面的显示
-            showToolbox: false, //控制控制器和标题的显示
-            // 视频容器元素
-            player: {
-                $player: null,
-                pos: null
-            },
-            // progress进度条元素
-            progressBar: {
-                progressElm: null, // 进度条DOM对象
-                pos: null
+    import { throttle } from '../../utils/throttle';
+    export default {
+        name: 'nut-video',
+        props: {
+            src: '',
+            playsinline: {
+                type: Boolean,
+                default: false
             },
-            // video控制显示设置
-            videoSet: {
-                loaded: 0, // 缓存长度
-                displayTime: '00:00', // 进度时间
-                totalTime: '00:00', // 总时间
-                progress: {
-                    width: 0, // 进度条长度
-                    current: 0 // 进度条当前位置
-                }
-            },
-            state: {
-                contrlShow: false,
-                vol: 0.5, //音量
-                currentTime: 0, //当前时间
-                fullScreen: false,
-                playing: false, //是否正在播放
-                isLoading: false,
-                isEnd: false,
-                isError: false
-            }
-        };
-    },
-    mounted() {
-        this.init();
-    },
-    methods: {
-        init() {
-            this.videoElm = this.$el.getElementsByTagName('video')[0];
-            if (this.options.autoplay) {
-                this.play();
+            sources: Array,
+            options: {
+                type: Object,
+                default() {
+                    return {
+                        autoplay: false, //是否自动播放
+                        volume: 0.5,
+                        poster: '',
+                        loop: false,
+                        controls: true,
+                        muted: false, //是否静音
+                        disabled: false, //禁止操作
+                        playsinline: false //行内展示
+                    };
+                },
+                required: true
             }
+        },
+        data() {
+            return {
+                videoElm: null,
+                initial: true, //控制封面的显示
+                showToolbox: false, //控制控制器和标题的显示
+                // 视频容器元素
+                player: {
+                    $player: null,
+                    pos: null
+                },
+                // progress进度条元素
+                progressBar: {
+                    progressElm: null, // 进度条DOM对象
+                    pos: null
+                },
+                // video控制显示设置
+                videoSet: {
+                    loaded: 0, // 缓存长度
+                    displayTime: '00:00', // 进度时间
+                    totalTime: '00:00', // 总时间
+                    progress: {
+                        width: 0, // 进度条长度
+                        current: 0 // 进度条当前位置
+                    }
+                },
+                state: {
+                    contrlShow: false,
+                    vol: 0.5, //音量
+                    currentTime: 0, //当前时间
+                    fullScreen: false,
+                    playing: false, //是否正在播放
+                    isLoading: false,
+                    isEnd: false,
+                    isError: false
+                }
+            };
+        },
+        mounted() {
+            this.init();
+        },
+        methods: {
+            init() {
+                this.videoElm = this.$el.getElementsByTagName('video')[0];
+                if (this.options.autoplay) {
+                    this.play();
+                }
 
-            if (this.options.playsinline) {
-                this.videoElm.setAttribute('playsinline', this.options.playsinline);
-                this.videoElm.setAttribute('webkit-playsinline', this.options.playsinline);
-                this.videoElm.setAttribute('x5-playsinline', this.options.playsinline);
-                this.videoElm.setAttribute('x5-video-player-type', 'h5');
-                this.videoElm.setAttribute('x5-video-player-fullscreen', false);
-            }
-            this.volumeHandle();
+                if (this.options.playsinline) {
+                    this.videoElm.setAttribute('playsinline', this.options.playsinline);
+                    this.videoElm.setAttribute('webkit-playsinline', this.options.playsinline);
+                    this.videoElm.setAttribute('x5-playsinline', this.options.playsinline);
+                    this.videoElm.setAttribute('x5-video-player-type', 'h5');
+                    this.videoElm.setAttribute('x5-video-player-fullscreen', false);
+                }
+                this.volumeHandle();
 
-            // const $player = this.$el;
-            // const $progress = this.$el.getElementsByClassName('progress')[0];
-            // // 播放器位置
-            // this.player.$player = $player;
-            // this.progressBar.$progress = $progress;
-            // this.player.pos = $player.getBoundingClientRect();
-            // this.progressBar.pos = $progress.getBoundingClientRect();
-            // this.videoSet.progress.width = Math.round($progress.getBoundingClientRect().width);
+                // const $player = this.$el;
+                // const $progress = this.$el.getElementsByClassName('progress')[0];
+                // // 播放器位置
+                // this.player.$player = $player;
+                // this.progressBar.$progress = $progress;
+                // this.player.pos = $player.getBoundingClientRect();
+                // this.progressBar.pos = $progress.getBoundingClientRect();
+                // this.videoSet.progress.width = Math.round($progress.getBoundingClientRect().width);
 
-            this.videoElm.addEventListener('play', () => {
-                this.state.playing = true;
-            });
-            this.videoElm.addEventListener('pause', () => {
-                this.state.playing = false;
-            });
-        },
-        play() {
-            this.state.playing = !this.state.playing;
+                this.videoElm.addEventListener('play', () => {
+                    this.state.playing = true;
+                });
+                this.videoElm.addEventListener('pause', () => {
+                    this.state.playing = false;
+                });
+            },
+            play() {
+                this.state.playing = !this.state.playing;
 
-            if (this.options.autoplay && this.options.disabled) {
-                this.state.playing = true;
-                return false;
-            }
-            if (this.videoElm) {
-                // if (this.state.playing) {
-                //     this.videoElm.play();
-                //     this.videoElm.addEventListener('ended', this.playEnded);
-                //     this.$emit('play', this.video);
-                // } else {
-                //     this.videoElm.pause();
-                //     this.$emit('pause', this.video);
-                // }
-                // 播放状态
-                if (this.state.playing) {
-                    try {
-                        this.videoElm.play();
-                        // this.isPauseTouch = false;
-                        // 监听缓存进度
-                        // this.videoElm.addEventListener('progress', e => {
-                        //     this.getLoadTime();
-                        // });
-                        // // 监听播放进度
-                        // this.videoElm.addEventListener('timeupdate', throttle(this.getPlayTime, 100, 1));
-                        // 监听结束
-                        this.videoElm.addEventListener('ended', this.playEnded);
-                        this.$emit('play', this.videoElm);
-                    } catch (e) {
-                        // 捕获url异常出现的错误
-                        this.handleError()
-                    }
+                if (this.options.autoplay && this.options.disabled) {
+                    this.state.playing = true;
+                    return false;
                 }
-                // 停止状态
-                else {
-                    this.isPauseTouch = true;
-                    this.videoElm.pause();
-                    this.$emit('pause', this.videoElm);
+                if (this.videoElm) {
+                    // if (this.state.playing) {
+                    //     this.videoElm.play();
+                    //     this.videoElm.addEventListener('ended', this.playEnded);
+                    //     this.$emit('play', this.video);
+                    // } else {
+                    //     this.videoElm.pause();
+                    //     this.$emit('pause', this.video);
+                    // }
+                    // 播放状态
+                    if (this.state.playing) {
+                        try {
+                            this.videoElm.play();
+                            // this.isPauseTouch = false;
+                            // 监听缓存进度
+                            // this.videoElm.addEventListener('progress', e => {
+                            //     this.getLoadTime();
+                            // });
+                            // // 监听播放进度
+                            // this.videoElm.addEventListener('timeupdate', throttle(this.getPlayTime, 100, 1));
+                            // 监听结束
+                            this.videoElm.addEventListener('ended', this.playEnded);
+                            this.$emit('play', this.videoElm);
+                        } catch (e) {
+                            // 捕获url异常出现的错误
+                            this.handleError()
+                        }
+                    }
+                    // 停止状态
+                    else {
+                        this.isPauseTouch = true;
+                        this.videoElm.pause();
+                        this.$emit('pause', this.videoElm);
+                    }
                 }
-            }
-        },
-        volumeHandle() {
-            this.state.vol = this.videoElm.volume;
-        },
-        playEnded() {
-            // console.log('ended')
-            this.state.playing = false;
-            this.state.isEnd = true;
-            this.state.controlBtnShow = true;
-            this.videoSet.displayTime = '00:00';
-            this.videoSet.progress.current = 0;
-            this.videoElm.currentTime = 0;
-            this.$emit('playend', this.videoElm);
-        },
-        // 数据加载出错
-        handleError() {
-            // console.log('error')
-            this.state.isError = true;
-        },
+            },
+            volumeHandle() {
+                this.state.vol = this.videoElm.volume;
+            },
+            playEnded() {
+                // console.log('ended')
+                this.state.playing = false;
+                this.state.isEnd = true;
+                this.state.controlBtnShow = true;
+                this.videoSet.displayTime = '00:00';
+                this.videoSet.progress.current = 0;
+                this.videoElm.currentTime = 0;
+                this.$emit('playend', this.videoElm);
+            },
+            // 数据加载出错
+            handleError() {
+                // console.log('error')
+                this.state.isError = true;
+            },
 
-        fullScreen() {
-            if (!this.state.fullScreen) {
-                this.state.fullScreen = true;
-                this.video.webkitRequestFullScreen();
-            } else {
-                this.state.fullScreen = false;
-                document.webkitCancelFullScreen();
+            fullScreen() {
+                if (!this.state.fullScreen) {
+                    this.state.fullScreen = true;
+                    this.video.webkitRequestFullScreen();
+                } else {
+                    this.state.fullScreen = false;
+                    document.webkitCancelFullScreen();
+                }
+                setTimeout(this.initVideo, 200);
+            },
+            // 获取播放时间
+            getPlayTime() {
+                const percent = this.videoElm.currentTime / this.videoElm.duration;
+                this.videoSet.progress.current = Math.round(this.videoSet.progress.width * percent);
+                // 赋值时长
+                this.videoSet.totalTime = timeParse(this.videoElm.duration);
+                this.videoSet.displayTime = timeParse(this.videoElm.currentTime);
+            },
+            // 获取缓存时间
+            getLoadTime() {
+                // console.log('缓存了...',this.videoElm.buffered.end(0));
+                this.videoSet.loaded = (this.videoElm.buffered.end(0) / this.videoElm.duration) * 100;
+            },
+            getTime() {
+                this.videoElm.addEventListener('durationchange', e => {
+                    console.log(e);
+                });
+                this.videoElm.addEventListener('progress', e => {
+                    this.videoSet.loaded = (-1 + this.videoElm.buffered.end(0) / this.videoElm.duration) * 100;
+                });
+                this.videoSet.len = this.videoElm.duration;
+            },
+            sliderStart() { },
+            touchmove() { },
+            touchend() { },
+            // 点击重新加载
+            retry() {
+                console.log('error')
+                this.state.isError = false;
+                this.init();
             }
-            setTimeout(this.initVideo, 200);
-        },
-        // 获取播放时间
-        getPlayTime() {
-            const percent = this.videoElm.currentTime / this.videoElm.duration;
-            this.videoSet.progress.current = Math.round(this.videoSet.progress.width * percent);
-            // 赋值时长
-            this.videoSet.totalTime = timeParse(this.videoElm.duration);
-            this.videoSet.displayTime = timeParse(this.videoElm.currentTime);
-        },
-        // 获取缓存时间
-        getLoadTime() {
-            // console.log('缓存了...',this.videoElm.buffered.end(0));
-            this.videoSet.loaded = (this.videoElm.buffered.end(0) / this.videoElm.duration) * 100;
         },
-        getTime() {
-            this.videoElm.addEventListener('durationchange', e => {
-                console.log(e);
-            });
-            this.videoElm.addEventListener('progress', e => {
-                this.videoSet.loaded = (-1 + this.videoElm.buffered.end(0) / this.videoElm.duration) * 100;
-            });
-            this.videoSet.len = this.videoElm.duration;
-        },
-        sliderStart() {},
-        touchmove() {},
-        touchend() {},
-        // 点击重新加载
-        retry() {
-            console.log('error')
-            this.state.isError = false;
-            this.init();
-        }
-    },
-    beforeDestroy() {}
-};
-</script>
+        beforeDestroy() { }
+    };
+</script>

+ 68 - 67
types/nutui.d.ts

@@ -1,7 +1,7 @@
-import Vue  from 'vue';
+import Vue from 'vue';
 
 declare class UIComponent extends Vue {
-    static install (vue: typeof Vue): void
+    static install(vue: typeof Vue): void
 }
 
 export interface InstallationOptions {
@@ -11,71 +11,72 @@ export interface InstallationOptions {
 
 export const version: string
 
-export const locale: (l:any) => void
+export const locale: (l: any) => void
 
-export function install (vue: typeof Vue, options: InstallationOptions): void
+export function install(vue: typeof Vue, options: InstallationOptions): void
 
-export declare class ActionSheet extends UIComponent {}
-export declare class Badge extends UIComponent {}
-export declare class Button extends UIComponent {}
-export declare class ButtonGroup extends UIComponent {}
-export declare class Calendar extends UIComponent {}
-export declare class Cell extends UIComponent {}
-export declare class CheckBox extends UIComponent {}
-export declare class CheckBoxGroup extends UIComponent {}
-export declare class Col extends UIComponent {}
-export declare class DatePicker extends UIComponent {}
-export declare class Dialog extends UIComponent {}
-export declare class Flex extends UIComponent {}
-export declare class Grid extends UIComponent {}
-export declare class GridCol extends UIComponent {}
-export declare class GridRow extends UIComponent {}
-export declare class Icon extends UIComponent {}
-export declare class ImagePicker extends UIComponent {}
-export declare class Menu extends UIComponent {}
-export declare class NavBar extends UIComponent {}
-export declare class NoticeBar extends UIComponent {}
-export declare class Picker extends UIComponent {}
-export declare class Price extends UIComponent {}
-export declare class Progress extends UIComponent {}
-export declare class Radio extends UIComponent {}
-export declare class RadioGroup extends UIComponent {}
-export declare class Range extends UIComponent {}
-export declare class Rate extends UIComponent {}
-export declare class Row extends UIComponent {}
-export declare class SearchBar extends UIComponent {}
-export declare class ShortPassword extends UIComponent {}
-export declare class Skeleton extends UIComponent {}
-export declare class Slider extends UIComponent {}
-export declare class Stepper extends UIComponent {}
-export declare class Steps extends UIComponent {}
-export declare class Swiper extends UIComponent {}
-export declare class Switch extends UIComponent {}
-export declare class Tab extends UIComponent {}
-export declare class Tabbar extends UIComponent {}
-export declare class TabPanel extends UIComponent {}
-export declare class Toast extends UIComponent {}
-export declare class BackTop extends UIComponent {}
-export declare class Scroller extends UIComponent {}
-export declare class CountDown extends UIComponent {}
-export declare class Uploader extends UIComponent {}
-export declare class TextInput extends UIComponent {}
-export declare class TextBox extends UIComponent {}
-export declare class Avatar extends UIComponent {}
-export declare class Infiniteloading extends UIComponent {}
-export declare class Lazyload extends UIComponent {}
-export declare class Elevator extends UIComponent {}
-export declare class LeftSlip extends UIComponent {}
-export declare class TabSelect extends UIComponent {}
-export declare class Popup extends UIComponent {}
+export declare class ActionSheet extends UIComponent { }
+export declare class Badge extends UIComponent { }
+export declare class Button extends UIComponent { }
+export declare class ButtonGroup extends UIComponent { }
+export declare class Calendar extends UIComponent { }
+export declare class Cell extends UIComponent { }
+export declare class CheckBox extends UIComponent { }
+export declare class CheckBoxGroup extends UIComponent { }
+export declare class Col extends UIComponent { }
+export declare class DatePicker extends UIComponent { }
+export declare class Dialog extends UIComponent { }
+export declare class Flex extends UIComponent { }
+export declare class Grid extends UIComponent { }
+export declare class GridCol extends UIComponent { }
+export declare class GridRow extends UIComponent { }
+export declare class Icon extends UIComponent { }
+export declare class ImagePicker extends UIComponent { }
+export declare class Menu extends UIComponent { }
+export declare class NavBar extends UIComponent { }
+export declare class NoticeBar extends UIComponent { }
+export declare class Picker extends UIComponent { }
+export declare class Price extends UIComponent { }
+export declare class Progress extends UIComponent { }
+export declare class Radio extends UIComponent { }
+export declare class RadioGroup extends UIComponent { }
+export declare class Range extends UIComponent { }
+export declare class Rate extends UIComponent { }
+export declare class Row extends UIComponent { }
+export declare class SearchBar extends UIComponent { }
+export declare class ShortPassword extends UIComponent { }
+export declare class Skeleton extends UIComponent { }
+export declare class Slider extends UIComponent { }
+export declare class Stepper extends UIComponent { }
+export declare class Steps extends UIComponent { }
+export declare class Swiper extends UIComponent { }
+export declare class Switch extends UIComponent { }
+export declare class Tab extends UIComponent { }
+export declare class Tabbar extends UIComponent { }
+export declare class TabPanel extends UIComponent { }
+export declare class Toast extends UIComponent { }
+export declare class BackTop extends UIComponent { }
+export declare class Scroller extends UIComponent { }
+export declare class CountDown extends UIComponent { }
+export declare class Uploader extends UIComponent { }
+export declare class TextInput extends UIComponent { }
+export declare class TextBox extends UIComponent { }
+export declare class Avatar extends UIComponent { }
+export declare class Infiniteloading extends UIComponent { }
+export declare class Lazyload extends UIComponent { }
+export declare class Elevator extends UIComponent { }
+export declare class LeftSlip extends UIComponent { }
+export declare class TabSelect extends UIComponent { }
+export declare class Popup extends UIComponent { }
 
-export declare class LuckDraw extends UIComponent {}
-export declare class Video extends UIComponent {}
-export declare class Signature extends UIComponent {}
-export declare class CircleProgress extends UIComponent {}
-export declare class TimeLine extends UIComponent {}
-export declare class TimeLineItem extends UIComponent {}
-export declare class SideNavBar extends UIComponent {}
-export declare class SubSideNavBar extends UIComponent {}
-export declare class SideNavBarItem extends UIComponent {}
-export declare class Qart extends UIComponent {}
+export declare class LuckDraw extends UIComponent { }
+export declare class Video extends UIComponent { }
+export declare class Signature extends UIComponent { }
+export declare class CircleProgress extends UIComponent { }
+export declare class TimeLine extends UIComponent { }
+export declare class TimeLineItem extends UIComponent { }
+export declare class SideNavBar extends UIComponent { }
+export declare class SubSideNavBar extends UIComponent { }
+export declare class SideNavBarItem extends UIComponent { }
+export declare class Qart extends UIComponent { }
+export declare class Drag extends UIComponent { }