fix:图片上传成功

This commit is contained in:
彭帅
2026-06-01 15:12:20 +08:00
parent 7d851eb5d5
commit 0a14707db5
11 changed files with 555 additions and 28 deletions

View File

@@ -168,9 +168,9 @@ const eventBody = (payload: EventPayload) => ({
});
const imageBody = (payload: ImagePayload) => ({
imageURL: requiredText(payload.image_url, "请先上传图片,上传成功后系统会自动填充图片字段"),
imageName: requiredText(payload.image_name, "Image name is required"),
imageFileName: optionalText(payload.image_file_name),
imageURL: optionalText(payload.image_url),
mimeType: optionalText(payload.mime_type),
description: optionalText(payload.description),
studyDbId: optionalText(payload.study_db_id),

View File

@@ -29,26 +29,17 @@ function formatFileDate(timestamp: number): string {
function buildAutoFillPatch(
image: UploadedImage,
file: File,
current: Record<string, unknown>,
): Record<string, string> {
const baseName = stripExtension(image.filename);
const patch: Record<string, string> = {
const baseName = stripExtension(image.filename).trim();
const imageId = toImageId(baseName);
return {
id: imageId,
image_name: baseName || imageId,
image_file_name: image.filename,
image_url: image.url,
mime_type: image.contentType,
image_time_stamp: formatFileDate(file.lastModified),
};
if (!String(current.id ?? "").trim()) {
patch.id = toImageId(baseName);
}
if (!String(current.image_name ?? "").trim()) {
patch.image_name = baseName;
}
if (!String(current.image_time_stamp ?? "").trim()) {
patch.image_time_stamp = formatFileDate(file.lastModified);
}
return patch;
}
type ImageFormUploadProps = {
@@ -57,15 +48,22 @@ type ImageFormUploadProps = {
updateFormBatch: (patch: Record<string, unknown>) => void;
};
export function ImageFormUpload({ formData, updateForm, updateFormBatch }: ImageFormUploadProps) {
export function ImageFormUpload({ formData, updateFormBatch }: ImageFormUploadProps) {
const imageUrl = String(formData.image_url ?? "").trim();
const handleUploaded = (image: UploadedImage, file: File) => {
updateFormBatch(buildAutoFillPatch(image, file, formData));
updateFormBatch(buildAutoFillPatch(image, file));
};
const handleRemoved = () => {
updateForm("image_url", "");
updateFormBatch({
id: "",
image_name: "",
image_file_name: "",
image_url: "",
mime_type: "",
image_time_stamp: "",
});
};
return (

View File

@@ -32,6 +32,7 @@ const eventTypeOptions: SelectOption[] = [
const mimeTypeOptions: SelectOption[] = [
{ value: "image/jpeg", label: "image/jpeg" },
{ value: "image/jpg", label: "image/jpg" },
{ value: "image/png", label: "image/png" },
{ value: "image/gif", label: "image/gif" },
{ value: "image/webp", label: "image/webp" },
@@ -97,12 +98,12 @@ export default function EventImagePage() {
], [studyOptions]);
const imageFields = useMemo<BrapiFormField[]>(() => [
{ key: "id", label: "Image ID", type: "text", required: true, placeholder: "image-001" },
{ key: "image_name", label: "Image Name", type: "text", required: true, placeholder: "plot-001-canopy" },
{ key: "image_file_name", label: "File Name", type: "text", placeholder: "image-001.jpg" },
{ key: "image_url", label: "Image URL", type: "text", placeholder: "https://example.org/image.jpg", colSpan: 2 },
{ key: "mime_type", label: "MIME Type", type: "select", options: mimeTypeOptions },
{ key: "image_time_stamp", label: "Image Date", type: "date" },
{ key: "id", label: "Image ID", type: "text", required: true, readOnly: true, placeholder: "上传图片后自动生成" },
{ key: "image_name", label: "Image Name", type: "text", required: true, readOnly: true, placeholder: "上传图片后自动填写" },
{ key: "image_file_name", label: "File Name", type: "text", readOnly: true, placeholder: "上传图片后自动填写" },
{ key: "image_url", label: "Image URL", type: "text", required: true, readOnly: true, placeholder: "上传图片后自动填写", colSpan: 2 },
{ key: "mime_type", label: "MIME Type", type: "select", readOnly: true, options: mimeTypeOptions },
{ key: "image_time_stamp", label: "Image Date", type: "date", readOnly: true },
{
key: "study_db_id",
label: "Study",
@@ -125,6 +126,14 @@ export default function EventImagePage() {
{ key: "description", label: "Description", type: "textarea", colSpan: 2 },
], [observationOptions, observationUnitOptions, studyOptions]);
const validateImageForm = useCallback((payload: Record<string, unknown>) => {
const imageUrl = String(payload.image_url ?? "").trim();
if (!imageUrl) {
return "请先上传图片,上传成功后系统会自动填充带 * 的图片字段。";
}
return null;
}, []);
return (
<Tabs defaultValue="events" className="flex min-h-full flex-col gap-4">
<TabsList className="w-full justify-start overflow-x-auto rounded-lg border bg-white p-1 dark:border-slate-800 dark:bg-slate-950 sm:w-fit">
@@ -182,6 +191,7 @@ export default function EventImagePage() {
stats={[{ label: "/brapi/v2/images", value: "BrAPI", className: "bg-purple-50 text-purple-700 dark:bg-purple-400/10 dark:text-purple-200" }]}
loadData={loadImages}
renderFormExtra={(props) => <ImageFormUpload {...props} />}
validateForm={validateImageForm}
createRecord={(payload) => createImageRow(payload) as unknown as Promise<Record<string, unknown>>}
updateRecord={(id, payload) => updateImageRow(id, payload) as unknown as Promise<Record<string, unknown>>}
deleteRecord={deleteImageRow}