Hair Keeper v1.0.0:一个高度集成、深度定制、约定优于配置的全栈Web应用模板,旨在保持灵活性的同时提供一套基于成熟架构的开发底座,自带身份认证、权限控制、丰富前端组件、文件上传、后台任务、智能体开发等丰富功能,提供AI开发辅助,免于纠结功能如何实现,可快速上手专注于业务逻辑

This commit is contained in:
2025-11-13 15:24:54 +08:00
commit 42be39b343
249 changed files with 38843 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
'use client'
import React from 'react'
import { Input } from '@/components/ui/input'
import { cn } from '@/lib/utils'
// 数值范围类型
export interface NumberRange {
min?: number
max?: number
}
export interface NumberRangeInputProps {
value?: NumberRange
onChange?: (value: NumberRange) => void
placeholder?: {
min?: string
max?: string
}
className?: string
disabled?: boolean
step?: number
min?: number
max?: number
}
export function NumberRangeInput({
value = {},
onChange,
placeholder = { min: '最小值', max: '最大值' },
className,
disabled = false,
step = 0.01,
min,
max
}: NumberRangeInputProps) {
const handleMinChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value
const newMin = inputValue === '' ? undefined : parseFloat(inputValue)
if (inputValue === '' || !isNaN(newMin!)) {
onChange?.({
...value,
min: newMin
})
}
}
const handleMaxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value
const newMax = inputValue === '' ? undefined : parseFloat(inputValue)
if (inputValue === '' || !isNaN(newMax!)) {
onChange?.({
...value,
max: newMax
})
}
}
return (
<div className={cn('flex items-center gap-2', className)}>
<Input
type="number"
step={step}
min={min}
max={max}
value={value.min ?? ''}
onChange={handleMinChange}
placeholder={placeholder.min}
disabled={disabled}
className="flex-1"
/>
<span className="text-muted-foreground text-sm"></span>
<Input
type="number"
step={step}
min={min}
max={max}
value={value.max ?? ''}
onChange={handleMaxChange}
placeholder={placeholder.max}
disabled={disabled}
className="flex-1"
/>
</div>
)
}