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
140 lines
2.7 KiB
<script setup lang="ts">
|
|
import { ref } from 'vue'
|
|
|
|
interface FTButton {
|
|
type?: 'default' | 'primary' | 'info'
|
|
size?: 'small' | 'default' | 'large'
|
|
disabled?: boolean
|
|
loading?: boolean
|
|
clickHandle?: () => any
|
|
}
|
|
|
|
const props = withDefaults(defineProps<FTButton>(), {
|
|
type: 'default',
|
|
size: 'default',
|
|
disabled: false,
|
|
loading: false,
|
|
clickHandle: () => {},
|
|
})
|
|
|
|
const isLoading = ref(false)
|
|
|
|
async function handleClick() {
|
|
if (!props.clickHandle || isLoading.value)
|
|
return
|
|
isLoading.value = true // 进入 loading
|
|
try {
|
|
await props.clickHandle() // 执行异步操作
|
|
}
|
|
finally {
|
|
isLoading.value = false // 结束 loading
|
|
}
|
|
}
|
|
|
|
const setLoading = (loading: boolean) => {
|
|
isLoading.value = loading
|
|
}
|
|
|
|
defineExpose({
|
|
setLoading,
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="ft-button" :class="{ 'ft-button-disabled': disabled || isLoading, [`ft-button-${size}`]: true }" @click="handleClick">
|
|
<!-- 添加 loading 判断 -->
|
|
<div v-show="disabled || isLoading" class="my-button-shadow" /> <!-- 添加 loading 判断 -->
|
|
<div
|
|
class="my-button" :class="{
|
|
[`my-button-${type}`]: true,
|
|
[`my-button-${size}`]: true,
|
|
'button-disabled': disabled || isLoading, // 添加 loading 判断
|
|
}"
|
|
>
|
|
<el-icon v-if="isLoading" :color="type === 'default' ? '#26509C' : '#fff'">
|
|
<!-- 添加 loading 判断 -->
|
|
<Loading class="rotate-loading" /> <!-- 添加旋转类 -->
|
|
</el-icon>
|
|
<div><slot /></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.ft-button {
|
|
position: relative;
|
|
display: inline-block;
|
|
margin-right: 10px;
|
|
}
|
|
.ft-button-small {
|
|
margin-right: 5px;
|
|
}
|
|
.ft-button-disabled {
|
|
pointer-events: none;
|
|
}
|
|
.my-button-shadow {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: 100;
|
|
}
|
|
.my-button {
|
|
height: 30px;
|
|
padding: 5px 20px;
|
|
border-radius: 5px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
//width: fit-content;
|
|
position: relative;
|
|
.el-icon {
|
|
position: absolute;
|
|
left: 5px;
|
|
svg {
|
|
width: 35px;
|
|
}
|
|
}
|
|
}
|
|
.button-disabled {
|
|
opacity: 0.5;
|
|
}
|
|
.my-button-small {
|
|
height: 25px;
|
|
font-size: 12px;
|
|
padding: 3px 15px;
|
|
.el-icon {
|
|
position: absolute;
|
|
left: 3px;
|
|
svg {
|
|
width: 25px;
|
|
}
|
|
}
|
|
}
|
|
.my-button-default {
|
|
background: #fff;
|
|
color: $primary-color;
|
|
border: 1px solid $primary-color;
|
|
}
|
|
.my-button-primary {
|
|
background: $primary-color;
|
|
color: #fff;
|
|
border: 1px solid $primary-color;
|
|
}
|
|
|
|
.my-button-info {
|
|
background: #335AA5;
|
|
color: #fff;
|
|
border: 1px solid #335AA5;
|
|
}
|
|
|
|
.rotate-loading {
|
|
animation: spin 1s linear infinite;
|
|
}
|
|
|
|
@keyframes spin {
|
|
0% { transform: rotate(0deg); }
|
|
100% { transform: rotate(360deg); }
|
|
}
|
|
</style>
|