'use client'; import * as React from 'react'; import { useState, useRef } from 'react'; import { Button } from '@nice/ui/components/button'; import { Popover, PopoverContent, PopoverTrigger } from '@nice/ui/components/popover'; import { Command, CommandEmpty, CommandGroup, CommandItem, CommandList, } from '@nice/ui/components/command'; import { IconChevronDown, IconCheck, IconStarFilled, IconX } from '@tabler/icons-react'; import { cn } from '@nice/ui/lib/utils'; import { Badge } from '@nice/ui/components/badge'; import { DutyLevel } from '@fenghuo/common'; // 职务等级选项定义 const DUTY_LEVEL_OPTIONS = [ { value: 3, label: DutyLevel.HIGH }, { value: 2, label: DutyLevel.MIDDLE }, { value: 1, label: DutyLevel.PRIMARY }, ]; // 职务等级选择器属性 interface DutyLevelSelectorProps { value?: number | number[]; // 支持单选和多选 onValueChange?: (value: number | number[]) => void; placeholder?: string; className?: string; disabled?: boolean; allowClear?: boolean; multiple?: boolean; // 是否支持多选 modal?: boolean; // 是否为模态模式,用于在 Dialog 中解决滚轮问题 } // 职务等级星星显示组件 function DutyLevelStars({ level }: { level: number }) { const stars = Array.from({ length: level }, (_, index) => ( )); return
{stars}
; } // 职务等级选项组件 interface DutyLevelItemProps { option: { value: number; label: string }; isSelected: boolean; onSelect: () => void; } function DutyLevelItem({ option, isSelected, onSelect }: DutyLevelItemProps) { return (
{/* 星星图标 */} {/* 等级信息 */}
{option.label}
{/* 选中状态指示 */} {isSelected && }
); } // 主组件 export function DutyLevelSelect({ value, onValueChange, placeholder = '选择职务等级', className, disabled = false, allowClear = true, multiple = false, modal = false, }: DutyLevelSelectorProps) { const [open, setOpen] = useState(false); const containerRef = useRef(null); // 获取选中的职务等级 const selectedLevels = React.useMemo(() => { if (!value) return []; const selectedValues = Array.isArray(value) ? value : [value]; return DUTY_LEVEL_OPTIONS.filter((option) => selectedValues.includes(option.value)); }, [value]); // 处理选择逻辑 const handleSelect = (levelValue: number) => { if (!onValueChange) return; if (multiple) { const currentValues = Array.isArray(value) ? value : value ? [value] : []; if (currentValues.includes(levelValue)) { // 取消选择 const newValues = currentValues.filter((val) => val !== levelValue); onValueChange(newValues); } else { // 添加选择 onValueChange([...currentValues, levelValue]); } } else { // 单选模式 onValueChange(levelValue); setOpen(false); } }; // 清除选择 const handleClear = (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); onValueChange?.(multiple ? [] : 0); }; // 处理单个职务等级移除(仅多选模式) const handleRemoveLevel = (levelValue: number, e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); if (multiple) { const currentValues = Array.isArray(value) ? value : value ? [value] : []; const newValues = currentValues.filter((val) => val !== levelValue); onValueChange?.(newValues); } }; // 渲染触发器内容 const renderTriggerContent = () => { if (selectedLevels.length === 0) { return placeholder; } if (multiple) { if (selectedLevels.length === 1) { return (
{selectedLevels[0]!.label}
); } else { return (
{selectedLevels.slice(0, 1).map((level) => (
{level.label}
handleRemoveLevel(level.value, e)} className="ml-1 hover:bg-muted-foreground/20 rounded-sm p-0.5 cursor-pointer inline-flex items-center justify-center" role="button" tabIndex={0} aria-label={`移除职务等级 ${level.label}`} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleRemoveLevel(level.value, e as any); } }} >
))} {selectedLevels.length > 1 && ( +{selectedLevels.length - 1} )}
); } } return (
{selectedLevels[0]!.label}
); }; // 检查是否选中 const isSelected = (levelValue: number) => { if (!value) return false; return Array.isArray(value) ? value.includes(levelValue) : value === levelValue; }; return (
{DUTY_LEVEL_OPTIONS.length === 0 ? ( 未找到职务等级 ) : ( {/* 多选模式下显示已选择数量 */} {multiple && selectedLevels.length > 0 && (
已选择 {selectedLevels.length} 个职务等级
)} {DUTY_LEVEL_OPTIONS.map((option) => ( handleSelect(option.value)} /> ))}
)}
); } // 导出便捷的单选和多选组件 export function SingleDutyLevelSelector( props: Omit & { onValueChange?: (value: number) => void; }, ) { const handleValueChange = (value: number | number[]) => { if (props.onValueChange && typeof value === 'number') { props.onValueChange(value); } }; return ; } export function MultipleDutyLevelSelector( props: Omit & { onValueChange?: (value: number[]) => void; }, ) { const handleValueChange = (value: number | number[]) => { if (props.onValueChange && Array.isArray(value)) { props.onValueChange(value); } }; return ; }