gaoluyang
3 天以前 92230c9a97dc9ce9df3313d11d26999c04bb6b26
src/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,268 @@
<template>
   <view class="uni-badge--x">
      <slot />
      <text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
         class="uni-badge" @click="onClick()">{{displayValue}}</text>
   </view>
</template>
<script>
   /**
    * Badge æ•°å­—è§’æ ‡
    * @description æ•°å­—角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
    * @tutorial https://ext.dcloud.net.cn/plugin?id=21
    * @property {String} text è§’标内容
    * @property {String} size = [normal|small] è§’标内容
    * @property {String} type = [info|primary|success|warning|error] é¢œè‰²ç±»åž‹
    *    @value info ç°è‰²
    *    @value primary è“è‰²
    *    @value success ç»¿è‰²
    *    @value warning é»„色
    *    @value error çº¢è‰²
    * @property {String} inverted = [true|false] æ˜¯å¦æ— éœ€èƒŒæ™¯é¢œè‰²
    * @property {Number} maxNum å±•示封顶的数字值,超过 99 æ˜¾ç¤º 99+
    * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] å¼€å¯ç»å¯¹å®šä½, è§’标将定位到其包裹的标签的四角上
    *    @value rightTop å³ä¸Š
    *    @value rightBottom å³ä¸‹
    *    @value leftTop å·¦ä¸Š
    *    @value leftBottom å·¦ä¸‹
    * @property {Array[number]} offset   è·å®šä½è§’中心点的偏移量,只有存在 absolute å±žæ€§æ—¶æœ‰æ•ˆï¼Œä¾‹å¦‚:[-10, -10] è¡¨ç¤ºå‘外偏移 10px,[10, 10] è¡¨ç¤ºå‘ absolute æŒ‡å®šçš„内偏移 10px
    * @property {String} isDot = [true|false] æ˜¯å¦æ˜¾ç¤ºä¸ºä¸€ä¸ªå°ç‚¹
    * @event {Function} click ç‚¹å‡» Badge è§¦å‘事件
    * @example <uni-badge text="1"></uni-badge>
    */
   export default {
      name: 'UniBadge',
      emits: ['click'],
      props: {
         type: {
            type: String,
            default: 'error'
         },
         inverted: {
            type: Boolean,
            default: false
         },
         isDot: {
            type: Boolean,
            default: false
         },
         maxNum: {
            type: Number,
            default: 99
         },
         absolute: {
            type: String,
            default: ''
         },
         offset: {
            type: Array,
            default () {
               return [0, 0]
            }
         },
         text: {
            type: [String, Number],
            default: ''
         },
         size: {
            type: String,
            default: 'small'
         },
         customStyle: {
            type: Object,
            default () {
               return {}
            }
         }
      },
      data() {
         return {};
      },
      computed: {
         width() {
            return String(this.text).length * 8 + 12
         },
         classNames() {
            const {
               inverted,
               type,
               size,
               absolute
            } = this
            return [
               inverted ? 'uni-badge--' + type + '-inverted' : '',
               'uni-badge--' + type,
               'uni-badge--' + size,
               absolute ? 'uni-badge--absolute' : ''
            ].join(' ')
         },
         positionStyle() {
            if (!this.absolute) return {}
            let w = this.width / 2,
               h = 10
            if (this.isDot) {
               w = 5
               h = 5
            }
            const x = `${- w  + this.offset[0]}px`
            const y = `${- h + this.offset[1]}px`
            const whiteList = {
               rightTop: {
                  right: x,
                  top: y
               },
               rightBottom: {
                  right: x,
                  bottom: y
               },
               leftBottom: {
                  left: x,
                  bottom: y
               },
               leftTop: {
                  left: x,
                  top: y
               }
            }
            const match = whiteList[this.absolute]
            return match ? match : whiteList['rightTop']
         },
         dotStyle() {
            if (!this.isDot) return {}
            return {
               width: '10px',
               minWidth: '0',
               height: '10px',
               padding: '0',
               borderRadius: '10px'
            }
         },
         displayValue() {
            const {
               isDot,
               text,
               maxNum
            } = this
            return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
         }
      },
      methods: {
         onClick() {
            this.$emit('click');
         }
      }
   };
</script>
<style lang="scss" >
   $uni-primary: #2979ff !default;
   $uni-success: #4cd964 !default;
   $uni-warning: #f0ad4e !default;
   $uni-error: #dd524d !default;
   $uni-info: #909399 !default;
   $bage-size: 12px;
   $bage-small: scale(0.8);
   .uni-badge--x {
      /* #ifdef APP-NVUE */
      // align-self: flex-start;
      /* #endif */
      /* #ifndef APP-NVUE */
      display: inline-block;
      /* #endif */
      position: relative;
   }
   .uni-badge--absolute {
      position: absolute;
   }
   .uni-badge--small {
      transform: $bage-small;
      transform-origin: center center;
   }
   .uni-badge {
      /* #ifndef APP-NVUE */
      display: flex;
      overflow: hidden;
      box-sizing: border-box;
      /* #endif */
      justify-content: center;
      flex-direction: row;
      height: 20px;
      min-width: 20px;
      padding: 0 4px;
      line-height: 18px;
      color: #fff;
      border-radius: 100px;
      background-color: $uni-info;
      background-color: transparent;
      border: 1px solid #fff;
      text-align: center;
      font-family: 'Helvetica Neue', Helvetica, sans-serif;
      font-feature-settings: "tnum";
      font-size: $bage-size;
      /* #ifdef H5 */
      z-index: 999;
      cursor: pointer;
      /* #endif */
      &--info {
         color: #fff;
         background-color: $uni-info;
      }
      &--primary {
         background-color: $uni-primary;
      }
      &--success {
         background-color: $uni-success;
      }
      &--warning {
         background-color: $uni-warning;
      }
      &--error {
         background-color: $uni-error;
      }
      &--inverted {
         padding: 0 5px 0 0;
         color: $uni-info;
      }
      &--info-inverted {
         color: $uni-info;
         background-color: transparent;
      }
      &--primary-inverted {
         color: $uni-primary;
         background-color: transparent;
      }
      &--success-inverted {
         color: $uni-success;
         background-color: transparent;
      }
      &--warning-inverted {
         color: $uni-warning;
         background-color: transparent;
      }
      &--error-inverted {
         color: $uni-error;
         background-color: transparent;
      }
   }
</style>