Files
sh-app/components/nbd-submit-bar.vue
T
2026-07-02 19:36:49 +08:00

92 lines
1.9 KiB
Vue

<template>
<view class="submit-bar">
<view
class="submit-btn"
:class="{ 'submit-btn--loading': loading }"
:style="btnStyle"
@click="handleClick"
>
<text v-if="icon" class="submit-btn__icon">{{ icon }}</text>
<text class="submit-btn__text">{{ loading ? '提交中...' : text }}</text>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
text: { type: String, default: '提交' },
icon: { type: String, default: '' },
color: { type: String, default: '#2979ff' },
loading: { type: Boolean, default: false }
})
const emit = defineEmits(['click'])
const lighten = (hex, amount = 0.25) => {
const c = hex.replace('#', '')
const r = Math.round(parseInt(c.substring(0, 2), 16) * (1 - amount) + 255 * amount)
const g = Math.round(parseInt(c.substring(2, 4), 16) * (1 - amount) + 255 * amount)
const b = Math.round(parseInt(c.substring(4, 6), 16) * (1 - amount) + 255 * amount)
return `rgb(${r},${g},${b})`
}
const btnStyle = computed(() => ({
background: `linear-gradient(135deg, ${props.color}, ${lighten(props.color)})`,
boxShadow: `0 6rpx 24rpx ${props.color}4d`
}))
const handleClick = () => {
if (!props.loading) emit('click')
}
</script>
<style lang="scss" scoped>
$primary: #2979ff;
$bg: #f4f2ee;
.submit-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
padding: 20rpx 24rpx;
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
background: linear-gradient(180deg, rgba($bg, 0) 0%, $bg 20%);
}
.submit-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 24rpx;
border-radius: 14rpx;
transition: opacity 0.2s ease, transform 0.2s ease;
&:active {
opacity: 0.9;
transform: scale(0.98);
}
&--loading {
opacity: 0.7;
pointer-events: none;
}
&__icon {
font-size: 30rpx;
color: #fff;
margin-right: 10rpx;
}
&__text {
font-size: 30rpx;
font-weight: 600;
color: #fff;
letter-spacing: 2rpx;
}
}
</style>