@hkyhy/marsun-components-core 0.1.124 → 0.1.126

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.
@@ -1 +1 @@
1
- {"version":3,"file":"InboxBell.js","sources":["../../../../../src/components/Tools/Inbox/InboxBell/InboxBell.tsx"],"sourcesContent":["import { Badge, Button, Drawer, Space, Tag, message } from 'antd';\nimport classNames from 'classnames';\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Empty } from '@/components/Empty';\nimport { Bell } from '@/components/Icons';\nimport { PageSpin } from '@/components/Layout';\nimport { SegmentedRadio } from '@/components/SegmentedRadio';\nimport { StateBar } from '@/components/StateBar';\nimport { sanitizeInboxHtml } from '../sanitizeInboxHtml';\nimport { INBOX_BADGE_REFRESH_EVENT } from '../requestInboxBadgeRefresh';\nimport styles from './style.module.scss';\n\nexport type InboxBellMessageType = 'alert' | 'action' | 'remind' | string;\n\nexport type InboxBellItem = {\n id: string;\n title?: string;\n /** 纯文本摘要(列表兼容) */\n summary?: string;\n /** 已渲染 HTML 正文;空则主摘要位回落 summary */\n bodyHtml?: string | null;\n read?: boolean;\n messageType?: InboxBellMessageType;\n href?: string;\n createdAt?: string;\n level?: string;\n};\n\nexport type InboxBellListResult = {\n itemList: InboxBellItem[];\n total?: number;\n unreadTotal?: number;\n unreadByMessageType?: Partial<Record<string, number>>;\n};\n\nexport type InboxBellListParams = {\n unreadOnly?: boolean;\n readOnly?: boolean;\n messageType?: InboxBellMessageType;\n currentPage?: number;\n pageSize?: number;\n};\n\nexport type InboxBellProps = {\n /** 拉取站内信(业务注入;须带 JWT 身份,禁止无身份全表) */\n fetchInbox: (params: InboxBellListParams) => Promise<InboxBellListResult>;\n /** 标记已读 */\n markRead: (id: string) => Promise<void | InboxBellItem>;\n /** 点击条目:默认用 window.location / 业务 navigate */\n onNavigate?: (href: string, item: InboxBellItem) => void;\n /**\n * 轮询未读角标(ms)。默认 `0`(关定时);`>0` 才 setInterval。\n * 角标另由:挂载首刷、`locationKey`、focus/visibility、`requestInboxBadgeRefresh` 触发。\n */\n pollMs?: number;\n /**\n * 路由/页面身份;变化时刷新角标(如 React Router `location.pathname`)。\n * 整页加载靠挂载首刷,不必另传。\n */\n locationKey?: string | number;\n pageSize?: number;\n className?: string;\n /** Drawer 标题 */\n title?: string;\n};\n\nexport type InboxBellHandle = {\n refreshBadge: () => Promise<void>;\n};\n\nconst TYPE_TABS: Array<{ key: string; label: string }> = [\n { key: '', label: '全部' },\n { key: 'alert', label: '预警' },\n { key: 'action', label: '行动' },\n { key: 'remind', label: '提醒' },\n];\n\nconst TYPE_TAG_LABEL: Record<string, string> = {\n alert: '预警',\n action: '行动',\n remind: '提醒',\n};\n\nconst FOCUS_DEBOUNCE_MS = 300;\n\nfunction messageTypeLabel(raw?: string): string {\n const key = String(raw || '')\n .trim()\n .toLowerCase();\n if (!key) return '';\n return TYPE_TAG_LABEL[key] || key;\n}\n\n/**\n * 通用站内信铃铛:列表 / 已读 / Tab / 角标。\n * 不含认领、行动等业务动作;由注入的 fetchInbox / markRead / onNavigate 对接消息服务。\n * 默认不定时轮询;有消息侧靠业务回调 / 路由 / 焦点再拉角标(真·SSE push 他窗)。\n */\nconst InboxBell = forwardRef<InboxBellHandle, InboxBellProps>(function InboxBell(\n {\n fetchInbox,\n markRead,\n onNavigate,\n pollMs = 0,\n locationKey,\n pageSize = 50,\n className,\n title = '站内信',\n },\n ref,\n) {\n const [open, setOpen] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [items, setItems] = useState<InboxBellItem[]>([]);\n const [unreadTotal, setUnreadTotal] = useState(0);\n const [unreadByType, setUnreadByType] = useState<Partial<Record<string, number>>>({});\n const [messageType, setMessageType] = useState<string>('');\n const [readFilter, setReadFilter] = useState<'all' | 'unread' | 'read'>('all');\n const focusDebounceRef = useRef<number | null>(null);\n const locationKeyPrimedRef = useRef(false);\n\n const load = useCallback(async () => {\n setLoading(true);\n setError('');\n try {\n const res = await fetchInbox({\n currentPage: 1,\n pageSize,\n messageType: messageType || undefined,\n unreadOnly: readFilter === 'unread' || undefined,\n readOnly: readFilter === 'read' || undefined,\n });\n setItems(res?.itemList || []);\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch (e) {\n setItems([]);\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setLoading(false);\n }\n }, [fetchInbox, messageType, pageSize, readFilter]);\n\n const refreshBadge = useCallback(async () => {\n try {\n const res = await fetchInbox({ currentPage: 1, pageSize: 1 });\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch {\n /* 角标失败不打断 UI */\n }\n }, [fetchInbox]);\n\n useImperativeHandle(ref, () => ({ refreshBadge }), [refreshBadge]);\n\n useEffect(() => {\n void refreshBadge();\n }, [refreshBadge]);\n\n useEffect(() => {\n if (locationKey === undefined) return;\n // 挂载首刷已由 refreshBadge effect 覆盖;仅后续路由变化再拉\n if (!locationKeyPrimedRef.current) {\n locationKeyPrimedRef.current = true;\n return;\n }\n void refreshBadge();\n }, [locationKey, refreshBadge]);\n\n useEffect(() => {\n if (pollMs <= 0) return undefined;\n const t = window.setInterval(() => {\n void refreshBadge();\n }, pollMs);\n return () => window.clearInterval(t);\n }, [pollMs, refreshBadge]);\n\n useEffect(() => {\n const schedule = () => {\n if (focusDebounceRef.current != null) {\n window.clearTimeout(focusDebounceRef.current);\n }\n focusDebounceRef.current = window.setTimeout(() => {\n focusDebounceRef.current = null;\n void refreshBadge();\n }, FOCUS_DEBOUNCE_MS);\n };\n\n const onVisibility = () => {\n if (document.visibilityState === 'visible') schedule();\n };\n\n window.addEventListener('focus', schedule);\n document.addEventListener('visibilitychange', onVisibility);\n return () => {\n window.removeEventListener('focus', schedule);\n document.removeEventListener('visibilitychange', onVisibility);\n if (focusDebounceRef.current != null) {\n window.clearTimeout(focusDebounceRef.current);\n focusDebounceRef.current = null;\n }\n };\n }, [refreshBadge]);\n\n useEffect(() => {\n const onExternal = () => {\n void refreshBadge();\n };\n window.addEventListener(INBOX_BADGE_REFRESH_EVENT, onExternal);\n return () => window.removeEventListener(INBOX_BADGE_REFRESH_EVENT, onExternal);\n }, [refreshBadge]);\n\n useEffect(() => {\n if (open) void load();\n }, [open, load]);\n\n const typeTabOptions = useMemo(\n () =>\n TYPE_TABS.map((t) => {\n const n = t.key ? unreadByType[t.key] || 0 : unreadTotal;\n return {\n key: t.key || 'all',\n label: n > 0 ? `${t.label} (${n})` : t.label,\n };\n }),\n [unreadByType, unreadTotal],\n );\n\n const handleOpenItem = async (item: InboxBellItem) => {\n if (!item.read) {\n try {\n await markRead(item.id);\n setItems((prev) => prev.map((x) => (x.id === item.id ? { ...x, read: true } : x)));\n setUnreadTotal((n) => Math.max(0, n - 1));\n } catch (e) {\n message.error(e instanceof Error ? e.message : '标记已读失败');\n return;\n }\n }\n const href = String(item.href || '').trim();\n if (!href) return;\n if (onNavigate) {\n onNavigate(href, item);\n setOpen(false);\n return;\n }\n if (href.startsWith('http://') || href.startsWith('https://')) {\n window.open(href, '_blank', 'noopener,noreferrer');\n } else {\n window.location.assign(href);\n }\n setOpen(false);\n };\n\n return (\n <div className={classNames(styles.bellWrap, className)}>\n <Badge count={unreadTotal} size=\"small\" overflowCount={99} offset={[-4, 4]}>\n <Button\n type=\"text\"\n className={styles.bellBtn}\n icon={<Bell size={16} aria-hidden />}\n aria-label={unreadTotal > 0 ? `站内信,${unreadTotal} 条未读` : '站内信'}\n onClick={() => setOpen(true)}\n />\n </Badge>\n <Drawer\n title={title}\n open={open}\n onClose={() => setOpen(false)}\n size={420}\n destroyOnClose={false}\n className={styles.drawer}\n styles={{\n header: { padding: '12px 16px' },\n body: { padding: '12px 16px' },\n }}\n >\n <StateBar\n className={styles.typeTabs}\n size=\"small\"\n activeKey={messageType || 'all'}\n onChange={(k) => setMessageType(k === 'all' ? '' : k)}\n stateOption={typeTabOptions}\n isInner\n />\n <div className={styles.filterRow}>\n <SegmentedRadio<'all' | 'unread' | 'read'>\n size=\"small\"\n value={readFilter}\n onChange={(v) => setReadFilter(v)}\n options={[\n { value: 'all', label: '全部' },\n { value: 'unread', label: '未读' },\n { value: 'read', label: '已读' },\n ]}\n />\n </div>\n {error ? <p className={styles.error}>{error}</p> : null}\n <PageSpin spinning={loading}>\n {!loading && !error && items.length === 0 ? (\n <Empty description=\"暂无站内信\" />\n ) : (\n <ul className={styles.list}>\n {items.map((item) => (\n <li key={item.id}>\n <button\n type=\"button\"\n className={classNames(styles.item, !item.read && styles.itemUnread)}\n onClick={() => void handleOpenItem(item)}\n >\n <Space orientation=\"vertical\" size={2} style={{ width: '100%' }}>\n <span className={styles.itemTitle}>{item.title || '(无标题)'}</span>\n {(() => {\n const safeHtml = sanitizeInboxHtml(item.bodyHtml);\n if (safeHtml) {\n return (\n <div\n className={styles.itemBodyHtml}\n dangerouslySetInnerHTML={{ __html: safeHtml }}\n />\n );\n }\n return item.summary ? (\n <span className={styles.itemSummary}>{item.summary}</span>\n ) : null;\n })()}\n {(() => {\n const typeLabel = messageTypeLabel(item.messageType);\n return (\n <span className={styles.itemMeta}>\n {typeLabel ? <Tag className={styles.typeTag}>{typeLabel}</Tag> : null}\n {item.createdAt || (typeLabel ? '' : '—')}\n </span>\n );\n })()}\n </Space>\n </button>\n </li>\n ))}\n </ul>\n )}\n </PageSpin>\n </Drawer>\n </div>\n );\n});\n\nexport default InboxBell;\n"],"names":["TYPE_TABS","TYPE_TAG_LABEL","FOCUS_DEBOUNCE_MS","messageTypeLabel","raw","key","InboxBell","forwardRef","fetchInbox","markRead","onNavigate","pollMs","locationKey","pageSize","className","title","ref","open","setOpen","useState","loading","setLoading","error","setError","items","setItems","unreadTotal","setUnreadTotal","unreadByType","setUnreadByType","messageType","setMessageType","readFilter","setReadFilter","focusDebounceRef","useRef","locationKeyPrimedRef","load","useCallback","res","refreshBadge","useImperativeHandle","useEffect","t","schedule","onVisibility","onExternal","INBOX_BADGE_REFRESH_EVENT","typeTabOptions","useMemo","n","handleOpenItem","item","prev","x","e","message","href","classNames","styles","jsx","Badge","Button","Bell","jsxs","Drawer","StateBar","k","SegmentedRadio","v","PageSpin","Empty","Space","safeHtml","sanitizeInboxHtml","typeLabel","Tag"],"mappings":"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"}
1
+ {"version":3,"file":"InboxBell.js","sources":["../../../../../src/components/Tools/Inbox/InboxBell/InboxBell.tsx"],"sourcesContent":["import { Badge, Button, Checkbox, Drawer, Space, message, notification } from 'antd';\nimport classNames from 'classnames';\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type UIEvent,\n} from 'react';\nimport { Empty } from '@/components/Empty';\nimport { Bell } from '@/components/Icons';\nimport { PageSpin } from '@/components/Layout';\nimport { SegmentedRadio } from '@/components/SegmentedRadio';\nimport { StateBar } from '@/components/StateBar';\nimport { SEMANTIC_COLORS, SemanticTag } from '@/components/Tag';\nimport { VirtualScrollbar } from '@/components/VirtualScrollbar';\nimport { sanitizeInboxHtml } from '../sanitizeInboxHtml';\nimport { INBOX_BADGE_REFRESH_EVENT } from '../requestInboxBadgeRefresh';\nimport { emphasizeQuoted } from './emphasizeQuoted';\nimport {\n filterInboxActionsForHost,\n isInboxButtonDriven,\n resolveInboxItemActions,\n type InboxItemActionKind,\n type InboxItemQuickAction,\n} from './inboxItemActions';\nimport {\n loadInboxToastPrefs,\n saveInboxToastPrefs,\n shouldToastForMessageType,\n type InboxToastPrefs,\n} from './toastPrefs';\nimport styles from './style.module.scss';\n\nexport type InboxBellMessageType = 'alert' | 'action' | 'remind' | string;\n\nexport type InboxBellItem = {\n id: string;\n title?: string;\n /** 纯文本摘要(列表兼容) */\n summary?: string;\n /** 已渲染 HTML 正文;空则主摘要位回落 summary */\n bodyHtml?: string | null;\n read?: boolean;\n messageType?: InboxBellMessageType;\n href?: string;\n createdAt?: string;\n level?: string;\n /** 级别展示名(业务仓从已有维表/工具函数填;空则回落 level) */\n levelLabel?: string;\n /**\n * 级别 Tag 色:业务仓传入预警级别设置色(如 QA `ALERT_LEVEL_COLORS.*.accent`)。\n * 支持 SemanticColor 键或 `#hex`;core 不自造级别色表。\n */\n levelColor?: string;\n category?: string;\n scene?: string;\n eventKey?: string;\n categoryLabel?: string;\n alertId?: string | null;\n actionId?: string | null;\n claimed?: boolean;\n started?: boolean;\n /** 行动当前状态(enrich / contextJson);终态时底栏只保留查看任务 */\n actionStatus?: string;\n factory?: string;\n variety?: string;\n metric?: string;\n /** 业务日/月份(如 2026-07-31);预警深链 date 用 */\n month?: string;\n};\n\nexport type InboxBellListResult = {\n /** 分页列表(Marsun list-api 唯一数组名) */\n pageData: InboxBellItem[];\n total?: number;\n unreadTotal?: number;\n unreadByMessageType?: Partial<Record<string, number>>;\n};\n\nexport type InboxBellListParams = {\n unreadOnly?: boolean;\n readOnly?: boolean;\n messageType?: InboxBellMessageType;\n currentPage?: number;\n pageSize?: number;\n};\n\nexport type InboxBellProps = {\n /** 拉取站内信(业务注入;须带 JWT 身份,禁止无身份全表) */\n fetchInbox: (params: InboxBellListParams) => Promise<InboxBellListResult>;\n /** 标记已读 */\n markRead: (id: string) => Promise<void | InboxBellItem>;\n /** 点击条目:默认用 window.location / 业务 navigate */\n onNavigate?: (href: string, item: InboxBellItem) => void;\n /**\n * 轮询未读角标(ms)。默认 `0`(关定时);`>0` 才 setInterval。\n * 角标另由:挂载首刷、`locationKey`、focus/visibility、`requestInboxBadgeRefresh` 触发。\n */\n pollMs?: number;\n /**\n * 路由/页面身份;变化时刷新角标(如 React Router `location.pathname`)。\n * 整页加载靠挂载首刷,不必另传。\n */\n locationKey?: string | number;\n pageSize?: number;\n className?: string;\n /** Drawer 标题 */\n title?: string;\n /**\n * 同源 SSE 路径(默认 `/api/v1/msg-center/inbox/stream`)。\n * 传 `false` 关闭。须配合 `getAccessToken`(EventSource 用 `access_token` 查询参数传 JWT)。\n * 失败回落写后刷新 / 焦点刷新,不定时轮询冒充。\n */\n streamPath?: string | false;\n /** 返回当前 JWT;空则不开 SSE */\n getAccessToken?: () => string | null | undefined;\n /**\n * 卡片底栏动作(认领/去执行/查看等)。不传则底栏按钮一律走 onNavigate / href。\n * 业务仓拦截 claim_alert / start_action;铃铛不解析新建任务。\n */\n onItemAction?: (kind: InboxItemActionKind, item: InboxBellItem) => void | Promise<void>;\n};\n\nexport type InboxBellHandle = {\n refreshBadge: () => Promise<void>;\n};\n\nconst TYPE_TABS: Array<{ key: string; label: string }> = [\n { key: '', label: '全部' },\n { key: 'alert', label: '预警' },\n { key: 'action', label: '行动' },\n { key: 'remind', label: '提醒' },\n];\n\nconst TYPE_TAG_LABEL: Record<string, string> = {\n alert: '预警',\n action: '行动',\n remind: '提醒',\n};\n\nconst FOCUS_DEBOUNCE_MS = 300;\n/** 距底部小于该值时拉下一页 */\nconst LOAD_MORE_GAP_PX = 72;\n\nfunction messageTypeLabel(raw?: string): string {\n const key = String(raw || '')\n .trim()\n .toLowerCase();\n if (!key) return '';\n return TYPE_TAG_LABEL[key] || key;\n}\n\nfunction messageTypeSemanticColor(raw?: string): string {\n const key = String(raw || '')\n .trim()\n .toLowerCase();\n if (key === 'alert') return SEMANTIC_COLORS.DANGER;\n if (key === 'action') return SEMANTIC_COLORS.PRIMARY;\n if (key === 'remind') return SEMANTIC_COLORS.WARNING;\n return SEMANTIC_COLORS.DEFAULT;\n}\n\nfunction itemMetaLine(item: InboxBellItem): string {\n return [item.factory, item.variety, item.metric]\n .map((x) => String(x || '').trim())\n .filter(Boolean)\n .join(' · ');\n}\n\n/** 业务传入色;无则 DEFAULT(禁止在 core 造级别→色平行表) */\nfunction resolveLevelTagColor(raw?: string): string {\n const c = String(raw || '').trim();\n return c || SEMANTIC_COLORS.DEFAULT;\n}\n\ntype BadgePreview = {\n messageType?: string;\n title?: string;\n summary?: string;\n};\n\nfunction parseBadgePreview(raw: string): BadgePreview | null {\n try {\n const data = JSON.parse(raw) as Record<string, unknown>;\n if (!data || typeof data !== 'object') return null;\n const messageType = String(data.messageType || data.message_type || '').trim();\n const title = String(data.title || '').trim();\n const summary = String(data.summary || '').trim();\n if (!messageType && !title && !summary) return null;\n return {\n messageType: messageType || undefined,\n title: title || undefined,\n summary: summary || undefined,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * 通用站内信铃铛:列表 / 已读 / Tab / 角标 / 卡片底栏动作 / 可选 SSE toast。\n * 认领、去执行等业务动作由 `onItemAction` 注入;默认底栏按钮走 onNavigate / href。\n * 默认不定时轮询;有消息侧靠业务回调 / 路由 / 焦点 / 可选 SSE 再拉角标。\n */\nconst InboxBell = forwardRef<InboxBellHandle, InboxBellProps>(function InboxBell(\n {\n fetchInbox,\n markRead,\n onNavigate,\n pollMs = 0,\n locationKey,\n pageSize = 20,\n className,\n title = '站内信',\n streamPath = '/api/v1/msg-center/inbox/stream',\n getAccessToken,\n onItemAction,\n },\n ref,\n) {\n const [open, setOpen] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [items, setItems] = useState<InboxBellItem[]>([]);\n const [unreadTotal, setUnreadTotal] = useState(0);\n const [unreadByType, setUnreadByType] = useState<Partial<Record<string, number>>>({});\n const [messageType, setMessageType] = useState<string>('');\n const [readFilter, setReadFilter] = useState<'all' | 'unread' | 'read'>('all');\n const [toastPrefs, setToastPrefs] = useState<InboxToastPrefs>(() => loadInboxToastPrefs());\n const [loadingMore, setLoadingMore] = useState(false);\n const focusDebounceRef = useRef<number | null>(null);\n const locationKeyPrimedRef = useRef(false);\n const toastPrefsRef = useRef(toastPrefs);\n toastPrefsRef.current = toastPrefs;\n const currentPageRef = useRef(1);\n const loadingMoreRef = useRef(false);\n const hasMoreRef = useRef(false);\n\n const listQuery = useMemo(\n () => ({\n messageType: messageType || undefined,\n unreadOnly: readFilter === 'unread' || undefined,\n readOnly: readFilter === 'read' || undefined,\n }),\n [messageType, readFilter],\n );\n\n const load = useCallback(async () => {\n setLoading(true);\n setError('');\n currentPageRef.current = 1;\n hasMoreRef.current = false;\n try {\n const res = await fetchInbox({\n currentPage: 1,\n pageSize,\n ...listQuery,\n });\n const page = res?.pageData || [];\n const total = typeof res?.total === 'number' ? res.total : page.length;\n setItems(page);\n hasMoreRef.current = page.length > 0 && page.length < total;\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch (e) {\n setItems([]);\n hasMoreRef.current = false;\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setLoading(false);\n }\n }, [fetchInbox, pageSize, listQuery]);\n\n const loadMore = useCallback(async () => {\n if (loadingMoreRef.current || !hasMoreRef.current) return;\n loadingMoreRef.current = true;\n setLoadingMore(true);\n try {\n const next = currentPageRef.current + 1;\n const res = await fetchInbox({\n currentPage: next,\n pageSize,\n ...listQuery,\n });\n const page = res?.pageData || [];\n const total = typeof res?.total === 'number' ? res.total : 0;\n setItems((prev) => {\n const seen = new Set(prev.map((x) => x.id));\n const extra = page.filter((x) => x?.id && !seen.has(x.id));\n const merged = extra.length ? [...prev, ...extra] : prev;\n hasMoreRef.current =\n extra.length > 0 && (total > 0 ? merged.length < total : extra.length >= pageSize);\n return merged;\n });\n if (page.length) currentPageRef.current = next;\n if (typeof res?.unreadTotal === 'number') setUnreadTotal(res.unreadTotal);\n if (res?.unreadByMessageType) setUnreadByType(res.unreadByMessageType);\n } catch {\n hasMoreRef.current = false;\n } finally {\n loadingMoreRef.current = false;\n setLoadingMore(false);\n }\n }, [fetchInbox, pageSize, listQuery]);\n\n const onListScroll = useCallback(\n (e: UIEvent<HTMLDivElement>) => {\n const el = e.currentTarget;\n if (el.scrollHeight - el.scrollTop - el.clientHeight <= LOAD_MORE_GAP_PX) {\n void loadMore();\n }\n },\n [loadMore],\n );\n\n const refreshBadge = useCallback(async () => {\n try {\n // 与列表同 pageSize(禁硬编码 1);角标只消费 unread* 字段\n const res = await fetchInbox({ currentPage: 1, pageSize });\n setUnreadTotal(typeof res?.unreadTotal === 'number' ? res.unreadTotal : 0);\n setUnreadByType(res?.unreadByMessageType || {});\n } catch {\n /* 角标失败不打断 UI */\n }\n }, [fetchInbox, pageSize]);\n\n useImperativeHandle(ref, () => ({ refreshBadge }), [refreshBadge]);\n\n useEffect(() => {\n void refreshBadge();\n }, [refreshBadge]);\n\n useEffect(() => {\n if (locationKey === undefined) return;\n // 挂载首刷已由 refreshBadge effect 覆盖;仅后续路由变化再拉\n if (!locationKeyPrimedRef.current) {\n locationKeyPrimedRef.current = true;\n return;\n }\n void refreshBadge();\n }, [locationKey, refreshBadge]);\n\n useEffect(() => {\n if (pollMs <= 0) return undefined;\n const t = window.setInterval(() => {\n void refreshBadge();\n }, pollMs);\n return () => window.clearInterval(t);\n }, [pollMs, refreshBadge]);\n\n useEffect(() => {\n const schedule = () => {\n if (focusDebounceRef.current != null) {\n window.clearTimeout(focusDebounceRef.current);\n }\n focusDebounceRef.current = window.setTimeout(() => {\n focusDebounceRef.current = null;\n void refreshBadge();\n }, FOCUS_DEBOUNCE_MS);\n };\n\n const onVisibility = () => {\n if (document.visibilityState === 'visible') schedule();\n };\n\n window.addEventListener('focus', schedule);\n document.addEventListener('visibilitychange', onVisibility);\n return () => {\n window.removeEventListener('focus', schedule);\n document.removeEventListener('visibilitychange', onVisibility);\n if (focusDebounceRef.current != null) {\n window.clearTimeout(focusDebounceRef.current);\n focusDebounceRef.current = null;\n }\n };\n }, [refreshBadge]);\n\n useEffect(() => {\n const onExternal = () => {\n void refreshBadge();\n };\n window.addEventListener(INBOX_BADGE_REFRESH_EVENT, onExternal);\n return () => window.removeEventListener(INBOX_BADGE_REFRESH_EVENT, onExternal);\n }, [refreshBadge]);\n\n useEffect(() => {\n if (streamPath === false) return undefined;\n if (typeof getAccessToken !== 'function') return undefined;\n if (typeof window === 'undefined' || typeof EventSource === 'undefined') return undefined;\n\n const token = String(getAccessToken() || '').trim();\n if (!token) return undefined;\n\n const base = String(streamPath || '/api/v1/msg-center/inbox/stream').trim();\n const url = new URL(base, window.location.origin);\n url.searchParams.set('access_token', token);\n\n let es: EventSource;\n try {\n es = new EventSource(url.toString());\n } catch {\n return undefined;\n }\n\n const onBadge = (ev: Event) => {\n void refreshBadge();\n const msgEv = ev as MessageEvent;\n const preview = typeof msgEv?.data === 'string' ? parseBadgePreview(msgEv.data) : null;\n if (!preview) return;\n if (!shouldToastForMessageType(toastPrefsRef.current, preview.messageType)) return;\n const toastTitle = preview.title || '新站内信';\n const toastDesc = preview.summary || '';\n const typeLabel = messageTypeLabel(preview.messageType);\n const openDrawer = () => {\n notification.destroy();\n setOpen(true);\n };\n const toastKey = `inbox-badge-${preview.messageType || 'msg'}-${Date.now()}`;\n notification.open({\n key: toastKey,\n className: classNames('marsun-inbox-toast', styles.toastNotice),\n closable: true,\n title: (\n <div className={styles.toastHead}>\n <span className={styles.toastTitle}>{emphasizeQuoted(toastTitle)}</span>\n {typeLabel ? (\n <SemanticTag\n color={messageTypeSemanticColor(preview.messageType)}\n className={styles.typeTag}\n >\n {typeLabel}\n </SemanticTag>\n ) : null}\n </div>\n ),\n message: (\n <div className={styles.toastHead}>\n <span className={styles.toastTitle}>{emphasizeQuoted(toastTitle)}</span>\n {typeLabel ? (\n <SemanticTag\n color={messageTypeSemanticColor(preview.messageType)}\n className={styles.typeTag}\n >\n {typeLabel}\n </SemanticTag>\n ) : null}\n </div>\n ),\n description: (\n <div className={styles.toastBody}>\n {toastDesc ? (\n <div className={styles.toastDesc}>{emphasizeQuoted(toastDesc)}</div>\n ) : null}\n <div className={styles.toastActions}>\n <Button\n type=\"primary\"\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n openDrawer();\n }}\n >\n 查看\n </Button>\n </div>\n </div>\n ),\n placement: 'topRight',\n duration: 6,\n onClick: openDrawer,\n });\n };\n es.addEventListener('badge', onBadge);\n es.addEventListener('inbox', onBadge);\n // 失败回落写后/焦点刷新;关连接防 EventSource 自动重连刷屏\n es.onerror = () => {\n es.close();\n };\n\n return () => {\n es.removeEventListener('badge', onBadge);\n es.removeEventListener('inbox', onBadge);\n es.close();\n };\n }, [streamPath, getAccessToken, refreshBadge]);\n\n useEffect(() => {\n if (open) void load();\n }, [open, load]);\n\n const typeTabOptions = useMemo(\n () =>\n TYPE_TABS.map((t) => {\n const n = t.key ? unreadByType[t.key] || 0 : unreadTotal;\n return {\n key: t.key || 'all',\n label: n > 0 ? `${t.label} (${n})` : t.label,\n };\n }),\n [unreadByType, unreadTotal],\n );\n\n const updateToastPref = (key: keyof InboxToastPrefs, checked: boolean) => {\n setToastPrefs((prev) => {\n const next = { ...prev, [key]: checked };\n saveInboxToastPrefs(next);\n return next;\n });\n };\n\n const handleOpenItem = async (item: InboxBellItem, opts?: { skipRead?: boolean }) => {\n if (!opts?.skipRead && !item.read) {\n try {\n await markRead(item.id);\n setItems((prev) => prev.map((x) => (x.id === item.id ? { ...x, read: true } : x)));\n setUnreadTotal((n) => Math.max(0, n - 1));\n } catch (e) {\n message.error(e instanceof Error ? e.message : '标记已读失败');\n return;\n }\n }\n const href = String(item.href || '').trim();\n if (!href) return;\n if (onNavigate) {\n onNavigate(href, item);\n setOpen(false);\n return;\n }\n if (href.startsWith('http://') || href.startsWith('https://')) {\n window.open(href, '_blank', 'noopener,noreferrer');\n } else {\n window.location.assign(href);\n }\n setOpen(false);\n };\n\n const runQuickAction = async (item: InboxBellItem, action: InboxItemQuickAction) => {\n if (action.disabled) return;\n if (onItemAction) {\n try {\n await onItemAction(action.kind, item);\n setOpen(false);\n void load();\n void refreshBadge();\n } catch (e) {\n message.error(e instanceof Error ? e.message : '操作失败');\n }\n return;\n }\n await handleOpenItem(item);\n };\n\n return (\n <div className={classNames(styles.bellWrap, className)}>\n <Badge count={unreadTotal} size=\"small\" overflowCount={99} offset={[-4, 4]}>\n <Button\n type=\"text\"\n className={styles.bellBtn}\n icon={<Bell size={16} aria-hidden />}\n aria-label={unreadTotal > 0 ? `站内信,${unreadTotal} 条未读` : '站内信'}\n onClick={() => setOpen(true)}\n />\n </Badge>\n <Drawer\n title={title}\n open={open}\n onClose={() => setOpen(false)}\n size={420}\n destroyOnClose={false}\n className={styles.drawer}\n styles={{\n header: { padding: '12px 16px' },\n body: { padding: '12px 16px' },\n }}\n >\n <StateBar\n className={styles.typeTabs}\n size=\"small\"\n activeKey={messageType || 'all'}\n onChange={(k) => setMessageType(k === 'all' ? '' : k)}\n stateOption={typeTabOptions}\n isInner\n />\n <div className={styles.filterRow}>\n <SegmentedRadio<'all' | 'unread' | 'read'>\n size=\"small\"\n value={readFilter}\n onChange={(v) => setReadFilter(v)}\n options={[\n { value: 'all', label: '全部' },\n { value: 'unread', label: '未读' },\n { value: 'read', label: '已读' },\n ]}\n />\n </div>\n <div className={styles.toastPrefs} data-testid=\"inbox-toast-prefs\">\n <div className={styles.toastPrefsTitle}>消息提示</div>\n <p className={styles.toastPrefsHint}>本机浏览器偏好,非租户策略</p>\n <Space size={12} wrap>\n <Checkbox\n checked={toastPrefs.alert}\n onChange={(e) => updateToastPref('alert', e.target.checked)}\n >\n 预警弹出\n </Checkbox>\n <Checkbox\n checked={toastPrefs.action}\n onChange={(e) => updateToastPref('action', e.target.checked)}\n >\n 行动弹出\n </Checkbox>\n <Checkbox\n checked={toastPrefs.remind}\n onChange={(e) => updateToastPref('remind', e.target.checked)}\n >\n 提醒弹出\n </Checkbox>\n </Space>\n </div>\n {error ? <p className={styles.error}>{error}</p> : null}\n <div className={classNames('inbox-bell-list-pane', styles.listPane)}>\n <PageSpin spinning={loading && items.length === 0}>\n {!loading && !error && items.length === 0 ? (\n <Empty description=\"暂无站内信\" />\n ) : items.length === 0 ? null : (\n <VirtualScrollbar\n wrapperClassName={classNames('inbox-bell-list-scroll', styles.listScroll)}\n className={styles.listViewport}\n data-testid=\"inbox-bell-list-scroll\"\n onScroll={onListScroll}\n >\n <ul className={styles.list}>\n {items.map((item) => {\n const typeLabel = messageTypeLabel(item.messageType);\n const levelText = String(item.levelLabel || item.level || '').trim();\n const showLevel = Boolean(levelText);\n const safeHtml = sanitizeInboxHtml(item.bodyHtml);\n const actions = filterInboxActionsForHost(\n resolveInboxItemActions(item),\n Boolean(onItemAction),\n );\n const buttonDriven = isInboxButtonDriven(item);\n const meta = itemMetaLine(item);\n const showActions = Boolean(actions.primary);\n return (\n <li key={item.id}>\n <div\n className={classNames(\n styles.item,\n !item.read && styles.itemUnread,\n buttonDriven && styles.itemStatic,\n )}\n role={buttonDriven ? undefined : 'button'}\n tabIndex={buttonDriven ? undefined : 0}\n onClick={buttonDriven ? undefined : () => void handleOpenItem(item)}\n onKeyDown={\n buttonDriven\n ? undefined\n : (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n void handleOpenItem(item);\n }\n }\n }\n >\n <div className={styles.itemHeader}>\n <span className={styles.itemHeaderLeft}>\n <span className={styles.itemTitle} title={item.title || '(无标题)'}>\n {item.title || '(无标题)'}\n </span>\n {typeLabel ? (\n <SemanticTag\n color={messageTypeSemanticColor(item.messageType)}\n className={styles.typeTag}\n >\n {typeLabel}\n </SemanticTag>\n ) : null}\n </span>\n <span className={styles.itemTime}>{item.createdAt || ''}</span>\n </div>\n <div className={styles.itemBody}>\n {safeHtml ? (\n <div\n className={styles.itemBodyHtml}\n dangerouslySetInnerHTML={{ __html: safeHtml }}\n />\n ) : item.summary ? (\n <span className={styles.itemSummary}>\n {emphasizeQuoted(item.summary)}\n </span>\n ) : null}\n </div>\n {meta ? <span className={styles.itemMeta}>{meta}</span> : null}\n {showLevel ? (\n <div className={styles.itemFooterTags}>\n <SemanticTag\n color={resolveLevelTagColor(item.levelColor)}\n className={styles.typeTag}\n >\n {levelText}\n </SemanticTag>\n </div>\n ) : null}\n {showActions && actions.primary ? (\n <div\n className={styles.itemActions}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <Space size={8} wrap>\n <Button\n size=\"small\"\n type=\"primary\"\n onClick={() => void runQuickAction(item, actions.primary!)}\n >\n {actions.primary.label}\n </Button>\n {actions.secondary ? (\n <Button\n size=\"small\"\n type=\"link\"\n onClick={() => void runQuickAction(item, actions.secondary!)}\n >\n {actions.secondary.label}\n </Button>\n ) : null}\n </Space>\n </div>\n ) : null}\n </div>\n </li>\n );\n })}\n </ul>\n {loadingMore ? (\n <p className={classNames('inbox-bell-list-footer', styles.listFooter)}>加载中…</p>\n ) : null}\n </VirtualScrollbar>\n )}\n </PageSpin>\n </div>\n </Drawer>\n </div>\n );\n});\n\nexport default InboxBell;\nexport {\n DEFAULT_INBOX_TOAST_PREFS,\n loadInboxToastPrefs,\n saveInboxToastPrefs,\n shouldToastForMessageType,\n} from './toastPrefs';\nexport type { InboxToastPrefs } from './toastPrefs';\nexport {\n resolveInboxItemActions,\n resolveInboxSceneKey,\n filterInboxActionsForHost,\n normalizeInboxActions,\n inboxSceneLabel,\n isInboxButtonDriven,\n isTerminalActionStatus,\n} from './inboxItemActions';\nexport type {\n InboxItemActionKind,\n InboxItemQuickAction,\n InboxItemActionsResolved,\n} from './inboxItemActions';\n"],"names":["TYPE_TABS","TYPE_TAG_LABEL","FOCUS_DEBOUNCE_MS","LOAD_MORE_GAP_PX","messageTypeLabel","raw","key","messageTypeSemanticColor","SEMANTIC_COLORS","itemMetaLine","item","x","resolveLevelTagColor","parseBadgePreview","data","messageType","title","summary","InboxBell","forwardRef","fetchInbox","markRead","onNavigate","pollMs","locationKey","pageSize","className","streamPath","getAccessToken","onItemAction","ref","open","setOpen","useState","loading","setLoading","error","setError","items","setItems","unreadTotal","setUnreadTotal","unreadByType","setUnreadByType","setMessageType","readFilter","setReadFilter","toastPrefs","setToastPrefs","loadInboxToastPrefs","loadingMore","setLoadingMore","focusDebounceRef","useRef","locationKeyPrimedRef","toastPrefsRef","currentPageRef","loadingMoreRef","hasMoreRef","listQuery","useMemo","load","useCallback","res","page","total","loadMore","next","prev","seen","extra","merged","onListScroll","el","refreshBadge","useImperativeHandle","useEffect","t","schedule","onVisibility","onExternal","INBOX_BADGE_REFRESH_EVENT","token","base","url","es","onBadge","ev","msgEv","preview","shouldToastForMessageType","toastTitle","toastDesc","typeLabel","openDrawer","notification","toastKey","classNames","styles","jsxs","jsx","emphasizeQuoted","SemanticTag","Button","e","typeTabOptions","n","updateToastPref","checked","saveInboxToastPrefs","handleOpenItem","opts","message","href","runQuickAction","action","Badge","Bell","Drawer","StateBar","k","SegmentedRadio","v","Space","Checkbox","PageSpin","Empty","VirtualScrollbar","levelText","showLevel","safeHtml","sanitizeInboxHtml","actions","filterInboxActionsForHost","resolveInboxItemActions","buttonDriven","isInboxButtonDriven","meta","showActions"],"mappings":";;;;;;;;;;;;;;;;;;;AAmIA,MAAMA,KAAmD;AAAA,EACvD,EAAE,KAAK,IAAI,OAAO,KAAA;AAAA,EAClB,EAAE,KAAK,SAAS,OAAO,KAAA;AAAA,EACvB,EAAE,KAAK,UAAU,OAAO,KAAA;AAAA,EACxB,EAAE,KAAK,UAAU,OAAO,KAAA;AAC1B,GAEMC,KAAyC;AAAA,EAC7C,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AACV,GAEMC,KAAoB,KAEpBC,KAAmB;AAEzB,SAASC,GAAiBC,GAAsB;AAC9C,QAAMC,IAAM,OAAOD,KAAO,EAAE,EACzB,KAAA,EACA,YAAA;AACH,SAAKC,IACEL,GAAeK,CAAG,KAAKA,IADb;AAEnB;AAEA,SAASC,EAAyBF,GAAsB;AACtD,QAAMC,IAAM,OAAOD,KAAO,EAAE,EACzB,KAAA,EACA,YAAA;AACH,SAAIC,MAAQ,UAAgBE,EAAgB,SACxCF,MAAQ,WAAiBE,EAAgB,UACzCF,MAAQ,WAAiBE,EAAgB,UACtCA,EAAgB;AACzB;AAEA,SAASC,GAAaC,GAA6B;AACjD,SAAO,CAACA,EAAK,SAASA,EAAK,SAASA,EAAK,MAAM,EAC5C,IAAI,CAACC,MAAM,OAAOA,KAAK,EAAE,EAAE,KAAA,CAAM,EACjC,OAAO,OAAO,EACd,KAAK,KAAK;AACf;AAGA,SAASC,GAAqBP,GAAsB;AAElD,SADU,OAAOA,KAAO,EAAE,EAAE,KAAA,KAChBG,EAAgB;AAC9B;AAQA,SAASK,GAAkBR,GAAkC;AAC3D,MAAI;AACF,UAAMS,IAAO,KAAK,MAAMT,CAAG;AAC3B,QAAI,CAACS,KAAQ,OAAOA,KAAS,SAAU,QAAO;AAC9C,UAAMC,IAAc,OAAOD,EAAK,eAAeA,EAAK,gBAAgB,EAAE,EAAE,KAAA,GAClEE,IAAQ,OAAOF,EAAK,SAAS,EAAE,EAAE,KAAA,GACjCG,IAAU,OAAOH,EAAK,WAAW,EAAE,EAAE,KAAA;AAC3C,WAAI,CAACC,KAAe,CAACC,KAAS,CAACC,IAAgB,OACxC;AAAA,MACL,aAAaF,KAAe;AAAA,MAC5B,OAAOC,KAAS;AAAA,MAChB,SAASC,KAAW;AAAA,IAAA;AAAA,EAExB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOA,MAAMC,KAAYC,GAA4C,SAC5D;AAAA,EACE,YAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,EACA,QAAAC,IAAS;AAAA,EACT,aAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,WAAAC;AAAA,EACA,OAAAV,KAAQ;AAAA,EACR,YAAAW,IAAa;AAAA,EACb,gBAAAC;AAAA,EACA,cAAAC;AACF,GACAC,IACA;AACA,QAAM,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAK,GAChC,CAACC,IAASC,EAAU,IAAIF,EAAS,EAAK,GACtC,CAACG,GAAOC,EAAQ,IAAIJ,EAAS,EAAE,GAC/B,CAACK,GAAOC,CAAQ,IAAIN,EAA0B,CAAA,CAAE,GAChD,CAACO,GAAaC,CAAc,IAAIR,EAAS,CAAC,GAC1C,CAACS,IAAcC,CAAe,IAAIV,EAA0C,CAAA,CAAE,GAC9E,CAAClB,GAAa6B,EAAc,IAAIX,EAAiB,EAAE,GACnD,CAACY,GAAYC,EAAa,IAAIb,EAAoC,KAAK,GACvE,CAACc,GAAYC,EAAa,IAAIf,EAA0B,MAAMgB,IAAqB,GACnF,CAACC,IAAaC,EAAc,IAAIlB,EAAS,EAAK,GAC9CmB,IAAmBC,EAAsB,IAAI,GAC7CC,KAAuBD,EAAO,EAAK,GACnCE,KAAgBF,EAAON,CAAU;AACvC,EAAAQ,GAAc,UAAUR;AACxB,QAAMS,IAAiBH,EAAO,CAAC,GACzBI,IAAiBJ,EAAO,EAAK,GAC7BK,IAAaL,EAAO,EAAK,GAEzBM,IAAYC;AAAA,IAChB,OAAO;AAAA,MACL,aAAa7C,KAAe;AAAA,MAC5B,YAAY8B,MAAe,YAAY;AAAA,MACvC,UAAUA,MAAe,UAAU;AAAA,IAAA;AAAA,IAErC,CAAC9B,GAAa8B,CAAU;AAAA,EAAA,GAGpBgB,IAAOC,EAAY,YAAY;AACnC,IAAA3B,GAAW,EAAI,GACfE,GAAS,EAAE,GACXmB,EAAe,UAAU,GACzBE,EAAW,UAAU;AACrB,QAAI;AACF,YAAMK,IAAM,MAAM3C,EAAW;AAAA,QAC3B,aAAa;AAAA,QACb,UAAAK;AAAA,QACA,GAAGkC;AAAA,MAAA,CACJ,GACKK,KAAOD,KAAA,gBAAAA,EAAK,aAAY,CAAA,GACxBE,IAAQ,QAAOF,KAAA,gBAAAA,EAAK,UAAU,WAAWA,EAAI,QAAQC,EAAK;AAChE,MAAAzB,EAASyB,CAAI,GACbN,EAAW,UAAUM,EAAK,SAAS,KAAKA,EAAK,SAASC,GACtDxB,EAAe,QAAOsB,KAAA,gBAAAA,EAAK,gBAAgB,WAAWA,EAAI,cAAc,CAAC,GACzEpB,GAAgBoB,KAAA,gBAAAA,EAAK,wBAAuB,EAAE;AAAA,IAChD,SAAS,GAAG;AACV,MAAAxB,EAAS,CAAA,CAAE,GACXmB,EAAW,UAAU,IACrBrB,GAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IACrD,UAAA;AACE,MAAAF,GAAW,EAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAACf,GAAYK,GAAUkC,CAAS,CAAC,GAE9BO,KAAWJ,EAAY,YAAY;AACvC,QAAI,EAAAL,EAAe,WAAW,CAACC,EAAW,UAC1C;AAAA,MAAAD,EAAe,UAAU,IACzBN,GAAe,EAAI;AACnB,UAAI;AACF,cAAMgB,IAAOX,EAAe,UAAU,GAChCO,IAAM,MAAM3C,EAAW;AAAA,UAC3B,aAAa+C;AAAA,UACb,UAAA1C;AAAA,UACA,GAAGkC;AAAA,QAAA,CACJ,GACKK,KAAOD,KAAA,gBAAAA,EAAK,aAAY,CAAA,GACxBE,IAAQ,QAAOF,KAAA,gBAAAA,EAAK,UAAU,WAAWA,EAAI,QAAQ;AAC3D,QAAAxB,EAAS,CAAC6B,MAAS;AACjB,gBAAMC,IAAO,IAAI,IAAID,EAAK,IAAI,CAACzD,MAAMA,EAAE,EAAE,CAAC,GACpC2D,IAAQN,EAAK,OAAO,CAACrD,OAAMA,KAAA,gBAAAA,EAAG,OAAM,CAAC0D,EAAK,IAAI1D,EAAE,EAAE,CAAC,GACnD4D,IAASD,EAAM,SAAS,CAAC,GAAGF,GAAM,GAAGE,CAAK,IAAIF;AACpD,iBAAAV,EAAW,UACTY,EAAM,SAAS,MAAML,IAAQ,IAAIM,EAAO,SAASN,IAAQK,EAAM,UAAU7C,IACpE8C;AAAA,QACT,CAAC,GACGP,EAAK,WAAQR,EAAe,UAAUW,IACtC,QAAOJ,KAAA,gBAAAA,EAAK,gBAAgB,YAAUtB,EAAesB,EAAI,WAAW,GACpEA,KAAA,QAAAA,EAAK,uBAAqBpB,EAAgBoB,EAAI,mBAAmB;AAAA,MACvE,QAAQ;AACN,QAAAL,EAAW,UAAU;AAAA,MACvB,UAAA;AACE,QAAAD,EAAe,UAAU,IACzBN,GAAe,EAAK;AAAA,MACtB;AAAA;AAAA,EACF,GAAG,CAAC/B,GAAYK,GAAUkC,CAAS,CAAC,GAE9Ba,KAAeV;AAAA,IACnB,CAAC,MAA+B;AAC9B,YAAMW,IAAK,EAAE;AACb,MAAIA,EAAG,eAAeA,EAAG,YAAYA,EAAG,gBAAgBtE,MACjD+D,GAAA;AAAA,IAET;AAAA,IACA,CAACA,EAAQ;AAAA,EAAA,GAGLQ,IAAeZ,EAAY,YAAY;AAC3C,QAAI;AAEF,YAAMC,IAAM,MAAM3C,EAAW,EAAE,aAAa,GAAG,UAAAK,GAAU;AACzD,MAAAgB,EAAe,QAAOsB,KAAA,gBAAAA,EAAK,gBAAgB,WAAWA,EAAI,cAAc,CAAC,GACzEpB,GAAgBoB,KAAA,gBAAAA,EAAK,wBAAuB,EAAE;AAAA,IAChD,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC3C,GAAYK,CAAQ,CAAC;AAEzB,EAAAkD,GAAoB7C,IAAK,OAAO,EAAE,cAAA4C,MAAiB,CAACA,CAAY,CAAC,GAEjEE,EAAU,MAAM;AACd,IAAKF,EAAA;AAAA,EACP,GAAG,CAACA,CAAY,CAAC,GAEjBE,EAAU,MAAM;AACd,QAAIpD,MAAgB,QAEpB;AAAA,UAAI,CAAC8B,GAAqB,SAAS;AACjC,QAAAA,GAAqB,UAAU;AAC/B;AAAA,MACF;AACA,MAAKoB,EAAA;AAAA;AAAA,EACP,GAAG,CAAClD,GAAakD,CAAY,CAAC,GAE9BE,EAAU,MAAM;AACd,QAAIrD,KAAU,EAAG;AACjB,UAAMsD,IAAI,OAAO,YAAY,MAAM;AACjC,MAAKH,EAAA;AAAA,IACP,GAAGnD,CAAM;AACT,WAAO,MAAM,OAAO,cAAcsD,CAAC;AAAA,EACrC,GAAG,CAACtD,GAAQmD,CAAY,CAAC,GAEzBE,EAAU,MAAM;AACd,UAAME,IAAW,MAAM;AACrB,MAAI1B,EAAiB,WAAW,QAC9B,OAAO,aAAaA,EAAiB,OAAO,GAE9CA,EAAiB,UAAU,OAAO,WAAW,MAAM;AACjD,QAAAA,EAAiB,UAAU,MACtBsB,EAAA;AAAA,MACP,GAAGxE,EAAiB;AAAA,IACtB,GAEM6E,IAAe,MAAM;AACzB,MAAI,SAAS,oBAAoB,aAAWD,EAAA;AAAA,IAC9C;AAEA,kBAAO,iBAAiB,SAASA,CAAQ,GACzC,SAAS,iBAAiB,oBAAoBC,CAAY,GACnD,MAAM;AACX,aAAO,oBAAoB,SAASD,CAAQ,GAC5C,SAAS,oBAAoB,oBAAoBC,CAAY,GACzD3B,EAAiB,WAAW,SAC9B,OAAO,aAAaA,EAAiB,OAAO,GAC5CA,EAAiB,UAAU;AAAA,IAE/B;AAAA,EACF,GAAG,CAACsB,CAAY,CAAC,GAEjBE,EAAU,MAAM;AACd,UAAMI,IAAa,MAAM;AACvB,MAAKN,EAAA;AAAA,IACP;AACA,kBAAO,iBAAiBO,IAA2BD,CAAU,GACtD,MAAM,OAAO,oBAAoBC,IAA2BD,CAAU;AAAA,EAC/E,GAAG,CAACN,CAAY,CAAC,GAEjBE,EAAU,MAAM;AAGd,QAFIjD,MAAe,MACf,OAAOC,KAAmB,cAC1B,OAAO,SAAW,OAAe,OAAO,cAAgB,IAAa;AAEzE,UAAMsD,IAAQ,OAAOtD,EAAA,KAAoB,EAAE,EAAE,KAAA;AAC7C,QAAI,CAACsD,EAAO;AAEZ,UAAMC,IAAO,OAAOxD,KAAc,iCAAiC,EAAE,KAAA,GAC/DyD,IAAM,IAAI,IAAID,GAAM,OAAO,SAAS,MAAM;AAChD,IAAAC,EAAI,aAAa,IAAI,gBAAgBF,CAAK;AAE1C,QAAIG;AACJ,QAAI;AACF,MAAAA,IAAK,IAAI,YAAYD,EAAI,SAAA,CAAU;AAAA,IACrC,QAAQ;AACN;AAAA,IACF;AAEA,UAAME,IAAU,CAACC,MAAc;AAC7B,MAAKb,EAAA;AACL,YAAMc,IAAQD,GACRE,IAAU,QAAOD,KAAA,gBAAAA,EAAO,SAAS,WAAW3E,GAAkB2E,EAAM,IAAI,IAAI;AAElF,UADI,CAACC,KACD,CAACC,GAA0BnC,GAAc,SAASkC,EAAQ,WAAW,EAAG;AAC5E,YAAME,IAAaF,EAAQ,SAAS,QAC9BG,IAAYH,EAAQ,WAAW,IAC/BI,IAAYzF,GAAiBqF,EAAQ,WAAW,GAChDK,KAAa,MAAM;AACvB,QAAAC,GAAa,QAAA,GACb/D,EAAQ,EAAI;AAAA,MACd,GACMgE,KAAW,eAAeP,EAAQ,eAAe,KAAK,IAAI,KAAK,KAAK;AAC1E,MAAAM,GAAa,KAAK;AAAA,QAChB,KAAKC;AAAA,QACL,WAAWC,EAAW,sBAAsBC,EAAO,WAAW;AAAA,QAC9D,UAAU;AAAA,QACV,OACE,gBAAAC,EAAC,OAAA,EAAI,WAAWD,EAAO,WACrB,UAAA;AAAA,UAAA,gBAAAE,EAAC,UAAK,WAAWF,EAAO,YAAa,UAAAG,EAAgBV,CAAU,GAAE;AAAA,UAChEE,IACC,gBAAAO;AAAA,YAACE;AAAA,YAAA;AAAA,cACC,OAAO/F,EAAyBkF,EAAQ,WAAW;AAAA,cACnD,WAAWS,EAAO;AAAA,cAEjB,UAAAL;AAAA,YAAA;AAAA,UAAA,IAED;AAAA,QAAA,GACN;AAAA,QAEF,SACE,gBAAAM,EAAC,OAAA,EAAI,WAAWD,EAAO,WACrB,UAAA;AAAA,UAAA,gBAAAE,EAAC,UAAK,WAAWF,EAAO,YAAa,UAAAG,EAAgBV,CAAU,GAAE;AAAA,UAChEE,IACC,gBAAAO;AAAA,YAACE;AAAA,YAAA;AAAA,cACC,OAAO/F,EAAyBkF,EAAQ,WAAW;AAAA,cACnD,WAAWS,EAAO;AAAA,cAEjB,UAAAL;AAAA,YAAA;AAAA,UAAA,IAED;AAAA,QAAA,GACN;AAAA,QAEF,aACE,gBAAAM,EAAC,OAAA,EAAI,WAAWD,EAAO,WACpB,UAAA;AAAA,UAAAN,IACC,gBAAAQ,EAAC,SAAI,WAAWF,EAAO,WAAY,UAAAG,EAAgBT,CAAS,GAAE,IAC5D;AAAA,UACJ,gBAAAQ,EAAC,OAAA,EAAI,WAAWF,EAAO,cACrB,UAAA,gBAAAE;AAAA,YAACG;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,MAAK;AAAA,cACL,SAAS,CAACC,OAAM;AACd,gBAAAA,GAAE,gBAAA,GACFV,GAAA;AAAA,cACF;AAAA,cACD,UAAA;AAAA,YAAA;AAAA,UAAA,EAED,CACF;AAAA,QAAA,GACF;AAAA,QAEF,WAAW;AAAA,QACX,UAAU;AAAA,QACV,SAASA;AAAA,MAAA,CACV;AAAA,IACH;AACA,WAAAT,EAAG,iBAAiB,SAASC,CAAO,GACpCD,EAAG,iBAAiB,SAASC,CAAO,GAEpCD,EAAG,UAAU,MAAM;AACjB,MAAAA,EAAG,MAAA;AAAA,IACL,GAEO,MAAM;AACX,MAAAA,EAAG,oBAAoB,SAASC,CAAO,GACvCD,EAAG,oBAAoB,SAASC,CAAO,GACvCD,EAAG,MAAA;AAAA,IACL;AAAA,EACF,GAAG,CAAC1D,GAAYC,GAAgB8C,CAAY,CAAC,GAE7CE,EAAU,MAAM;AACd,IAAI7C,KAAW8B,EAAA;AAAA,EACjB,GAAG,CAAC9B,GAAM8B,CAAI,CAAC;AAEf,QAAM4C,KAAiB7C;AAAA,IACrB,MACE5D,GAAU,IAAI,CAAC6E,MAAM;AACnB,YAAM6B,IAAI7B,EAAE,MAAMnC,GAAamC,EAAE,GAAG,KAAK,IAAIrC;AAC7C,aAAO;AAAA,QACL,KAAKqC,EAAE,OAAO;AAAA,QACd,OAAO6B,IAAI,IAAI,GAAG7B,EAAE,KAAK,KAAK6B,CAAC,MAAM7B,EAAE;AAAA,MAAA;AAAA,IAE3C,CAAC;AAAA,IACH,CAACnC,IAAcF,CAAW;AAAA,EAAA,GAGtBmE,IAAkB,CAACrG,GAA4BsG,MAAqB;AACxE,IAAA5D,GAAc,CAACoB,MAAS;AACtB,YAAMD,IAAO,EAAE,GAAGC,GAAM,CAAC9D,CAAG,GAAGsG,EAAA;AAC/B,aAAAC,GAAoB1C,CAAI,GACjBA;AAAA,IACT,CAAC;AAAA,EACH,GAEM2C,IAAiB,OAAOpG,GAAqBqG,MAAkC;AACnF,QAAuB,CAACrG,EAAK;AAC3B,UAAI;AACF,cAAMW,EAASX,EAAK,EAAE,GACtB6B,EAAS,CAAC6B,MAASA,EAAK,IAAI,CAACzD,MAAOA,EAAE,OAAOD,EAAK,KAAK,EAAE,GAAGC,GAAG,MAAM,GAAA,IAASA,CAAE,CAAC,GACjF8B,EAAe,CAACiE,MAAM,KAAK,IAAI,GAAGA,IAAI,CAAC,CAAC;AAAA,MAC1C,SAASF,GAAG;AACV,QAAAQ,GAAQ,MAAMR,aAAa,QAAQA,EAAE,UAAU,QAAQ;AACvD;AAAA,MACF;AAEF,UAAMS,IAAO,OAAOvG,EAAK,QAAQ,EAAE,EAAE,KAAA;AACrC,QAAKuG,GACL;AAAA,UAAI3F,GAAY;AACd,QAAAA,EAAW2F,GAAMvG,CAAI,GACrBsB,EAAQ,EAAK;AACb;AAAA,MACF;AACA,MAAIiF,EAAK,WAAW,SAAS,KAAKA,EAAK,WAAW,UAAU,IAC1D,OAAO,KAAKA,GAAM,UAAU,qBAAqB,IAEjD,OAAO,SAAS,OAAOA,CAAI,GAE7BjF,EAAQ,EAAK;AAAA;AAAA,EACf,GAEMkF,KAAiB,OAAOxG,GAAqByG,MAAiC;AAClF,QAAI,CAAAA,EAAO,UACX;AAAA,UAAItF,IAAc;AAChB,YAAI;AACF,gBAAMA,GAAasF,EAAO,MAAMzG,CAAI,GACpCsB,EAAQ,EAAK,GACR6B,EAAA,GACAa,EAAA;AAAA,QACP,SAAS8B,GAAG;AACV,UAAAQ,GAAQ,MAAMR,aAAa,QAAQA,EAAE,UAAU,MAAM;AAAA,QACvD;AACA;AAAA,MACF;AACA,YAAMM,EAAepG,CAAI;AAAA;AAAA,EAC3B;AAEA,2BACG,OAAA,EAAI,WAAWuF,EAAWC,EAAO,UAAUxE,EAAS,GACnD,UAAA;AAAA,IAAA,gBAAA0E,EAACgB,IAAA,EAAM,OAAO5E,GAAa,MAAK,SAAQ,eAAe,IAAI,QAAQ,CAAC,IAAI,CAAC,GACvE,UAAA,gBAAA4D;AAAA,MAACG;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWL,EAAO;AAAA,QAClB,MAAM,gBAAAE,EAACiB,IAAA,EAAK,MAAM,IAAI,eAAW,IAAC;AAAA,QAClC,cAAY7E,IAAc,IAAI,OAAOA,CAAW,SAAS;AAAA,QACzD,SAAS,MAAMR,EAAQ,EAAI;AAAA,MAAA;AAAA,IAAA,GAE/B;AAAA,IACA,gBAAAmE;AAAA,MAACmB;AAAA,MAAA;AAAA,QACC,OAAAtG;AAAA,QACA,MAAAe;AAAA,QACA,SAAS,MAAMC,EAAQ,EAAK;AAAA,QAC5B,MAAM;AAAA,QACN,gBAAgB;AAAA,QAChB,WAAWkE,EAAO;AAAA,QAClB,QAAQ;AAAA,UACN,QAAQ,EAAE,SAAS,YAAA;AAAA,UACnB,MAAM,EAAE,SAAS,YAAA;AAAA,QAAY;AAAA,QAG/B,UAAA;AAAA,UAAA,gBAAAE;AAAA,YAACmB;AAAA,YAAA;AAAA,cACC,WAAWrB,EAAO;AAAA,cAClB,MAAK;AAAA,cACL,WAAWnF,KAAe;AAAA,cAC1B,UAAU,CAACyG,MAAM5E,GAAe4E,MAAM,QAAQ,KAAKA,CAAC;AAAA,cACpD,aAAaf;AAAA,cACb,SAAO;AAAA,YAAA;AAAA,UAAA;AAAA,UAET,gBAAAL,EAAC,OAAA,EAAI,WAAWF,EAAO,WACrB,UAAA,gBAAAE;AAAA,YAACqB;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAO5E;AAAA,cACP,UAAU,CAAC6E,MAAM5E,GAAc4E,CAAC;AAAA,cAChC,SAAS;AAAA,gBACP,EAAE,OAAO,OAAO,OAAO,KAAA;AAAA,gBACvB,EAAE,OAAO,UAAU,OAAO,KAAA;AAAA,gBAC1B,EAAE,OAAO,QAAQ,OAAO,KAAA;AAAA,cAAK;AAAA,YAC/B;AAAA,UAAA,GAEJ;AAAA,4BACC,OAAA,EAAI,WAAWxB,EAAO,YAAY,eAAY,qBAC7C,UAAA;AAAA,YAAA,gBAAAE,EAAC,OAAA,EAAI,WAAWF,EAAO,iBAAiB,UAAA,QAAI;AAAA,YAC5C,gBAAAE,EAAC,KAAA,EAAE,WAAWF,EAAO,gBAAgB,UAAA,iBAAa;AAAA,YAClD,gBAAAC,EAACwB,IAAA,EAAM,MAAM,IAAI,MAAI,IACnB,UAAA;AAAA,cAAA,gBAAAvB;AAAA,gBAACwB;AAAA,gBAAA;AAAA,kBACC,SAAS7E,EAAW;AAAA,kBACpB,UAAU,CAAC,MAAM4D,EAAgB,SAAS,EAAE,OAAO,OAAO;AAAA,kBAC3D,UAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGD,gBAAAP;AAAA,gBAACwB;AAAA,gBAAA;AAAA,kBACC,SAAS7E,EAAW;AAAA,kBACpB,UAAU,CAAC,MAAM4D,EAAgB,UAAU,EAAE,OAAO,OAAO;AAAA,kBAC5D,UAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGD,gBAAAP;AAAA,gBAACwB;AAAA,gBAAA;AAAA,kBACC,SAAS7E,EAAW;AAAA,kBACpB,UAAU,CAAC,MAAM4D,EAAgB,UAAU,EAAE,OAAO,OAAO;AAAA,kBAC5D,UAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,YAED,EAAA,CACF;AAAA,UAAA,GACF;AAAA,UACCvE,IAAQ,gBAAAgE,EAAC,KAAA,EAAE,WAAWF,EAAO,OAAQ,aAAM,IAAO;AAAA,UACnD,gBAAAE,EAAC,OAAA,EAAI,WAAWH,EAAW,wBAAwBC,EAAO,QAAQ,GAChE,UAAA,gBAAAE,EAACyB,IAAA,EAAS,UAAU3F,MAAWI,EAAM,WAAW,GAC7C,UAAA,CAACJ,MAAW,CAACE,KAASE,EAAM,WAAW,IACtC,gBAAA8D,EAAC0B,IAAA,EAAM,aAAY,QAAA,CAAQ,IACzBxF,EAAM,WAAW,IAAI,OACvB,gBAAA6D;AAAA,YAAC4B;AAAA,YAAA;AAAA,cACC,kBAAkB9B,EAAW,0BAA0BC,EAAO,UAAU;AAAA,cACxE,WAAWA,EAAO;AAAA,cAClB,eAAY;AAAA,cACZ,UAAU1B;AAAA,cAEV,UAAA;AAAA,gBAAA,gBAAA4B,EAAC,QAAG,WAAWF,EAAO,MACnB,UAAA5D,EAAM,IAAI,CAAC5B,MAAS;AACnB,wBAAMmF,IAAYzF,GAAiBM,EAAK,WAAW,GAC7CsH,IAAY,OAAOtH,EAAK,cAAcA,EAAK,SAAS,EAAE,EAAE,KAAA,GACxDuH,IAAY,EAAQD,GACpBE,IAAWC,GAAkBzH,EAAK,QAAQ,GAC1C0H,IAAUC;AAAA,oBACdC,GAAwB5H,CAAI;AAAA,kBAE9B,GACM6H,IAAeC,GAAoB9H,CAAI,GACvC+H,IAAOhI,GAAaC,CAAI,GACxBgI,IAAc,EAAQN,EAAQ;AACpC,2CACG,MAAA,EACC,UAAA,gBAAAjC;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,WAAWF;AAAA,wBACTC,EAAO;AAAA,wBACP,CAACxF,EAAK,QAAQwF,EAAO;AAAA,wBACrBqC,KAAgBrC,EAAO;AAAA,sBAAA;AAAA,sBAEzB,MAAMqC,IAAe,SAAY;AAAA,sBACjC,UAAUA,IAAe,SAAY;AAAA,sBACrC,SAASA,IAAe,SAAY,MAAM,KAAKzB,EAAepG,CAAI;AAAA,sBAClE,WACE6H,IACI,SACA,CAAC/B,MAAM;AACL,yBAAIA,EAAE,QAAQ,WAAWA,EAAE,QAAQ,SACjCA,EAAE,eAAA,GACGM,EAAepG,CAAI;AAAA,sBAE5B;AAAA,sBAGN,UAAA;AAAA,wBAAA,gBAAAyF,EAAC,OAAA,EAAI,WAAWD,EAAO,YACrB,UAAA;AAAA,0BAAA,gBAAAC,EAAC,QAAA,EAAK,WAAWD,EAAO,gBACtB,UAAA;AAAA,4BAAA,gBAAAE,EAAC,QAAA,EAAK,WAAWF,EAAO,WAAW,OAAOxF,EAAK,SAAS,SACrD,UAAAA,EAAK,SAAS,QAAA,CACjB;AAAA,4BACCmF,IACC,gBAAAO;AAAA,8BAACE;AAAA,8BAAA;AAAA,gCACC,OAAO/F,EAAyBG,EAAK,WAAW;AAAA,gCAChD,WAAWwF,EAAO;AAAA,gCAEjB,UAAAL;AAAA,8BAAA;AAAA,4BAAA,IAED;AAAA,0BAAA,GACN;AAAA,4CACC,QAAA,EAAK,WAAWK,EAAO,UAAW,UAAAxF,EAAK,aAAa,GAAA,CAAG;AAAA,wBAAA,GAC1D;AAAA,wBACA,gBAAA0F,EAAC,OAAA,EAAI,WAAWF,EAAO,UACpB,UAAAgC,IACC,gBAAA9B;AAAA,0BAAC;AAAA,0BAAA;AAAA,4BACC,WAAWF,EAAO;AAAA,4BAClB,yBAAyB,EAAE,QAAQgC,EAAA;AAAA,0BAAS;AAAA,wBAAA,IAE5CxH,EAAK,UACP,gBAAA0F,EAAC,QAAA,EAAK,WAAWF,EAAO,aACrB,UAAAG,EAAgB3F,EAAK,OAAO,EAAA,CAC/B,IACE,MACN;AAAA,wBACC+H,IAAO,gBAAArC,EAAC,QAAA,EAAK,WAAWF,EAAO,UAAW,aAAK,IAAU;AAAA,wBACzD+B,IACC,gBAAA7B,EAAC,OAAA,EAAI,WAAWF,EAAO,gBACrB,UAAA,gBAAAE;AAAA,0BAACE;AAAA,0BAAA;AAAA,4BACC,OAAO1F,GAAqBF,EAAK,UAAU;AAAA,4BAC3C,WAAWwF,EAAO;AAAA,4BAEjB,UAAA8B;AAAA,0BAAA;AAAA,wBAAA,GAEL,IACE;AAAA,wBACHU,KAAeN,EAAQ,UACtB,gBAAAhC;AAAA,0BAAC;AAAA,0BAAA;AAAA,4BACC,WAAWF,EAAO;AAAA,4BAClB,SAAS,CAACM,MAAMA,EAAE,gBAAA;AAAA,4BAClB,WAAW,CAACA,MAAMA,EAAE,gBAAA;AAAA,4BAEpB,UAAA,gBAAAL,EAACwB,IAAA,EAAM,MAAM,GAAG,MAAI,IAClB,UAAA;AAAA,8BAAA,gBAAAvB;AAAA,gCAACG;AAAA,gCAAA;AAAA,kCACC,MAAK;AAAA,kCACL,MAAK;AAAA,kCACL,SAAS,MAAM,KAAKW,GAAexG,GAAM0H,EAAQ,OAAQ;AAAA,kCAExD,YAAQ,QAAQ;AAAA,gCAAA;AAAA,8BAAA;AAAA,8BAElBA,EAAQ,YACP,gBAAAhC;AAAA,gCAACG;AAAA,gCAAA;AAAA,kCACC,MAAK;AAAA,kCACL,MAAK;AAAA,kCACL,SAAS,MAAM,KAAKW,GAAexG,GAAM0H,EAAQ,SAAU;AAAA,kCAE1D,YAAQ,UAAU;AAAA,gCAAA;AAAA,8BAAA,IAEnB;AAAA,4BAAA,EAAA,CACN;AAAA,0BAAA;AAAA,wBAAA,IAEA;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA,EACN,GAtFO1H,EAAK,EAuFd;AAAA,gBAEJ,CAAC,EAAA,CACH;AAAA,gBACCwC,KACC,gBAAAkD,EAAC,KAAA,EAAE,WAAWH,EAAW,0BAA0BC,EAAO,UAAU,GAAG,UAAA,OAAA,CAAI,IACzE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA,GAGV,EAAA,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ,CAAC;"}
@@ -0,0 +1,3 @@
1
+ import { ReactNode } from 'react';
2
+ /** 把「」内文案加粗,供 toast / 摘要强调 */
3
+ export declare function emphasizeQuoted(text: string): ReactNode;
@@ -0,0 +1,13 @@
1
+ import { jsx as s } from "react/jsx-runtime";
2
+ function u(e) {
3
+ const n = String(e || "");
4
+ if (!n) return null;
5
+ const r = n.split(/(「[^」]*」)/g);
6
+ return r.length === 1 ? n : r.map(
7
+ (t, i) => t.startsWith("「") && t.endsWith("」") ? /* @__PURE__ */ s("strong", { children: t }, i) : t
8
+ );
9
+ }
10
+ export {
11
+ u as emphasizeQuoted
12
+ };
13
+ //# sourceMappingURL=emphasizeQuoted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emphasizeQuoted.js","sources":["../../../../../src/components/Tools/Inbox/InboxBell/emphasizeQuoted.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\n/** 把「」内文案加粗,供 toast / 摘要强调 */\nexport function emphasizeQuoted(text: string): ReactNode {\n const raw = String(text || '');\n if (!raw) return null;\n const parts = raw.split(/(「[^」]*」)/g);\n if (parts.length === 1) return raw;\n return parts.map((part, i) =>\n part.startsWith('「') && part.endsWith('」') ? <strong key={i}>{part}</strong> : part,\n );\n}\n"],"names":["emphasizeQuoted","text","raw","parts","part","jsx"],"mappings":";AAGO,SAASA,EAAgBC,GAAyB;AACvD,QAAMC,IAAM,OAAOD,KAAQ,EAAE;AAC7B,MAAI,CAACC,EAAK,QAAO;AACjB,QAAMC,IAAQD,EAAI,MAAM,YAAY;AACpC,SAAIC,EAAM,WAAW,IAAUD,IACxBC,EAAM;AAAA,IAAI,CAACC,GAAM,MACtBA,EAAK,WAAW,GAAG,KAAKA,EAAK,SAAS,GAAG,IAAI,gBAAAC,EAAC,UAAA,EAAgB,UAAAD,EAAA,GAAJ,CAAS,IAAYA;AAAA,EAAA;AAEnF;"}
@@ -0,0 +1,43 @@
1
+ export type InboxItemActionKind = 'view_alert' | 'claim_alert' | 'start_action' | 'view_task'
2
+ /** @deprecated 铃铛永不解析;保留类型以免破对外联合 */
3
+ | 'create_task' | 'open_actions' | 'view_rca' | 'view_href';
4
+ export type InboxItemQuickAction = {
5
+ kind: InboxItemActionKind;
6
+ label: string;
7
+ /** 解析中间态用;渲染前会被 normalize 丢掉,禁止灰显占位 */
8
+ disabled?: boolean;
9
+ };
10
+ export type InboxItemActionsResolved = {
11
+ primary?: InboxItemQuickAction;
12
+ secondary?: InboxItemQuickAction;
13
+ };
14
+ export type InboxItemActionSource = {
15
+ category?: string | null;
16
+ scene?: string | null;
17
+ eventKey?: string | null;
18
+ messageType?: string | null;
19
+ alertId?: string | null;
20
+ actionId?: string | null;
21
+ claimed?: boolean;
22
+ started?: boolean;
23
+ /** 行动项当前状态:approved/in_progress/done/reviewed/cancelled 等 */
24
+ actionStatus?: string | null;
25
+ href?: string | null;
26
+ };
27
+ /**
28
+ * 场景键:优先能映射到已知场景的 eventKey → scene → category;
29
+ * 避免脏 category 压过正确 eventKey(如 action.status_changed)。
30
+ */
31
+ export declare function resolveInboxSceneKey(item: InboxItemActionSource): string;
32
+ export declare function inboxSceneLabel(item: InboxItemActionSource): string;
33
+ export declare function isInboxButtonDriven(item: InboxItemActionSource): boolean;
34
+ export declare function isTerminalActionStatus(status?: string | null): boolean;
35
+ /**
36
+ * 解析卡片底栏动作。
37
+ * 约定:禁用态不返回(由 normalize 再保险);终态任务只给「查看任务」;永不解析新建任务。
38
+ */
39
+ export declare function resolveInboxItemActions(n: InboxItemActionSource): InboxItemActionsResolved;
40
+ /** 去掉 disabled;主按钮空时把次按钮升格;统一主/次语义 */
41
+ export declare function normalizeInboxActions(resolved: InboxItemActionsResolved): InboxItemActionsResolved;
42
+ /** 铃铛永不展示「新建任务」(解析路径已停产;此处再防御) */
43
+ export declare function filterInboxActionsForHost(resolved: InboxItemActionsResolved, _hasItemAction: boolean): InboxItemActionsResolved;
@@ -0,0 +1,95 @@
1
+ const l = {
2
+ inspect_alert: "巡检预警",
3
+ claim_due: "认领到期",
4
+ claim_overdue: "认领到期",
5
+ dispose_escalation: "处置升级",
6
+ action_overdue: "行动超期",
7
+ action_assigned: "任务分配",
8
+ action_status_changed: "状态变更",
9
+ action_claimed: "任务认领",
10
+ action_followed: "任务跟进",
11
+ l3_parallel: "L3并行"
12
+ }, d = {
13
+ "alert.inspect": "inspect_alert",
14
+ "remind.claim_due": "claim_due",
15
+ "action.overdue": "action_overdue",
16
+ "action.assigned": "action_assigned",
17
+ "action.status_changed": "action_status_changed",
18
+ "action.status": "action_status_changed",
19
+ "action.due_soon": "action_overdue",
20
+ "action.claimed": "action_claimed",
21
+ "action.followed": "action_followed"
22
+ }, f = /* @__PURE__ */ new Set(["done", "reviewed", "cancelled", "closed"]);
23
+ function m(i) {
24
+ const e = String(i || "").trim().toLowerCase();
25
+ if (!e) return "";
26
+ if (l[e]) return e;
27
+ if (d[e]) return d[e];
28
+ const t = e.replace(/\./g, "_");
29
+ return l[t] ? t : e;
30
+ }
31
+ function p(i) {
32
+ return !!(i && l[i]);
33
+ }
34
+ function s(i) {
35
+ const e = [i.eventKey, i.scene, i.category].map((t) => m(t));
36
+ for (const t of e)
37
+ if (p(t)) return t;
38
+ return e.find(Boolean) || "";
39
+ }
40
+ function k(i) {
41
+ const e = s(i);
42
+ return e && l[e] || "";
43
+ }
44
+ function w(i) {
45
+ const e = s(i);
46
+ return e === "claim_due" || e === "claim_overdue" || e === "action_overdue" || e === "action_assigned" || e === "action_status_changed" || e === "action_claimed" || e === "action_followed" || e === "inspect_alert";
47
+ }
48
+ function _(i) {
49
+ return String(i || "").trim().toLowerCase();
50
+ }
51
+ function v(i) {
52
+ return f.has(_(i));
53
+ }
54
+ function y(i, e) {
55
+ return String(i.messageType || "").trim().toLowerCase() === "action" ? !0 : e.startsWith("action_") || e === "action_overdue" || e === "action_assigned" || e === "action_status_changed" || e === "action_claimed" || e === "action_followed";
56
+ }
57
+ function c(i, e) {
58
+ return e ? { primary: { kind: "view_task", label: "查看任务" } } : String(i.href || "").trim() ? { primary: { kind: "view_href", label: "查看" } } : { primary: { kind: "open_actions", label: "查看任务" } };
59
+ }
60
+ function g(i) {
61
+ const e = s(i), t = String(i.actionId || "").trim(), n = String(i.alertId || "").trim(), r = _(i.actionStatus), a = v(r), o = !!i.started || a || r === "in_progress" || e === "action_followed" || e === "action_claimed", u = !!i.claimed || !!t || e === "action_claimed";
62
+ return e === "claim_due" || e === "claim_overdue" ? u ? t ? { primary: { kind: "view_task", label: "查看任务" } } : { primary: { kind: "view_alert", label: "查看预警" } } : { primary: { kind: "claim_alert", label: "去认领" } } : e === "action_claimed" || e === "action_followed" || e === "action_status_changed" ? c(i, t) : e === "action_overdue" || e === "action_assigned" ? a || o ? c(i, t) : t ? { primary: { kind: "start_action", label: "去执行" } } : String(i.href || "").trim() ? { primary: { kind: "view_href", label: "查看" } } : {} : e === "dispose_escalation" ? t ? {
63
+ primary: { kind: "view_task", label: "查看任务" },
64
+ secondary: n ? { kind: "view_alert", label: "查看预警" } : void 0
65
+ } : {
66
+ primary: { kind: "view_alert", label: "查看预警" },
67
+ secondary: { kind: "open_actions", label: "去任务跟踪" }
68
+ } : e.startsWith("rca") || e === "rca_approved" ? { primary: { kind: "view_rca", label: "查看根因" } } : e === "inspect_alert" || e === "l3_parallel" ? t ? {
69
+ primary: { kind: "view_alert", label: "查看预警" },
70
+ secondary: { kind: "view_task", label: "查看任务" }
71
+ } : { primary: { kind: "view_alert", label: "查看预警" } } : y(i, e) ? a || o || e === "action_claimed" ? c(i, t) : t ? { primary: { kind: "start_action", label: "去执行" } } : c(i, t) : n ? t ? {
72
+ primary: { kind: "view_alert", label: "查看预警" },
73
+ secondary: { kind: "view_task", label: "查看任务" }
74
+ } : { primary: { kind: "view_alert", label: "查看预警" } } : t ? a || o ? { primary: { kind: "view_task", label: "查看任务" } } : { primary: { kind: "start_action", label: "去执行" } } : String(i.href || "").trim() ? { primary: { kind: "view_href", label: "查看" } } : {};
75
+ }
76
+ function b(i) {
77
+ const e = (r) => r && !r.disabled ? { ...r, disabled: void 0 } : void 0;
78
+ let t = e(i.primary), n = e(i.secondary);
79
+ return !t && n && (t = n, n = void 0), t && n && t.kind === n.kind && (n = void 0), { primary: t, secondary: n };
80
+ }
81
+ function S(i, e) {
82
+ const t = b(i), n = (o) => o && o.kind === "create_task" ? void 0 : o;
83
+ let r = n(t.primary), a = n(t.secondary);
84
+ return !r && a && (r = a, a = void 0), { primary: r, secondary: a };
85
+ }
86
+ export {
87
+ S as filterInboxActionsForHost,
88
+ k as inboxSceneLabel,
89
+ w as isInboxButtonDriven,
90
+ v as isTerminalActionStatus,
91
+ b as normalizeInboxActions,
92
+ g as resolveInboxItemActions,
93
+ s as resolveInboxSceneKey
94
+ };
95
+ //# sourceMappingURL=inboxItemActions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inboxItemActions.js","sources":["../../../../../src/components/Tools/Inbox/InboxBell/inboxItemActions.ts"],"sourcesContent":["export type InboxItemActionKind =\n | 'view_alert'\n | 'claim_alert'\n | 'start_action'\n | 'view_task'\n /** @deprecated 铃铛永不解析;保留类型以免破对外联合 */\n | 'create_task'\n | 'open_actions'\n | 'view_rca'\n | 'view_href';\n\nexport type InboxItemQuickAction = {\n kind: InboxItemActionKind;\n label: string;\n /** 解析中间态用;渲染前会被 normalize 丢掉,禁止灰显占位 */\n disabled?: boolean;\n};\n\nexport type InboxItemActionsResolved = {\n primary?: InboxItemQuickAction;\n secondary?: InboxItemQuickAction;\n};\n\nexport type InboxItemActionSource = {\n category?: string | null;\n scene?: string | null;\n eventKey?: string | null;\n messageType?: string | null;\n alertId?: string | null;\n actionId?: string | null;\n claimed?: boolean;\n started?: boolean;\n /** 行动项当前状态:approved/in_progress/done/reviewed/cancelled 等 */\n actionStatus?: string | null;\n href?: string | null;\n};\n\nconst SCENE_LABEL: Record<string, string> = {\n inspect_alert: '巡检预警',\n claim_due: '认领到期',\n claim_overdue: '认领到期',\n dispose_escalation: '处置升级',\n action_overdue: '行动超期',\n action_assigned: '任务分配',\n action_status_changed: '状态变更',\n action_claimed: '任务认领',\n action_followed: '任务跟进',\n l3_parallel: 'L3并行',\n};\n\nconst SCENE_ALIAS: Record<string, string> = {\n 'alert.inspect': 'inspect_alert',\n 'remind.claim_due': 'claim_due',\n 'action.overdue': 'action_overdue',\n 'action.assigned': 'action_assigned',\n 'action.status_changed': 'action_status_changed',\n 'action.status': 'action_status_changed',\n 'action.due_soon': 'action_overdue',\n 'action.claimed': 'action_claimed',\n 'action.followed': 'action_followed',\n};\n\nconst TERMINAL_STATUS = new Set(['done', 'reviewed', 'cancelled', 'closed']);\n\nfunction canonScene(raw?: string | null): string {\n const c = String(raw || '')\n .trim()\n .toLowerCase();\n if (!c) return '';\n if (SCENE_LABEL[c]) return c;\n if (SCENE_ALIAS[c]) return SCENE_ALIAS[c];\n const underscored = c.replace(/\\./g, '_');\n if (SCENE_LABEL[underscored]) return underscored;\n return c;\n}\n\n/** 是否已映射到 SCENE_LABEL 已知键(非原样回落的未知串) */\nfunction isKnownSceneKey(key: string): boolean {\n return Boolean(key && SCENE_LABEL[key]);\n}\n\n/**\n * 场景键:优先能映射到已知场景的 eventKey → scene → category;\n * 避免脏 category 压过正确 eventKey(如 action.status_changed)。\n */\nexport function resolveInboxSceneKey(item: InboxItemActionSource): string {\n const candidates = [item.eventKey, item.scene, item.category].map((x) => canonScene(x));\n for (const c of candidates) {\n if (isKnownSceneKey(c)) return c;\n }\n return candidates.find(Boolean) || '';\n}\n\nexport function inboxSceneLabel(item: InboxItemActionSource): string {\n const key = resolveInboxSceneKey(item);\n if (!key) return '';\n return SCENE_LABEL[key] || '';\n}\n\nexport function isInboxButtonDriven(item: InboxItemActionSource): boolean {\n const c = resolveInboxSceneKey(item);\n return (\n c === 'claim_due' ||\n c === 'claim_overdue' ||\n c === 'action_overdue' ||\n c === 'action_assigned' ||\n c === 'action_status_changed' ||\n c === 'action_claimed' ||\n c === 'action_followed' ||\n c === 'inspect_alert'\n );\n}\n\nfunction normStatus(raw?: string | null): string {\n return String(raw || '')\n .trim()\n .toLowerCase();\n}\n\nexport function isTerminalActionStatus(status?: string | null): boolean {\n return TERMINAL_STATUS.has(normStatus(status));\n}\n\nfunction isActionMessage(n: InboxItemActionSource, scene: string): boolean {\n const mt = String(n.messageType || '')\n .trim()\n .toLowerCase();\n if (mt === 'action') return true;\n return (\n scene.startsWith('action_') ||\n scene === 'action_overdue' ||\n scene === 'action_assigned' ||\n scene === 'action_status_changed' ||\n scene === 'action_claimed' ||\n scene === 'action_followed'\n );\n}\n\nfunction viewTaskOrHref(n: InboxItemActionSource, actionId: string): InboxItemActionsResolved {\n if (actionId) return { primary: { kind: 'view_task', label: '查看任务' } };\n if (String(n.href || '').trim()) return { primary: { kind: 'view_href', label: '查看' } };\n return { primary: { kind: 'open_actions', label: '查看任务' } };\n}\n\n/**\n * 解析卡片底栏动作。\n * 约定:禁用态不返回(由 normalize 再保险);终态任务只给「查看任务」;永不解析新建任务。\n */\nexport function resolveInboxItemActions(n: InboxItemActionSource): InboxItemActionsResolved {\n const c = resolveInboxSceneKey(n);\n const actionId = String(n.actionId || '').trim();\n const alertId = String(n.alertId || '').trim();\n const status = normStatus(n.actionStatus);\n const terminal = isTerminalActionStatus(status);\n const started =\n Boolean(n.started) ||\n terminal ||\n status === 'in_progress' ||\n c === 'action_followed' ||\n c === 'action_claimed';\n const claimed = Boolean(n.claimed) || Boolean(actionId) || c === 'action_claimed';\n\n if (c === 'claim_due' || c === 'claim_overdue') {\n if (claimed) {\n return actionId\n ? { primary: { kind: 'view_task', label: '查看任务' } }\n : { primary: { kind: 'view_alert', label: '查看预警' } };\n }\n return { primary: { kind: 'claim_alert', label: '去认领' } };\n }\n\n // 已认领 / 已跟进 / 状态变更:只看任务(勿落「查看预警」)\n if (c === 'action_claimed' || c === 'action_followed' || c === 'action_status_changed') {\n return viewTaskOrHref(n, actionId);\n }\n\n if (c === 'action_overdue' || c === 'action_assigned') {\n if (terminal || started) {\n return viewTaskOrHref(n, actionId);\n }\n if (!actionId) {\n return String(n.href || '').trim() ? { primary: { kind: 'view_href', label: '查看' } } : {};\n }\n return { primary: { kind: 'start_action', label: '去执行' } };\n }\n\n if (c === 'dispose_escalation') {\n if (actionId) {\n return {\n primary: { kind: 'view_task', label: '查看任务' },\n secondary: alertId ? { kind: 'view_alert', label: '查看预警' } : undefined,\n };\n }\n return {\n primary: { kind: 'view_alert', label: '查看预警' },\n secondary: { kind: 'open_actions', label: '去任务跟踪' },\n };\n }\n\n if (c.startsWith('rca') || c === 'rca_approved') {\n return { primary: { kind: 'view_rca', label: '查看根因' } };\n }\n\n if (c === 'inspect_alert' || c === 'l3_parallel') {\n if (actionId) {\n return {\n primary: { kind: 'view_alert', label: '查看预警' },\n secondary: { kind: 'view_task', label: '查看任务' },\n };\n }\n return { primary: { kind: 'view_alert', label: '查看预警' } };\n }\n\n // 行动类消息(含历史 category 空):优先任务,禁止误用「查看预警」\n if (isActionMessage(n, c)) {\n if (terminal || started || c === 'action_claimed') {\n return viewTaskOrHref(n, actionId);\n }\n if (actionId) {\n return { primary: { kind: 'start_action', label: '去执行' } };\n }\n return viewTaskOrHref(n, actionId);\n }\n\n if (alertId) {\n if (actionId) {\n return {\n primary: { kind: 'view_alert', label: '查看预警' },\n secondary: { kind: 'view_task', label: '查看任务' },\n };\n }\n return { primary: { kind: 'view_alert', label: '查看预警' } };\n }\n\n if (actionId) {\n if (terminal || started) return { primary: { kind: 'view_task', label: '查看任务' } };\n return { primary: { kind: 'start_action', label: '去执行' } };\n }\n\n if (String(n.href || '').trim()) {\n return { primary: { kind: 'view_href', label: '查看' } };\n }\n\n return {};\n}\n\n/** 去掉 disabled;主按钮空时把次按钮升格;统一主/次语义 */\nexport function normalizeInboxActions(\n resolved: InboxItemActionsResolved,\n): InboxItemActionsResolved {\n const usable = (a?: InboxItemQuickAction) =>\n a && !a.disabled ? { ...a, disabled: undefined } : undefined;\n let primary = usable(resolved.primary);\n let secondary = usable(resolved.secondary);\n if (!primary && secondary) {\n primary = secondary;\n secondary = undefined;\n }\n if (primary && secondary && primary.kind === secondary.kind) {\n secondary = undefined;\n }\n return { primary, secondary };\n}\n\n/** 铃铛永不展示「新建任务」(解析路径已停产;此处再防御) */\nexport function filterInboxActionsForHost(\n resolved: InboxItemActionsResolved,\n _hasItemAction: boolean,\n): InboxItemActionsResolved {\n const base = normalizeInboxActions(resolved);\n const dropCreate = (a?: InboxItemQuickAction) => (a && a.kind === 'create_task' ? undefined : a);\n let primary = dropCreate(base.primary);\n let secondary = dropCreate(base.secondary);\n if (!primary && secondary) {\n primary = secondary;\n secondary = undefined;\n }\n return { primary, secondary };\n}\n"],"names":["SCENE_LABEL","SCENE_ALIAS","TERMINAL_STATUS","canonScene","raw","c","underscored","isKnownSceneKey","key","resolveInboxSceneKey","item","candidates","x","inboxSceneLabel","isInboxButtonDriven","normStatus","isTerminalActionStatus","status","isActionMessage","n","scene","viewTaskOrHref","actionId","resolveInboxItemActions","alertId","terminal","started","claimed","normalizeInboxActions","resolved","usable","a","primary","secondary","filterInboxActionsForHost","_hasItemAction","base","dropCreate"],"mappings":"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"}
@@ -1,2 +1,4 @@
1
1
  export { default as InboxBell } from './InboxBell';
