@hkyhy/marsun-components-core 0.1.126 → 0.1.128
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/Tools/Inbox/InboxBell/InboxBell.js +331 -300
- package/dist/components/Tools/Inbox/InboxBell/InboxBell.js.map +1 -1
- package/dist/components/Tools/Inbox/index.d.ts +1 -0
- package/dist/components/Tools/Inbox/requestInboxBadgeRefresh.d.ts +11 -2
- package/dist/components/Tools/Inbox/requestInboxBadgeRefresh.js +10 -10
- package/dist/components/Tools/Inbox/requestInboxBadgeRefresh.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,317 +1,348 @@
|
|
|
1
|
-
import { jsxs as m, jsx as
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import { forwardRef as
|
|
5
|
-
import { sanitizeInboxHtml as
|
|
6
|
-
import { INBOX_BADGE_REFRESH_EVENT as
|
|
7
|
-
import { emphasizeQuoted as
|
|
8
|
-
import { filterInboxActionsForHost as
|
|
9
|
-
import { inboxSceneLabel as
|
|
10
|
-
import { loadInboxToastPrefs as
|
|
11
|
-
import { DEFAULT_INBOX_TOAST_PREFS as
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
const
|
|
1
|
+
import { jsxs as m, jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import { notification as pe, Button as F, Badge as Re, Drawer as Pe, Space as ye, Checkbox as ee, message as ge } from "antd";
|
|
3
|
+
import k from "classnames";
|
|
4
|
+
import { forwardRef as De, useState as p, useRef as v, useMemo as he, useCallback as x, useImperativeHandle as Me, useEffect as T } from "react";
|
|
5
|
+
import { sanitizeInboxHtml as _e } from "../sanitizeInboxHtml.js";
|
|
6
|
+
import { INBOX_BADGE_REFRESH_EVENT as ve } from "../requestInboxBadgeRefresh.js";
|
|
7
|
+
import { emphasizeQuoted as U } from "./emphasizeQuoted.js";
|
|
8
|
+
import { filterInboxActionsForHost as Ae, resolveInboxItemActions as Ie, isInboxButtonDriven as Oe } from "./inboxItemActions.js";
|
|
9
|
+
import { inboxSceneLabel as wt, isTerminalActionStatus as Nt, normalizeInboxActions as Et, resolveInboxSceneKey as St } from "./inboxItemActions.js";
|
|
10
|
+
import { loadInboxToastPrefs as He, shouldToastForMessageType as Fe, saveInboxToastPrefs as Ue } from "./toastPrefs.js";
|
|
11
|
+
import { DEFAULT_INBOX_TOAST_PREFS as Bt } from "./toastPrefs.js";
|
|
12
|
+
import r from "./style.module.scss.js";
|
|
13
|
+
import z, { SEMANTIC_COLORS as D } from "../../../Tag/SemanticTag.js";
|
|
14
|
+
import { Bell as ze } from "../../../Icons/Bell.js";
|
|
15
|
+
import Ge from "../../../StateBar/StateBar.js";
|
|
16
|
+
import Ke from "../../../SegmentedRadio/SegmentedRadio.js";
|
|
17
|
+
import $e from "../../../Layout/PageSpin/index.js";
|
|
18
|
+
import je from "../../../Empty/Empty.js";
|
|
19
|
+
import Ve from "../../../VirtualScrollbar/VirtualScrollbar/index.js";
|
|
20
|
+
const We = [
|
|
21
21
|
{ key: "", label: "全部" },
|
|
22
22
|
{ key: "alert", label: "预警" },
|
|
23
23
|
{ key: "action", label: "行动" },
|
|
24
24
|
{ key: "remind", label: "提醒" }
|
|
25
|
-
],
|
|
25
|
+
], Qe = {
|
|
26
26
|
alert: "预警",
|
|
27
27
|
action: "行动",
|
|
28
28
|
remind: "提醒"
|
|
29
|
-
},
|
|
30
|
-
function
|
|
31
|
-
const
|
|
32
|
-
return
|
|
29
|
+
}, Xe = 300, Ye = 1500, Je = 72;
|
|
30
|
+
function Te(u) {
|
|
31
|
+
const s = String(u || "").trim().toLowerCase();
|
|
32
|
+
return s ? Qe[s] || s : "";
|
|
33
33
|
}
|
|
34
|
-
function
|
|
35
|
-
const
|
|
36
|
-
return
|
|
34
|
+
function te(u) {
|
|
35
|
+
const s = String(u || "").trim().toLowerCase();
|
|
36
|
+
return s === "alert" ? D.DANGER : s === "action" ? D.PRIMARY : s === "remind" ? D.WARNING : D.DEFAULT;
|
|
37
37
|
}
|
|
38
|
-
function
|
|
39
|
-
return [u.factory, u.variety, u.metric].map((
|
|
38
|
+
function qe(u) {
|
|
39
|
+
return [u.factory, u.variety, u.metric].map((s) => String(s || "").trim()).filter(Boolean).join(" · ");
|
|
40
40
|
}
|
|
41
|
-
function
|
|
42
|
-
return String(u || "").trim() ||
|
|
41
|
+
function Ze(u) {
|
|
42
|
+
return String(u || "").trim() || D.DEFAULT;
|
|
43
43
|
}
|
|
44
|
-
function
|
|
44
|
+
function et(u) {
|
|
45
45
|
try {
|
|
46
|
-
const
|
|
47
|
-
if (!
|
|
48
|
-
const
|
|
49
|
-
return !
|
|
50
|
-
messageType:
|
|
51
|
-
title:
|
|
52
|
-
summary:
|
|
46
|
+
const s = JSON.parse(u);
|
|
47
|
+
if (!s || typeof s != "object") return null;
|
|
48
|
+
const M = String(s.messageType || s.message_type || "").trim(), C = String(s.title || "").trim(), S = String(s.summary || "").trim();
|
|
49
|
+
return !M && !C && !S ? null : {
|
|
50
|
+
messageType: M || void 0,
|
|
51
|
+
title: C || void 0,
|
|
52
|
+
summary: S || void 0
|
|
53
53
|
};
|
|
54
54
|
} catch {
|
|
55
55
|
return null;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
const
|
|
59
|
-
fetchInbox:
|
|
60
|
-
markRead:
|
|
61
|
-
onNavigate:
|
|
62
|
-
pollMs:
|
|
63
|
-
locationKey:
|
|
64
|
-
pageSize:
|
|
65
|
-
className:
|
|
66
|
-
title:
|
|
67
|
-
streamPath:
|
|
68
|
-
getAccessToken:
|
|
69
|
-
onItemAction:
|
|
70
|
-
},
|
|
71
|
-
const [
|
|
72
|
-
|
|
73
|
-
const
|
|
58
|
+
const vt = De(function({
|
|
59
|
+
fetchInbox: s,
|
|
60
|
+
markRead: M,
|
|
61
|
+
onNavigate: C,
|
|
62
|
+
pollMs: S = 0,
|
|
63
|
+
locationKey: ne,
|
|
64
|
+
pageSize: b = 20,
|
|
65
|
+
className: be,
|
|
66
|
+
title: we = "站内信",
|
|
67
|
+
streamPath: G = "/api/v1/msg-center/inbox/stream",
|
|
68
|
+
getAccessToken: K,
|
|
69
|
+
onItemAction: re
|
|
70
|
+
}, Ne) {
|
|
71
|
+
const [$, L] = p(!1), [ae, oe] = p(!1), [j, se] = p(""), [_, A] = p([]), [R, I] = p(0), [le, V] = p({}), [W, Ee] = p(""), [O, Se] = p("all"), [P, Le] = p(() => He()), [Be, ie] = p(!1), w = v(null), N = v(null), Q = v(null), ce = v(!1), de = v(P);
|
|
72
|
+
de.current = P;
|
|
73
|
+
const X = v(1), Y = v(!1), B = v(!1), H = he(
|
|
74
74
|
() => ({
|
|
75
|
-
messageType:
|
|
76
|
-
unreadOnly:
|
|
77
|
-
readOnly:
|
|
75
|
+
messageType: W || void 0,
|
|
76
|
+
unreadOnly: O === "unread" || void 0,
|
|
77
|
+
readOnly: O === "read" || void 0
|
|
78
78
|
}),
|
|
79
|
-
[
|
|
80
|
-
),
|
|
81
|
-
|
|
79
|
+
[W, O]
|
|
80
|
+
), J = x(async () => {
|
|
81
|
+
oe(!0), se(""), X.current = 1, B.current = !1;
|
|
82
82
|
try {
|
|
83
|
-
const e = await
|
|
83
|
+
const e = await s({
|
|
84
84
|
currentPage: 1,
|
|
85
|
-
pageSize:
|
|
86
|
-
...
|
|
87
|
-
}), t = (e == null ? void 0 : e.pageData) || [],
|
|
88
|
-
|
|
85
|
+
pageSize: b,
|
|
86
|
+
...H
|
|
87
|
+
}), t = (e == null ? void 0 : e.pageData) || [], n = typeof (e == null ? void 0 : e.total) == "number" ? e.total : t.length;
|
|
88
|
+
A(t), B.current = t.length > 0 && t.length < n, I(typeof (e == null ? void 0 : e.unreadTotal) == "number" ? e.unreadTotal : 0), V((e == null ? void 0 : e.unreadByMessageType) || {});
|
|
89
89
|
} catch (e) {
|
|
90
|
-
|
|
90
|
+
A([]), B.current = !1, se(e instanceof Error ? e.message : String(e));
|
|
91
91
|
} finally {
|
|
92
|
-
|
|
92
|
+
oe(!1);
|
|
93
93
|
}
|
|
94
|
-
}, [
|
|
95
|
-
if (!(
|
|
96
|
-
|
|
94
|
+
}, [s, b, H]), ue = x(async () => {
|
|
95
|
+
if (!(Y.current || !B.current)) {
|
|
96
|
+
Y.current = !0, ie(!0);
|
|
97
97
|
try {
|
|
98
|
-
const e =
|
|
98
|
+
const e = X.current + 1, t = await s({
|
|
99
99
|
currentPage: e,
|
|
100
|
-
pageSize:
|
|
101
|
-
...
|
|
102
|
-
}),
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
return
|
|
106
|
-
}),
|
|
100
|
+
pageSize: b,
|
|
101
|
+
...H
|
|
102
|
+
}), n = (t == null ? void 0 : t.pageData) || [], o = typeof (t == null ? void 0 : t.total) == "number" ? t.total : 0;
|
|
103
|
+
A((i) => {
|
|
104
|
+
const l = new Set(i.map((f) => f.id)), c = n.filter((f) => (f == null ? void 0 : f.id) && !l.has(f.id)), g = c.length ? [...i, ...c] : i;
|
|
105
|
+
return B.current = c.length > 0 && (o > 0 ? g.length < o : c.length >= b), g;
|
|
106
|
+
}), n.length && (X.current = e), typeof (t == null ? void 0 : t.unreadTotal) == "number" && I(t.unreadTotal), t != null && t.unreadByMessageType && V(t.unreadByMessageType);
|
|
107
107
|
} catch {
|
|
108
|
-
|
|
108
|
+
B.current = !1;
|
|
109
109
|
} finally {
|
|
110
|
-
|
|
110
|
+
Y.current = !1, ie(!1);
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
}, [
|
|
113
|
+
}, [s, b, H]), ke = x(
|
|
114
114
|
(e) => {
|
|
115
115
|
const t = e.currentTarget;
|
|
116
|
-
t.scrollHeight - t.scrollTop - t.clientHeight <=
|
|
116
|
+
t.scrollHeight - t.scrollTop - t.clientHeight <= Je && ue();
|
|
117
117
|
},
|
|
118
|
-
[
|
|
119
|
-
),
|
|
118
|
+
[ue]
|
|
119
|
+
), y = x(async () => {
|
|
120
120
|
try {
|
|
121
|
-
const e = await
|
|
122
|
-
|
|
121
|
+
const e = await s({ currentPage: 1, pageSize: b });
|
|
122
|
+
I(typeof (e == null ? void 0 : e.unreadTotal) == "number" ? e.unreadTotal : 0), V((e == null ? void 0 : e.unreadByMessageType) || {});
|
|
123
123
|
} catch {
|
|
124
124
|
}
|
|
125
|
-
}, [
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
125
|
+
}, [s, b]), me = x(() => {
|
|
126
|
+
const e = Q.current;
|
|
127
|
+
if (Q.current = null, !e || !Fe(de.current, e.messageType)) return;
|
|
128
|
+
const t = e.title || "新站内信", n = e.summary || "", o = Te(e.messageType), i = () => {
|
|
129
|
+
pe.destroy(), L(!0);
|
|
130
|
+
}, l = `inbox-badge-${e.messageType || "msg"}-${Date.now()}`;
|
|
131
|
+
pe.open({
|
|
132
|
+
key: l,
|
|
133
|
+
className: k("marsun-inbox-toast", r.toastNotice),
|
|
134
|
+
closable: !0,
|
|
135
|
+
title: /* @__PURE__ */ m("div", { className: r.toastHead, children: [
|
|
136
|
+
/* @__PURE__ */ a("span", { className: r.toastTitle, children: U(t) }),
|
|
137
|
+
o ? /* @__PURE__ */ a(
|
|
138
|
+
z,
|
|
139
|
+
{
|
|
140
|
+
color: te(e.messageType),
|
|
141
|
+
className: r.typeTag,
|
|
142
|
+
children: o
|
|
143
|
+
}
|
|
144
|
+
) : null
|
|
145
|
+
] }),
|
|
146
|
+
message: /* @__PURE__ */ m("div", { className: r.toastHead, children: [
|
|
147
|
+
/* @__PURE__ */ a("span", { className: r.toastTitle, children: U(t) }),
|
|
148
|
+
o ? /* @__PURE__ */ a(
|
|
149
|
+
z,
|
|
150
|
+
{
|
|
151
|
+
color: te(e.messageType),
|
|
152
|
+
className: r.typeTag,
|
|
153
|
+
children: o
|
|
154
|
+
}
|
|
155
|
+
) : null
|
|
156
|
+
] }),
|
|
157
|
+
description: /* @__PURE__ */ m("div", { className: r.toastBody, children: [
|
|
158
|
+
n ? /* @__PURE__ */ a("div", { className: r.toastDesc, children: U(n) }) : null,
|
|
159
|
+
/* @__PURE__ */ a("div", { className: r.toastActions, children: /* @__PURE__ */ a(
|
|
160
|
+
F,
|
|
161
|
+
{
|
|
162
|
+
type: "primary",
|
|
163
|
+
size: "small",
|
|
164
|
+
onClick: (c) => {
|
|
165
|
+
c.stopPropagation(), i();
|
|
166
|
+
},
|
|
167
|
+
children: "查看"
|
|
168
|
+
}
|
|
169
|
+
) })
|
|
170
|
+
] }),
|
|
171
|
+
placement: "topRight",
|
|
172
|
+
duration: 6,
|
|
173
|
+
onClick: i
|
|
174
|
+
});
|
|
175
|
+
}, []), h = x(
|
|
176
|
+
(e) => {
|
|
177
|
+
e && (Q.current = e, me()), N.current != null && window.clearTimeout(N.current), N.current = window.setTimeout(() => {
|
|
178
|
+
N.current = null, y();
|
|
179
|
+
}, Ye);
|
|
180
|
+
},
|
|
181
|
+
[y, me]
|
|
182
|
+
);
|
|
183
|
+
Me(Ne, () => ({ refreshBadge: y }), [y]), T(() => {
|
|
184
|
+
y();
|
|
185
|
+
}, [y]), T(() => {
|
|
186
|
+
if (ne !== void 0) {
|
|
187
|
+
if (!ce.current) {
|
|
188
|
+
ce.current = !0;
|
|
132
189
|
return;
|
|
133
190
|
}
|
|
134
|
-
|
|
191
|
+
h();
|
|
135
192
|
}
|
|
136
|
-
}, [
|
|
137
|
-
if (
|
|
193
|
+
}, [ne, h]), T(() => {
|
|
194
|
+
if (S <= 0) return;
|
|
138
195
|
const e = window.setInterval(() => {
|
|
139
|
-
|
|
140
|
-
},
|
|
196
|
+
y();
|
|
197
|
+
}, S);
|
|
141
198
|
return () => window.clearInterval(e);
|
|
142
|
-
}, [
|
|
199
|
+
}, [S, y]), T(() => {
|
|
143
200
|
const e = () => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
},
|
|
201
|
+
w.current != null && window.clearTimeout(w.current), w.current = window.setTimeout(() => {
|
|
202
|
+
w.current = null, h();
|
|
203
|
+
}, Xe);
|
|
147
204
|
}, t = () => {
|
|
148
205
|
document.visibilityState === "visible" && e();
|
|
149
206
|
};
|
|
150
207
|
return window.addEventListener("focus", e), document.addEventListener("visibilitychange", t), () => {
|
|
151
|
-
window.removeEventListener("focus", e), document.removeEventListener("visibilitychange", t),
|
|
208
|
+
window.removeEventListener("focus", e), document.removeEventListener("visibilitychange", t), w.current != null && (window.clearTimeout(w.current), w.current = null);
|
|
152
209
|
};
|
|
153
|
-
}, [
|
|
154
|
-
const e = () => {
|
|
155
|
-
|
|
210
|
+
}, [h]), T(() => {
|
|
211
|
+
const e = (t) => {
|
|
212
|
+
const n = t.detail;
|
|
213
|
+
h((n == null ? void 0 : n.preview) || void 0);
|
|
156
214
|
};
|
|
157
|
-
return window.addEventListener(
|
|
158
|
-
}, [
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (!
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
{
|
|
197
|
-
color: q(d.messageType),
|
|
198
|
-
className: n.typeTag,
|
|
199
|
-
children: M
|
|
200
|
-
}
|
|
201
|
-
) : null
|
|
202
|
-
] }),
|
|
203
|
-
description: /* @__PURE__ */ m("div", { className: n.toastBody, children: [
|
|
204
|
-
y ? /* @__PURE__ */ r("div", { className: n.toastDesc, children: H(y) }) : null,
|
|
205
|
-
/* @__PURE__ */ r("div", { className: n.toastActions, children: /* @__PURE__ */ r(
|
|
206
|
-
I,
|
|
207
|
-
{
|
|
208
|
-
type: "primary",
|
|
209
|
-
size: "small",
|
|
210
|
-
onClick: (Be) => {
|
|
211
|
-
Be.stopPropagation(), de();
|
|
212
|
-
},
|
|
213
|
-
children: "查看"
|
|
214
|
-
}
|
|
215
|
-
) })
|
|
216
|
-
] }),
|
|
217
|
-
placement: "topRight",
|
|
218
|
-
duration: 6,
|
|
219
|
-
onClick: de
|
|
220
|
-
});
|
|
215
|
+
return window.addEventListener(ve, e), () => window.removeEventListener(ve, e);
|
|
216
|
+
}, [h]), T(() => () => {
|
|
217
|
+
N.current != null && (window.clearTimeout(N.current), N.current = null);
|
|
218
|
+
}, []), T(() => {
|
|
219
|
+
if (G === !1 || typeof K != "function" || typeof window > "u" || typeof EventSource > "u") return;
|
|
220
|
+
const e = String(G || "/api/v1/msg-center/inbox/stream").trim();
|
|
221
|
+
let t = !1, n = null, o = null, i = 0;
|
|
222
|
+
const l = (d) => {
|
|
223
|
+
const E = d, Ce = typeof (E == null ? void 0 : E.data) == "string" ? et(E.data) : null;
|
|
224
|
+
h(Ce);
|
|
225
|
+
}, c = () => {
|
|
226
|
+
o != null && (window.clearTimeout(o), o = null);
|
|
227
|
+
}, g = () => {
|
|
228
|
+
if (t || o != null) return;
|
|
229
|
+
const d = Math.min(3e4, 1e3 * 2 ** Math.min(i, 5));
|
|
230
|
+
i += 1, o = window.setTimeout(() => {
|
|
231
|
+
o = null, f();
|
|
232
|
+
}, d);
|
|
233
|
+
}, f = () => {
|
|
234
|
+
if (t) return;
|
|
235
|
+
const d = String(K() || "").trim();
|
|
236
|
+
if (!d) {
|
|
237
|
+
g();
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
n && (n.removeEventListener("badge", l), n.removeEventListener("inbox", l), n.close(), n = null);
|
|
241
|
+
const E = new URL(e, window.location.origin);
|
|
242
|
+
E.searchParams.set("access_token", d);
|
|
243
|
+
try {
|
|
244
|
+
n = new EventSource(E.toString());
|
|
245
|
+
} catch {
|
|
246
|
+
g();
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
n.addEventListener("badge", l), n.addEventListener("inbox", l), n.onopen = () => {
|
|
250
|
+
i = 0;
|
|
251
|
+
}, n.onerror = () => {
|
|
252
|
+
t || (n == null || n.close(), n = null, g());
|
|
253
|
+
};
|
|
221
254
|
};
|
|
222
|
-
return
|
|
223
|
-
|
|
224
|
-
}, () => {
|
|
225
|
-
o.removeEventListener("badge", i), o.removeEventListener("inbox", i), o.close();
|
|
255
|
+
return f(), () => {
|
|
256
|
+
t = !0, c(), n && (n.removeEventListener("badge", l), n.removeEventListener("inbox", l), n.close(), n = null);
|
|
226
257
|
};
|
|
227
|
-
}, [
|
|
228
|
-
|
|
229
|
-
}, [
|
|
230
|
-
const
|
|
231
|
-
() =>
|
|
232
|
-
const t = e.key ?
|
|
258
|
+
}, [G, K, h]), T(() => {
|
|
259
|
+
$ && J();
|
|
260
|
+
}, [$, J]);
|
|
261
|
+
const xe = he(
|
|
262
|
+
() => We.map((e) => {
|
|
263
|
+
const t = e.key ? le[e.key] || 0 : R;
|
|
233
264
|
return {
|
|
234
265
|
key: e.key || "all",
|
|
235
266
|
label: t > 0 ? `${e.label} (${t})` : e.label
|
|
236
267
|
};
|
|
237
268
|
}),
|
|
238
|
-
[
|
|
239
|
-
),
|
|
240
|
-
|
|
241
|
-
const o = { ...
|
|
242
|
-
return
|
|
269
|
+
[le, R]
|
|
270
|
+
), q = (e, t) => {
|
|
271
|
+
Le((n) => {
|
|
272
|
+
const o = { ...n, [e]: t };
|
|
273
|
+
return Ue(o), o;
|
|
243
274
|
});
|
|
244
|
-
},
|
|
275
|
+
}, Z = async (e, t) => {
|
|
245
276
|
if (!e.read)
|
|
246
277
|
try {
|
|
247
|
-
await
|
|
278
|
+
await M(e.id), A((o) => o.map((i) => i.id === e.id ? { ...i, read: !0 } : i)), I((o) => Math.max(0, o - 1));
|
|
248
279
|
} catch (o) {
|
|
249
|
-
|
|
280
|
+
ge.error(o instanceof Error ? o.message : "标记已读失败");
|
|
250
281
|
return;
|
|
251
282
|
}
|
|
252
|
-
const
|
|
253
|
-
if (
|
|
254
|
-
if (
|
|
255
|
-
|
|
283
|
+
const n = String(e.href || "").trim();
|
|
284
|
+
if (n) {
|
|
285
|
+
if (C) {
|
|
286
|
+
C(n, e), L(!1);
|
|
256
287
|
return;
|
|
257
288
|
}
|
|
258
|
-
|
|
289
|
+
n.startsWith("http://") || n.startsWith("https://") ? window.open(n, "_blank", "noopener,noreferrer") : window.location.assign(n), L(!1);
|
|
259
290
|
}
|
|
260
|
-
},
|
|
291
|
+
}, fe = async (e, t) => {
|
|
261
292
|
if (!t.disabled) {
|
|
262
|
-
if (
|
|
293
|
+
if (re) {
|
|
263
294
|
try {
|
|
264
|
-
await
|
|
265
|
-
} catch (
|
|
266
|
-
|
|
295
|
+
await re(t.kind, e), L(!1), J(), y();
|
|
296
|
+
} catch (n) {
|
|
297
|
+
ge.error(n instanceof Error ? n.message : "操作失败");
|
|
267
298
|
}
|
|
268
299
|
return;
|
|
269
300
|
}
|
|
270
|
-
await
|
|
301
|
+
await Z(e);
|
|
271
302
|
}
|
|
272
303
|
};
|
|
273
|
-
return /* @__PURE__ */ m("div", { className:
|
|
274
|
-
/* @__PURE__ */
|
|
275
|
-
|
|
304
|
+
return /* @__PURE__ */ m("div", { className: k(r.bellWrap, be), children: [
|
|
305
|
+
/* @__PURE__ */ a(Re, { count: R, size: "small", overflowCount: 99, offset: [-4, 4], children: /* @__PURE__ */ a(
|
|
306
|
+
F,
|
|
276
307
|
{
|
|
277
308
|
type: "text",
|
|
278
|
-
className:
|
|
279
|
-
icon: /* @__PURE__ */
|
|
280
|
-
"aria-label":
|
|
281
|
-
onClick: () =>
|
|
309
|
+
className: r.bellBtn,
|
|
310
|
+
icon: /* @__PURE__ */ a(ze, { size: 16, "aria-hidden": !0 }),
|
|
311
|
+
"aria-label": R > 0 ? `站内信,${R} 条未读` : "站内信",
|
|
312
|
+
onClick: () => L(!0)
|
|
282
313
|
}
|
|
283
314
|
) }),
|
|
284
315
|
/* @__PURE__ */ m(
|
|
285
|
-
|
|
316
|
+
Pe,
|
|
286
317
|
{
|
|
287
|
-
title:
|
|
288
|
-
open:
|
|
289
|
-
onClose: () =>
|
|
318
|
+
title: we,
|
|
319
|
+
open: $,
|
|
320
|
+
onClose: () => L(!1),
|
|
290
321
|
size: 420,
|
|
291
322
|
destroyOnClose: !1,
|
|
292
|
-
className:
|
|
323
|
+
className: r.drawer,
|
|
293
324
|
styles: {
|
|
294
325
|
header: { padding: "12px 16px" },
|
|
295
326
|
body: { padding: "12px 16px" }
|
|
296
327
|
},
|
|
297
328
|
children: [
|
|
298
|
-
/* @__PURE__ */
|
|
299
|
-
|
|
329
|
+
/* @__PURE__ */ a(
|
|
330
|
+
Ge,
|
|
300
331
|
{
|
|
301
|
-
className:
|
|
332
|
+
className: r.typeTabs,
|
|
302
333
|
size: "small",
|
|
303
|
-
activeKey:
|
|
304
|
-
onChange: (e) =>
|
|
305
|
-
stateOption:
|
|
334
|
+
activeKey: W || "all",
|
|
335
|
+
onChange: (e) => Ee(e === "all" ? "" : e),
|
|
336
|
+
stateOption: xe,
|
|
306
337
|
isInner: !0
|
|
307
338
|
}
|
|
308
339
|
),
|
|
309
|
-
/* @__PURE__ */
|
|
310
|
-
|
|
340
|
+
/* @__PURE__ */ a("div", { className: r.filterRow, children: /* @__PURE__ */ a(
|
|
341
|
+
Ke,
|
|
311
342
|
{
|
|
312
343
|
size: "small",
|
|
313
|
-
value:
|
|
314
|
-
onChange: (e) =>
|
|
344
|
+
value: O,
|
|
345
|
+
onChange: (e) => Se(e),
|
|
315
346
|
options: [
|
|
316
347
|
{ value: "all", label: "全部" },
|
|
317
348
|
{ value: "unread", label: "未读" },
|
|
@@ -319,117 +350,117 @@ const yt = Pe(function({
|
|
|
319
350
|
]
|
|
320
351
|
}
|
|
321
352
|
) }),
|
|
322
|
-
/* @__PURE__ */ m("div", { className:
|
|
323
|
-
/* @__PURE__ */
|
|
324
|
-
/* @__PURE__ */
|
|
325
|
-
/* @__PURE__ */ m(
|
|
326
|
-
/* @__PURE__ */
|
|
327
|
-
|
|
353
|
+
/* @__PURE__ */ m("div", { className: r.toastPrefs, "data-testid": "inbox-toast-prefs", children: [
|
|
354
|
+
/* @__PURE__ */ a("div", { className: r.toastPrefsTitle, children: "消息提示" }),
|
|
355
|
+
/* @__PURE__ */ a("p", { className: r.toastPrefsHint, children: "本机浏览器偏好,非租户策略" }),
|
|
356
|
+
/* @__PURE__ */ m(ye, { size: 12, wrap: !0, children: [
|
|
357
|
+
/* @__PURE__ */ a(
|
|
358
|
+
ee,
|
|
328
359
|
{
|
|
329
|
-
checked:
|
|
330
|
-
onChange: (e) =>
|
|
360
|
+
checked: P.alert,
|
|
361
|
+
onChange: (e) => q("alert", e.target.checked),
|
|
331
362
|
children: "预警弹出"
|
|
332
363
|
}
|
|
333
364
|
),
|
|
334
|
-
/* @__PURE__ */
|
|
335
|
-
|
|
365
|
+
/* @__PURE__ */ a(
|
|
366
|
+
ee,
|
|
336
367
|
{
|
|
337
|
-
checked:
|
|
338
|
-
onChange: (e) =>
|
|
368
|
+
checked: P.action,
|
|
369
|
+
onChange: (e) => q("action", e.target.checked),
|
|
339
370
|
children: "行动弹出"
|
|
340
371
|
}
|
|
341
372
|
),
|
|
342
|
-
/* @__PURE__ */
|
|
343
|
-
|
|
373
|
+
/* @__PURE__ */ a(
|
|
374
|
+
ee,
|
|
344
375
|
{
|
|
345
|
-
checked:
|
|
346
|
-
onChange: (e) =>
|
|
376
|
+
checked: P.remind,
|
|
377
|
+
onChange: (e) => q("remind", e.target.checked),
|
|
347
378
|
children: "提醒弹出"
|
|
348
379
|
}
|
|
349
380
|
)
|
|
350
381
|
] })
|
|
351
382
|
] }),
|
|
352
|
-
|
|
353
|
-
/* @__PURE__ */
|
|
354
|
-
|
|
383
|
+
j ? /* @__PURE__ */ a("p", { className: r.error, children: j }) : null,
|
|
384
|
+
/* @__PURE__ */ a("div", { className: k("inbox-bell-list-pane", r.listPane), children: /* @__PURE__ */ a($e, { spinning: ae && _.length === 0, children: !ae && !j && _.length === 0 ? /* @__PURE__ */ a(je, { description: "暂无站内信" }) : _.length === 0 ? null : /* @__PURE__ */ m(
|
|
385
|
+
Ve,
|
|
355
386
|
{
|
|
356
|
-
wrapperClassName:
|
|
357
|
-
className:
|
|
387
|
+
wrapperClassName: k("inbox-bell-list-scroll", r.listScroll),
|
|
388
|
+
className: r.listViewport,
|
|
358
389
|
"data-testid": "inbox-bell-list-scroll",
|
|
359
|
-
onScroll:
|
|
390
|
+
onScroll: ke,
|
|
360
391
|
children: [
|
|
361
|
-
/* @__PURE__ */
|
|
362
|
-
const t =
|
|
363
|
-
|
|
364
|
-
), c =
|
|
365
|
-
return /* @__PURE__ */
|
|
392
|
+
/* @__PURE__ */ a("ul", { className: r.list, children: _.map((e) => {
|
|
393
|
+
const t = Te(e.messageType), n = String(e.levelLabel || e.level || "").trim(), o = !!n, i = _e(e.bodyHtml), l = Ae(
|
|
394
|
+
Ie(e)
|
|
395
|
+
), c = Oe(e), g = qe(e), f = !!l.primary;
|
|
396
|
+
return /* @__PURE__ */ a("li", { children: /* @__PURE__ */ m(
|
|
366
397
|
"div",
|
|
367
398
|
{
|
|
368
|
-
className:
|
|
369
|
-
|
|
370
|
-
!e.read &&
|
|
371
|
-
c &&
|
|
399
|
+
className: k(
|
|
400
|
+
r.item,
|
|
401
|
+
!e.read && r.itemUnread,
|
|
402
|
+
c && r.itemStatic
|
|
372
403
|
),
|
|
373
404
|
role: c ? void 0 : "button",
|
|
374
405
|
tabIndex: c ? void 0 : 0,
|
|
375
|
-
onClick: c ? void 0 : () => void
|
|
376
|
-
onKeyDown: c ? void 0 : (
|
|
377
|
-
(
|
|
406
|
+
onClick: c ? void 0 : () => void Z(e),
|
|
407
|
+
onKeyDown: c ? void 0 : (d) => {
|
|
408
|
+
(d.key === "Enter" || d.key === " ") && (d.preventDefault(), Z(e));
|
|
378
409
|
},
|
|
379
410
|
children: [
|
|
380
|
-
/* @__PURE__ */ m("div", { className:
|
|
381
|
-
/* @__PURE__ */ m("span", { className:
|
|
382
|
-
/* @__PURE__ */
|
|
383
|
-
t ? /* @__PURE__ */
|
|
384
|
-
|
|
411
|
+
/* @__PURE__ */ m("div", { className: r.itemHeader, children: [
|
|
412
|
+
/* @__PURE__ */ m("span", { className: r.itemHeaderLeft, children: [
|
|
413
|
+
/* @__PURE__ */ a("span", { className: r.itemTitle, title: e.title || "(无标题)", children: e.title || "(无标题)" }),
|
|
414
|
+
t ? /* @__PURE__ */ a(
|
|
415
|
+
z,
|
|
385
416
|
{
|
|
386
|
-
color:
|
|
387
|
-
className:
|
|
417
|
+
color: te(e.messageType),
|
|
418
|
+
className: r.typeTag,
|
|
388
419
|
children: t
|
|
389
420
|
}
|
|
390
421
|
) : null
|
|
391
422
|
] }),
|
|
392
|
-
/* @__PURE__ */
|
|
423
|
+
/* @__PURE__ */ a("span", { className: r.itemTime, children: e.createdAt || "" })
|
|
393
424
|
] }),
|
|
394
|
-
/* @__PURE__ */
|
|
425
|
+
/* @__PURE__ */ a("div", { className: r.itemBody, children: i ? /* @__PURE__ */ a(
|
|
395
426
|
"div",
|
|
396
427
|
{
|
|
397
|
-
className:
|
|
428
|
+
className: r.itemBodyHtml,
|
|
398
429
|
dangerouslySetInnerHTML: { __html: i }
|
|
399
430
|
}
|
|
400
|
-
) : e.summary ? /* @__PURE__ */
|
|
401
|
-
|
|
402
|
-
o ? /* @__PURE__ */
|
|
403
|
-
|
|
431
|
+
) : e.summary ? /* @__PURE__ */ a("span", { className: r.itemSummary, children: U(e.summary) }) : null }),
|
|
432
|
+
g ? /* @__PURE__ */ a("span", { className: r.itemMeta, children: g }) : null,
|
|
433
|
+
o ? /* @__PURE__ */ a("div", { className: r.itemFooterTags, children: /* @__PURE__ */ a(
|
|
434
|
+
z,
|
|
404
435
|
{
|
|
405
|
-
color:
|
|
406
|
-
className:
|
|
407
|
-
children:
|
|
436
|
+
color: Ze(e.levelColor),
|
|
437
|
+
className: r.typeTag,
|
|
438
|
+
children: n
|
|
408
439
|
}
|
|
409
440
|
) }) : null,
|
|
410
|
-
f &&
|
|
441
|
+
f && l.primary ? /* @__PURE__ */ a(
|
|
411
442
|
"div",
|
|
412
443
|
{
|
|
413
|
-
className:
|
|
414
|
-
onClick: (
|
|
415
|
-
onKeyDown: (
|
|
416
|
-
children: /* @__PURE__ */ m(
|
|
417
|
-
/* @__PURE__ */
|
|
418
|
-
|
|
444
|
+
className: r.itemActions,
|
|
445
|
+
onClick: (d) => d.stopPropagation(),
|
|
446
|
+
onKeyDown: (d) => d.stopPropagation(),
|
|
447
|
+
children: /* @__PURE__ */ m(ye, { size: 8, wrap: !0, children: [
|
|
448
|
+
/* @__PURE__ */ a(
|
|
449
|
+
F,
|
|
419
450
|
{
|
|
420
451
|
size: "small",
|
|
421
452
|
type: "primary",
|
|
422
|
-
onClick: () => void
|
|
423
|
-
children:
|
|
453
|
+
onClick: () => void fe(e, l.primary),
|
|
454
|
+
children: l.primary.label
|
|
424
455
|
}
|
|
425
456
|
),
|
|
426
|
-
|
|
427
|
-
|
|
457
|
+
l.secondary ? /* @__PURE__ */ a(
|
|
458
|
+
F,
|
|
428
459
|
{
|
|
429
460
|
size: "small",
|
|
430
461
|
type: "link",
|
|
431
|
-
onClick: () => void
|
|
432
|
-
children:
|
|
462
|
+
onClick: () => void fe(e, l.secondary),
|
|
463
|
+
children: l.secondary.label
|
|
433
464
|
}
|
|
434
465
|
) : null
|
|
435
466
|
] })
|
|
@@ -439,7 +470,7 @@ const yt = Pe(function({
|
|
|
439
470
|
}
|
|
440
471
|
) }, e.id);
|
|
441
472
|
}) }),
|
|
442
|
-
|
|
473
|
+
Be ? /* @__PURE__ */ a("p", { className: k("inbox-bell-list-footer", r.listFooter), children: "加载中…" }) : null
|
|
443
474
|
]
|
|
444
475
|
}
|
|
445
476
|
) }) })
|
|
@@ -449,17 +480,17 @@ const yt = Pe(function({
|
|
|
449
480
|
] });
|
|
450
481
|
});
|
|
451
482
|
export {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
483
|
+
Bt as DEFAULT_INBOX_TOAST_PREFS,
|
|
484
|
+
vt as default,
|
|
485
|
+
Ae as filterInboxActionsForHost,
|
|
486
|
+
wt as inboxSceneLabel,
|
|
487
|
+
Oe as isInboxButtonDriven,
|
|
488
|
+
Nt as isTerminalActionStatus,
|
|
489
|
+
He as loadInboxToastPrefs,
|
|
490
|
+
Et as normalizeInboxActions,
|
|
491
|
+
Ie as resolveInboxItemActions,
|
|
492
|
+
St as resolveInboxSceneKey,
|
|
493
|
+
Ue as saveInboxToastPrefs,
|
|
494
|
+
Fe as shouldToastForMessageType
|
|
464
495
|
};
|
|
465
496
|
//# sourceMappingURL=InboxBell.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InboxBell.js","sources":["../../../../../src/components/Tools/Inbox/InboxBell/InboxBell.tsx"],"sourcesContent":["import { Badge, Button, Checkbox, Drawer, Space, message, notification } from 'antd';\nimport classNames from 'classnames';\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type UIEvent,\n} 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 { SEMANTIC_COLORS, SemanticTag } from '@/components/Tag';\nimport { VirtualScrollbar } from '@/components/VirtualScrollbar';\nimport { sanitizeInboxHtml } from '../sanitizeInboxHtml';\nimport { INBOX_BADGE_REFRESH_EVENT } from '../requestInboxBadgeRefresh';\nimport { emphasizeQuoted } from './emphasizeQuoted';\nimport {\n filterInboxActionsForHost,\n isInboxButtonDriven,\n resolveInboxItemActions,\n type InboxItemActionKind,\n type InboxItemQuickAction,\n} from './inboxItemActions';\nimport {\n loadInboxToastPrefs,\n saveInboxToastPrefs,\n shouldToastForMessageType,\n type InboxToastPrefs,\n} from './toastPrefs';\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 /** 级别展示名(业务仓从已有维表/工具函数填;空则回落 level) */\n levelLabel?: string;\n /**\n * 级别 Tag 色:业务仓传入预警级别设置色(如 QA `ALERT_LEVEL_COLORS.*.accent`)。\n * 支持 SemanticColor 键或 `#hex`;core 不自造级别色表。\n */\n levelColor?: string;\n category?: string;\n scene?: string;\n eventKey?: string;\n categoryLabel?: string;\n alertId?: string | null;\n actionId?: string | null;\n claimed?: boolean;\n started?: boolean;\n /** 行动当前状态(enrich / contextJson);终态时底栏只保留查看任务 */\n actionStatus?: string;\n factory?: string;\n variety?: string;\n metric?: string;\n /** 业务日/月份(如 2026-07-31);预警深链 date 用 */\n month?: string;\n};\n\nexport type InboxBellListResult = {\n /** 分页列表(Marsun list-api 唯一数组名) */\n pageData: 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 /**\n * 轮询未读角标(ms)。默认 `0`(关定时);`>0` 才 setInterval。\n * 角标另由:挂载首刷、`locationKey`、focus/visibility、`requestInboxBadgeRefresh` 触发。\n */\n pollMs?: number;\n /**\n * 路由/页面身份;变化时刷新角标(如 React Router `location.pathname`)。\n * 整页加载靠挂载首刷,不必另传。\n */\n locationKey?: string | number;\n pageSize?: number;\n className?: string;\n /** Drawer 标题 */\n title?: string;\n /**\n * 同源 SSE 路径(默认 `/api/v1/msg-center/inbox/stream`)。\n * 传 `false` 关闭。须配合 `getAccessToken`(EventSource 用 `access_token` 查询参数传 JWT)。\n * 失败回落写后刷新 / 焦点刷新,不定时轮询冒充。\n */\n streamPath?: string | false;\n /** 返回当前 JWT;空则不开 SSE */\n getAccessToken?: () => string | null | undefined;\n /**\n * 卡片底栏动作(认领/去执行/查看等)。不传则底栏按钮一律走 onNavigate / href。\n * 业务仓拦截 claim_alert / start_action;铃铛不解析新建任务。\n */\n onItemAction?: (kind: InboxItemActionKind, item: InboxBellItem) => void | Promise<void>;\n};\n\nexport type InboxBellHandle = {\n refreshBadge: () => Promise<void>;\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\nconst TYPE_TAG_LABEL: Record<string, string> = {\n alert: '预警',\n action: '行动',\n remind: '提醒',\n};\n\nconst FOCUS_DEBOUNCE_MS = 300;\n/** 距底部小于该值时拉下一页 */\nconst LOAD_MORE_GAP_PX = 72;\n\nfunction messageTypeLabel(raw?: string): string {\n const key = String(raw || '')\n .trim()\n .toLowerCase();\n if (!key) return '';\n return TYPE_TAG_LABEL[key] || key;\n}\n\nfunction messageTypeSemanticColor(raw?: string): string {\n const key = String(raw || '')\n .trim()\n .toLowerCase();\n if (key === 'alert') return SEMANTIC_COLORS.DANGER;\n if (key === 'action') return SEMANTIC_COLORS.PRIMARY;\n if (key === 'remind') return SEMANTIC_COLORS.WARNING;\n return SEMANTIC_COLORS.DEFAULT;\n}\n\nfunction itemMetaLine(item: InboxBellItem): string {\n return [item.factory, item.variety, item.metric]\n .map((x) => String(x || '').trim())\n .filter(Boolean)\n .join(' · ');\n}\n\n/** 业务传入色;无则 DEFAULT(禁止在 core 造级别→色平行表) */\nfunction resolveLevelTagColor(raw?: string): string {\n const c = String(raw || '').trim();\n return c || SEMANTIC_COLORS.DEFAULT;\n}\n\ntype BadgePreview = {\n messageType?: string;\n title?: string;\n summary?: string;\n};\n\nfunction parseBadgePreview(raw: string): BadgePreview | null {\n try {\n const data = JSON.parse(raw) as Record<string, unknown>;\n if (!data || typeof data !== 'object') return null;\n const messageType = String(data.messageType || data.message_type || '').trim();\n const title = String(data.title || '').trim();\n const summary = String(data.summary || '').trim();\n if (!messageType && !title && !summary) return null;\n return {\n messageType: messageType || undefined,\n title: title || undefined,\n summary: summary || undefined,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * 通用站内信铃铛:列表 / 已读 / Tab / 角标 / 卡片底栏动作 / 可选 SSE toast。\n * 认领、去执行等业务动作由 `onItemAction` 注入;默认底栏按钮走 onNavigate / href。\n * 默认不定时轮询;有消息侧靠业务回调 / 路由 / 焦点 / 可选 SSE 再拉角标。\n */\nconst InboxBell = forwardRef<InboxBellHandle, InboxBellProps>(function InboxBell(\n {\n fetchInbox,\n markRead,\n onNavigate,\n pollMs = 0,\n locationKey,\n pageSize = 20,\n className,\n title = '站内信',\n streamPath = '/api/v1/msg-center/inbox/stream',\n getAccessToken,\n onItemAction,\n },\n ref,\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 const [toastPrefs, setToastPrefs] = useState<InboxToastPrefs>(() => loadInboxToastPrefs());\n const [loadingMore, setLoadingMore] = useState(false);\n const focusDebounceRef = useRef<number | null>(null);\n const locationKeyPrimedRef = useRef(false);\n const toastPrefsRef = useRef(toastPrefs);\n toastPrefsRef.current = toastPrefs;\n const currentPageRef = useRef(1);\n const loadingMoreRef = useRef(false);\n const hasMoreRef = useRef(false);\n\n const listQuery = useMemo(\n () => ({\n messageType: messageType || undefined,\n unreadOnly: readFilter === 'unread' || undefined,\n readOnly: readFilter === 'read' || undefined,\n }),\n [messageType, readFilter],\n );\n\n const load = useCallback(async () => {\n setLoading(true);\n setError('');\n currentPageRef.current = 1;\n hasMoreRef.current = false;\n try {\n const res = await fetchInbox({\n currentPage: 1,\n pageSize,\n ...listQuery,\n });\n const page = res?.pageData || [];\n const total = typeof res?.total === 'number' ? res.total : page.length;\n setItems(page);\n hasMoreRef.current = page.length > 0 && page.length < total;\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch (e) {\n setItems([]);\n hasMoreRef.current = false;\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setLoading(false);\n }\n }, [fetchInbox, pageSize, listQuery]);\n\n const loadMore = useCallback(async () => {\n if (loadingMoreRef.current || !hasMoreRef.current) return;\n loadingMoreRef.current = true;\n setLoadingMore(true);\n try {\n const next = currentPageRef.current + 1;\n const res = await fetchInbox({\n currentPage: next,\n pageSize,\n ...listQuery,\n });\n const page = res?.pageData || [];\n const total = typeof res?.total === 'number' ? res.total : 0;\n setItems((prev) => {\n const seen = new Set(prev.map((x) => x.id));\n const extra = page.filter((x) => x?.id && !seen.has(x.id));\n const merged = extra.length ? [...prev, ...extra] : prev;\n hasMoreRef.current =\n extra.length > 0 && (total > 0 ? merged.length < total : extra.length >= pageSize);\n return merged;\n });\n if (page.length) currentPageRef.current = next;\n if (typeof res?.unreadTotal === 'number') setUnreadTotal(res.unreadTotal);\n if (res?.unreadByMessageType) setUnreadByType(res.unreadByMessageType);\n } catch {\n hasMoreRef.current = false;\n } finally {\n loadingMoreRef.current = false;\n setLoadingMore(false);\n }\n }, [fetchInbox, pageSize, listQuery]);\n\n const onListScroll = useCallback(\n (e: UIEvent<HTMLDivElement>) => {\n const el = e.currentTarget;\n if (el.scrollHeight - el.scrollTop - el.clientHeight <= LOAD_MORE_GAP_PX) {\n void loadMore();\n }\n },\n [loadMore],\n );\n\n const refreshBadge = useCallback(async () => {\n try {\n // 与列表同 pageSize(禁硬编码 1);角标只消费 unread* 字段\n const res = await fetchInbox({ currentPage: 1, pageSize });\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch {\n /* 角标失败不打断 UI */\n }\n }, [fetchInbox, pageSize]);\n\n useImperativeHandle(ref, () => ({ refreshBadge }), [refreshBadge]);\n\n useEffect(() => {\n void refreshBadge();\n }, [refreshBadge]);\n\n useEffect(() => {\n if (locationKey === undefined) return;\n // 挂载首刷已由 refreshBadge effect 覆盖;仅后续路由变化再拉\n if (!locationKeyPrimedRef.current) {\n locationKeyPrimedRef.current = true;\n return;\n }\n void refreshBadge();\n }, [locationKey, 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 const schedule = () => {\n if (focusDebounceRef.current != null) {\n window.clearTimeout(focusDebounceRef.current);\n }\n focusDebounceRef.current = window.setTimeout(() => {\n focusDebounceRef.current = null;\n void refreshBadge();\n }, FOCUS_DEBOUNCE_MS);\n };\n\n const onVisibility = () => {\n if (document.visibilityState === 'visible') schedule();\n };\n\n window.addEventListener('focus', schedule);\n document.addEventListener('visibilitychange', onVisibility);\n return () => {\n window.removeEventListener('focus', schedule);\n document.removeEventListener('visibilitychange', onVisibility);\n if (focusDebounceRef.current != null) {\n window.clearTimeout(focusDebounceRef.current);\n focusDebounceRef.current = null;\n }\n };\n }, [refreshBadge]);\n\n useEffect(() => {\n const onExternal = () => {\n void refreshBadge();\n };\n window.addEventListener(INBOX_BADGE_REFRESH_EVENT, onExternal);\n return () => window.removeEventListener(INBOX_BADGE_REFRESH_EVENT, onExternal);\n }, [refreshBadge]);\n\n useEffect(() => {\n if (streamPath === false) return undefined;\n if (typeof getAccessToken !== 'function') return undefined;\n if (typeof window === 'undefined' || typeof EventSource === 'undefined') return undefined;\n\n const token = String(getAccessToken() || '').trim();\n if (!token) return undefined;\n\n const base = String(streamPath || '/api/v1/msg-center/inbox/stream').trim();\n const url = new URL(base, window.location.origin);\n url.searchParams.set('access_token', token);\n\n let es: EventSource;\n try {\n es = new EventSource(url.toString());\n } catch {\n return undefined;\n }\n\n const onBadge = (ev: Event) => {\n void refreshBadge();\n const msgEv = ev as MessageEvent;\n const preview = typeof msgEv?.data === 'string' ? parseBadgePreview(msgEv.data) : null;\n if (!preview) return;\n if (!shouldToastForMessageType(toastPrefsRef.current, preview.messageType)) return;\n const toastTitle = preview.title || '新站内信';\n const toastDesc = preview.summary || '';\n const typeLabel = messageTypeLabel(preview.messageType);\n const openDrawer = () => {\n notification.destroy();\n setOpen(true);\n };\n const toastKey = `inbox-badge-${preview.messageType || 'msg'}-${Date.now()}`;\n notification.open({\n key: toastKey,\n className: classNames('marsun-inbox-toast', styles.toastNotice),\n closable: true,\n title: (\n <div className={styles.toastHead}>\n <span className={styles.toastTitle}>{emphasizeQuoted(toastTitle)}</span>\n {typeLabel ? (\n <SemanticTag\n color={messageTypeSemanticColor(preview.messageType)}\n className={styles.typeTag}\n >\n {typeLabel}\n </SemanticTag>\n ) : null}\n </div>\n ),\n message: (\n <div className={styles.toastHead}>\n <span className={styles.toastTitle}>{emphasizeQuoted(toastTitle)}</span>\n {typeLabel ? (\n <SemanticTag\n color={messageTypeSemanticColor(preview.messageType)}\n className={styles.typeTag}\n >\n {typeLabel}\n </SemanticTag>\n ) : null}\n </div>\n ),\n description: (\n <div className={styles.toastBody}>\n {toastDesc ? (\n <div className={styles.toastDesc}>{emphasizeQuoted(toastDesc)}</div>\n ) : null}\n <div className={styles.toastActions}>\n <Button\n type=\"primary\"\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n openDrawer();\n }}\n >\n 查看\n </Button>\n </div>\n </div>\n ),\n placement: 'topRight',\n duration: 6,\n onClick: openDrawer,\n });\n };\n es.addEventListener('badge', onBadge);\n es.addEventListener('inbox', onBadge);\n // 失败回落写后/焦点刷新;关连接防 EventSource 自动重连刷屏\n es.onerror = () => {\n es.close();\n };\n\n return () => {\n es.removeEventListener('badge', onBadge);\n es.removeEventListener('inbox', onBadge);\n es.close();\n };\n }, [streamPath, getAccessToken, 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 updateToastPref = (key: keyof InboxToastPrefs, checked: boolean) => {\n setToastPrefs((prev) => {\n const next = { ...prev, [key]: checked };\n saveInboxToastPrefs(next);\n return next;\n });\n };\n\n const handleOpenItem = async (item: InboxBellItem, opts?: { skipRead?: boolean }) => {\n if (!opts?.skipRead && !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 const runQuickAction = async (item: InboxBellItem, action: InboxItemQuickAction) => {\n if (action.disabled) return;\n if (onItemAction) {\n try {\n await onItemAction(action.kind, item);\n setOpen(false);\n void load();\n void refreshBadge();\n } catch (e) {\n message.error(e instanceof Error ? e.message : '操作失败');\n }\n return;\n }\n await handleOpenItem(item);\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 <div className={styles.toastPrefs} data-testid=\"inbox-toast-prefs\">\n <div className={styles.toastPrefsTitle}>消息提示</div>\n <p className={styles.toastPrefsHint}>本机浏览器偏好,非租户策略</p>\n <Space size={12} wrap>\n <Checkbox\n checked={toastPrefs.alert}\n onChange={(e) => updateToastPref('alert', e.target.checked)}\n >\n 预警弹出\n </Checkbox>\n <Checkbox\n checked={toastPrefs.action}\n onChange={(e) => updateToastPref('action', e.target.checked)}\n >\n 行动弹出\n </Checkbox>\n <Checkbox\n checked={toastPrefs.remind}\n onChange={(e) => updateToastPref('remind', e.target.checked)}\n >\n 提醒弹出\n </Checkbox>\n </Space>\n </div>\n {error ? <p className={styles.error}>{error}</p> : null}\n <div className={classNames('inbox-bell-list-pane', styles.listPane)}>\n <PageSpin spinning={loading && items.length === 0}>\n {!loading && !error && items.length === 0 ? (\n <Empty description=\"暂无站内信\" />\n ) : items.length === 0 ? null : (\n <VirtualScrollbar\n wrapperClassName={classNames('inbox-bell-list-scroll', styles.listScroll)}\n className={styles.listViewport}\n data-testid=\"inbox-bell-list-scroll\"\n onScroll={onListScroll}\n >\n <ul className={styles.list}>\n {items.map((item) => {\n const typeLabel = messageTypeLabel(item.messageType);\n const levelText = String(item.levelLabel || item.level || '').trim();\n const showLevel = Boolean(levelText);\n const safeHtml = sanitizeInboxHtml(item.bodyHtml);\n const actions = filterInboxActionsForHost(\n resolveInboxItemActions(item),\n Boolean(onItemAction),\n );\n const buttonDriven = isInboxButtonDriven(item);\n const meta = itemMetaLine(item);\n const showActions = Boolean(actions.primary);\n return (\n <li key={item.id}>\n <div\n className={classNames(\n styles.item,\n !item.read && styles.itemUnread,\n buttonDriven && styles.itemStatic,\n )}\n role={buttonDriven ? undefined : 'button'}\n tabIndex={buttonDriven ? undefined : 0}\n onClick={buttonDriven ? undefined : () => void handleOpenItem(item)}\n onKeyDown={\n buttonDriven\n ? undefined\n : (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n void handleOpenItem(item);\n }\n }\n }\n >\n <div className={styles.itemHeader}>\n <span className={styles.itemHeaderLeft}>\n <span className={styles.itemTitle} title={item.title || '(无标题)'}>\n {item.title || '(无标题)'}\n </span>\n {typeLabel ? (\n <SemanticTag\n color={messageTypeSemanticColor(item.messageType)}\n className={styles.typeTag}\n >\n {typeLabel}\n </SemanticTag>\n ) : null}\n </span>\n <span className={styles.itemTime}>{item.createdAt || ''}</span>\n </div>\n <div className={styles.itemBody}>\n {safeHtml ? (\n <div\n className={styles.itemBodyHtml}\n dangerouslySetInnerHTML={{ __html: safeHtml }}\n />\n ) : item.summary ? (\n <span className={styles.itemSummary}>\n {emphasizeQuoted(item.summary)}\n </span>\n ) : null}\n </div>\n {meta ? <span className={styles.itemMeta}>{meta}</span> : null}\n {showLevel ? (\n <div className={styles.itemFooterTags}>\n <SemanticTag\n color={resolveLevelTagColor(item.levelColor)}\n className={styles.typeTag}\n >\n {levelText}\n </SemanticTag>\n </div>\n ) : null}\n {showActions && actions.primary ? (\n <div\n className={styles.itemActions}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <Space size={8} wrap>\n <Button\n size=\"small\"\n type=\"primary\"\n onClick={() => void runQuickAction(item, actions.primary!)}\n >\n {actions.primary.label}\n </Button>\n {actions.secondary ? (\n <Button\n size=\"small\"\n type=\"link\"\n onClick={() => void runQuickAction(item, actions.secondary!)}\n >\n {actions.secondary.label}\n </Button>\n ) : null}\n </Space>\n </div>\n ) : null}\n </div>\n </li>\n );\n })}\n </ul>\n {loadingMore ? (\n <p className={classNames('inbox-bell-list-footer', styles.listFooter)}>加载中…</p>\n ) : null}\n </VirtualScrollbar>\n )}\n </PageSpin>\n </div>\n </Drawer>\n </div>\n );\n});\n\nexport default InboxBell;\nexport {\n DEFAULT_INBOX_TOAST_PREFS,\n loadInboxToastPrefs,\n saveInboxToastPrefs,\n shouldToastForMessageType,\n} from './toastPrefs';\nexport type { InboxToastPrefs } from './toastPrefs';\nexport {\n resolveInboxItemActions,\n resolveInboxSceneKey,\n filterInboxActionsForHost,\n normalizeInboxActions,\n inboxSceneLabel,\n isInboxButtonDriven,\n isTerminalActionStatus,\n} from './inboxItemActions';\nexport type {\n InboxItemActionKind,\n InboxItemQuickAction,\n InboxItemActionsResolved,\n} from './inboxItemActions';\n"],"names":["TYPE_TABS","TYPE_TAG_LABEL","FOCUS_DEBOUNCE_MS","LOAD_MORE_GAP_PX","messageTypeLabel","raw","key","messageTypeSemanticColor","SEMANTIC_COLORS","itemMetaLine","item","x","resolveLevelTagColor","parseBadgePreview","data","messageType","title","summary","InboxBell","forwardRef","fetchInbox","markRead","onNavigate","pollMs","locationKey","pageSize","className","streamPath","getAccessToken","onItemAction","ref","open","setOpen","useState","loading","setLoading","error","setError","items","setItems","unreadTotal","setUnreadTotal","unreadByType","setUnreadByType","setMessageType","readFilter","setReadFilter","toastPrefs","setToastPrefs","loadInboxToastPrefs","loadingMore","setLoadingMore","focusDebounceRef","useRef","locationKeyPrimedRef","toastPrefsRef","currentPageRef","loadingMoreRef","hasMoreRef","listQuery","useMemo","load","useCallback","res","page","total","loadMore","next","prev","seen","extra","merged","onListScroll","el","refreshBadge","useImperativeHandle","useEffect","t","schedule","onVisibility","onExternal","INBOX_BADGE_REFRESH_EVENT","token","base","url","es","onBadge","ev","msgEv","preview","shouldToastForMessageType","toastTitle","toastDesc","typeLabel","openDrawer","notification","toastKey","classNames","styles","jsxs","jsx","emphasizeQuoted","SemanticTag","Button","e","typeTabOptions","n","updateToastPref","checked","saveInboxToastPrefs","handleOpenItem","opts","message","href","runQuickAction","action","Badge","Bell","Drawer","StateBar","k","SegmentedRadio","v","Space","Checkbox","PageSpin","Empty","VirtualScrollbar","levelText","showLevel","safeHtml","sanitizeInboxHtml","actions","filterInboxActionsForHost","resolveInboxItemActions","buttonDriven","isInboxButtonDriven","meta","showActions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InboxBell.js","sources":["../../../../../src/components/Tools/Inbox/InboxBell/InboxBell.tsx"],"sourcesContent":["import { Badge, Button, Checkbox, Drawer, Space, message, notification } from 'antd';\nimport classNames from 'classnames';\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type UIEvent,\n} 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 { SEMANTIC_COLORS, SemanticTag } from '@/components/Tag';\nimport { VirtualScrollbar } from '@/components/VirtualScrollbar';\nimport { sanitizeInboxHtml } from '../sanitizeInboxHtml';\nimport { INBOX_BADGE_REFRESH_EVENT } from '../requestInboxBadgeRefresh';\nimport { emphasizeQuoted } from './emphasizeQuoted';\nimport {\n filterInboxActionsForHost,\n isInboxButtonDriven,\n resolveInboxItemActions,\n type InboxItemActionKind,\n type InboxItemQuickAction,\n} from './inboxItemActions';\nimport {\n loadInboxToastPrefs,\n saveInboxToastPrefs,\n shouldToastForMessageType,\n type InboxToastPrefs,\n} from './toastPrefs';\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 /** 级别展示名(业务仓从已有维表/工具函数填;空则回落 level) */\n levelLabel?: string;\n /**\n * 级别 Tag 色:业务仓传入预警级别设置色(如 QA `ALERT_LEVEL_COLORS.*.accent`)。\n * 支持 SemanticColor 键或 `#hex`;core 不自造级别色表。\n */\n levelColor?: string;\n category?: string;\n scene?: string;\n eventKey?: string;\n categoryLabel?: string;\n alertId?: string | null;\n actionId?: string | null;\n claimed?: boolean;\n started?: boolean;\n /** 行动当前状态(enrich / contextJson);终态时底栏只保留查看任务 */\n actionStatus?: string;\n factory?: string;\n variety?: string;\n metric?: string;\n /** 业务日/月份(如 2026-07-31);预警深链 date 用 */\n month?: string;\n};\n\nexport type InboxBellListResult = {\n /** 分页列表(Marsun list-api 唯一数组名) */\n pageData: 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 /**\n * 轮询未读角标(ms)。默认 `0`(关定时);`>0` 才 setInterval。\n * 角标另由:挂载首刷、`locationKey`、focus/visibility、`requestInboxBadgeRefresh` 触发。\n */\n pollMs?: number;\n /**\n * 路由/页面身份;变化时刷新角标(如 React Router `location.pathname`)。\n * 整页加载靠挂载首刷,不必另传。\n */\n locationKey?: string | number;\n pageSize?: number;\n className?: string;\n /** Drawer 标题 */\n title?: string;\n /**\n * 同源 SSE 路径(默认 `/api/v1/msg-center/inbox/stream`)。\n * 传 `false` 关闭。须配合 `getAccessToken`(EventSource 用 `access_token` 查询参数传 JWT)。\n * 失败回落写后刷新 / 焦点刷新,不定时轮询冒充。\n */\n streamPath?: string | false;\n /** 返回当前 JWT;空则不开 SSE */\n getAccessToken?: () => string | null | undefined;\n /**\n * 卡片底栏动作(认领/去执行/查看等)。不传则底栏按钮一律走 onNavigate / href。\n * 业务仓拦截 claim_alert / start_action;铃铛不解析新建任务。\n */\n onItemAction?: (kind: InboxItemActionKind, item: InboxBellItem) => void | Promise<void>;\n};\n\nexport type InboxBellHandle = {\n refreshBadge: () => Promise<void>;\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\nconst TYPE_TAG_LABEL: Record<string, string> = {\n alert: '预警',\n action: '行动',\n remind: '提醒',\n};\n\nconst FOCUS_DEBOUNCE_MS = 300;\n/** SSE / 写后 / 外部刷角标合并窗口,避免扫描风暴打爆 inbox */\nconst BADGE_DEBOUNCE_MS = 1_500;\n/** 距底部小于该值时拉下一页 */\nconst LOAD_MORE_GAP_PX = 72;\n\nfunction messageTypeLabel(raw?: string): string {\n const key = String(raw || '')\n .trim()\n .toLowerCase();\n if (!key) return '';\n return TYPE_TAG_LABEL[key] || key;\n}\n\nfunction messageTypeSemanticColor(raw?: string): string {\n const key = String(raw || '')\n .trim()\n .toLowerCase();\n if (key === 'alert') return SEMANTIC_COLORS.DANGER;\n if (key === 'action') return SEMANTIC_COLORS.PRIMARY;\n if (key === 'remind') return SEMANTIC_COLORS.WARNING;\n return SEMANTIC_COLORS.DEFAULT;\n}\n\nfunction itemMetaLine(item: InboxBellItem): string {\n return [item.factory, item.variety, item.metric]\n .map((x) => String(x || '').trim())\n .filter(Boolean)\n .join(' · ');\n}\n\n/** 业务传入色;无则 DEFAULT(禁止在 core 造级别→色平行表) */\nfunction resolveLevelTagColor(raw?: string): string {\n const c = String(raw || '').trim();\n return c || SEMANTIC_COLORS.DEFAULT;\n}\n\ntype BadgePreview = {\n messageType?: string;\n title?: string;\n summary?: string;\n};\n\nfunction parseBadgePreview(raw: string): BadgePreview | null {\n try {\n const data = JSON.parse(raw) as Record<string, unknown>;\n if (!data || typeof data !== 'object') return null;\n const messageType = String(data.messageType || data.message_type || '').trim();\n const title = String(data.title || '').trim();\n const summary = String(data.summary || '').trim();\n if (!messageType && !title && !summary) return null;\n return {\n messageType: messageType || undefined,\n title: title || undefined,\n summary: summary || undefined,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * 通用站内信铃铛:列表 / 已读 / Tab / 角标 / 卡片底栏动作 / 可选 SSE toast。\n * 认领、去执行等业务动作由 `onItemAction` 注入;默认底栏按钮走 onNavigate / href。\n * 默认不定时轮询;有消息侧靠业务回调 / 路由 / 焦点 / 可选 SSE 再拉角标。\n */\nconst InboxBell = forwardRef<InboxBellHandle, InboxBellProps>(function InboxBell(\n {\n fetchInbox,\n markRead,\n onNavigate,\n pollMs = 0,\n locationKey,\n pageSize = 20,\n className,\n title = '站内信',\n streamPath = '/api/v1/msg-center/inbox/stream',\n getAccessToken,\n onItemAction,\n },\n ref,\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 const [toastPrefs, setToastPrefs] = useState<InboxToastPrefs>(() => loadInboxToastPrefs());\n const [loadingMore, setLoadingMore] = useState(false);\n const focusDebounceRef = useRef<number | null>(null);\n const badgeDebounceRef = useRef<number | null>(null);\n const pendingToastRef = useRef<BadgePreview | null>(null);\n const locationKeyPrimedRef = useRef(false);\n const toastPrefsRef = useRef(toastPrefs);\n toastPrefsRef.current = toastPrefs;\n const currentPageRef = useRef(1);\n const loadingMoreRef = useRef(false);\n const hasMoreRef = useRef(false);\n\n const listQuery = useMemo(\n () => ({\n messageType: messageType || undefined,\n unreadOnly: readFilter === 'unread' || undefined,\n readOnly: readFilter === 'read' || undefined,\n }),\n [messageType, readFilter],\n );\n\n const load = useCallback(async () => {\n setLoading(true);\n setError('');\n currentPageRef.current = 1;\n hasMoreRef.current = false;\n try {\n const res = await fetchInbox({\n currentPage: 1,\n pageSize,\n ...listQuery,\n });\n const page = res?.pageData || [];\n const total = typeof res?.total === 'number' ? res.total : page.length;\n setItems(page);\n hasMoreRef.current = page.length > 0 && page.length < total;\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch (e) {\n setItems([]);\n hasMoreRef.current = false;\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setLoading(false);\n }\n }, [fetchInbox, pageSize, listQuery]);\n\n const loadMore = useCallback(async () => {\n if (loadingMoreRef.current || !hasMoreRef.current) return;\n loadingMoreRef.current = true;\n setLoadingMore(true);\n try {\n const next = currentPageRef.current + 1;\n const res = await fetchInbox({\n currentPage: next,\n pageSize,\n ...listQuery,\n });\n const page = res?.pageData || [];\n const total = typeof res?.total === 'number' ? res.total : 0;\n setItems((prev) => {\n const seen = new Set(prev.map((x) => x.id));\n const extra = page.filter((x) => x?.id && !seen.has(x.id));\n const merged = extra.length ? [...prev, ...extra] : prev;\n hasMoreRef.current =\n extra.length > 0 && (total > 0 ? merged.length < total : extra.length >= pageSize);\n return merged;\n });\n if (page.length) currentPageRef.current = next;\n if (typeof res?.unreadTotal === 'number') setUnreadTotal(res.unreadTotal);\n if (res?.unreadByMessageType) setUnreadByType(res.unreadByMessageType);\n } catch {\n hasMoreRef.current = false;\n } finally {\n loadingMoreRef.current = false;\n setLoadingMore(false);\n }\n }, [fetchInbox, pageSize, listQuery]);\n\n const onListScroll = useCallback(\n (e: UIEvent<HTMLDivElement>) => {\n const el = e.currentTarget;\n if (el.scrollHeight - el.scrollTop - el.clientHeight <= LOAD_MORE_GAP_PX) {\n void loadMore();\n }\n },\n [loadMore],\n );\n\n const refreshBadge = useCallback(async () => {\n try {\n // 与列表同 pageSize(禁硬编码 1);角标只消费 unread* 字段\n const res = await fetchInbox({ currentPage: 1, pageSize });\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch {\n /* 角标失败不打断 UI */\n }\n }, [fetchInbox, pageSize]);\n\n const flushPendingToast = useCallback(() => {\n const preview = pendingToastRef.current;\n pendingToastRef.current = null;\n if (!preview) return;\n if (!shouldToastForMessageType(toastPrefsRef.current, preview.messageType)) return;\n const toastTitle = preview.title || '新站内信';\n const toastDesc = preview.summary || '';\n const typeLabel = messageTypeLabel(preview.messageType);\n const openDrawer = () => {\n notification.destroy();\n setOpen(true);\n };\n const toastKey = `inbox-badge-${preview.messageType || 'msg'}-${Date.now()}`;\n notification.open({\n key: toastKey,\n className: classNames('marsun-inbox-toast', styles.toastNotice),\n closable: true,\n title: (\n <div className={styles.toastHead}>\n <span className={styles.toastTitle}>{emphasizeQuoted(toastTitle)}</span>\n {typeLabel ? (\n <SemanticTag\n color={messageTypeSemanticColor(preview.messageType)}\n className={styles.typeTag}\n >\n {typeLabel}\n </SemanticTag>\n ) : null}\n </div>\n ),\n message: (\n <div className={styles.toastHead}>\n <span className={styles.toastTitle}>{emphasizeQuoted(toastTitle)}</span>\n {typeLabel ? (\n <SemanticTag\n color={messageTypeSemanticColor(preview.messageType)}\n className={styles.typeTag}\n >\n {typeLabel}\n </SemanticTag>\n ) : null}\n </div>\n ),\n description: (\n <div className={styles.toastBody}>\n {toastDesc ? <div className={styles.toastDesc}>{emphasizeQuoted(toastDesc)}</div> : null}\n <div className={styles.toastActions}>\n <Button\n type=\"primary\"\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n openDrawer();\n }}\n >\n 查看\n </Button>\n </div>\n </div>\n ),\n placement: 'topRight',\n duration: 6,\n onClick: openDrawer,\n });\n }, []);\n\n /** 合并高频角标刷新(SSE 扫描风暴 / 写后 / 路由 / 焦点);有预览时立即 toast,角标仍防抖 */\n const scheduleBadgeRefresh = useCallback(\n (preview?: BadgePreview | null) => {\n if (preview) {\n pendingToastRef.current = preview;\n flushPendingToast();\n }\n if (badgeDebounceRef.current != null) {\n window.clearTimeout(badgeDebounceRef.current);\n }\n badgeDebounceRef.current = window.setTimeout(() => {\n badgeDebounceRef.current = null;\n void refreshBadge();\n }, BADGE_DEBOUNCE_MS);\n },\n [refreshBadge, flushPendingToast],\n );\n\n useImperativeHandle(ref, () => ({ refreshBadge }), [refreshBadge]);\n\n useEffect(() => {\n void refreshBadge();\n }, [refreshBadge]);\n\n useEffect(() => {\n if (locationKey === undefined) return;\n // 挂载首刷已由 refreshBadge effect 覆盖;仅后续路由变化再拉\n if (!locationKeyPrimedRef.current) {\n locationKeyPrimedRef.current = true;\n return;\n }\n scheduleBadgeRefresh();\n }, [locationKey, scheduleBadgeRefresh]);\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 const schedule = () => {\n if (focusDebounceRef.current != null) {\n window.clearTimeout(focusDebounceRef.current);\n }\n focusDebounceRef.current = window.setTimeout(() => {\n focusDebounceRef.current = null;\n scheduleBadgeRefresh();\n }, FOCUS_DEBOUNCE_MS);\n };\n\n const onVisibility = () => {\n if (document.visibilityState === 'visible') schedule();\n };\n\n window.addEventListener('focus', schedule);\n document.addEventListener('visibilitychange', onVisibility);\n return () => {\n window.removeEventListener('focus', schedule);\n document.removeEventListener('visibilitychange', onVisibility);\n if (focusDebounceRef.current != null) {\n window.clearTimeout(focusDebounceRef.current);\n focusDebounceRef.current = null;\n }\n };\n }, [scheduleBadgeRefresh]);\n\n useEffect(() => {\n const onExternal = (ev: Event) => {\n const detail = (ev as CustomEvent<{ preview?: BadgePreview | null }>).detail;\n scheduleBadgeRefresh(detail?.preview || undefined);\n };\n window.addEventListener(INBOX_BADGE_REFRESH_EVENT, onExternal);\n return () => window.removeEventListener(INBOX_BADGE_REFRESH_EVENT, onExternal);\n }, [scheduleBadgeRefresh]);\n\n useEffect(() => {\n return () => {\n if (badgeDebounceRef.current != null) {\n window.clearTimeout(badgeDebounceRef.current);\n badgeDebounceRef.current = null;\n }\n };\n }, []);\n\n useEffect(() => {\n if (streamPath === false) return undefined;\n if (typeof getAccessToken !== 'function') return undefined;\n if (typeof window === 'undefined' || typeof EventSource === 'undefined') return undefined;\n\n const base = String(streamPath || '/api/v1/msg-center/inbox/stream').trim();\n let closed = false;\n let es: EventSource | null = null;\n let retryTimer: number | null = null;\n let attempt = 0;\n\n const onBadge = (ev: Event) => {\n const msgEv = ev as MessageEvent;\n const preview = typeof msgEv?.data === 'string' ? parseBadgePreview(msgEv.data) : null;\n scheduleBadgeRefresh(preview);\n };\n\n const clearRetry = () => {\n if (retryTimer != null) {\n window.clearTimeout(retryTimer);\n retryTimer = null;\n }\n };\n\n const scheduleReconnect = () => {\n if (closed || retryTimer != null) return;\n const delay = Math.min(30_000, 1_000 * 2 ** Math.min(attempt, 5));\n attempt += 1;\n retryTimer = window.setTimeout(() => {\n retryTimer = null;\n connect();\n }, delay);\n };\n\n const connect = () => {\n if (closed) return;\n const token = String(getAccessToken() || '').trim();\n if (!token) {\n scheduleReconnect();\n return;\n }\n if (es) {\n es.removeEventListener('badge', onBadge);\n es.removeEventListener('inbox', onBadge);\n es.close();\n es = null;\n }\n const url = new URL(base, window.location.origin);\n url.searchParams.set('access_token', token);\n try {\n es = new EventSource(url.toString());\n } catch {\n scheduleReconnect();\n return;\n }\n es.addEventListener('badge', onBadge);\n es.addEventListener('inbox', onBadge);\n es.onopen = () => {\n attempt = 0;\n };\n // 受控退避重连(勿永久 close;否则站内信 toast 再也收不到)\n es.onerror = () => {\n if (closed) return;\n es?.close();\n es = null;\n scheduleReconnect();\n };\n };\n\n connect();\n\n return () => {\n closed = true;\n clearRetry();\n if (es) {\n es.removeEventListener('badge', onBadge);\n es.removeEventListener('inbox', onBadge);\n es.close();\n es = null;\n }\n };\n }, [streamPath, getAccessToken, scheduleBadgeRefresh]);\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 updateToastPref = (key: keyof InboxToastPrefs, checked: boolean) => {\n setToastPrefs((prev) => {\n const next = { ...prev, [key]: checked };\n saveInboxToastPrefs(next);\n return next;\n });\n };\n\n const handleOpenItem = async (item: InboxBellItem, opts?: { skipRead?: boolean }) => {\n if (!opts?.skipRead && !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 const runQuickAction = async (item: InboxBellItem, action: InboxItemQuickAction) => {\n if (action.disabled) return;\n if (onItemAction) {\n try {\n await onItemAction(action.kind, item);\n setOpen(false);\n void load();\n void refreshBadge();\n } catch (e) {\n message.error(e instanceof Error ? e.message : '操作失败');\n }\n return;\n }\n await handleOpenItem(item);\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 <div className={styles.toastPrefs} data-testid=\"inbox-toast-prefs\">\n <div className={styles.toastPrefsTitle}>消息提示</div>\n <p className={styles.toastPrefsHint}>本机浏览器偏好,非租户策略</p>\n <Space size={12} wrap>\n <Checkbox\n checked={toastPrefs.alert}\n onChange={(e) => updateToastPref('alert', e.target.checked)}\n >\n 预警弹出\n </Checkbox>\n <Checkbox\n checked={toastPrefs.action}\n onChange={(e) => updateToastPref('action', e.target.checked)}\n >\n 行动弹出\n </Checkbox>\n <Checkbox\n checked={toastPrefs.remind}\n onChange={(e) => updateToastPref('remind', e.target.checked)}\n >\n 提醒弹出\n </Checkbox>\n </Space>\n </div>\n {error ? <p className={styles.error}>{error}</p> : null}\n <div className={classNames('inbox-bell-list-pane', styles.listPane)}>\n <PageSpin spinning={loading && items.length === 0}>\n {!loading && !error && items.length === 0 ? (\n <Empty description=\"暂无站内信\" />\n ) : items.length === 0 ? null : (\n <VirtualScrollbar\n wrapperClassName={classNames('inbox-bell-list-scroll', styles.listScroll)}\n className={styles.listViewport}\n data-testid=\"inbox-bell-list-scroll\"\n onScroll={onListScroll}\n >\n <ul className={styles.list}>\n {items.map((item) => {\n const typeLabel = messageTypeLabel(item.messageType);\n const levelText = String(item.levelLabel || item.level || '').trim();\n const showLevel = Boolean(levelText);\n const safeHtml = sanitizeInboxHtml(item.bodyHtml);\n const actions = filterInboxActionsForHost(\n resolveInboxItemActions(item),\n Boolean(onItemAction),\n );\n const buttonDriven = isInboxButtonDriven(item);\n const meta = itemMetaLine(item);\n const showActions = Boolean(actions.primary);\n return (\n <li key={item.id}>\n <div\n className={classNames(\n styles.item,\n !item.read && styles.itemUnread,\n buttonDriven && styles.itemStatic,\n )}\n role={buttonDriven ? undefined : 'button'}\n tabIndex={buttonDriven ? undefined : 0}\n onClick={buttonDriven ? undefined : () => void handleOpenItem(item)}\n onKeyDown={\n buttonDriven\n ? undefined\n : (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n void handleOpenItem(item);\n }\n }\n }\n >\n <div className={styles.itemHeader}>\n <span className={styles.itemHeaderLeft}>\n <span className={styles.itemTitle} title={item.title || '(无标题)'}>\n {item.title || '(无标题)'}\n </span>\n {typeLabel ? (\n <SemanticTag\n color={messageTypeSemanticColor(item.messageType)}\n className={styles.typeTag}\n >\n {typeLabel}\n </SemanticTag>\n ) : null}\n </span>\n <span className={styles.itemTime}>{item.createdAt || ''}</span>\n </div>\n <div className={styles.itemBody}>\n {safeHtml ? (\n <div\n className={styles.itemBodyHtml}\n dangerouslySetInnerHTML={{ __html: safeHtml }}\n />\n ) : item.summary ? (\n <span className={styles.itemSummary}>\n {emphasizeQuoted(item.summary)}\n </span>\n ) : null}\n </div>\n {meta ? <span className={styles.itemMeta}>{meta}</span> : null}\n {showLevel ? (\n <div className={styles.itemFooterTags}>\n <SemanticTag\n color={resolveLevelTagColor(item.levelColor)}\n className={styles.typeTag}\n >\n {levelText}\n </SemanticTag>\n </div>\n ) : null}\n {showActions && actions.primary ? (\n <div\n className={styles.itemActions}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <Space size={8} wrap>\n <Button\n size=\"small\"\n type=\"primary\"\n onClick={() => void runQuickAction(item, actions.primary!)}\n >\n {actions.primary.label}\n </Button>\n {actions.secondary ? (\n <Button\n size=\"small\"\n type=\"link\"\n onClick={() => void runQuickAction(item, actions.secondary!)}\n >\n {actions.secondary.label}\n </Button>\n ) : null}\n </Space>\n </div>\n ) : null}\n </div>\n </li>\n );\n })}\n </ul>\n {loadingMore ? (\n <p className={classNames('inbox-bell-list-footer', styles.listFooter)}>加载中…</p>\n ) : null}\n </VirtualScrollbar>\n )}\n </PageSpin>\n </div>\n </Drawer>\n </div>\n );\n});\n\nexport default InboxBell;\nexport {\n DEFAULT_INBOX_TOAST_PREFS,\n loadInboxToastPrefs,\n saveInboxToastPrefs,\n shouldToastForMessageType,\n} from './toastPrefs';\nexport type { InboxToastPrefs } from './toastPrefs';\nexport {\n resolveInboxItemActions,\n resolveInboxSceneKey,\n filterInboxActionsForHost,\n normalizeInboxActions,\n inboxSceneLabel,\n isInboxButtonDriven,\n isTerminalActionStatus,\n} from './inboxItemActions';\nexport type {\n InboxItemActionKind,\n InboxItemQuickAction,\n InboxItemActionsResolved,\n} from './inboxItemActions';\n"],"names":["TYPE_TABS","TYPE_TAG_LABEL","FOCUS_DEBOUNCE_MS","BADGE_DEBOUNCE_MS","LOAD_MORE_GAP_PX","messageTypeLabel","raw","key","messageTypeSemanticColor","SEMANTIC_COLORS","itemMetaLine","item","x","resolveLevelTagColor","parseBadgePreview","data","messageType","title","summary","InboxBell","forwardRef","fetchInbox","markRead","onNavigate","pollMs","locationKey","pageSize","className","streamPath","getAccessToken","onItemAction","ref","open","setOpen","useState","loading","setLoading","error","setError","items","setItems","unreadTotal","setUnreadTotal","unreadByType","setUnreadByType","setMessageType","readFilter","setReadFilter","toastPrefs","setToastPrefs","loadInboxToastPrefs","loadingMore","setLoadingMore","focusDebounceRef","useRef","badgeDebounceRef","pendingToastRef","locationKeyPrimedRef","toastPrefsRef","currentPageRef","loadingMoreRef","hasMoreRef","listQuery","useMemo","load","useCallback","res","page","total","loadMore","next","prev","seen","extra","merged","onListScroll","el","refreshBadge","flushPendingToast","preview","shouldToastForMessageType","toastTitle","toastDesc","typeLabel","openDrawer","notification","toastKey","classNames","styles","jsxs","jsx","emphasizeQuoted","SemanticTag","Button","e","scheduleBadgeRefresh","useImperativeHandle","useEffect","t","schedule","onVisibility","onExternal","ev","detail","INBOX_BADGE_REFRESH_EVENT","base","closed","es","retryTimer","attempt","onBadge","msgEv","clearRetry","scheduleReconnect","delay","connect","token","url","typeTabOptions","n","updateToastPref","checked","saveInboxToastPrefs","handleOpenItem","opts","message","href","runQuickAction","action","Badge","Bell","Drawer","StateBar","k","SegmentedRadio","v","Space","Checkbox","PageSpin","Empty","VirtualScrollbar","levelText","showLevel","safeHtml","sanitizeInboxHtml","actions","filterInboxActionsForHost","resolveInboxItemActions","buttonDriven","isInboxButtonDriven","meta","showActions"],"mappings":"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"}
|
|
@@ -4,3 +4,4 @@ export { resolveInboxItemActions, resolveInboxSceneKey, filterInboxActionsForHos
|
|
|
4
4
|
export type { InboxItemActionKind, InboxItemQuickAction, InboxItemActionsResolved, } from './InboxBell';
|
|
5
5
|
export { sanitizeInboxHtml } from './sanitizeInboxHtml';
|
|
6
6
|
export { INBOX_BADGE_REFRESH_EVENT, requestInboxBadgeRefresh, requestInboxBadgeRefreshAfterWrite, } from './requestInboxBadgeRefresh';
|
|
7
|
+
export type { InboxBadgeRefreshDetail } from './requestInboxBadgeRefresh';
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
/** 站内信角标:外部(业务写成功 / AppShell)触发刷新的事件名 */
|
|
2
2
|
export declare const INBOX_BADGE_REFRESH_EVENT = "marsun-msg-center:refresh-badge";
|
|
3
|
+
/** 业务写后可附带预览,铃铛在 SSE 未达时仍可弹 toast */
|
|
4
|
+
export type InboxBadgeRefreshDetail = {
|
|
5
|
+
preview?: {
|
|
6
|
+
messageType?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
summary?: string;
|
|
9
|
+
} | null;
|
|
10
|
+
};
|
|
3
11
|
/**
|
|
4
12
|
* 请求刷新 InboxBell 未读角标(window CustomEvent)。
|
|
5
13
|
* 铃铛未挂载时无副作用;挂载实例会监听并 refreshBadge。
|
|
14
|
+
* `detail.preview` 有值时按偏好弹出站内信 toast(不依赖 SSE)。
|
|
6
15
|
*/
|
|
7
|
-
export declare function requestInboxBadgeRefresh(): void;
|
|
16
|
+
export declare function requestInboxBadgeRefresh(detail?: InboxBadgeRefreshDetail): void;
|
|
8
17
|
/** 业务写成功后:立即 + 单次延迟补刷(盖 async outbox;非轮询) */
|
|
9
|
-
export declare function requestInboxBadgeRefreshAfterWrite(delayMs?: number): void;
|
|
18
|
+
export declare function requestInboxBadgeRefreshAfterWrite(delayMs?: number, detail?: InboxBadgeRefreshDetail): void;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
const
|
|
2
|
-
function e
|
|
3
|
-
typeof window > "u" || window.dispatchEvent(new CustomEvent(
|
|
1
|
+
const r = "marsun-msg-center:refresh-badge";
|
|
2
|
+
function n(e) {
|
|
3
|
+
typeof window > "u" || window.dispatchEvent(new CustomEvent(r, { detail: e || {} }));
|
|
4
4
|
}
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
},
|
|
5
|
+
function i(e = 1200, t) {
|
|
6
|
+
n(t), !(typeof window > "u") && window.setTimeout(() => {
|
|
7
|
+
n();
|
|
8
|
+
}, e);
|
|
9
9
|
}
|
|
10
10
|
export {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
r as INBOX_BADGE_REFRESH_EVENT,
|
|
12
|
+
n as requestInboxBadgeRefresh,
|
|
13
|
+
i as requestInboxBadgeRefreshAfterWrite
|
|
14
14
|
};
|
|
15
15
|
//# sourceMappingURL=requestInboxBadgeRefresh.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requestInboxBadgeRefresh.js","sources":["../../../../src/components/Tools/Inbox/requestInboxBadgeRefresh.ts"],"sourcesContent":["/** 站内信角标:外部(业务写成功 / AppShell)触发刷新的事件名 */\nexport const INBOX_BADGE_REFRESH_EVENT = 'marsun-msg-center:refresh-badge';\n\n/**\n * 请求刷新 InboxBell 未读角标(window CustomEvent)。\n * 铃铛未挂载时无副作用;挂载实例会监听并 refreshBadge。\n */\nexport function requestInboxBadgeRefresh(): void {\n if (typeof window === 'undefined') return;\n window.dispatchEvent(new CustomEvent(INBOX_BADGE_REFRESH_EVENT));\n}\n\n/** 业务写成功后:立即 + 单次延迟补刷(盖 async outbox;非轮询) */\nexport function requestInboxBadgeRefreshAfterWrite(delayMs = 1200): void {\n requestInboxBadgeRefresh();\n if (typeof window === 'undefined') return;\n window.setTimeout(() => {\n requestInboxBadgeRefresh();\n }, delayMs);\n}\n"],"names":["INBOX_BADGE_REFRESH_EVENT","requestInboxBadgeRefresh","requestInboxBadgeRefreshAfterWrite","delayMs"],"mappings":"AACO,MAAMA,IAA4B;
|
|
1
|
+
{"version":3,"file":"requestInboxBadgeRefresh.js","sources":["../../../../src/components/Tools/Inbox/requestInboxBadgeRefresh.ts"],"sourcesContent":["/** 站内信角标:外部(业务写成功 / AppShell)触发刷新的事件名 */\nexport const INBOX_BADGE_REFRESH_EVENT = 'marsun-msg-center:refresh-badge';\n\n/** 业务写后可附带预览,铃铛在 SSE 未达时仍可弹 toast */\nexport type InboxBadgeRefreshDetail = {\n preview?: {\n messageType?: string;\n title?: string;\n summary?: string;\n } | null;\n};\n\n/**\n * 请求刷新 InboxBell 未读角标(window CustomEvent)。\n * 铃铛未挂载时无副作用;挂载实例会监听并 refreshBadge。\n * `detail.preview` 有值时按偏好弹出站内信 toast(不依赖 SSE)。\n */\nexport function requestInboxBadgeRefresh(detail?: InboxBadgeRefreshDetail): void {\n if (typeof window === 'undefined') return;\n window.dispatchEvent(new CustomEvent(INBOX_BADGE_REFRESH_EVENT, { detail: detail || {} }));\n}\n\n/** 业务写成功后:立即 + 单次延迟补刷(盖 async outbox;非轮询) */\nexport function requestInboxBadgeRefreshAfterWrite(\n delayMs = 1200,\n detail?: InboxBadgeRefreshDetail,\n): void {\n requestInboxBadgeRefresh(detail);\n if (typeof window === 'undefined') return;\n window.setTimeout(() => {\n requestInboxBadgeRefresh();\n }, delayMs);\n}\n"],"names":["INBOX_BADGE_REFRESH_EVENT","requestInboxBadgeRefresh","detail","requestInboxBadgeRefreshAfterWrite","delayMs"],"mappings":"AACO,MAAMA,IAA4B;AAgBlC,SAASC,EAAyBC,GAAwC;AAC/E,EAAI,OAAO,SAAW,OACtB,OAAO,cAAc,IAAI,YAAYF,GAA2B,EAAE,QAAQE,KAAU,CAAA,EAAC,CAAG,CAAC;AAC3F;AAGO,SAASC,EACdC,IAAU,MACVF,GACM;AAEN,EADAD,EAAyBC,CAAM,GAC3B,SAAO,SAAW,QACtB,OAAO,WAAW,MAAM;AACtB,IAAAD,EAAA;AAAA,EACF,GAAGG,CAAO;AACZ;"}
|