Browse Source

Merge branch 'v2-dev' of https://github.com/jdf2e/nutui into v2-dev

yangkaixuan 5 years ago
parent
commit
64180758e3

+ 0 - 71
eslint-config.js

@@ -1,71 +0,0 @@
-module.exports = {
-  extends: ['plugin:vue/recommended'],
-
-  parserOptions: {
-    parser: '@typescript-eslint/parser',
-    ecmaVersion: 2018,
-    sourceType: 'module',
-    extraFileExtensions: ['.vue']
-  },
-
-  plugins: ['@typescript-eslint'],
-
-  env: {
-    es6: true,
-    node: true,
-    jest: true,
-    browser: true
-  },
-
-  globals: {
-    window: false,
-    document: false,
-    navigator: false
-  },
-
-  rules: {
-    'no-new': 0,
-    'no-shadow': 0,
-    camelcase: 1,
-    'no-bitwise': 0,
-    'func-names': 0,
-    'no-console': 0,
-    'no-plusplus': 0,
-    'arrow-parens': 0,
-    'comma-dangle': 0,
-    'default-case': 0,
-    'prefer-template': 0,
-    'consistent-return': 0,
-    'no-param-reassign': 0,
-    'no-nested-ternary': 0,
-    'operator-linebreak': 0,
-    'object-curly-newline': 0,
-    'no-underscore-dangle': 1,
-    'no-unused-expressions': 0,
-    'no-restricted-globals': 0,
-    'function-paren-newline': 0,
-    'class-methods-use-this': 0,
-    'implicit-arrow-linebreak': 0,
-    'space-before-function-paren': 0,
-    'max-len': ['error', { code: 150 }],
-    'prefer-destructuring': ['error', { object: true, array: false }],
-    'import/order': 0,
-    'import/extensions': 0,
-    'import/no-unresolved': 0,
-    'import/prefer-default-export': 0,
-    'import/no-extraneous-dependencies': 0,
-    'vue/no-v-html': 0,
-    'vue/attributes-order': 0,
-    'vue/require-v-for-key': 0,
-    'vue/require-default-prop': 0,
-    'vue/no-unused-components': 0,
-    'vue/max-attributes-per-line': 0,
-    'vue/singleline-html-element-content-newline': 0,
-    'vue/name-property-casing': ['error', 'kebab-case'],
-    'vue/component-name-in-template-casing': ['error', 'kebab-case'],
-    'vue/html-closing-bracket-newline': 2,
-    '@typescript-eslint/no-unused-vars': ['error'],
-    'vue/html-indent': 0,
-    'vue/html-self-closing': 0
-  }
-};

+ 7 - 4
package.json

@@ -19,15 +19,17 @@
     "add": "nutui-cli add",
     "test": "cross-env NODE_ENV=test nyc mocha-webpack --webpack-config node_modules/@nutui/cli/dist_cli/webpack/test.config.js  --require node_modules/@nutui/cli/dist_cli/test/setup.js src/packages/*/__test__/**.spec.js",
     "coveralls": "cat ./coverage/lcov.info | coveralls",
-    "test:watch": "npm run test --watch",
-    "prettier:fix": "prettier --write src/**/*.{ts,js,vue,scss}"
+    "test:watch": "npm run test --watch"
   },
   "husky": {
     "hooks": {
-      "pre-commit": "node ./scripts/verifymail.js",
+      "pre-commit": "node ./scripts/verifymail.js && lint-staged",
       "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
     }
   },
