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

如何在Hangfire仪表盘添加作业暂停/恢复、增删功能?

Hangfire仪表盘扩展:添加暂停/恢复、删除、新增作业功能

可以通过Hangfire提供的仪表盘扩展机制实现这些功能,官方虽无专门的可视化修改指南,但可利用内置钩子、自定义页面和API来完成扩展,具体步骤如下:

一、自定义仪表盘导航

通过IDashboardMenuFilter添加自定义菜单项,指向你的作业管理页面:

public class CustomDashboardMenuFilter : IDashboardMenuFilter
{
    public void OnMenuCreating(MenuCreatingContext context)
    {
        context.Items.Add(new MenuItem("作业管理", "/custom-job-manager")
        {
            Icon = "fa fa-cogs"
        });
    }
}

注册过滤器到Hangfire仪表盘:

app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
    MenuFilters = new[] { new CustomDashboardMenuFilter() }
});

二、实现作业操作的后台API

在应用中添加处理作业操作的端点,直接调用Hangfire的核心API完成对应操作:

// 暂停作业
[HttpPost("/api/hangfire/jobs/pause")]
public IActionResult PauseJob(string jobId)
{
    BackgroundJob.Pause(jobId);
    return Ok();
}

// 恢复作业
[HttpPost("/api/hangfire/jobs/resume")]
public IActionResult ResumeJob(string jobId)
{
    BackgroundJob.Resume(jobId);
    return Ok();
}

// 删除作业
[HttpPost("/api/hangfire/jobs/delete")]
public IActionResult DeleteJob(string jobId)
{
    BackgroundJob.Delete(jobId);
    return Ok();
}

// 新增作业
[HttpPost("/api/hangfire/jobs/add")]
public IActionResult AddJob(string jobType)
{
    switch(jobType)
    {
        case "Cleanup":
            BackgroundJob.Enqueue(() => CleanupService.Run());
            break;
        case "DataSync":
            BackgroundJob.Enqueue(() => DataSyncService.Sync());
            break;
    }
    return Ok();
}

// 获取作业列表(用于前端展示)
[HttpGet("/api/hangfire/jobs/list")]
public IActionResult GetJobs()
{
    var connection = JobStorage.Current.GetConnection();
    var jobIds = connection.GetRecurringJobs().Select(j => j.Id)
        .Union(connection.GetJobsCountByStateName("Enqueued") > 0 ? connection.GetJobsFromState("Enqueued") : new List<string>())
        .Union(connection.GetJobsCountByStateName("Suspended") > 0 ? connection.GetJobsFromState("Suspended") : new List<string>());
    
    var jobs = jobIds.Select(id => new 
    {
        Id = id,
        State = connection.GetJobData(id)?.State
    }).ToList();
    
    return Ok(jobs);
}

三、创建自定义作业管理页面

添加HTML页面(或Razor视图),通过AJAX调用上述API实现可视化操作,样式可复用Hangfire仪表盘的CSS类保持一致性:

<div class="hf-content">
    <h1 class="hf-title">作业管理</h1>
    <div class="hf-table-container">
        <table class="hf-table">
            <thead>
                <tr>
                    <th>作业ID</th>
                    <th>当前状态</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody id="jobTableBody">
                <!-- 动态加载作业列表 -->
            </tbody>
        </table>
    </div>

    <div class="hf-form" style="margin-top: 20px;">
        <h3>新增作业</h3>
        <select id="jobTypeSelect" class="hf-input">
            <option value="Cleanup">清理缓存作业</option>
            <option value="DataSync">数据同步作业</option>
        </select>
        <button onclick="addJob()" class="hf-btn hf-btn-primary">添加</button>
    </div>
</div>

<script>
// 加载作业列表
function loadJobs() {
    fetch('/api/hangfire/jobs/list')
        .then(res => res.json())
        .then(jobs => {
            const tbody = document.getElementById('jobTableBody');
            tbody.innerHTML = jobs.map(job => `
                <tr>
                    <td>${job.Id}</td>
                    <td>${job.State || "未知"}</td>
                    <td>
                        ${job.State === 'Suspended' ? 
                            `<button onclick="resumeJob('${job.Id}')" class="hf-btn hf-btn-success">恢复</button>` : 
                            `<button onclick="pauseJob('${job.Id}')" class="hf-btn hf-btn-warning">暂停</button>`}
                        <button onclick="deleteJob('${job.Id}')" class="hf-btn hf-btn-danger">删除</button>
                    </td>
                </tr>
            `).join('');
        });
}

// 暂停作业
function pauseJob(jobId) {
    fetch('/api/hangfire/jobs/pause', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ jobId })
    }).then(() => loadJobs());
}

// 恢复作业
function resumeJob(jobId) {
    fetch('/api/hangfire/jobs/resume', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ jobId })
    }).then(() => loadJobs());
}

// 删除作业
function deleteJob(jobId) {
    if(confirm('确定删除该作业?')) {
        fetch('/api/hangfire/jobs/delete', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ jobId })
        }).then(() => loadJobs());
    }
}

// 添加作业
function addJob() {
    const jobType = document.getElementById('jobTypeSelect').value;
    fetch('/api/hangfire/jobs/add', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ jobType })
    }).then(() => {
        loadJobs();
        alert('作业已添加');
    });
}

// 页面初始化加载
window.onload = loadJobs;
</script>

四、权限控制(可选)

如果需要限制操作权限,可自定义IAuthorizationFilter并注册到仪表盘:

public class CustomHangfireAuthFilter : IAuthorizationFilter
{
    public bool Authorize(DashboardContext context)
    {
        // 实现你的权限验证逻辑,比如检查当前用户是否为管理员
        var user = context.GetHttpContext().User;
        return user.IsInRole("Admin");
    }
}

// 注册到仪表盘
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
    Authorization = new[] { new CustomHangfireAuthFilter() },
    MenuFilters = new[] { new CustomDashboardMenuFilter() }
});

注意事项

  • 针对周期性作业(RecurringJob),需使用对应的API:RecurringJob.Pause(jobId)、RecurringJob.Resume(jobId)、RecurringJob.RemoveIfExists(jobId)
  • 作业状态可通过JobStorage.Current.GetConnection().GetJobData(jobId)获取
  • 自定义页面的路由需确保能被Hangfire仪表盘的上下文访问,可将页面嵌入到项目的静态文件目录或使用Razor视图路由

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:34:58