index.vue 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. }"
  31. v-if="showText && textInside && slotDefault"
  32. >
  33. <slot></slot>
  34. </div>
  35. </div>
  36. </div>
  37. <div class="nut-progress-text" v-if="showText && !textInside">
  38. <template v-if="status == 'active' || status == ''">
  39. <span :style="textStyle">{{ percentage }}{{ isShowPercentage ? '%' : '' }}</span>
  40. </template>
  41. <template v-else-if="status == 'icon'">
  42. <slot name="iconName">
  43. <Checked width="15px" height="15px" color="#439422"></Checked>
  44. </slot>
  45. </template>
  46. </div>
  47. </div>
  48. </template>
  49. <script lang="ts">
  50. import { computed, onMounted, useSlots, ref, watch } from 'vue';
  51. import { createComponent } from '@/packages/utils/create';
  52. const { create } = createComponent('progress');
  53. import { Checked } from '@nutui/icons-vue';
  54. export default create({
  55. components: { Checked },
  56. props: {
  57. percentage: {
  58. type: [Number, String],
  59. default: 0,
  60. required: true
  61. },
  62. size: {
  63. type: String,
  64. default: 'base'
  65. },
  66. status: {
  67. type: String,
  68. default: ''
  69. },
  70. strokeWidth: {
  71. type: [Number, String],
  72. default: ''
  73. },
  74. textInside: {
  75. type: Boolean,
  76. default: false
  77. },
  78. showText: {
  79. type: Boolean,
  80. default: true
  81. },
  82. strokeColor: {
  83. type: String,
  84. default: ''
  85. },
  86. textColor: {
  87. type: String,
  88. default: ''
  89. },
  90. textBackground: {
  91. type: String,
  92. default: ''
  93. },
  94. isShowPercentage: {
  95. type: Boolean,
  96. default: true
  97. }
  98. },
  99. setup(props) {
  100. const slotDefault = !!useSlots().default;
  101. const height = ref(props.strokeWidth + 'px');
  102. const progressOuter = ref();
  103. const insideText = ref();
  104. const percentage = computed(() => {
  105. return props.percentage >= 100 ? 100 : props.percentage;
  106. });
  107. const bgStyle = computed(() => {
  108. return {
  109. width: percentage.value + '%',
  110. background: props.strokeColor || ''
  111. };
  112. });
  113. const textStyle = computed(() => {
  114. return {
  115. color: props.textColor || ''
  116. };
  117. });
  118. onMounted(() => {});
  119. return {
  120. height,
  121. percentage,
  122. bgStyle,
  123. textStyle,
  124. progressOuter,
  125. insideText,
  126. slotDefault
  127. };
  128. }
  129. });
  130. </script>