+  "lint-staged": {
+    "*.{ts,js,vue,scss}": "prettier --write"
+  },
   "repository": {
     "type": "git",
     "url": "https://github.com/jdf2e/nutui.git"
@@ -62,14 +64,15 @@
     "vue": "^2.6.10"
   },
   "devDependencies": {
-    "@nutui/cli": "^0.3.3",
     "@babel/plugin-syntax-dynamic-import": "^7.8.3",
     "@babel/plugin-transform-object-assign": "^7.8.3",
+    "@nutui/cli": "^0.3.5",
     "@typescript-eslint/eslint-plugin": "^2.16.0",
     "@typescript-eslint/parser": "^2.16.0",
     "babel-plugin-transform-object-rest-spread": "^6.26.0",
     "eslint-plugin-import": "^2.20.0",
     "eslint-plugin-vue": "^6.1.2",
+    "lint-staged": "^10.2.11",
     "stylelint-config-standard": "^19.0.0"
   },
   "nyc": {

+ 2 - 2
src/config.json

@@ -509,8 +509,8 @@
     {
       "version": "1.0.0",
       "name": "TabSelect",
-      "chnName": "分类选择",
-      "desc": "两级分类选择",
+      "chnName": "配送时间",
+      "desc": "两级配送时间",
       "type": "component",
       "sort": "6",
       "showDemo": true,

+ 4 - 4
src/packages/actionsheet/actionsheet.vue

@@ -82,19 +82,19 @@ export default {
         if (value) {
           document.body.classList.add('nut-overflow-hidden');
         } else {
-          this.remolveLockScrool();
+          this.removeLockScrool();
         }
       }
     }
   },
   deactivated() {
-    this.remolveLockScroll();
+    this.removeLockScroll();
   },
   destroyed() {
-    this.remolveLockScroll();
+    this.removeLockScroll();
   },
   methods: {
-    remolveLockScroll() {
+    removeLockScroll() {
       document.body.classList.remove('nut-overflow-hidden');
     },
     isHighlight(item) {

+ 3 - 0
src/packages/address/address.vue

@@ -241,6 +241,7 @@ export default {
         calBack.next = this.tabName[this.tabIndex];
         calBack.value = item;
         this.$emit('onChange', calBack);
+        this.$emit('on-change', calBack);
       } else {
         this.handClose();
       }
@@ -308,6 +309,7 @@ export default {
         this.$emit('close', res);
       } else {
         this.$emit('closeMask', { closeWay: this.closeWay });
+        this.$emit('close-mask', { closeWay: this.closeWay });
       }
 
       setTimeout(() => {
@@ -345,6 +347,7 @@ export default {
       this.initAddress();
 
       this.$emit('switchModule', { type: this.showModule });
+      this.$emit('switch-module', { type: this.showModule });
     }
   }
 };

+ 56 - 47
src/packages/countup/countup.scss

@@ -1,50 +1,59 @@
-.nut-countup{
-    display:inline-block;
-    width: 100%;
-    padding:5px;
-    color: #000;
-	font-weight:bold;
-	// text-align:center;
-    .run-number{
-        margin: 0 auto;
-        padding: 0;
-        overflow: hidden;
-        height: 50px;
-        line-height: 50px;
-        text-align: center;
-        font-weight: bold;
-        position: relative;
-        li {
-            position: absolute;
-            transition: none;
-            // transition: all linear .1s;
-            // animation: myMove 1s linear infinite;
-            // animation-fill-mode: forwards;
-            // @keyframes myMove {
-            //     0% {
-            //       transform: translateY(0);
-            //     }
-            //     100% {
-            //       transform: translateY(-50px);
-            //     }
-            // }
-            span {
-                display: block;
-            }
-        }
-    }
-    .pointstyl {
-        position: absolute;
+.nut-countup {
+  display: inline-block;
+  width: 100%;
+  padding: 5px;
+  color: #000;
+  font-weight: bold;
+  // text-align:center;
+  .run-number {
+    margin: 0 auto;
+    padding: 0;
+    overflow: hidden;
+    height: 50px;
+    line-height: 50px;
+    text-align: center;
+    font-weight: bold;
+    position: relative;
+    li {
+      position: absolute;
+      transition: none;
+      // transition: all linear .1s;
+      // animation: myMove 1s linear infinite;
+      // animation-fill-mode: forwards;
+      // @keyframes myMove {
+      //     0% {
+      //       transform: translateY(0);
+      //     }
+      //     100% {
+      //       transform: translateY(-50px);
+      //     }
+      // }
+      span {
         display: block;
+      }
+    }
+  }
+  .pointstyl {
+    position: absolute;
+    display: block;
+  }
+  .run-number-machine-img {
+    overflow: hidden;
+    li {
+      float: left;
+      background-position: center 0;
+      background-repeat: repeat-y;
+      background-attachment: scroll;
     }
-    .run-number-img {
-        position: relative;
-        li {
-            position: absolute;
-            transition: none;
-            display: inline-block;
-            background-position: 0 0;
-            background-repeat: no-repeat;
-        }
+  }
+  .run-number-img {
+    position: relative;
+    li {
+      position: absolute;
+      transition: none;
+      display: inline-block;
+      background-position: 0 0;
+      background-repeat: no-repeat;
     }
-}
+  }
+}

+ 166 - 65
src/packages/countup/countup.vue

@@ -1,32 +1,52 @@
 <template>
   <div class="nut-countup">
     <template v-if="customBgImg != ''">
-      <ul class="run-number-img" :style="{ height: numHeight + 'px' }">
-        <li
-          class="run-number-img-li"
-          v-for="(val, index) of num_total_len"
-          :key="'cImg' + index"
-          :style="{
-            width: numWidth + 'px',
-            height: numHeight + 'px',
-            left: numWidth * (index > num_total_len - pointNum - 1 ? (index == num_total_len - pointNum ? index * 1.5 : index * 1.3) : index) + 'px',
-            backgroundImage: 'url(' + customBgImg + ')',
-            backgroundPosition: '0 ' + -(String(relNum)[index] * numHeight + customSpacNum * String(relNum)[index]) + 'px',
-            transition: 'all linear ' + during / 10 + 'ms'
-          }"
-        ></li>
-        <div
-          v-if="pointNum > 0"
-          class="pointstyl"
-          :style="{
-            width: numWidth / 2 + 'px',
-            bottom: 0,
-            left: numWidth * (num_total_len - pointNum) * 1.1 + 'px',
-            fontSize: '30px'
-          }"
-          >.</div
-        >
-      </ul>
+      <template v-if="type == 'machine'">
+        <ul class="run-number-machine-img" :style="{ height: numHeight + 'px' }">
+          <li
+            class="run-number-machine-img-li"
+            ref="run-number-machine-img-li"
+            v-for="(val, index) of machineNum"
+            :key="'mImg' + index"
+            :style="{
+              width: numWidth + 'px',
+              height: numHeight + 'px',
+              backgroundImage: 'url(' + customBgImg + ')',
+              backgroundPositionY: prizeY[index] + 'px'
+            }"
+          ></li>
+          <!-- backgroundPositionY: prizeLevelTrun + 'px', -->
+        </ul>
+      </template>
+      <template v-else>
+        <ul class="run-number-img" :style="{ height: numHeight + 'px' }">
+          <li
+            class="run-number-img-li"
+            v-for="(val, index) of num_total_len"
+            :key="'cImg' + index"
+            :style="{
+              width: numWidth + 'px',
+              height: numHeight + 'px',
+              left:
+                numWidth * (index > num_total_len - pointNum - 1 ? (index == num_total_len - pointNum ? index * 1.5 : index * 1.3) : index) + 'px',
+              backgroundImage: 'url(' + customBgImg + ')',
+              backgroundPosition: '0 ' + -(String(relNum)[index] * numHeight + customSpacNum * String(relNum)[index]) + 'px',
+              transition: 'all linear ' + during / 10 + 'ms'
+            }"
+          ></li>
+          <div
+            v-if="pointNum > 0"
+            class="pointstyl"
+            :style="{
+              width: numWidth / 2 + 'px',
+              bottom: 0,
+              left: numWidth * (num_total_len - pointNum) * 1.1 + 'px',
+              fontSize: '30px'
+            }"
+            >.</div
+          >
+        </ul>
+      </template>
     </template>
     <template v-else>
       <ul v-if="scrolling" class="run-number" :style="{ height: numHeight + 'px' }">
