@composy/announcement-core
@composy/announcement-core
框架无关的企业公告核心库:以公告列表板、滚动播报条、详情弹窗三种形态发布信息,内置分类筛选、搜索、分页、置顶、已读管理、HTML 净化、亮暗主题与国际化。
✨ 核心能力
- 📌 公告列表板:
AnnouncementBoard/createAnnouncementBoard支持搜索、分类筛选、统计卡片与分页 - 📢 滚动播报条:
AnnouncementMarquee/createAnnouncementMarquee横向 / 纵向滚动,悬停暂停并尊重prefers-reduced-motion - 🗔 详情弹窗:
AnnouncementModal/createAnnouncementModal焦点圈定、背景滚动锁定、附件展示与阅读确认 - 🛡️ 安全渲染:
renderContentAs: 'html' | 'text'两种模式,配套sanitizeHtml/sanitizeUrl/stripHtml防 XSS - 🔍 数据工具:
searchAnnouncements/filterByCategory/sortAnnouncements/paginate/getAnnouncementStats纯函数处理 - 🎨 主题系统:
light/dark/system三种ThemeMode,ThemeManager+lightTokens/darkTokens/mergeThemeTokens - 🌐 国际化:内置中英文案(
zhCNLocale/enUSLocale),支持locale覆盖 - 📅 时间工具:
formatDate/relativeTime/isExpired处理发布与过期时间
📦 安装
pnpm add @composy/announcement-core
子路径导出:. 与 ./types。
🚀 快速开始
import {
createAnnouncementBoard,
createAnnouncementMarquee,
createAnnouncementModal,
} from '@composy/announcement-core'
const announcements = [
{
id: 'release-2026-06',
title: '版本发布窗口',
content: '发布窗口将于 22:00 开始。',
category: 'announcement',
priority: 'important',
pinned: true,
publishedAt: new Date().toISOString(),
author: 'Ops',
tags: ['release'],
attachments: [],
readCount: 0,
isRead: false,
},
]
const board = createAnnouncementBoard({
container: '#announcement-board',
announcements,
showSummary: true,
theme: 'system',
})
const marquee = createAnnouncementMarquee({
container: '#announcement-marquee',
announcements,
separator: ' | ',
})
const modal = createAnnouncementModal({
announcement: announcements[0],
confirmRead: true,
})
modal.open()
board.setThemeTokens({
light: {
colorPrimary: 'var(--ld-primary-default)',
spacingLg: 'var(--ld-spacing-xl)',
},
})
marquee.pause()
📖 API 参考
工厂与类
| 导出 | 说明 |
|---|---|
AnnouncementBoard / createAnnouncementBoard(config) |
公告列表板实例 |
AnnouncementMarquee / createAnnouncementMarquee(config) |
滚动播报条实例 |
AnnouncementModal / createAnnouncementModal(config) |
详情弹窗实例 |
EventEmitter |
类型化事件发射器 |
数据模型
Announcement
必填字段:id、title、content、category('notice' \| 'announcement' \| 'policy' \| 'event')、priority('normal' \| 'important' \| 'urgent')、pinned、publishedAt、author、tags、attachments、readCount、isRead;可选
expiresAt。
主要配置项
AnnouncementBoardConfig:container(必填)、announcements?、categories?、showPinned?、showSearch?、showCategoryFilter?、showSummary?、showUnreadOnlyToggle?(「仅看未读」切换按钮)、unreadOnly?(初始未读筛选)、markReadOnClick?(点击即标记已读,默认
true)、pageSize?、hideExpired?、searchDebounce?、searchFields?('title' \| 'content' \| 'author' \| 'tags')、maxVisibleTags?、sortOptions?、renderContentAs?、ariaLabel?、theme?、themeTokens?、locale?;回调
onRead、onClick、onSearch、onCategoryChange、onPageChange。
MarqueeConfig:container(必填)、announcements?、speed?、direction?: 'left' \| 'up'、autoPlay?、pauseOnHover?、hideExpired?、showCategoryLabel?、respectReducedMotion?、separator?、ariaLabel?、theme?、themeTokens?;回调
onClick。事件:click、play、pause。
ModalConfig:container?(弹窗挂载容器,缺省为
document.body)、announcement(必填)、confirmRead?、confirmText?、closable?、closeOnEscape?、closeOnBackdrop?、showAttachments?、renderContentAs?、theme?、themeTokens?;回调
onConfirm、onClose。事件:open、confirm(announcement)、close(按钮 / ESC / 遮罩 / 编程式
close() 关闭时触发一次;确认已读后的自动关闭不再触发)。
实例方法
| 实例 | 方法 |
|---|---|
| Board | getAnnouncements() / setAnnouncements(list) / addAnnouncement(item) / updateAnnouncement(id, patch) / removeAnnouncement(id) / clearAnnouncements() |
| Board | markAsRead(id) / markAllAsRead() / getUnreadCount() / getFilteredAnnouncements() / getStats() / getPagination() |
| Board | setCategory(category | 'all') / setSearch(keyword) / setPageSize(n) / setSortOptions(options) / setPage(page) |
| Board | setUnreadOnly(enabled) / isUnreadOnly() / openDetail(id) / closeDetail() |
| Board | setTheme(mode) / setThemeTokens(tokens?) / setLocale(overrides?) / updateOptions(options) / refresh() / destroy() |
| Marquee | getAnnouncements() / setAnnouncements(list) / play() / pause() / isPlaying() |
| Marquee | setSpeed(n)(即时生效)/ setDirection(dir) / setSeparator(str) / refresh() |
| Marquee | setTheme(mode) / setThemeTokens(tokens?) / setLocale(overrides?) / updateOptions(options) / destroy() |
| Modal | open() / close() / isOpen() / setAnnouncement(item)(打开中就地刷新内容) |
| Modal | setTheme(mode) / setThemeTokens(tokens?) / setLocale(overrides?) / updateOptions(options) / destroy() |
updateOptions接收除container/ 数据 / 事件回调之外的配置补丁,运行期立即生效;Modal 的container仅在创建时确定。所有查询结果和事件公告均为防御性快照;传入 HTMLElement 时 DOM、样式、主题和弹窗焦点均跟随其所属Document。addAnnouncement遇到同id条目时按更新处理,不会产生重复项。
工具函数导出
| 导出 | 说明 |
|---|---|
searchAnnouncements / filterByCategory / sortAnnouncements / paginate / getAnnouncementStats |
数据查询与统计 |
cloneAnnouncement / cloneAnnouncements / mergeAnnouncement |
公告快照与更新边界 |
sanitizeHtml / sanitizeUrl / stripHtml / setElementContent |
内容净化与安全写入 |
formatDate(value) / relativeTime(value, locale?) / isExpired(expiresAt?) |
时间格式化与有效期判断 |
ThemeManager、lightTokens / darkTokens / mergeThemeTokens |
主题管理与 token 合并 |
ensureAnnouncementDesignTokens |
设计令牌桥接注入 |
announcementClasses、ANNOUNCEMENT_CLASS_PREFIX、ANNOUNCEMENT_CSS_VAR_PREFIX |
类名常量与助手 |
🎨 样式与主题
- 所有 DOM 类名使用
ldesign-announcement-*前缀(如ldesign-announcement-board__shell)。 - 组件级 CSS 变量统一为
--ldesign-announcement-*。 - 默认 token 值引用由
packages/color与packages/size生成的var(--ld-*)变量。宿主应用需加载对应的 Color 与 Size CSS 变量,或在themeTokens中提供自定义变量。 - 运行时可通过配置项
themeTokens或实例方法setThemeTokens()覆盖,支持按light/dark分别指定。
🔨 构建产物与验证
使用 @composy/builder(ldesign-builder build)构建,产出:
packages/core/
├─ dist/ 浏览器 bundle
├─ es/ ESM 入口与类型声明
├─ esm/ 保留模块结构的 ESM
└─ lib/ CommonJS 入口与声明
验证命令(取自包 package.json):
pnpm build # Builder + 产物归一化和 exports 检查
pnpm type-check # ESM 类型检查
pnpm type-check:cjs # CJS 类型检查
pnpm lint:check # 使用 .ldesign/eslint.config.js 严格检查
Builder、ESLint 与 TypeScript 的权威配置分别位于
packages/core/.ldesign/;根目录配置文件只保留兼容转发入口。构建使用 @composy/builder
的默认 rolldown,并同步核对 dist、es、 esm、lib 与 package exports。
🔗 相关链接
- 工作区总览
@composy/announcement-vue— Vue 组件与组合式函数适配层
Related Packages
Version History
| Version | Released | License |
|---|---|---|
| 0.0.2 | MIT | |
| 0.0.1 | MIT |