feat: 为素材绑定页面添加项目筛选功能

- 添加项目筛选下拉框,支持按项目过滤素材
- 集成useProjectStore获取项目列表
- 修改loadMaterials函数支持项目ID筛选参数
- 在搜索条件变化时包含项目筛选条件
- 优化筛选UI布局,项目筛选位于绑定状态筛选之前
- 支持全部项目和特定项目的素材筛选功能
This commit is contained in:
imeepos 2025-07-15 14:23:26 +08:00
parent 7c40da1b83
commit 37cf8bb75a
1 changed files with 23 additions and 3 deletions

View File

@ -26,17 +26,20 @@ import {
MaterialModelBindingService, MaterialModelBindingService,
MaterialModelBindingStats MaterialModelBindingStats
} from '../services/materialModelBindingService'; } from '../services/materialModelBindingService';
import { useProjectStore } from '../store/projectStore';
export const MaterialModelBinding: React.FC = () => { export const MaterialModelBinding: React.FC = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const { success, error } = useNotifications(); const { success, error } = useNotifications();
const { projects, loadProjects } = useProjectStore();
const [materials, setMaterials] = useState<Material[]>([]); const [materials, setMaterials] = useState<Material[]>([]);
const [models, setModels] = useState<Model[]>([]); const [models, setModels] = useState<Model[]>([]);
const [stats, setStats] = useState<MaterialModelBindingStats | null>(null); const [stats, setStats] = useState<MaterialModelBindingStats | null>(null);
const [selectedModel, setSelectedModel] = useState<string>(''); const [selectedModel, setSelectedModel] = useState<string>('');
const [selectedProject, setSelectedProject] = useState<string>('');
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
const [filterType, setFilterType] = useState<'all' | 'bound' | 'unbound'>('all'); const [filterType, setFilterType] = useState<'all' | 'bound' | 'unbound'>('all');
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
@ -52,10 +55,10 @@ export const MaterialModelBinding: React.FC = () => {
// 当搜索条件变化时重新加载素材 // 当搜索条件变化时重新加载素材
useEffect(() => { useEffect(() => {
if (searchQuery !== '' || filterType !== 'all' || selectedModel !== '') { if (searchQuery !== '' || filterType !== 'all' || selectedModel !== '' || selectedProject !== '') {
loadMaterials(); loadMaterials();
} }
}, [searchQuery, filterType, selectedModel]); }, [searchQuery, filterType, selectedModel, selectedProject]);
const loadData = async () => { const loadData = async () => {
setLoading(true); setLoading(true);
@ -63,6 +66,7 @@ export const MaterialModelBinding: React.FC = () => {
await Promise.all([ await Promise.all([
loadMaterials(), loadMaterials(),
loadModels(), loadModels(),
loadProjects(),
loadStats(), loadStats(),
]); ]);
} catch (err) { } catch (err) {
@ -75,6 +79,7 @@ export const MaterialModelBinding: React.FC = () => {
const loadMaterials = async () => { const loadMaterials = async () => {
try { try {
const materialsData = await MaterialModelBindingService.getMaterialsByFilter({ const materialsData = await MaterialModelBindingService.getMaterialsByFilter({
projectId: selectedProject || undefined,
modelId: filterType === 'bound' ? selectedModel : undefined, modelId: filterType === 'bound' ? selectedModel : undefined,
bound: filterType === 'bound' ? true : filterType === 'unbound' ? false : undefined, bound: filterType === 'bound' ? true : filterType === 'unbound' ? false : undefined,
search: searchQuery, search: searchQuery,
@ -187,6 +192,15 @@ export const MaterialModelBinding: React.FC = () => {
})), })),
]; ];
// 获取项目选项
const getProjectOptions = () => [
{ value: '', label: '全部项目' },
...projects.map(project => ({
value: project.id,
label: project.name,
})),
];
const getFilterOptions = () => [ const getFilterOptions = () => [
{ value: 'all', label: '全部素材' }, { value: 'all', label: '全部素材' },
{ value: 'bound', label: '已绑定' }, { value: 'bound', label: '已绑定' },
@ -302,6 +316,12 @@ export const MaterialModelBinding: React.FC = () => {
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<Filter className="w-4 h-4 text-gray-500" /> <Filter className="w-4 h-4 text-gray-500" />
<CustomSelect
value={selectedProject}
onChange={setSelectedProject}
options={getProjectOptions()}
className="min-w-[150px]"
/>
<CustomSelect <CustomSelect
value={filterType} value={filterType}
onChange={(value) => setFilterType(value as any)} onChange={(value) => setFilterType(value as any)}