'use client'; import { useControllableValue } from 'ahooks'; import React, { useState } from 'react'; import { cn } from '@/lib'; import Image from 'next/image'; type RateProps = { readonly?: boolean; // 0 - 10 value?: number; onChange?: (value: number) => void; } & React.HTMLAttributes; export default function Rate(props: RateProps) { const { readonly = false, ...others } = props; const [value = 0, onChange] = useControllableValue(props); const [hoveredValue, setHoveredValue] = useState(0); const readonlyRender = () => { // value 范围 0-10,每颗星代表 2 分 const fullCounts = Math.floor(value / 2); // 满星数量 const halfCount = value % 2; // 半星数量(0 或 1) const emptyCount = 5 - fullCounts - halfCount; // 空星数量 const starDoms = [ // 满星 ...Array.from({ length: fullCounts }, (_, i) => ( full star )), // 半星 ...Array.from({ length: halfCount }, (_, i) => ( half star )), // 空星 ]; return ( <> {starDoms} {value} ); }; const editRender = () => { const finalValue = hoveredValue || value; // 将 0-10 的值转换为 0-5 的星级 const starValue = finalValue / 2; return Array.from({ length: 5 }, (_, index) => { let src = '/component/star_empty.svg'; // 判断当前星星应该显示什么状态 if (index < Math.floor(starValue)) { // 满星 src = '/component/star_full.svg'; } return ( star onChange?.((index + 1) * 2)} onMouseEnter={() => setHoveredValue((index + 1) * 2)} /> ); }); }; const render = readonly ? readonlyRender : editRender; return (
setHoveredValue(0)} className={cn('flex items-center gap-1', props.className)} > {render()}
); }