490 lines
14 KiB
JavaScript
490 lines
14 KiB
JavaScript
import { defineComponent as ce, ref as g, computed as p, watch as me, nextTick as ye, openBlock as w, createElementBlock as ge, normalizeClass as pe, createBlock as C, resolveDynamicComponent as I, mergeProps as _, withCtx as G, normalizeProps as we, guardReactiveProps as ve, createElementVNode as he, createCommentVNode as be } from "vue";
|
||
import { useUi as Le, useI18n as Ue } from "@fast-crud/fast-crud";
|
||
import { merge as P, cloneDeep as Te } from "lodash-es";
|
||
import { u as Fe, _ as xe } from "./index-50ffe046.mjs";
|
||
const Ve = ce({
|
||
name: "FsFileUploader",
|
||
inheritAttrs: !1,
|
||
props: {
|
||
/**
|
||
* value
|
||
*/
|
||
modelValue: {},
|
||
/**
|
||
* 限制文件数量
|
||
* 当限制数量>1时,返回值为数组
|
||
*/
|
||
limit: {
|
||
type: Number
|
||
},
|
||
/**
|
||
* 文件大小限制,单位:字节
|
||
* 可以直接传一个数字,也可以传 `{limit:number,tip:'自定义提示文本'}`
|
||
*/
|
||
sizeLimit: {
|
||
type: [Number, Object]
|
||
},
|
||
/**
|
||
* 限制上传图片的像素尺寸
|
||
* 可以传数组会对象{ width?: number, height?: number, tip?: string } | [number, number?, string?]
|
||
*/
|
||
pixelLimit: {
|
||
type: Object,
|
||
required: !1
|
||
},
|
||
/**
|
||
* 是否显示限制提示
|
||
*/
|
||
showLimitTip: {
|
||
type: Boolean,
|
||
default: !0
|
||
},
|
||
/**
|
||
* 构建url的方法
|
||
* 后台返回key之后,将其build成一个可访问的url,用于反显
|
||
* 如果successHandle返回的object中已包含url,此配置将不会执行
|
||
*/
|
||
buildUrl: {
|
||
default() {
|
||
return (n) => n;
|
||
}
|
||
},
|
||
/**
|
||
* 多个value值构建多个url
|
||
* 如果successHandle 返回的object中已包含url,此方法将不会执行
|
||
*/
|
||
buildUrls: {},
|
||
/**
|
||
* 上传按钮配置,参考FsButton参数
|
||
*/
|
||
button: {
|
||
type: Object
|
||
},
|
||
/**
|
||
* 展示模式,对应[x]-uploader组件的 listType参数
|
||
*/
|
||
listType: {
|
||
type: String
|
||
},
|
||
/**
|
||
* 上传前的判断操作
|
||
*/
|
||
beforeUpload: {
|
||
type: Function
|
||
},
|
||
/**
|
||
* 上传请求前的操作,可以压缩图片等,替换掉context中的file
|
||
* type: `async (context)=>void`
|
||
*/
|
||
beforeUploadRequest: {
|
||
type: Function
|
||
},
|
||
/**
|
||
* FsUploaderXXX的配置
|
||
* 可以覆盖全局配置里各个上传类型对应的配置
|
||
* 例如: `{action:'xxx',bucket:'xxx',...}`
|
||
*/
|
||
uploader: {
|
||
type: Object
|
||
},
|
||
/**
|
||
* 预览配置
|
||
*/
|
||
preview: {
|
||
type: Object
|
||
},
|
||
/**
|
||
* 上传成功后从结果中取值类型
|
||
* 支持:`[object,url,key,其他(successHandle返回的object内要有该字段,不要用'id')]`
|
||
* 如果配置了非url,则需要配置buildUrl用于反显
|
||
*/
|
||
valueType: {
|
||
type: String,
|
||
// url ,key, object
|
||
default: "url"
|
||
},
|
||
/**
|
||
* 根据value获取文件名,用于显示在fileList里面
|
||
*/
|
||
getFileName: {}
|
||
},
|
||
emits: ["change", "update:modelValue", "success", "exceed", "remove"],
|
||
setup(n, r) {
|
||
const { ui: o } = Le(), { t: d } = Ue(), s = g([]), v = g(), c = g(), H = p(() => n.getFileName || (async (e) => {
|
||
if (typeof e != "string")
|
||
return console.warn("获取文件名失败,请配置getFileName"), e;
|
||
const t = e.substring(e.lastIndexOf("/") + 1), i = t.indexOf("?");
|
||
return i >= 0 ? t.substring(0, i) : t;
|
||
}));
|
||
function h(e) {
|
||
return n.valueType === "object" ? e : e[n.valueType];
|
||
}
|
||
function K(e) {
|
||
const t = [];
|
||
for (let i of e)
|
||
t.push(h(i));
|
||
return t;
|
||
}
|
||
async function W(e) {
|
||
const t = [];
|
||
for (let i of e) {
|
||
let l;
|
||
typeof i == "string" || typeof i == "number" || typeof i == "boolean" || i instanceof Date ? (l = {
|
||
url: void 0,
|
||
key: i,
|
||
value: i
|
||
}, n.valueType !== "object" && (l[n.valueType] = i)) : l = i, l[o.upload.id] || (l[o.upload.id] = Math.random() + ""), l.status || (l.status = o.upload.status.success), t.push(l);
|
||
}
|
||
await z(t);
|
||
for (const i of t)
|
||
if (!i.name) {
|
||
const l = i.url || i.value;
|
||
i.name = await H.value(l, i);
|
||
}
|
||
return t;
|
||
}
|
||
async function B(e) {
|
||
const t = [];
|
||
for (let i of e) {
|
||
const l = i.response || i.fsRes, a = {
|
||
size: i.size,
|
||
name: i.name,
|
||
uid: i.uid,
|
||
...l ?? i
|
||
};
|
||
t.push(a);
|
||
}
|
||
return await z(t), K(t);
|
||
}
|
||
async function b(e) {
|
||
const t = [];
|
||
if (e == null || e.length === 0) {
|
||
s.value = t;
|
||
return;
|
||
}
|
||
if (e instanceof Array)
|
||
for (let l of e)
|
||
t.push(l);
|
||
else
|
||
t.push(e);
|
||
const i = await W(t);
|
||
N(i);
|
||
}
|
||
async function J() {
|
||
await S.onChange(), await S.onBlur();
|
||
}
|
||
async function R(e) {
|
||
let t = await Q(e);
|
||
k(t), ye(async () => {
|
||
await J();
|
||
});
|
||
}
|
||
async function Q(e) {
|
||
if (e == null || e.length === 0)
|
||
return n.limit === 1 ? null : [];
|
||
if (n.limit === 1)
|
||
return (await B(e))[0];
|
||
const t = [];
|
||
for (let i of e)
|
||
o.upload.isSuccess(i) && t.push(i);
|
||
return await B(t);
|
||
}
|
||
async function z(e) {
|
||
let t = e.filter((i) => i.url == null);
|
||
if (n.buildUrls) {
|
||
const i = t.map((a) => h(a)), l = await n.buildUrls(i);
|
||
for (let a = 0; a < t.length; a++)
|
||
t[a].url = l[a];
|
||
} else if (n.buildUrl)
|
||
for (let i of t)
|
||
i.url = await n.buildUrl(h(i));
|
||
else
|
||
for (let i of t)
|
||
i.url = i.value || i.key;
|
||
}
|
||
function E(e) {
|
||
r.emit("change", e);
|
||
}
|
||
function k(e) {
|
||
v.value = e, r.emit("update:modelValue", e);
|
||
}
|
||
const S = o.formItem.injectFormItemContext();
|
||
me(
|
||
() => n.modelValue,
|
||
async (e) => {
|
||
E(e), e !== v.value && await b(e);
|
||
}
|
||
), b(n.modelValue);
|
||
function X() {
|
||
return s.value.filter((t) => t.status === o.upload.status.uploading).length > 0;
|
||
}
|
||
function m(e, t) {
|
||
N(t), R(t);
|
||
}
|
||
function L(e, t, i) {
|
||
r.emit("success", { res: e, file: t, fileList: i }), m(t, i);
|
||
}
|
||
function O(e) {
|
||
let t;
|
||
return e > 1024 * 1024 * 1024 ? t = (e / (1024 * 1024 * 1024)).toFixed(2) + "G" : e > 1024 * 1024 ? t = (e / (1024 * 1024)).toFixed(2) + "M" : t = Math.round(e / 1024) + "K", t;
|
||
}
|
||
const j = (e = !1) => {
|
||
const t = e ? o.upload.limitAdd : 0;
|
||
return n.limit > 0 && s.value.length >= n.limit + t;
|
||
};
|
||
function Y() {
|
||
n.showLimitTip && o.message.warn(d("fs.extends.fileUploader.limitTip", [n.limit]));
|
||
}
|
||
function Z() {
|
||
if (j(!0))
|
||
throw Y(), r.emit("exceed", { fileList: s.value, limit: n.limit }), new Error("文件数量超限");
|
||
}
|
||
function ee(e) {
|
||
if (n.sizeLimit != null) {
|
||
let t = n.sizeLimit, i = null;
|
||
if (typeof n.sizeLimit == "number" ? i = (l, a) => {
|
||
const f = O(a), u = O(e.size);
|
||
o.message.warn(d("fs.extends.fileUploader.sizeLimitTip", [f, u]));
|
||
} : (t = n.sizeLimit.limit, i = n.sizeLimit.tip), e.size > t) {
|
||
let l = "文件大小超过限制,当前文件大小:" + e.size / 1024 + "k";
|
||
throw i(e.size, t), new Error(l);
|
||
}
|
||
}
|
||
}
|
||
const te = (e) => {
|
||
let t = 0, i = 0, l = "";
|
||
if (n.pixelLimit)
|
||
Array.isArray(n.pixelLimit) ? (t = n.pixelLimit[0], i = n.pixelLimit[1] || n.pixelLimit[0] || 0, l = n.pixelLimit[2] || "") : typeof n.pixelLimit == "object" && (t = n.pixelLimit.width || 0, i = n.pixelLimit.height || 0, l = n.pixelLimit.tip || "");
|
||
else
|
||
return Promise.resolve(!0);
|
||
let a = l || d("fs.extends.fileUploader.pixelLimitTip", [t, i]);
|
||
return new Promise((f, u) => {
|
||
let M = new FileReader();
|
||
M.onload = (fe) => {
|
||
var $;
|
||
let D = ($ = fe.target) == null ? void 0 : $.result, y = new Image();
|
||
y.onload = function() {
|
||
t && y.width > t || i && y.height > i ? (o.message.warn(a), u(a)) : f(!0);
|
||
}, y.onerror = function(Pe) {
|
||
o.message.warn(d("fs.extends.fileUploader.loadError")), u(d("fs.extends.fileUploader.loadError"));
|
||
}, D && (y.src = D);
|
||
}, M.readAsDataURL(e);
|
||
});
|
||
}, U = async (e, t = s.value) => {
|
||
if (n.beforeUpload && await n.beforeUpload({ file: e, fileList: s.value }) === !1)
|
||
return !1;
|
||
try {
|
||
Z(), ee(e), F() && await te(e);
|
||
} catch {
|
||
return !1;
|
||
}
|
||
};
|
||
function N(e) {
|
||
s.value = e;
|
||
}
|
||
async function ie(e) {
|
||
e.options = n.uploader || {};
|
||
const { getUploaderImpl: t } = Fe();
|
||
let i = await t(e.options.type);
|
||
if (i == null)
|
||
throw o.message.warn("Sorry,The uploader component is not ready yet"), new Error("Sorry,The component is not ready yet");
|
||
return await (i == null ? void 0 : i.upload(e));
|
||
}
|
||
async function T(e) {
|
||
n.beforeUploadRequest && await n.beforeUploadRequest(e);
|
||
const { file: t, onProgress: i, onSuccess: l, onError: a } = e, f = {
|
||
file: t,
|
||
fileName: t.name,
|
||
onProgress: i
|
||
};
|
||
try {
|
||
const u = await ie(f);
|
||
l(u);
|
||
} catch (u) {
|
||
console.error("上传失败", u), a(u);
|
||
}
|
||
}
|
||
const ne = p(() => oe() ? {
|
||
is: "FsIcon",
|
||
icon: o.icons.plus
|
||
} : {
|
||
is: "FsButton",
|
||
icon: o.icons.upload,
|
||
text: d("fs.extends.fileUploader.text"),
|
||
...n.button
|
||
}), A = g(!1), q = g(), le = p(() => ({
|
||
...o.dialog.footer(),
|
||
...n.preview
|
||
}));
|
||
function ae(e) {
|
||
return new Promise((t, i) => {
|
||
const l = new FileReader();
|
||
l.readAsDataURL(e), l.onload = () => t(l.result), l.onerror = (a) => i(a);
|
||
});
|
||
}
|
||
function F() {
|
||
return n.listType === o.upload.typeImageCard || n.listType === o.upload.typeImage;
|
||
}
|
||
function oe() {
|
||
return n.listType === o.upload.typeImageCard;
|
||
}
|
||
const x = async (e) => {
|
||
var t, i;
|
||
if (!F()) {
|
||
let l;
|
||
e.url ? l = e.url : o.type === "antdv" ? l = (t = e.response) == null ? void 0 : t.url : o.type === "element" ? l = (i = e.fsRes) == null ? void 0 : i.url : l = e.url, window.open(l, "_blank");
|
||
}
|
||
!e.url && !e.preview && e.originFileObj && (e.preview = await ae(e.originFileObj)), q.value = e.url || e.preview, A.value = !0;
|
||
};
|
||
function re() {
|
||
const e = {
|
||
customRequest: T,
|
||
beforeUpload: U,
|
||
limit: n.limit,
|
||
listType: n.listType,
|
||
onChange: (t) => {
|
||
const { file: i, fileList: l } = t;
|
||
m(i, l), i.status === "done" && L(i.response, i, l);
|
||
},
|
||
onPreview: x
|
||
};
|
||
return n.limit != null && r.attrs.maxCount == null && (e.maxCount = n.limit), e;
|
||
}
|
||
function se() {
|
||
return {
|
||
action: "",
|
||
listType: n.listType,
|
||
limit: n.limit,
|
||
beforeUpload: U,
|
||
httpRequest: T,
|
||
onExceed: (e) => {
|
||
r.emit("exceed", e, s);
|
||
},
|
||
onRemove: (e, t) => {
|
||
m(e, t), r.emit("remove", e, t);
|
||
},
|
||
onChange: (e, t) => {
|
||
m(e, t);
|
||
},
|
||
onSuccess: (e, t, i) => {
|
||
e != null && (t.response = e, t.fsRes = e, L(e, t, i));
|
||
},
|
||
// "on-error": "handleUploadFileError",
|
||
// "on-progress": "handleUploadProgress"
|
||
onPreview: x
|
||
};
|
||
}
|
||
const V = {};
|
||
function ue() {
|
||
function e(t) {
|
||
let i = t.value || t;
|
||
i = Te(i);
|
||
for (let l of i) {
|
||
const a = V[l.id];
|
||
a && P(l, a);
|
||
}
|
||
return i;
|
||
}
|
||
return {
|
||
action: "",
|
||
limit: n.limit,
|
||
listType: n.listType,
|
||
onBeforeUpload: async ({ file: t, fileList: i }) => U(t, i),
|
||
customRequest: (t) => {
|
||
const i = t.file;
|
||
T({
|
||
...t,
|
||
file: i.file,
|
||
onSuccess: async (l) => {
|
||
const a = n.valueType === "object" ? l : l[n.valueType];
|
||
l.url = await n.buildUrl(a), P(i, l), V[i.id] = {
|
||
...l,
|
||
fsRes: l
|
||
}, t.onFinish(i);
|
||
},
|
||
onProgress: (l) => {
|
||
t.onProgress(l);
|
||
}
|
||
});
|
||
},
|
||
onExceed: (t) => {
|
||
r.emit("exceed", t);
|
||
},
|
||
onRemove: (t) => {
|
||
r.emit("remove", t);
|
||
},
|
||
onChange: (t) => {
|
||
const { event: i, file: l, fileList: a } = t, f = e(a);
|
||
m(l, [...f]);
|
||
},
|
||
onFinish: (t) => {
|
||
const i = V[t.id];
|
||
i && P(t, i);
|
||
const l = e(s);
|
||
L(i, t, l);
|
||
},
|
||
onPreview: x
|
||
};
|
||
}
|
||
const de = p(() => {
|
||
let e = null;
|
||
return o.type === "antdv" ? e = re() : o.type === "element" ? e = se() : e = ue(), {
|
||
...e,
|
||
...r.attrs
|
||
};
|
||
});
|
||
return {
|
||
ui: o,
|
||
fileList: s,
|
||
fileUploaderRef: c,
|
||
initValue: b,
|
||
onChange: E,
|
||
onInput: k,
|
||
hasUploading: X,
|
||
isPicture: F,
|
||
computedFileSelectBtn: ne,
|
||
previewVisible: A,
|
||
previewImage: q,
|
||
computedPreview: le,
|
||
computedOnLimit: j,
|
||
computedBinding: de,
|
||
emitValue: R
|
||
};
|
||
}
|
||
});
|
||
const Ce = ["src"];
|
||
function Ie(n, r, o, d, s, v) {
|
||
return w(), ge("div", {
|
||
class: pe(["fs-file-uploader", { "fs-file-uploader-limit": n.computedOnLimit() }])
|
||
}, [
|
||
(w(), C(I(n.ui.upload.name), _({
|
||
ref: "fileUploaderRef",
|
||
"file-list": n.fileList,
|
||
"onUpdate:fileList": r[0] || (r[0] = (c) => n.fileList = c)
|
||
}, n.computedBinding), {
|
||
default: G(() => [
|
||
(w(), C(I(n.computedFileSelectBtn.is), we(ve(n.computedFileSelectBtn)), null, 16))
|
||
]),
|
||
_: 1
|
||
}, 16, ["file-list"])),
|
||
n.isPicture() ? (w(), C(I(n.ui.dialog.name), _({
|
||
key: 0,
|
||
[n.ui.dialog.visible]: n.previewVisible,
|
||
["onUpdate:" + n.ui.dialog.visible]: r[1] || (r[1] = (c) => n.previewVisible = c)
|
||
}, n.computedPreview), {
|
||
default: G(() => [
|
||
he("img", {
|
||
style: { "max-width": "100%", "max-height": "100%" },
|
||
src: n.previewImage
|
||
}, null, 8, Ce)
|
||
]),
|
||
_: 1
|
||
}, 16)) : be("", !0)
|
||
], 2);
|
||
}
|
||
const ke = /* @__PURE__ */ xe(Ve, [["render", Ie]]);
|
||
export {
|
||
ke as default
|
||
};
|
||
//# sourceMappingURL=fs-file-uploader-506e96b9.mjs.map
|