@@ -120,6 +140,27 @@ export default {
     customChangeNum: {
       type: Number,
       default: 1
+    },
+    // 抽奖
+    type: {
+      type: String,
+      default: ''
+    },
+    machineNum: {
+      type: Number,
+      default: 3
+    },
+    machinePrizeNum: {
+      type: Number,
+      default: 0
+    },
+    machinePrizeLevel: {
+      type: Number,
+      default: 0
+    },
+    machineTrunMore: {
+      type: Number,
+      default: 0
     }
   },
   data() {
@@ -136,7 +177,14 @@ export default {
       numberVal: 0, //数字
       num_total_len: 0, //数字长度
       relNum: 0, //去除小数点
-      customNumber: 1
+      customNumber: 1,
+      prizeLevelTrun: 0,
+      prizeY: [],
+      prizeYPrev: [],
+      // machineTransition: 'none',
+      finshMachine: 0,
+      notPrize: [],
+      typeMachine: ''
     };
   },
   computed: {},
@@ -144,12 +192,17 @@ export default {
     customChangeNum: function(n, o) {
       this.customNumber = n;
       this.countGo();
+    },
+    machinePrizeLevel: function(n, o) {
+      this.prizeLevelTrun = n;
     }
   },
   mounted() {
     if (this.startFlag) {
       if (this.scrolling || this.customBgImg) {
-        this.countGo();
+        if (this.type != 'machine') {
+          this.countGo();
+        }
       } else {
         this.countChange();
       }
@@ -228,6 +281,7 @@ export default {
         // this.endNum = this.endNum.toFixed(this.toFixed);
       }
       let { initNum, endNum, toFixed, customBgImg } = this;
+
       if (customBgImg) {
         initNum = this.customNumber;
       }
@@ -394,43 +448,90 @@ export default {
           }, that.during);
         });
       });
-
-      // that.timer = setInterval(() => {
-      //     that.relNum = that.calculation(that.relNum, Math.floor(Math.random() * (20 - 4 + 1) + 4), '+');;
-      // }, that.during)
-      // let that = this;
-      // that.clearInterval();
-      // var m = 1;
-      // if(that.pointNum!=0){
-      //     m = (Math.pow(10,that.pointNum));
-      // }
-      // that.timer = setInterval(() => {
-      // if(that.sortFlag == 'add') {
-      //     that.relNum = that.calculation(that.relNum, m * that.speed, '+');
-      //     if(that.relNum >= that.endNum*m) {
-      //         that.relNum = that.endNum*m;
-      //         that.clearInterval();
-      //         this.$emit('scroll-end');
-      //     }
-      // }else {
-      //     that.relNum = that.calculation(that.relNum, m * that.speed, '-');
-      //     if(that.relNum <= 0) {
-      //         that.relNum = String(0).repeat(that.num_total_len);
-      //         that.clearInterval();
-      //         this.$emit('scroll-end');
-      //     }
-      // }
-      // that.relNum = that.calculation(that.relNum, m * that.speed, that.sortFlag == 'add'?'+':'-');
-      // if(that.relNum <= 0) {
-      //     that.relNum = String(0).repeat(that.num_total_len);
-      //     that.clearInterval();
-      //     this.$emit('scroll-end');
-      // }
-      // if(that.relNum >= that.endNum*m) {
-      //     that.relNum = that.endNum*m;
-      //     that.clearInterval();
-      // }
-      // }, that.during);
+    },
+    // 不中奖设置随机数
+    generateRandom() {
+      this.notPrize = [];
+      while (this.notPrize.length < 3) {
+        var rand = Math.floor(Math.random() * this.machinePrizeNum + 1);
+        if (this.notPrize.indexOf(rand) == -1) {
+          this.notPrize.push(rand);
+        }
+      }
+    },
+    // 抽奖
+    machineLuck() {
+      this.machineTrunMore = this.machineTrunMore < 0 ? 0 : this.machineTrunMore;
+      let distance = this.numHeight * this.machinePrizeNum; // 所有奖品的高度,雪碧图的高度
+      if (this.prizeLevelTrun < 0) {
+        this.generateRandom();
+      }
+      for (let i = 0; i < this.machineNum; i++) {
+        setTimeout(() => {
+          let turn = distance * (i + 1 + parseFloat(this.machineTrunMore));
+          if (this.prizeYPrev.length != 0) {
+            // this.machineTransition = 'none';
+            // console.log(this.prizeYPrev[i]-(this.numHeight * this.machinePrizeNum));
+            this.$set(this.prizeY, i, this.prizeYPrev[i]);
+          }
+          let local = this.prizeYPrev[i] ? this.prizeYPrev[i] : 0;
+          let newLocation = turn + local + (this.machinePrizeNum - this.prizeLevelTrun + 1) * this.numHeight + (distance - local);
+          if (this.prizeLevelTrun < 0) {
+            newLocation += this.numHeight * this.notPrize[i];
+          }
+          this.scrollTime(
+            i,
+            // parseFloat((this.machinePrizeNum-(this.prizeLevelTrun-1))*this.numHeight + turn + local),
+            newLocation,
+            local
+          );
+        }, 500 * i);
+      }
+    },
+    scrollTime(index, total, num) {
+      // this.machineTransition = `all linear ${this.during/this.machinePrizeNum}ms`;
+      let t = setInterval(() => {
+        if (num <= total) {
+          num += 10;
+          this.$set(this.prizeY, index, parseFloat(num));
+        } else {
+          clearInterval(t);
+          t = null;
+          this.finshMachine += 1;
+          this.$set(this.prizeY, index, total);
+          // 动画未完成的时候触发了判断,需要加个延时或者监听最后一个动画执行结束,保证在动画执行结束
+          // this.$nextTick(() => {
+          //     var f = document.getElementsByClassName('run-number-machine-img-li');
+          //     f[f.length-1].addEventListener('webkitTransitionEnd', () => {
+          //         setTimeout(() => {
+          //             if(this.finshMachine == this.machineNum) {
+          //                 this.finshMachine = 0;
+          //             }
+          //         },200)
+          //     });
+          // })
+          if (this.finshMachine == this.machineNum) {
+            let distance = this.numHeight * this.machinePrizeNum;
+            this.prizeYPrev = [];
+            let prevAry = JSON.parse(JSON.stringify(this.prizeY));
+            prevAry.forEach(item => {
+              let n = item;
+              while (n > distance) {
+                n -= distance;
+              }
+              this.prizeYPrev.push(n);
+            });
+            setTimeout(() => {
+              this.finshMachine = 0;
+              if (this.prizeLevelTrun < 0) {
+                this.$emit('scroll-end', false);
+              } else {
+                this.$emit('scroll-end', true);
+              }
+            }, 130);
+          }
+        }
+      }, 30);
     }
   }
 };

