uni-badge.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <template>
  2. <view class="uni-badge--x">
  3. <slot />
  4. <text v-if="text" :class="classNames" :style="[badgeWidth, positionStyle, customStyle, dotStyle]"
  5. class="uni-badge" @click="onClick()">{{displayValue}}</text>
  6. </view>
  7. </template>
  8. <script>
  9. /**
  10. * Badge 数字角标
  11. * @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
  12. * @tutorial https://ext.dcloud.net.cn/plugin?id=21
  13. * @property {String} text 角标内容
  14. * @property {String} size = [normal|small] 角标内容
  15. * @property {String} type = [info|primary|success|warning|error] 颜色类型
  16. * @value info 灰色
  17. * @value primary 蓝色
  18. * @value success 绿色
  19. * @value warning 黄色
  20. * @value error 红色
  21. * @property {String} inverted = [true|false] 是否无需背景颜色
  22. * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
  23. * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
  24. * @value rightTop 右上
  25. * @value rightBottom 右下
  26. * @value leftTop 左上
  27. * @value leftBottom 左下
  28. * @property {Array[number]} offset 距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
  29. * @property {String} isDot = [true|false] 是否显示为一个小点
  30. * @event {Function} click 点击 Badge 触发事件
  31. * @example <uni-badge text="1"></uni-badge>
  32. */
  33. export default {
  34. name: 'UniBadge',
  35. emits: ['click'],
  36. props: {
  37. type: {
  38. type: String,
  39. default: 'error'
  40. },
  41. inverted: {
  42. type: Boolean,
  43. default: false
  44. },
  45. isDot: {
  46. type: Boolean,
  47. default: false
  48. },
  49. maxNum: {
  50. type: Number,
  51. default: 99
  52. },
  53. absolute: {
  54. type: String,
  55. default: ''
  56. },
  57. offset: {
  58. type: Array,
  59. default () {
  60. return [0, 0]
  61. }
  62. },
  63. text: {
  64. type: [String, Number],
  65. default: ''
  66. },
  67. size: {
  68. type: String,
  69. default: 'small'
  70. },
  71. customStyle: {
  72. type: Object,
  73. default () {
  74. return {}
  75. }
  76. }
  77. },
  78. data() {
  79. return {};
  80. },
  81. computed: {
  82. width() {
  83. return String(this.text).length * 8 + 12
  84. },
  85. classNames() {
  86. const {
  87. inverted,
  88. type,
  89. size,
  90. absolute
  91. } = this
  92. return [
  93. inverted ? 'uni-badge--' + type + '-inverted' : '',
  94. 'uni-badge--' + type,
  95. 'uni-badge--' + size,
  96. absolute ? 'uni-badge--absolute' : ''
  97. ].join(' ')
  98. },
  99. positionStyle() {
  100. if (!this.absolute) return {}
  101. let w = this.width / 2,
  102. h = 10
  103. if (this.isDot) {
  104. w = 5
  105. h = 5
  106. }
  107. const x = `${- w + this.offset[0]}px`
  108. const y = `${- h + this.offset[1]}px`
  109. const whiteList = {
  110. rightTop: {
  111. right: x,
  112. top: y
  113. },
  114. rightBottom: {
  115. right: x,
  116. bottom: y
  117. },
  118. leftBottom: {
  119. left: x,
  120. bottom: y
  121. },
  122. leftTop: {
  123. left: x,
  124. top: y
  125. }
  126. }
  127. const match = whiteList[this.absolute]
  128. return match ? match : whiteList['rightTop']
  129. },
  130. badgeWidth() {
  131. return {
  132. width: `${this.width}px`
  133. }
  134. },
  135. dotStyle() {
  136. if (!this.isDot) return {}
  137. return {
  138. width: '10px',
  139. height: '10px',
  140. borderRadius: '10px'
  141. }
  142. },
  143. displayValue() {
  144. const {
  145. isDot,
  146. text,
  147. maxNum
  148. } = this
  149. return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
  150. }
  151. },
  152. methods: {
  153. onClick() {
  154. this.$emit('click');
  155. }
  156. }
  157. };
  158. </script>
  159. <style lang="scss" scoped>
  160. $uni-primary: #2979ff !default;
  161. $uni-success: #4cd964 !default;
  162. $uni-warning: #f0ad4e !default;
  163. $uni-error: #dd524d !default;
  164. $uni-info: #909399 !default;
  165. $bage-size: 12px;
  166. $bage-small: scale(0.8);
  167. .uni-badge--x {
  168. /* #ifdef APP-NVUE */
  169. // align-self: flex-start;
  170. /* #endif */
  171. /* #ifndef APP-NVUE */
  172. display: inline-block;
  173. /* #endif */
  174. position: relative;
  175. }
  176. .uni-badge--absolute {
  177. position: absolute;
  178. }
  179. .uni-badge--small {
  180. transform: $bage-small;
  181. transform-origin: center center;
  182. }
  183. .uni-badge {
  184. /* #ifndef APP-NVUE */
  185. display: flex;
  186. overflow: hidden;
  187. box-sizing: border-box;
  188. /* #endif */
  189. justify-content: center;
  190. flex-direction: row;
  191. height: 20px;
  192. line-height: 18px;
  193. color: #fff;
  194. border-radius: 100px;
  195. background-color: $uni-info;
  196. background-color: transparent;
  197. border: 1px solid #fff;
  198. text-align: center;
  199. font-family: 'Helvetica Neue', Helvetica, sans-serif;
  200. font-size: $bage-size;
  201. /* #ifdef H5 */
  202. z-index: 999;
  203. cursor: pointer;
  204. /* #endif */
  205. &--info {
  206. color: #fff;
  207. background-color: $uni-info;
  208. }
  209. &--primary {
  210. background-color: $uni-primary;
  211. }
  212. &--success {
  213. background-color: $uni-success;
  214. }
  215. &--warning {
  216. background-color: $uni-warning;
  217. }
  218. &--error {
  219. background-color: $uni-error;
  220. }
  221. &--inverted {
  222. padding: 0 5px 0 0;
  223. color: $uni-info;
  224. }
  225. &--info-inverted {
  226. color: $uni-info;
  227. background-color: transparent;
  228. }
  229. &--primary-inverted {
  230. color: $uni-primary;
  231. background-color: transparent;
  232. }
  233. &--success-inverted {
  234. color: $uni-success;
  235. background-color: transparent;
  236. }
  237. &--warning-inverted {
  238. color: $uni-warning;
  239. background-color: transparent;
  240. }
  241. &--error-inverted {
  242. color: $uni-error;
  243. background-color: transparent;
  244. }
  245. }
  246. </style>