fix: 修复模板匹配结果应用时素材使用记录创建失败的问题
- 修复 create_usage_records_from_matching_result 命令参数命名问题 - 将前端调用参数从 snake_case 改为 camelCase 以匹配 Tauri 自动转换规则 - 确保模板匹配结果应用后能正确创建素材使用记录 - 遵循 Tauri 开发规范的参数命名约定
This commit is contained in:
parent
5d39ddea80
commit
31f94a51ff
|
|
@ -188,19 +188,6 @@ export const MaterialMatchingResultDialog: React.FC<MaterialMatchingResultDialog
|
||||||
<span>匹配失败 ({result.failed_segments.length})</span>
|
<span>匹配失败 ({result.failed_segments.length})</span>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
onClick={() => setActiveTab('records')}
|
|
||||||
className={`py-4 px-1 border-b-2 font-medium text-sm transition-all duration-200 ${
|
|
||||||
activeTab === 'records'
|
|
||||||
? 'border-blue-500 text-blue-600'
|
|
||||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<Users className="w-4 h-4" />
|
|
||||||
<span>匹配记录</span>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -215,9 +202,6 @@ export const MaterialMatchingResultDialog: React.FC<MaterialMatchingResultDialog
|
||||||
{activeTab === 'failures' && (
|
{activeTab === 'failures' && (
|
||||||
<FailuresTab failures={result.failed_segments} />
|
<FailuresTab failures={result.failed_segments} />
|
||||||
)}
|
)}
|
||||||
{activeTab === 'records' && (
|
|
||||||
<MatchingRecordsTab />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -547,131 +531,3 @@ const FailuresTab: React.FC<{ failures: FailedSegmentMatch[] }> = ({ failures })
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 匹配记录选项卡组件
|
|
||||||
const MatchingRecordsTab: React.FC = () => {
|
|
||||||
// 模拟匹配记录数据
|
|
||||||
const mockRecords = [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
timestamp: '2024-01-15 14:30:25',
|
|
||||||
template_name: '时尚写真模板',
|
|
||||||
project_name: '春季新品拍摄',
|
|
||||||
success_rate: 0.85,
|
|
||||||
total_segments: 24,
|
|
||||||
matched_segments: 20,
|
|
||||||
used_materials: 15,
|
|
||||||
used_models: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
timestamp: '2024-01-14 16:45:12',
|
|
||||||
template_name: '商务风格模板',
|
|
||||||
project_name: '企业形象拍摄',
|
|
||||||
success_rate: 0.92,
|
|
||||||
total_segments: 18,
|
|
||||||
matched_segments: 17,
|
|
||||||
used_materials: 12,
|
|
||||||
used_models: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3',
|
|
||||||
timestamp: '2024-01-13 10:20:08',
|
|
||||||
template_name: '休闲生活模板',
|
|
||||||
project_name: '日常生活记录',
|
|
||||||
success_rate: 0.78,
|
|
||||||
total_segments: 32,
|
|
||||||
matched_segments: 25,
|
|
||||||
used_materials: 20,
|
|
||||||
used_models: 4
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const getSuccessRateColor = (rate: number): string => {
|
|
||||||
if (rate >= 0.8) return 'text-green-600';
|
|
||||||
if (rate >= 0.6) return 'text-yellow-600';
|
|
||||||
return 'text-red-600';
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSuccessRateBgColor = (rate: number): string => {
|
|
||||||
if (rate >= 0.8) return 'bg-green-100';
|
|
||||||
if (rate >= 0.6) return 'bg-yellow-100';
|
|
||||||
return 'bg-red-100';
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center justify-between mb-6">
|
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-semibold text-gray-900">历史匹配记录</h3>
|
|
||||||
<p className="text-sm text-gray-600 mt-1">查看之前的素材匹配结果</p>
|
|
||||||
</div>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
共 {mockRecords.length} 条记录
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{mockRecords.length === 0 ? (
|
|
||||||
<div className="text-center py-12">
|
|
||||||
<Users className="w-16 h-16 text-gray-400 mx-auto mb-4" />
|
|
||||||
<p className="text-gray-600 text-lg font-medium">暂无匹配记录</p>
|
|
||||||
<p className="text-gray-500 text-sm mt-2">完成首次匹配后,记录将显示在这里</p>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="space-y-4">
|
|
||||||
{mockRecords.map((record) => (
|
|
||||||
<div key={record.id} className="bg-white border border-gray-200 rounded-xl p-6 shadow-sm hover:shadow-md transition-all duration-200 hover:-translate-y-1">
|
|
||||||
<div className="flex items-start justify-between mb-4">
|
|
||||||
<div className="flex-1">
|
|
||||||
<div className="flex items-center space-x-3 mb-2">
|
|
||||||
<h4 className="font-semibold text-gray-900">{record.template_name}</h4>
|
|
||||||
<span className={`px-2 py-1 rounded-full text-xs font-medium ${getSuccessRateBgColor(record.success_rate)} ${getSuccessRateColor(record.success_rate)}`}>
|
|
||||||
{(record.success_rate * 100).toFixed(1)}% 成功率
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<p className="text-sm text-gray-600 mb-1">项目: {record.project_name}</p>
|
|
||||||
<p className="text-xs text-gray-500">{record.timestamp}</p>
|
|
||||||
</div>
|
|
||||||
<div className="text-right">
|
|
||||||
<div className="text-sm text-gray-600 space-y-1">
|
|
||||||
<div>匹配: {record.matched_segments}/{record.total_segments}</div>
|
|
||||||
<div>素材: {record.used_materials} 个</div>
|
|
||||||
<div>模特: {record.used_models} 个</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 进度条 */}
|
|
||||||
<div className="mb-4">
|
|
||||||
<div className="flex items-center justify-between text-xs text-gray-600 mb-2">
|
|
||||||
<span>匹配进度</span>
|
|
||||||
<span>{record.matched_segments}/{record.total_segments}</span>
|
|
||||||
</div>
|
|
||||||
<div className="w-full bg-gray-200 rounded-full h-2">
|
|
||||||
<div
|
|
||||||
className={`h-2 rounded-full transition-all duration-300 ${
|
|
||||||
record.success_rate >= 0.8 ? 'bg-gradient-to-r from-green-500 to-green-600' :
|
|
||||||
record.success_rate >= 0.6 ? 'bg-gradient-to-r from-yellow-500 to-yellow-600' :
|
|
||||||
'bg-gradient-to-r from-red-500 to-red-600'
|
|
||||||
}`}
|
|
||||||
style={{ width: `${record.success_rate * 100}%` }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 操作按钮 */}
|
|
||||||
<div className="flex items-center justify-end space-x-2">
|
|
||||||
<button className="text-xs text-blue-600 hover:text-blue-700 font-medium px-3 py-1 rounded-md hover:bg-blue-50 transition-colors">
|
|
||||||
查看详情
|
|
||||||
</button>
|
|
||||||
<button className="text-xs text-gray-600 hover:text-gray-700 font-medium px-3 py-1 rounded-md hover:bg-gray-50 transition-colors">
|
|
||||||
重新应用
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export const TabNavigation: React.FC<TabNavigationProps> = ({
|
||||||
className = '',
|
className = '',
|
||||||
}) => {
|
}) => {
|
||||||
const getTabClasses = (tab: TabItem, isActive: boolean) => {
|
const getTabClasses = (tab: TabItem, isActive: boolean) => {
|
||||||
const baseClasses = 'inline-flex items-center gap-2 font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2';
|
const baseClasses = 'inline-flex items-center gap-2 font-medium';
|
||||||
|
|
||||||
// 尺寸样式
|
// 尺寸样式
|
||||||
const sizeClasses = {
|
const sizeClasses = {
|
||||||
|
|
|
||||||
|
|
@ -304,6 +304,8 @@ export const TemplateMatchingResultDetailModal: React.FC<TemplateMatchingResultD
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
activeTab={activeTab}
|
activeTab={activeTab}
|
||||||
onTabChange={setActiveTab}
|
onTabChange={setActiveTab}
|
||||||
|
variant="underline"
|
||||||
|
className='px-4'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 标签页内容 */}
|
{/* 标签页内容 */}
|
||||||
|
|
|
||||||
|
|
@ -404,10 +404,10 @@ export const ProjectDetails: React.FC = () => {
|
||||||
if (savedResult && typeof savedResult === 'object' && 'id' in savedResult) {
|
if (savedResult && typeof savedResult === 'object' && 'id' in savedResult) {
|
||||||
try {
|
try {
|
||||||
await invoke('create_usage_records_from_matching_result', {
|
await invoke('create_usage_records_from_matching_result', {
|
||||||
project_id: project?.id,
|
projectId: project?.id,
|
||||||
template_id: currentMatchingBinding.binding.template_id,
|
templateId: currentMatchingBinding.binding.template_id,
|
||||||
binding_id: currentMatchingBinding.binding.id,
|
bindingId: currentMatchingBinding.binding.id,
|
||||||
template_matching_result_id: (savedResult as any).id,
|
templateMatchingResultId: (savedResult as any).id,
|
||||||
matches: result.matches
|
matches: result.matches
|
||||||
});
|
});
|
||||||
console.log('素材使用记录创建成功');
|
console.log('素材使用记录创建成功');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue