UNPKG

@matechat/core

Version:

前端智能化场景解决方案UI库,轻松构建你的AI应用。

288 lines (287 loc) 9 kB
import "./index.css"; import { computed as P, defineComponent as E, inject as U, ref as b, watch as N, onMounted as S, onBeforeUnmount as R, createBlock as k, openBlock as T, Teleport as V, withDirectives as M, createElementVNode as w, renderSlot as A, vShow as O, mergeModels as x, useSlots as B, useModel as $, provide as j, createElementBlock as z, unref as g, normalizeClass as _, createCommentVNode as H, withCtx as L, createTextVNode as W, toDisplayString as q } from "vue"; import { useMcI18n as Y } from "@matechat/core/Locale"; const K = { uploadOptions: { type: Object, default: () => ({}) }, disabled: { type: Boolean, default: !1 }, accept: { type: String, default: "" }, dropPlaceholder: { type: String }, maxCount: { type: Number, default: Number.POSITIVE_INFINITY }, maxSize: { type: Number, default: Number.POSITIVE_INFINITY }, multiple: { type: Boolean, default: !0 }, draggable: { type: Boolean, default: !0 }, beforeUpload: { type: Function, default: null }, getDropContainer: { type: Function } }, X = { change: (a, s) => a instanceof File && Array.isArray(s), success: (a, s, o) => a instanceof File && Array.isArray(o), error: (a, s, o) => a instanceof File && Array.isArray(o), progress: (a, s) => a instanceof File && Array.isArray(s), drop: (a) => Array.isArray(a), validChange: (a) => Array.isArray(a) }, I = "mc-attachment"; function G(a) { const { file: s, options: o, onProgress: i, onSuccess: h, onError: p } = a, t = new XMLHttpRequest(); t.upload.onprogress = (l) => { if (l.lengthComputable) { const r = Math.round(l.loaded * 100 / l.total); i(r); } }, t.onerror = () => { p({ message: "Upload failed due to a network error.", status: t.status, statusText: t.statusText }); }, t.onload = () => { if (t.status >= 200 && t.status < 300) { const l = o.responseType === "text" || !t.response ? t.responseText : t.response; h(l); } else p({ message: `Upload failed with status: ${t.status}`, status: t.status, statusText: t.statusText, response: t.response }); }; const c = new FormData(), m = o.fileFieldName || "file"; if (c.append(m, s, s.name), o.additionalParameter) for (const l of Object.keys(o.additionalParameter)) c.append(l, o.additionalParameter[l]); if (t.open(o.method || "POST", o.uri, !0), o.withCredentials && (t.withCredentials = !0), o.responseType && (t.responseType = o.responseType), o.headers) for (const l of Object.keys(o.headers)) t.setRequestHeader(l, o.headers[l]); if (o.authToken) { const l = o.authTokenHeader || "Authorization"; t.setRequestHeader(l, o.authToken); } t.send(c); } let J = Date.now(); function Q(a, s, o, i) { const h = P(() => a.disabled || i.value.length >= a.maxCount), p = (r) => { const d = URL.createObjectURL(r); return { uid: J++, name: r.name, size: r.size, type: r.type, status: "uploading", percentage: 0, url: d, thumbUrl: d }; }, t = async (r) => { if (r.length === 0) return; if (i.value.length + r.length > a.maxCount) { s("validChange", [{ type: "exceedCount" }]); return; } const d = [], u = []; for (const n of r) { let e = !0; if (a.accept && a.accept !== "*") { const f = a.accept.split(",").map((y) => y.trim().toLowerCase()), v = n.type.toLowerCase(), C = n.name.toLowerCase(); f.some((y) => y.endsWith("/*") ? v.startsWith(y.slice(0, -1)) : y.startsWith(".") ? C.endsWith(y) : v === y) || (u.push({ type: "unsupportedFileType", file: n }), e = !1); } if (e && n.size / 1024 / 1024 > a.maxSize && (u.push({ type: "exceedSizeLimit", file: n }), e = !1), e && a.beforeUpload) try { await Promise.resolve(a.beforeUpload(n)) === !1 && (u.push({ type: "beforeUploadRejected", file: n }), e = !1); } catch { u.push({ type: "beforeUploadRejected", file: n }), e = !1; } e && d.push(n); } if (u.length > 0 && s("validChange", u), d.length !== 0) for (const n of d) { const e = p(n); i.value.push(e), s("change", n, [...i.value]), c(n, e); } }, c = (r, d) => { const u = () => i.value.findIndex((n) => n.uid === d.uid); G({ file: r, options: a.uploadOptions, onProgress: (n) => { const e = u(); e > -1 && (i.value[e].percentage = n, s("progress", r, [...i.value])); }, onSuccess: (n) => { const e = u(); e > -1 && (i.value[e].status = "success", i.value[e].response = n, s("success", r, n, [...i.value])); }, onError: (n) => { const e = u(); e > -1 && (i.value[e].status = "uploadError", i.value[e].error = n, s("error", r, n, [...i.value])); } }); }; return { isDisabled: h, handleClick: () => { var r; h.value || (r = o.value) == null || r.click(); }, handleFileChange: (r) => { const d = r.target.files; d && t(Array.from(d)); }, uploadFiles: t }; } const Z = /* @__PURE__ */ E({ __name: "drop-area", setup(a) { const { rootProps: s, rootEmits: o, isDisabled: i, uploadFiles: h } = U( I ), p = b(), t = b(), c = b(!1); let m = 0; N( () => s.getDropContainer, (e) => { if (e) { const f = e(); p.value !== f && (p.value = f); } } ); const l = (e) => { if (e.preventDefault(), m++, m === 1 && (c.value = !0), p.value && t.value) if (p.value === document.body) t.value.style.inset = "0"; else { const { x: f, y: v, width: C, height: D } = p.value.getBoundingClientRect(); t.value.style.width = `${C}px`, t.value.style.height = `${D}px`, t.value.style.top = `${v}px`, t.value.style.left = `${f}px`; } }, r = (e) => { e.preventDefault(); }, d = (e) => { e.preventDefault(), m--, m === 0 && (c.value = !1); }, u = (e) => { var v; if (e.preventDefault(), c.value = !1, m = 0, i.value) return; const f = Array.from(((v = e.dataTransfer) == null ? void 0 : v.files) || []); f.length > 0 && (o("drop", f), h(f)); }; function n(e) { e.preventDefault(), c.value = !1, m = 0; } return S(() => { s.getDropContainer && (p.value = s.getDropContainer()), document.body.addEventListener("dragenter", l), document.body.addEventListener("dragover", r), document.body.addEventListener("dragleave", d), document.body.addEventListener("drop", n); }), R(() => { document.body.removeEventListener("dragenter", l), document.body.removeEventListener("dragover", r), document.body.removeEventListener("dragleave", d), document.body.removeEventListener("drop", n); }), (e, f) => (T(), k(V, { to: "body" }, [ M(w( "div", { ref_key: "dropAreaEl", ref: t, class: "mc-attachment-drop-area", onDrop: u }, [ A(e.$slots, "default") ], 544 /* NEED_HYDRATION, NEED_PATCH */ ), [ [O, c.value] ]) ])); } }), ee = ["accept", "multiple", "disabled"], F = /* @__PURE__ */ E({ name: "McAttachment", __name: "Attachment", props: /* @__PURE__ */ x(K, { modelValue: { default: [] }, modelModifiers: {} }), emits: /* @__PURE__ */ x(X, ["update:modelValue"]), setup(a, { emit: s }) { const o = a, i = s; B(); const h = $(a, "modelValue"), { t: p } = Y(), t = b(), { handleClick: c, handleFileChange: m, isDisabled: l, uploadFiles: r } = Q( o, i, t, h ); return j(I, { rootProps: o, rootEmits: i, isDisabled: l, uploadFiles: r }), (d, u) => (T(), z( "div", { class: _(["mc-attachment", { "is-disabled": g(l) }]), onClick: u[1] || (u[1] = //@ts-ignore (...n) => g(c) && g(c)(...n)) }, [ A(d.$slots, "default"), w("input", { ref_key: "inputRef", ref: t, type: "file", class: "mc-attachment-file", accept: d.accept, multiple: d.multiple, disabled: g(l), onChange: u[0] || (u[0] = //@ts-ignore (...n) => g(m) && g(m)(...n)) }, null, 40, ee), d.draggable ? (T(), k(Z, { key: 0 }, { default: L(() => [ A(d.$slots, "dropPlaceholder", {}, () => [ W( q(d.dropPlaceholder ?? g(p)("Attachment.dragToUpload")), 1 /* TEXT */ ) ]) ]), _: 3 /* FORWARDED */ })) : H("v-if", !0) ], 2 /* CLASS */ )); } }); F.install = (a) => { a.component("McAttachment", F); }; export { F as McAttachment };