+ 52 - 2
src/packages/countup/demo.vue

@@ -17,16 +17,38 @@
       <nut-countup :custom-change-num="customNumber" :custom-bg-img="bgImage" :custom-spac-num="11" :num-width="33" :num-height="47" :during="5000">
       </nut-countup>
     </div>
+    <h4>抽奖(模拟滚动抽奖)</h4>
+    <div class="show-demo">
+      <nut-countup
+        ref="countup-machine"
+        type="machine"
+        :machine-num="machineNum"
+        :machine-prize-num="5"
+        :machine-prize-level="prizeLevel"
+        :custom-bg-img="bgImage2"
+        :num-width="100"
+        :num-height="100"
+        :during="3000"
+        @scroll-end="scrollAniEnd"
+      >
+      </nut-countup>
+      <nut-button @click="startRole" :disabled="startFlag">抽奖</nut-button>
+      <nut-button @click="startRole2" :disabled="startFlag2">不中奖</nut-button>
+    </div>
   </div>
 </template>
 
 <script>
 export default {
-  components: {},
   data() {
     return {
       customNumber: 618,
-      bgImage: 'https://img10.360buyimg.com/imagetools/jfs/t1/133024/3/2251/2646/5ee7549aE8dc02d7e/de6901b6c72db396.png'
+      bgImage: 'https://img10.360buyimg.com/imagetools/jfs/t1/133024/3/2251/2646/5ee7549aE8dc02d7e/de6901b6c72db396.png',
+      startFlag: false,
+      startFlag2: false,
+      machineNum: 3,
+      bgImage2: 'https://img10.360buyimg.com/imagetools/jfs/t1/121466/20/6784/28830/5f06e7f2Edbb8998c/9bdd9e7b24dff9fe.png',
+      prizeLevel: 0
     };
   },
   methods: {
@@ -35,6 +57,29 @@ export default {
       timer = setInterval(() => {
         this.customNumber = Math.floor(Math.random() * (700 - 100 + 1) + 100);
       }, 5000);
+    },
+    startRole() {
+      this.prizeLevel = Math.floor(Math.random() * 5 + 1);
+      console.log(this.prizeLevel, '中奖');
+      this.startFlag = true;
+      // 实际运行情况下,开始滚动函数,需要放在奖品回调函数之后,如果异步操作会影响转动结果
+      setTimeout(() => {
+        this.$refs['countup-machine'].machineLuck();
+      }, 500);
+    },
+    startRole2() {
+      this.prizeLevel = -1;
+      console.log(this.prizeLevel, '不中奖');
+      this.startFlag2 = true;
+      setTimeout(() => {
+        this.$refs['countup-machine'].machineLuck();
+      }, 500);
+    },
+    scrollAniEnd(val) {
+      this.$toast.text(val ? '恭喜中奖!!!' : '很遗憾!没有中奖');
+      setTimeout(() => {
+        val ? (this.startFlag = false) : (this.startFlag2 = false);
+      }, 300);
     }
   },
   mounted() {
@@ -47,4 +92,9 @@ export default {
 .show-demo {
   background: #ffffff;
 }
+.disabledClick {
+  pointer-events: none !important;
+  cursor: not-allowed !important;
+  opacity: 0.6 !important;
+}
 </style>

+ 52 - 2
src/packages/countup/doc.md

@@ -51,6 +51,50 @@ export default {
 };
 ```
 
+## 抽奖
+
+```html
+<nut-countup
+    ref="countup-machine"
+    type="machine"
+    :machine-num="machineNum"
+    :machine-prize-num="5"
+    :machine-prize-level="prizeLevel"
+    :custom-bg-img="bgImage"
+    :num-width="100"
+    :num-height="100"
+    :during="3000"
+    @scroll-end="scrollAniEnd"
+>
+</nut-countup>
+<nut-button @click="startRole" :disabled="startFlag">抽奖</nut-button>
+```
+```javascript
+export default {
+    data() {
+        return {
+            startFlag: false,
+            machineNum: 3,
+            bgImage: 'https://img10.360buyimg.com/imagetools/jfs/t1/121466/20/6784/28830/5f06e7f2Edbb8998c/9bdd9e7b24dff9fe.png',
+            prizeLevel: 0
+        };
+    },
+    methods: {
+        startRole() {
+            this.prizeLevel = Math.floor(Math.random() * 5 + 1);
+            this.startFlag = true;
+            this.$refs['countup-machine'].machineLuck();
+        },
+        scrollAniEnd() {
+            this.$toast.text('恭喜中奖!!!');
+            setTimeout(() => {
+                this.startFlag = false;
+            }, 300);
+        }
+    }
+};
+```
+
 
 ## Prop
 
@@ -63,13 +107,19 @@ export default {
 | start-flag | 触发数字滚动的标识 | Boolean | true
 | during | 滚动一次运行时间 | Number | 1000
 | num-width | 数字宽度,常用于自定义无缝滚动 | Number | 20
-| num-height | 数字高度,常用于自定义无缝滚动 | Number | 20
+| num-height | 数字高度,常用于自定义无缝滚动(抽奖功能必传) | Number | 20
 | scrolling | 用于数字滚动展示 | Boolean | false
 | custom | 用于自定义图片数字滚动 | Boolean | false
 | custom-change-num | 要变化的数字(用于自定义图片,initNum\endNum在此无效) | Number | 1
-| custom-bg-img | 自定义图片(建议使用雪碧图实现) | - | -
+| custom-bg-img | 自定义图片(建议使用雪碧图实现,使用抽奖功能必须使用雪碧图) | - | -
 | custom-spac-num | 图片中数字之间可能会存在间距 | Number | 0
+| type | 使用抽奖功能必传“machine” | string | ''
+| machine-prize-num | 奖品个数,一共多少个奖品,必传 | number | 4
+| machine-num | 抽奖位,即滚动几个,必传 | number | 3
+| machine-prize-level | 中奖图标,图标在雪碧图中的位置 | number | 0
+| machine-trun-more | 滚动圈数 | number | 0
 
+> 说明:抽奖功能需要结合图标位置计算,故需传入雪碧图中单个图标的高度 num-height;中奖奖品根据雪碧图中的奖品位数来定位,从 1 到 N;
 
 
 

+ 16 - 0
src/packages/imagepicker/imagepicker.vue

@@ -110,6 +110,10 @@ export default {
           code: 1,
           msg: fileArr
         });
+        self.$emit('img-msg', {
+          code: 1,
+          msg: fileArr
+        });
       } else {
         fileArr.forEach((item, index) => {
           let reader = new FileReader();
@@ -126,6 +130,10 @@ export default {
           code: 2,
           msg: fileArr
         });
+        self.$emit('img-msg', {
+          code: 2,
+          msg: fileArr
+        });
       }
     },
     preview(id) {
@@ -133,6 +141,10 @@ export default {
         code: 4,
         msg: id
       });
+      this.$emit('img-msg', {
+        code: 4,
+        msg: id
+      });
     },
     deleteImg(id) {
       this.list = this.list.filter(item => item.id != id);
@@ -141,6 +153,10 @@ export default {
         code: 3,
         msg: id
       });
+      this.$emit('img-msg', {
+        code: 3,
+        msg: id
+      });
     },
     touchStart(id) {
       console.log(this.longTapTime);

+ 13 - 3
src/packages/picker/demo.vue

@@ -74,7 +74,7 @@
     <nut-picker
       :is-visible="isVisible2"
       title="请选择城市"
-      :default-value-data="defaultValueData"
+      :default-value-data="defaultValueData3"
       :list-data="custmerCityData"
       @close="switchPicker('isVisible2')"
       @confirm="setChooseValueCustmer"
@@ -188,9 +188,19 @@ export default {
           }
         ]
       ],
-      cityCustmer: null,
+      cityCustmer: '北京-海淀区',
       isVisible2: false,
-      defaultValueData1: null
+      defaultValueData1: null,
+      defaultValueData3: [
+        {
+          label: 1,
+          value: '北京'
+        },
+        {
+          label: 4,
+          value: '海淀区'
+        }
+      ]
     };
   },
   created() {

+ 7 - 0
src/packages/picker/doc.md

@@ -17,6 +17,13 @@
 ## 多列用法
 
 ```html
+<nut-cell :showIcon="true" :isLink="true" @click.native="switchPicker('isVisible0')">
+  <span slot="title">
+    <label>年月选择</label>
+  </span>
+  <span slot="sub-title">不联动多列~~~</span>
+  <div slot="desc" class="selected-option">{{ date ? date : '请选择' }}</div>
+</nut-cell>
 <nut-picker 
     :is-visible="isVisible0" 
     :list-data="listData0"

+ 11 - 1
src/packages/picker/picker-slot.vue

@@ -181,7 +181,17 @@ export default {
 
     modifyStatus(type, defaultValue) {
       defaultValue = defaultValue ? defaultValue : this.defaultValue;
-      let index = this.listData.indexOf(defaultValue);
+      let index = -1;
+      if (defaultValue && defaultValue.value) {
+        this.listData.some((item, idx) => {
+          if (item.value == defaultValue.value) {
+            index = idx;
+            return true;
+          }
+        });
+      } else {
+        index = this.listData.indexOf(defaultValue);
+      }
       this.currIndex = index === -1 ? 1 : index + 1;
       let move = index === -1 ? 0 : index * this.lineSpacing;
       type && this.setChooseValue(-move);

+ 3 - 3
src/packages/popup/demo.vue

@@ -57,14 +57,14 @@ export default {
       showRound: false,
       showIconPosition: false,
       showCloseIcon: false,
-      getContainer: false,
+      getContainer: false
     };
   },
   methods: {
     show() {
       this.isShow = true;
-    },
-  },
+    }
+  }
 };
 </script>
 <style lang="scss" scoped></style>

+ 4 - 4
src/packages/popup/overlay/overlay.vue

@@ -33,15 +33,15 @@ const overlayProps = {
   },
   overlayClass: {
     type: String,
-    default: '',
+    default: ''
   },
   overlayStyle: {
     type: Object,
-    default: () => {},
+    default: () => {}
   },
   zIndex: {
-    type: Number,
-  },
+    type: Number
+  }
 };
 export { overlayProps };
 export default {

+ 21 - 22
src/packages/popup/popup.vue

@@ -34,48 +34,48 @@ const overflowScrollReg = /scroll|auto/i;
 const popupProps = {
   position: {
     type: String,
-    default: 'center',
+    default: 'center'
   },
 
   transition: String,
 
   closeable: {
     type: Boolean,
-    default: false,
+    default: false
   },
   closeIconPosition: {
     type: String,
-    default: 'top-right',
+    default: 'top-right'
   },
   closeIcon: {
     type: String,
-    default: 'cross',
+    default: 'cross'
   },
 
   closeOnClickOverlay: {
     type: Boolean,
-    default: true,
+    default: true
   },
 
   destroyOnClose: {
     type: Boolean,
-    default: false,
+    default: false
   },
   getContainer: String,
   round: {
     type: Boolean,
-    default: false,
-  },
+    default: false
+  }
 };
 export default {
   name: 'nut-popup',
   mixins: [touchMixins],
   components: {
-    icon: Icon,
+    icon: Icon
   },
   props: {
     ...overlayProps,
-    ...popupProps,
+    ...popupProps
   },
   created() {
     this.transition ? (this.transitionName = this.transition) : (this.transitionName = `popup-slide-${this.position}`);
@@ -111,19 +111,19 @@ export default {
       val === 'center' ? (this.transitionName = 'popup-fade') : (this.transitionName = `popup-slide-${this.position}`);
     },
     getContainer: 'portal',
-    overlay: 'renderOverlay',
+    overlay: 'renderOverlay'
   },
   data() {
     return {
       showSlot: true,
       transitionName: 'popup-fade-center',
-      overlayInstant: null,
+      overlayInstant: null
     };
   },
   computed: {
     transitionDuration() {
       return this.duration ? this.duration + 's' : 'initial';
-    },
+    }
   },
 
   methods: {
@@ -131,7 +131,7 @@ export default {
       if (this.opened) {
         return;
       }
-      if(this.destroyOnClose){
+      if (this.destroyOnClose) {
         this.showSlot = true;
       }
       this.opened = true;
@@ -144,7 +144,7 @@ export default {
         overlayClass,
         overlayStyle,
         lockScroll,
-        closeOnClickOverlay,
+        closeOnClickOverlay
       };
 
       this.renderOverlay(config);
@@ -206,13 +206,12 @@ export default {
         if (!overlayManager.lockCount) {
           document.body.classList.remove('nut-overflow-hidden');
         }
-      } 
-      if(this.destroyOnClose){
-        setTimeout(()=>{
+      }
+      if (this.destroyOnClose) {
+        setTimeout(() => {
           this.showSlot = false;
-        },this.duration*1000)        
+        }, this.duration * 1000);
       }
-      
 
       overlayManager.closeOverlay(this);
       this.$emit('input', false);
@@ -235,8 +234,8 @@ export default {
       if (container && container !== el.parentNode) {
         container.appendChild(el);
       }
-    },
-  },
+    }
+  }
 };
 export { popupProps };
 </script>

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

