65 lines
2.1 KiB
JavaScript
65 lines
2.1 KiB
JavaScript
import CloudUploadOutlined from "@mui/icons-material/CloudUploadOutlined";
|
|
import Alert from "@mui/material/Alert";
|
|
import Box from "@mui/material/Box";
|
|
import Button from "@mui/material/Button";
|
|
import CircularProgress from "@mui/material/CircularProgress";
|
|
import Stack from "@mui/material/Stack";
|
|
import Typography from "@mui/material/Typography";
|
|
import { useRef, useState } from "react";
|
|
import { uploadExternalImage } from "../api/business.js";
|
|
|
|
export function ExternalImageUploadField({ disabled, label, onChange, value }) {
|
|
const inputRef = useRef(null);
|
|
const [error, setError] = useState("");
|
|
const [uploading, setUploading] = useState(false);
|
|
|
|
const handleFile = async (event) => {
|
|
const file = event.target.files?.[0];
|
|
event.target.value = "";
|
|
if (!file) {
|
|
return;
|
|
}
|
|
if (!file.type.startsWith("image/")) {
|
|
setError("请选择图片文件");
|
|
return;
|
|
}
|
|
if (file.size > 10 * 1024 * 1024) {
|
|
setError("图片不能超过 10MB");
|
|
return;
|
|
}
|
|
|
|
setError("");
|
|
setUploading(true);
|
|
try {
|
|
const url = await uploadExternalImage(file);
|
|
if (!url) {
|
|
throw new Error("上传结果缺少图片地址");
|
|
}
|
|
onChange(url);
|
|
} catch (uploadError) {
|
|
setError(uploadError.message || "图片上传失败");
|
|
} finally {
|
|
setUploading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Stack spacing={1}>
|
|
<Typography color="text.secondary" variant="body2">{label}</Typography>
|
|
<Box className="external-image-field">
|
|
{value ? <img alt={`${label}预览`} src={value} /> : <Box className="external-image-placeholder">暂无图片</Box>}
|
|
<Button
|
|
disabled={disabled || uploading}
|
|
onClick={() => inputRef.current?.click()}
|
|
startIcon={uploading ? <CircularProgress size={16} /> : <CloudUploadOutlined />}
|
|
variant="outlined"
|
|
>
|
|
{uploading ? "上传中" : value ? "更换图片" : "上传图片"}
|
|
</Button>
|
|
<input accept="image/*" hidden ref={inputRef} type="file" onChange={handleFile} />
|
|
</Box>
|
|
{error ? <Alert severity="error">{error}</Alert> : null}
|
|
</Stack>
|
|
);
|
|
}
|