@hkyhy/marsun-components-core 0.1.131 → 0.1.133

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.
Files changed (87) hide show
  1. package/README.md +2 -0
  2. package/dist/_virtual/index.js +5 -5
  3. package/dist/_virtual/index2.js +5 -5
  4. package/dist/_virtual/index3.js +2 -2
  5. package/dist/_virtual/index4.js +5 -2
  6. package/dist/_virtual/index4.js.map +1 -1
  7. package/dist/_virtual/index5.js +2 -5
  8. package/dist/_virtual/index5.js.map +1 -1
  9. package/dist/_virtual/index6.js +2 -2
  10. package/dist/_virtual/index7.js +2 -2
  11. package/dist/components/Disposition/DispositionBar/formatDispositionStatusBadge.d.ts +22 -0
  12. package/dist/components/Disposition/DispositionBar/formatDispositionStatusBadge.js +14 -0
  13. package/dist/components/Disposition/DispositionBar/formatDispositionStatusBadge.js.map +1 -0
  14. package/dist/components/Disposition/DispositionBar/index.js +6 -6
  15. package/dist/components/Disposition/DispositionBar/index.js.map +1 -1
  16. package/dist/components/Disposition/DispositionBar/style.module.scss.js +6 -6
  17. package/dist/components/Disposition/index.d.ts +2 -0
  18. package/dist/components/Tools/ActionTracking/List/ActionListTable.module.scss.js +4 -4
  19. package/dist/components/Tools/ActionTracking/List/listTypes.d.ts +5 -0
  20. package/dist/components/Tools/ActionTracking/index.d.ts +2 -1
  21. package/dist/components/Tools/ActionTracking/utils/actionExecuteGate.d.ts +18 -0
  22. package/dist/components/Tools/ActionTracking/utils/actionExecuteGate.js +11 -0
  23. package/dist/components/Tools/ActionTracking/utils/actionExecuteGate.js.map +1 -0
  24. package/dist/components/Tools/ActionTracking/utils/index.d.ts +2 -0
  25. package/dist/components/Tools/Inbox/InboxBell/style.module.scss.js +56 -56
  26. package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/List/columns.d.ts +5 -0
  27. package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/List/columns.js +25 -12
  28. package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/List/columns.js.map +1 -1
  29. package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/Modal/TemplateFormModal.js +82 -78
  30. package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/Modal/TemplateFormModal.js.map +1 -1
  31. package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/types.d.ts +5 -0
  32. package/dist/components/Tools/MessageCenter/MessageTemplateAdmin/types.js.map +1 -1
  33. package/dist/components/Tools/index.d.ts +2 -2
  34. package/dist/components/index.d.ts +2 -2
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.js +210 -206
  37. package/dist/index.js.map +1 -1
  38. package/dist/marsun-components-core.css +1 -1
  39. package/dist/node_modules/@ant-design/charts-util/es/react/render.js +27 -27
  40. package/dist/node_modules/@ant-design/charts-util/es/react/render.js.map +1 -1
  41. package/dist/node_modules/@antv/component/node_modules/@antv/scale/esm/utils/color.js +1 -1
  42. package/dist/node_modules/@antv/coord/node_modules/@antv/scale/esm/utils/color.js +1 -1
  43. package/dist/node_modules/@antv/g-lite/dist/index.esm.js +1 -1
  44. package/dist/node_modules/@antv/g2/esm/data/kde.js +1 -1
  45. package/dist/node_modules/@antv/g6-extension-react/esm/react-node/render18.js +19 -19
  46. package/dist/node_modules/@antv/g6-extension-react/esm/react-node/render18.js.map +1 -1
  47. package/dist/node_modules/@antv/scale/esm/utils/color.js +1 -1
  48. package/dist/node_modules/color-string/index.js +1 -1
  49. package/dist/node_modules/eventemitter3/index.js +1 -1
  50. package/dist/node_modules/eventemitter3/index2.js +1 -1
  51. package/dist/node_modules/pdfast/src/index.js +1 -1
  52. package/dist/node_modules/simple-swizzle/index.js +1 -1
  53. package/dist/styles/global.css +1 -1
  54. package/dist/utils/ensureDayjsZhCn.js +1 -1
  55. package/package.json +1 -1
  56. package/dist/_virtual/client.js +0 -28
  57. package/dist/_virtual/client.js.map +0 -1
  58. package/dist/_virtual/client2.js +0 -5
  59. package/dist/_virtual/client2.js.map +0 -1
  60. package/dist/_virtual/index8.js +0 -5
  61. package/dist/_virtual/index8.js.map +0 -1
  62. package/dist/_virtual/react-dom-client.development.js +0 -5
  63. package/dist/_virtual/react-dom-client.development.js.map +0 -1
  64. package/dist/_virtual/react-dom-client.production.js +0 -5
  65. package/dist/_virtual/react-dom-client.production.js.map +0 -1
  66. package/dist/_virtual/scheduler.development.js +0 -5
  67. package/dist/_virtual/scheduler.development.js.map +0 -1
  68. package/dist/_virtual/scheduler.production.js +0 -5
  69. package/dist/_virtual/scheduler.production.js.map +0 -1
  70. package/dist/_virtual/zh-cn.js +0 -3
  71. package/dist/_virtual/zh-cn.js.map +0 -1
  72. package/dist/_virtual/zh-cn2.js +0 -5
  73. package/dist/_virtual/zh-cn2.js.map +0 -1
  74. package/dist/node_modules/dayjs/locale/zh-cn.js +0 -25
  75. package/dist/node_modules/dayjs/locale/zh-cn.js.map +0 -1
  76. package/dist/node_modules/react-dom/cjs/react-dom-client.development.js +0 -17062
  77. package/dist/node_modules/react-dom/cjs/react-dom-client.development.js.map +0 -1
  78. package/dist/node_modules/react-dom/cjs/react-dom-client.production.js +0 -9790
  79. package/dist/node_modules/react-dom/cjs/react-dom-client.production.js.map +0 -1
  80. package/dist/node_modules/react-dom/client.js +0 -24
  81. package/dist/node_modules/react-dom/client.js.map +0 -1
  82. package/dist/node_modules/scheduler/cjs/scheduler.development.js +0 -237
  83. package/dist/node_modules/scheduler/cjs/scheduler.development.js.map +0 -1
  84. package/dist/node_modules/scheduler/cjs/scheduler.production.js +0 -234
  85. package/dist/node_modules/scheduler/cjs/scheduler.production.js.map +0 -1
  86. package/dist/node_modules/scheduler/index.js +0 -11
  87. package/dist/node_modules/scheduler/index.js.map +0 -1
@@ -1,46 +1,47 @@
1
- import { jsx as t, jsxs as y } from "react/jsx-runtime";
2
- import { RichTextField as q } from "../../../../FormInfo/RichTextField/index.js";
3
- import { ensureRichTextBlockHtml as L, unwrapMsgVarSpansForStorage as G } from "../../../../Editor/variableMention.js";
4
- import { sanitizeInboxHtml as U } from "../../../Inbox/sanitizeInboxHtml.js";
5
- import { normalizeTemplatePlaceholders as b, applyTemplateVars as O } from "../../utils/templateCode.js";
6
- import { message as T, Modal as J, Typography as D, Collapse as X } from "antd";
7
- import { useState as A, useRef as Y, useEffect as Z, useMemo as P, useCallback as i } from "react";
8
- import { AUDIENCE_SLOT_OPTIONS as W, normalizeAudienceSlots as ee, hasAudienceSelection as oe, ORG_TENANT_SLOT as le } from "../audienceSlots.js";
1
+ import { jsx as t, jsxs as p } from "react/jsx-runtime";
2
+ import { RichTextField as G } from "../../../../FormInfo/RichTextField/index.js";
3
+ import { ensureRichTextBlockHtml as O, unwrapMsgVarSpansForStorage as U } from "../../../../Editor/variableMention.js";
4
+ import { sanitizeInboxHtml as J } from "../../../Inbox/sanitizeInboxHtml.js";
5
+ import { normalizeTemplatePlaceholders as b, applyTemplateVars as D } from "../../utils/templateCode.js";
6
+ import { message as T, Modal as X, Typography as A, Collapse as Y, Space as Z, Tag as i } from "antd";
7
+ import { useState as V, useRef as W, useEffect as ee, useMemo as I, useCallback as oe } from "react";
8
+ import { AUDIENCE_SLOT_OPTIONS as le, normalizeAudienceSlots as te, hasAudienceSelection as se, ORG_TENANT_SLOT as re } from "../audienceSlots.js";
9
+ import { templateSourceTag as ne } from "../List/columns.js";
9
10
  import s from "../style.module.scss.js";
