UNPKG

sensitive-data-display

Version:

A Vue 3 component for displaying sensitive data with masking and toggle functionality

286 lines (285 loc) 8.39 kB
import { defineComponent as b, ref as h, computed as q, openBlock as v, createElementBlock as A, createVNode as p, unref as y, withCtx as D, createElementVNode as B, normalizeClass as T, toDisplayString as O, createBlock as _, createCommentVNode as H, h as K } from "vue"; import { Tooltip as z, Button as J } from "ant-design-vue"; import { EyeOutlined as W, EyeInvisibleOutlined as X } from "@ant-design/icons-vue"; const L = { class: "sensitive-data-display" }, M = "SENSITIVE_CACHE_", U = /* @__PURE__ */ b({ __name: "SensitiveDataDisplay", props: { value: {}, mode: { default: "server" }, type: { default: "custom" }, showStart: { default: 3 }, showEnd: { default: 4 }, maskChar: { default: "*" }, defaultVisible: { type: Boolean, default: !1 }, fetchFullData: {}, dataId: {}, cacheExpiry: { default: 10 }, cacheStorage: { default: "memory" } }, emits: ["toggleRequest"], setup(e, { expose: o, emit: s }) { const t = e, r = s, n = h(t.defaultVisible), l = h(!1), u = h(""), m = h(0), S = h(!1), g = () => `${M}${t.dataId || "default"}`, d = { // 写入缓存 setCache(a, c) { try { const i = JSON.stringify(c); switch (t.cacheStorage) { case "session": sessionStorage.setItem(a, i); break; case "local": localStorage.setItem(a, i); break; case "memory": default: u.value = c.data, m.value = c.timestamp; break; } } catch (i) { console.warn("Failed to set cache:", i); } }, // 读取缓存 getCache(a) { try { let c = null; switch (t.cacheStorage) { case "session": c = sessionStorage.getItem(a); break; case "local": c = localStorage.getItem(a); break; case "memory": default: return u.value && m.value ? { data: u.value, timestamp: m.value, expiry: t.cacheExpiry * 60 * 1e3 } : null; } if (c) return JSON.parse(c); } catch (c) { console.warn("Failed to get cache:", c); } return null; }, // 清除缓存 clearCache(a) { try { switch (t.cacheStorage) { case "session": sessionStorage.removeItem(a); break; case "local": localStorage.removeItem(a); break; case "memory": default: u.value = "", m.value = 0; break; } } catch (c) { console.warn("Failed to clear cache:", c); } } }, I = () => { const a = g(), c = d.getCache(a); return c && Date.now() - c.timestamp < c.expiry ? c.data : (d.clearCache(a), null); }, f = async () => { if (!l.value) { if (t.mode === "custom") { r("toggleRequest", !n, t.dataId); return; } n.value ? n.value = !1 : await x(); } }, x = async () => { if (!l.value) try { l.value = !0, S.value = !1; let a = ""; if (t.mode === "server") if (t.fetchFullData) a = await t.fetchFullData(); else throw new Error("fetchFullData function is required for server mode"); else a = t.value; const c = g(), i = { data: a, timestamp: Date.now(), expiry: t.cacheExpiry * 60 * 1e3 }; d.setCache(c, i), n.value = !0; } catch (a) { console.error("Failed to fetch full data:", a), S.value = !0; } finally { l.value = !1; } }, F = (a, c) => { if (!a) return ""; switch (c) { case "phone": return a.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2"); case "idCard": return a.replace(/(\d{6})\d{8}(\d{4})/, "$1********$2"); case "bankCard": return a.replace(/(\d{4})\d{8}(\d{4})/, "$1********$2"); case "email": const [i, V] = a.split("@"); return i.length <= 2 ? a : `${i.substring(0, 2)}***@${V}`; case "custom": default: if (a.length <= t.showStart + t.showEnd) return a; const $ = a.substring(0, t.showStart), N = a.substring(a.length - t.showEnd), R = t.maskChar.repeat(a.length - t.showStart - t.showEnd); return `${$}${R}${N}`; } }, C = q(() => n.value ? t.mode === "server" && I() || t.value : F(t.value, t.type)); return o({ // 设置完整数据并显示 setFullDataAndShow: (a) => { u.value = a, m.value = Date.now(), n.value = !0; }, // 隐藏数据 hideData: () => { n.value = !1; }, // 切换显示状态 toggle: () => { f(); }, // 获取当前显示状态 getVisibleState: () => n.value, // 清除缓存 clearCache: () => { const a = g(); d.clearCache(a); } }), (a, c) => (v(), A("div", L, [ p(y(z), { title: C.value, placement: "top" }, { default: D(() => [ B("span", { class: T(["data-text", { "is-masked": !n.value && t.mode === "client" }]) }, O(C.value), 3) ]), _: 1 }, 8, ["title"]), p(y(J), { type: "text", size: "small", class: "toggle-btn", onClick: f, loading: l.value }, { icon: D(() => [ !n.value && !l.value ? (v(), _(y(W), { key: 0 })) : n.value && !l.value ? (v(), _(y(X), { key: 1 })) : H("", !0) ]), _: 1 }, 8, ["loading"]) ])); } }); const j = (e, o) => { const s = e.__vccOpts || e; for (const [t, r] of o) s[t] = r; return s; }, k = /* @__PURE__ */ j(U, [["__scopeId", "data-v-8cb6442a"]]), w = "SENSITIVE_CACHE_", E = (e, o) => { const s = []; for (let t = 0; t < e.length; t++) { const r = e.key(t); r && r.startsWith(o) && s.push(r); } s.forEach((t) => e.removeItem(t)); }, Z = (e) => { const o = () => b({ name: "SensitiveDataDisplayWrapper", props: { value: { type: String, required: !0 }, mode: { type: String, default: (e == null ? void 0 : e.mode) || "server" }, type: { type: String, default: (e == null ? void 0 : e.type) || "custom" }, showStart: { type: Number, default: (e == null ? void 0 : e.showStart) || 3 }, showEnd: { type: Number, default: (e == null ? void 0 : e.showEnd) || 4 }, maskChar: { type: String, default: (e == null ? void 0 : e.maskChar) || "*" }, defaultVisible: { type: Boolean, default: (e == null ? void 0 : e.defaultVisible) || !1 }, fetchFullData: { type: Function, default: e == null ? void 0 : e.fetchFullData }, dataId: { type: [String, Number], default: e == null ? void 0 : e.dataId }, cacheExpiry: { type: Number, default: (e == null ? void 0 : e.cacheExpiry) || 10 }, cacheStorage: { type: String, default: (e == null ? void 0 : e.cacheStorage) || "memory" } }, emits: ["toggleRequest"], setup(s, { emit: t, attrs: r }) { const n = h(); return () => K(k, { ref: n, ...s, ...r, onToggleRequest: (l, u) => { t("toggleRequest", l, u); } }); } }); return { SensitiveDataDisplayComponent: o(), createComponent: o }; }, P = () => { try { typeof sessionStorage < "u" && E(sessionStorage, w), typeof localStorage < "u" && E(localStorage, w), console.log("All sensitive data cache cleared"); } catch (e) { console.warn("Failed to clear sensitive cache:", e); } }, ee = { install: (e) => { e.component("SensitiveDataDisplay", k); } }; export { k as SensitiveDataDisplay, P as clearAllSensitiveCache, ee as default, Z as useSensitiveDataDisplay };