import React, { FC, useState, useCallback, useMemo } from "react"; import Input from "./BaseInput"; import { NumberInputProps } from "./interface"; import clsx from "clsx"; import { filterNumAndLimit, toDefaultNumber, getDecimalNumber } from "@utils/FormatNumber"; import { last, dropLast, compose, concat } from "ramda"; // 最小值 export const _NORMALIZED_MIN_ = 0; // 最大值 export const _NORMALIZED_MAX_ = 9999999999; const NumberInput: FC = props => { const [isFocus, setIsFocus] = useState(false); const { scale, value, min, max, error, proOnBlur, proOnFocus, limitInputStep, step, onChange, allowNegative, ...otherProps } = props; const onBlur = useCallback( (v: any) => { proOnBlur?.(v); setIsFocus(false); }, [proOnBlur] ); const onFocus = useCallback( (v: any) => { proOnFocus?.(v); setIsFocus(true); }, [proOnFocus] ); const onRootInputChange = useCallback( (e: any) => { let val = e?.target?.value; const numScale = toDefaultNumber(scale) ?? 8; // 输入精度验证 const iptEnterLimit = filterNumAndLimit(val, numScale); if (!iptEnterLimit) return; // 输入max验证 const numValue = toDefaultNumber(val); const numMax = toDefaultNumber(max); if (numMax && numValue > numMax) { return; } /** * 末尾修正: 比如价格BTC/USDT的为0.5 * 1.0 - 1.4 => 1.0 * 1.5 - 1.9 => 1.5 */ const stepVal = toDefaultNumber(step); if (limitInputStep && stepVal > 1) { const iptScale = getDecimalNumber(val); if (iptScale >= numScale) { const lastVal = toDefaultNumber(last(val)); const stepValNum = toDefaultNumber(last(stepVal.toString())); const lastNum = (lastVal >= stepValNum ? stepValNum : 0).toString(); val = compose((_v: string) => { return concat(_v, lastNum); }, dropLast(1))(val); } } onChange?.(val); }, [onChange, scale, max, step] ); const statusClassName = useMemo(() => { return error ? "error" : isFocus ? "focus" : ""; }, [error, isFocus]); return ( ); }; NumberInput.defaultProps = { scale: 8, value: "", min: _NORMALIZED_MIN_, max: _NORMALIZED_MAX_, step: 1 }; export { NumberInputProps } from "./interface"; export default NumberInput;