UNPKG

@glodon-aiot/react-components

Version:

aiot react components

440 lines (439 loc) 13.9 kB
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 };