333 lines
9.2 KiB
JavaScript
333 lines
9.2 KiB
JavaScript
import { defineComponent as G, ref as d, watch as J, getCurrentInstance as K, computed as M, reactive as X, resolveComponent as S, openBlock as n, createElementBlock as c, normalizeClass as z, createElementVNode as m, createBlock as h, resolveDynamicComponent as I, withCtx as E, Fragment as Y, renderList as Z, mergeProps as x, createVNode as f, createCommentVNode as w } from "vue";
|
||
import { useUi as ee } from "@fast-crud/fast-crud";
|
||
import { u as oe, _ as te } from "./index-50ffe046.mjs";
|
||
import "lodash-es";
|
||
const re = G({
|
||
name: "FsCropperUploader",
|
||
props: {
|
||
/**
|
||
* 初始图片url,或者是数组
|
||
*/
|
||
modelValue: {
|
||
type: [String, Object, Array]
|
||
},
|
||
img: {},
|
||
/**
|
||
* 上传后端类型,[form, cos, qiniu , alioss]
|
||
*/
|
||
type: {
|
||
type: String
|
||
},
|
||
/**
|
||
* 上传提示
|
||
*/
|
||
uploadTip: {
|
||
type: String
|
||
},
|
||
/**
|
||
* 对话框标题
|
||
*/
|
||
title: String,
|
||
/**
|
||
* cropper的高度,默认为浏览器可视窗口高度的40%,最小270
|
||
*/
|
||
cropperHeight: {
|
||
type: [String, Number]
|
||
},
|
||
/**
|
||
* 对话框宽度,默认50%
|
||
*/
|
||
dialogWidth: {
|
||
type: [String, Number],
|
||
default: "50%"
|
||
},
|
||
/**
|
||
* 图片大小限制,单位MB
|
||
*/
|
||
maxSize: {
|
||
type: Number,
|
||
default: 5
|
||
},
|
||
/**
|
||
* 图片数量限制,0为不限制
|
||
*/
|
||
limit: {
|
||
type: Number,
|
||
default: 1
|
||
},
|
||
/**
|
||
* 可接收的文件后缀
|
||
*/
|
||
accept: {
|
||
type: String,
|
||
default: ".jpg, .jpeg, .png, .gif, .webp"
|
||
},
|
||
/**
|
||
* [cropperjs的参数](https://github.com/fengyuanchen/cropperjs)
|
||
*/
|
||
cropper: {
|
||
type: Object
|
||
},
|
||
/**
|
||
* FsUploaderXXX的配置,会临时覆盖全局上传配置参数
|
||
*/
|
||
uploader: {
|
||
type: Object
|
||
},
|
||
/**
|
||
* 压缩质量
|
||
*/
|
||
compressQuality: {
|
||
type: Number,
|
||
default: 0.8
|
||
},
|
||
/**
|
||
* 构建下载url方法,不影响提交的value
|
||
*/
|
||
buildUrl: {
|
||
type: Function,
|
||
default: async function(e) {
|
||
return typeof e == "object" ? e.url : e;
|
||
}
|
||
},
|
||
/**
|
||
* 返回值类型
|
||
* 支持:`[url,key,object]`
|
||
*/
|
||
valueType: {
|
||
type: String,
|
||
// url ,key, object
|
||
default: "url"
|
||
},
|
||
/**
|
||
* 是否禁用
|
||
*/
|
||
disabled: {}
|
||
},
|
||
emits: ["update:modelValue", "change", "ready"],
|
||
setup(e, a) {
|
||
const { ui: b } = ee(), g = d(), N = d(), U = d(), s = d([]), u = b.formItem.injectFormItemContext();
|
||
let y = e.modelValue;
|
||
i(e.modelValue);
|
||
async function i(o) {
|
||
const t = [];
|
||
if (o == null || o === "") {
|
||
s.value = t;
|
||
return;
|
||
}
|
||
if (typeof o == "string")
|
||
t.push({ url: await e.buildUrl(o), value: o, status: "done" });
|
||
else if (Array.isArray(o))
|
||
for (const r of o)
|
||
t.push({ url: await e.buildUrl(r), value: r, status: "done" });
|
||
else if (typeof o == "object")
|
||
t.push({ url: await e.buildUrl(o), value: o, status: "done" });
|
||
else
|
||
for (const r of o)
|
||
t.push({ url: await e.buildUrl(r), value: r, status: "done" });
|
||
s.value = t;
|
||
}
|
||
function v() {
|
||
e.disabled || (U.value = void 0, g.value.clear(), g.value.open());
|
||
}
|
||
function C(o) {
|
||
s.value.splice(o, 1), j();
|
||
}
|
||
function B() {
|
||
const o = s.value;
|
||
if (o && o.length > 0) {
|
||
for (const t of o)
|
||
if (t.status === "uploading")
|
||
return !0;
|
||
}
|
||
return !1;
|
||
}
|
||
async function _(o) {
|
||
const t = o.blob, r = o.dataUrl, T = o.file.name, L = new File([t], T, { type: t.type }), p = X({
|
||
url: void 0,
|
||
dataUrl: r,
|
||
status: "uploading",
|
||
progress: 0
|
||
}), Q = (l) => {
|
||
p.progress = l.percent;
|
||
}, $ = (l) => {
|
||
p.status = "error", p.message = "文件上传出错:" + l.message, console.error(l);
|
||
}, W = {
|
||
file: L,
|
||
onProgress: Q,
|
||
onError: $,
|
||
fileName: T
|
||
};
|
||
s.value.push(p);
|
||
try {
|
||
const l = await R(W);
|
||
let V = l;
|
||
e.valueType !== "object" && (V = l[e.valueType]), p.url = await e.buildUrl(V), p.value = V, p.status = "done", j();
|
||
} catch (l) {
|
||
$(l);
|
||
}
|
||
}
|
||
async function R(o) {
|
||
o.options = e.uploader || {};
|
||
const { getUploaderImpl: t } = oe();
|
||
let r = await t(o.options.type);
|
||
if (r == null)
|
||
throw new Error("Sorry,The component is not ready yet");
|
||
return await (r == null ? void 0 : r.upload(o));
|
||
}
|
||
async function j() {
|
||
const o = [];
|
||
for (const r of s.value)
|
||
typeof r == "string" ? o.push(r) : o.push(r.value);
|
||
let t = o;
|
||
e.limit === 1 && (t = o && o.length > 0 ? o[0] : void 0), y = t, a.emit("update:modelValue", t), await u.onChange(), await u.onBlur();
|
||
}
|
||
function F(o) {
|
||
return o.dataUrl ? o.dataUrl : o.url;
|
||
}
|
||
const P = d(!1), k = d();
|
||
function A(o) {
|
||
P.value = !0, k.value = F(o);
|
||
}
|
||
function D() {
|
||
P.value = !1, k.value = null;
|
||
}
|
||
J(
|
||
() => e.modelValue,
|
||
async (o) => {
|
||
a.emit("change", o), o !== y && await i(o);
|
||
}
|
||
);
|
||
const O = K();
|
||
function q(o) {
|
||
a.emit("ready", {
|
||
uploaderRef: O,
|
||
...o
|
||
});
|
||
}
|
||
const H = M(() => ({
|
||
...e
|
||
}));
|
||
return {
|
||
ui: b,
|
||
cropperRef: g,
|
||
uploaderImplRef: N,
|
||
indexRef: U,
|
||
listRef: s,
|
||
addNewImage: v,
|
||
hasUploading: B,
|
||
cropComplete: _,
|
||
doUpload: R,
|
||
removeImage: C,
|
||
getImageSrc: F,
|
||
previewUrl: k,
|
||
previewVisible: P,
|
||
preview: A,
|
||
closePreview: D,
|
||
doReady: q,
|
||
computedProps: H
|
||
};
|
||
}
|
||
});
|
||
const ie = { class: "image-list" }, ne = { class: "image-slot" }, se = { class: "delete" }, le = {
|
||
key: 0,
|
||
class: "status-uploading"
|
||
}, ae = {
|
||
key: 1,
|
||
class: "status-done"
|
||
}, ue = { class: "fs-cropper-preview-content" }, pe = ["src"];
|
||
function ce(e, a, b, g, N, U) {
|
||
const s = S("fs-loading"), u = S("fs-icon"), y = S("fs-cropper");
|
||
return n(), c("div", {
|
||
class: z(["fs-cropper-uploader", { "is-disabled": e.computedProps.disabled }])
|
||
}, [
|
||
m("div", ie, [
|
||
(n(), h(I(e.ui.imageGroup.name), null, {
|
||
default: E(() => [
|
||
(n(!0), c(Y, null, Z(e.listRef, (i, v) => (n(), c("div", {
|
||
key: v,
|
||
class: "image-item"
|
||
}, [
|
||
(n(), h(I(e.ui.image.name), x({
|
||
class: "image",
|
||
src: e.getImageSrc(i)
|
||
}, { ref_for: !0 }, e.computedProps.img), {
|
||
placeholder: E(() => [
|
||
m("div", ne, [
|
||
f(s, { loading: !0 })
|
||
])
|
||
]),
|
||
_: 2
|
||
}, 1040, ["src"])),
|
||
m("div", se, [
|
||
e.computedProps.disabled ? w("", !0) : (n(), h(u, {
|
||
key: 0,
|
||
icon: e.ui.icons.remove,
|
||
onClick: (C) => e.removeImage(v)
|
||
}, null, 8, ["icon", "onClick"])),
|
||
f(u, {
|
||
icon: e.ui.icons.search,
|
||
onClick: (C) => e.preview(i)
|
||
}, null, 8, ["icon", "onClick"])
|
||
]),
|
||
i.status === "uploading" ? (n(), c("div", le, [
|
||
(n(), h(I(e.ui.progress.name), {
|
||
type: "circle",
|
||
percentage: i.progress,
|
||
width: 70
|
||
}, null, 8, ["percentage"]))
|
||
])) : i.status === "done" ? (n(), c("div", ae, [
|
||
f(u, {
|
||
icon: e.ui.icons.check,
|
||
class: "status-down-icon"
|
||
}, null, 8, ["icon"])
|
||
])) : w("", !0)
|
||
]))), 128)),
|
||
e.computedProps.limit <= 0 || e.computedProps.limit > e.listRef.length ? (n(), c("div", {
|
||
key: 0,
|
||
class: "image-item image-plus",
|
||
onClick: a[0] || (a[0] = (...i) => e.addNewImage && e.addNewImage(...i))
|
||
}, [
|
||
f(u, {
|
||
icon: e.ui.icons.plus,
|
||
class: "cropper-uploader-icon"
|
||
}, null, 8, ["icon"])
|
||
])) : w("", !0)
|
||
]),
|
||
_: 1
|
||
}))
|
||
]),
|
||
f(y, {
|
||
ref: "cropperRef",
|
||
title: e.computedProps.title,
|
||
"cropper-height": e.computedProps.cropperHeight,
|
||
"dialog-width": e.computedProps.dialogWidth,
|
||
accept: e.computedProps.accept,
|
||
"upload-tip": e.computedProps.uploadTip,
|
||
"max-size": e.computedProps.maxSize,
|
||
cropper: e.computedProps.cropper,
|
||
"compress-quality": e.computedProps.compressQuality,
|
||
output: "all",
|
||
onDone: e.cropComplete,
|
||
onReady: e.doReady
|
||
}, null, 8, ["title", "cropper-height", "dialog-width", "accept", "upload-tip", "max-size", "cropper", "compress-quality", "onDone", "onReady"]),
|
||
m("div", {
|
||
class: z(["fs-cropper-preview", { open: e.previewVisible }]),
|
||
onClick: a[1] || (a[1] = (...i) => e.closePreview && e.closePreview(...i))
|
||
}, [
|
||
m("div", ue, [
|
||
e.previewUrl ? (n(), c("img", {
|
||
key: 0,
|
||
src: e.previewUrl,
|
||
class: "preview-image"
|
||
}, null, 8, pe)) : w("", !0)
|
||
])
|
||
], 2)
|
||
], 2);
|
||
}
|
||
const ve = /* @__PURE__ */ te(re, [["render", ce]]);
|
||
export {
|
||
ve as default
|
||
};
|
||
//# sourceMappingURL=fs-cropper-uploader-c3fbe88c.mjs.map
|