step.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <template>
  2. <div
  3. class="el-step"
  4. :style="style"
  5. :class="['is-' + $parent.direction]">
  6. <div
  7. class="el-step__head"
  8. :class="['is-' + currentStatus, { 'is-text': !icon }]">
  9. <div
  10. class="el-step__line"
  11. :class="['is-' + $parent.direction,{ 'is-icon': icon }]">
  12. <i class="el-step__line-inner" :style="lineStyle"></i>
  13. </div>
  14. <slot
  15. v-if="currentStatus !== 'success' && currentStatus !== 'error'"
  16. name="icon">
  17. <i v-if="icon" :class="['el-step__icon', 'el-icon-' + icon]"></i>
  18. <div v-else>{{ index + 1 }}</div>
  19. </slot>
  20. <i
  21. v-else
  22. class="el-step__icon"
  23. :class="['el-icon-' + (currentStatus === 'success' ? 'check' : 'close')]">
  24. </i>
  25. </div>
  26. <div
  27. class="el-step__main"
  28. :style="{ marginLeft: mainOffset }">
  29. <div
  30. class="el-step__title"
  31. ref="title"
  32. :class="['is-' + currentStatus]">
  33. <slot name="title">{{ title }}</slot>
  34. </div>
  35. <div
  36. class="el-step__description"
  37. :class="['is-' + currentStatus]">
  38. <slot name="description">{{ description }}</slot>
  39. </div>
  40. </div>
  41. </div>
  42. </template>
  43. <script>
  44. export default {
  45. name: 'el-step',
  46. props: {
  47. title: String,
  48. icon: String,
  49. description: String,
  50. status: {
  51. type: String,
  52. default: 'wait'
  53. }
  54. },
  55. data() {
  56. return {
  57. index: -1,
  58. style: { width: 0, height: 0 },
  59. lineStyle: { width: 0, height: 0 },
  60. mainOffset: 0,
  61. currentStatus: this.status
  62. };
  63. },
  64. created() {
  65. this.$parent.steps.push(this);
  66. },
  67. methods: {
  68. updateStatus(val) {
  69. const prevChild = this.$parent.$children[this.index - 1];
  70. if (val > this.index) {
  71. this.currentStatus = this.$parent.finishStatus;
  72. } else if (val === this.index) {
  73. this.currentStatus = this.$parent.processStatus;
  74. } else {
  75. this.currentStatus = 'wait';
  76. }
  77. if (prevChild) prevChild.calcProgress(this.currentStatus);
  78. },
  79. calcProgress(status) {
  80. let step = 100;
  81. this.lineStyle.transitionDelay = 150 * this.index + 'ms';
  82. if (status === this.$parent.processStatus) {
  83. step = 50;
  84. } else if (status === 'wait') {
  85. step = 0;
  86. this.lineStyle.transitionDelay = (-150 * this.index) + 'ms';
  87. }
  88. this.$parent.direction === 'vertical'
  89. ? this.lineStyle.height = step + '%'
  90. : this.lineStyle.width = step + '%';
  91. }
  92. },
  93. mounted() {
  94. const parent = this.$parent;
  95. const space = parent.space
  96. ? parent.space + 'px'
  97. : 100 / parent.steps.length + '%';
  98. if (parent.direction === 'horizontal') {
  99. this.style = { width: space };
  100. this.mainOffset = -this.$refs.title.getBoundingClientRect().width / 2 + 16 + 'px';
  101. } else {
  102. this.style = { height: space };
  103. }
  104. const unwatch = this.$watch('index', val => {
  105. this.$watch('$parent.active', this.updateStatus, { immediate: true });
  106. unwatch();
  107. });
  108. }
  109. };
  110. </script>