257 lines
8.2 KiB
JavaScript
257 lines
8.2 KiB
JavaScript
import { a1 as ElUpload, E as ElMessage, R as ElImage, i as ElIcon } from "./element-plus.CkEW9frc.js";
|
||
import { J as defineComponent, ey as useCssVars, ev as useModel, m as watch, aO as resolveComponent, S as openBlock, _ as createElementBlock, $ as createVNode, a0 as withCtx, H as Fragment, T as createBlock, aw as withModifiers, a8 as createCommentVNode, aa as toDisplayString, ez as mergeModels, r as ref } from "./.pnpm.BW3P1y8f.js";
|
||
import { P as ParamsAPI } from "./index.CMd5bD1r.js";
|
||
import { _ as _export_sfc } from "./_plugin-vue_export-helper.1tPrXgE0.js";
|
||
const _hoisted_1 = { class: "single-image-upload" };
|
||
const _hoisted_2 = {
|
||
key: 0,
|
||
class: "el-upload__tip"
|
||
};
|
||
const _sfc_main = /* @__PURE__ */ defineComponent({
|
||
__name: "SingleImageUpload",
|
||
props: /* @__PURE__ */ mergeModels({
|
||
/**
|
||
* 请求携带的额外参数
|
||
*/
|
||
data: {
|
||
type: Object,
|
||
default: () => {
|
||
return {};
|
||
}
|
||
},
|
||
/**
|
||
* 上传文件的参数名
|
||
*/
|
||
name: {
|
||
type: String,
|
||
default: "file"
|
||
},
|
||
/**
|
||
* 最大文件大小(单位:M)
|
||
*/
|
||
maxFileSize: {
|
||
type: Number,
|
||
default: 10
|
||
},
|
||
/**
|
||
* 上传图片格式,默认支持所有图片(image/*),指定格式示例:'.png,.jpg,.jpeg,.gif,.bmp'
|
||
*/
|
||
accept: {
|
||
type: String,
|
||
default: "image/*"
|
||
},
|
||
/**
|
||
* 自定义样式,用于设置组件的宽度和高度等其他样式
|
||
*/
|
||
style: {
|
||
type: Object,
|
||
default: () => {
|
||
return {
|
||
width: "150px",
|
||
height: "150px"
|
||
};
|
||
}
|
||
},
|
||
/**
|
||
* 是否禁用
|
||
*/
|
||
disabled: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
/**
|
||
* 是否显示提示信息
|
||
*/
|
||
showTip: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
/**
|
||
* 提示文本
|
||
*/
|
||
tipText: {
|
||
type: String,
|
||
default: ""
|
||
},
|
||
/**
|
||
* 是否启用图片预览功能
|
||
*/
|
||
enablePreview: {
|
||
type: Boolean,
|
||
default: true
|
||
}
|
||
}, {
|
||
"modelValue": {
|
||
default: ""
|
||
},
|
||
"modelModifiers": {}
|
||
}),
|
||
emits: /* @__PURE__ */ mergeModels(["success", "error", "input", "update:modelValue"], ["update:modelValue"]),
|
||
setup(__props, { emit: __emit }) {
|
||
useCssVars((_ctx) => ({
|
||
"v4b209376": props.style.width ?? "150px",
|
||
"b464b91e": props.style.height ?? "150px"
|
||
}));
|
||
const props = __props;
|
||
const modelValue = useModel(__props, "modelValue");
|
||
const internalFileList = ref([]);
|
||
watch(
|
||
() => modelValue.value,
|
||
(newVal) => {
|
||
if (newVal) {
|
||
internalFileList.value = [
|
||
{
|
||
name: newVal.split("/").pop() || "image",
|
||
url: newVal
|
||
}
|
||
];
|
||
} else {
|
||
internalFileList.value = [];
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
watch(
|
||
() => internalFileList.value,
|
||
(newVal) => {
|
||
if (newVal && newVal.length > 0 && newVal[0].url) {
|
||
modelValue.value = newVal[0].url;
|
||
} else {
|
||
modelValue.value = "";
|
||
}
|
||
},
|
||
{ deep: true }
|
||
);
|
||
const emit = __emit;
|
||
function handleBeforeUpload(file) {
|
||
const acceptTypes = props.accept.split(",").map((type) => type.trim());
|
||
const isValidType = acceptTypes.some((type) => {
|
||
if (type === "image/*") {
|
||
return file.type.startsWith("image/");
|
||
} else if (type.startsWith(".")) {
|
||
return file.name.toLowerCase().endsWith(type);
|
||
} else {
|
||
return file.type === type;
|
||
}
|
||
});
|
||
if (!isValidType) {
|
||
ElMessage.warning(`上传文件的格式不正确,仅支持:${props.accept}`);
|
||
return false;
|
||
}
|
||
if (file.size > props.maxFileSize * 1024 * 1024) {
|
||
ElMessage.warning(`上传图片不能大于 ${props.maxFileSize}MB`);
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
async function handleUpload(options) {
|
||
try {
|
||
const file = options.file;
|
||
const formData = new FormData();
|
||
formData.append(props.name, file);
|
||
for (const [key, value] of Object.entries(props.data)) {
|
||
formData.append(key, String(value));
|
||
}
|
||
const response = await ParamsAPI.uploadFile(formData);
|
||
if (response.data.code === 0 && response.data) {
|
||
const fileInfo = response.data.data;
|
||
onSuccess(fileInfo);
|
||
return fileInfo;
|
||
} else {
|
||
const errorMsg = response.data.msg || "上传失败";
|
||
ElMessage.error(errorMsg);
|
||
throw new Error(errorMsg);
|
||
}
|
||
} catch (error) {
|
||
onError(error instanceof Error ? error : new Error(String(error)));
|
||
throw error;
|
||
}
|
||
}
|
||
function handleDelete() {
|
||
internalFileList.value = [];
|
||
}
|
||
function handleImageClick(event) {
|
||
event.stopPropagation();
|
||
if (props.enablePreview && internalFileList.value && internalFileList.value.length > 0 && internalFileList.value[0].url) ;
|
||
}
|
||
const onSuccess = (fileInfo) => {
|
||
const newFileList = [
|
||
{
|
||
name: fileInfo.file_name,
|
||
url: fileInfo.file_url
|
||
}
|
||
];
|
||
internalFileList.value = newFileList;
|
||
emit("success", fileInfo);
|
||
emit("input", fileInfo.file_url);
|
||
emit("update:modelValue", fileInfo.file_url);
|
||
};
|
||
const onError = (error) => {
|
||
console.error("图片上传失败:", error);
|
||
ElMessage.error("图片上传失败,请重试");
|
||
emit("error", error);
|
||
};
|
||
return (_ctx, _cache) => {
|
||
const _component_el_image = ElImage;
|
||
const _component_CircleCloseFilled = resolveComponent("CircleCloseFilled");
|
||
const _component_el_icon = ElIcon;
|
||
const _component_Plus = resolveComponent("Plus");
|
||
const _component_el_upload = ElUpload;
|
||
return openBlock(), createElementBlock("div", _hoisted_1, [
|
||
createVNode(_component_el_upload, {
|
||
"file-list": internalFileList.value,
|
||
"onUpdate:fileList": _cache[0] || (_cache[0] = ($event) => internalFileList.value = $event),
|
||
class: "single-upload",
|
||
"list-type": "picture-card",
|
||
"show-file-list": false,
|
||
accept: props.accept,
|
||
"before-upload": handleBeforeUpload,
|
||
"http-request": handleUpload,
|
||
"on-success": onSuccess,
|
||
"on-error": onError,
|
||
"on-remove": handleDelete,
|
||
disabled: props.disabled
|
||
}, {
|
||
default: withCtx(() => [
|
||
internalFileList.value && internalFileList.value.length > 0 && internalFileList.value[0].url ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
|
||
(openBlock(), createBlock(_component_el_image, {
|
||
key: internalFileList.value[0].url,
|
||
class: "single-upload__image",
|
||
src: internalFileList.value[0].url,
|
||
fit: "cover",
|
||
"preview-src-list": props.enablePreview ? [internalFileList.value[0].url] : [],
|
||
"preview-teleported": true,
|
||
onClick: withModifiers(handleImageClick, ["stop"])
|
||
}, null, 8, ["src", "preview-src-list"])),
|
||
!props.disabled ? (openBlock(), createBlock(_component_el_icon, {
|
||
key: 0,
|
||
class: "single-upload__delete-btn",
|
||
onClick: withModifiers(handleDelete, ["stop"])
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_CircleCloseFilled)
|
||
]),
|
||
_: 1
|
||
})) : createCommentVNode("", true)
|
||
], 64)) : (openBlock(), createBlock(_component_el_icon, {
|
||
key: 1,
|
||
class: "single-upload__add-btn"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_Plus)
|
||
]),
|
||
_: 1
|
||
}))
|
||
]),
|
||
_: 1
|
||
}, 8, ["file-list", "accept", "disabled"]),
|
||
props.showTip ? (openBlock(), createElementBlock("div", _hoisted_2, toDisplayString(props.tipText || `支持 ${props.accept} 格式,文件大小不超过 ${props.maxFileSize}MB`), 1)) : createCommentVNode("", true)
|
||
]);
|
||
};
|
||
}
|
||
});
|
||
const SingleImageUpload = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-d3fd4602"]]);
|
||
export {
|
||
SingleImageUpload as S
|
||
};
|