@@ -2,29 +2,41 @@
   <div class="s-bar demo-list">
     <h4>基本用法</h4>
     <div class="demo1">
-      <nut-searchbar></nut-searchbar>
+      <nut-searchbar v-model="value"></nut-searchbar>
     </div>
     <p>右侧搜索按钮可根据需要进行配置</p>
     <div class="demo1">
-      <nut-searchbar placeText="请输入自定义文案" :hasSearchButton="false"></nut-searchbar>
+      <nut-searchbar v-model="value" placeText="请输入自定义文案" :hasSearchButton="false"></nut-searchbar>
     </div>
     <p>可配置输入框前面是否显示搜索图标、右侧是否显示文字按钮、显示文字、自定义 class</p>
     <div class="demo1">
-      <nut-searchbar placeText="ERP/姓名/邮箱" :hasIcon="true" :hasTextButton="true" customClass="search_demo"></nut-searchbar>
+      <nut-searchbar v-model="value" placeText="ERP/姓名/邮箱" :hasIcon="true" :hasTextButton="true" customClass="search_demo"></nut-searchbar>
     </div>
     <h4>事件</h4>
     <div class="demo1">
-      <nut-searchbar placeText="请输入自定义文案" @focus="focusFun" @input="inputFun" @blur="blurFun" @submit="submitFun"></nut-searchbar>
+      <nut-searchbar
+        v-model="value"
+        placeText="请输入自定义文案"
+        @focus="focusFun"
+        @input="inputFun"
+        @blur="blurFun"
+        @submit="submitFun"
+      ></nut-searchbar>
     </div>
 
     <h4>获取焦点与失去焦点</h4>
     <div class="demo1">
