@hkyhy/marsun-components-core 0.1.101 → 0.1.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Editor/VariablePicker.js +13 -13
- package/dist/components/Editor/VariablePicker.js.map +1 -1
- package/dist/components/FormInfo/RichTextField/index.js +46 -69
- package/dist/components/FormInfo/RichTextField/index.js.map +1 -1
- package/dist/components/FormInfo/VariableMentionInput/index.d.ts +1 -0
- package/dist/components/FormInfo/VariableMentionInput/index.js +53 -47
- package/dist/components/FormInfo/VariableMentionInput/index.js.map +1 -1
- package/dist/components/FormInfo/VariableMentionInput/style.module.scss.js +6 -5
- package/dist/components/FormInfo/VariableMentionInput/style.module.scss.js.map +1 -1
- package/dist/components/Tools/Inbox/InboxBell/InboxBell.d.ts +3 -0
- package/dist/components/Tools/Inbox/InboxBell/InboxBell.js +59 -49
- package/dist/components/Tools/Inbox/InboxBell/InboxBell.js.map +1 -1
- package/dist/components/Tools/Inbox/InboxBell/style.module.scss.js +20 -18
- package/dist/components/Tools/Inbox/InboxBell/style.module.scss.js.map +1 -1
- package/dist/components/Tools/Inbox/index.d.ts +1 -0
- package/dist/components/Tools/Inbox/sanitizeInboxHtml.d.ts +5 -0
- package/dist/components/Tools/Inbox/sanitizeInboxHtml.js +14 -0
- package/dist/components/Tools/Inbox/sanitizeInboxHtml.js.map +1 -0
- package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/Modal/TemplateFormModal.js +100 -99
- package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/Modal/TemplateFormModal.js.map +1 -1
- package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/PushRulesPanel/index.js +47 -45
- package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/PushRulesPanel/index.js.map +1 -1
- package/dist/components/Tools/MessageCenter/MsgCenterAppSwitcher/MsgCenterAppSwitcher.d.ts +22 -0
- package/dist/components/Tools/MessageCenter/MsgCenterAppSwitcher/MsgCenterAppSwitcher.js +64 -0
- package/dist/components/Tools/MessageCenter/MsgCenterAppSwitcher/MsgCenterAppSwitcher.js.map +1 -0
- package/dist/components/Tools/MessageCenter/MsgCenterAppSwitcher/index.d.ts +2 -0
- package/dist/components/Tools/MessageCenter/index.d.ts +5 -0
- package/dist/components/Tools/MessageCenter/msgCenterAppSwitch.d.ts +39 -0
- package/dist/components/Tools/MessageCenter/msgCenterAppSwitch.js +94 -0
- package/dist/components/Tools/MessageCenter/msgCenterAppSwitch.js.map +1 -0
- package/dist/components/Tools/MessageCenter/useMsgCenterAppKey.d.ts +2 -0
- package/dist/components/Tools/MessageCenter/useMsgCenterAppKey.js +18 -0
- package/dist/components/Tools/MessageCenter/useMsgCenterAppKey.js.map +1 -0
- package/dist/components/Tools/index.d.ts +2 -1
- package/dist/index.js +641 -626
- package/dist/index.js.map +1 -1
- package/dist/marsun-components-core.css +1 -1
- package/dist/node_modules/dompurify/dist/purify.es.js +908 -0
- package/dist/node_modules/dompurify/dist/purify.es.js.map +1 -0
- package/dist/node_modules/isomorphic-dompurify/dist/browser.js +17 -0
- package/dist/node_modules/isomorphic-dompurify/dist/browser.js.map +1 -0
- package/dist/styles/global.css +1 -1
- package/package.json +2 -1
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
import { jsxs as b, jsx as a } from "react/jsx-runtime";
|
|
2
|
-
import { Badge as
|
|
3
|
-
import
|
|
4
|
-
import { useState as n, useCallback as
|
|
5
|
-
import
|
|
2
|
+
import { Badge as R, Button as U, Drawer as W, Space as $, message as A } from "antd";
|
|
3
|
+
import x from "classnames";
|
|
4
|
+
import { useState as n, useCallback as E, useEffect as T, useMemo as F } from "react";
|
|
5
|
+
import { sanitizeInboxHtml as D } from "../sanitizeInboxHtml.js";
|
|
6
|
+
import t from "./style.module.scss.js";
|
|
6
7
|
import { Bell as K } from "../../../Icons/Bell.js";
|
|
7
8
|
import Y from "../../../StateBar/StateBar.js";
|
|
8
9
|
import q from "../../../SegmentedRadio/SegmentedRadio.js";
|
|
9
10
|
import G from "../../../Layout/PageSpin/index.js";
|
|
10
|
-
import
|
|
11
|
-
const
|
|
11
|
+
import J from "../../../Empty/Empty.js";
|
|
12
|
+
const Q = [
|
|
12
13
|
{ key: "", label: "全部" },
|
|
13
14
|
{ key: "alert", label: "预警" },
|
|
14
15
|
{ key: "action", label: "行动" },
|
|
15
16
|
{ key: "remind", label: "提醒" }
|
|
16
|
-
],
|
|
17
|
+
], ie = ({
|
|
17
18
|
fetchInbox: o,
|
|
18
19
|
markRead: M,
|
|
19
20
|
onNavigate: v,
|
|
20
21
|
pollMs: m = 6e4,
|
|
21
22
|
pageSize: w = 50,
|
|
22
|
-
className:
|
|
23
|
-
title:
|
|
23
|
+
className: H,
|
|
24
|
+
title: I = "站内信"
|
|
24
25
|
}) => {
|
|
25
|
-
const [p, i] = n(!1), [B,
|
|
26
|
-
|
|
26
|
+
const [p, i] = n(!1), [B, N] = n(!1), [u, k] = n(""), [S, y] = n([]), [s, f] = n(0), [C, z] = n({}), [h, P] = n(""), [d, _] = n("all"), O = E(async () => {
|
|
27
|
+
N(!0), k("");
|
|
27
28
|
try {
|
|
28
29
|
const e = await o({
|
|
29
30
|
currentPage: 1,
|
|
@@ -32,16 +33,16 @@ const J = [
|
|
|
32
33
|
unreadOnly: d === "unread" || void 0,
|
|
33
34
|
readOnly: d === "read" || void 0
|
|
34
35
|
});
|
|
35
|
-
y((e == null ? void 0 : e.itemList) || []), f(typeof (e == null ? void 0 : e.unreadTotal) == "number" ? e.unreadTotal : 0),
|
|
36
|
+
y((e == null ? void 0 : e.itemList) || []), f(typeof (e == null ? void 0 : e.unreadTotal) == "number" ? e.unreadTotal : 0), z((e == null ? void 0 : e.unreadByMessageType) || {});
|
|
36
37
|
} catch (e) {
|
|
37
|
-
y([]),
|
|
38
|
+
y([]), k(e instanceof Error ? e.message : String(e));
|
|
38
39
|
} finally {
|
|
39
|
-
|
|
40
|
+
N(!1);
|
|
40
41
|
}
|
|
41
|
-
}, [o, h, w, d]), c =
|
|
42
|
+
}, [o, h, w, d]), c = E(async () => {
|
|
42
43
|
try {
|
|
43
44
|
const e = await o({ currentPage: 1, pageSize: 1 });
|
|
44
|
-
f(typeof (e == null ? void 0 : e.unreadTotal) == "number" ? e.unreadTotal : 0),
|
|
45
|
+
f(typeof (e == null ? void 0 : e.unreadTotal) == "number" ? e.unreadTotal : 0), z((e == null ? void 0 : e.unreadByMessageType) || {});
|
|
45
46
|
} catch {
|
|
46
47
|
}
|
|
47
48
|
}, [o]);
|
|
@@ -54,54 +55,54 @@ const J = [
|
|
|
54
55
|
}, m);
|
|
55
56
|
return () => window.clearInterval(e);
|
|
56
57
|
}, [m, c]), T(() => {
|
|
57
|
-
p &&
|
|
58
|
-
}, [p,
|
|
59
|
-
const
|
|
60
|
-
() =>
|
|
61
|
-
const
|
|
58
|
+
p && O();
|
|
59
|
+
}, [p, O]);
|
|
60
|
+
const j = F(
|
|
61
|
+
() => Q.map((e) => {
|
|
62
|
+
const r = e.key ? C[e.key] || 0 : s;
|
|
62
63
|
return {
|
|
63
64
|
key: e.key || "all",
|
|
64
|
-
label:
|
|
65
|
+
label: r > 0 ? `${e.label} (${r})` : e.label
|
|
65
66
|
};
|
|
66
67
|
}),
|
|
67
68
|
[C, s]
|
|
68
|
-
),
|
|
69
|
+
), L = async (e) => {
|
|
69
70
|
if (!e.read)
|
|
70
71
|
try {
|
|
71
72
|
await M(e.id), y((l) => l.map((g) => g.id === e.id ? { ...g, read: !0 } : g)), f((l) => Math.max(0, l - 1));
|
|
72
73
|
} catch (l) {
|
|
73
|
-
|
|
74
|
+
A.error(l instanceof Error ? l.message : "标记已读失败");
|
|
74
75
|
return;
|
|
75
76
|
}
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
77
|
+
const r = String(e.href || "").trim();
|
|
78
|
+
if (r) {
|
|
78
79
|
if (v) {
|
|
79
|
-
v(
|
|
80
|
+
v(r, e), i(!1);
|
|
80
81
|
return;
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
+
r.startsWith("http://") || r.startsWith("https://") ? window.open(r, "_blank", "noopener,noreferrer") : window.location.assign(r), i(!1);
|
|
83
84
|
}
|
|
84
85
|
};
|
|
85
|
-
return /* @__PURE__ */ b("div", { className:
|
|
86
|
-
/* @__PURE__ */ a(
|
|
87
|
-
|
|
86
|
+
return /* @__PURE__ */ b("div", { className: x(t.bellWrap, H), children: [
|
|
87
|
+
/* @__PURE__ */ a(R, { count: s, size: "small", overflowCount: 99, offset: [-4, 4], children: /* @__PURE__ */ a(
|
|
88
|
+
U,
|
|
88
89
|
{
|
|
89
90
|
type: "text",
|
|
90
|
-
className:
|
|
91
|
+
className: t.bellBtn,
|
|
91
92
|
icon: /* @__PURE__ */ a(K, { size: 16, "aria-hidden": !0 }),
|
|
92
93
|
"aria-label": s > 0 ? `站内信,${s} 条未读` : "站内信",
|
|
93
94
|
onClick: () => i(!0)
|
|
94
95
|
}
|
|
95
96
|
) }),
|
|
96
97
|
/* @__PURE__ */ b(
|
|
97
|
-
|
|
98
|
+
W,
|
|
98
99
|
{
|
|
99
|
-
title:
|
|
100
|
+
title: I,
|
|
100
101
|
open: p,
|
|
101
102
|
onClose: () => i(!1),
|
|
102
103
|
size: 420,
|
|
103
104
|
destroyOnClose: !1,
|
|
104
|
-
className:
|
|
105
|
+
className: t.drawer,
|
|
105
106
|
styles: {
|
|
106
107
|
header: { padding: "12px 16px" },
|
|
107
108
|
body: { padding: "12px 16px" }
|
|
@@ -110,20 +111,20 @@ const J = [
|
|
|
110
111
|
/* @__PURE__ */ a(
|
|
111
112
|
Y,
|
|
112
113
|
{
|
|
113
|
-
className:
|
|
114
|
+
className: t.typeTabs,
|
|
114
115
|
size: "small",
|
|
115
116
|
activeKey: h || "all",
|
|
116
|
-
onChange: (e) =>
|
|
117
|
-
stateOption:
|
|
117
|
+
onChange: (e) => P(e === "all" ? "" : e),
|
|
118
|
+
stateOption: j,
|
|
118
119
|
isInner: !0
|
|
119
120
|
}
|
|
120
121
|
),
|
|
121
|
-
/* @__PURE__ */ a("div", { className:
|
|
122
|
+
/* @__PURE__ */ a("div", { className: t.filterRow, children: /* @__PURE__ */ a(
|
|
122
123
|
q,
|
|
123
124
|
{
|
|
124
125
|
size: "small",
|
|
125
126
|
value: d,
|
|
126
|
-
onChange: (e) =>
|
|
127
|
+
onChange: (e) => _(e),
|
|
127
128
|
options: [
|
|
128
129
|
{ value: "all", label: "全部" },
|
|
129
130
|
{ value: "unread", label: "未读" },
|
|
@@ -131,17 +132,26 @@ const J = [
|
|
|
131
132
|
]
|
|
132
133
|
}
|
|
133
134
|
) }),
|
|
134
|
-
u ? /* @__PURE__ */ a("p", { className:
|
|
135
|
-
/* @__PURE__ */ a(G, { spinning: B, children: !B && !u && S.length === 0 ? /* @__PURE__ */ a(
|
|
135
|
+
u ? /* @__PURE__ */ a("p", { className: t.error, children: u }) : null,
|
|
136
|
+
/* @__PURE__ */ a(G, { spinning: B, children: !B && !u && S.length === 0 ? /* @__PURE__ */ a(J, { description: "暂无站内信" }) : /* @__PURE__ */ a("ul", { className: t.list, children: S.map((e) => /* @__PURE__ */ a("li", { children: /* @__PURE__ */ a(
|
|
136
137
|
"button",
|
|
137
138
|
{
|
|
138
139
|
type: "button",
|
|
139
|
-
className:
|
|
140
|
-
onClick: () => void
|
|
141
|
-
children: /* @__PURE__ */ b(
|
|
142
|
-
/* @__PURE__ */ a("span", { className:
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
className: x(t.item, !e.read && t.itemUnread),
|
|
141
|
+
onClick: () => void L(e),
|
|
142
|
+
children: /* @__PURE__ */ b($, { orientation: "vertical", size: 2, style: { width: "100%" }, children: [
|
|
143
|
+
/* @__PURE__ */ a("span", { className: t.itemTitle, children: e.title || "(无标题)" }),
|
|
144
|
+
(() => {
|
|
145
|
+
const r = D(e.bodyHtml);
|
|
146
|
+
return r ? /* @__PURE__ */ a(
|
|
147
|
+
"div",
|
|
148
|
+
{
|
|
149
|
+
className: t.itemBodyHtml,
|
|
150
|
+
dangerouslySetInnerHTML: { __html: r }
|
|
151
|
+
}
|
|
152
|
+
) : e.summary ? /* @__PURE__ */ a("span", { className: t.itemSummary, children: e.summary }) : null;
|
|
153
|
+
})(),
|
|
154
|
+
/* @__PURE__ */ a("span", { className: t.itemMeta, children: [e.messageType, e.createdAt].filter(Boolean).join(" · ") || "—" })
|
|
145
155
|
] })
|
|
146
156
|
}
|
|
147
157
|
) }, e.id)) }) })
|
|
@@ -151,6 +161,6 @@ const J = [
|
|
|
151
161
|
] });
|
|
152
162
|
};
|
|
153
163
|
export {
|
|
154
|
-
|
|
164
|
+
ie as default
|
|
155
165
|
};
|
|
156
166
|
//# sourceMappingURL=InboxBell.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InboxBell.js","sources":["../../../../../src/components/Tools/Inbox/InboxBell/InboxBell.tsx"],"sourcesContent":["import { Badge, Button, Drawer, Space, message } from 'antd';\nimport classNames from 'classnames';\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Empty } from '@/components/Empty';\nimport { Bell } from '@/components/Icons';\nimport { PageSpin } from '@/components/Layout';\nimport { SegmentedRadio } from '@/components/SegmentedRadio';\nimport { StateBar } from '@/components/StateBar';\nimport styles from './style.module.scss';\n\nexport type InboxBellMessageType = 'alert' | 'action' | 'remind' | string;\n\nexport type InboxBellItem = {\n id: string;\n title?: string;\n summary?: string;\n read?: boolean;\n messageType?: InboxBellMessageType;\n href?: string;\n createdAt?: string;\n level?: string;\n};\n\nexport type InboxBellListResult = {\n itemList: InboxBellItem[];\n total?: number;\n unreadTotal?: number;\n unreadByMessageType?: Partial<Record<string, number>>;\n};\n\nexport type InboxBellListParams = {\n unreadOnly?: boolean;\n readOnly?: boolean;\n messageType?: InboxBellMessageType;\n currentPage?: number;\n pageSize?: number;\n};\n\nexport type InboxBellProps = {\n /** 拉取站内信(业务注入;须带 JWT 身份,禁止无身份全表) */\n fetchInbox: (params: InboxBellListParams) => Promise<InboxBellListResult>;\n /** 标记已读 */\n markRead: (id: string) => Promise<void | InboxBellItem>;\n /** 点击条目:默认用 window.location / 业务 navigate */\n onNavigate?: (href: string, item: InboxBellItem) => void;\n /** 轮询未读角标(ms);≤0 关闭 */\n pollMs?: number;\n pageSize?: number;\n className?: string;\n /** Drawer 标题 */\n title?: string;\n};\n\nconst TYPE_TABS: Array<{ key: string; label: string }> = [\n { key: '', label: '全部' },\n { key: 'alert', label: '预警' },\n { key: 'action', label: '行动' },\n { key: 'remind', label: '提醒' },\n];\n\n/**\n * 通用站内信铃铛:列表 / 已读 / Tab / 角标。\n * 不含认领、行动等业务动作;由注入的 fetchInbox / markRead / onNavigate 对接消息服务。\n */\nconst InboxBell: React.FC<InboxBellProps> = ({\n fetchInbox,\n markRead,\n onNavigate,\n pollMs = 60_000,\n pageSize = 50,\n className,\n title = '站内信',\n}) => {\n const [open, setOpen] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [items, setItems] = useState<InboxBellItem[]>([]);\n const [unreadTotal, setUnreadTotal] = useState(0);\n const [unreadByType, setUnreadByType] = useState<Partial<Record<string, number>>>({});\n const [messageType, setMessageType] = useState<string>('');\n const [readFilter, setReadFilter] = useState<'all' | 'unread' | 'read'>('all');\n\n const load = useCallback(async () => {\n setLoading(true);\n setError('');\n try {\n const res = await fetchInbox({\n currentPage: 1,\n pageSize,\n messageType: messageType || undefined,\n unreadOnly: readFilter === 'unread' || undefined,\n readOnly: readFilter === 'read' || undefined,\n });\n setItems(res?.itemList || []);\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch (e) {\n setItems([]);\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setLoading(false);\n }\n }, [fetchInbox, messageType, pageSize, readFilter]);\n\n const refreshBadge = useCallback(async () => {\n try {\n const res = await fetchInbox({ currentPage: 1, pageSize: 1 });\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch {\n /* 角标失败不打断 UI */\n }\n }, [fetchInbox]);\n\n useEffect(() => {\n void refreshBadge();\n }, [refreshBadge]);\n\n useEffect(() => {\n if (pollMs <= 0) return undefined;\n const t = window.setInterval(() => {\n void refreshBadge();\n }, pollMs);\n return () => window.clearInterval(t);\n }, [pollMs, refreshBadge]);\n\n useEffect(() => {\n if (open) void load();\n }, [open, load]);\n\n const typeTabOptions = useMemo(\n () =>\n TYPE_TABS.map((t) => {\n const n = t.key ? unreadByType[t.key] || 0 : unreadTotal;\n return {\n key: t.key || 'all',\n label: n > 0 ? `${t.label} (${n})` : t.label,\n };\n }),\n [unreadByType, unreadTotal],\n );\n\n const handleOpenItem = async (item: InboxBellItem) => {\n if (!item.read) {\n try {\n await markRead(item.id);\n setItems((prev) => prev.map((x) => (x.id === item.id ? { ...x, read: true } : x)));\n setUnreadTotal((n) => Math.max(0, n - 1));\n } catch (e) {\n message.error(e instanceof Error ? e.message : '标记已读失败');\n return;\n }\n }\n const href = String(item.href || '').trim();\n if (!href) return;\n if (onNavigate) {\n onNavigate(href, item);\n setOpen(false);\n return;\n }\n if (href.startsWith('http://') || href.startsWith('https://')) {\n window.open(href, '_blank', 'noopener,noreferrer');\n } else {\n window.location.assign(href);\n }\n setOpen(false);\n };\n\n return (\n <div className={classNames(styles.bellWrap, className)}>\n <Badge count={unreadTotal} size=\"small\" overflowCount={99} offset={[-4, 4]}>\n <Button\n type=\"text\"\n className={styles.bellBtn}\n icon={<Bell size={16} aria-hidden />}\n aria-label={unreadTotal > 0 ? `站内信,${unreadTotal} 条未读` : '站内信'}\n onClick={() => setOpen(true)}\n />\n </Badge>\n <Drawer\n title={title}\n open={open}\n onClose={() => setOpen(false)}\n size={420}\n destroyOnClose={false}\n className={styles.drawer}\n styles={{\n header: { padding: '12px 16px' },\n body: { padding: '12px 16px' },\n }}\n >\n <StateBar\n className={styles.typeTabs}\n size=\"small\"\n activeKey={messageType || 'all'}\n onChange={(k) => setMessageType(k === 'all' ? '' : k)}\n stateOption={typeTabOptions}\n isInner\n />\n <div className={styles.filterRow}>\n <SegmentedRadio<'all' | 'unread' | 'read'>\n size=\"small\"\n value={readFilter}\n onChange={(v) => setReadFilter(v)}\n options={[\n { value: 'all', label: '全部' },\n { value: 'unread', label: '未读' },\n { value: 'read', label: '已读' },\n ]}\n />\n </div>\n {error ? <p className={styles.error}>{error}</p> : null}\n <PageSpin spinning={loading}>\n {!loading && !error && items.length === 0 ? (\n <Empty description=\"暂无站内信\" />\n ) : (\n <ul className={styles.list}>\n {items.map((item) => (\n <li key={item.id}>\n <button\n type=\"button\"\n className={classNames(styles.item, !item.read && styles.itemUnread)}\n onClick={() => void handleOpenItem(item)}\n >\n <Space orientation=\"vertical\" size={2} style={{ width: '100%' }}>\n <span className={styles.itemTitle}>{item.title || '(无标题)'}</span>\n {item.summary ? (\n <span className={styles.itemSummary}>{item.summary}</span>\n ) : null}\n <span className={styles.itemMeta}>\n {[item.messageType, item.createdAt].filter(Boolean).join(' · ') || '—'}\n </span>\n </Space>\n </button>\n </li>\n ))}\n </ul>\n )}\n </PageSpin>\n </Drawer>\n </div>\n );\n};\n\nexport default InboxBell;\n"],"names":["TYPE_TABS","InboxBell","fetchInbox","markRead","onNavigate","pollMs","pageSize","className","title","open","setOpen","useState","loading","setLoading","error","setError","items","setItems","unreadTotal","setUnreadTotal","unreadByType","setUnreadByType","messageType","setMessageType","readFilter","setReadFilter","load","useCallback","res","refreshBadge","useEffect","t","typeTabOptions","useMemo","n","handleOpenItem","item","prev","x","e","message","href","classNames","styles","jsx","Badge","Button","Bell","jsxs","Drawer","StateBar","k","SegmentedRadio","v","PageSpin","Empty","Space"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InboxBell.js","sources":["../../../../../src/components/Tools/Inbox/InboxBell/InboxBell.tsx"],"sourcesContent":["import { Badge, Button, Drawer, Space, message } from 'antd';\nimport classNames from 'classnames';\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Empty } from '@/components/Empty';\nimport { Bell } from '@/components/Icons';\nimport { PageSpin } from '@/components/Layout';\nimport { SegmentedRadio } from '@/components/SegmentedRadio';\nimport { StateBar } from '@/components/StateBar';\nimport { sanitizeInboxHtml } from '../sanitizeInboxHtml';\nimport styles from './style.module.scss';\n\nexport type InboxBellMessageType = 'alert' | 'action' | 'remind' | string;\n\nexport type InboxBellItem = {\n id: string;\n title?: string;\n /** 纯文本摘要(列表兼容) */\n summary?: string;\n /** 已渲染 HTML 正文;空则主摘要位回落 summary */\n bodyHtml?: string | null;\n read?: boolean;\n messageType?: InboxBellMessageType;\n href?: string;\n createdAt?: string;\n level?: string;\n};\n\nexport type InboxBellListResult = {\n itemList: InboxBellItem[];\n total?: number;\n unreadTotal?: number;\n unreadByMessageType?: Partial<Record<string, number>>;\n};\n\nexport type InboxBellListParams = {\n unreadOnly?: boolean;\n readOnly?: boolean;\n messageType?: InboxBellMessageType;\n currentPage?: number;\n pageSize?: number;\n};\n\nexport type InboxBellProps = {\n /** 拉取站内信(业务注入;须带 JWT 身份,禁止无身份全表) */\n fetchInbox: (params: InboxBellListParams) => Promise<InboxBellListResult>;\n /** 标记已读 */\n markRead: (id: string) => Promise<void | InboxBellItem>;\n /** 点击条目:默认用 window.location / 业务 navigate */\n onNavigate?: (href: string, item: InboxBellItem) => void;\n /** 轮询未读角标(ms);≤0 关闭 */\n pollMs?: number;\n pageSize?: number;\n className?: string;\n /** Drawer 标题 */\n title?: string;\n};\n\nconst TYPE_TABS: Array<{ key: string; label: string }> = [\n { key: '', label: '全部' },\n { key: 'alert', label: '预警' },\n { key: 'action', label: '行动' },\n { key: 'remind', label: '提醒' },\n];\n\n/**\n * 通用站内信铃铛:列表 / 已读 / Tab / 角标。\n * 不含认领、行动等业务动作;由注入的 fetchInbox / markRead / onNavigate 对接消息服务。\n */\nconst InboxBell: React.FC<InboxBellProps> = ({\n fetchInbox,\n markRead,\n onNavigate,\n pollMs = 60_000,\n pageSize = 50,\n className,\n title = '站内信',\n}) => {\n const [open, setOpen] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [items, setItems] = useState<InboxBellItem[]>([]);\n const [unreadTotal, setUnreadTotal] = useState(0);\n const [unreadByType, setUnreadByType] = useState<Partial<Record<string, number>>>({});\n const [messageType, setMessageType] = useState<string>('');\n const [readFilter, setReadFilter] = useState<'all' | 'unread' | 'read'>('all');\n\n const load = useCallback(async () => {\n setLoading(true);\n setError('');\n try {\n const res = await fetchInbox({\n currentPage: 1,\n pageSize,\n messageType: messageType || undefined,\n unreadOnly: readFilter === 'unread' || undefined,\n readOnly: readFilter === 'read' || undefined,\n });\n setItems(res?.itemList || []);\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch (e) {\n setItems([]);\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setLoading(false);\n }\n }, [fetchInbox, messageType, pageSize, readFilter]);\n\n const refreshBadge = useCallback(async () => {\n try {\n const res = await fetchInbox({ currentPage: 1, pageSize: 1 });\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch {\n /* 角标失败不打断 UI */\n }\n }, [fetchInbox]);\n\n useEffect(() => {\n void refreshBadge();\n }, [refreshBadge]);\n\n useEffect(() => {\n if (pollMs <= 0) return undefined;\n const t = window.setInterval(() => {\n void refreshBadge();\n }, pollMs);\n return () => window.clearInterval(t);\n }, [pollMs, refreshBadge]);\n\n useEffect(() => {\n if (open) void load();\n }, [open, load]);\n\n const typeTabOptions = useMemo(\n () =>\n TYPE_TABS.map((t) => {\n const n = t.key ? unreadByType[t.key] || 0 : unreadTotal;\n return {\n key: t.key || 'all',\n label: n > 0 ? `${t.label} (${n})` : t.label,\n };\n }),\n [unreadByType, unreadTotal],\n );\n\n const handleOpenItem = async (item: InboxBellItem) => {\n if (!item.read) {\n try {\n await markRead(item.id);\n setItems((prev) => prev.map((x) => (x.id === item.id ? { ...x, read: true } : x)));\n setUnreadTotal((n) => Math.max(0, n - 1));\n } catch (e) {\n message.error(e instanceof Error ? e.message : '标记已读失败');\n return;\n }\n }\n const href = String(item.href || '').trim();\n if (!href) return;\n if (onNavigate) {\n onNavigate(href, item);\n setOpen(false);\n return;\n }\n if (href.startsWith('http://') || href.startsWith('https://')) {\n window.open(href, '_blank', 'noopener,noreferrer');\n } else {\n window.location.assign(href);\n }\n setOpen(false);\n };\n\n return (\n <div className={classNames(styles.bellWrap, className)}>\n <Badge count={unreadTotal} size=\"small\" overflowCount={99} offset={[-4, 4]}>\n <Button\n type=\"text\"\n className={styles.bellBtn}\n icon={<Bell size={16} aria-hidden />}\n aria-label={unreadTotal > 0 ? `站内信,${unreadTotal} 条未读` : '站内信'}\n onClick={() => setOpen(true)}\n />\n </Badge>\n <Drawer\n title={title}\n open={open}\n onClose={() => setOpen(false)}\n size={420}\n destroyOnClose={false}\n className={styles.drawer}\n styles={{\n header: { padding: '12px 16px' },\n body: { padding: '12px 16px' },\n }}\n >\n <StateBar\n className={styles.typeTabs}\n size=\"small\"\n activeKey={messageType || 'all'}\n onChange={(k) => setMessageType(k === 'all' ? '' : k)}\n stateOption={typeTabOptions}\n isInner\n />\n <div className={styles.filterRow}>\n <SegmentedRadio<'all' | 'unread' | 'read'>\n size=\"small\"\n value={readFilter}\n onChange={(v) => setReadFilter(v)}\n options={[\n { value: 'all', label: '全部' },\n { value: 'unread', label: '未读' },\n { value: 'read', label: '已读' },\n ]}\n />\n </div>\n {error ? <p className={styles.error}>{error}</p> : null}\n <PageSpin spinning={loading}>\n {!loading && !error && items.length === 0 ? (\n <Empty description=\"暂无站内信\" />\n ) : (\n <ul className={styles.list}>\n {items.map((item) => (\n <li key={item.id}>\n <button\n type=\"button\"\n className={classNames(styles.item, !item.read && styles.itemUnread)}\n onClick={() => void handleOpenItem(item)}\n >\n <Space orientation=\"vertical\" size={2} style={{ width: '100%' }}>\n <span className={styles.itemTitle}>{item.title || '(无标题)'}</span>\n {(() => {\n const safeHtml = sanitizeInboxHtml(item.bodyHtml);\n if (safeHtml) {\n return (\n <div\n className={styles.itemBodyHtml}\n dangerouslySetInnerHTML={{ __html: safeHtml }}\n />\n );\n }\n return item.summary ? (\n <span className={styles.itemSummary}>{item.summary}</span>\n ) : null;\n })()}\n <span className={styles.itemMeta}>\n {[item.messageType, item.createdAt].filter(Boolean).join(' · ') || '—'}\n </span>\n </Space>\n </button>\n </li>\n ))}\n </ul>\n )}\n </PageSpin>\n </Drawer>\n </div>\n );\n};\n\nexport default InboxBell;\n"],"names":["TYPE_TABS","InboxBell","fetchInbox","markRead","onNavigate","pollMs","pageSize","className","title","open","setOpen","useState","loading","setLoading","error","setError","items","setItems","unreadTotal","setUnreadTotal","unreadByType","setUnreadByType","messageType","setMessageType","readFilter","setReadFilter","load","useCallback","res","refreshBadge","useEffect","t","typeTabOptions","useMemo","n","handleOpenItem","item","prev","x","e","message","href","classNames","styles","jsx","Badge","Button","Bell","jsxs","Drawer","StateBar","k","SegmentedRadio","v","PageSpin","Empty","Space","safeHtml","sanitizeInboxHtml"],"mappings":"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"}
|
|
@@ -1,30 +1,32 @@
|
|
|
1
|
-
const t = "
|
|
1
|
+
const t = "_bellWrap_1t9v6_1", e = "_drawer_1t9v6_9", _ = "_bellBtn_1t9v6_16", r = "_typeTabs_1t9v6_35", i = "_filterRow_1t9v6_42", m = "_error_1t9v6_50", l = "_list_1t9v6_56", o = "_item_1t9v6_65", s = "_itemUnread_1t9v6_79", a = "_itemTitle_1t9v6_84", n = "_itemSummary_1t9v6_92", c = "_itemBodyHtml_1t9v6_100", v = "_itemMeta_1t9v6_120", d = {
|
|
2
2
|
bellWrap: t,
|
|
3
3
|
drawer: e,
|
|
4
4
|
bellBtn: _,
|
|
5
|
-
typeTabs:
|
|
6
|
-
filterRow:
|
|
7
|
-
error:
|
|
5
|
+
typeTabs: r,
|
|
6
|
+
filterRow: i,
|
|
7
|
+
error: m,
|
|
8
8
|
list: l,
|
|
9
|
-
item:
|
|
10
|
-
itemUnread:
|
|
11
|
-
itemTitle:
|
|
12
|
-
itemSummary:
|
|
13
|
-
|
|
9
|
+
item: o,
|
|
10
|
+
itemUnread: s,
|
|
11
|
+
itemTitle: a,
|
|
12
|
+
itemSummary: n,
|
|
13
|
+
itemBodyHtml: c,
|
|
14
|
+
itemMeta: v
|
|
14
15
|
};
|
|
15
16
|
export {
|
|
16
17
|
_ as bellBtn,
|
|
17
18
|
t as bellWrap,
|
|
18
|
-
|
|
19
|
+
d as default,
|
|
19
20
|
e as drawer,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
m as error,
|
|
22
|
+
i as filterRow,
|
|
23
|
+
o as item,
|
|
24
|
+
c as itemBodyHtml,
|
|
25
|
+
v as itemMeta,
|
|
26
|
+
n as itemSummary,
|
|
27
|
+
a as itemTitle,
|
|
28
|
+
s as itemUnread,
|
|
27
29
|
l as list,
|
|
28
|
-
|
|
30
|
+
r as typeTabs
|
|
29
31
|
};
|
|
30
32
|
//# sourceMappingURL=style.module.scss.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import e from "../../../node_modules/isomorphic-dompurify/dist/browser.js";
|
|
2
|
+
const i = {
|
|
3
|
+
ALLOWED_TAGS: ["p", "br", "strong", "b", "em", "i", "u", "ul", "ol", "li", "span", "div", "a"],
|
|
4
|
+
ALLOWED_ATTR: ["style", "class", "href", "target", "rel"],
|
|
5
|
+
ALLOW_DATA_ATTR: !1
|
|
6
|
+
};
|
|
7
|
+
function s(t) {
|
|
8
|
+
const r = String(t || "").trim();
|
|
9
|
+
return r ? e.sanitize(r, i) : "";
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
s as sanitizeInboxHtml
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=sanitizeInboxHtml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizeInboxHtml.js","sources":["../../../../src/components/Tools/Inbox/sanitizeInboxHtml.ts"],"sourcesContent":["import DOMPurify from 'isomorphic-dompurify';\nimport type { Config } from 'dompurify';\n\n/** CKEditor 常用标签白名单;禁 script / 事件属性 */\nconst INBOX_HTML_CONFIG: Config = {\n ALLOWED_TAGS: ['p', 'br', 'strong', 'b', 'em', 'i', 'u', 'ul', 'ol', 'li', 'span', 'div', 'a'],\n ALLOWED_ATTR: ['style', 'class', 'href', 'target', 'rel'],\n ALLOW_DATA_ATTR: false,\n};\n\n/**\n * 站内信 bodyHtml → 安全 HTML(isomorphic-dompurify,浏览器与 Node/单测一致)。\n * 空串返回 ''。\n */\nexport function sanitizeInboxHtml(raw: string | null | undefined): string {\n const src = String(raw || '').trim();\n if (!src) return '';\n return DOMPurify.sanitize(src, INBOX_HTML_CONFIG);\n}\n"],"names":["INBOX_HTML_CONFIG","sanitizeInboxHtml","raw","src","DOMPurify"],"mappings":";AAIA,MAAMA,IAA4B;AAAA,EAChC,cAAc,CAAC,KAAK,MAAM,UAAU,KAAK,MAAM,KAAK,KAAK,MAAM,MAAM,MAAM,QAAQ,OAAO,GAAG;AAAA,EAC7F,cAAc,CAAC,SAAS,SAAS,QAAQ,UAAU,KAAK;AAAA,EACxD,iBAAiB;AACnB;AAMO,SAASC,EAAkBC,GAAwC;AACxE,QAAMC,IAAM,OAAOD,KAAO,EAAE,EAAE,KAAA;AAC9B,SAAKC,IACEC,EAAU,SAASD,GAAKH,CAAiB,IAD/B;AAEnB;"}
|