134 lines
4.0 KiB
TypeScript
134 lines
4.0 KiB
TypeScript
import React, { useState, useCallback } from 'react'
|
|
import { View, Text } from '@tarojs/components'
|
|
import Taro from '@tarojs/taro'
|
|
import './NTRPSlider.scss'
|
|
|
|
export interface NTRPRange {
|
|
min: number
|
|
max: number
|
|
}
|
|
|
|
// 获取NTRP显示文本的工具函数
|
|
export const getNTRPRangeText = (range: NTRPRange): string => {
|
|
if (range.min === 2.0 && range.max === 4.0) {
|
|
return '不限'
|
|
}
|
|
return `${range.min} - ${range.max}`
|
|
}
|
|
|
|
interface NTRPSliderProps {
|
|
value: NTRPRange
|
|
onChange: (range: NTRPRange) => void
|
|
title?: string
|
|
showTitle?: boolean
|
|
}
|
|
|
|
const NTRPSlider: React.FC<NTRPSliderProps> = ({
|
|
value = {
|
|
min: 1.0,
|
|
max: 5.0
|
|
},
|
|
onChange,
|
|
title = 'NTRP水平要求',
|
|
showTitle = false
|
|
}) => {
|
|
const [activeThumb, setActiveThumb] = useState<'min' | 'max' | null>(null)
|
|
|
|
// 计算滑动条位置百分比
|
|
const getSliderPercentage = useCallback((level: number) => {
|
|
return ((level - 2.0) / 2.0) * 100
|
|
}, [])
|
|
|
|
// 获取当前NTRP显示文本
|
|
const currentRangeText = getNTRPRangeText(value)
|
|
|
|
const handleSliderTouchStart = useCallback((thumb: 'min' | 'max') => {
|
|
setActiveThumb(thumb)
|
|
}, [])
|
|
|
|
const handleSliderTouchMove = useCallback((e: any) => {
|
|
if (!activeThumb) return
|
|
|
|
e.preventDefault()
|
|
const query = Taro.createSelectorQuery()
|
|
query.select('.ntrp-slider-track').boundingClientRect((rect: any) => {
|
|
if (rect && !Array.isArray(rect)) {
|
|
const touch = e.touches[0]
|
|
const relativeX = touch.clientX - rect.left
|
|
const percentage = Math.max(0, Math.min(1, relativeX / rect.width))
|
|
const level = Number((2.0 + percentage * 2.0).toFixed(1))
|
|
|
|
if (activeThumb === 'min') {
|
|
const newMin = Math.min(level, value.max - 0.1)
|
|
onChange({ min: newMin, max: value.max })
|
|
} else {
|
|
const newMax = Math.max(level, value.min + 0.1)
|
|
onChange({ min: value.min, max: newMax })
|
|
}
|
|
}
|
|
}).exec()
|
|
}, [activeThumb, value, onChange])
|
|
|
|
const handleSliderTouchEnd = useCallback(() => {
|
|
setActiveThumb(null)
|
|
}, [])
|
|
|
|
return (
|
|
<View className='ntrp-slider'>
|
|
{showTitle && (
|
|
<View className='section-title-wrapper'>
|
|
<Text className='section-title'>{title}</Text>
|
|
<Text className='section-summary'>{currentRangeText}</Text>
|
|
</View>
|
|
)}
|
|
|
|
<View className='ntrp-control-section'>
|
|
<View className='ntrp-slider-container'>
|
|
<View className='ntrp-labels'>
|
|
<Text className='ntrp-label'>2.0及以下</Text>
|
|
<Text className='ntrp-label'>4.0及以上</Text>
|
|
</View>
|
|
|
|
<View
|
|
className='ntrp-slider-track'
|
|
onTouchMove={handleSliderTouchMove}
|
|
onTouchEnd={handleSliderTouchEnd}
|
|
>
|
|
{/* 背景轨道 */}
|
|
<View className='slider-bg'></View>
|
|
|
|
{/* 选中区间 */}
|
|
<View
|
|
className='slider-range'
|
|
style={{
|
|
left: `${getSliderPercentage(value.min)}%`,
|
|
width: `${getSliderPercentage(value.max) - getSliderPercentage(value.min)}%`
|
|
}}
|
|
></View>
|
|
|
|
{/* 最小值滑块 */}
|
|
<View
|
|
className={`slider-thumb ${activeThumb === 'min' ? 'active' : ''}`}
|
|
style={{ left: `${getSliderPercentage(value.min)}%` }}
|
|
onTouchStart={() => handleSliderTouchStart('min')}
|
|
>
|
|
<View className='thumb-value'>{value.min}</View>
|
|
</View>
|
|
|
|
{/* 最大值滑块 */}
|
|
<View
|
|
className={`slider-thumb ${activeThumb === 'max' ? 'active' : ''}`}
|
|
style={{ left: `${getSliderPercentage(value.max)}%` }}
|
|
onTouchStart={() => handleSliderTouchStart('max')}
|
|
>
|
|
<View className='thumb-value'>{value.max}</View>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
export default NTRPSlider
|