-      <nut-searchbar placeText="请输入自定义文案" @submit="search" @focus="focusFun" ref="myInput"></nut-searchbar>
+      <nut-searchbar v-model="value" placeText="请输入自定义文案" @submit="search" @focus="focusFun" ref="myInput"> </nut-searchbar>
     </div>
   </div>
 </template>
 <script>
 export default {
+  data() {
+    return {
+      value: ''
+    };
+  },
   mounted() {
     const th = this;
     this.$nextTick(function() {

+ 5 - 3
src/packages/searchbar/doc.md

@@ -99,6 +99,7 @@ export default {
 
 | 字段 | 说明 | 类型 | 默认值
 |----- | ----- | ----- | -----
+| vaule | 当前input值,可使用 v-model 双向绑定数据 | String | ''
 | hasIcon | 是否显示输入框前面的 icon | Boolean | false
 | placeText | 输入框 placeholder 内容 | String | '请输入内容...'
 | hasSearchButton | 是否显示右侧搜索按钮 | Boolean | true
@@ -118,6 +119,7 @@ export default {
 | 字段 | 说明 | 回调参数
 |----- | ----- | -----
 | focus | 输入框获取焦点时触发事件 | 无
-| input | 输入框输入内容时触发事件 | 无
-| blur | 输入框失去焦点时触发事件 | 无
-| submit | 默认提交事件,点击右侧Icon或文字也会触发 | 无
+| input | 输入框输入内容时触发事件 | value
+| blur | 输入框失去焦点时触发事件 | value
+| submit | 默认提交事件,点击右侧Icon或文字也会触发 | value
+| clear | 清空事件 | 无

+ 25 - 10
src/packages/searchbar/searchbar.vue

@@ -5,7 +5,7 @@
         <nut-icon type="search" v-if="hasIcon" :size="searchIconSize" :color="searchIconColor"></nut-icon>
         <input
           type="search"
-          v-model="value"
+          :value="value"
           :placeholder="placeText || nutTranslate('lang.searchbar.placeText')"
           @keyup.enter="submitFun"
           @input="inputFun"
@@ -80,6 +80,10 @@ export default {
     customClass: {
       type: String,
       default: ''
+    },
+    value: {
+      type: [String, Number],
+      default: ''
     }
   },
   components: {
@@ -87,32 +91,43 @@ export default {
   },
   data() {
     return {
-      value: '', //输入值
-      hasCloseIcon: false,
       inputFocusAnimation: false
     };
   },
-  computed: {},
+  watch: {
+    value(newValue, oldValue) {
+      this.updateValue('change');
+    }
+  },
+  computed: {
+    hasCloseIcon() {
+      return this.value ? true : false;
+    }
+  },
+  mounted() {},
   methods: {
+    updateValue(trigger = 'input') {
+      let searchInputValue = trigger == 'change' ? this.value : this.$refs.searchInput.value;
+      this.$emit(trigger, searchInputValue);
+    },
     //清空 input 输入
     clearInput() {
-      this.value = '';
-      this.hasCloseIcon = false;
+      this.$emit('clear', '');
+      this.$emit('input', '');
     },
     focusFun() {
       this.inputFocusAnimation = true;
       this.$emit('focus');
     },
     inputFun() {
-      this.hasCloseIcon = this.value ? true : false;
-      this.$emit('input', this.value);
+      this.updateValue();
     },
     blurFun() {
       this.inputFocusAnimation = false;
-      this.$emit('blur', this.value);
+      this.updateValue('blur');
     },
     submitFun() {
-      this.$emit('submit', this.value);
+      this.updateValue('submit');
     },
     // 失去焦点
     blur() {

+ 1 - 1
src/packages/tabselect/doc.md

@@ -1,4 +1,4 @@
-# TabSelect 分类选择
+# TabSelect 配送时间
 
 ## 基本用法
 

+ 5 - 2
src/packages/textbox/demo.vue

@@ -3,6 +3,8 @@
     <!-- <h4>示例</h4> -->
     <h4>默认用法 支持异步回显数据</h4>
     <nut-textbox v-model="val"></nut-textbox>
+    <h4>禁用</h4>
+    <nut-textbox disabled v-model="val"></nut-textbox>
     <h4>自定义高度:100px</h4>
     <nut-textbox :txtAreaH="100" :maxNum="300" v-model="val"></nut-textbox>
 
@@ -13,7 +15,7 @@
     <nut-textbox :maxNum="100" v-model="val2"></nut-textbox>
 
     <h4>限制字数不可超出</h4>
-    <nut-textbox :switchMax="true" :maxNum="10" :txtAreaH="100" textBgColor="#efefef"></nut-textbox>
+    <nut-textbox :switchMax="true" :maxNum="10" :txtAreaH="100" textBgColor="#efefef" v-model="val3"></nut-textbox>
 
     <h4>字数超出报错</h4>
     <nut-textbox :maxNum="10" :txtAreaH="100" @errorFunc="overLength" v-model="val1"></nut-textbox>
@@ -35,7 +37,8 @@ export default {
     return {
       val: '',
       val1: '',
-      val2: '自定义数据'
+      val2: '自定义数据',
+      val3: 'ceshi'
     };
   },
   methods: {

+ 10 - 4
src/packages/textbox/doc.md

@@ -7,6 +7,11 @@
 ```html
 <nut-textbox v-model="val"></nut-textbox>
 ```
+## 禁用
+
+```html
+<nut-textbox disabled v-model="val"></nut-textbox>
+```
 
 ## 自定义高度
 
@@ -29,8 +34,8 @@
 ## 限制字数不可超出
 
 ```html
-<nut-textbox :switchMax="true" :maxNum="10" :txtAreaH="2" textBgColor="#efefef" v-model="val2">
-</nut-textbox>
+<nut-textbox :switchMax="true" :maxNum="10" :txtAreaH="100" textBgColor="#efefef" v-model="val3"></nut-textbox>
+
 ```
 
 ## 字数超出报错
@@ -82,7 +87,7 @@ export default {
 ## Prop
 
 | 字段        | 说明                                                        | 类型    | 默认值     |
-| ----------- | ----------------------------------------------------------- | ------- | ---------- |
+|-------------|-------------------------------------------------------------|---------|------------|
 | value       | 当前 input 值,可使用 v-model 双向绑定数据                  | String  | ''         |
 | txtAreaH    | 文本框高度                                                  | Number  | 1rem       |
 | placeText   | 自定义 placeholder 文案提示                                 | String  | 请您在此输 |
@@ -90,10 +95,11 @@ export default {
 | switchMax   | 控制字数超出是否不可输入,注意:最大字数限制,请设置 maxNum | Boolean | false      |
 | textBgColor | 设置输入框背景色                                            | String  | #fff       |
 | limitShow   | 不显示字数限制                                              | Boolean | true       |
+| disabled    | 是否禁用                                                    | Boolean | false      |
 
 ## Event
 
 | 字段      | 说明                               | 回调参数 |
-| --------- | ---------------------------------- | -------- |
+|-----------|------------------------------------|----------|
 | errorFunc | 输入字数超过限定字数时触发事件     | --       |
 | inputFunc | 文字输入事件回调,默认传回输入文本 | --       |

+ 38 - 33
src/packages/textbox/textbox.scss

@@ -1,34 +1,39 @@
-.nut-textbox{
-	background:#fff;
-    .txt-area{
-        border: 1px solid #ececee;
-	    padding: 5px 20px 5px 10px;;
-	    position: relative;
-        &.num-none{
-            padding:10px 20px;
-        }
-        textarea{
-            resize: none;
-		    width: 100%;
-		    border: none;
-		    outline: none;
-		    margin: 0;
-		    padding: 0;
-		    background: transparent;
-            display:block;
-        }
-        span{
-            color: #666;
-		    position: absolute;
-		    right: 10px;
-		    bottom: 5px;
-		    font-size:12px;
-        }
-        &.error{
-        	border:1px solid #e2231a;
-        	span{
-        		color:#e2231a;
-        	}
-        }
+.nut-textbox {
+  background: #fff;
+  .txt-area {
+    border: 1px solid #ececee;
+    padding: 5px 20px 5px 10px;
+    position: relative;
+    &.num-none {
+      padding: 10px 20px;
     }
-}
+    textarea {
+      resize: none;
+      width: 100%;
+      border: none;
+      outline: none;
+      margin: 0;
+      padding: 0;
+      background: transparent;
+      display: block;
+    }
+    span {
+      color: #666;
+      position: absolute;
+      right: 10px;
+      bottom: 5px;
+      font-size: 12px;
+    }
+    &.error {
+      border: 1px solid #e2231a;
+      span {
+        color: #e2231a;
+      }
+    }
+    &.disabled {
+      background-color: #f5f7fa !important;
+      border-color: #e5e7ed;
+      color: #999;
+    }
+  }
+}

+ 7 - 3
src/packages/textbox/textbox.vue

@@ -1,12 +1,12 @@
 <template>
   <div class="nut-textbox">
-    <div class="txt-area" :class="{ error: errorState, 'num-none': limitShow == false }" :style="{ background: textBgColor }">
+    <div class="txt-area" :class="{ error: errorState, 'num-none': limitShow == false, disabled: disabled }" :style="{ background: textBgColor }">
       <textarea
         :placeholder="placeText"
         :style="{ height: txtAreaHeight + 'px' }"
         v-model="currentValue"
+        :disabled="disabled"
         @input="txtIptLength"
-        :switchMax="switchMax"
         :maxlength="iptMaxlength"
       ></textarea>
       <span v-show="limitShow">{{ txtNum }}/{{ maxNum }}</span>
@@ -18,9 +18,13 @@ export default {
   name: 'nut-textbox',
   props: {
     value: {
-      type: String,
+      type: [String, Number],
       default: ''
     },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
     maxNum: {
       type: [String, Number],
       default: 50

+ 1 - 1
src/packages/textinput/textinput.vue

@@ -26,7 +26,7 @@ export default {
   name: 'nut-textinput',
   props: {
     value: {
-      type: String,
+      type: [String, Number],
       default: ''
     },
     type: {

+ 0 - 14
stylelint-config.js

@@ -1,14 +0,0 @@
-module.exports = {
-  extends: ['stylelint-config-standard'],
-  rules: {
-    // 'order/properties-order': [],
-    // 'at-rule-no-unknown': null,
-    // 'number-leading-zero': null,
-    // 'no-descending-specificity': null,
-    // 'declaration-colon-newline-after': null,
-    // 'font-family-no-missing-generic-family-keyword': null
-    indentation: 'tab',
-    'number-leading-zero': null,
-    'no-empty-source': 0
-  }
-};