工单SLA超时预警机制:从"客户催才知道超时"到"系统提前30分钟自动告警"

5 阅读6分钟

做过售后运维的都知道一个场景:客户打电话来骂"我报修了3天了怎么还没人来?"你去查工单——确实3天前报修的,一直没人处理。你赶紧安排工程师上门,再回头安抚客户。

这个问题的根因是:没有SLA(服务等级协议)预警机制。 工单超时了没人知道,等到客户催才发现。

我在搭贝低代码平台上设计了一套工单引擎,核心就是SLA超时预警。这篇文章拆解预警机制的技术实现。

一、SLA是什么,怎么定

SLA(Service Level Agreement)就是服务等级承诺。售后工单的SLA通常包含两个指标:

响应时间。 从客户报修到工程师首次联系客户的时间。紧急故障SLA可能要求2小时内响应。

解决时间。 从客户报修到工单完成关闭的时间。紧急故障SLA可能要求24小时内解决。

不同优先级的工单有不同的SLA:

紧急(P1):响应2h,解决24h
高(P2):响应4h,解决48h
中(P3):响应8h,解决5个工作日
低(P4):响应24h,解决10个工作日

SLA不是拍脑袋定的,是根据客户合同和服务能力协商的。你承诺的SLA越短,需要的工程师就越多。

二、SLA计时器的核心设计

SLA预警的核心是精确计时。但计时不是简单的"创建时间到现在的时间差"——有几个复杂因素要处理:

因素一:工作时间排除

SLA通常是"工作小时内"计时。周五晚上10点报修的工单,SLA从周一早上9点开始算。

from datetime import datetime, timedelta

WORK_START = 9  # 早上9点
WORK_END = 18   # 下午6点

def calculate sla_deadline(create_time, priority, work_calendar):
    """计算SLA截止时间(仅计算工作时间)"""
    sla_config = {
        'P1': {'response_hours': 2, 'resolve_hours': 24},
        'P2': {'response_hours': 4, 'resolve_hours': 48},
        'P3': {'response_hours': 8, 'resolve_hours': 120},  # 5个工作日
        'P4': {'response_hours': 24, 'resolve_hours': 240}, # 10个工作日
    }
    
    config = sla_config[priority]
    response_deadline = add_work_hours(
        create_time, config['response_hours'], work_calendar
    )
    resolve_deadline = add_work_hours(
        create_time, config['resolve_hours'], work_calendar
    )
    
    return {
        'response_deadline': response_deadline,
        'resolve_deadline': resolve_deadline
    }

def add_work_hours(start, hours, calendar):
    """在工作时间基础上加指定小时数"""
    current = start
    remaining = hours
    
    while remaining > 0:
        # 跳过非工作日
        if current.weekday() >= 5 or is_holiday(current, calendar):
            current = next_workday(current)
            continue
        
        # 计算今天剩余工作时间
        today_work_start = current.replace(hour=WORK_START, minute=0)
        today_work_end = current.replace(hour=WORK_END, minute=0)
        
        if current < today_work_start:
            current = today_work_start
        
        available_today = (today_work_end - current).total_seconds() / 3600
        if available_today <= 0:
            current = next_workday(current)
            continue
        
        if remaining <= available_today:
            current = current + timedelta(hours=remaining)
            remaining = 0
        else:
            remaining -= available_today
            current = next_workday(current)
    
    return current

因素二:暂停计时

有些场景SLA计时需要暂停:

  • 等客户寄送配件(客户原因导致的等待)
  • 等供应商技术支持(第三方原因)
  • 工程师已经联系客户但客户约了明天上门(客户改约)
def pause_sla_timer(ticket_id, reason):
    """暂停SLA计时"""
    active = get_active_timer(ticket_id)
    if active:
        db.update('sla_timer', active['id'], {
            'paused_at': now(),
            'pause_reason': reason
        })

def resume_sla_timer(ticket_id):
    """恢复SLA计时"""
    paused = get_paused_timer(ticket_id)
    if paused:
        pause_duration = now() - paused['paused_at']
        # 把暂停时长加到deadline上
        new_deadline = paused['original_deadline'] + pause_duration
        db.update('sla_timer', paused['id'], {
            'resumed_at': now(),
            'adjusted_deadline': new_deadline
        })

因素三:升级触发

当SLA即将超时或已经超时,系统自动触发升级动作:

def check_sla_alerts():
    """定时任务:每5分钟检查一次SLA状态"""
    active_tickets = get_all_active_tickets()
    
    for ticket in active_tickets:
        sla = get_sla_status(ticket['id'])
        
        # 预警:距离超时还有30分钟
        if sla['time_remaining'] < 30 and not sla['warning_sent']:
            send_alert(
                to=ticket['assignee'],
                msg=f"⚠️ 工单{ticket['code']}即将SLA超时!"
                    f"剩余时间:{sla['time_remaining']}分钟"
            )
            mark_warning_sent(ticket['id'])
        
        # 响应超时:通知主管
        if sla['response_overdue'] and not sla['escalated']:
            send_alert(
                to=ticket['assignee']['manager'],
                msg=f"🔴 工单{ticket['code']}响应已超时!"
                    f"客户等待时间:{sla['response_overdue_by']}"
            )
            escalate_ticket(ticket['id'], level=1)
        
        # 解决超时:升级到更高层级
        if sla['resolve_overdue'] and sla['escalation_level'] < 2:
            send_alert(
                to=get_service_director(),
                msg=f"🔴 工单{ticket['code']}解决已超时!"
                    f"超时时长:{sla['resolve_overdue_by']}"
            )
            escalate_ticket(ticket['id'], level=2)

三、在搭贝平台上的实现方式

搭贝低代码平台的SLA实现用了三种机制组合:

定时任务。 每5分钟运行一次SLA检查脚本。检查所有活跃工单的SLA状态,发送预警。

审批流触发。 工单状态变更时(如工程师接单、处理完成),流程节点触发SLA计时器的启动/暂停/恢复。

消息推送。 预警和超时通知通过企微/钉钉推送给对应人员。

四、上线后的效果

指标旧方式SLA预警系统
响应超时率22%3%
解决超时率35%8%
客户投诉率月均8次月均1次
工程师人均工单数看不清实时可见,负载均衡

最有价值的变化是从被动响应变成主动预警。 以前是客户催了才发现超时,现在是超时前30分钟系统先预警,工程师有30分钟窗口赶在SLA红线前响应。客户体验完全不同。

还有一个意料之外的收益:SLA数据量化后,发现某个客户的工单量是其他客户的3倍,但合同价格一样。销售拿这个数据去谈续约,涨价20%。

常见问题

Q1:低代码MES和专业MES系统差距大吗?

功能深度有差距。专业MES(如西门子Camstar)在实时设备集成、SPC统计分析、高级排程算法等方面更强。低代码MES覆盖了80%的中小制造企业需求——工单管理、报工记录、质量追溯、生产看板。对于年营收5000万-2亿的中小企业,低代码MES够用且性价比远超专业MES。

Q2:车间的老设备没有数据接口,低代码能做数据采集吗?

不能自动采集,但可以半自动。方案:设备操作员在工位平板或手机上手动录入关键参数(如温度、压力、产量),系统记录时间戳和操作人。如果设备有串口或OPC接口,可以通过脚本扩展定期轮询采集数据。

Q3:生产报工数据不准怎么办?

系统上线初期数据不准是正常的。解决方法:1)扫码报工——工人扫工单二维码+扫员工卡,系统自动记录人和时间,减少手工输入错误;2)车间大屏实时显示报工数据,异常立即发现;3)报工数据与出入库数据交叉验证,差异超过5%自动预警。