消毒机设备
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.

140 lines
2.7 KiB

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