fs-badge.vue 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. <template>
  2. <view class="fs-badge">
  3. <slot></slot>
  4. <view
  5. v-if="dot"
  6. class="fs-badge-dot"
  7. :class="['bg-' + bgColorType, {absolute: slots.default}]"
  8. :style="{
  9. backgroundColor: bgColor
  10. }">
  11. </view>
  12. <view
  13. v-else
  14. class="fs-badge-count"
  15. :class="['bg-' + bgColorType, {absolute: slots.default}]"
  16. :style="{
  17. backgroundColor: bgColor
  18. }">
  19. <slot name="count">{{value}}</slot>
  20. </view>
  21. </view>
  22. </template>
  23. <script setup>
  24. import { computed, useSlots } from 'vue'
  25. const props = defineProps({
  26. dot: Boolean,
  27. count: Number,
  28. bgColor: String,
  29. bgColorType: {
  30. type: String,
  31. default: 'danger',
  32. validator(value) {
  33. return ['primary', 'success', 'info', 'warning', 'danger'].includes(value)
  34. }
  35. }
  36. })
  37. const value = computed(() => props.count > 99 ? '99+' : props.count)
  38. const slots = useSlots()
  39. </script>
  40. <style lang="scss" scoped>
  41. .fs-badge {
  42. position: relative;
  43. display: inline-block;
  44. vertical-align: middle;
  45. &-dot {
  46. width: 16rpx;
  47. height: 16rpx;
  48. border-radius: 50%;
  49. top: -8rpx;
  50. right: -8rpx;
  51. z-index: 10;
  52. }
  53. &-count {
  54. color: #fff;
  55. font-size: 12px;
  56. font-weight: 500;
  57. padding: 0 6px;
  58. line-height: 36rpx;
  59. min-width: 36rpx;
  60. border-radius: 18rpx;
  61. text-align: center;
  62. box-sizing: border-box;
  63. white-space: nowrap;
  64. z-index: 10;
  65. &.absolute{
  66. top: 0;
  67. right: 0;
  68. transform: translate(50%, -50%) scale(0.8);
  69. }
  70. }
  71. .absolute{
  72. position: absolute;
  73. }
  74. }
  75. </style>