修复详情替换产品图预览
This commit is contained in:
parent
378900e0da
commit
35a1b75df9
@ -88,6 +88,7 @@ export function SceneFusionView({ onBack, initialProductImage, initialProductNam
|
||||
|
||||
// 状态管理
|
||||
const [productImage, setProductImage] = useState<string | null>(null);
|
||||
const [productImagePreview, setProductImagePreview] = useState<string | null>(null);
|
||||
const [productName, setProductName] = useState<string>(initialProductName || ""); // 产品名称(如"沙发")
|
||||
const [scenes, setScenes] = useState<SceneItem[]>([]);
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
@ -97,14 +98,41 @@ export function SceneFusionView({ onBack, initialProductImage, initialProductNam
|
||||
// 文件上传 Input 引用
|
||||
const productInputRef = useRef<HTMLInputElement>(null);
|
||||
const sceneInputRef = useRef<HTMLInputElement>(null);
|
||||
const productPreviewObjectUrlRef = useRef<string | null>(null);
|
||||
|
||||
// 如果外部传入了初始产品图,则在首次挂载或传入值变化时自动带入
|
||||
const updateProductPreview = (previewUrl: string | null, isObjectUrl = false) => {
|
||||
if (productPreviewObjectUrlRef.current) {
|
||||
URL.revokeObjectURL(productPreviewObjectUrlRef.current);
|
||||
productPreviewObjectUrlRef.current = null;
|
||||
}
|
||||
setProductImagePreview(previewUrl);
|
||||
if (isObjectUrl && previewUrl) {
|
||||
productPreviewObjectUrlRef.current = previewUrl;
|
||||
}
|
||||
};
|
||||
|
||||
const clearProductImage = () => {
|
||||
setProductImage(null);
|
||||
updateProductPreview(null);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (initialProductImage) {
|
||||
setProductImage(initialProductImage);
|
||||
updateProductPreview(initialProductImage);
|
||||
}
|
||||
}, [initialProductImage]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (productPreviewObjectUrlRef.current) {
|
||||
URL.revokeObjectURL(productPreviewObjectUrlRef.current);
|
||||
productPreviewObjectUrlRef.current = null;
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 处理产品图上传
|
||||
const handleProductUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
@ -115,9 +143,23 @@ export function SceneFusionView({ onBack, initialProductImage, initialProductNam
|
||||
return;
|
||||
}
|
||||
|
||||
setProductImage(null);
|
||||
const previewUrl = URL.createObjectURL(file);
|
||||
updateProductPreview(previewUrl, true);
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
setProductImage(e.target?.result as string);
|
||||
const result = e.target?.result;
|
||||
if (typeof result === "string") {
|
||||
setProductImage(result);
|
||||
} else {
|
||||
toast.error("图片读取失败,请重试");
|
||||
clearProductImage();
|
||||
}
|
||||
};
|
||||
reader.onerror = () => {
|
||||
toast.error("图片读取失败,请重试");
|
||||
clearProductImage();
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
// 重置 input,允许重复选择同一文件
|
||||
@ -590,8 +632,8 @@ export function SceneFusionView({ onBack, initialProductImage, initialProductNam
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-base font-medium">产品图 A (必须)</Label>
|
||||
{productImage && (
|
||||
<Button variant="ghost" size="sm" onClick={() => setProductImage(null)} className="h-6 text-xs text-muted-foreground hover:text-destructive">
|
||||
{(productImagePreview || productImage) && (
|
||||
<Button variant="ghost" size="sm" onClick={clearProductImage} className="h-6 text-xs text-muted-foreground hover:text-destructive">
|
||||
清除
|
||||
</Button>
|
||||
)}
|
||||
@ -600,9 +642,9 @@ export function SceneFusionView({ onBack, initialProductImage, initialProductNam
|
||||
<div
|
||||
className={cn(
|
||||
"border-2 border-dashed rounded-lg p-4 transition-colors text-center cursor-pointer relative group",
|
||||
productImage ? "border-primary/50 bg-primary/5" : "border-muted-foreground/25 hover:border-primary/50 hover:bg-muted/50"
|
||||
(productImagePreview || productImage) ? "border-primary/50 bg-primary/5" : "border-muted-foreground/25 hover:border-primary/50 hover:bg-muted/50"
|
||||
)}
|
||||
onClick={() => !productImage && productInputRef.current?.click()}
|
||||
onClick={() => !(productImagePreview || productImage) && productInputRef.current?.click()}
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
@ -612,9 +654,9 @@ export function SceneFusionView({ onBack, initialProductImage, initialProductNam
|
||||
onChange={handleProductUpload}
|
||||
/>
|
||||
|
||||
{productImage ? (
|
||||
{(productImagePreview || productImage) ? (
|
||||
<div className="relative aspect-square w-full max-w-[200px] mx-auto">
|
||||
<img src={productImage} alt="产品图" className="w-full h-full object-contain rounded-md" />
|
||||
<img src={productImagePreview || productImage || ""} alt="产品图" className="w-full h-full object-contain rounded-md" />
|
||||
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center rounded-md">
|
||||
<Button variant="secondary" size="sm" onClick={(e) => { e.stopPropagation(); productInputRef.current?.click(); }}>
|
||||
更换图片
|
||||
@ -630,7 +672,7 @@ export function SceneFusionView({ onBack, initialProductImage, initialProductNam
|
||||
</div>
|
||||
|
||||
{/* 产品名称输入 */}
|
||||
{productImage && (
|
||||
{(productImagePreview || productImage) && (
|
||||
<div className="mt-2">
|
||||
<Input
|
||||
placeholder="产品名称(如:沙发、椅子、花瓶)"
|
||||
@ -905,4 +947,4 @@ export function SceneFusionView({ onBack, initialProductImage, initialProductNam
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user