fix: uploads
This commit is contained in:
@@ -20,6 +20,8 @@ import {
|
||||
} from 'antd';
|
||||
import {
|
||||
CloudUploadOutlined,
|
||||
CameraOutlined,
|
||||
PictureOutlined,
|
||||
ScanOutlined,
|
||||
MergeCellsOutlined,
|
||||
ApartmentOutlined,
|
||||
@@ -182,6 +184,95 @@ const Workspace: React.FC = () => {
|
||||
},
|
||||
];
|
||||
|
||||
const handleBeforeUpload = (file: File) => {
|
||||
if (!batchActiveRef.current) {
|
||||
batchActiveRef.current = true;
|
||||
batchCounterRef.current = { success: 0, failed: 0 };
|
||||
setUploadBatchItems((prev) => {
|
||||
prev.forEach((item) => {
|
||||
if (item.previewUrl) URL.revokeObjectURL(item.previewUrl);
|
||||
});
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
const localId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
||||
const previewUrl = URL.createObjectURL(file);
|
||||
setUploadingCount((c) => {
|
||||
const next = c + 1;
|
||||
message.open({
|
||||
key: 'img-upload',
|
||||
type: 'loading',
|
||||
content: `正在上传截图(队列中 ${next} 张):${file.name}`,
|
||||
duration: 0,
|
||||
});
|
||||
return next;
|
||||
});
|
||||
setUploadBatchItems((prev) => [
|
||||
...prev,
|
||||
{
|
||||
localId,
|
||||
fileName: file.name,
|
||||
fileSize: file.size,
|
||||
status: 'uploading',
|
||||
previewUrl,
|
||||
},
|
||||
]);
|
||||
uploadImages(id, [file])
|
||||
.then((uploaded) => {
|
||||
const uploadedImage = uploaded?.[0];
|
||||
setUploadBatchItems((prev) =>
|
||||
prev.map((item) =>
|
||||
item.localId === localId
|
||||
? {
|
||||
...item,
|
||||
status: 'success',
|
||||
uploadedImageId: uploadedImage?.id,
|
||||
}
|
||||
: item,
|
||||
),
|
||||
);
|
||||
batchCounterRef.current.success += 1;
|
||||
})
|
||||
.then(() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['images', id] });
|
||||
queryClient.invalidateQueries({ queryKey: ['case', id] });
|
||||
})
|
||||
.catch(() => {
|
||||
setUploadBatchItems((prev) =>
|
||||
prev.map((item) =>
|
||||
item.localId === localId
|
||||
? { ...item, status: 'error' }
|
||||
: item,
|
||||
),
|
||||
);
|
||||
batchCounterRef.current.failed += 1;
|
||||
})
|
||||
.finally(() => {
|
||||
setUploadingCount((c) => {
|
||||
const next = Math.max(0, c - 1);
|
||||
if (next === 0) {
|
||||
batchActiveRef.current = false;
|
||||
message.destroy('img-upload');
|
||||
const summary = {
|
||||
success: batchCounterRef.current.success,
|
||||
failed: batchCounterRef.current.failed,
|
||||
};
|
||||
message.success(`本次上传完成:成功 ${summary.success} 张,失败 ${summary.failed} 张`);
|
||||
} else {
|
||||
message.open({
|
||||
key: 'img-upload',
|
||||
type: 'loading',
|
||||
content: `正在上传截图(队列中 ${next} 张)...`,
|
||||
duration: 0,
|
||||
});
|
||||
}
|
||||
return next;
|
||||
});
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Card style={{ marginBottom: 24 }}>
|
||||
@@ -225,102 +316,33 @@ const Workspace: React.FC = () => {
|
||||
style={{ marginBottom: 24 }}
|
||||
extra={
|
||||
<Typography.Text type="secondary">
|
||||
支持 JPG/PNG,可批量拖拽
|
||||
支持手机拍照/相册上传,或桌面端批量拖拽
|
||||
</Typography.Text>
|
||||
}
|
||||
>
|
||||
<Space wrap style={{ marginBottom: 12 }}>
|
||||
<Upload
|
||||
accept="image/*"
|
||||
capture="environment"
|
||||
showUploadList={false}
|
||||
beforeUpload={(file) => handleBeforeUpload(file as File)}
|
||||
>
|
||||
<Button icon={<CameraOutlined />}>手机拍照上传</Button>
|
||||
</Upload>
|
||||
<Upload
|
||||
multiple
|
||||
accept="image/*"
|
||||
showUploadList={false}
|
||||
beforeUpload={(file) => handleBeforeUpload(file as File)}
|
||||
>
|
||||
<Button icon={<PictureOutlined />}>手机相册上传</Button>
|
||||
</Upload>
|
||||
</Space>
|
||||
<Dragger
|
||||
multiple
|
||||
accept="image/*"
|
||||
showUploadList={false}
|
||||
beforeUpload={(file) => {
|
||||
if (!batchActiveRef.current) {
|
||||
batchActiveRef.current = true;
|
||||
batchCounterRef.current = { success: 0, failed: 0 };
|
||||
setUploadBatchItems((prev) => {
|
||||
prev.forEach((item) => {
|
||||
if (item.previewUrl) URL.revokeObjectURL(item.previewUrl);
|
||||
});
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
const localId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
||||
const previewUrl = URL.createObjectURL(file as File);
|
||||
setUploadingCount((c) => {
|
||||
const next = c + 1;
|
||||
message.open({
|
||||
key: 'img-upload',
|
||||
type: 'loading',
|
||||
content: `正在上传截图(队列中 ${next} 张):${file.name}`,
|
||||
duration: 0,
|
||||
});
|
||||
return next;
|
||||
});
|
||||
setUploadBatchItems((prev) => [
|
||||
...prev,
|
||||
{
|
||||
localId,
|
||||
fileName: file.name,
|
||||
fileSize: file.size,
|
||||
status: 'uploading',
|
||||
previewUrl,
|
||||
},
|
||||
]);
|
||||
uploadImages(id, [file as File])
|
||||
.then((uploaded) => {
|
||||
const uploadedImage = uploaded?.[0];
|
||||
setUploadBatchItems((prev) =>
|
||||
prev.map((item) =>
|
||||
item.localId === localId
|
||||
? {
|
||||
...item,
|
||||
status: 'success',
|
||||
uploadedImageId: uploadedImage?.id,
|
||||
}
|
||||
: item,
|
||||
),
|
||||
);
|
||||
batchCounterRef.current.success += 1;
|
||||
})
|
||||
.then(() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['images', id] });
|
||||
queryClient.invalidateQueries({ queryKey: ['case', id] });
|
||||
})
|
||||
.catch(() => {
|
||||
setUploadBatchItems((prev) =>
|
||||
prev.map((item) =>
|
||||
item.localId === localId
|
||||
? { ...item, status: 'error' }
|
||||
: item,
|
||||
),
|
||||
);
|
||||
batchCounterRef.current.failed += 1;
|
||||
})
|
||||
.finally(() => {
|
||||
setUploadingCount((c) => {
|
||||
const next = Math.max(0, c - 1);
|
||||
if (next === 0) {
|
||||
batchActiveRef.current = false;
|
||||
message.destroy('img-upload');
|
||||
const summary = {
|
||||
success: batchCounterRef.current.success,
|
||||
failed: batchCounterRef.current.failed,
|
||||
};
|
||||
message.success(`本次上传完成:成功 ${summary.success} 张,失败 ${summary.failed} 张`);
|
||||
} else {
|
||||
message.open({
|
||||
key: 'img-upload',
|
||||
type: 'loading',
|
||||
content: `正在上传截图(队列中 ${next} 张)...`,
|
||||
duration: 0,
|
||||
});
|
||||
}
|
||||
return next;
|
||||
});
|
||||
});
|
||||
return false;
|
||||
}}
|
||||
beforeUpload={(file) => handleBeforeUpload(file as File)}
|
||||
style={{ padding: '20px 0' }}
|
||||
>
|
||||
<p className="ant-upload-drag-icon">
|
||||
|
||||
Reference in New Issue
Block a user