refactor: 简化穿搭图片生成弹框,移除风格偏好和生成记录功能
- 移除OutfitImageGenerator中的风格偏好标签功能 - 删除stylePreferences状态和相关函数 - 移除风格偏好UI界面和预设按钮 - 更新使用说明,去掉风格偏好描述 - 简化OutfitImageGenerationModal组件 - 移除穿搭图片生成记录显示功能 - 删除OutfitImageGallery组件使用 - 移除底部操作栏和记录相关参数 - 改为单列居中布局,专注生成功能 - 清理ModelDetail页面中不再使用的代码 - 移除outfitRecordsLoading状态 - 删除handleDeleteOutfitRecord函数 - 简化loadOutfitRecords函数 - 优化用户体验,界面更加简洁清爽
This commit is contained in:
parent
26353f49a7
commit
44486e5df7
|
|
@ -2,20 +2,15 @@ import React, { useEffect } from 'react';
|
|||
import { createPortal } from 'react-dom';
|
||||
import { X, Sparkles } from 'lucide-react';
|
||||
import { Model } from '../types/model';
|
||||
import { OutfitImageRecord, OutfitImageGenerationRequest } from '../types/outfitImage';
|
||||
import { OutfitImageGenerationRequest } from '../types/outfitImage';
|
||||
import { OutfitImageGenerator } from './OutfitImageGenerator';
|
||||
import { OutfitImageGallery } from './OutfitImageGallery';
|
||||
|
||||
interface OutfitImageGenerationModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
model: Model;
|
||||
outfitRecords: OutfitImageRecord[];
|
||||
onGenerate: (request: OutfitImageGenerationRequest) => Promise<void>;
|
||||
onDeleteRecord: (record: OutfitImageRecord) => Promise<void>;
|
||||
onRefreshRecords: () => Promise<void>;
|
||||
isGenerating?: boolean;
|
||||
recordsLoading?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -26,12 +21,8 @@ export const OutfitImageGenerationModal: React.FC<OutfitImageGenerationModalProp
|
|||
isOpen,
|
||||
onClose,
|
||||
model,
|
||||
outfitRecords,
|
||||
onGenerate,
|
||||
onDeleteRecord,
|
||||
onRefreshRecords,
|
||||
isGenerating = false,
|
||||
recordsLoading = false
|
||||
isGenerating = false
|
||||
}) => {
|
||||
// 键盘事件处理
|
||||
useEffect(() => {
|
||||
|
|
@ -93,50 +84,18 @@ export const OutfitImageGenerationModal: React.FC<OutfitImageGenerationModalProp
|
|||
|
||||
{/* 主要内容区域 */}
|
||||
<div className="flex-1 overflow-y-auto p-6">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 h-full">
|
||||
<div className="max-w-2xl mx-auto">
|
||||
{/* 穿搭图片生成器 */}
|
||||
<div className="space-y-6">
|
||||
<OutfitImageGenerator
|
||||
modelId={model.id}
|
||||
modelPhotos={model.photos}
|
||||
onGenerate={onGenerate}
|
||||
isGenerating={isGenerating}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 穿搭图片生成记录 */}
|
||||
<div className="space-y-6">
|
||||
<OutfitImageGallery
|
||||
records={outfitRecords}
|
||||
onDelete={onDeleteRecord}
|
||||
onRefresh={onRefreshRecords}
|
||||
loading={recordsLoading}
|
||||
/>
|
||||
</div>
|
||||
<OutfitImageGenerator
|
||||
modelId={model.id}
|
||||
modelPhotos={model.photos}
|
||||
onGenerate={onGenerate}
|
||||
isGenerating={isGenerating}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 底部操作栏(可选) */}
|
||||
<div className="flex items-center justify-between p-6 border-t border-gray-200 bg-gray-50">
|
||||
<div className="text-sm text-gray-500">
|
||||
共 {outfitRecords.length} 条生成记录
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-3">
|
||||
<button
|
||||
onClick={onRefreshRecords}
|
||||
className="px-4 py-2 text-gray-600 hover:text-gray-800 hover:bg-gray-200 rounded-lg transition-colors text-sm"
|
||||
>
|
||||
刷新记录
|
||||
</button>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="px-6 py-2 bg-gray-600 text-white rounded-lg hover:bg-gray-700 transition-colors text-sm"
|
||||
>
|
||||
关闭
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
modalRoot
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ import {
|
|||
AlertCircle,
|
||||
Image as ImageIcon,
|
||||
Wand2,
|
||||
Settings,
|
||||
Plus
|
||||
Settings
|
||||
} from 'lucide-react';
|
||||
import { ModelPhoto, PhotoType } from '../types/model';
|
||||
import { OutfitImageGenerationRequest } from '../types/outfitImage';
|
||||
|
|
@ -38,7 +37,6 @@ export const OutfitImageGenerator: React.FC<OutfitImageGeneratorProps> = ({
|
|||
const [selectedModelImageId, setSelectedModelImageId] = useState<string>('');
|
||||
const [productImages, setProductImages] = useState<string[]>([]);
|
||||
const [generationPrompt, setGenerationPrompt] = useState('');
|
||||
const [stylePreferences, setStylePreferences] = useState<string[]>([]);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [dragOver, setDragOver] = useState(false);
|
||||
|
||||
|
|
@ -125,17 +123,7 @@ export const OutfitImageGenerator: React.FC<OutfitImageGeneratorProps> = ({
|
|||
setProductImages(prev => prev.filter((_, i) => i !== index));
|
||||
}, []);
|
||||
|
||||
// 添加风格偏好
|
||||
const addStylePreference = useCallback((style: string) => {
|
||||
if (style.trim() && !stylePreferences.includes(style.trim())) {
|
||||
setStylePreferences(prev => [...prev, style.trim()]);
|
||||
}
|
||||
}, [stylePreferences]);
|
||||
|
||||
// 移除风格偏好
|
||||
const removeStylePreference = useCallback((index: number) => {
|
||||
setStylePreferences(prev => prev.filter((_, i) => i !== index));
|
||||
}, []);
|
||||
|
||||
// 处理生成请求
|
||||
const handleGenerate = useCallback(async () => {
|
||||
|
|
@ -157,7 +145,7 @@ export const OutfitImageGenerator: React.FC<OutfitImageGeneratorProps> = ({
|
|||
model_image_id: selectedModelImageId,
|
||||
product_image_paths: productImages,
|
||||
generation_prompt: generationPrompt || undefined,
|
||||
style_preferences: stylePreferences.length > 0 ? stylePreferences : undefined
|
||||
style_preferences: undefined
|
||||
};
|
||||
|
||||
await onGenerate(request);
|
||||
|
|
@ -166,12 +154,11 @@ export const OutfitImageGenerator: React.FC<OutfitImageGeneratorProps> = ({
|
|||
setSelectedModelImageId('');
|
||||
setProductImages([]);
|
||||
setGenerationPrompt('');
|
||||
setStylePreferences([]);
|
||||
} catch (error) {
|
||||
console.error('生成穿搭图片失败:', error);
|
||||
setError(`生成穿搭图片失败: ${error}`);
|
||||
}
|
||||
}, [modelId, selectedModelImageId, productImages, generationPrompt, stylePreferences, onGenerate]);
|
||||
}, [modelId, selectedModelImageId, productImages, generationPrompt, onGenerate]);
|
||||
|
||||
const canGenerate = selectedModelImageId && productImages.length > 0 && !isGenerating && !disabled;
|
||||
|
||||
|
|
@ -323,43 +310,7 @@ export const OutfitImageGenerator: React.FC<OutfitImageGeneratorProps> = ({
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* 风格偏好 */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
风格偏好标签
|
||||
</label>
|
||||
<div className="flex flex-wrap gap-2 mb-2">
|
||||
{stylePreferences.map((style, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className="inline-flex items-center px-3 py-1 bg-purple-100 text-purple-800 text-sm rounded-full"
|
||||
>
|
||||
{style}
|
||||
<button
|
||||
onClick={() => removeStylePreference(index)}
|
||||
className="ml-2 text-purple-600 hover:text-purple-800"
|
||||
disabled={disabled || isGenerating}
|
||||
>
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex space-x-2">
|
||||
{['时尚', '休闲', '商务', '运动', '甜美', '酷炫'].map((style) => (
|
||||
<button
|
||||
key={style}
|
||||
onClick={() => addStylePreference(style)}
|
||||
className="px-3 py-1 text-sm border border-gray-300 rounded-full hover:bg-gray-50 transition-colors"
|
||||
disabled={disabled || isGenerating || stylePreferences.includes(style)}
|
||||
>
|
||||
<Plus className="w-3 h-3 inline mr-1" />
|
||||
{style}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 错误提示 */}
|
||||
|
|
@ -410,7 +361,7 @@ export const OutfitImageGenerator: React.FC<OutfitImageGeneratorProps> = ({
|
|||
<ul className="space-y-1 text-xs">
|
||||
<li>• 选择一张模特的个人形象照片作为基础</li>
|
||||
<li>• 上传要搭配的商品图片(服装、配饰等)</li>
|
||||
<li>• 可选择添加生成提示词和风格偏好</li>
|
||||
<li>• 可选择添加生成提示词来指导AI生成</li>
|
||||
<li>• 点击生成按钮,AI将为您创建穿搭效果图</li>
|
||||
<li>• 生成的图片数量与上传的商品图片数量相等</li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ const ModelDetail: React.FC = () => {
|
|||
const [dashboardStats, setDashboardStats] = useState<ModelDashboardStats | null>(null);
|
||||
const [statsLoading, setStatsLoading] = useState(false);
|
||||
const [outfitRecords, setOutfitRecords] = useState<OutfitImageRecord[]>([]);
|
||||
const [outfitRecordsLoading, setOutfitRecordsLoading] = useState(false);
|
||||
|
||||
const [generatingOutfit, setGeneratingOutfit] = useState(false);
|
||||
const [activeTab, setActiveTab] = useState<TabId>('overview');
|
||||
const [dynamics] = useState<ModelDynamic[]>([]);
|
||||
|
|
@ -169,13 +169,10 @@ const ModelDetail: React.FC = () => {
|
|||
if (!id) return;
|
||||
|
||||
try {
|
||||
setOutfitRecordsLoading(true);
|
||||
const records = await OutfitImageService.getOutfitImageRecords(id);
|
||||
setOutfitRecords(records);
|
||||
} catch (err) {
|
||||
console.error('加载穿搭图片记录失败:', err);
|
||||
} finally {
|
||||
setOutfitRecordsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -196,19 +193,7 @@ const ModelDetail: React.FC = () => {
|
|||
}
|
||||
};
|
||||
|
||||
// 删除穿搭图片记录
|
||||
const handleDeleteOutfitRecord = async (record: OutfitImageRecord) => {
|
||||
try {
|
||||
await OutfitImageService.deleteOutfitImageRecord(record.id);
|
||||
|
||||
// 重新加载记录和统计信息
|
||||
await loadOutfitRecords();
|
||||
await loadDashboardStats();
|
||||
} catch (err) {
|
||||
console.error('删除穿搭图片记录失败:', err);
|
||||
setError(err as string);
|
||||
}
|
||||
};
|
||||
|
||||
// 上传照片
|
||||
const handleUploadPhotos = async () => {
|
||||
|
|
@ -563,12 +548,8 @@ const ModelDetail: React.FC = () => {
|
|||
isOpen={showOutfitModal}
|
||||
onClose={() => setShowOutfitModal(false)}
|
||||
model={model}
|
||||
outfitRecords={outfitRecords}
|
||||
onGenerate={handleGenerateOutfitImages}
|
||||
onDeleteRecord={handleDeleteOutfitRecord}
|
||||
onRefreshRecords={loadOutfitRecords}
|
||||
isGenerating={generatingOutfit}
|
||||
recordsLoading={outfitRecordsLoading}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue