@glodon-aiot/react-components
Version:
aiot react components
440 lines (439 loc) • 13.9 kB
JavaScript
var g = (o, n, r) => new Promise((f, u) => {
var w = (l) => {
try {
e(r.next(l));
} catch (s) {
u(s);
}
}, h = (l) => {
try {
e(r.throw(l));
} catch (s) {
u(s);
}
}, e = (l) => l.done ? f(l.value) : Promise.resolve(l.value).then(w, h);
e((r = r.apply(o, n)).next());
});
import { jsxs as C, jsx as t } from "react/jsx-runtime";
import { useMemo as x, useState as p, useEffect as _, useCallback as M, useRef as de } from "react";
import { message as b, Space as ue, Button as D, Dropdown as me, Spin as Z, Alert as J } from "antd";
import { DownloadOutlined as L, CopyOutlined as pe } from "@ant-design/icons";
import { renderAsync as fe } from "docx-preview";
import { getFileExtension as V, getFileType as we } from "../../utils/file.mjs";
import { MAX_FILE_SIZE as B } from "./constants.mjs";
import { normalizeUrl as he } from "./utils.mjs";
import { useZipViewer as ye } from "./hooks/useZipViewer.mjs";
import { TextRenderer as X, CodeRenderer as ve, XmlRenderer as ge, HtmlRenderer as xe, MarkdownRenderer as be, JsonlRenderer as ke, TsvRenderer as Ce, CsvRenderer as Te, JsonRenderer as Re } from "./components/FileRenderers.mjs";
import { AudioRenderer as Fe, VideoRenderer as ze, ImageRenderer as Ne } from "./components/MediaRenderers.mjs";
import { ZipRenderer as Ee } from "./components/ZipRenderer.mjs";
import { ErrorAlert as Me } from "./components/ErrorAlert.mjs";
import "./style.less.mjs";
import Be from "./components/PDFViewer/index.mjs";
const De = (o) => {
if (!o)
return "unknown";
const n = o.split(";")[0].trim().toLowerCase();
return n.startsWith("image/") ? "image" : n.startsWith("video/") ? "video" : n.startsWith("audio/") ? "audio" : n === "application/pdf" ? "pdf" : n === "text/markdown" || n === "text/x-markdown" ? "markdown" : n === "application/json" ? "json" : n === "application/jsonl" ? "jsonl" : n === "text/csv" || n === "application/csv" ? "csv" : n === "text/tab-separated-values" ? "tsv" : n === "application/javascript" || n === "text/javascript" ? "code" : n === "application/xml" || n === "text/xml" ? "xml" : n === "text/html" || n === "application/xhtml+xml" ? "html" : n === "text/plain" ? "text" : "unknown";
}, Le = (o) => !o || Number.isNaN(o) ? "大小未知" : o < 1024 ? `${o}B` : o < 1024 * 1024 ? `${(o / 1024).toFixed(1)}KB` : o < 1024 * 1024 * 1024 ? `${(o / 1024 / 1024).toFixed(1)}MB` : `${(o / 1024 / 1024 / 1024).toFixed(1)}GB`, Se = (o, n) => {
if (n)
return n;
try {
const u = new URL(o).pathname.split("/").filter(Boolean).pop();
return decodeURIComponent(u || o);
} catch (r) {
return o;
}
}, je = (o) => {
const {
url: n,
fileName: r,
className: f,
style: u,
showToolbar: w = !1,
page: h = 1
} = o, e = x(() => he(n), [n]);
console.log("normalizedUrl", e);
const l = x(() => V(e) || V(r || ""), [e, r]), s = x(() => we(l), [l]), [k, T] = p(s), {
zipFiles: G,
zipLoading: K,
zipError: q,
selectedZipFile: Q,
zipFileContent: Y,
handleFileClick: ee
} = ye(s === "zip" ? e : ""), [te, m] = p(!0), [S, y] = p(null), [a, j] = p(null), [c, $] = p(0), [re, O] = p(!1), U = x(() => Se(e, r), [r, e]), ne = x(() => Le(c), [c]), R = !!(a != null && a.content), oe = !R && !e, ie = x(() => [{
key: "copy-content",
label: "复制内容",
disabled: !R
}, {
key: "copy-url",
label: "复制地址",
disabled: !e
}], [R, e]);
_(() => {
if (T(s), s === "pdf" || s === "zip") {
m(!1);
return;
}
if (!e) {
y("文件URL不能为空"), m(!1);
return;
}
if (["image", "video", "audio", "office"].includes(s)) {
m(!1);
return;
}
m(!0), y(null), g(void 0, null, function* () {
try {
if (e.startsWith("blob:") || e.startsWith("data:")) {
const v = yield fetch(e);
if (!v.ok)
throw new Error(`HTTP error! status: ${v.status}`);
const P = yield v.blob(), E = P.size;
if ($(E), E > B) {
y(`文件过大(${Math.round(E / 1024 / 1024)}MB),无法预览。请下载后查看。`), m(!1);
return;
}
const ce = yield P.text();
s === "unknown" && T("text"), j({
content: ce
}), m(!1);
return;
}
const i = yield fetch(e, {
method: "HEAD"
}), I = i.headers.get("Content-Length"), le = i.headers.get("Content-Type"), z = I ? parseInt(I, 10) : 0;
if ($(z), s === "unknown") {
const v = De(le);
v !== "unknown" && T(v);
}
if (z > B) {
y(`文件过大(${Math.round(z / 1024 / 1024)}MB),无法预览。请下载后查看。`), m(!1);
return;
}
const N = yield fetch(e);
if (!N.ok)
throw new Error(`HTTP error! status: ${N.status}`);
const A = yield N.text(), W = new Blob([A]).size;
if (W > B) {
y(`文件过大(${Math.round(W / 1024 / 1024)}MB),无法预览。请下载后查看。`), m(!1);
return;
}
k === "unknown" && T("text"), j({
content: A
}), m(!1);
} catch (d) {
y(d.message || "加载文件失败"), m(!1);
}
});
}, [e, s]);
const F = M(() => g(void 0, null, function* () {
var d;
if (!(a != null && a.content)) {
b.warning("暂无可复制的内容");
return;
}
try {
if (O(!0), (d = navigator == null ? void 0 : navigator.clipboard) != null && d.writeText)
yield navigator.clipboard.writeText(a.content);
else {
const i = document.createElement("textarea");
i.value = a.content, i.style.position = "fixed", i.style.opacity = "0", document.body.appendChild(i), i.select(), document.execCommand("copy"), document.body.removeChild(i);
}
b.success("内容已复制到剪贴板");
} catch (i) {
b.error((i == null ? void 0 : i.message) || "复制失败,请手动复制");
} finally {
O(!1);
}
}), [a]), H = M(() => g(void 0, null, function* () {
var d;
if (!e) {
b.warning("暂无可复制的地址");
return;
}
try {
if ((d = navigator == null ? void 0 : navigator.clipboard) != null && d.writeText)
yield navigator.clipboard.writeText(e);
else {
const i = document.createElement("textarea");
i.value = e, i.style.position = "fixed", i.style.opacity = "0", document.body.appendChild(i), i.select(), document.execCommand("copy"), document.body.removeChild(i);
}
b.success("链接已复制到剪贴板");
} catch (i) {
b.error((i == null ? void 0 : i.message) || "复制失败,请手动复制");
}
}), [e]), ae = M((i) => g(void 0, [i], function* ({
key: d
}) {
d === "copy-content" && (yield F()), d === "copy-url" && (yield H());
}), [F, H]), se = () => {
if (te)
return /* @__PURE__ */ t("div", {
className: "document-viewer-loading",
children: /* @__PURE__ */ t(Z, {
size: "large",
tip: "加载中..."
})
});
if (S)
return /* @__PURE__ */ t(Me, {
message: "加载失败",
description: S,
url: e,
fileName: r
});
if (k === "unknown" && (a != null && a.content))
return /* @__PURE__ */ t(X, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
switch (k) {
case "text":
return /* @__PURE__ */ t(X, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
case "json":
return /* @__PURE__ */ t(Re, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
case "csv":
return /* @__PURE__ */ t(Te, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
case "tsv":
return /* @__PURE__ */ t(Ce, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
case "jsonl":
return /* @__PURE__ */ t(ke, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
case "markdown":
return /* @__PURE__ */ t(be, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
case "html":
return /* @__PURE__ */ t(xe, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
case "xml":
return /* @__PURE__ */ t(ge, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
case "code":
return /* @__PURE__ */ t(ve, {
fileContent: a,
fileSize: c,
url: e,
fileName: r
});
case "image":
return /* @__PURE__ */ t(Ne, {
url: e,
fileName: r
});
case "video":
return /* @__PURE__ */ t(ze, {
url: e,
fileName: r
});
case "audio":
return /* @__PURE__ */ t(Fe, {
url: e,
fileName: r
});
case "pdf":
return /* @__PURE__ */ t(Be, {
fileUrl: e,
pageNumber: h
});
case "office":
return /* @__PURE__ */ t($e, {
url: e,
fileName: r,
extension: l
});
case "zip":
return /* @__PURE__ */ t(Ee, {
zipFiles: G,
zipLoading: K,
zipError: q,
selectedZipFile: Q,
zipFileContent: Y,
onFileClick: ee,
url: e
});
case "unknown":
default:
return /* @__PURE__ */ t(Ue, {
url: e
});
}
};
return /* @__PURE__ */ C("div", {
className: `document-viewer ${f || ""}`,
style: u,
children: [w && /* @__PURE__ */ C("div", {
className: "document-viewer-toolbar",
children: [/* @__PURE__ */ C("div", {
className: "document-viewer-toolbar-meta",
children: [/* @__PURE__ */ t("span", {
className: "document-viewer-toolbar-name",
title: U,
children: U
}), /* @__PURE__ */ t("span", {
className: "document-viewer-toolbar-size",
children: ne
})]
}), /* @__PURE__ */ C(ue, {
size: 8,
wrap: !0,
children: [/* @__PURE__ */ t(D, {
icon: /* @__PURE__ */ t(L, {}),
size: "small",
href: e,
target: "_blank",
rel: "noopener noreferrer",
download: r || void 0,
children: "下载"
}), /* @__PURE__ */ t(me.Button, {
size: "small",
icon: /* @__PURE__ */ t(pe, {}),
menu: {
items: ie,
onClick: ae
},
disabled: oe,
loading: re,
onClick: F,
children: "复制"
})]
})]
}), /* @__PURE__ */ t("div", {
className: "document-viewer-body",
children: se()
})]
});
}, $e = ({
url: o,
fileName: n,
extension: r
}) => r === "docx" ? /* @__PURE__ */ t(Oe, {
url: o,
fileName: n
}) : /* @__PURE__ */ t("div", {
className: "document-viewer-office",
children: /* @__PURE__ */ t(J, {
className: "document-viewer-alert-full",
message: "暂不支持在线预览",
description: "当前仅支持 docx 文件在线预览,其他 Office 文档请下载后查看。",
type: "info",
showIcon: !0,
action: /* @__PURE__ */ t(D, {
type: "link",
icon: /* @__PURE__ */ t(L, {}),
href: o,
download: n,
target: "_blank",
rel: "noopener noreferrer",
children: "下载文件"
})
})
}), Oe = ({
url: o,
fileName: n
}) => {
const r = de(null), [f, u] = p(!0), [w, h] = p(null);
return _(() => {
let e = !1;
const l = r.current;
return l && (l.innerHTML = ""), u(!0), h(null), g(void 0, null, function* () {
try {
const s = yield fetch(o);
if (!s.ok)
throw new Error(`HTTP error! status: ${s.status}`);
const k = yield s.blob();
if (e || !r.current)
return;
yield fe(k, r.current, void 0, {
inWrapper: !1,
ignoreWidth: !1,
ignoreHeight: !1,
breakPages: !0
}), e || u(!1);
} catch (s) {
e || (h((s == null ? void 0 : s.message) || "DOCX文件预览失败"), u(!1));
}
}), () => {
e = !0, l && (l.innerHTML = "");
};
}, [o]), /* @__PURE__ */ C("div", {
className: "document-viewer-office document-viewer-docx",
children: [f && /* @__PURE__ */ t("div", {
className: "document-viewer-loading",
children: /* @__PURE__ */ t(Z, {
size: "large",
tip: "加载DOCX中..."
})
}), w && /* @__PURE__ */ t(J, {
className: "document-viewer-alert-full",
message: "DOCX预览失败",
description: "文件无法在线预览,请下载后查看。",
type: "warning",
showIcon: !0,
action: /* @__PURE__ */ t(D, {
type: "link",
icon: /* @__PURE__ */ t(L, {}),
href: o,
download: n,
target: "_blank",
rel: "noopener noreferrer",
children: "下载文件"
})
}), /* @__PURE__ */ t("div", {
ref: r,
className: "document-viewer-docx-content",
style: {
display: f || w ? "none" : void 0
}
})]
});
}, Ue = ({
url: o
}) => /* @__PURE__ */ t("div", {
className: "document-viewer-unknown",
children: /* @__PURE__ */ t("iframe", {
src: o,
className: "document-viewer-iframe",
title: "File Preview"
})
}), tt = je;
export {
tt as default
};