You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
2.4 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. const props = defineProps({
  4. type: {
  5. type: String,
  6. default: 'default',
  7. },
  8. disabled: {
  9. type: Boolean,
  10. default: false,
  11. },
  12. loading: { // 添加 loading 属性
  13. type: Boolean,
  14. default: false,
  15. },
  16. clickHandle: {
  17. type: Function,
  18. required: false,
  19. },
  20. })
  21. const isLoading = ref(false)
  22. async function handleClick() {
  23. if (!props.clickHandle || isLoading.value)
  24. return
  25. isLoading.value = true // 进入 loading
  26. try {
  27. await props.clickHandle() // 执行异步操作
  28. }
  29. finally {
  30. isLoading.value = false // 结束 loading
  31. }
  32. }
  33. const setLoading = (loading: boolean) => {
  34. isLoading.value = loading
  35. }
  36. defineExpose({
  37. setLoading,
  38. })
  39. </script>
  40. <template>
  41. <div class="ft-button" :class="{ 'ft-button-disabled': disabled || isLoading }" @click="handleClick">
  42. <!-- 添加 loading 判断 -->
  43. <div v-show="disabled || isLoading" class="my-button-shadow" /> <!-- 添加 loading 判断 -->
  44. <div
  45. class="my-button" :class="{
  46. [`my-button-${type}`]: true,
  47. 'button-disabled': disabled || isLoading, // 添加 loading 判断
  48. }"
  49. >
  50. <el-icon v-if="isLoading" :color="type === 'default' ? '#26509C' : '#fff'">
  51. <!-- 添加 loading 判断 -->
  52. <Loading class="rotate-loading" /> <!-- 添加旋转类 -->
  53. </el-icon>
  54. <slot />
  55. </div>
  56. </div>
  57. </template>
  58. <style scoped lang="scss">
  59. .ft-button {
  60. position: relative;
  61. display: inline-block;
  62. margin-right: 10px;
  63. }
  64. .ft-button-disabled {
  65. pointer-events: none;
  66. }
  67. .my-button-shadow {
  68. position: absolute;
  69. width: 100%;
  70. height: 100%;
  71. z-index: 100;
  72. }
  73. .my-button {
  74. height: var(--el-button-size);
  75. padding: 5px 20px;
  76. border-radius: 5px;
  77. display: flex;
  78. align-items: center;
  79. cursor: pointer;
  80. font-size: 14px;
  81. width: fit-content;
  82. position: relative;
  83. .el-icon {
  84. position: absolute;
  85. left: 5px;
  86. svg {
  87. width: 35px;
  88. }
  89. }
  90. }
  91. .button-disabled {
  92. opacity: 0.5;
  93. }
  94. .my-button-default {
  95. background: #fff;
  96. color: $primary-color;
  97. border: 1px solid $primary-color;
  98. }
  99. .my-button-primary {
  100. background: $primary-color;
  101. color: #fff;
  102. border: 1px solid $primary-color;
  103. }
  104. .my-button-info {
  105. background: #335AA5;
  106. color: #fff;
  107. border: 1px solid #335AA5;
  108. }
  109. .rotate-loading {
  110. animation: spin 1s linear infinite;
  111. }
  112. @keyframes spin {
  113. 0% { transform: rotate(0deg); }
  114. 100% { transform: rotate(360deg); }
  115. }
  116. </style>