(null);
const trpc = useTRPC();
// 使用 tRPC 获取专业列表
const {
data: professions = [],
isLoading,
error,
} = useQuery({
...trpc.term.findMany.queryOptions({
where: {
taxonomy: {
slug: TaxonomySlug.PROFESSION,
},
deletedAt: null,
},
orderBy: [
{ order: 'asc' },
{ name: 'asc' },
],
}),
});
// 过滤专业(根据搜索关键词)
const filteredProfessions = React.useMemo(() => {
if (!searchValue.trim()) {
return professions;
}
const searchTerm = searchValue.toLowerCase();
return professions.filter(
(profession) =>
profession.name.toLowerCase().includes(searchTerm) ||
profession.description?.toLowerCase().includes(searchTerm) ||
profession.slug.toLowerCase().includes(searchTerm),
);
}, [professions, searchValue]);
// 获取选中的专业
const selectedProfessions = React.useMemo(() => {
if (!value) return [];
const selectedIds = Array.isArray(value) ? value : [value];
return professions.filter((profession) => selectedIds.includes(profession.id));
}, [professions, value]);
// 处理选择逻辑
const handleSelect = (professionId: string) => {
if (!onValueChange) return;
if (multiple) {
const currentValues = Array.isArray(value) ? value : value ? [value] : [];
if (currentValues.includes(professionId)) {
// 取消选择
const newValues = currentValues.filter((id) => id !== professionId);
onValueChange(newValues);
} else {
// 添加选择
onValueChange([...currentValues, professionId]);
}
} else {
// 单选模式
onValueChange(professionId);
setOpen(false);
}
};
// 清除选择
const handleClear = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
onValueChange?.(multiple ? [] : '');
};
// 处理单个专业移除(仅多选模式)
const handleRemoveProfession = (professionId: string, e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
if (multiple) {
const currentValues = Array.isArray(value) ? value : value ? [value] : [];
const newValues = currentValues.filter((id) => id !== professionId);
onValueChange?.(newValues);
}
};
// 渲染触发器内容
const renderTriggerContent = () => {
if (selectedProfessions.length === 0) {
return placeholder;
}
if (multiple) {
if (selectedProfessions.length === 1) {
return selectedProfessions[0]!.name;
} else {
return (
{selectedProfessions.slice(0, 1).map((profession) => (
{profession.name}
handleRemoveProfession(profession.id, 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={`移除专业 ${profession.name}`}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleRemoveProfession(profession.id, e as any);
}
}}
>
))}
{selectedProfessions.length > 1 && (
+{selectedProfessions.length - 1}
)}
);
}
}
return selectedProfessions[0]!.name;
};
// 检查是否选中
const isSelected = (professionId: string) => {
if (!value) return false;
return Array.isArray(value) ? value.includes(professionId) : value === professionId;
};
if (error) {
console.error('加载专业列表失败:', error);
}
return (
{isLoading ? (
加载中...
) : filteredProfessions.length === 0 ? (
未找到专业
) : (
{/* 多选模式下显示已选择数量 */}
{multiple && selectedProfessions.length > 0 && (
已选择 {selectedProfessions.length} 个专业
)}
{filteredProfessions.map((profession) => (
handleSelect(profession.id)}
/>
))}
)}
);
}
// 导出便捷的单选和多选组件
export function SingleProfessionSelector(
props: Omit & {
onValueChange?: (value: string) => void;
},
) {
const handleValueChange = (value: string | string[]) => {
if (props.onValueChange && typeof value === 'string') {
props.onValueChange(value);
}
};
return ;
}
export function MultipleProfessionSelector(
props: Omit & {
onValueChange?: (value: string[]) => void;
},
) {
const handleValueChange = (value: string | string[]) => {
if (props.onValueChange && Array.isArray(value)) {
props.onValueChange(value);
}
};
return ;
}