2026-01-21 17:13:51 +08:00
|
|
|
<template>
|
|
|
|
|
<view
|
|
|
|
|
class="text-button"
|
2026-01-23 16:20:10 +08:00
|
|
|
:class="[
|
|
|
|
|
`text-button--${type}`,
|
|
|
|
|
{
|
|
|
|
|
'text-button--disabled': disabled,
|
|
|
|
|
'text-button--loading': loading
|
|
|
|
|
}
|
|
|
|
|
]"
|
2026-01-21 17:13:51 +08:00
|
|
|
@click="handleClick"
|
|
|
|
|
>
|
2026-01-23 16:20:10 +08:00
|
|
|
<text v-if="!loading" class="text-button__text">{{ text }}</text>
|
|
|
|
|
<view v-else class="text-button__spinner"></view>
|
2026-01-21 17:13:51 +08:00
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
text: { type: String, required: true },
|
|
|
|
|
type: { type: String, default: 'default' },
|
2026-01-23 16:20:10 +08:00
|
|
|
disabled: { type: Boolean, default: false },
|
|
|
|
|
loading: { type: Boolean, default: false }
|
2026-01-21 17:13:51 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['click'])
|
|
|
|
|
|
|
|
|
|
function handleClick() {
|
2026-01-23 16:20:10 +08:00
|
|
|
if (!props.disabled && !props.loading) {
|
2026-01-21 17:13:51 +08:00
|
|
|
emit('click')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
.text-button {
|
2026-01-23 16:20:10 +08:00
|
|
|
position: relative;
|
2026-01-21 17:13:51 +08:00
|
|
|
display: inline-flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
padding: 16rpx 32rpx;
|
|
|
|
|
border-radius: 8rpx;
|
2026-01-23 16:20:10 +08:00
|
|
|
font-size: 26rpx;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
|
|
|
|
// 涟漪效果
|
|
|
|
|
&::after {
|
|
|
|
|
content: '';
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 50%;
|
|
|
|
|
left: 50%;
|
|
|
|
|
width: 0;
|
|
|
|
|
height: 0;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
background: rgba(255, 255, 255, 0.3);
|
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
|
transition: width 0.3s, height 0.3s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:active::after {
|
|
|
|
|
width: 200%;
|
|
|
|
|
height: 200%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&__text {
|
|
|
|
|
position: relative;
|
|
|
|
|
z-index: 1;
|
|
|
|
|
}
|
2026-01-21 17:13:51 +08:00
|
|
|
|
|
|
|
|
&--default {
|
|
|
|
|
background-color: $bg-tertiary;
|
|
|
|
|
color: $text-primary;
|
2026-01-23 16:20:10 +08:00
|
|
|
border: 1rpx solid transparent;
|
2026-01-21 17:13:51 +08:00
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
background-color: $bg-secondary;
|
2026-01-23 16:20:10 +08:00
|
|
|
transform: scale(0.98);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--primary {
|
|
|
|
|
background-color: $accent;
|
|
|
|
|
color: #fff;
|
|
|
|
|
border: 1rpx solid $accent;
|
|
|
|
|
box-shadow: 0 4rpx 12rpx rgba($accent, 0.3);
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
background-color: darken($accent, 10%);
|
|
|
|
|
transform: scale(0.98);
|
|
|
|
|
box-shadow: 0 2rpx 6rpx rgba($accent, 0.3);
|
2026-01-21 17:13:51 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--danger {
|
2026-01-23 16:20:10 +08:00
|
|
|
background-color: rgba($danger, 0.15);
|
2026-01-21 17:13:51 +08:00
|
|
|
color: $danger;
|
2026-01-23 16:20:10 +08:00
|
|
|
border: 1rpx solid rgba($danger, 0.3);
|
2026-01-21 17:13:51 +08:00
|
|
|
|
|
|
|
|
&:active {
|
2026-01-23 16:20:10 +08:00
|
|
|
background-color: rgba($danger, 0.25);
|
|
|
|
|
transform: scale(0.98);
|
2026-01-21 17:13:51 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--warning {
|
2026-01-23 16:20:10 +08:00
|
|
|
background-color: rgba($warning, 0.15);
|
2026-01-21 17:13:51 +08:00
|
|
|
color: $warning;
|
2026-01-23 16:20:10 +08:00
|
|
|
border: 1rpx solid rgba($warning, 0.3);
|
2026-01-21 17:13:51 +08:00
|
|
|
|
|
|
|
|
&:active {
|
2026-01-23 16:20:10 +08:00
|
|
|
background-color: rgba($warning, 0.25);
|
|
|
|
|
transform: scale(0.98);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--success {
|
|
|
|
|
background-color: rgba($success, 0.15);
|
|
|
|
|
color: $success;
|
|
|
|
|
border: 1rpx solid rgba($success, 0.3);
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
background-color: rgba($success, 0.25);
|
|
|
|
|
transform: scale(0.98);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--info {
|
|
|
|
|
background-color: rgba($info, 0.15);
|
|
|
|
|
color: $info;
|
|
|
|
|
border: 1rpx solid rgba($info, 0.3);
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
background-color: rgba($info, 0.25);
|
|
|
|
|
transform: scale(0.98);
|
2026-01-21 17:13:51 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--disabled {
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
pointer-events: none;
|
2026-01-23 16:20:10 +08:00
|
|
|
filter: grayscale(0.5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&--loading {
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&__spinner {
|
|
|
|
|
width: 32rpx;
|
|
|
|
|
height: 32rpx;
|
|
|
|
|
border: 3rpx solid rgba(255, 255, 255, 0.3);
|
|
|
|
|
border-top-color: #fff;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
animation: spin 0.8s linear infinite;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes spin {
|
|
|
|
|
to {
|
|
|
|
|
transform: rotate(360deg);
|
2026-01-21 17:13:51 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|