Appearance
BizAnnouncement 系统公告
系统公告弹窗:ElDialog 封装(append-to-body / destroy-on-close / width 受控)。等级头部条——info 常规(primary + InfoFilled)、warning 警告(WarningFilled)、important 重要(danger + Bell + 「重要」徽标);正文按 \n 分段,发布者 / 时间脚注;「今日不再提示」复选按日静默(localStorage),open() 编程入口自动跳过已静默日;关闭时回传阅读时长(read-report)。系统升级、停机维护、运营活动通知。
基础用法
visible:false;closed 事件触发次数:0(确认 / 关闭后 v-model 置 false)
v-model 控制显隐;content 用 \n 分段;确认或关闭后回传 closed。<script setup lang="ts">
/** 场景:基础——v-model 显隐 + \n 分段正文 */
import { ref } from 'vue'
import { ElButton } from 'element-plus'
import { BizAnnouncement } from 'vue3-ep-biz-lib'
const visible = ref(false)
const closedCount = ref(0)
const onClosed = (): void => {
closedCount.value += 1
}
</script>
<template>
<div>
<ElButton type="primary" @click="visible = true">查看系统公告</ElButton>
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
visible:{{ visible }};closed 事件触发次数:{{ closedCount }}(确认 / 关闭后 v-model 置 false)
</p>
<BizAnnouncement
v-model="visible"
title="系统升级通知"
content="系统将于 2026-10-26 02:00 - 04:00 进行版本升级。\n升级期间平台暂停访问,请提前保存工作内容。\n升级完成后将支持批量导出与自定义报表能力。"
@closed="onClosed"
/>
</div>
</template>
显示代码
等级
当前等级:info(info=primary+InfoFilled、warning+WarningFilled、danger+Bell+「重要」徽标)
info / warning / important 三级:头部色条与图标随等级切换,important 追加「重要」徽标。
<script setup lang="ts">
/** 场景:等级——info / warning / important */
import { ref } from 'vue'
import { ElButton } from 'element-plus'
import { BizAnnouncement } from 'vue3-ep-biz-lib'
type Level = 'info' | 'warning' | 'important'
const visible = ref(false)
const level = ref<Level>('info')
const show = (next: Level): void => {
level.value = next
visible.value = true
}
</script>
<template>
<div>
<ElButton @click="show('info')">info 常规</ElButton>
<ElButton @click="show('warning')">warning 警告</ElButton>
<ElButton type="danger" plain @click="show('important')">important 重要</ElButton>
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
当前等级:{{ level }}(info=primary+InfoFilled、warning+WarningFilled、danger+Bell+「重要」徽标)
</p>
<BizAnnouncement
v-model="visible"
:level="level"
title="等级示例"
content="info:常规功能上线通知。\nwarning:请留意账户余额与到期时间。\nimportant:安全策略变更,请尽快处理。"
/>
</div>
</template>
显示代码
今日不再提示
今日已静默:false;最近一次 open() 返回:—
勾选后确认 / 关闭写入当日静默记录;
open() 当日返回 false 不再打开;clearMute() 清除记录恢复弹窗。<script setup lang="ts">
/** 场景:今日不再提示——按日静默 + clearMute 恢复 */
import { onMounted, ref } from 'vue'
import { ElButton, ElMessage } from 'element-plus'
import { BizAnnouncement } from 'vue3-ep-biz-lib'
import type { BizAnnouncementInstance } from 'vue3-ep-biz-lib'
const annRef = ref<BizAnnouncementInstance>()
const visible = ref(false)
const muted = ref(false)
const lastOpenResult = ref<boolean | null>(null)
const refreshMuted = (): void => {
muted.value = annRef.value?.isMutedToday() ?? false
}
const openByApi = (): void => {
const ok = annRef.value?.open() ?? false
lastOpenResult.value = ok
if (!ok) ElMessage.warning('今日已静默,open() 返回 false 不再打开')
}
const clear = (): void => {
annRef.value?.clearMute()
lastOpenResult.value = null
refreshMuted()
ElMessage.success('静默记录已清除,可重新打开')
}
onMounted(refreshMuted)
</script>
<template>
<div>
<ElButton type="primary" @click="openByApi">open() 打开公告</ElButton>
<ElButton :disabled="!muted" @click="clear">clearMute() 恢复</ElButton>
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
今日已静默:{{ muted }};最近一次 open() 返回:{{ lastOpenResult === null ? '—' : String(lastOpenResult) }}
</p>
<BizAnnouncement
ref="annRef"
v-model="visible"
title="每日巡检提醒"
content="勾选「今日不再提示」并确认后,本日不再弹出。\n点击 clearMute() 可清除静默记录重新打开。"
storage-key="biz-announcement-mute-demo"
@closed="refreshMuted"
/>
</div>
</template>
显示代码
富内容插槽
默认插槽放置富内容(时间线、标签等);publisher / publishTime 脚注仍正常渲染。
默认插槽替换正文,可放 ElAlert、列表等富内容;publisher / publishTime 脚注仍可用。
<script setup lang="ts">
/** 场景:富内容插槽——默认插槽替换正文 */
import { ref } from 'vue'
import { ElButton, ElTag, ElTimeline, ElTimelineItem } from 'element-plus'
import { BizAnnouncement } from 'vue3-ep-biz-lib'
const visible = ref(false)
</script>
<template>
<div>
<ElButton type="primary" @click="visible = true">版本更新公告</ElButton>
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
默认插槽放置富内容(时间线、标签等);publisher / publishTime 脚注仍正常渲染。
</p>
<BizAnnouncement
v-model="visible"
title="v2.8.0 版本更新"
publisher="平台产品团队"
publish-time="2026-10-18 10:00"
level="info"
>
<ElTimeline style="padding-left: 2px">
<ElTimelineItem timestamp="新增" type="primary">
报表中心支持自定义指标与批量导出
</ElTimelineItem>
<ElTimelineItem timestamp="优化" type="success">
列表页加载速度提升约 40%
</ElTimelineItem>
<ElTimelineItem timestamp="修复" type="warning">
修复部分浏览器下附件预览失败的问题
</ElTimelineItem>
</ElTimeline>
<div>
<ElTag size="small" effect="plain">灰度发布</ElTag>
<ElTag size="small" type="info" effect="plain">全量预计 3 天内完成</ElTag>
</div>
</BizAnnouncement>
</div>
</template>
显示代码
自定义底栏
#footer 完全替换默认底栏(确认按钮 + 今日不再提示复选不再渲染)。
#footer 插槽替换默认底栏(确认按钮 + 今日不再提示复选)。<script setup lang="ts">
/** 场景:自定义底栏——#footer 插槽替换默认按钮区 */
import { onUnmounted, ref } from 'vue'
import { ElButton, ElMessage } from 'element-plus'
import { BizAnnouncement } from 'vue3-ep-biz-lib'
const visible = ref(false)
const agreeLoading = ref(false)
let timer: ReturnType<typeof setTimeout> | null = null
/** 自定义底栏:模拟阅读并同意协议后关闭 */
const onAgree = (): void => {
agreeLoading.value = true
if (timer !== null) clearTimeout(timer)
timer = setTimeout(() => {
agreeLoading.value = false
visible.value = false
ElMessage.success('已同意并关闭公告')
}, 800)
}
onUnmounted(() => {
if (timer !== null) clearTimeout(timer)
})
</script>
<template>
<div>
<ElButton type="primary" @click="visible = true">打开合规公告</ElButton>
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
#footer 完全替换默认底栏(确认按钮 + 今日不再提示复选不再渲染)。
</p>
<BizAnnouncement
v-model="visible"
title="平台服务协议更新"
level="important"
content="为向你提供更好的服务,平台服务协议已更新。\n请阅读并确认后继续使用,未确认将影响部分功能访问。"
>
<template #footer>
<div style="display: flex; justify-content: flex-end; gap: 10px; width: 100%">
<ElButton @click="visible = false">暂不同意</ElButton>
<ElButton type="primary" :loading="agreeLoading" @click="onAgree">阅读并同意</ElButton>
</div>
</template>
</BizAnnouncement>
</div>
</template>
显示代码
阅读时长上报
最近一次 read-report: (暂无,打开几秒后再关闭试试)
打开起计时,弹窗以任意方式关闭时
read-report 回传 { title, durationMs },用于运营统计触达效果。<script setup lang="ts">
/** 场景:阅读时长上报——read-report 回显 */
import { ref } from 'vue'
import { ElButton } from 'element-plus'
import { BizAnnouncement } from 'vue3-ep-biz-lib'
import type { BizAnnouncementReadReport } from 'vue3-ep-biz-lib'
const visible = ref(false)
const lastReport = ref<BizAnnouncementReadReport | null>(null)
const onReadReport = (report: BizAnnouncementReadReport): void => {
lastReport.value = report
}
</script>
<template>
<div>
<ElButton type="primary" @click="visible = true">打开公告并阅读</ElButton>
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
最近一次 read-report:
{{
lastReport === null
? '(暂无,打开几秒后再关闭试试)'
: `「${lastReport.title}」阅读 ${lastReport.durationMs}ms(约 ${Math.round(lastReport.durationMs / 100) / 10} 秒)`
}}
</p>
<BizAnnouncement
v-model="visible"
title="运营活动上线"
content="双 11 预售活动 10 月 24 日 20:00 正式开启。\n全场企业版许可续费享 8 折优惠。\n活动详情请咨询客户成功经理。"
:dont-show-again="false"
@read-report="onReadReport"
/>
</div>
</template>
显示代码
发布者与时间
publisher / publishTime 渲染为正文下方 secondary 小字脚注(二者可只传其一)。
publisher / publishTime 渲染为正文下方 secondary 小字脚注。<script setup lang="ts">
/** 场景:发布者与时间——脚注展示 */
import { ref } from 'vue'
import { ElButton } from 'element-plus'
import { BizAnnouncement } from 'vue3-ep-biz-lib'
const visible = ref(false)
</script>
<template>
<div>
<ElButton type="primary" @click="visible = true">查看停机维护公告</ElButton>
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
publisher / publishTime 渲染为正文下方 secondary 小字脚注(二者可只传其一)。
</p>
<BizAnnouncement
v-model="visible"
title="停机维护通知"
level="warning"
content="平台将于 2026-10-24 00:00 - 06:00 进行数据库迁移维护。\n维护期间所有服务暂停访问,任务自动顺延。\n如有疑问请提交工单或联系值班工程师。"
publisher="运维值班组 王磊"
publish-time="2026-10-20 17:30"
/>
</div>
</template>
显示代码
受控与遮罩点击
弹窗打开时切换开关不生效(destroy-on-close 下按本次打开配置渲染);任意方式关闭都会触发 closed。
close-on-click-modal 允许点遮罩快速关闭(默认 false 防误触);show-close 控制右上角关闭按钮。<script setup lang="ts">
/** 场景:受控与遮罩点击——close-on-click-modal / show-close */
import { ref } from 'vue'
import { ElButton, ElMessage } from 'element-plus'
import { BizAnnouncement } from 'vue3-ep-biz-lib'
const visible = ref(false)
const allowModal = ref(true)
const showClose = ref(true)
const openDialog = (): void => {
visible.value = true
ElMessage.info(`遮罩关闭:${allowModal.value ? '开' : '关'},右上角关闭按钮:${showClose.value ? '显示' : '隐藏'}`)
}
</script>
<template>
<div>
<div style="display: flex; align-items: center; gap: 12px; flex-wrap: wrap">
<ElButton type="primary" @click="openDialog">打开公告</ElButton>
<ElButton :disabled="visible" @click="allowModal = !allowModal">
遮罩关闭:{{ allowModal ? '开' : '关' }}
</ElButton>
<ElButton :disabled="visible" @click="showClose = !showClose">
关闭按钮:{{ showClose ? '显示' : '隐藏' }}
</ElButton>
</div>
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
弹窗打开时切换开关不生效(destroy-on-close 下按本次打开配置渲染);任意方式关闭都会触发 closed。
</p>
<BizAnnouncement
v-model="visible"
title="会话即将过期"
level="warning"
content="你的登录会话将于 10 分钟后过期。\n点击任意位置重新登录可继续当前操作。"
:close-on-click-modal="allowModal"
:show-close="showClose"
:dont-show-again="false"
/>
</div>
</template>
显示代码
尺寸与文案
width 支持 number(px)与 string(百分比 / 'auto');show-footer=false 时为纯展示公告。
width 支持 number(px)与 string;title / confirm-text 自定义文案;show-footer=false 隐藏底栏做纯展示。<script setup lang="ts">
/** 场景:尺寸与文案——width / confirm-text / show-footer */
import { ref } from 'vue'
import { ElButton } from 'element-plus'
import { BizAnnouncement } from 'vue3-ep-biz-lib'
const visible = ref(false)
const width = ref<number | string>(380)
const showFooter = ref(true)
const openDialog = (next: number | string, footer: boolean): void => {
width.value = next
showFooter.value = footer
visible.value = true
}
</script>
<template>
<div>
<ElButton @click="openDialog(380, true)">小尺寸 380</ElButton>
<ElButton @click="openDialog(720, true)">宽尺寸 720</ElButton>
<ElButton @click="openDialog('46%', false)">百分比 + 无底栏</ElButton>
<p style="margin: 10px 0 0; font-size: 12px; color: var(--el-text-color-secondary)">
width 支持 number(px)与 string(百分比 / 'auto');show-footer=false 时为纯展示公告。
</p>
<BizAnnouncement
v-model="visible"
title="隐私政策摘要"
confirm-text="同意并继续"
:width="width"
:show-footer="showFooter"
:dont-show-again="false"
content="我们高度重视用户个人信息保护。\n本摘要提示数据收集范围:账号信息、操作日志与必要设备信息。\n完整政策请前往「设置 - 隐私」查看。"
/>
</div>
</template>
显示代码
Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| v-model | boolean | false | 显隐(双向) |
| title | string | '系统公告' | 公告标题 |
| level | 'info' | 'warning' | 'important' | 'info' | 等级(头部条颜色与图标) |
| content | string | '' | 正文(\n 分段渲染) |
| publisher | string | '' | 发布者(脚注) |
| publish-time | string | '' | 发布时间(脚注) |
| confirm-text | string | '我知道了' | 确认按钮文案 |
| show-footer | boolean | true | 显示底栏 |
| dont-show-again | boolean | true | 显示「今日不再提示」复选 |
| storage-key | string | 'biz-announcement-mute' | 静默记录 localStorage key |
| width | number | string | 520 | 弹窗宽度(number 按 px) |
| close-on-click-modal | boolean | false | 点击遮罩关闭 |
| show-close | boolean | true | 右上角关闭按钮 |
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
| update:modelValue | (value: boolean) | 显隐变化 |
| confirm | — | 点击确认按钮(随后自动关闭) |
| open | — | 弹窗打开 |
| closed | — | 弹窗关闭(任意方式,动画结束) |
| read-report | (report: { title: string; durationMs: number }) | 阅读上报:关闭时回传标题与阅读时长 |
Slots
| 插槽名 | 说明 |
|---|---|
| default | 替换正文(默认按 \n 分段渲染 content) |
| footer | 替换底栏(默认确认按钮 + 今日不再提示) |
Expose
| 名称 | 类型 | 说明 |
|---|---|---|
| open | () => boolean | 打开公告;今日已静默返回 false 不打开,成功打开返回 true |
| close | () => void | 关闭公告 |
| clearMute | () => void | 清除「今日不再提示」静默记录 |
| isMutedToday | () => boolean | 今日是否已静默 |