2
2
  export type { InboxBellItem, InboxBellListResult, InboxBellListParams, InboxBellProps, InboxBellMessageType, InboxBellHandle, } from './InboxBell';
3
+ export { resolveInboxItemActions, resolveInboxSceneKey, filterInboxActionsForHost, normalizeInboxActions, inboxSceneLabel, isInboxButtonDriven, isTerminalActionStatus, } from './inboxItemActions';
4
+ export type { InboxItemActionKind, InboxItemQuickAction, InboxItemActionsResolved, } from './inboxItemActions';
@@ -1,34 +1,74 @@
1
- const t = "_bellWrap_12frd_1", e = "_drawer_12frd_9", r = "_bellBtn_12frd_16", _ = "_typeTabs_12frd_35", i = "_filterRow_12frd_42", m = "_error_12frd_50", l = "_list_12frd_56", o = "_item_12frd_65", d = "_itemUnread_12frd_79", s = "_itemTitle_12frd_84", a = "_itemSummary_12frd_92", n = "_itemBodyHtml_12frd_100", f = "_itemMeta_12frd_120", c = "_typeTag_12frd_131", y = {
1
+ const t = "_bellWrap_wtkzr_2", e = "_drawer_wtkzr_10", o = "_listPane_wtkzr_23", s = "_listScroll_wtkzr_30", _ = "_listViewport_wtkzr_36", r = "_listFooter_wtkzr_40", i = "_bellBtn_wtkzr_49", a = "_typeTabs_wtkzr_68", c = "_filterRow_wtkzr_75", n = "_toastPrefs_wtkzr_83", m = "_toastPrefsTitle_wtkzr_91", l = "_toastPrefsHint_wtkzr_98", w = "_error_wtkzr_106", k = "_list_wtkzr_23", z = "_item_wtkzr_121", d = "_itemStatic_wtkzr_136", T = "_itemUnread_wtkzr_142", y = "_itemHeader_wtkzr_151", f = "_itemHeaderLeft_wtkzr_160", H = "_itemTitle_wtkzr_168", p = "_itemTime_wtkzr_179", B = "_itemBody_wtkzr_188", P = "_itemSummary_wtkzr_192", b = "_itemBodyHtml_wtkzr_204", S = "_typeTag_wtkzr_224", g = "_itemMeta_wtkzr_229", A = "_itemFooterTags_wtkzr_237", F = "_itemActions_wtkzr_245", u = "_toastNotice_wtkzr_252", D = "_toastHead_wtkzr_259", L = "_toastTitle_wtkzr_267", M = "_toastBody_wtkzr_274", N = "_toastDesc_wtkzr_278", R = "_toastActions_wtkzr_289", U = {
2
2
  bellWrap: t,
3
3
  drawer: e,
4
- bellBtn: r,
5
- typeTabs: _,
6
- filterRow: i,
7
- error: m,
8
- list: l,
9
- item: o,
10
- itemUnread: d,
11
- itemTitle: s,
12
- itemSummary: a,
13
- itemBodyHtml: n,
14
- itemMeta: f,
15
- typeTag: c
4
+ listPane: o,
5
+ listScroll: s,
6
+ listViewport: _,
7
+ listFooter: r,
8
+ bellBtn: i,
9
+ typeTabs: a,
10
+ filterRow: c,
11
+ toastPrefs: n,
12
+ toastPrefsTitle: m,
13
+ toastPrefsHint: l,
14
+ error: w,
15
+ list: k,
16
+ item: z,
17
+ itemStatic: d,
18
+ itemUnread: T,
19
+ itemHeader: y,
20
+ itemHeaderLeft: f,
21
+ itemTitle: H,
22
+ itemTime: p,
23
+ itemBody: B,
24
+ itemSummary: P,
25
+ itemBodyHtml: b,
26
+ typeTag: S,
27
+ itemMeta: g,
28
+ itemFooterTags: A,
29
+ itemActions: F,
30
+ toastNotice: u,
31
+ toastHead: D,
32
+ toastTitle: L,
33
+ toastBody: M,
34
+ toastDesc: N,
35
+ toastActions: R
16
36
  };
17
37
  export {
18
- r as bellBtn,
38
+ i as bellBtn,
19
39
  t as bellWrap,
20
- y as default,
40
+ U as default,
21
41
  e as drawer,
22
- m as error,
23
- i as filterRow,
24
- o as item,
25
- n as itemBodyHtml,
26
- f as itemMeta,
27
- a as itemSummary,
28
- s as itemTitle,
29
- d as itemUnread,
30
- l as list,
31
- _ as typeTabs,
32
- c as typeTag
42
+ w as error,
43
+ c as filterRow,
44
+ z as item,
45
+ F as itemActions,
46
+ B as itemBody,
47
+ b as itemBodyHtml,
48
+ A as itemFooterTags,
49
+ y as itemHeader,
50
+ f as itemHeaderLeft,
51
+ g as itemMeta,
52
+ d as itemStatic,
53
+ P as itemSummary,
54
+ p as itemTime,
55
+ H as itemTitle,
56
+ T as itemUnread,
57
+ k as list,
58
+ r as listFooter,
59
+ o as listPane,
60
+ s as listScroll,
61
+ _ as listViewport,
62
+ R as toastActions,
63
+ M as toastBody,
64
+ N as toastDesc,
65
+ D as toastHead,
66
+ u as toastNotice,
67
+ n as toastPrefs,
68
+ l as toastPrefsHint,
69
+ m as toastPrefsTitle,
70
+ L as toastTitle,
71
+ a as typeTabs,
72
+ S as typeTag
33
73
  };
34
74
  //# sourceMappingURL=style.module.scss.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"style.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,10 @@
1
+ /** 本机浏览器站内信弹出偏好(非租户策略)。 */
2
+ export type InboxToastMessageType = 'alert' | 'action' | 'remind';
3
+ export type InboxToastPrefs = Record<InboxToastMessageType, boolean>;
4
+ export declare const INBOX_TOAST_PREFS_KEY = "marsun-inbox-bell-toast-prefs";
5
+ /** 默认:预警/行动弹出,提醒仅角标 */
6
+ export declare const DEFAULT_INBOX_TOAST_PREFS: InboxToastPrefs;
7
+ export declare function normalizeInboxToastPrefs(raw: unknown): InboxToastPrefs;
8
+ export declare function loadInboxToastPrefs(): InboxToastPrefs;
9
+ export declare function saveInboxToastPrefs(prefs: InboxToastPrefs): void;
10
+ export declare function shouldToastForMessageType(prefs: InboxToastPrefs, messageType: string | undefined | null): boolean;
@@ -0,0 +1,46 @@
1
+ const a = "marsun-inbox-bell-toast-prefs", n = {
2
+ alert: !0,
3
+ action: !0,
4
+ remind: !1
5
+ };
6
+ function i(o) {
7
+ const e = { ...n };
8
+ if (!o || typeof o != "object") return e;
9
+ const t = o;
10
+ for (const r of ["alert", "action", "remind"])
11
+ typeof t[r] == "boolean" && (e[r] = t[r]);
12
+ return e;
13
+ }
14
+ function s() {
15
+ if (typeof window > "u" || !window.localStorage)
16
+ return { ...n };
17
+ try {
18
+ const o = window.localStorage.getItem(a);
19
+ return o ? i(JSON.parse(o)) : { ...n };
20
+ } catch {
21
+ return { ...n };
22
+ }
23
+ }
24
+ function f(o) {
25
+ if (!(typeof window > "u" || !window.localStorage))
26
+ try {
27
+ window.localStorage.setItem(
28
+ a,
29
+ JSON.stringify(i(o))
30
+ );
31
+ } catch {
32
+ }
33
+ }
34
+ function c(o, e) {
35
+ const t = String(e || "").trim().toLowerCase();
36
+ return t === "alert" || t === "action" || t === "remind" ? !!o[t] : !1;
37
+ }
38
+ export {
39
+ n as DEFAULT_INBOX_TOAST_PREFS,
40
+ a as INBOX_TOAST_PREFS_KEY,
41
+ s as loadInboxToastPrefs,
42
+ i as normalizeInboxToastPrefs,
43
+ f as saveInboxToastPrefs,
44
+ c as shouldToastForMessageType
45
+ };
46
+ //# sourceMappingURL=toastPrefs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toastPrefs.js","sources":["../../../../../src/components/Tools/Inbox/InboxBell/toastPrefs.ts"],"sourcesContent":["/** 本机浏览器站内信弹出偏好(非租户策略)。 */\n\nexport type InboxToastMessageType = 'alert' | 'action' | 'remind';\n\nexport type InboxToastPrefs = Record<InboxToastMessageType, boolean>;\n\nexport const INBOX_TOAST_PREFS_KEY = 'marsun-inbox-bell-toast-prefs';\n\n/** 默认:预警/行动弹出,提醒仅角标 */\nexport const DEFAULT_INBOX_TOAST_PREFS: InboxToastPrefs = {\n alert: true,\n action: true,\n remind: false,\n};\n\nexport function normalizeInboxToastPrefs(raw: unknown): InboxToastPrefs {\n const base = { ...DEFAULT_INBOX_TOAST_PREFS };\n if (!raw || typeof raw !== 'object') return base;\n const o = raw as Record<string, unknown>;\n for (const k of ['alert', 'action', 'remind'] as const) {\n if (typeof o[k] === 'boolean') base[k] = o[k];\n }\n return base;\n}\n\nexport function loadInboxToastPrefs(): InboxToastPrefs {\n if (typeof window === 'undefined' || !window.localStorage) {\n return { ...DEFAULT_INBOX_TOAST_PREFS };\n }\n try {\n const raw = window.localStorage.getItem(INBOX_TOAST_PREFS_KEY);\n if (!raw) return { ...DEFAULT_INBOX_TOAST_PREFS };\n return normalizeInboxToastPrefs(JSON.parse(raw));\n } catch {\n return { ...DEFAULT_INBOX_TOAST_PREFS };\n }\n}\n\nexport function saveInboxToastPrefs(prefs: InboxToastPrefs): void {\n if (typeof window === 'undefined' || !window.localStorage) return;\n try {\n window.localStorage.setItem(\n INBOX_TOAST_PREFS_KEY,\n JSON.stringify(normalizeInboxToastPrefs(prefs)),\n );\n } catch {\n /* quota / private mode:忽略 */\n }\n}\n\nexport function shouldToastForMessageType(\n prefs: InboxToastPrefs,\n messageType: string | undefined | null,\n): boolean {\n const key = String(messageType || '')\n .trim()\n .toLowerCase();\n if (key === 'alert' || key === 'action' || key === 'remind') {\n return Boolean(prefs[key]);\n }\n // 未知类型:不弹,只刷角标\n return false;\n}\n"],"names":["INBOX_TOAST_PREFS_KEY","DEFAULT_INBOX_TOAST_PREFS","normalizeInboxToastPrefs","raw","base","o","k","loadInboxToastPrefs","saveInboxToastPrefs","prefs","shouldToastForMessageType","messageType","key"],"mappings":"AAMO,MAAMA,IAAwB,iCAGxBC,IAA6C;AAAA,EACxD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AACV;AAEO,SAASC,EAAyBC,GAA+B;AACtE,QAAMC,IAAO,EAAE,GAAGH,EAAA;AAClB,MAAI,CAACE,KAAO,OAAOA,KAAQ,SAAU,QAAOC;AAC5C,QAAMC,IAAIF;AACV,aAAWG,KAAK,CAAC,SAAS,UAAU,QAAQ;AAC1C,IAAI,OAAOD,EAAEC,CAAC,KAAM,cAAWF,EAAKE,CAAC,IAAID,EAAEC,CAAC;AAE9C,SAAOF;AACT;AAEO,SAASG,IAAuC;AACrD,MAAI,OAAO,SAAW,OAAe,CAAC,OAAO;AAC3C,WAAO,EAAE,GAAGN,EAAA;AAEd,MAAI;AACF,UAAME,IAAM,OAAO,aAAa,QAAQH,CAAqB;AAC7D,WAAKG,IACED,EAAyB,KAAK,MAAMC,CAAG,CAAC,IAD9B,EAAE,GAAGF,EAAA;AAAA,EAExB,QAAQ;AACN,WAAO,EAAE,GAAGA,EAAA;AAAA,EACd;AACF;AAEO,SAASO,EAAoBC,GAA8B;AAChE,MAAI,SAAO,SAAW,OAAe,CAAC,OAAO;AAC7C,QAAI;AACF,aAAO,aAAa;AAAA,QAClBT;AAAA,QACA,KAAK,UAAUE,EAAyBO,CAAK,CAAC;AAAA,MAAA;AAAA,IAElD,QAAQ;AAAA,IAER;AACF;AAEO,SAASC,EACdD,GACAE,GACS;AACT,QAAMC,IAAM,OAAOD,KAAe,EAAE,EACjC,KAAA,EACA,YAAA;AACH,SAAIC,MAAQ,WAAWA,MAAQ,YAAYA,MAAQ,WAC1C,EAAQH,EAAMG,CAAG,IAGnB;AACT;"}
@@ -1,4 +1,6 @@
1
1
  export { InboxBell } from './InboxBell';
2
2
  export type { InboxBellItem, InboxBellListResult, InboxBellListParams, InboxBellProps, InboxBellMessageType, InboxBellHandle, } from './InboxBell';
3
+ export { resolveInboxItemActions, resolveInboxSceneKey, filterInboxActionsForHost, normalizeInboxActions, inboxSceneLabel, isInboxButtonDriven, isTerminalActionStatus, } from './InboxBell';
4
+ export type { InboxItemActionKind, InboxItemQuickAction, InboxItemActionsResolved, } from './InboxBell';
3
5
  export { sanitizeInboxHtml } from './sanitizeInboxHtml';
4
6
  export { INBOX_BADGE_REFRESH_EVENT, requestInboxBadgeRefresh, requestInboxBadgeRefreshAfterWrite, } from './requestInboxBadgeRefresh';
@@ -1,5 +1,6 @@
1
1
  export { InboxBell } from './Inbox';
2
- export type { InboxBellItem, InboxBellListResult, InboxBellListParams, InboxBellProps, InboxBellMessageType, InboxBellHandle, } from './Inbox';
2
+ export type { InboxBellItem, InboxBellListResult, InboxBellListParams, InboxBellProps, InboxBellMessageType, InboxBellHandle, InboxItemActionKind, InboxItemQuickAction, InboxItemActionsResolved, } from './Inbox';
3
+ export { resolveInboxItemActions, resolveInboxSceneKey, filterInboxActionsForHost, normalizeInboxActions, inboxSceneLabel, isInboxButtonDriven, isTerminalActionStatus, } from './Inbox';
3
4
  export { INBOX_BADGE_REFRESH_EVENT, requestInboxBadgeRefresh, requestInboxBadgeRefreshAfterWrite, } from './Inbox';
4
5
  export { ActionTrackingShell } from './ActionTracking';
5
6
  export type { ActionTrackingShellProps } from './ActionTracking';