index.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <template>
  2. <div class="nut-progress">
  3. <div
  4. class="nut-progress-outer"
  5. ref="progressOuter"
  6. :class="[showText && !textInside ? 'nut-progress-outer-part' : '', size ? 'nut-progress-' + size : '']"
  7. :style="{ height: height }"
  8. >
  9. <div :class="['nut-progress-inner', status == 'active' ? 'nut-active' : '']" :style="bgStyle">
  10. <div
  11. class="nut-progress-text nut-progress-insidetext"
  12. ref="insideText"
  13. :style="{
  14. lineHeight: height,
  15. left: `${percentage}%`,
  16. transform: `translate(-${+percentage}%,-50%)`,
  17. background: textBackground || strokeColor
  18. }"
  19. v-if="showText && textInside && !slotDefault"
  20. >
  21. <span :style="textStyle">{{ percentage }}{{ isShowPercentage ? '%' : '' }} </span>
  22. </div>
  23. <div
  24. ref="insideText"
  25. :style="{
  26. position: `absolute`,
  27. top: `50%`,
  28. left: `${percentage}%`,
  29. transform: `translate(-${+percentage}%,-50%)`,
  30. transition: 'all 0.4s'
  31. }"
  32. v-if="showText && textInside && slotDefault"
  33. >
  34. <slot></slot>
  35. </div>
  36. </div>
  37. </div>
  38. <div class="nut-progress-text" v-if="showText && !textInside">
  39. <template v-if="status == 'active' || status == ''">
  40. <span :style="textStyle">{{ percentage }}{{ isShowPercentage ? '%' : '' }}</span>
  41. </template>
  42. <template v-else-if="status == 'icon'">
  43. <nut-icon v-bind="$attrs" size="16px" :name="iconName" :color="iconColor"></nut-icon>
  44. </template>
  45. </div>
  46. </div>
  47. </template>
  48. <script lang="ts">
  49. import { computed, onMounted, useSlots, ref, watch } from 'vue';
  50. import { createComponent } from '@/packages/utils/create';
  51. const { create } = createComponent('progress');
  52. export default create({
  53. props: {
  54. percentage: {
  55. type: [Number, String],
  56. default: 0,
  57. required: true
  58. },
  59. size: {
  60. type: String,
  61. default: 'base'
  62. },
  63. status: {
  64. type: String,
  65. default: ''
  66. },
  67. strokeWidth: {
  68. type: [Number, String],
  69. default: ''
  70. },
  71. textInside: {
  72. type: Boolean,
  73. default: false
  74. },
  75. showText: {
  76. type: Boolean,
  77. default: true
  78. },
  79. strokeColor: {
  80. type: String,
  81. default: ''
  82. },
  83. textColor: {
  84. type: String,
  85. default: ''
  86. },
  87. textBackground: {
  88. type: String,
  89. default: ''
  90. },
  91. iconName: {
  92. type: String,
  93. default: 'checked'
  94. },
  95. iconColor: {
  96. type: String,
  97. default: '#439422'
  98. },
  99. isShowPercentage: {
  100. type: Boolean,
  101. default: true
  102. }
  103. },
  104. setup(props) {
  105. const slotDefault = !!useSlots().default;
  106. const height = ref(props.strokeWidth + 'px');
  107. const progressOuter = ref();
  108. const insideText = ref();
  109. const percentage = computed(() => {
  110. return props.percentage >= 100 ? 100 : props.percentage;
  111. });
  112. const bgStyle = computed(() => {
  113. return {
  114. width: percentage.value + '%',
  115. background: props.strokeColor || ''
  116. };
  117. });
  118. const textStyle = computed(() => {
  119. return {
  120. color: props.textColor || ''
  121. };
  122. });
  123. onMounted(() => {});
  124. return {
  125. height,
  126. bgStyle,
  127. textStyle,
  128. percentage,
  129. progressOuter,
  130. insideText,
  131. slotDefault
  132. };
  133. }
  134. });
  135. </script>