You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor应用浏览器最小化时如何显示SignalR任务栏通知

问题本质

你当前使用的SfToast是Blazor页面内渲染的UI组件,仅能在浏览器视口范围内展示。当浏览器最小化、标签页失焦切到后台时,页面内组件无法突破浏览器沙箱触达系统层面的通知栏,必须配合浏览器原生的Web Notifications API才能实现系统级弹窗提醒。

具体实现步骤
  • 第一步:封装JS交互方法
    在项目wwwroot目录下的JS文件中(没有就新建一个,记得在_Host.cshtml或index.html中引用)添加通知权限请求、系统通知弹出的逻辑:
// 请求桌面通知权限
window.requestNotifyPermission = async function () {
    if (!("Notification" in window)) return false;
    const res = await Notification.requestPermission();
    return res === "granted";
}

// 触发系统通知
window.showDesktopToast = function (title, content, icon, jumpPath) {
    // 无权限或页面当前处于激活状态时,不弹系统通知,走原有页内Toast逻辑
    if (Notification.permission !== "granted" || document.visibilityState === "visible") return;

    const notify = new Notification(title, {
        body: content,
        icon: icon,
        tag: "app-notify", // 同tag通知自动覆盖,避免重复堆叠
        renotify: true
    });

    // 点击通知自动切回应用窗口,可跳转至对应通知详情页
    notify.onclick = () => {
        window.focus();
        if (jumpPath) window.location.href = jumpPath;
        notify.close();
    };

    // 和原有页内Toast超时时间保持一致自动关闭
    setTimeout(() => notify.close(), 5000);
}
  • 第二步:改造Blazor端逻辑
    注入IJSRuntime用于JS互操作,调整SignalR消息接收逻辑,在页面后台时触发系统通知,同时补充你原有代码遗漏的Hub连接启动逻辑:
[Inject]
protected IJSRuntime JSRuntime { get; set; }

private HubConnection bpmHubConnection;
private bool _desktopNotifyEnabled = false;

protected async override Task OnInitializedAsync()
{
    bpmHubConnection = new HubConnectionBuilder()
            .WithUrl(ONEERP.Web.Models.SessionManager.BpmApiBaseAddress + "hubs/BPMBroadCastHub")
            .Build();

    bpmHubConnection.On<int, int, string, string>("SendNotification", async (userGroupID, userID, name, message) =>
    {
        if (SessionManager.UserID == userID)
        {
            CallLoadNotification();
            // 后台状态下触发系统通知
            if (_desktopNotifyEnabled)
            {
                await JSRuntime.InvokeVoidAsync("showDesktopToast",
                    "新通知提醒",
                    message,
                    "/images/notify-icon.png", // 替换为你自己的通知图标路径
                    "/notification/list"); // 替换为点击通知后要跳转的页面路径
            }
            StateHasChanged();
        }
    });

    // 原有代码遗漏了Hub连接启动,必须加上
    await bpmHubConnection.StartAsync();
}
  • 第三步:添加用户授权入口
    浏览器安全规则限制,通知权限必须由用户主动点击等交互行为触发申请,不能页面加载时自动请求(会被直接拦截)。在razor页面中添加授权按钮即可:
@* 未授权时显示开启按钮 *@
@if (!_desktopNotifyEnabled)
{
    <button class="btn btn-sm text-muted" @onclick=OpenDesktopNotify>
        开启桌面通知
    </button>
}

@* 原有Toast组件保留,页面激活时正常显示 *@
<SfToast ID="toastNotification" ShowCloseButton="true" @ref="ToastNotificationObj" Title="Notification" Content="@ToastNotificationContent" CssClass="@ToastNotificationStyle" Timeout=@ConstantClass.ToastTimeout Icon="e-meeting">
    <ToastPosition X="Right" Y="Bottom"></ToastPosition>
</SfToast>

@code {
    private async Task OpenDesktopNotify()
    {
        _desktopNotifyEnabled = await JSRuntime.InvokeAsync<bool>("requestNotifyPermission");
        StateHasChanged();
    }
}
注意事项
  • Web Notifications API仅在HTTPS环境下生效(本地localhost调试不受限制)
  • 系统通知的样式由操作系统决定,无法自定义成和Syncfusion页内Toast完全一致的外观
  • 如果需要更严格的后台存活能力,可以搭配Service Worker做离线通知,但普通业务场景下上述实现已经满足最小化/切后台时的提醒需求
  • 可以额外监听document的visibilitychange事件,实现更细粒度的弹窗策略,比如切后台超过30秒收到消息再弹系统通知,避免用户短暂切标签就被打扰

内容的提问来源于stack exchange,提问作者Muhammed Ismail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 19:48:30