feat(lenticular): 新增 ManualTiltSlider 独立组件

- uniapp <slider> 包装,0..1 双向绑定
- 内置 ↺ 复位按钮
- value validator 拦截 0..1 范围外输入

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zerosaturation 2026-07-06 17:36:07 +08:00
parent c6cb55dfc0
commit 86a5fdfbb5

View File

@ -0,0 +1,85 @@
<template>
<view v-if="showReset || label" class="tilt-slider-row">
<view v-if="showReset" class="tilt-slider-reset" @tap="handleReset">
<text class="tilt-slider-reset-icon"></text>
</view>
<text v-if="label" class="tilt-slider-label">{{ label }}</text>
<slider
class="tilt-slider"
:min="min"
:max="max"
:step="step"
:value="value"
:disabled="disabled"
:activeColor="activeColor"
:backgroundColor="backgroundColor"
:show-value="false"
@change="handleChange"
/>
</view>
</template>
<script setup>
defineProps({
value: { type: Number, default: 0.5, validator: v => v >= 0 && v <= 1 },
disabled: { type: Boolean, default: false },
label: { type: String, default: '手动调节倾斜' },
showReset: { type: Boolean, default: true },
min: { type: Number, default: 0 },
max: { type: Number, default: 1 },
step: { type: Number, default: 0.01 },
activeColor: { type: String, default: '#6E7AFF' },
backgroundColor: { type: String, default: '#E5E7EB' },
})
const emit = defineEmits(['change', 'reset'])
function handleChange(e) {
const v = Number(e.detail.value)
if (!Number.isFinite(v)) {
console.warn('[ManualTiltSlider] non-finite value', e.detail.value)
return
}
if (v < 0 || v > 1) {
console.warn('[ManualTiltSlider] value out of [0,1]', v)
return
}
emit('change', v)
}
function handleReset() {
emit('reset')
}
</script>
<style scoped>
.tilt-slider-row {
display: flex;
align-items: center;
gap: 12rpx;
padding: 8rpx 16rpx;
height: 48rpx;
}
.tilt-slider-reset {
width: 32rpx;
height: 32rpx;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.tilt-slider-reset-icon {
font-size: 28rpx;
color: #6B7280;
}
.tilt-slider-label {
font-size: 12px;
color: #6B7280;
white-space: nowrap;
flex-shrink: 0;
}
.tilt-slider {
flex: 1;
min-width: 0;
}
</style>