fix: uploads
This commit is contained in:
@@ -20,6 +20,8 @@ import {
|
|||||||
} from 'antd';
|
} from 'antd';
|
||||||
import {
|
import {
|
||||||
CloudUploadOutlined,
|
CloudUploadOutlined,
|
||||||
|
CameraOutlined,
|
||||||
|
PictureOutlined,
|
||||||
ScanOutlined,
|
ScanOutlined,
|
||||||
MergeCellsOutlined,
|
MergeCellsOutlined,
|
||||||
ApartmentOutlined,
|
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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Card style={{ marginBottom: 24 }}>
|
<Card style={{ marginBottom: 24 }}>
|
||||||
@@ -225,102 +316,33 @@ const Workspace: React.FC = () => {
|
|||||||
style={{ marginBottom: 24 }}
|
style={{ marginBottom: 24 }}
|
||||||
extra={
|
extra={
|
||||||
<Typography.Text type="secondary">
|
<Typography.Text type="secondary">
|
||||||
支持 JPG/PNG,可批量拖拽
|
支持手机拍照/相册上传,或桌面端批量拖拽
|
||||||
</Typography.Text>
|
</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
|
<Dragger
|
||||||
multiple
|
multiple
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
showUploadList={false}
|
showUploadList={false}
|
||||||
beforeUpload={(file) => {
|
beforeUpload={(file) => handleBeforeUpload(file as 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;
|
|
||||||
}}
|
|
||||||
style={{ padding: '20px 0' }}
|
style={{ padding: '20px 0' }}
|
||||||
>
|
>
|
||||||
<p className="ant-upload-drag-icon">
|
<p className="ant-upload-drag-icon">
|
||||||
|
|||||||
Reference in New Issue
Block a user