fix: uploads

This commit is contained in:
2026-03-14 21:57:07 +08:00
parent 5c096ae753
commit 6ebf03d351

View File

@@ -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">