2025-11-25 16:53:19 +08:00
|
|
|
<script setup>
|
|
|
|
|
import { ref } from "vue";
|
|
|
|
|
import { debounce } from "@/util";
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
width: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: "calc(100vw - 20px)",
|
|
|
|
|
},
|
|
|
|
|
rounded: {
|
|
|
|
|
type: Number,
|
|
|
|
|
default: 45,
|
|
|
|
|
},
|
|
|
|
|
onClick: {
|
|
|
|
|
type: Function,
|
|
|
|
|
default: async () => {},
|
|
|
|
|
},
|
|
|
|
|
disabled: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false,
|
|
|
|
|
},
|
|
|
|
|
backgroundColor: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: "#fed847",
|
|
|
|
|
},
|
|
|
|
|
color: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: "#000",
|
|
|
|
|
},
|
|
|
|
|
disabledColor: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: "#757575",
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
const timer = ref(null);
|
|
|
|
|
|
|
|
|
|
const onBtnClick = debounce(async () => {
|
|
|
|
|
if (props.disabled || loading.value) return;
|
|
|
|
|
|
|
|
|
|
let loadingTimer = null;
|
|
|
|
|
loadingTimer = setTimeout(() => {
|
|
|
|
|
loading.value = true;
|
|
|
|
|
}, 300);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await props.onClick();
|
|
|
|
|
} finally {
|
|
|
|
|
clearTimeout(loadingTimer);
|
|
|
|
|
loading.value = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
2025-11-26 16:05:30 +08:00
|
|
|
<view
|
2025-11-25 16:53:19 +08:00
|
|
|
class="sbtn"
|
|
|
|
|
:style="{
|
|
|
|
|
width: width,
|
|
|
|
|
borderRadius: rounded + 'rpx',
|
|
|
|
|
backgroundColor: disabled ? disabledColor : backgroundColor,
|
|
|
|
|
color,
|
|
|
|
|
}"
|
|
|
|
|
open-type="getUserInfo"
|
|
|
|
|
@click="onBtnClick"
|
|
|
|
|
>
|
|
|
|
|
<block v-if="!loading">
|
|
|
|
|
<slot />
|
|
|
|
|
</block>
|
|
|
|
|
<block v-else>
|
|
|
|
|
<image src="../static/btn-loading.png" mode="widthFix" class="loading" />
|
|
|
|
|
</block>
|
2025-11-26 16:05:30 +08:00
|
|
|
</view>
|
2025-11-25 16:53:19 +08:00
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
.sbtn {
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
height: 88rpx;
|
|
|
|
|
line-height: 44px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
font-size: 42rpx;
|
|
|
|
|
display: flex;
|
|
|
|
|
text-align: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
overflow: initial;
|
|
|
|
|
}
|
|
|
|
|
.loading {
|
|
|
|
|
width: 25px;
|
|
|
|
|
height: 25px;
|
|
|
|
|
background-blend-mode: darken;
|
|
|
|
|
animation: rotate 1s linear infinite;
|
|
|
|
|
}
|
|
|
|
|
</style>
|