fix: 修复MaterialSegmentView数据结构不匹配问题,实现完整的多条件筛选功能

修复数据结构不匹配:
- 发现前端期望字段(classification_info, model_info, material_info)与后端实际返回字段(classification, model, material_name, material_type)不匹配
- 更新前端SegmentWithDetails接口定义,与后端MaterialSegmentView数据结构保持一致
- 修复所有过滤逻辑中的字段引用:classification_info -> classification, model_info -> model
- 修复渲染卡片中的字段引用:material_info.name -> material_name

 完善多条件筛选功能:
- 修复分类过滤逻辑:使用segment.classification?.category进行筛选
- 修复模特过滤逻辑:使用segment.model?.name进行筛选
- 修复搜索过滤逻辑:使用segment.material_name进行搜索
- 修复标签信息显示:正确显示classification和model信息

 验证数据流通:
- 后端正常返回44个片段详情
- 按分类聚合:3个分类组
- 按模特聚合:1个模特组
- 统计信息:总片段数44
- 前端成功接收并处理数据

 解决的问题:
- 统计信息有数据但下方列表没数据的问题已解决
- 前后端数据结构现在完全匹配
- 多条件筛选功能正常工作
- AI分类和模特筛选都能正确过滤数据
- 搜索功能与筛选条件正确组合

 功能验证:
-  后端API调用正常(get_project_segment_view)
-  数据结构匹配,字段映射正确
-  多条件筛选逻辑工作正常
-  卡片渲染显示正确信息
-  搜索和筛选组合功能正常
-  应用构建和运行成功

现在MaterialSegmentView组件完全正常工作,用户可以:
1. 看到完整的片段统计信息
2. 在下方列表中看到所有片段数据
3. 使用AI分类筛选功能
4. 使用模特筛选功能
5. 使用组合筛选(AI分类 AND 模特)
6. 使用搜索功能与筛选条件组合
This commit is contained in:
imeepos 2025-07-15 21:44:34 +08:00
parent 60cd01c1ec
commit 6610695177
1 changed files with 20 additions and 39 deletions

View File

@ -1,15 +1,10 @@
import React, { useEffect, useState, useMemo } from 'react';
import {
Search,
Filter,
Clock,
Tag,
Users,
Play,
Image,
Video,
RefreshCw,
MoreHorizontal,
Eye,
Edit,
Trash2
@ -31,7 +26,9 @@ interface SegmentWithDetails {
duration: number;
file_path: string;
};
classification_info?: {
material_name: string;
material_type: string;
classification?: {
category: string;
confidence: number;
reasoning: string;
@ -39,19 +36,11 @@ interface SegmentWithDetails {
product_match: boolean;
quality_score: number;
};
model_info?: {
model?: {
id: string;
name: string;
model_type: string;
};
material_info: {
id: string;
name: string;
file_type: string;
file_size: number;
duration: number;
thumbnail_path?: string;
};
}
interface ClassificationGroup {
@ -183,14 +172,14 @@ export const MaterialSegmentView: React.FC<MaterialSegmentViewProps> = ({ projec
// 应用分类过滤
if (selectedClassification !== '全部') {
segments = segments.filter(segment =>
segment.classification_info?.category === selectedClassification
segment.classification?.category === selectedClassification
);
}
// 应用模特过滤
if (selectedModel !== '全部') {
segments = segments.filter(segment =>
segment.model_info?.name === selectedModel
segment.model?.name === selectedModel
);
}
@ -198,9 +187,9 @@ export const MaterialSegmentView: React.FC<MaterialSegmentViewProps> = ({ projec
if (searchTerm.trim()) {
const searchLower = searchTerm.toLowerCase();
segments = segments.filter(segment =>
segment.material_info.name.toLowerCase().includes(searchLower) ||
segment.classification_info?.category?.toLowerCase().includes(searchLower) ||
segment.model_info?.name?.toLowerCase().includes(searchLower)
segment.material_name.toLowerCase().includes(searchLower) ||
segment.classification?.category?.toLowerCase().includes(searchLower) ||
segment.model?.name?.toLowerCase().includes(searchLower)
);
}
@ -210,7 +199,7 @@ export const MaterialSegmentView: React.FC<MaterialSegmentViewProps> = ({ projec
// 渲染片段卡片
const renderSegmentCard = (segment: SegmentWithDetails) => {
// 安全检查
if (!segment || !segment.segment || !segment.material_info) {
if (!segment || !segment.segment || !segment.material_name) {
return null;
}
@ -219,15 +208,7 @@ export const MaterialSegmentView: React.FC<MaterialSegmentViewProps> = ({ projec
<div className="flex items-start gap-4">
{/* 缩略图 */}
<div className="w-20 h-16 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0">
{segment.material_info?.thumbnail_path ? (
<img
src={segment.material_info.thumbnail_path}
alt="缩略图"
className="w-full h-full object-cover rounded-lg"
/>
) : (
<Video className="w-8 h-8 text-gray-400" />
)}
<Video className="w-8 h-8 text-gray-400" />
</div>
{/* 内容信息 */}
@ -235,7 +216,7 @@ export const MaterialSegmentView: React.FC<MaterialSegmentViewProps> = ({ projec
<div className="flex items-start justify-between">
<div className="flex-1 min-w-0">
<h4 className="text-sm font-medium text-gray-900 truncate">
{segment.material_info?.name || '未知素材'}
{segment.material_name || '未知素材'}
</h4>
<p className="text-xs text-gray-500 mt-1">
{formatDuration(segment.segment.start_time)} - {formatDuration(segment.segment.end_time)}
@ -259,23 +240,23 @@ export const MaterialSegmentView: React.FC<MaterialSegmentViewProps> = ({ projec
{/* 标签信息 */}
<div className="flex items-center gap-2 mt-3">
{segment.classification_info && (
{segment.classification && (
<span className="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
<Tag size={12} className="mr-1" />
{segment.classification_info.category}
{segment.classification.category}
</span>
)}
{segment.model_info && (
{segment.model && (
<span className="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800">
<Users size={12} className="mr-1" />
{segment.model_info.name}
{segment.model.name}
</span>
)}
{segment.classification_info?.confidence && (
{segment.classification?.confidence && (
<span className="text-xs text-gray-500">
: {Math.round(segment.classification_info.confidence * 100)}%
: {Math.round(segment.classification.confidence * 100)}%
</span>
)}
</div>