@hkyhy/marsun-components-core 0.1.127 → 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 +306 -286
- 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,168 +1,168 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { notification as
|
|
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 { Bell as
|
|
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 s = String(
|
|
32
|
-
return s ?
|
|
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 s = String(
|
|
36
|
-
return s === "alert" ?
|
|
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 [
|
|
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(
|
|
41
|
+
function Ze(u) {
|
|
42
|
+
return String(u || "").trim() || D.DEFAULT;
|
|
43
43
|
}
|
|
44
|
-
function
|
|
44
|
+
function et(u) {
|
|
45
45
|
try {
|
|
46
|
-
const s = JSON.parse(
|
|
46
|
+
const s = JSON.parse(u);
|
|
47
47
|
if (!s || typeof s != "object") return null;
|
|
48
|
-
const
|
|
49
|
-
return !
|
|
50
|
-
messageType:
|
|
51
|
-
title:
|
|
52
|
-
summary:
|
|
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
|
|
58
|
+
const vt = De(function({
|
|
59
59
|
fetchInbox: s,
|
|
60
|
-
markRead:
|
|
61
|
-
onNavigate:
|
|
62
|
-
pollMs:
|
|
63
|
-
locationKey:
|
|
64
|
-
pageSize:
|
|
60
|
+
markRead: M,
|
|
61
|
+
onNavigate: C,
|
|
62
|
+
pollMs: S = 0,
|
|
63
|
+
locationKey: ne,
|
|
64
|
+
pageSize: b = 20,
|
|
65
65
|
className: be,
|
|
66
|
-
title:
|
|
67
|
-
streamPath:
|
|
68
|
-
getAccessToken:
|
|
69
|
-
onItemAction:
|
|
70
|
-
},
|
|
71
|
-
const [
|
|
72
|
-
|
|
73
|
-
const
|
|
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
83
|
const e = await s({
|
|
84
84
|
currentPage: 1,
|
|
85
|
-
pageSize:
|
|
86
|
-
...
|
|
87
|
-
}), t = (e == null ? void 0 : e.pageData) || [],
|
|
88
|
-
A(t),
|
|
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
|
-
A([]),
|
|
90
|
+
A([]), B.current = !1, se(e instanceof Error ? e.message : String(e));
|
|
91
91
|
} finally {
|
|
92
|
-
|
|
92
|
+
oe(!1);
|
|
93
93
|
}
|
|
94
|
-
}, [s,
|
|
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
|
-
A((
|
|
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
|
-
}, [s,
|
|
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 s({ currentPage: 1, pageSize:
|
|
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
|
-
}, [s,
|
|
126
|
-
const e =
|
|
127
|
-
if (
|
|
128
|
-
const t = e.title || "新站内信",
|
|
129
|
-
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
key:
|
|
133
|
-
className:
|
|
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
134
|
closable: !0,
|
|
135
|
-
title: /* @__PURE__ */
|
|
136
|
-
/* @__PURE__ */
|
|
137
|
-
|
|
138
|
-
|
|
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
139
|
{
|
|
140
|
-
color:
|
|
141
|
-
className:
|
|
142
|
-
children:
|
|
140
|
+
color: te(e.messageType),
|
|
141
|
+
className: r.typeTag,
|
|
142
|
+
children: o
|
|
143
143
|
}
|
|
144
144
|
) : null
|
|
145
145
|
] }),
|
|
146
|
-
message: /* @__PURE__ */
|
|
147
|
-
/* @__PURE__ */
|
|
148
|
-
|
|
149
|
-
|
|
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
150
|
{
|
|
151
|
-
color:
|
|
152
|
-
className:
|
|
153
|
-
children:
|
|
151
|
+
color: te(e.messageType),
|
|
152
|
+
className: r.typeTag,
|
|
153
|
+
children: o
|
|
154
154
|
}
|
|
155
155
|
) : null
|
|
156
156
|
] }),
|
|
157
|
-
description: /* @__PURE__ */
|
|
158
|
-
|
|
159
|
-
/* @__PURE__ */
|
|
160
|
-
|
|
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
161
|
{
|
|
162
162
|
type: "primary",
|
|
163
163
|
size: "small",
|
|
164
|
-
onClick: (
|
|
165
|
-
|
|
164
|
+
onClick: (c) => {
|
|
165
|
+
c.stopPropagation(), i();
|
|
166
166
|
},
|
|
167
167
|
children: "查看"
|
|
168
168
|
}
|
|
@@ -170,159 +170,179 @@ const gt = Pe(function({
|
|
|
170
170
|
] }),
|
|
171
171
|
placement: "topRight",
|
|
172
172
|
duration: 6,
|
|
173
|
-
onClick:
|
|
173
|
+
onClick: i
|
|
174
174
|
});
|
|
175
|
-
}, []),
|
|
175
|
+
}, []), h = x(
|
|
176
176
|
(e) => {
|
|
177
|
-
e && (
|
|
178
|
-
|
|
179
|
-
},
|
|
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
180
|
},
|
|
181
|
-
[
|
|
181
|
+
[y, me]
|
|
182
182
|
);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}, [
|
|
186
|
-
if (
|
|
187
|
-
if (!
|
|
188
|
-
|
|
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;
|
|
189
189
|
return;
|
|
190
190
|
}
|
|
191
|
-
|
|
191
|
+
h();
|
|
192
192
|
}
|
|
193
|
-
}, [
|
|
194
|
-
if (
|
|
193
|
+
}, [ne, h]), T(() => {
|
|
194
|
+
if (S <= 0) return;
|
|
195
195
|
const e = window.setInterval(() => {
|
|
196
|
-
|
|
197
|
-
},
|
|
196
|
+
y();
|
|
197
|
+
}, S);
|
|
198
198
|
return () => window.clearInterval(e);
|
|
199
|
-
}, [
|
|
199
|
+
}, [S, y]), T(() => {
|
|
200
200
|
const e = () => {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
},
|
|
201
|
+
w.current != null && window.clearTimeout(w.current), w.current = window.setTimeout(() => {
|
|
202
|
+
w.current = null, h();
|
|
203
|
+
}, Xe);
|
|
204
204
|
}, t = () => {
|
|
205
205
|
document.visibilityState === "visible" && e();
|
|
206
206
|
};
|
|
207
207
|
return window.addEventListener("focus", e), document.addEventListener("visibilitychange", t), () => {
|
|
208
|
-
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);
|
|
209
209
|
};
|
|
210
|
-
}, [
|
|
211
|
-
const e = () => {
|
|
212
|
-
|
|
210
|
+
}, [h]), T(() => {
|
|
211
|
+
const e = (t) => {
|
|
212
|
+
const n = t.detail;
|
|
213
|
+
h((n == null ? void 0 : n.preview) || void 0);
|
|
213
214
|
};
|
|
214
|
-
return window.addEventListener(
|
|
215
|
-
}, [
|
|
216
|
-
|
|
217
|
-
}, []),
|
|
218
|
-
if (
|
|
219
|
-
const e = String(G
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
return;
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
+
};
|
|
232
254
|
};
|
|
233
|
-
return
|
|
234
|
-
|
|
235
|
-
}, () => {
|
|
236
|
-
a.removeEventListener("badge", l), a.removeEventListener("inbox", l), a.close();
|
|
255
|
+
return f(), () => {
|
|
256
|
+
t = !0, c(), n && (n.removeEventListener("badge", l), n.removeEventListener("inbox", l), n.close(), n = null);
|
|
237
257
|
};
|
|
238
|
-
}, [
|
|
239
|
-
|
|
240
|
-
}, [
|
|
241
|
-
const
|
|
242
|
-
() =>
|
|
243
|
-
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;
|
|
244
264
|
return {
|
|
245
265
|
key: e.key || "all",
|
|
246
266
|
label: t > 0 ? `${e.label} (${t})` : e.label
|
|
247
267
|
};
|
|
248
268
|
}),
|
|
249
|
-
[
|
|
250
|
-
),
|
|
251
|
-
|
|
252
|
-
const
|
|
253
|
-
return
|
|
269
|
+
[le, R]
|
|
270
|
+
), q = (e, t) => {
|
|
271
|
+
Le((n) => {
|
|
272
|
+
const o = { ...n, [e]: t };
|
|
273
|
+
return Ue(o), o;
|
|
254
274
|
});
|
|
255
|
-
},
|
|
275
|
+
}, Z = async (e, t) => {
|
|
256
276
|
if (!e.read)
|
|
257
277
|
try {
|
|
258
|
-
await
|
|
259
|
-
} catch (
|
|
260
|
-
|
|
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));
|
|
279
|
+
} catch (o) {
|
|
280
|
+
ge.error(o instanceof Error ? o.message : "标记已读失败");
|
|
261
281
|
return;
|
|
262
282
|
}
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
265
|
-
if (
|
|
266
|
-
|
|
283
|
+
const n = String(e.href || "").trim();
|
|
284
|
+
if (n) {
|
|
285
|
+
if (C) {
|
|
286
|
+
C(n, e), L(!1);
|
|
267
287
|
return;
|
|
268
288
|
}
|
|
269
|
-
|
|
289
|
+
n.startsWith("http://") || n.startsWith("https://") ? window.open(n, "_blank", "noopener,noreferrer") : window.location.assign(n), L(!1);
|
|
270
290
|
}
|
|
271
|
-
},
|
|
291
|
+
}, fe = async (e, t) => {
|
|
272
292
|
if (!t.disabled) {
|
|
273
|
-
if (
|
|
293
|
+
if (re) {
|
|
274
294
|
try {
|
|
275
|
-
await
|
|
276
|
-
} catch (
|
|
277
|
-
|
|
295
|
+
await re(t.kind, e), L(!1), J(), y();
|
|
296
|
+
} catch (n) {
|
|
297
|
+
ge.error(n instanceof Error ? n.message : "操作失败");
|
|
278
298
|
}
|
|
279
299
|
return;
|
|
280
300
|
}
|
|
281
|
-
await
|
|
301
|
+
await Z(e);
|
|
282
302
|
}
|
|
283
303
|
};
|
|
284
|
-
return /* @__PURE__ */
|
|
285
|
-
/* @__PURE__ */
|
|
286
|
-
|
|
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,
|
|
287
307
|
{
|
|
288
308
|
type: "text",
|
|
289
|
-
className:
|
|
290
|
-
icon: /* @__PURE__ */
|
|
291
|
-
"aria-label":
|
|
292
|
-
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)
|
|
293
313
|
}
|
|
294
314
|
) }),
|
|
295
|
-
/* @__PURE__ */
|
|
296
|
-
|
|
315
|
+
/* @__PURE__ */ m(
|
|
316
|
+
Pe,
|
|
297
317
|
{
|
|
298
|
-
title:
|
|
299
|
-
open:
|
|
300
|
-
onClose: () =>
|
|
318
|
+
title: we,
|
|
319
|
+
open: $,
|
|
320
|
+
onClose: () => L(!1),
|
|
301
321
|
size: 420,
|
|
302
322
|
destroyOnClose: !1,
|
|
303
|
-
className:
|
|
323
|
+
className: r.drawer,
|
|
304
324
|
styles: {
|
|
305
325
|
header: { padding: "12px 16px" },
|
|
306
326
|
body: { padding: "12px 16px" }
|
|
307
327
|
},
|
|
308
328
|
children: [
|
|
309
|
-
/* @__PURE__ */
|
|
310
|
-
|
|
329
|
+
/* @__PURE__ */ a(
|
|
330
|
+
Ge,
|
|
311
331
|
{
|
|
312
|
-
className:
|
|
332
|
+
className: r.typeTabs,
|
|
313
333
|
size: "small",
|
|
314
|
-
activeKey:
|
|
315
|
-
onChange: (e) =>
|
|
316
|
-
stateOption:
|
|
334
|
+
activeKey: W || "all",
|
|
335
|
+
onChange: (e) => Ee(e === "all" ? "" : e),
|
|
336
|
+
stateOption: xe,
|
|
317
337
|
isInner: !0
|
|
318
338
|
}
|
|
319
339
|
),
|
|
320
|
-
/* @__PURE__ */
|
|
321
|
-
|
|
340
|
+
/* @__PURE__ */ a("div", { className: r.filterRow, children: /* @__PURE__ */ a(
|
|
341
|
+
Ke,
|
|
322
342
|
{
|
|
323
343
|
size: "small",
|
|
324
|
-
value:
|
|
325
|
-
onChange: (e) =>
|
|
344
|
+
value: O,
|
|
345
|
+
onChange: (e) => Se(e),
|
|
326
346
|
options: [
|
|
327
347
|
{ value: "all", label: "全部" },
|
|
328
348
|
{ value: "unread", label: "未读" },
|
|
@@ -330,117 +350,117 @@ const gt = Pe(function({
|
|
|
330
350
|
]
|
|
331
351
|
}
|
|
332
352
|
) }),
|
|
333
|
-
/* @__PURE__ */
|
|
334
|
-
/* @__PURE__ */
|
|
335
|
-
/* @__PURE__ */
|
|
336
|
-
/* @__PURE__ */
|
|
337
|
-
/* @__PURE__ */
|
|
338
|
-
|
|
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,
|
|
339
359
|
{
|
|
340
360
|
checked: P.alert,
|
|
341
|
-
onChange: (e) =>
|
|
361
|
+
onChange: (e) => q("alert", e.target.checked),
|
|
342
362
|
children: "预警弹出"
|
|
343
363
|
}
|
|
344
364
|
),
|
|
345
|
-
/* @__PURE__ */
|
|
346
|
-
|
|
365
|
+
/* @__PURE__ */ a(
|
|
366
|
+
ee,
|
|
347
367
|
{
|
|
348
368
|
checked: P.action,
|
|
349
|
-
onChange: (e) =>
|
|
369
|
+
onChange: (e) => q("action", e.target.checked),
|
|
350
370
|
children: "行动弹出"
|
|
351
371
|
}
|
|
352
372
|
),
|
|
353
|
-
/* @__PURE__ */
|
|
354
|
-
|
|
373
|
+
/* @__PURE__ */ a(
|
|
374
|
+
ee,
|
|
355
375
|
{
|
|
356
376
|
checked: P.remind,
|
|
357
|
-
onChange: (e) =>
|
|
377
|
+
onChange: (e) => q("remind", e.target.checked),
|
|
358
378
|
children: "提醒弹出"
|
|
359
379
|
}
|
|
360
380
|
)
|
|
361
381
|
] })
|
|
362
382
|
] }),
|
|
363
|
-
|
|
364
|
-
/* @__PURE__ */
|
|
365
|
-
|
|
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,
|
|
366
386
|
{
|
|
367
|
-
wrapperClassName:
|
|
368
|
-
className:
|
|
387
|
+
wrapperClassName: k("inbox-bell-list-scroll", r.listScroll),
|
|
388
|
+
className: r.listViewport,
|
|
369
389
|
"data-testid": "inbox-bell-list-scroll",
|
|
370
|
-
onScroll:
|
|
390
|
+
onScroll: ke,
|
|
371
391
|
children: [
|
|
372
|
-
/* @__PURE__ */
|
|
373
|
-
const t =
|
|
374
|
-
|
|
375
|
-
),
|
|
376
|
-
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(
|
|
377
397
|
"div",
|
|
378
398
|
{
|
|
379
|
-
className:
|
|
380
|
-
|
|
381
|
-
!e.read &&
|
|
382
|
-
|
|
399
|
+
className: k(
|
|
400
|
+
r.item,
|
|
401
|
+
!e.read && r.itemUnread,
|
|
402
|
+
c && r.itemStatic
|
|
383
403
|
),
|
|
384
|
-
role:
|
|
385
|
-
tabIndex:
|
|
386
|
-
onClick:
|
|
387
|
-
onKeyDown:
|
|
388
|
-
(
|
|
404
|
+
role: c ? void 0 : "button",
|
|
405
|
+
tabIndex: c ? void 0 : 0,
|
|
406
|
+
onClick: c ? void 0 : () => void Z(e),
|
|
407
|
+
onKeyDown: c ? void 0 : (d) => {
|
|
408
|
+
(d.key === "Enter" || d.key === " ") && (d.preventDefault(), Z(e));
|
|
389
409
|
},
|
|
390
410
|
children: [
|
|
391
|
-
/* @__PURE__ */
|
|
392
|
-
/* @__PURE__ */
|
|
393
|
-
/* @__PURE__ */
|
|
394
|
-
t ? /* @__PURE__ */
|
|
395
|
-
|
|
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,
|
|
396
416
|
{
|
|
397
|
-
color:
|
|
398
|
-
className:
|
|
417
|
+
color: te(e.messageType),
|
|
418
|
+
className: r.typeTag,
|
|
399
419
|
children: t
|
|
400
420
|
}
|
|
401
421
|
) : null
|
|
402
422
|
] }),
|
|
403
|
-
/* @__PURE__ */
|
|
423
|
+
/* @__PURE__ */ a("span", { className: r.itemTime, children: e.createdAt || "" })
|
|
404
424
|
] }),
|
|
405
|
-
/* @__PURE__ */
|
|
425
|
+
/* @__PURE__ */ a("div", { className: r.itemBody, children: i ? /* @__PURE__ */ a(
|
|
406
426
|
"div",
|
|
407
427
|
{
|
|
408
|
-
className:
|
|
409
|
-
dangerouslySetInnerHTML: { __html:
|
|
428
|
+
className: r.itemBodyHtml,
|
|
429
|
+
dangerouslySetInnerHTML: { __html: i }
|
|
410
430
|
}
|
|
411
|
-
) : e.summary ? /* @__PURE__ */
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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,
|
|
415
435
|
{
|
|
416
|
-
color:
|
|
417
|
-
className:
|
|
418
|
-
children:
|
|
436
|
+
color: Ze(e.levelColor),
|
|
437
|
+
className: r.typeTag,
|
|
438
|
+
children: n
|
|
419
439
|
}
|
|
420
440
|
) }) : null,
|
|
421
|
-
|
|
441
|
+
f && l.primary ? /* @__PURE__ */ a(
|
|
422
442
|
"div",
|
|
423
443
|
{
|
|
424
|
-
className:
|
|
425
|
-
onClick: (
|
|
426
|
-
onKeyDown: (
|
|
427
|
-
children: /* @__PURE__ */
|
|
428
|
-
/* @__PURE__ */
|
|
429
|
-
|
|
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,
|
|
430
450
|
{
|
|
431
451
|
size: "small",
|
|
432
452
|
type: "primary",
|
|
433
|
-
onClick: () => void
|
|
434
|
-
children:
|
|
453
|
+
onClick: () => void fe(e, l.primary),
|
|
454
|
+
children: l.primary.label
|
|
435
455
|
}
|
|
436
456
|
),
|
|
437
|
-
|
|
438
|
-
|
|
457
|
+
l.secondary ? /* @__PURE__ */ a(
|
|
458
|
+
F,
|
|
439
459
|
{
|
|
440
460
|
size: "small",
|
|
441
461
|
type: "link",
|
|
442
|
-
onClick: () => void
|
|
443
|
-
children:
|
|
462
|
+
onClick: () => void fe(e, l.secondary),
|
|
463
|
+
children: l.secondary.label
|
|
444
464
|
}
|
|
445
465
|
) : null
|
|
446
466
|
] })
|
|
@@ -450,7 +470,7 @@ const gt = Pe(function({
|
|
|
450
470
|
}
|
|
451
471
|
) }, e.id);
|
|
452
472
|
}) }),
|
|
453
|
-
|
|
473
|
+
Be ? /* @__PURE__ */ a("p", { className: k("inbox-bell-list-footer", r.listFooter), children: "加载中…" }) : null
|
|
454
474
|
]
|
|
455
475
|
}
|
|
456
476
|
) }) })
|
|
@@ -460,17 +480,17 @@ const gt = Pe(function({
|
|
|
460
480
|
] });
|
|
461
481
|
});
|
|
462
482
|
export {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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
|
|
475
495
|
};
|
|
476
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/** 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 扫描风暴 / 写后 / 路由 / 焦点);命令式 refreshBadge 仍立即执行 */\n const scheduleBadgeRefresh = useCallback(\n (preview?: BadgePreview | null) => {\n if (preview) pendingToastRef.current = preview;\n if (badgeDebounceRef.current != null) {\n window.clearTimeout(badgeDebounceRef.current);\n }\n badgeDebounceRef.current = window.setTimeout(() => {\n badgeDebounceRef.current = null;\n void refreshBadge();\n flushPendingToast();\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 = () => {\n scheduleBadgeRefresh();\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 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 const msgEv = ev as MessageEvent;\n const preview = typeof msgEv?.data === 'string' ? parseBadgePreview(msgEv.data) : null;\n scheduleBadgeRefresh(preview);\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, 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","INBOX_BADGE_REFRESH_EVENT","token","base","url","es","onBadge","ev","msgEv","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;"}
|