10
- import { Input as V, Select as I } from "../../../../FormInfo/fields.js";
11
- import te from "../../../../FormInfo/FormModal.js";
12
- import se from "../../../../FormInfo/FormInfo.js";
13
- import re from "../../../../FormInfo/FormItem.js";
14
- const C = {
11
+ import { Input as $, Select as C } from "../../../../FormInfo/fields.js";
12
+ import ae from "../../../../FormInfo/FormModal.js";
13
+ import me from "../../../../FormInfo/FormInfo.js";
14
+ import ce from "../../../../FormInfo/FormItem.js";
15
+ const K = {
15
16
  getPopupContainer: () => document.body,
16
17
  styles: { popup: { root: { zIndex: 2e3 } } }
17
- }, ve = ({
18
+ }, Ne = ({
18
19
  open: S,
19
20
  isCreate: n,
20
21
  initial: e,
21
- catalog: p,
22
+ catalog: u,
22
23
  roleOptions: R,
23
24
  variables: h,
24
- catalogError: u,
25
- previewVars: K,
25
+ catalogError: f,
26
+ previewVars: F,
26
27
  canWrite: r,
27
28
  onCancel: x,
28
- onSubmit: F,
29
+ onSubmit: M,
29
30
  renderAudienceField: a
30
31
  }) => {
31
- const [N, M] = A([]), [E, g] = A(!1), v = Y("");
32
- Z(() => {
32
+ const [N, E] = V([]), [H, g] = V(!1), v = W("");
33
+ ee(() => {
33
34
  if (!S || !e) {
34
35
  g(!1), v.current = "";
35
36
  return;
36
37
  }
37
- M(e.audienceRoles || e.roles || []), v.current = L(
38
+ E(e.audienceRoles || e.roles || []), v.current = O(
38
39
  b(e.bodyTemplate || "")
39
40
  );
40
41
  const o = window.requestAnimationFrame(() => g(!0));
41
42
  return () => window.cancelAnimationFrame(o);
42
43
  }, [S, e]);
43
- const H = (e == null ? void 0 : e.id) || (e == null ? void 0 : e.code) || (n ? "create" : "edit"), k = P(() => e ? {
44
+ const z = (e == null ? void 0 : e.id) || (e == null ? void 0 : e.code) || (n ? "create" : "edit"), k = I(() => e ? {
44
45
  code: e.code,
45
46
  eventKey: e.eventKey,
46
47
  scenario: e.scenario || e.label || "",
@@ -48,35 +49,35 @@ const C = {
48
49
  e.titleTemplate || e.titlePreview || ""
49
50
  ),
50
51
  // seed/库内常为无 <p> 纯文本;先块级化,避免 RTE setData 丢正文
51
- bodyTemplate: L(
52
+ bodyTemplate: O(
52
53
  b(e.bodyTemplate || "")
53
54
  ),
54
55
  audienceRoles: e.audienceRoles || e.roles || [],
55
56
  audienceSlots: e.audienceSlots || []
56
- } : {}, [e]), _ = u ? `目录加载失败,无法插入变量(${u})` : h.length === 0 ? "暂无 catalog 变量" : "", $ = i((o) => {
57
+ } : {}, [e]), _ = f ? `目录加载失败,无法插入变量(${f})` : h.length === 0 ? "暂无 catalog 变量" : "", j = oe((o) => {
57
58
  g(!!o);
58
- }, []), j = P(() => {
59
+ }, []), Q = I(() => {
59
60
  const o = [];
60
- return n || o.push(/* @__PURE__ */ t(V, { name: "code", label: "编号", disabled: !0 }, "code")), o.push(
61
+ return n || o.push(/* @__PURE__ */ t($, { name: "code", label: "编号", disabled: !0 }, "code")), o.push(
61
62
  /* @__PURE__ */ t(
62
- I,
63
+ C,
63
64
  {
64
65
  name: "eventKey",
65
66
  label: "适用场景",
66
67
  rule: "REQ",
67
68
  disabled: !r,
68
69
  optionLabelProp: "label",
69
- options: p.map((l) => ({
70
+ options: u.map((l) => ({
70
71
  value: l.eventKey,
71
72
  label: l.label || l.eventKey
72
73
  })),
73
- placeholder: p.length ? "选择场景" : "暂无事件目录",
74
- ...C
74
+ placeholder: u.length ? "选择场景" : "暂无事件目录",
75
+ ...K
75
76
  },
76
77
  "eventKey"
77
78
  ),
78
79
  /* @__PURE__ */ t(
79
- V,
80
+ $,
80
81
  {
81
82
  name: "titleTemplate",
82
83
  label: "标题模板",
@@ -84,22 +85,22 @@ const C = {
84
85
  disabled: !r,
85
86
  enableVariableMention: !0,
86
87
  variables: h,
87
- catalogError: u,
88
+ catalogError: f,
88
89
  placeholder: "点「插入变量」选择 catalog 变量",
89
90
  labelTips: n ? "新建默认停用。标题:点「插入变量」插入明文 {{key}}(可手改)。正文:原子色块,不可改字,整颗删除。" : "标题可手改 {{key}};正文为原子色块(不可改字、Backspace 整颗删)。"
90
91
  },
91
92
  "titleTemplate"
92
93
  ),
93
94
  /* @__PURE__ */ t(
94
- q,
95
+ G,
95
96
  {
96
97
  name: "bodyTemplate",
97
98
  label: "正文模板",
98
99
  disabled: !r,
99
100
  enableVariableMention: !0,
100
101
  variables: h,
101
- catalogError: u,
102
- editorKey: H,
102
+ catalogError: f,
103
+ editorKey: z,
103
104
  placeholder: "编辑正文,点「插入变量」",
104
105
  minHeight: 160,
105
106
  onEditorHtml: (l) => {
@@ -110,7 +111,7 @@ const C = {
110
111
  )
111
112
  ), a || o.push(
112
113
  /* @__PURE__ */ t(
113
- I,
114
+ C,
114
115
  {
115
116
  name: "audienceRoles",
116
117
  label: "受众角色",
@@ -126,19 +127,19 @@ const C = {
126
127
  placeholder: R.length ? "下拉选择角色(可多选)" : "暂无角色数据",
127
128
  notFoundContent: "暂无角色",
128
129
  labelTips: "可与「通知范围」并存;至少选角色或槽位之一。emit 与显式 userIds 并集送达。",
129
- ...C
130
+ ...K
130
131
  },
131
132
  "audienceRoles"
132
133
  ),
133
134
  /* @__PURE__ */ t(
134
- I,
135
+ C,
135
136
  {
136
137
  name: "audienceSlots",
137
138
  label: "通知范围",
138
139
  mode: "multiple",
139
140
  allowClear: !0,
140
141
  disabled: !r,
141
- options: W.map((l) => ({
142
+ options: le.map((l) => ({
142
143
  value: l.value,
143
144
  label: l.label
144
145
  })),
@@ -147,22 +148,22 @@ const C = {
147
148
  placeholder: "可选:本人/领导/部门/分厂/租户或任务当事人",
148
149
  notFoundContent: "暂无槽位",
149
150
  labelTips: "依赖业务 emit.audienceContext;无上下文的槽不会发出。选「本租户」保存前会确认。",
150
- ...C
151
+ ...K
151
152
  },
152
153
  "audienceSlots"
153
154
  )
154
155
  ), o;
155
156
  }, [
156
- E,
157
+ H,
157
158
  n,
158
159
  r,
159
- p,
160
- h,
161
- H,
162
160
  u,
161
+ h,
162
+ z,
163
+ f,
163
164
  a,
164
165
  R
165
- ]), Q = P(
166
+ ]), q = I(
166
167
  () => ({
167
168
  data: k,
168
169
  onSubmit: async (o) => {
@@ -174,41 +175,41 @@ const C = {
174
175
  const w = b(String(o.titleTemplate || ""));
175
176
  if (!w.trim())
176
177
  return T.warning("请填写标题模板"), !1;
177
- const f = a ? N : Array.isArray(o.audienceRoles) ? o.audienceRoles : [], m = ee(o.audienceSlots || []);
178
- if (!oe({
179
- roles: f,
178
+ const y = a ? N : Array.isArray(o.audienceRoles) ? o.audienceRoles : [], m = te(o.audienceSlots || []);
179
+ if (!se({
180
+ roles: y,
180
181
  slots: m,
181
182
  userIds: null
182
183
  }))
183
184
  return T.warning("请选择受众角色或通知范围(至少一个)"), !1;
184
- if (m.includes(le) && !await new Promise((B) => {
185
- J.confirm({
185
+ if (m.includes(re) && !await new Promise((L) => {
186
+ X.confirm({
186
187
  title: "确认通知本租户全员?",
187
188
  content: "已选「本租户(全公司)」:将向当前租户内用户展开(≠跨租户)。确认保存?",
188
189
  okText: "确认保存",
189
190
  cancelText: "取消",
190
- onOk: () => B(!0),
191
- onCancel: () => B(!1)
191
+ onOk: () => L(!0),
192
+ onCancel: () => L(!1)
192
193
  });
193
194
  }))
194
195
  return !1;
195
- const c = p.find((d) => d.eventKey === l), z = String((c == null ? void 0 : c.label) || o.scenario || l).trim();
196
+ const c = u.find((d) => d.eventKey === l), B = String((c == null ? void 0 : c.label) || o.scenario || l).trim();
196
197
  try {
197
- await F({
198
+ await M({
198
199
  ...e || {},
199
200
  code: o.code || (e == null ? void 0 : e.code),
200
201
  eventKey: l,
201
- scenario: z,
202
- label: z,
202
+ scenario: B,
203
+ label: B,
203
204
  messageType: (c == null ? void 0 : c.messageType) || (e == null ? void 0 : e.messageType) || "alert",
204
205
  titleTemplate: w,
205
- bodyTemplate: G(
206
+ bodyTemplate: U(
206
207
  b(
207
208
  String(v.current || o.bodyTemplate || "")
208
209
  )
209
210
  ),
210
- audienceRoles: f,
211
- roles: f,
211
+ audienceRoles: y,
212
+ roles: y,
212
213
  audienceSlots: m,
213
214
  enabled: n ? !1 : (e == null ? void 0 : e.enabled) !== !1,
214
215
  channel: (e == null ? void 0 : e.channel) || "in_app"
@@ -221,19 +222,22 @@ const C = {
221
222
  [
222
223
  k,
223
224
  r,
224
- p,
225
- F,
225
+ u,
226
+ M,
226
227
  e,
227
228
  N,
228
229
  n,
229
230
  x,
230
231
  a
231
232
  ]
232
- );
233
- return /* @__PURE__ */ y(
234
- te,
233
+ ), P = !n && e ? ne(e) : null;
234
+ return /* @__PURE__ */ p(
235
+ ae,
235
236
  {
236
- title: n ? "新建模板" : "编辑模板",
237
+ title: P ? /* @__PURE__ */ p(Z, { size: 8, children: [
238
+ /* @__PURE__ */ t("span", { children: "编辑模板" }),
239
+ /* @__PURE__ */ t(i, { color: P.color, children: P.label })
240
+ ] }) : "新建模板",
237
241
  open: S,
238
242
  onCancel: x,
239
243
  width: 720,
@@ -242,23 +246,23 @@ const C = {
242
246
  okText: "保存",
243
247
  autoClose: !1,
244
248
  focusable: { trap: !1 },
245
- afterOpenChange: $,
246
- formProps: Q,
249
+ afterOpenChange: j,
250
+ formProps: q,
247
251
  children: [
248
- /* @__PURE__ */ t(se, { column: 1, list: j }),
249
- a ? /* @__PURE__ */ y("div", { className: s.audienceBlock, children: [
250
- /* @__PURE__ */ y(D.Text, { className: s.audienceLabel, children: [
252
+ /* @__PURE__ */ t(me, { column: 1, list: Q }),
253
+ a ? /* @__PURE__ */ p("div", { className: s.audienceBlock, children: [
254
+ /* @__PURE__ */ p(A.Text, { className: s.audienceLabel, children: [
251
255
  /* @__PURE__ */ t("span", { style: { color: "#ff4d4f", marginRight: 4 }, children: "*" }),
252
256
  "受众角色"
253
257
  ] }),
254
- a({ roles: N, onChange: M })
258
+ a({ roles: N, onChange: E })
255
259
  ] }) : null,
256
- E ? /* @__PURE__ */ t(re, { children: (o) => {
257
- const l = (typeof o.getFormData == "function" ? o.getFormData() : void 0) ?? o.formData ?? k, w = O(String(l.titleTemplate || ""), K), f = O(String(l.bodyTemplate || ""), K), m = U(f);
258
- return /* @__PURE__ */ y("div", { className: s.previewCollapse, children: [
259
- _ ? /* @__PURE__ */ t(D.Text, { type: "secondary", children: _ }) : null,
260
+ H ? /* @__PURE__ */ t(ce, { children: (o) => {
261
+ const l = (typeof o.getFormData == "function" ? o.getFormData() : void 0) ?? o.formData ?? k, w = D(String(l.titleTemplate || ""), F), y = D(String(l.bodyTemplate || ""), F), m = J(y);
262
+ return /* @__PURE__ */ p("div", { className: s.previewCollapse, children: [
263
+ _ ? /* @__PURE__ */ t(A.Text, { type: "secondary", children: _ }) : null,
260
264
  /* @__PURE__ */ t(
261
- X,
265
+ Y,
262
266
  {
263
267
  ghost: !0,
264
268
  size: "small",
@@ -266,7 +270,7 @@ const C = {
266
270
  {
267
271
  key: "preview",
268
272
  label: "效果预览",
269
- children: /* @__PURE__ */ y("div", { className: s.previewCard, children: [
273
+ children: /* @__PURE__ */ p("div", { className: s.previewCard, children: [
270
274
  /* @__PURE__ */ t("div", { className: s.previewTitle, children: w.trim() || /* @__PURE__ */ t("span", { className: s.previewEmpty, children: "(无标题)" }) }),
271
275
  m ? /* @__PURE__ */ t(
272
276
  "div",
@@ -287,6 +291,6 @@ const C = {
287
291
  );
288
292
  };
289
293
  export {
290
- ve as TemplateFormModal
294
+ Ne as TemplateFormModal
291
295
  };
292
296
  //# sourceMappingURL=TemplateFormModal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateFormModal.js","sources":["../../../../../../src/components/Tools/MessageCenter/MessageTemplateAdmin/Modal/TemplateFormModal.tsx"],"sourcesContent":["import { FormInfo, FormItem, FormModal, Input, Select } from '@/components/FormInfo';\nimport { RichTextField } from '@/components/FormInfo/RichTextField';\nimport {\n ensureRichTextBlockHtml,\n unwrapMsgVarSpansForStorage,\n} from '@/components/Editor/variableMention';\nimport { sanitizeInboxHtml } from '@/components/Tools/Inbox/sanitizeInboxHtml';\nimport { applyTemplateVars, normalizeTemplatePlaceholders } from '../../utils/templateCode';\nimport { Collapse, Modal, Typography, message } from 'antd';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n MessageAudienceRoleOption,\n MessageEventCatalogItem,\n MessageTemplateAdminItem,\n MessageTemplateVariable,\n} from '../types';\nimport {\n AUDIENCE_SLOT_OPTIONS,\n ORG_TENANT_SLOT,\n hasAudienceSelection,\n normalizeAudienceSlots,\n} from '../audienceSlots';\nimport styles from '../style.module.scss';\n\n/** ReactModal 内 Select 弹出层须高于 Modal(≈1100) */\nconst selectInModalPopupProps = {\n getPopupContainer: () => document.body,\n styles: { popup: { root: { zIndex: 2000 } } },\n} as const;\n\nexport type TemplateFormModalProps = {\n open: boolean;\n isCreate: boolean;\n initial: MessageTemplateAdminItem | null;\n catalog: MessageEventCatalogItem[];\n roleOptions: MessageAudienceRoleOption[];\n variables: MessageTemplateVariable[];\n /** catalog 请求失败时的短文案(与「变量为空」区分) */\n catalogError?: string;\n previewVars: Record<string, string>;\n canWrite: boolean;\n onCancel: () => void;\n onSubmit: (item: MessageTemplateAdminItem) => Promise<void>;\n renderAudienceField?: (ctx: {\n roles: string[];\n onChange: (roles: string[]) => void;\n }) => React.ReactNode;\n};\n\ntype FormShape = {\n code?: string;\n eventKey?: string;\n scenario?: string;\n titleTemplate?: string;\n bodyTemplate?: string;\n audienceRoles?: string[];\n audienceSlots?: string[];\n};\n\ntype FormApiLike = {\n formData?: FormShape;\n getFormData?: () => FormShape;\n};\n\n/**\n * 模板新建/编辑:FormModal + FormInfo;正文 RichTextField。\n * CKEditor 在 open 后微任务挂载,避免与 Modal focus/动画互抢;禁 mention uplift 死循环。\n */\nexport const TemplateFormModal: React.FC<TemplateFormModalProps> = ({\n open,\n isCreate,\n initial,\n catalog,\n roleOptions,\n variables,\n catalogError,\n previewVars,\n canWrite,\n onCancel,\n onSubmit,\n renderAudienceField,\n}) => {\n /** 仅业务 DI 自定义受众插槽时使用;默认走 FormInfo Select */\n const [roles, setRoles] = useState<string[]>([]);\n const [editorReady, setEditorReady] = useState(false);\n /** 编辑器最新 HTML(优先于 Form data,避免字色/加粗未写入 Form 就点保存) */\n const latestBodyHtmlRef = useRef('');\n\n useEffect(() => {\n if (!open || !initial) {\n setEditorReady(false);\n latestBodyHtmlRef.current = '';\n return;\n }\n setRoles(initial.audienceRoles || initial.roles || []);\n latestBodyHtmlRef.current = ensureRichTextBlockHtml(\n normalizeTemplatePlaceholders(initial.bodyTemplate || ''),\n );\n const id = window.requestAnimationFrame(() => setEditorReady(true));\n return () => window.cancelAnimationFrame(id);\n }, [open, initial]);\n\n const editorKey = initial?.id || initial?.code || (isCreate ? 'create' : 'edit');\n\n const formData = useMemo<FormShape>(() => {\n if (!initial) return {};\n return {\n code: initial.code,\n eventKey: initial.eventKey,\n scenario: initial.scenario || initial.label || '',\n titleTemplate: normalizeTemplatePlaceholders(\n initial.titleTemplate || initial.titlePreview || '',\n ),\n // seed/库内常为无 <p> 纯文本;先块级化,避免 RTE setData 丢正文\n bodyTemplate: ensureRichTextBlockHtml(\n normalizeTemplatePlaceholders(initial.bodyTemplate || ''),\n ),\n audienceRoles: initial.audienceRoles || initial.roles || [],\n audienceSlots: initial.audienceSlots || [],\n };\n }, [initial]);\n\n const varsEmptyHint = catalogError\n ? `目录加载失败,无法插入变量(${catalogError})`\n : variables.length === 0\n ? '暂无 catalog 变量'\n : '';\n\n const handleAfterOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen) setEditorReady(true);\n else setEditorReady(false);\n }, []);\n\n const fieldList = useMemo(() => {\n // 始终登记 bodyTemplate 等字段(勿先只渲染「加载中」——Form 首挂无 name 时 data 回填易丢,\n // 预览仍能读到 store/兜底,编辑区却一直空)。CKEditor 仅用 editorReady 控制挂载。\n const fields: React.ReactNode[] = [];\n if (!isCreate) {\n fields.push(<Input key=\"code\" name=\"code\" label=\"编号\" disabled />);\n }\n fields.push(\n <Select\n key=\"eventKey\"\n name=\"eventKey\"\n label=\"适用场景\"\n rule=\"REQ\"\n disabled={!canWrite}\n optionLabelProp=\"label\"\n options={catalog.map((c) => ({\n value: c.eventKey,\n label: c.label || c.eventKey,\n }))}\n placeholder={catalog.length ? '选择场景' : '暂无事件目录'}\n {...selectInModalPopupProps}\n />,\n <Input\n key=\"titleTemplate\"\n name=\"titleTemplate\"\n label=\"标题模板\"\n rule=\"REQ\"\n disabled={!canWrite}\n enableVariableMention\n variables={variables}\n catalogError={catalogError}\n placeholder=\"点「插入变量」选择 catalog 变量\"\n labelTips={\n isCreate\n ? '新建默认停用。标题:点「插入变量」插入明文 {{key}}(可手改)。正文:原子色块,不可改字,整颗删除。'\n : '标题可手改 {{key}};正文为原子色块(不可改字、Backspace 整颗删)。'\n }\n />,\n <RichTextField\n key=\"bodyTemplate\"\n name=\"bodyTemplate\"\n label=\"正文模板\"\n disabled={!canWrite}\n enableVariableMention\n variables={variables}\n catalogError={catalogError}\n editorKey={editorKey}\n placeholder=\"编辑正文,点「插入变量」\"\n minHeight={160}\n onEditorHtml={(html) => {\n latestBodyHtmlRef.current = html;\n }}\n />,\n );\n if (!renderAudienceField) {\n fields.push(\n <Select\n key=\"audienceRoles\"\n name=\"audienceRoles\"\n label=\"受众角色\"\n mode=\"multiple\"\n allowClear\n disabled={!canWrite}\n options={roleOptions.map((r) => ({\n value: r.code,\n label: r.name || r.code,\n }))}\n optionFilterProp=\"label\"\n maxTagCount=\"responsive\"\n placeholder={roleOptions.length ? '下拉选择角色(可多选)' : '暂无角色数据'}\n notFoundContent=\"暂无角色\"\n labelTips=\"可与「通知范围」并存;至少选角色或槽位之一。emit 与显式 userIds 并集送达。\"\n {...selectInModalPopupProps}\n />,\n <Select\n key=\"audienceSlots\"\n name=\"audienceSlots\"\n label=\"通知范围\"\n mode=\"multiple\"\n allowClear\n disabled={!canWrite}\n options={AUDIENCE_SLOT_OPTIONS.map((o) => ({\n value: o.value,\n label: o.label,\n }))}\n optionFilterProp=\"label\"\n maxTagCount=\"responsive\"\n placeholder=\"可选:本人/领导/部门/分厂/租户或任务当事人\"\n notFoundContent=\"暂无槽位\"\n labelTips=\"依赖业务 emit.audienceContext;无上下文的槽不会发出。选「本租户」保存前会确认。\"\n {...selectInModalPopupProps}\n />,\n );\n }\n return fields;\n }, [\n editorReady,\n isCreate,\n canWrite,\n catalog,\n variables,\n editorKey,\n catalogError,\n renderAudienceField,\n roleOptions,\n ]);\n\n const formProps = useMemo(\n () => ({\n data: formData,\n onSubmit: async (data: FormShape) => {\n if (!canWrite) {\n message.warning('当前为只读(业务未授予写权限)');\n return false;\n }\n const eventKey = String(data.eventKey || '').trim();\n if (!eventKey) {\n message.warning('请选择适用场景');\n return false;\n }\n const titleTemplate = normalizeTemplatePlaceholders(String(data.titleTemplate || ''));\n if (!titleTemplate.trim()) {\n message.warning('请填写标题模板');\n return false;\n }\n const audienceRoles = renderAudienceField\n ? roles\n : Array.isArray(data.audienceRoles)\n ? data.audienceRoles\n : [];\n const audienceSlots = normalizeAudienceSlots(data.audienceSlots || []);\n if (\n !hasAudienceSelection({\n roles: audienceRoles,\n slots: audienceSlots,\n userIds: null,\n })\n ) {\n message.warning('请选择受众角色或通知范围(至少一个)');\n return false;\n }\n if (audienceSlots.includes(ORG_TENANT_SLOT)) {\n const ok = await new Promise<boolean>((resolve) => {\n Modal.confirm({\n title: '确认通知本租户全员?',\n content: '已选「本租户(全公司)」:将向当前租户内用户展开(≠跨租户)。确认保存?',\n okText: '确认保存',\n cancelText: '取消',\n onOk: () => resolve(true),\n onCancel: () => resolve(false),\n });\n });\n if (!ok) return false;\n }\n const hit = catalog.find((c) => c.eventKey === eventKey);\n const scenario = String(hit?.label || data.scenario || eventKey).trim();\n try {\n await onSubmit({\n ...(initial || {}),\n code: data.code || initial?.code,\n eventKey,\n scenario,\n label: scenario,\n messageType: hit?.messageType || initial?.messageType || 'alert',\n titleTemplate,\n bodyTemplate: unwrapMsgVarSpansForStorage(\n normalizeTemplatePlaceholders(\n String(latestBodyHtmlRef.current || data.bodyTemplate || ''),\n ),\n ),\n audienceRoles,\n roles: audienceRoles,\n audienceSlots,\n enabled: isCreate ? false : initial?.enabled !== false,\n channel: initial?.channel || 'in_app',\n });\n onCancel();\n } catch (e) {\n message.error(e instanceof Error ? e.message : String(e));\n return false;\n }\n },\n }),\n [\n formData,\n canWrite,\n catalog,\n onSubmit,\n initial,\n roles,\n isCreate,\n onCancel,\n renderAudienceField,\n ],\n );\n\n return (\n <FormModal\n title={isCreate ? '新建模板' : '编辑模板'}\n open={open}\n onCancel={onCancel}\n width={720}\n size=\"small\"\n className=\"msg-center-form-modal\"\n okText=\"保存\"\n autoClose={false}\n focusable={{ trap: false }}\n afterOpenChange={handleAfterOpenChange}\n formProps={formProps}\n >\n <FormInfo column={1} list={fieldList} />\n {renderAudienceField ? (\n <div className={styles.audienceBlock}>\n <Typography.Text className={styles.audienceLabel}>\n <span style={{ color: '#ff4d4f', marginRight: 4 }}>*</span>\n 受众角色\n </Typography.Text>\n {renderAudienceField({ roles, onChange: setRoles })}\n </div>\n ) : null}\n {editorReady ? (\n <FormItem>\n {(api: FormApiLike) => {\n const data =\n (typeof api.getFormData === 'function' ? api.getFormData() : undefined) ??\n api.formData ??\n formData;\n const titlePreview = applyTemplateVars(String(data.titleTemplate || ''), previewVars);\n const bodyRaw = applyTemplateVars(String(data.bodyTemplate || ''), previewVars);\n const bodyHtml = sanitizeInboxHtml(bodyRaw);\n return (\n <div className={styles.previewCollapse}>\n {varsEmptyHint ? (\n <Typography.Text type=\"secondary\">{varsEmptyHint}</Typography.Text>\n ) : null}\n <Collapse\n ghost\n size=\"small\"\n items={[\n {\n key: 'preview',\n label: '效果预览',\n children: (\n <div className={styles.previewCard}>\n <div className={styles.previewTitle}>\n {titlePreview.trim() || (\n <span className={styles.previewEmpty}>(无标题)</span>\n )}\n </div>\n {bodyHtml ? (\n <div\n className={styles.previewBody}\n dangerouslySetInnerHTML={{ __html: bodyHtml }}\n />\n ) : (\n <div className={`${styles.previewBody} ${styles.previewEmpty}`}>\n (无正文)\n </div>\n )}\n </div>\n ),\n },\n ]}\n />\n </div>\n );\n }}\n </FormItem>\n ) : null}\n </FormModal>\n );\n};\n\nexport default TemplateFormModal;\n"],"names":["selectInModalPopupProps","TemplateFormModal","open","isCreate","initial","catalog","roleOptions","variables","catalogError","previewVars","canWrite","onCancel","onSubmit","renderAudienceField","roles","setRoles","useState","editorReady","setEditorReady","latestBodyHtmlRef","useRef","useEffect","ensureRichTextBlockHtml","normalizeTemplatePlaceholders","id","editorKey","formData","useMemo","varsEmptyHint","handleAfterOpenChange","useCallback","nextOpen","fieldList","fields","jsx","Input","Select","c","RichTextField","html","r","AUDIENCE_SLOT_OPTIONS","o","formProps","data","message","eventKey","titleTemplate","audienceRoles","audienceSlots","normalizeAudienceSlots","hasAudienceSelection","ORG_TENANT_SLOT","resolve","Modal","hit","scenario","unwrapMsgVarSpansForStorage","e","jsxs","FormModal","FormInfo","styles","Typography","FormItem","api","titlePreview","applyTemplateVars","bodyRaw","bodyHtml","sanitizeInboxHtml","Collapse"],"mappings":"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"}
1
+ {"version":3,"file":"TemplateFormModal.js","sources":["../../../../../../src/components/Tools/MessageCenter/MessageTemplateAdmin/Modal/TemplateFormModal.tsx"],"sourcesContent":["import { FormInfo, FormItem, FormModal, Input, Select } from '@/components/FormInfo';\nimport { RichTextField } from '@/components/FormInfo/RichTextField';\nimport {\n ensureRichTextBlockHtml,\n unwrapMsgVarSpansForStorage,\n} from '@/components/Editor/variableMention';\nimport { sanitizeInboxHtml } from '@/components/Tools/Inbox/sanitizeInboxHtml';\nimport { applyTemplateVars, normalizeTemplatePlaceholders } from '../../utils/templateCode';\nimport { Collapse, Modal, Space, Tag, Typography, message } from 'antd';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n MessageAudienceRoleOption,\n MessageEventCatalogItem,\n MessageTemplateAdminItem,\n MessageTemplateVariable,\n} from '../types';\nimport {\n AUDIENCE_SLOT_OPTIONS,\n ORG_TENANT_SLOT,\n hasAudienceSelection,\n normalizeAudienceSlots,\n} from '../audienceSlots';\nimport { templateSourceTag } from '../List/columns';\nimport styles from '../style.module.scss';\n\n/** ReactModal 内 Select 弹出层须高于 Modal(≈1100) */\nconst selectInModalPopupProps = {\n getPopupContainer: () => document.body,\n styles: { popup: { root: { zIndex: 2000 } } },\n} as const;\n\nexport type TemplateFormModalProps = {\n open: boolean;\n isCreate: boolean;\n initial: MessageTemplateAdminItem | null;\n catalog: MessageEventCatalogItem[];\n roleOptions: MessageAudienceRoleOption[];\n variables: MessageTemplateVariable[];\n /** catalog 请求失败时的短文案(与「变量为空」区分) */\n catalogError?: string;\n previewVars: Record<string, string>;\n canWrite: boolean;\n onCancel: () => void;\n onSubmit: (item: MessageTemplateAdminItem) => Promise<void>;\n renderAudienceField?: (ctx: {\n roles: string[];\n onChange: (roles: string[]) => void;\n }) => React.ReactNode;\n};\n\ntype FormShape = {\n code?: string;\n eventKey?: string;\n scenario?: string;\n titleTemplate?: string;\n bodyTemplate?: string;\n audienceRoles?: string[];\n audienceSlots?: string[];\n};\n\ntype FormApiLike = {\n formData?: FormShape;\n getFormData?: () => FormShape;\n};\n\n/**\n * 模板新建/编辑:FormModal + FormInfo;正文 RichTextField。\n * CKEditor 在 open 后微任务挂载,避免与 Modal focus/动画互抢;禁 mention uplift 死循环。\n */\nexport const TemplateFormModal: React.FC<TemplateFormModalProps> = ({\n open,\n isCreate,\n initial,\n catalog,\n roleOptions,\n variables,\n catalogError,\n previewVars,\n canWrite,\n onCancel,\n onSubmit,\n renderAudienceField,\n}) => {\n /** 仅业务 DI 自定义受众插槽时使用;默认走 FormInfo Select */\n const [roles, setRoles] = useState<string[]>([]);\n const [editorReady, setEditorReady] = useState(false);\n /** 编辑器最新 HTML(优先于 Form data,避免字色/加粗未写入 Form 就点保存) */\n const latestBodyHtmlRef = useRef('');\n\n useEffect(() => {\n if (!open || !initial) {\n setEditorReady(false);\n latestBodyHtmlRef.current = '';\n return;\n }\n setRoles(initial.audienceRoles || initial.roles || []);\n latestBodyHtmlRef.current = ensureRichTextBlockHtml(\n normalizeTemplatePlaceholders(initial.bodyTemplate || ''),\n );\n const id = window.requestAnimationFrame(() => setEditorReady(true));\n return () => window.cancelAnimationFrame(id);\n }, [open, initial]);\n\n const editorKey = initial?.id || initial?.code || (isCreate ? 'create' : 'edit');\n\n const formData = useMemo<FormShape>(() => {\n if (!initial) return {};\n return {\n code: initial.code,\n eventKey: initial.eventKey,\n scenario: initial.scenario || initial.label || '',\n titleTemplate: normalizeTemplatePlaceholders(\n initial.titleTemplate || initial.titlePreview || '',\n ),\n // seed/库内常为无 <p> 纯文本;先块级化,避免 RTE setData 丢正文\n bodyTemplate: ensureRichTextBlockHtml(\n normalizeTemplatePlaceholders(initial.bodyTemplate || ''),\n ),\n audienceRoles: initial.audienceRoles || initial.roles || [],\n audienceSlots: initial.audienceSlots || [],\n };\n }, [initial]);\n\n const varsEmptyHint = catalogError\n ? `目录加载失败,无法插入变量(${catalogError})`\n : variables.length === 0\n ? '暂无 catalog 变量'\n : '';\n\n const handleAfterOpenChange = useCallback((nextOpen: boolean) => {\n if (nextOpen) setEditorReady(true);\n else setEditorReady(false);\n }, []);\n\n const fieldList = useMemo(() => {\n // 始终登记 bodyTemplate 等字段(勿先只渲染「加载中」——Form 首挂无 name 时 data 回填易丢,\n // 预览仍能读到 store/兜底,编辑区却一直空)。CKEditor 仅用 editorReady 控制挂载。\n const fields: React.ReactNode[] = [];\n if (!isCreate) {\n fields.push(<Input key=\"code\" name=\"code\" label=\"编号\" disabled />);\n }\n fields.push(\n <Select\n key=\"eventKey\"\n name=\"eventKey\"\n label=\"适用场景\"\n rule=\"REQ\"\n disabled={!canWrite}\n optionLabelProp=\"label\"\n options={catalog.map((c) => ({\n value: c.eventKey,\n label: c.label || c.eventKey,\n }))}\n placeholder={catalog.length ? '选择场景' : '暂无事件目录'}\n {...selectInModalPopupProps}\n />,\n <Input\n key=\"titleTemplate\"\n name=\"titleTemplate\"\n label=\"标题模板\"\n rule=\"REQ\"\n disabled={!canWrite}\n enableVariableMention\n variables={variables}\n catalogError={catalogError}\n placeholder=\"点「插入变量」选择 catalog 变量\"\n labelTips={\n isCreate\n ? '新建默认停用。标题:点「插入变量」插入明文 {{key}}(可手改)。正文:原子色块,不可改字,整颗删除。'\n : '标题可手改 {{key}};正文为原子色块(不可改字、Backspace 整颗删)。'\n }\n />,\n <RichTextField\n key=\"bodyTemplate\"\n name=\"bodyTemplate\"\n label=\"正文模板\"\n disabled={!canWrite}\n enableVariableMention\n variables={variables}\n catalogError={catalogError}\n editorKey={editorKey}\n placeholder=\"编辑正文,点「插入变量」\"\n minHeight={160}\n onEditorHtml={(html) => {\n latestBodyHtmlRef.current = html;\n }}\n />,\n );\n if (!renderAudienceField) {\n fields.push(\n <Select\n key=\"audienceRoles\"\n name=\"audienceRoles\"\n label=\"受众角色\"\n mode=\"multiple\"\n allowClear\n disabled={!canWrite}\n options={roleOptions.map((r) => ({\n value: r.code,\n label: r.name || r.code,\n }))}\n optionFilterProp=\"label\"\n maxTagCount=\"responsive\"\n placeholder={roleOptions.length ? '下拉选择角色(可多选)' : '暂无角色数据'}\n notFoundContent=\"暂无角色\"\n labelTips=\"可与「通知范围」并存;至少选角色或槽位之一。emit 与显式 userIds 并集送达。\"\n {...selectInModalPopupProps}\n />,\n <Select\n key=\"audienceSlots\"\n name=\"audienceSlots\"\n label=\"通知范围\"\n mode=\"multiple\"\n allowClear\n disabled={!canWrite}\n options={AUDIENCE_SLOT_OPTIONS.map((o) => ({\n value: o.value,\n label: o.label,\n }))}\n optionFilterProp=\"label\"\n maxTagCount=\"responsive\"\n placeholder=\"可选:本人/领导/部门/分厂/租户或任务当事人\"\n notFoundContent=\"暂无槽位\"\n labelTips=\"依赖业务 emit.audienceContext;无上下文的槽不会发出。选「本租户」保存前会确认。\"\n {...selectInModalPopupProps}\n />,\n );\n }\n return fields;\n }, [\n editorReady,\n isCreate,\n canWrite,\n catalog,\n variables,\n editorKey,\n catalogError,\n renderAudienceField,\n roleOptions,\n ]);\n\n const formProps = useMemo(\n () => ({\n data: formData,\n onSubmit: async (data: FormShape) => {\n if (!canWrite) {\n message.warning('当前为只读(业务未授予写权限)');\n return false;\n }\n const eventKey = String(data.eventKey || '').trim();\n if (!eventKey) {\n message.warning('请选择适用场景');\n return false;\n }\n const titleTemplate = normalizeTemplatePlaceholders(String(data.titleTemplate || ''));\n if (!titleTemplate.trim()) {\n message.warning('请填写标题模板');\n return false;\n }\n const audienceRoles = renderAudienceField\n ? roles\n : Array.isArray(data.audienceRoles)\n ? data.audienceRoles\n : [];\n const audienceSlots = normalizeAudienceSlots(data.audienceSlots || []);\n if (\n !hasAudienceSelection({\n roles: audienceRoles,\n slots: audienceSlots,\n userIds: null,\n })\n ) {\n message.warning('请选择受众角色或通知范围(至少一个)');\n return false;\n }\n if (audienceSlots.includes(ORG_TENANT_SLOT)) {\n const ok = await new Promise<boolean>((resolve) => {\n Modal.confirm({\n title: '确认通知本租户全员?',\n content: '已选「本租户(全公司)」:将向当前租户内用户展开(≠跨租户)。确认保存?',\n okText: '确认保存',\n cancelText: '取消',\n onOk: () => resolve(true),\n onCancel: () => resolve(false),\n });\n });\n if (!ok) return false;\n }\n const hit = catalog.find((c) => c.eventKey === eventKey);\n const scenario = String(hit?.label || data.scenario || eventKey).trim();\n try {\n await onSubmit({\n ...(initial || {}),\n code: data.code || initial?.code,\n eventKey,\n scenario,\n label: scenario,\n messageType: hit?.messageType || initial?.messageType || 'alert',\n titleTemplate,\n bodyTemplate: unwrapMsgVarSpansForStorage(\n normalizeTemplatePlaceholders(\n String(latestBodyHtmlRef.current || data.bodyTemplate || ''),\n ),\n ),\n audienceRoles,\n roles: audienceRoles,\n audienceSlots,\n enabled: isCreate ? false : initial?.enabled !== false,\n channel: initial?.channel || 'in_app',\n });\n onCancel();\n } catch (e) {\n message.error(e instanceof Error ? e.message : String(e));\n return false;\n }\n },\n }),\n [\n formData,\n canWrite,\n catalog,\n onSubmit,\n initial,\n roles,\n isCreate,\n onCancel,\n renderAudienceField,\n ],\n );\n\n const sourceTag = !isCreate && initial ? templateSourceTag(initial) : null;\n\n return (\n <FormModal\n title={\n sourceTag ? (\n <Space size={8}>\n <span>编辑模板</span>\n <Tag color={sourceTag.color}>{sourceTag.label}</Tag>\n </Space>\n ) : (\n '新建模板'\n )\n }\n open={open}\n onCancel={onCancel}\n width={720}\n size=\"small\"\n className=\"msg-center-form-modal\"\n okText=\"保存\"\n autoClose={false}\n focusable={{ trap: false }}\n afterOpenChange={handleAfterOpenChange}\n formProps={formProps}\n >\n <FormInfo column={1} list={fieldList} />\n {renderAudienceField ? (\n <div className={styles.audienceBlock}>\n <Typography.Text className={styles.audienceLabel}>\n <span style={{ color: '#ff4d4f', marginRight: 4 }}>*</span>\n 受众角色\n </Typography.Text>\n {renderAudienceField({ roles, onChange: setRoles })}\n </div>\n ) : null}\n {editorReady ? (\n <FormItem>\n {(api: FormApiLike) => {\n const data =\n (typeof api.getFormData === 'function' ? api.getFormData() : undefined) ??\n api.formData ??\n formData;\n const titlePreview = applyTemplateVars(String(data.titleTemplate || ''), previewVars);\n const bodyRaw = applyTemplateVars(String(data.bodyTemplate || ''), previewVars);\n const bodyHtml = sanitizeInboxHtml(bodyRaw);\n return (\n <div className={styles.previewCollapse}>\n {varsEmptyHint ? (\n <Typography.Text type=\"secondary\">{varsEmptyHint}</Typography.Text>\n ) : null}\n <Collapse\n ghost\n size=\"small\"\n items={[\n {\n key: 'preview',\n label: '效果预览',\n children: (\n <div className={styles.previewCard}>\n <div className={styles.previewTitle}>\n {titlePreview.trim() || (\n <span className={styles.previewEmpty}>(无标题)</span>\n )}\n </div>\n {bodyHtml ? (\n <div\n className={styles.previewBody}\n dangerouslySetInnerHTML={{ __html: bodyHtml }}\n />\n ) : (\n <div className={`${styles.previewBody} ${styles.previewEmpty}`}>\n (无正文)\n </div>\n )}\n </div>\n ),\n },\n ]}\n />\n </div>\n );\n }}\n </FormItem>\n ) : null}\n </FormModal>\n );\n};\n\nexport default TemplateFormModal;\n"],"names":["selectInModalPopupProps","TemplateFormModal","open","isCreate","initial","catalog","roleOptions","variables","catalogError","previewVars","canWrite","onCancel","onSubmit","renderAudienceField","roles","setRoles","useState","editorReady","setEditorReady","latestBodyHtmlRef","useRef","useEffect","ensureRichTextBlockHtml","normalizeTemplatePlaceholders","id","editorKey","formData","useMemo","varsEmptyHint","handleAfterOpenChange","useCallback","nextOpen","fieldList","fields","jsx","Input","Select","c","RichTextField","html","r","AUDIENCE_SLOT_OPTIONS","o","formProps","data","message","eventKey","titleTemplate","audienceRoles","audienceSlots","normalizeAudienceSlots","hasAudienceSelection","ORG_TENANT_SLOT","resolve","Modal","hit","scenario","unwrapMsgVarSpansForStorage","e","sourceTag","templateSourceTag","jsxs","FormModal","Space","Tag","FormInfo","styles","Typography","FormItem","api","titlePreview","applyTemplateVars","bodyRaw","bodyHtml","sanitizeInboxHtml","Collapse"],"mappings":"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"}
@@ -32,6 +32,11 @@ export type MessageTemplateAdminItem = {
32
32
  audienceSlots?: string[];
33
33
  enabled?: boolean;
34
34
  channel?: string;
35
+ /**
36
+ * 配置归属:catalog=Agent 内置(可虚拟行);tenant=租户自定义/覆盖。
37
+ * 与 mc list `source` 对齐。
38
+ */
39
+ source?: 'catalog' | 'tenant';
35
40
  };
36
41
  export type MessageEventCatalogItem = {
37
42
  eventKey: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../../../../../src/components/Tools/MessageCenter/MessageTemplateAdmin/types.ts"],"sourcesContent":["import type { ReactNode } from 'react';\n\nexport type MessageCrudFlags = {\n create: boolean;\n read: boolean;\n update: boolean;\n delete: boolean;\n};\n\nexport type MessageAdminPermissions = {\n template?: Partial<MessageCrudFlags>;\n push?: Partial<MessageCrudFlags>;\n variable?: Partial<MessageCrudFlags>;\n};\n\nconst ALL_CRUD_OFF: MessageCrudFlags = {\n create: false,\n read: false,\n update: false,\n delete: false,\n};\n\nconst ALL_CRUD_ON: MessageCrudFlags = {\n create: true,\n read: true,\n update: true,\n delete: true,\n};\n\nfunction mergeCrud(\n partial: Partial<MessageCrudFlags> | undefined,\n fallback: MessageCrudFlags,\n): MessageCrudFlags {\n return {\n create: partial?.create ?? fallback.create,\n read: partial?.read ?? fallback.read,\n update: partial?.update ?? fallback.update,\n delete: partial?.delete ?? fallback.delete,\n };\n}\n\n/** 解析 Admin 门禁:有 permissions 用细粒度;否则 canWrite 作 Showcase 全开/全关。 */\nexport function resolveMessageAdminPermissions(\n permissions: MessageAdminPermissions | undefined,\n canWrite: boolean | undefined,\n): { template: MessageCrudFlags; push: MessageCrudFlags; variable: MessageCrudFlags } {\n const fallback = canWrite ? ALL_CRUD_ON : ALL_CRUD_OFF;\n if (!permissions) {\n return { template: fallback, push: fallback, variable: fallback };\n }\n return {\n template: mergeCrud(permissions.template, ALL_CRUD_OFF),\n push: mergeCrud(permissions.push, ALL_CRUD_OFF),\n variable: mergeCrud(permissions.variable, ALL_CRUD_OFF),\n };\n}\n\nexport type MessageTemplateAdminItem = {\n id?: string;\n code?: string;\n eventKey?: string;\n scenario?: string;\n label?: string;\n messageType?: string;\n titleTemplate?: string;\n titlePreview?: string;\n bodyTemplate?: string;\n audienceRoles?: string[];\n roles?: string[];\n /** 受众槽位码(与 mc audienceSlots 对齐) */\n audienceSlots?: string[];\n enabled?: boolean;\n channel?: string;\n};\n\nexport type MessageEventCatalogItem = {\n eventKey: string;\n label: string;\n messageType?: string;\n};\n\n/** catalog API 完整载荷(含变量 SSOT) */\nexport type MessageEventCatalogPayload = {\n events: MessageEventCatalogItem[];\n /** 原始 schema;优先用 variables */\n contextSchema?: Record<string, string | { type?: string; label?: string }>;\n variables?: MessageTemplateVariable[];\n /** 受众槽位 options(与 core AUDIENCE_SLOT_OPTIONS 对齐;有则优先) */\n audienceSlotOptions?: { value: string; label: string }[];\n};\n\nexport type MessageAudienceRoleOption = {\n /** 写入模板的角色码 */\n code: string;\n /** 展示名(来自 SSO / fixture) */\n name: string;\n};\n\n/** 推送规则例外抄送选项(SSO 本租户用户;展示名取自接口) */\nexport type MessageAudienceUserOption = {\n id: string;\n /** displayName 优先 */\n name: string;\n /** 工号(SSO employeeId) */\n employeeId?: string;\n /** 主部门 / 首个组织名(SSO orgs) */\n departmentName?: string;\n /** 角色展示名,顿号拼接(SSO roles.name) */\n roleNames?: string;\n};\n\nexport type MessageTemplateVariable = {\n key: string;\n /** 可选中文说明;无则下拉只显示 code */\n label?: string;\n type?: string;\n source?: 'catalog' | 'tenant';\n baseline?: boolean;\n};\n\n/** 变量管理行 */\nexport type MessageTemplateVariableAdmin = MessageTemplateVariable;\n\nexport type PushRuleAdminItem = {\n id?: string;\n code?: string;\n label?: string;\n eventKey?: string;\n levels?: string[];\n templateCode?: string;\n audienceRoles?: string[];\n audienceUserIds?: string[];\n audienceSlots?: string[];\n channels?: string[];\n slaHours?: number;\n scanLookbackDays?: number;\n enabled?: boolean;\n};\n\nexport type MessageTemplateAdminProps = {\n fetchTemplates: () => Promise<MessageTemplateAdminItem[]>;\n saveTemplate?: (item: MessageTemplateAdminItem) => Promise<void>;\n /**\n * 事件目录。可返回数组(仅 events)或完整 payload(含 variables / contextSchema)。\n * 变量优先取 payload.variables,否则从 contextSchema 推导;**禁止** FE 平行 DEFAULT_VARS。\n */\n fetchEventCatalog?: () => Promise<MessageEventCatalogItem[] | MessageEventCatalogPayload>;\n /** 列表行切换启用(不经新建表单) */\n setTemplateEnabled?: (item: MessageTemplateAdminItem, enabled: boolean) => Promise<void>;\n /**\n * 受众角色选项(SSO 本系统角色)。未传且无 renderAudienceField 时用空 Select(禁 tags 手输码)。\n */\n fetchAudienceRoles?: () => Promise<MessageAudienceRoleOption[]>;\n /**\n * 推送规则「例外抄送」多选 options(SSO 本租户用户;静态 userIds)。\n * 未传则例外抄送 Select 为空(禁手输 id);展示名须来自接口 displayName。\n * 任务认领人/分配人等当事人由业务 emit 传 userIds,勿靠配置面点名。\n */\n fetchAudienceUsers?: () => Promise<MessageAudienceUserOption[]>;\n /**\n * @deprecated 变量须来自 catalog;仅联调 fixture 可传。业务页勿硬编码平行表。\n */\n templateVariables?: MessageTemplateVariable[];\n /** 预览用示例值;未传则按 variables 生成 */\n previewVars?: Record<string, string>;\n /**\n * Showcase 快捷:true→十二项全开,false→全关。\n * 业务仓须传 permissions,禁止只靠 canWrite 当真门禁。\n */\n canWrite?: boolean;\n /**\n * 细粒度 CRUD 门禁(模板 / 推送 / 变量 × create|read|update|delete)。\n * 传入后优先于 canWrite。\n */\n permissions?: MessageAdminPermissions;\n /** 模板受众角色插槽;须保持多选下拉语义,禁止 Tree 盖壳默认 Select */\n renderAudienceField?: (ctx: {\n roles: string[];\n onChange: (roles: string[]) => void;\n }) => ReactNode;\n /** @deprecated 优先传 fetchPushRules */\n pushRulesSlot?: ReactNode;\n fetchPushRules?: () => Promise<PushRuleAdminItem[]>;\n savePushRule?: (item: PushRuleAdminItem) => Promise<void>;\n setPushRuleEnabled?: (item: PushRuleAdminItem, enabled: boolean) => Promise<void>;\n deletePushRule?: (item: PushRuleAdminItem) => Promise<void>;\n fetchVariables?: () => Promise<MessageTemplateVariableAdmin[]>;\n saveVariable?: (item: MessageTemplateVariableAdmin) => Promise<void>;\n deleteVariable?: (item: MessageTemplateVariableAdmin) => Promise<void>;\n emptyText?: string;\n className?: string;\n /** 自动编号前缀,默认 MEQ */\n codePrefix?: string;\n};\n\nexport function variablesFromCatalog(\n payload: MessageEventCatalogPayload | null | undefined,\n): MessageTemplateVariable[] {\n if (!payload) return [];\n if (Array.isArray(payload.variables) && payload.variables.length) {\n return payload.variables\n .map((v) => ({\n key: String(v.key || '').trim(),\n label: v.label,\n type: v.type,\n source: v.source,\n baseline: v.baseline,\n }))\n .filter((v) => v.key);\n }\n const schema = payload.contextSchema;\n if (!schema || typeof schema !== 'object') return [];\n return Object.entries(schema)\n .map(([key, raw]) => {\n if (typeof raw === 'string') return { key, type: raw };\n if (raw && typeof raw === 'object') {\n return {\n key,\n type: raw.type || 'string',\n label: raw.label,\n };\n }\n return { key };\n })\n .filter((v) => v.key);\n}\n\nexport function previewVarsFromVariables(vars: MessageTemplateVariable[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const v of vars) {\n out[v.key] = v.type === 'number' ? '1' : v.label || v.key;\n }\n return out;\n}\n"],"names":["ALL_CRUD_OFF","ALL_CRUD_ON","mergeCrud","partial","fallback","resolveMessageAdminPermissions","permissions","canWrite","variablesFromCatalog","payload","v","schema","key","raw","previewVarsFromVariables","vars","out"],"mappings":"AAeA,MAAMA,IAAiC;AAAA,EACrC,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AACV,GAEMC,IAAgC;AAAA,EACpC,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AACV;AAEA,SAASC,EACPC,GACAC,GACkB;AAClB,SAAO;AAAA,IACL,SAAQD,KAAA,gBAAAA,EAAS,WAAUC,EAAS;AAAA,IACpC,OAAMD,KAAA,gBAAAA,EAAS,SAAQC,EAAS;AAAA,IAChC,SAAQD,KAAA,gBAAAA,EAAS,WAAUC,EAAS;AAAA,IACpC,SAAQD,KAAA,gBAAAA,EAAS,WAAUC,EAAS;AAAA,EAAA;AAExC;AAGO,SAASC,EACdC,GACAC,GACoF;AACpF,QAAMH,IAAWG,IAAWN,IAAcD;AAC1C,SAAKM,IAGE;AAAA,IACL,UAAUJ,EAAUI,EAAY,UAAUN,CAAY;AAAA,IACtD,MAAME,EAAUI,EAAY,MAAMN,CAAY;AAAA,IAC9C,UAAUE,EAAUI,EAAY,UAAUN,CAAY;AAAA,EAAA,IAL/C,EAAE,UAAUI,GAAU,MAAMA,GAAU,UAAUA,EAAA;AAO3D;AA4IO,SAASI,EACdC,GAC2B;AAC3B,MAAI,CAACA,EAAS,QAAO,CAAA;AACrB,MAAI,MAAM,QAAQA,EAAQ,SAAS,KAAKA,EAAQ,UAAU;AACxD,WAAOA,EAAQ,UACZ,IAAI,CAACC,OAAO;AAAA,MACX,KAAK,OAAOA,EAAE,OAAO,EAAE,EAAE,KAAA;AAAA,MACzB,OAAOA,EAAE;AAAA,MACT,MAAMA,EAAE;AAAA,MACR,QAAQA,EAAE;AAAA,MACV,UAAUA,EAAE;AAAA,IAAA,EACZ,EACD,OAAO,CAACA,MAAMA,EAAE,GAAG;AAExB,QAAMC,IAASF,EAAQ;AACvB,SAAI,CAACE,KAAU,OAAOA,KAAW,WAAiB,CAAA,IAC3C,OAAO,QAAQA,CAAM,EACzB,IAAI,CAAC,CAACC,GAAKC,CAAG,MACT,OAAOA,KAAQ,WAAiB,EAAE,KAAAD,GAAK,MAAMC,EAAA,IAC7CA,KAAO,OAAOA,KAAQ,WACjB;AAAA,IACL,KAAAD;AAAA,IACA,MAAMC,EAAI,QAAQ;AAAA,IAClB,OAAOA,EAAI;AAAA,EAAA,IAGR,EAAE,KAAAD,EAAA,CACV,EACA,OAAO,CAACF,MAAMA,EAAE,GAAG;AACxB;AAEO,SAASI,EAAyBC,GAAyD;AAChG,QAAMC,IAA8B,CAAA;AACpC,aAAWN,KAAKK;AACd,IAAAC,EAAIN,EAAE,GAAG,IAAIA,EAAE,SAAS,WAAW,MAAMA,EAAE,SAASA,EAAE;AAExD,SAAOM;AACT;"}
1
+ {"version":3,"file":"types.js","sources":["../../../../../src/components/Tools/MessageCenter/MessageTemplateAdmin/types.ts"],"sourcesContent":["import type { ReactNode } from 'react';\n\nexport type MessageCrudFlags = {\n create: boolean;\n read: boolean;\n update: boolean;\n delete: boolean;\n};\n\nexport type MessageAdminPermissions = {\n template?: Partial<MessageCrudFlags>;\n push?: Partial<MessageCrudFlags>;\n variable?: Partial<MessageCrudFlags>;\n};\n\nconst ALL_CRUD_OFF: MessageCrudFlags = {\n create: false,\n read: false,\n update: false,\n delete: false,\n};\n\nconst ALL_CRUD_ON: MessageCrudFlags = {\n create: true,\n read: true,\n update: true,\n delete: true,\n};\n\nfunction mergeCrud(\n partial: Partial<MessageCrudFlags> | undefined,\n fallback: MessageCrudFlags,\n): MessageCrudFlags {\n return {\n create: partial?.create ?? fallback.create,\n read: partial?.read ?? fallback.read,\n update: partial?.update ?? fallback.update,\n delete: partial?.delete ?? fallback.delete,\n };\n}\n\n/** 解析 Admin 门禁:有 permissions 用细粒度;否则 canWrite 作 Showcase 全开/全关。 */\nexport function resolveMessageAdminPermissions(\n permissions: MessageAdminPermissions | undefined,\n canWrite: boolean | undefined,\n): { template: MessageCrudFlags; push: MessageCrudFlags; variable: MessageCrudFlags } {\n const fallback = canWrite ? ALL_CRUD_ON : ALL_CRUD_OFF;\n if (!permissions) {\n return { template: fallback, push: fallback, variable: fallback };\n }\n return {\n template: mergeCrud(permissions.template, ALL_CRUD_OFF),\n push: mergeCrud(permissions.push, ALL_CRUD_OFF),\n variable: mergeCrud(permissions.variable, ALL_CRUD_OFF),\n };\n}\n\nexport type MessageTemplateAdminItem = {\n id?: string;\n code?: string;\n eventKey?: string;\n scenario?: string;\n label?: string;\n messageType?: string;\n titleTemplate?: string;\n titlePreview?: string;\n bodyTemplate?: string;\n audienceRoles?: string[];\n roles?: string[];\n /** 受众槽位码(与 mc audienceSlots 对齐) */\n audienceSlots?: string[];\n enabled?: boolean;\n channel?: string;\n /**\n * 配置归属:catalog=Agent 内置(可虚拟行);tenant=租户自定义/覆盖。\n * 与 mc list `source` 对齐。\n */\n source?: 'catalog' | 'tenant';\n};\n\nexport type MessageEventCatalogItem = {\n eventKey: string;\n label: string;\n messageType?: string;\n};\n\n/** catalog API 完整载荷(含变量 SSOT) */\nexport type MessageEventCatalogPayload = {\n events: MessageEventCatalogItem[];\n /** 原始 schema;优先用 variables */\n contextSchema?: Record<string, string | { type?: string; label?: string }>;\n variables?: MessageTemplateVariable[];\n /** 受众槽位 options(与 core AUDIENCE_SLOT_OPTIONS 对齐;有则优先) */\n audienceSlotOptions?: { value: string; label: string }[];\n};\n\nexport type MessageAudienceRoleOption = {\n /** 写入模板的角色码 */\n code: string;\n /** 展示名(来自 SSO / fixture) */\n name: string;\n};\n\n/** 推送规则例外抄送选项(SSO 本租户用户;展示名取自接口) */\nexport type MessageAudienceUserOption = {\n id: string;\n /** displayName 优先 */\n name: string;\n /** 工号(SSO employeeId) */\n employeeId?: string;\n /** 主部门 / 首个组织名(SSO orgs) */\n departmentName?: string;\n /** 角色展示名,顿号拼接(SSO roles.name) */\n roleNames?: string;\n};\n\nexport type MessageTemplateVariable = {\n key: string;\n /** 可选中文说明;无则下拉只显示 code */\n label?: string;\n type?: string;\n source?: 'catalog' | 'tenant';\n baseline?: boolean;\n};\n\n/** 变量管理行 */\nexport type MessageTemplateVariableAdmin = MessageTemplateVariable;\n\nexport type PushRuleAdminItem = {\n id?: string;\n code?: string;\n label?: string;\n eventKey?: string;\n levels?: string[];\n templateCode?: string;\n audienceRoles?: string[];\n audienceUserIds?: string[];\n audienceSlots?: string[];\n channels?: string[];\n slaHours?: number;\n scanLookbackDays?: number;\n enabled?: boolean;\n};\n\nexport type MessageTemplateAdminProps = {\n fetchTemplates: () => Promise<MessageTemplateAdminItem[]>;\n saveTemplate?: (item: MessageTemplateAdminItem) => Promise<void>;\n /**\n * 事件目录。可返回数组(仅 events)或完整 payload(含 variables / contextSchema)。\n * 变量优先取 payload.variables,否则从 contextSchema 推导;**禁止** FE 平行 DEFAULT_VARS。\n */\n fetchEventCatalog?: () => Promise<MessageEventCatalogItem[] | MessageEventCatalogPayload>;\n /** 列表行切换启用(不经新建表单) */\n setTemplateEnabled?: (item: MessageTemplateAdminItem, enabled: boolean) => Promise<void>;\n /**\n * 受众角色选项(SSO 本系统角色)。未传且无 renderAudienceField 时用空 Select(禁 tags 手输码)。\n */\n fetchAudienceRoles?: () => Promise<MessageAudienceRoleOption[]>;\n /**\n * 推送规则「例外抄送」多选 options(SSO 本租户用户;静态 userIds)。\n * 未传则例外抄送 Select 为空(禁手输 id);展示名须来自接口 displayName。\n * 任务认领人/分配人等当事人由业务 emit 传 userIds,勿靠配置面点名。\n */\n fetchAudienceUsers?: () => Promise<MessageAudienceUserOption[]>;\n /**\n * @deprecated 变量须来自 catalog;仅联调 fixture 可传。业务页勿硬编码平行表。\n */\n templateVariables?: MessageTemplateVariable[];\n /** 预览用示例值;未传则按 variables 生成 */\n previewVars?: Record<string, string>;\n /**\n * Showcase 快捷:true→十二项全开,false→全关。\n * 业务仓须传 permissions,禁止只靠 canWrite 当真门禁。\n */\n canWrite?: boolean;\n /**\n * 细粒度 CRUD 门禁(模板 / 推送 / 变量 × create|read|update|delete)。\n * 传入后优先于 canWrite。\n */\n permissions?: MessageAdminPermissions;\n /** 模板受众角色插槽;须保持多选下拉语义,禁止 Tree 盖壳默认 Select */\n renderAudienceField?: (ctx: {\n roles: string[];\n onChange: (roles: string[]) => void;\n }) => ReactNode;\n /** @deprecated 优先传 fetchPushRules */\n pushRulesSlot?: ReactNode;\n fetchPushRules?: () => Promise<PushRuleAdminItem[]>;\n savePushRule?: (item: PushRuleAdminItem) => Promise<void>;\n setPushRuleEnabled?: (item: PushRuleAdminItem, enabled: boolean) => Promise<void>;\n deletePushRule?: (item: PushRuleAdminItem) => Promise<void>;\n fetchVariables?: () => Promise<MessageTemplateVariableAdmin[]>;\n saveVariable?: (item: MessageTemplateVariableAdmin) => Promise<void>;\n deleteVariable?: (item: MessageTemplateVariableAdmin) => Promise<void>;\n emptyText?: string;\n className?: string;\n /** 自动编号前缀,默认 MEQ */\n codePrefix?: string;\n};\n\nexport function variablesFromCatalog(\n payload: MessageEventCatalogPayload | null | undefined,\n): MessageTemplateVariable[] {\n if (!payload) return [];\n if (Array.isArray(payload.variables) && payload.variables.length) {\n return payload.variables\n .map((v) => ({\n key: String(v.key || '').trim(),\n label: v.label,\n type: v.type,\n source: v.source,\n baseline: v.baseline,\n }))\n .filter((v) => v.key);\n }\n const schema = payload.contextSchema;\n if (!schema || typeof schema !== 'object') return [];\n return Object.entries(schema)\n .map(([key, raw]) => {\n if (typeof raw === 'string') return { key, type: raw };\n if (raw && typeof raw === 'object') {\n return {\n key,\n type: raw.type || 'string',\n label: raw.label,\n };\n }\n return { key };\n })\n .filter((v) => v.key);\n}\n\nexport function previewVarsFromVariables(vars: MessageTemplateVariable[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const v of vars) {\n out[v.key] = v.type === 'number' ? '1' : v.label || v.key;\n }\n return out;\n}\n"],"names":["ALL_CRUD_OFF","ALL_CRUD_ON","mergeCrud","partial","fallback","resolveMessageAdminPermissions","permissions","canWrite","variablesFromCatalog","payload","v","schema","key","raw","previewVarsFromVariables","vars","out"],"mappings":"AAeA,MAAMA,IAAiC;AAAA,EACrC,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AACV,GAEMC,IAAgC;AAAA,EACpC,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AACV;AAEA,SAASC,EACPC,GACAC,GACkB;AAClB,SAAO;AAAA,IACL,SAAQD,KAAA,gBAAAA,EAAS,WAAUC,EAAS;AAAA,IACpC,OAAMD,KAAA,gBAAAA,EAAS,SAAQC,EAAS;AAAA,IAChC,SAAQD,KAAA,gBAAAA,EAAS,WAAUC,EAAS;AAAA,IACpC,SAAQD,KAAA,gBAAAA,EAAS,WAAUC,EAAS;AAAA,EAAA;AAExC;AAGO,SAASC,EACdC,GACAC,GACoF;AACpF,QAAMH,IAAWG,IAAWN,IAAcD;AAC1C,SAAKM,IAGE;AAAA,IACL,UAAUJ,EAAUI,EAAY,UAAUN,CAAY;AAAA,IACtD,MAAME,EAAUI,EAAY,MAAMN,CAAY;AAAA,IAC9C,UAAUE,EAAUI,EAAY,UAAUN,CAAY;AAAA,EAAA,IAL/C,EAAE,UAAUI,GAAU,MAAMA,GAAU,UAAUA,EAAA;AAO3D;AAiJO,SAASI,EACdC,GAC2B;AAC3B,MAAI,CAACA,EAAS,QAAO,CAAA;AACrB,MAAI,MAAM,QAAQA,EAAQ,SAAS,KAAKA,EAAQ,UAAU;AACxD,WAAOA,EAAQ,UACZ,IAAI,CAACC,OAAO;AAAA,MACX,KAAK,OAAOA,EAAE,OAAO,EAAE,EAAE,KAAA;AAAA,MACzB,OAAOA,EAAE;AAAA,MACT,MAAMA,EAAE;AAAA,MACR,QAAQA,EAAE;AAAA,MACV,UAAUA,EAAE;AAAA,IAAA,EACZ,EACD,OAAO,CAACA,MAAMA,EAAE,GAAG;AAExB,QAAMC,IAASF,EAAQ;AACvB,SAAI,CAACE,KAAU,OAAOA,KAAW,WAAiB,CAAA,IAC3C,OAAO,QAAQA,CAAM,EACzB,IAAI,CAAC,CAACC,GAAKC,CAAG,MACT,OAAOA,KAAQ,WAAiB,EAAE,KAAAD,GAAK,MAAMC,EAAA,IAC7CA,KAAO,OAAOA,KAAQ,WACjB;AAAA,IACL,KAAAD;AAAA,IACA,MAAMC,EAAI,QAAQ;AAAA,IAClB,OAAOA,EAAI;AAAA,EAAA,IAGR,EAAE,KAAAD,EAAA,CACV,EACA,OAAO,CAACF,MAAMA,EAAE,GAAG;AACxB;AAEO,SAASI,EAAyBC,GAAyD;AAChG,QAAMC,IAA8B,CAAA;AACpC,aAAWN,KAAKK;AACd,IAAAC,EAAIN,EAAE,GAAG,IAAIA,EAAE,SAAS,WAAW,MAAMA,EAAE,SAASA,EAAE;AAExD,SAAOM;AACT;"}
@@ -4,8 +4,8 @@ export { resolveInboxItemActions, resolveInboxSceneKey, filterInboxActionsForHos
4
4
  export { INBOX_BADGE_REFRESH_EVENT, requestInboxBadgeRefresh, requestInboxBadgeRefreshAfterWrite, } from './Inbox';
5
5
  export { ActionTrackingShell } from './ActionTracking';
6
6
  export type { ActionTrackingShellProps } from './ActionTracking';
7
- export { CreateActionModal, CreateActionForm, renderPersonOptionLabel, CREATE_ACTION_VARIETY_PAGE_SIZE, PersonRoleCascader, PersonRoleCascaderField, SetFormFields, findPersonCascadePath, cascadePathStillValid, validateCreateActionPersons, createActionPersonWarnMessage, personDisplayName, addDaysYmd, ActionFilterBar, ActionListTable, ActionFollowModal, CancelExecutionModal, CancelExecutionForm, sanitizeActionHtml, defaultCreatedRange, normalizeActionFilters, canQueryActionList, resetActionFiltersToDefault, } from './ActionTracking';
8
- export type { CreateActionModalProps, CreateActionFormProps, PersonRoleCascaderProps, PersonRoleCascaderFieldProps, CreateActionPrefill, CreateActionScopeLock, CreateActionScopeMode, LockedContextField, ActionPersonCascadeOption, ActionPersonOption, CreateActionPersonCatalog, CreateActionSelectOption, CreateActionDimensionOption, CreateActionLoaders, CreateActionSelectPageQuery, CreateActionSelectPageResult, CreateActionSubmitPayload, CreateActionPersonValidateError, CreateActionPersonValidateResult, ActionFilterBarProps, ActionListTableProps, ActionFollowModalProps, ActionFollowView, CancelExecutionModalProps, ActionListFilters, ActionListRowBase, ActionListSelectOption, ActionListColumns, ActionListEmptyConfig, } from './ActionTracking';
7
+ export { CreateActionModal, CreateActionForm, renderPersonOptionLabel, CREATE_ACTION_VARIETY_PAGE_SIZE, PersonRoleCascader, PersonRoleCascaderField, SetFormFields, findPersonCascadePath, cascadePathStillValid, validateCreateActionPersons, createActionPersonWarnMessage, personDisplayName, addDaysYmd, ActionFilterBar, ActionListTable, ActionFollowModal, CancelExecutionModal, CancelExecutionForm, sanitizeActionHtml, isActionExecuteHidden, defaultCreatedRange, normalizeActionFilters, canQueryActionList, resetActionFiltersToDefault, } from './ActionTracking';
8
+ export type { ActionExecuteGateRow, ActionExecuteGateOptions, CreateActionModalProps, CreateActionFormProps, PersonRoleCascaderProps, PersonRoleCascaderFieldProps, CreateActionPrefill, CreateActionScopeLock, CreateActionScopeMode, LockedContextField, ActionPersonCascadeOption, ActionPersonOption, CreateActionPersonCatalog, CreateActionSelectOption, CreateActionDimensionOption, CreateActionLoaders, CreateActionSelectPageQuery, CreateActionSelectPageResult, CreateActionSubmitPayload, CreateActionPersonValidateError, CreateActionPersonValidateResult, ActionFilterBarProps, ActionListTableProps, ActionFollowModalProps, ActionFollowView, CancelExecutionModalProps, ActionListFilters, ActionListRowBase, ActionListSelectOption, ActionListColumns, ActionListEmptyConfig, } from './ActionTracking';
9
9
  export { MessageTemplateAdmin } from './MessageCenter';
10
10
  export type { MessageTemplateAdminProps, MessageTemplateAdminItem, MessageEventCatalogItem, MessageEventCatalogPayload, MessageAudienceRoleOption, MessageAudienceUserOption, MessageTemplateVariable, MessageTemplateVariableAdmin, PushRuleAdminItem, MessageCrudFlags, MessageAdminPermissions, } from './MessageCenter';
11
11
  export { generateTemplateCode, normalizeTemplatePlaceholders, applyTemplateVars, resolveMessageAdminPermissions, MSG_CENTER_APP_SWITCH_STORAGE_KEY, SYSTEM_APP_TO_MSG_CENTER_APP_KEY, MSG_CENTER_SWITCHABLE_APP_KEYS, msgCenterAppKeyFromSystemAppCode, filterMsgCenterSwitchableApps, getMsgCenterAppKey, setMsgCenterAppKey, subscribeMsgCenterAppKey, bindMsgCenterAppKeyStorageSync, resolveMsgCenterSwitchState, useMsgCenterAppKey, MsgCenterAppSwitcher, } from './MessageCenter';
@@ -21,8 +21,8 @@ export * from './OrgTree';
21
21
  export * from './StateBar';
22
22
  export * from './SegmentedRadio';
23
23
  export * from './Navigation';
24
- export { DispositionBar, AlertDispositionPanel, DispositionAlertLevelLegend, formatDispositionTriggerText, getDispositionAlertLevel, buildDispositionAlertContext, } from './Disposition';
25
- export type { DispositionBarProps, AlertDispositionPanelProps, DispositionAlertContext, DispositionAlertKind, DispositionAlertLevelSpec, DispositionAlertLevelCatalog, DispositionAlertLevelLegendProps, } from './Disposition';
24
+ export { DispositionBar, AlertDispositionPanel, DispositionAlertLevelLegend, formatDispositionTriggerText, formatDispositionStatusBadge, getDispositionAlertLevel, buildDispositionAlertContext, } from './Disposition';
25
+ export type { DispositionBarProps, AlertDispositionPanelProps, DispositionAlertContext, DispositionAlertKind, DispositionAlertLevelSpec, DispositionAlertLevelCatalog, DispositionAlertLevelLegendProps, DispositionStatusBadgeParts, DispositionStatusBadgeFormatted, } from './Disposition';
26
26
  export * from './Audit';
27
27
  export * from './Stat';
28
28
  export * from './Table';
package/dist/index.d.ts CHANGED
@@ -48,8 +48,8 @@ export * from './components/OrgTree';
48
48
  export * from './components/StateBar';
49
49
  export * from './components/SegmentedRadio';
50
50
  export * from './components/Navigation';
51
- export { DispositionBar, AlertDispositionPanel, DispositionAlertLevelLegend, formatDispositionTriggerText, getDispositionAlertLevel, buildDispositionAlertContext, } from './components/Disposition';
52
- export type { DispositionBarProps, AlertDispositionPanelProps, DispositionAlertContext, DispositionAlertKind, DispositionAlertLevelSpec, DispositionAlertLevelCatalog, DispositionAlertLevelLegendProps, } from './components/Disposition';
51
+ export { DispositionBar, AlertDispositionPanel, DispositionAlertLevelLegend, formatDispositionTriggerText, formatDispositionStatusBadge, getDispositionAlertLevel, buildDispositionAlertContext, } from './components/Disposition';
52
+ export type { DispositionBarProps, AlertDispositionPanelProps, DispositionAlertContext, DispositionAlertKind, DispositionAlertLevelSpec, DispositionAlertLevelCatalog, DispositionAlertLevelLegendProps, DispositionStatusBadgeParts, DispositionStatusBadgeFormatted, } from './components/Disposition';
53
53
  export * from './components/Audit';
54
54
  export * from './components/Stat';
55
55
  export * from './components/Table';