@qiqb/message-domain 0.1.3 → 0.1.4

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/README.md CHANGED
@@ -17,6 +17,7 @@ configureMessageDomainRuntime({
17
17
  useLocation, // 返回 { search: string },支持 receiptId 查询参数打开详情
18
18
  useAccess, // 返回 { verifyElementPermission(code, projectCode) }
19
19
  projectCode: 'qiqb_platform',
20
+ sourceSystem: 'qiqb_platform', // 平台宿主新增主题的来源;业务宿主填写实际发布方编码
20
21
  apiPrefix: '/api/qiqb_platform/message',
21
22
  inboxPath: '/p/message/inbox',
22
23
  receiptQueryParam: 'receiptId',
@@ -27,6 +28,10 @@ configureMessageDomainRuntime({
27
28
 
28
29
  `request` 由宿主继续处理 token、超时及鉴权。默认 fetch 只提供同源 JSON 请求,适合无框架预览;正式接入应注入现有请求层。页面使用 `WebResp<T> { success, message?, data? }` 与 `PageInfo<T> { total, records?, current?, size? }`。消息领域自行提示业务失败,传入 `skipErrorHandler: true`,避免宿主重复弹出相同错误。
29
30
 
31
+ 新增主题的 `sourceSystem` 由宿主在页面挂载前配置,表单不再要求手填,保存请求和后端字段继续保留。该编码必须与业务发布参数 `MessagePublishParam.sourceSystem` 完全一致,大小写保留;例如发布方使用 `wmp`,业务宿主就配置 `sourceSystem: 'wmp'`。它表示发布方,与按钮授权使用的 `projectCode` 独立,领域包不从权限项目或应用名称推断来源,也不提供默认来源。
32
+
33
+ 来源格式与后端一致:以英文字母开头,后续仅允许英文字母、数字、下划线、点或短横线,最多 64 个字符。宿主未配置或配置不合法时,页面提示原因并禁止新增主题;已有主题仍按原记录编辑。编辑时只读展示并保留该主题的原来源,平台宿主管理其他系统的主题时也不会改成当前宿主来源。
34
+
30
35
  ### 可选实时订阅
31
36
 
32
37
  消息包不依赖 Socket.IO 客户端。宿主安装并配置独立 `@qiqb/socketio-domain` 后,将同账户共享连接的
@@ -187,6 +192,7 @@ configureMessageDomainRuntime({
187
192
  useLocation,
188
193
  useAccess,
189
194
  projectCode: 'prokeeper_bip',
195
+ // sourceSystem: messageSourceSystem, // 填实际业务发布来源,与发布参数一致
190
196
  apiPrefix: '/api/qiqb_platform/message', // 消息服务迁入平台;如过渡服务另有地址可显式覆盖
191
197
  storageNamespace: 'prokeeper-bip',
192
198
  });
@@ -203,12 +209,13 @@ cd frontend
203
209
  corepack pnpm --filter @qiqb/message-domain lint
204
210
  corepack pnpm --filter @qiqb/message-domain test:reminders
205
211
  corepack pnpm --filter @qiqb/message-domain test:runtime
212
+ corepack pnpm --filter @qiqb/message-domain test:topics
206
213
  corepack pnpm --filter @qiqb/message-domain test:presentation
207
214
  corepack pnpm build:message-domain
208
215
  corepack pnpm --filter @qiqb/message-domain test:routes
209
216
  corepack pnpm pack:message-domain
210
217
  ```
211
218
 
212
- 打包到 `/private/tmp/qiqb-message-domain-0.1.3.tgz`,可通过 `pnpm add /private/tmp/qiqb-message-domain-0.1.3.tgz` 在消费仓库安装验证。构建仅清理本包 `build/`,输出 ESM 的相对 `.js` 导入、界面 `.d.ts`、独立路由 `.cjs`/`.d.cts` 和按源路径复制的 `.less`。包内容只包含 `build/`、README 和 package.json,不包含源代码、测试、依赖缓存或宿主生成文件。
219
+ 打包到 `/private/tmp/qiqb-message-domain-0.1.4.tgz`,可通过 `pnpm add /private/tmp/qiqb-message-domain-0.1.4.tgz` 在消费仓库安装验证。构建仅清理本包 `build/`,输出 ESM 的相对 `.js` 导入、界面 `.d.ts`、独立路由 `.cjs`/`.d.cts` 和按源路径复制的 `.less`。包内容只包含 `build/`、README 和 package.json,不包含源代码、测试、依赖缓存或宿主生成文件。
213
220
 
214
221
  `publish:message-domain` 与包内 `publish:official` 默认发布到 npm 官方仓库,使用公开 scoped 包;`publish:private/publish:local/publish:nexus` 保留为显式私服入口。它们不会在 build/pack 时自动执行;只有明确要发布时再运行。验证和打包不启动宿主应用、不部署后端、不远程发布。
@@ -7,8 +7,10 @@ interface Props {
7
7
  description: string;
8
8
  icon?: ReactNode;
9
9
  extra?: ReactNode;
10
+ /** 页面可在领域主题下调整自身布局,不影响主题/订阅等其他消息页面。 */
11
+ className?: string;
10
12
  children: ReactNode;
11
13
  }
12
14
  /** 只在消息领域内统一页面框架,避免把订阅语义放进跨领域 shared 包。 */
13
- export default function MessageWorkspace({ title, description, icon, extra, children, }: Props): import("react").JSX.Element;
15
+ export default function MessageWorkspace({ title, description, icon, extra, className, children, }: Props): import("react").JSX.Element;
14
16
  export {};
@@ -20,7 +20,7 @@ export function useMessageTheme() {
20
20
  };
21
21
  }
22
22
  /** 只在消息领域内统一页面框架,避免把订阅语义放进跨领域 shared 包。 */
23
- export default function MessageWorkspace({ title, description, icon = _jsx(BellOutlined, {}), extra, children, }) {
23
+ export default function MessageWorkspace({ title, description, icon = _jsx(BellOutlined, {}), extra, className, children, }) {
24
24
  const messageTheme = useMessageTheme();
25
- return (_jsx(PageContainer, { pageHeaderRender: false, className: "qiqb-message-page", children: _jsxs("div", { className: "qiqb-message", style: messageTheme, children: [_jsxs("header", { className: "qiqb-message-heading", children: [_jsxs("div", { className: "qiqb-message-heading-main", children: [_jsx("div", { className: "qiqb-message-heading-icon", "aria-hidden": true, children: icon }), _jsxs("div", { children: [_jsx("h1", { children: title }), _jsx("p", { children: description })] })] }), extra && _jsx("div", { className: "qiqb-message-heading-actions", children: extra })] }), children] }) }));
25
+ return (_jsx(PageContainer, { pageHeaderRender: false, className: "qiqb-message-page", children: _jsxs("div", { className: ['qiqb-message', className].filter(Boolean).join(' '), style: messageTheme, children: [_jsxs("header", { className: "qiqb-message-heading", children: [_jsxs("div", { className: "qiqb-message-heading-main", children: [_jsx("div", { className: "qiqb-message-heading-icon", "aria-hidden": true, children: icon }), _jsxs("div", { children: [_jsx("h1", { children: title }), _jsx("p", { children: description })] })] }), extra && _jsx("div", { className: "qiqb-message-heading-actions", children: extra })] }), children] }) }));
26
26
  }
@@ -11,6 +11,14 @@ const receiptId = (record) => record.receiptId || record.id;
11
11
  function isExpired(record) {
12
12
  return (!!record.expiresAt && new Date(record.expiresAt).getTime() <= Date.now());
13
13
  }
14
+ /** 只强调发布时保存的重要/严重级别,历史消息不额外占用普通级别标签。 */
15
+ function messageLevelTag(record) {
16
+ if (record.messageLevel === 'SEVERE')
17
+ return _jsx(Tag, { color: "error", children: "\u4E25\u91CD" });
18
+ if (record.messageLevel === 'IMPORTANT')
19
+ return _jsx(Tag, { color: "warning", children: "\u91CD\u8981" });
20
+ return null;
21
+ }
14
22
  /** 服务端本地时间不附带时区,按浏览器本地时间展示;无效值保留原文便于识别。 */
15
23
  function formatTime(value, short = false) {
16
24
  if (!value)
@@ -219,29 +227,29 @@ export default function InboxPage() {
219
227
  void loadDetail(id);
220
228
  // URL 定位来自全局提醒;只有地址变化才加载,普通列表状态更新不能反复读取详情。
221
229
  }, [location.search]);
222
- const reader = (_jsx("section", { className: "qiqb-inbox-reader", "aria-label": "\u6D88\u606F\u8BE6\u60C5", "aria-busy": detailLoading, children: detailLoading && !detail ? (_jsx("div", { className: "qiqb-inbox-reader-body", children: _jsx(Skeleton, { active: true, title: { width: '60%' }, paragraph: { rows: 8 } }) })) : detail ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "qiqb-inbox-reader-top", children: [_jsxs(Space, { size: 8, wrap: true, children: [_jsx(Tag, { color: "blue", children: topicName(detail) }), _jsx("span", { className: "qiqb-message-caption", children: detail.sourceSystem.toUpperCase() })] }), _jsxs("span", { className: "qiqb-inbox-read-state", children: [detail.readAt ? (_jsxs(_Fragment, { children: [_jsx(CheckOutlined, {}), " \u5DF2\u8BFB"] })) : ('未读'), isExpired(detail) && _jsx(Tag, { children: "\u5DF2\u8FC7\u671F" })] })] }), _jsxs("div", { className: "qiqb-inbox-reader-body", children: [_jsx("h2", { children: detail.title }), _jsxs("div", { className: "qiqb-inbox-reader-time", children: ["\u6536\u5230\u4E8E ", formatTime(detail.createTime)] }), _jsx("div", { className: "qiqb-inbox-message-content", children: detail.content }), _jsxs("dl", { className: "qiqb-inbox-detail-meta", children: [_jsxs("div", { children: [_jsx("dt", { children: "\u53D1\u751F\u65F6\u95F4" }), _jsx("dd", { children: formatTime(detail.occurredAt) })] }), detail.businessType && (_jsxs("div", { children: [_jsx("dt", { children: "\u4E1A\u52A1\u7C7B\u578B" }), _jsx("dd", { children: detail.businessType })] })), detail.businessId && (_jsxs("div", { children: [_jsx("dt", { children: "\u4E1A\u52A1\u7F16\u53F7" }), _jsx("dd", { children: detail.businessId })] })), detail.expiresAt && (_jsxs("div", { children: [_jsx("dt", { children: "\u6709\u6548\u671F\u81F3" }), _jsx("dd", { children: formatTime(detail.expiresAt) })] }))] })] }), (isInternalMessagePath(detail.targetPath) || !detail.readAt) && (_jsx("div", { className: "qiqb-inbox-reader-footer", children: _jsxs(Space, { wrap: true, children: [isInternalMessagePath(detail.targetPath) && (_jsx(Button, { type: "primary", icon: _jsx(ArrowRightOutlined, {}), onClick: () => navigate(detail.targetPath), children: "\u67E5\u770B\u76F8\u5173\u4E1A\u52A1" })), !detail.readAt && (_jsx(Button, { icon: _jsx(CheckOutlined, {}), loading: busyIds.includes(receiptId(detail)), onClick: () => void markRead(detail), children: "\u6807\u8BB0\u5DF2\u8BFB" }))] }) }))] })) : (_jsxs("div", { className: "qiqb-message-state qiqb-inbox-reader-placeholder", children: [_jsx("span", { className: "qiqb-message-state-icon", children: _jsx(ReadOutlined, {}) }), _jsx("h3", { children: detailFailed ? '暂时无法打开这条消息' : '选择一条消息开始阅读' }), _jsx("p", { children: detailFailed
230
+ const reader = (_jsx("section", { className: "qiqb-inbox-reader", "aria-label": "\u6D88\u606F\u8BE6\u60C5", "aria-busy": detailLoading, children: detailLoading && !detail ? (_jsx("div", { className: "qiqb-inbox-reader-body", children: _jsx(Skeleton, { active: true, title: { width: '60%' }, paragraph: { rows: 8 } }) })) : detail ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "qiqb-inbox-reader-top", children: [_jsxs("div", { className: "qiqb-inbox-reader-heading", children: [_jsxs("h2", { className: "qiqb-inbox-reader-title", children: [detail.title, ' ', _jsx("span", { className: "qiqb-inbox-reader-topic", children: topicName(detail) })] }), (isInternalMessagePath(detail.targetPath) || !detail.readAt) && (_jsxs(Space, { className: "qiqb-inbox-reader-actions", size: 8, wrap: true, children: [isInternalMessagePath(detail.targetPath) && (_jsx(Button, { type: "primary", size: "small", icon: _jsx(ArrowRightOutlined, {}), onClick: () => navigate(detail.targetPath), children: "\u67E5\u770B\u76F8\u5173\u4E1A\u52A1" })), !detail.readAt && (_jsx(Button, { size: "small", icon: _jsx(CheckOutlined, {}), loading: busyIds.includes(receiptId(detail)), onClick: () => void markRead(detail), children: "\u6807\u8BB0\u5DF2\u8BFB" }))] }))] }), _jsxs("div", { className: "qiqb-inbox-reader-info", children: [_jsxs(Space, { size: [8, 4], wrap: true, children: [messageLevelTag(detail), _jsx("span", { children: detail.sourceSystem.toUpperCase() }), _jsxs("span", { children: ["\u6536\u5230\u4E8E ", formatTime(detail.createTime)] })] }), _jsxs("span", { className: "qiqb-inbox-read-state", children: [detail.readAt ? (_jsxs(_Fragment, { children: [_jsx(CheckOutlined, {}), " \u5DF2\u8BFB"] })) : ('未读'), isExpired(detail) && _jsx(Tag, { children: "\u5DF2\u8FC7\u671F" })] })] })] }), _jsxs("div", { className: "qiqb-inbox-reader-body", children: [_jsx("div", { className: "qiqb-inbox-message-content", children: detail.content }), _jsxs("dl", { className: "qiqb-inbox-detail-meta", children: [_jsxs("div", { children: [_jsx("dt", { children: "\u53D1\u751F\u65F6\u95F4" }), _jsx("dd", { children: formatTime(detail.occurredAt) })] }), detail.businessType && (_jsxs("div", { children: [_jsx("dt", { children: "\u4E1A\u52A1\u7C7B\u578B" }), _jsx("dd", { children: detail.businessType })] })), detail.businessId && (_jsxs("div", { children: [_jsx("dt", { children: "\u4E1A\u52A1\u7F16\u53F7" }), _jsx("dd", { children: detail.businessId })] })), detail.expiresAt && (_jsxs("div", { children: [_jsx("dt", { children: "\u6709\u6548\u671F\u81F3" }), _jsx("dd", { children: formatTime(detail.expiresAt) })] }))] })] })] })) : (_jsxs("div", { className: "qiqb-message-state qiqb-inbox-reader-placeholder", children: [_jsx("span", { className: "qiqb-message-state-icon", children: _jsx(ReadOutlined, {}) }), _jsx("h3", { children: detailFailed ? '暂时无法打开这条消息' : '选择一条消息开始阅读' }), _jsx("p", { children: detailFailed
223
231
  ? '消息详情加载失败,请重试。'
224
232
  : '在左侧查看消息,阅读详情或前往相关业务。' }), detailFailed && detailId && (_jsx(Button, { onClick: () => void loadDetail(detailId), children: "\u91CD\u65B0\u52A0\u8F7D" }))] })) }));
225
- return (_jsxs(MessageWorkspace, { title: "\u6211\u7684\u6D88\u606F", description: "\u96C6\u4E2D\u67E5\u770B\u4E1A\u52A1\u63D0\u9192\uFF0C\u53CA\u65F6\u8DDF\u8FDB\u4E0E\u4F60\u76F8\u5173\u7684\u6D88\u606F\u3002", icon: _jsx(InboxOutlined, {}), extra: _jsxs(_Fragment, { children: [_jsxs("span", { className: "qiqb-inbox-unread-summary", children: [_jsx("span", { children: "\u672A\u8BFB" }), _jsx("strong", { "aria-live": "polite", children: unreadCount === undefined ? '—' : unreadCount })] }), _jsx(Button, { icon: _jsx(ReloadOutlined, {}), loading: loading || countLoading, onClick: refresh, children: "\u5237\u65B0\u6D88\u606F" })] }), children: [_jsxs("div", { className: "qiqb-message-surface", children: [_jsxs("div", { className: "qiqb-message-toolbar", children: [_jsx(Segmented, { "aria-label": "\u7B5B\u9009\u9605\u8BFB\u72B6\u6001", value: query.unread === undefined
226
- ? 'ALL'
227
- : query.unread
228
- ? 'UNREAD'
229
- : 'READ', options: [
230
- { label: '全部消息', value: 'ALL' },
231
- { label: '未读', value: 'UNREAD' },
232
- { label: '已读', value: 'READ' },
233
- ], onChange: (value) => setQuery((current) => ({
234
- ...current,
235
- current: 1,
236
- unread: value === 'ALL' ? undefined : value === 'UNREAD',
237
- })) }), _jsx(Select, { className: "qiqb-message-filter-select", "aria-label": "\u7B5B\u9009\u6D88\u606F\u4E3B\u9898", placeholder: "\u5168\u90E8\u6D88\u606F\u4E3B\u9898", allowClear: true, showSearch: true, optionFilterProp: "label", value: query.topicCode, options: topics.map((topic) => ({
238
- value: topic.code,
239
- label: topic.name,
240
- })), onChange: (topicCode) => setQuery((current) => ({ ...current, current: 1, topicCode })) })] }), _jsxs("div", { className: "qiqb-inbox-layout", children: [_jsxs("section", { className: "qiqb-inbox-list", "aria-label": "\u6D88\u606F\u5217\u8868", "aria-busy": loading, children: [_jsxs("div", { className: "qiqb-inbox-list-heading", children: [_jsx("span", { children: "\u6D88\u606F\u5217\u8868" }), _jsx("span", { className: "qiqb-message-caption", children: listFailed ? '加载失败' : total + ' 条消息' })] }), _jsx("div", { className: "qiqb-inbox-list-body", children: loading ? (_jsx("div", { className: "qiqb-inbox-list-skeleton", children: [0, 1, 2].map((key) => (_jsx(Skeleton, { active: true, title: true, paragraph: { rows: 2 } }, key))) })) : listFailed ? (_jsxs("div", { className: "qiqb-message-state", children: [_jsx("span", { className: "qiqb-message-state-icon", children: _jsx(InboxOutlined, {}) }), _jsx("h3", { children: "\u6D88\u606F\u52A0\u8F7D\u5931\u8D25" }), _jsx("p", { children: "\u8BF7\u91CD\u65B0\u52A0\u8F7D\u540E\u7EE7\u7EED\u67E5\u770B\u3002" }), _jsx(Button, { onClick: refresh, children: "\u91CD\u65B0\u52A0\u8F7D" })] })) : records.length ? (records.map((record) => (_jsxs("button", { type: "button", className: [
233
+ return (_jsxs(MessageWorkspace, { title: "\u6211\u7684\u6D88\u606F", description: "\u96C6\u4E2D\u67E5\u770B\u4E1A\u52A1\u63D0\u9192\uFF0C\u53CA\u65F6\u8DDF\u8FDB\u4E0E\u4F60\u76F8\u5173\u7684\u6D88\u606F\u3002", icon: _jsx(InboxOutlined, {}), className: "qiqb-inbox-workspace", children: [_jsxs("div", { className: "qiqb-message-surface", children: [_jsxs("div", { className: "qiqb-message-toolbar qiqb-inbox-toolbar", children: [_jsxs("div", { className: "qiqb-inbox-filters", children: [_jsx(Segmented, { "aria-label": "\u7B5B\u9009\u9605\u8BFB\u72B6\u6001", value: query.unread === undefined
234
+ ? 'ALL'
235
+ : query.unread
236
+ ? 'UNREAD'
237
+ : 'READ', options: [
238
+ { label: '全部消息', value: 'ALL' },
239
+ { label: '未读', value: 'UNREAD' },
240
+ { label: '已读', value: 'READ' },
241
+ ], onChange: (value) => setQuery((current) => ({
242
+ ...current,
243
+ current: 1,
244
+ unread: value === 'ALL' ? undefined : value === 'UNREAD',
245
+ })) }), _jsx(Select, { className: "qiqb-message-filter-select", "aria-label": "\u7B5B\u9009\u6D88\u606F\u4E3B\u9898", placeholder: "\u5168\u90E8\u6D88\u606F\u4E3B\u9898", allowClear: true, showSearch: true, optionFilterProp: "label", value: query.topicCode, options: topics.map((topic) => ({
246
+ value: topic.code,
247
+ label: topic.name,
248
+ })), onChange: (topicCode) => setQuery((current) => ({ ...current, current: 1, topicCode })) })] }), _jsxs("div", { className: "qiqb-inbox-toolbar-summary", children: [_jsx("span", { className: "qiqb-message-caption", "aria-live": "polite", children: listFailed ? '加载失败' : '共 ' + total + ' 条' }), _jsxs("span", { className: "qiqb-inbox-unread-summary", children: ["\u672A\u8BFB", ' ', _jsx("strong", { "aria-live": "polite", children: unreadCount === undefined ? '—' : unreadCount })] }), _jsx(Button, { size: "small", icon: _jsx(ReloadOutlined, {}), loading: loading || countLoading, onClick: refresh, children: "\u5237\u65B0" })] })] }), _jsxs("div", { className: "qiqb-inbox-layout", children: [_jsxs("section", { className: "qiqb-inbox-list", "aria-label": "\u6D88\u606F\u5217\u8868", "aria-busy": loading, children: [_jsx("div", { className: "qiqb-inbox-list-body", children: loading ? (_jsx("div", { className: "qiqb-inbox-list-skeleton", children: [0, 1, 2].map((key) => (_jsx(Skeleton, { active: true, title: true, paragraph: { rows: 2 } }, key))) })) : listFailed ? (_jsxs("div", { className: "qiqb-message-state", children: [_jsx("span", { className: "qiqb-message-state-icon", children: _jsx(InboxOutlined, {}) }), _jsx("h3", { children: "\u6D88\u606F\u52A0\u8F7D\u5931\u8D25" }), _jsx("p", { children: "\u8BF7\u91CD\u65B0\u52A0\u8F7D\u540E\u7EE7\u7EED\u67E5\u770B\u3002" }), _jsx(Button, { onClick: refresh, children: "\u91CD\u65B0\u52A0\u8F7D" })] })) : records.length ? (records.map((record) => (_jsxs("button", { type: "button", className: [
241
249
  'qiqb-inbox-item',
242
250
  receiptId(record) === detailId ? 'is-selected' : '',
243
251
  !record.readAt ? 'is-unread' : '',
244
- ].join(' '), "aria-pressed": receiptId(record) === detailId, onClick: () => void loadDetail(receiptId(record)), children: [_jsxs("span", { className: "qiqb-inbox-item-heading", children: [_jsx("span", { className: "qiqb-inbox-item-topic", children: topicName(record) }), _jsx("time", { children: formatTime(record.createTime, true) })] }), _jsxs("span", { className: "qiqb-inbox-item-title", children: [!record.readAt && (_jsx("span", { className: "qiqb-inbox-unread-dot", "aria-label": "\u672A\u8BFB" })), record.title] }), _jsx("span", { className: "qiqb-inbox-item-preview", children: record.content || '点击查看消息详情' }), _jsxs("span", { className: "qiqb-inbox-item-footer", children: [_jsx("span", { children: record.sourceSystem.toUpperCase() }), _jsx("span", { children: isExpired(record)
252
+ ].join(' '), "aria-pressed": receiptId(record) === detailId, onClick: () => void loadDetail(receiptId(record)), children: [_jsxs("span", { className: "qiqb-inbox-item-heading", children: [_jsxs("span", { className: "qiqb-inbox-item-title-group", children: [_jsxs("span", { className: "qiqb-inbox-item-title", title: record.title, children: [!record.readAt && (_jsx("span", { className: "qiqb-inbox-unread-dot", "aria-label": "\u672A\u8BFB" })), record.title] }), _jsx("span", { className: "qiqb-inbox-item-topic", title: topicName(record), children: topicName(record) })] }), _jsx("time", { children: formatTime(record.createTime, true) })] }), _jsx("span", { className: "qiqb-inbox-item-preview", children: record.content || '点击查看消息详情' }), _jsxs("span", { className: "qiqb-inbox-item-footer", children: [_jsxs("span", { className: "qiqb-inbox-item-meta", children: [messageLevelTag(record), _jsx("span", { className: "qiqb-inbox-item-source", children: record.sourceSystem.toUpperCase() }), record.businessId && (_jsx("span", { className: "qiqb-inbox-item-business", title: '业务编号:' + record.businessId, children: record.businessId }))] }), _jsx("span", { className: "qiqb-inbox-item-state", children: isExpired(record)
245
253
  ? '已过期'
246
254
  : record.readAt
247
255
  ? '已读'
@@ -1,30 +1,75 @@
1
+ /* 收件箱单独收紧页头,其他消息管理页面继续使用领域默认间距。 */
2
+ .qiqb-inbox-workspace {
3
+ .qiqb-message-heading {
4
+ gap: 12px;
5
+ margin-bottom: 12px;
6
+ }
7
+
8
+ .qiqb-message-heading-main {
9
+ gap: 10px;
10
+
11
+ h1 {
12
+ font-size: 20px;
13
+ }
14
+
15
+ p {
16
+ margin-top: 0;
17
+ font-size: 12px;
18
+ }
19
+ }
20
+
21
+ .qiqb-message-heading-icon {
22
+ flex-basis: 36px;
23
+ width: 36px;
24
+ height: 36px;
25
+ border-radius: 10px;
26
+ font-size: 18px;
27
+ }
28
+ }
29
+
1
30
  .qiqb-message {
2
- .qiqb-inbox-unread-summary {
31
+ .qiqb-inbox-toolbar {
32
+ gap: 10px 16px;
33
+ padding: 10px 16px;
34
+ }
35
+
36
+ .qiqb-inbox-filters,
37
+ .qiqb-inbox-toolbar-summary {
3
38
  display: flex;
4
39
  align-items: center;
5
- gap: 8px;
40
+ flex-wrap: wrap;
41
+ gap: 10px;
42
+ min-width: 0;
43
+ }
44
+
45
+ .qiqb-inbox-toolbar-summary {
46
+ margin-left: auto;
47
+ }
48
+
49
+ .qiqb-inbox-unread-summary {
50
+ display: inline-flex;
51
+ align-items: center;
52
+ gap: 6px;
6
53
  color: var(--message-muted);
7
- font-size: 13px;
54
+ font-size: 12px;
8
55
 
9
56
  strong {
10
- display: inline-flex;
11
- align-items: center;
12
- justify-content: center;
13
- min-width: 30px;
14
- height: 28px;
15
- padding: 0 8px;
57
+ min-width: 22px;
58
+ padding: 1px 6px;
16
59
  color: var(--message-primary);
17
60
  background: var(--message-primary-bg);
18
- border-radius: 8px;
19
- font-size: 15px;
61
+ border-radius: 4px;
62
+ font-weight: 500;
20
63
  font-variant-numeric: tabular-nums;
64
+ text-align: center;
21
65
  }
22
66
  }
23
67
 
24
68
  .qiqb-inbox-layout {
25
69
  display: grid;
26
- grid-template-columns: minmax(290px, 36%) minmax(0, 1fr);
27
- height: clamp(520px, calc(100vh - 270px), 820px);
70
+ /* 宽屏限制摘要列宽,把主要空间留给正文;小桌面仍保证标题可读。 */
71
+ grid-template-columns: minmax(300px, min(38%, 480px)) minmax(0, 1fr);
72
+ height: clamp(400px, calc(100vh - 216px), 780px);
28
73
  }
29
74
 
30
75
  .qiqb-inbox-list {
@@ -35,17 +80,6 @@
35
80
  border-right: 1px solid var(--message-border);
36
81
  }
37
82
 
38
- .qiqb-inbox-list-heading {
39
- display: flex;
40
- flex-shrink: 0;
41
- justify-content: space-between;
42
- gap: 12px;
43
- padding: 15px 20px;
44
- font-size: 13px;
45
- font-weight: 500;
46
- border-bottom: 1px solid var(--message-border);
47
- }
48
-
49
83
  .qiqb-inbox-list-body {
50
84
  flex: 1;
51
85
  min-height: 0;
@@ -54,10 +88,10 @@
54
88
  }
55
89
 
56
90
  .qiqb-inbox-list-skeleton {
57
- padding: 20px;
91
+ padding: 16px;
58
92
 
59
93
  > div + div {
60
- margin-top: 26px;
94
+ margin-top: 20px;
61
95
  }
62
96
  }
63
97
 
@@ -66,8 +100,8 @@
66
100
  width: 100%;
67
101
  min-width: 0;
68
102
  flex-direction: column;
69
- gap: 8px;
70
- padding: 18px 20px;
103
+ gap: 5px;
104
+ padding: 11px 16px 11px 13px;
71
105
  color: var(--message-text);
72
106
  background: transparent;
73
107
  border: 0;
@@ -103,28 +137,35 @@
103
137
  align-items: center;
104
138
  justify-content: space-between;
105
139
  gap: 12px;
140
+ min-width: 0;
106
141
  color: var(--message-muted);
107
- font-size: 11px;
108
- line-height: 1.6;
142
+ font-size: 12px;
143
+ line-height: 20px;
109
144
 
110
145
  time {
111
146
  flex-shrink: 0;
147
+ font-size: 11px;
112
148
  font-variant-numeric: tabular-nums;
113
149
  }
114
150
  }
115
151
 
116
- .qiqb-inbox-item-topic {
152
+ .qiqb-inbox-item-title-group {
153
+ display: flex;
154
+ flex: 1;
155
+ align-items: baseline;
156
+ gap: 8px;
157
+ min-width: 0;
117
158
  overflow: hidden;
118
- color: var(--message-primary);
119
- text-overflow: ellipsis;
120
- white-space: nowrap;
121
159
  }
122
160
 
123
161
  .qiqb-inbox-item-title {
124
162
  display: block;
163
+ flex: 0 1 auto;
164
+ min-width: 0;
125
165
  overflow: hidden;
166
+ color: var(--message-text);
126
167
  font-size: 14px;
127
- line-height: 1.6;
168
+ line-height: 22px;
128
169
  text-overflow: ellipsis;
129
170
  white-space: nowrap;
130
171
  }
@@ -139,27 +180,79 @@
139
180
  }
140
181
 
141
182
  .qiqb-inbox-item-preview {
142
- display: -webkit-box;
183
+ display: block;
143
184
  overflow: hidden;
144
185
  color: var(--message-muted);
186
+ font-size: 13px;
187
+ line-height: 20px;
188
+ text-overflow: ellipsis;
189
+ white-space: nowrap;
190
+ }
191
+
192
+ /* 级别、来源与编号共享一行;长业务字段只在列表省略,详情保留完整值。 */
193
+ .qiqb-inbox-item-meta {
194
+ display: flex;
195
+ flex: 1;
196
+ align-items: center;
197
+ gap: 8px;
198
+ min-width: 0;
199
+ overflow: hidden;
200
+
201
+ .ant-tag {
202
+ flex-shrink: 0;
203
+ margin: 0;
204
+ padding-inline: 4px;
205
+ font-size: 11px;
206
+ line-height: 18px;
207
+ }
208
+ }
209
+
210
+ .qiqb-inbox-item-topic,
211
+ .qiqb-inbox-item-source,
212
+ .qiqb-inbox-item-business {
213
+ min-width: 0;
214
+ overflow: hidden;
215
+ text-overflow: ellipsis;
216
+ white-space: nowrap;
217
+ }
218
+
219
+ .qiqb-inbox-item-topic {
220
+ /* 附加主题最多占标题区域约三分之一,避免长主题挤掉消息标题。 */
221
+ flex: 0 0 auto;
222
+ max-width: 35%;
223
+ color: var(--message-muted);
145
224
  font-size: 12px;
146
- line-height: 1.8;
147
- overflow-wrap: anywhere;
148
- -webkit-line-clamp: 2;
149
- -webkit-box-orient: vertical;
150
225
  }
151
226
 
152
- .qiqb-inbox-item-footer {
153
- margin-top: 2px;
154
- font-size: 10px;
155
- letter-spacing: 0.3px;
227
+ .qiqb-inbox-item-source,
228
+ .qiqb-inbox-item-business {
229
+ padding-left: 8px;
230
+ border-left: 1px solid var(--message-border);
231
+ line-height: 14px;
232
+ }
233
+
234
+ .qiqb-inbox-item-source {
235
+ /* 编号过长时仍保留来源系统,方便识别消息来自哪个业务。 */
236
+ flex-shrink: 0;
237
+ max-width: 28%;
238
+
239
+ /* 普通消息没有级别标签,来源位于首项时不显示多余的分隔线。 */
240
+ &:first-child {
241
+ padding-left: 0;
242
+ border-left: 0;
243
+ }
244
+ }
245
+
246
+ .qiqb-inbox-item-state {
247
+ flex-shrink: 0;
248
+ font-size: 11px;
156
249
  }
157
250
 
158
251
  .qiqb-inbox-pagination {
159
252
  display: flex;
160
253
  flex-shrink: 0;
161
254
  justify-content: center;
162
- padding: 14px 16px;
255
+ padding: 10px 12px;
163
256
  border-top: 1px solid var(--message-border);
164
257
  }
165
258
 
@@ -168,58 +261,89 @@
168
261
  min-width: 0;
169
262
  min-height: 0;
170
263
  flex-direction: column;
264
+ /* 标题、主题和正文共同滚动,长标题不会挤掉正文的阅读空间。 */
265
+ overflow: auto;
171
266
  background: var(--message-surface);
267
+ scrollbar-width: thin;
172
268
  }
173
269
 
174
270
  .qiqb-inbox-reader-top {
175
- display: flex;
176
271
  flex-shrink: 0;
177
- align-items: center;
178
- justify-content: space-between;
179
- flex-wrap: wrap;
180
- gap: 12px;
181
- padding: 18px 28px;
272
+ padding: 16px 22px;
182
273
  border-bottom: 1px solid var(--message-border);
183
274
 
184
275
  .ant-tag {
276
+ max-width: 100%;
185
277
  margin-inline-end: 0;
278
+ white-space: normal;
279
+ overflow-wrap: anywhere;
186
280
  }
187
281
  }
188
282
 
189
- .qiqb-inbox-read-state {
190
- display: inline-flex;
283
+ .qiqb-inbox-reader-heading,
284
+ .qiqb-inbox-reader-info {
285
+ display: flex;
191
286
  align-items: center;
192
- gap: 6px;
287
+ justify-content: space-between;
288
+ flex-wrap: wrap;
289
+ gap: 8px 12px;
290
+ min-width: 0;
291
+ }
292
+
293
+ .qiqb-inbox-reader-title {
294
+ display: block;
295
+ flex: 1;
296
+ min-width: 160px;
297
+ margin: 0;
298
+ color: var(--message-text);
299
+ font-size: 18px;
300
+ font-weight: 600;
301
+ line-height: 1.5;
302
+ overflow-wrap: anywhere;
303
+ }
304
+
305
+ .qiqb-inbox-reader-topic {
306
+ margin-left: 10px;
193
307
  color: var(--message-muted);
194
308
  font-size: 12px;
309
+ font-weight: 400;
195
310
  }
196
311
 
197
- .qiqb-inbox-reader-body {
198
- flex: 1;
199
- min-height: 0;
200
- overflow: auto;
201
- padding: 28px 32px;
312
+ .qiqb-inbox-reader-actions {
313
+ flex-shrink: 0;
314
+ }
202
315
 
203
- h2 {
204
- margin: 0;
205
- font-size: 22px;
206
- font-weight: 600;
207
- line-height: 1.6;
316
+ .qiqb-inbox-reader-info {
317
+ margin-top: 8px;
318
+ color: var(--message-muted);
319
+ font-size: 12px;
320
+ line-height: 22px;
321
+
322
+ > .ant-space {
323
+ flex: 1;
324
+ min-width: 0;
208
325
  overflow-wrap: anywhere;
209
326
  }
210
327
  }
211
328
 
212
- .qiqb-inbox-reader-time {
213
- margin-top: 10px;
329
+ .qiqb-inbox-read-state {
330
+ display: inline-flex;
331
+ align-items: center;
332
+ flex-shrink: 0;
333
+ gap: 6px;
214
334
  color: var(--message-muted);
215
335
  font-size: 12px;
216
336
  }
217
337
 
338
+ .qiqb-inbox-reader-body {
339
+ flex: 1;
340
+ flex-shrink: 0;
341
+ padding: 20px 22px;
342
+ }
343
+
218
344
  .qiqb-inbox-message-content {
219
- min-height: 160px;
220
- margin: 30px 0;
221
345
  font-size: 14px;
222
- line-height: 2;
346
+ line-height: 1.8;
223
347
  white-space: pre-wrap;
224
348
  overflow-wrap: anywhere;
225
349
  }
@@ -227,40 +351,58 @@
227
351
  .qiqb-inbox-detail-meta {
228
352
  display: grid;
229
353
  grid-template-columns: repeat(2, minmax(0, 1fr));
230
- gap: 18px 24px;
231
- margin: 0;
232
- padding: 20px;
233
- background: var(--message-fill);
234
- border-radius: 8px;
354
+ gap: 10px 24px;
355
+ margin: 20px 0 0;
356
+ padding-top: 16px;
357
+ border-top: 1px solid var(--message-border);
235
358
  font-size: 12px;
359
+ line-height: 20px;
360
+
361
+ > div {
362
+ display: flex;
363
+ gap: 12px;
364
+ min-width: 0;
365
+ }
236
366
 
237
367
  dt {
238
- margin-bottom: 6px;
368
+ flex-shrink: 0;
239
369
  color: var(--message-muted);
240
370
  }
241
371
 
242
372
  dd {
373
+ min-width: 0;
243
374
  margin: 0;
375
+ color: var(--message-text);
244
376
  overflow-wrap: anywhere;
245
377
  }
246
378
  }
247
379
 
248
- .qiqb-inbox-reader-footer {
249
- flex-shrink: 0;
250
- padding: 18px 32px;
251
- border-top: 1px solid var(--message-border);
252
- }
253
-
254
380
  .qiqb-inbox-reader-placeholder {
255
381
  flex: 1;
256
- min-height: 500px;
382
+ min-height: 0;
383
+ }
384
+
385
+ @media (max-width: 991px) {
386
+ .qiqb-inbox-detail-meta {
387
+ grid-template-columns: minmax(0, 1fr);
388
+ }
257
389
  }
258
390
 
259
391
  @media (max-width: 767px) {
392
+ .qiqb-inbox-filters {
393
+ width: 100%;
394
+
395
+ .qiqb-message-filter-select {
396
+ flex: 1;
397
+ width: auto;
398
+ min-width: 140px;
399
+ }
400
+ }
401
+
260
402
  .qiqb-inbox-layout {
261
403
  grid-template-columns: minmax(0, 1fr);
262
404
  height: auto;
263
- min-height: 440px;
405
+ min-height: 360px;
264
406
  }
265
407
 
266
408
  .qiqb-inbox-list-body {
@@ -272,16 +414,11 @@
272
414
  }
273
415
 
274
416
  .qiqb-inbox-reader-body {
275
- padding: 24px 20px;
417
+ padding: 16px;
276
418
  }
277
419
 
278
- .qiqb-inbox-reader-top,
279
- .qiqb-inbox-reader-footer {
280
- padding: 16px 20px;
281
- }
282
-
283
- .qiqb-inbox-detail-meta {
284
- grid-template-columns: minmax(0, 1fr);
420
+ .qiqb-inbox-reader-top {
421
+ padding: 14px 16px;
285
422
  }
286
423
  }
287
424
 
@@ -3,7 +3,7 @@ import { EyeOutlined, PlusOutlined, SyncOutlined } from '@ant-design/icons';
3
3
  import { PageContainer, ProTable, } from '@ant-design/pro-components';
4
4
  import { Alert, Button, Col, Form, Input, Modal, Popconfirm, Row, Select, Space, Switch, Tag, Typography, message, } from 'antd';
5
5
  import { useCallback, useEffect, useRef, useState } from 'react';
6
- import { useAccess } from '../../runtime/index.js';
6
+ import { getMessageDomainRuntime, useAccess } from '../../runtime/index.js';
7
7
  import { dispatchMessageReminderPreview } from '../../runtime/reminderEvents.js';
8
8
  import { getMessageSubscriptionModes, pageMessageTopics, removeMessageTopic, saveMessageTopic, showMessageError, syncMessageTopicSubscriptions, } from '../../services/MessageController.js';
9
9
  // 两组设置各自定义完整选项,不按级别禁用提醒方式,让业务自由搭配。
@@ -39,6 +39,10 @@ export default function TopicPage() {
39
39
  const mounted = useRef(true);
40
40
  const canSave = access.verifyElementPermission('MessageTopicSaveBtn');
41
41
  const canRemove = access.verifyElementPermission('MessageTopicRemoveBtn');
42
+ const hostSourceSystem = getMessageDomainRuntime().sourceSystem;
43
+ // 沿用后端主题来源的标识格式;隐藏手填后,缺失配置不能误存成权限项目或默认来源。
44
+ const hasHostSource = !!hostSourceSystem &&
45
+ /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(hostSourceSystem);
42
46
  const loadSubscriptionModes = useCallback(async () => {
43
47
  const version = ++modesVersion.current;
44
48
  setModesLoading(true);
@@ -86,6 +90,12 @@ export default function TopicPage() {
86
90
  const save = async () => {
87
91
  if (!canSave || modesLoading || modesFailed)
88
92
  return;
93
+ // 来源由宿主负责提供;编辑仍使用历史来源,避免当前宿主覆盖其它系统的已有主题。
94
+ const sourceSystem = editing ? editing.sourceSystem : hostSourceSystem;
95
+ if (!sourceSystem || (!editing && !hasHostSource)) {
96
+ message.error('当前应用未配置有效的消息来源,请联系管理员。');
97
+ return;
98
+ }
89
99
  // 校验失败留在表单内提示;服务失败保留已输入内容,便于修正后重试。
90
100
  const values = await form.validateFields().catch(() => undefined);
91
101
  if (!values)
@@ -95,6 +105,7 @@ export default function TopicPage() {
95
105
  await saveMessageTopic({
96
106
  ...values,
97
107
  id: editing?.id,
108
+ sourceSystem,
98
109
  reminderMode: values.reminderMode || 'FLOATING',
99
110
  messageLevel: values.messageLevel || 'NORMAL',
100
111
  subscriptionMode: values.subscriptionMode || 'ALL_ACCOUNTS',
@@ -157,7 +168,10 @@ export default function TopicPage() {
157
168
  messageId: previewId,
158
169
  topicCode: values.code?.trim() || 'PREVIEW_TOPIC',
159
170
  topicName,
160
- sourceSystem: values.sourceSystem?.trim() || 'Platform',
171
+ // 预览沿用同一来源;未配置时仅使用示例标签,不会写入后台或充当发布来源。
172
+ sourceSystem: editing
173
+ ? editing.sourceSystem
174
+ : hostSourceSystem || 'Platform',
161
175
  title: `提醒预览 · ${topicName}`,
162
176
  content: `这是一条${messageLevelLabels[messageLevel]}级别的示例消息,采用${reminderModeLabels[reminderMode]}展示。预览不会保存配置、发布消息或改变收件状态。`,
163
177
  createTime: now,
@@ -169,7 +183,6 @@ export default function TopicPage() {
169
183
  const columns = [
170
184
  { title: '主题编码', dataIndex: 'code', copyable: true, width: 190 },
171
185
  { title: '主题名称', dataIndex: 'name', width: 190 },
172
- { title: '来源系统', dataIndex: 'sourceSystem', width: 130 },
173
186
  {
174
187
  title: '提醒方式',
175
188
  dataIndex: 'reminderMode',
@@ -229,11 +242,11 @@ export default function TopicPage() {
229
242
  }, children: _jsx(Button, { size: "small", type: "link", danger: true, loading: removingId === record.id, disabled: syncingId === record.id, children: "\u5220\u9664" }) }))] })),
230
243
  },
231
244
  ];
232
- return (_jsxs(PageContainer, { title: "\u6D88\u606F\u4E3B\u9898", children: [modesFailed && (_jsx(Alert, { type: "error", showIcon: true, message: "\u8BA2\u9605\u6A21\u5F0F\u52A0\u8F7D\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u540E\u4FDD\u5B58\u4E3B\u9898\u3002", action: _jsx(Button, { size: "small", onClick: () => void loadSubscriptionModes(), children: "\u91CD\u8BD5" }) })), _jsx(ProTable, { rowKey: "id", actionRef: actionRef, columns: columns,
245
+ return (_jsxs(PageContainer, { title: "\u6D88\u606F\u4E3B\u9898", children: [canSave && !hasHostSource && (_jsx(Alert, { type: "warning", showIcon: true, message: "\u5F53\u524D\u5E94\u7528\u672A\u914D\u7F6E\u6709\u6548\u7684\u6D88\u606F\u6765\u6E90\uFF0C\u6682\u65F6\u65E0\u6CD5\u65B0\u589E\u4E3B\u9898\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002" })), modesFailed && (_jsx(Alert, { type: "error", showIcon: true, message: "\u8BA2\u9605\u6A21\u5F0F\u52A0\u8F7D\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u540E\u4FDD\u5B58\u4E3B\u9898\u3002", action: _jsx(Button, { size: "small", onClick: () => void loadSubscriptionModes(), children: "\u91CD\u8BD5" }) })), _jsx(ProTable, { rowKey: "id", actionRef: actionRef, columns: columns,
233
246
  // 列表保留主题管理字段,窄屏通过横向滚动展示,避免压缩新增配置的中文标签。
234
- scroll: { x: 1440 }, pagination: { defaultPageSize: 20, showSizeChanger: true }, toolBarRender: () => canSave
247
+ scroll: { x: 1310 }, pagination: { defaultPageSize: 20, showSizeChanger: true }, toolBarRender: () => canSave
235
248
  ? [
236
- _jsx(Button, { type: "primary", icon: _jsx(PlusOutlined, {}), onClick: () => editTopic(), children: "\u65B0\u589E\u4E3B\u9898" }, "create"),
249
+ _jsx(Button, { type: "primary", icon: _jsx(PlusOutlined, {}), disabled: !hasHostSource, onClick: () => editTopic(), children: "\u65B0\u589E\u4E3B\u9898" }, "create"),
237
250
  ]
238
251
  : [], request: async (params) => {
239
252
  try {
@@ -256,13 +269,16 @@ export default function TopicPage() {
256
269
  } }), _jsx(Modal, { title: editing ? '编辑消息主题' : '新增消息主题', open: open, width: 680, onCancel: () => {
257
270
  if (!saving)
258
271
  setOpen(false);
259
- }, onOk: save, confirmLoading: saving, okButtonProps: { disabled: !canSave || modesLoading || modesFailed }, cancelButtonProps: { disabled: saving }, destroyOnHidden: true, children: _jsxs(Form, { form: form, layout: "vertical", children: [_jsx(Form.Item, { name: "code", label: "\u4E3B\u9898\u7F16\u7801", rules: [
272
+ }, onOk: save, confirmLoading: saving, okButtonProps: {
273
+ disabled: !canSave ||
274
+ modesLoading ||
275
+ modesFailed ||
276
+ (!editing && !hasHostSource),
277
+ }, cancelButtonProps: { disabled: saving }, destroyOnHidden: true, children: _jsxs(Form, { form: form, layout: "vertical", children: [_jsx(Form.Item, { name: "code", label: "\u4E3B\u9898\u7F16\u7801", rules: [
260
278
  { required: true, whitespace: true, message: '请输入主题编码' },
261
279
  ], children: _jsx(Input, { disabled: !!editing, placeholder: "\u4F8B\u5982 ERP_APPROVAL_NOTICE", maxLength: 64 }) }), _jsx(Form.Item, { name: "name", label: "\u4E3B\u9898\u540D\u79F0", rules: [
262
280
  { required: true, whitespace: true, message: '请输入主题名称' },
263
- ], children: _jsx(Input, { maxLength: 128 }) }), _jsx(Form.Item, { name: "sourceSystem", label: "\u6765\u6E90\u7CFB\u7EDF", rules: [
264
- { required: true, whitespace: true, message: '请输入来源系统' },
265
- ], children: _jsx(Input, { disabled: !!editing, placeholder: "\u4F8B\u5982 ERP\u3001OA\u3001CRM", maxLength: 64 }) }), _jsx(Form.Item, { name: "enabled", label: "\u542F\u7528", valuePropName: "checked", children: _jsx(Switch, {}) }), _jsx(Form.Item, { name: "subscriptionMode", label: "\u8BA2\u9605\u6A21\u5F0F", extra: "\u5168\u91CF\u8D26\u6237\u8BA2\u9605\u4F1A\u5728\u521B\u5EFA\u4E3B\u9898\u65F6\u7ED1\u5B9A\u6709\u6548\u8D26\u6237\uFF1B\u89D2\u8272\u8BA2\u9605\u7531\u89D2\u8272\u914D\u7F6E\u4E0E\u8D26\u6237\u7ED1\u5B9A\u5173\u7CFB\u786E\u5B9A\u3002\u540C\u6B65\u8BA2\u9605\u53EF\u8865\u9F50\u6211\u7684\u8BA2\u9605\u3002", rules: [{ required: true, message: '请选择订阅模式' }], children: _jsx(Select, { loading: modesLoading, disabled: modesLoading || modesFailed, options: subscriptionModes.map((item) => ({
281
+ ], children: _jsx(Input, { maxLength: 128 }) }), editing && (_jsx(Form.Item, { label: "\u6765\u6E90\u7CFB\u7EDF", children: _jsx(Input, { value: editing.sourceSystem, readOnly: true }) })), _jsx(Form.Item, { name: "enabled", label: "\u542F\u7528", valuePropName: "checked", children: _jsx(Switch, {}) }), _jsx(Form.Item, { name: "subscriptionMode", label: "\u8BA2\u9605\u6A21\u5F0F", extra: "\u5168\u91CF\u8D26\u6237\u8BA2\u9605\u4F1A\u5728\u521B\u5EFA\u4E3B\u9898\u65F6\u7ED1\u5B9A\u6709\u6548\u8D26\u6237\uFF1B\u89D2\u8272\u8BA2\u9605\u7531\u89D2\u8272\u914D\u7F6E\u4E0E\u8D26\u6237\u7ED1\u5B9A\u5173\u7CFB\u786E\u5B9A\u3002\u540C\u6B65\u8BA2\u9605\u53EF\u8865\u9F50\u6211\u7684\u8BA2\u9605\u3002", rules: [{ required: true, message: '请选择订阅模式' }], children: _jsx(Select, { loading: modesLoading, disabled: modesLoading || modesFailed, options: subscriptionModes.map((item) => ({
266
282
  value: item.code,
267
283
  label: item.name,
268
284
  })) }) }), _jsxs(Row, { gutter: 16, children: [_jsx(Col, { xs: 24, sm: 12, children: _jsx(Form.Item, { name: "reminderMode", label: "\u63D0\u9192\u65B9\u5F0F", children: _jsx(Select, { options: Object.entries(reminderModeLabels).map(([value, label]) => ({
@@ -47,6 +47,8 @@ export interface MessageDomainRuntimeAdapter {
47
47
  fieldLabel?: (field: string) => string | undefined;
48
48
  apiPrefix?: string;
49
49
  projectCode?: string;
50
+ /** 宿主创建消息主题的业务来源,与发布接口的 sourceSystem 一致;不由权限项目号推断。 */
51
+ sourceSystem?: string;
50
52
  inboxPath?: string;
51
53
  receiptQueryParam?: string;
52
54
  /** BIP 传入 prokeeper-bip 可沿用原来的 sessionStorage 收件标识去重记录。 */
@@ -10,6 +10,8 @@ let runtime = {
10
10
  };
11
11
  export function configureMessageDomainRuntime(adapter) {
12
12
  const next = { ...runtime, ...adapter };
13
+ // 来源编码保留大小写,后端会严格核对;显式清空时不沿用其它宿主的来源。
14
+ next.sourceSystem = next.sourceSystem?.trim() || undefined;
13
15
  next.apiPrefix = (adapter.apiPrefix ?? runtime.apiPrefix).replace(/\/+$/, '');
14
16
  next.projectCode = adapter.projectCode?.trim() || runtime.projectCode;
15
17
  next.storageNamespace =
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qiqb/message-domain",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "与宿主框架无关的 QIQB 消息主题、订阅、收件箱与全局提醒领域包",
5
5
  "sideEffects": [
6
6
  "**/*.less"
@@ -59,6 +59,7 @@
59
59
  "scripts": {
60
60
  "build": "node scripts/build.mjs",
61
61
  "lint": "tsc -p tsconfig.json --noEmit",
62
+ "prepack": "npm run build",
62
63
  "pack:local": "npm pack --pack-destination /private/tmp",
63
64
  "publish:local": "node ../scripts/publish-platform-domain.mjs --package message-domain --target local",
64
65
  "publish:nexus": "node ../scripts/publish-platform-domain.mjs --package message-domain --target nexus",
@@ -66,6 +67,7 @@
66
67
  "test:reminders": "node scripts/reminder-regression.cjs",
67
68
  "test:routes": "node scripts/routes-entry-regression.cjs",
68
69
  "test:runtime": "node scripts/runtime-regression.cjs",
70
+ "test:topics": "node scripts/topic-regression.cjs",
69
71
  "test:presentation": "node scripts/presentation-regression.cjs",
70
72
  "test:display": "node scripts/display-regression.cjs",
71
73
  "test:navigation": "node scripts/navigation-regression.cjs",
@@ -91,7 +93,6 @@
91
93
  "react-dom": ">=18.0.0 <20.0.0"
92
94
  },
93
95
  "publishConfig": {
94
- "access": "public",
95
- "registry": "https://registry.npmjs.org/"
96
+ "access": "public"
96
97
  }
97
98
  }