影刀RPA 状态机模式在流程中的实现:订单从待处理到完成的状态流转
2026/7/21 7:53:02 网站建设 项目流程

影刀RPA 状态机模式:按数据状态调度不同处理逻辑

很多RPA流程本质上是"检查数据的状态 → 决定做什么"的循环。订单"待付款"要催付、"已付款"要发货、"已发货"要跟踪物流——每个状态对应不同的操作。

这种场景天然适合用状态机模式来设计流程。这篇文章讲怎么在影刀里实现。


什么是状态机

状态机三要素:

  1. 状态:数据当前处于什么阶段。比如订单的"待付款"“已付款”“已发货”“已完成”“已取消”。
  2. 事件:触发状态变化的原因。比如"用户付款"“超时自动取消”。
  3. 动作:状态变化时做什么。比如"已付款"→"扣库存+通知仓库"。

在RPA中,你通常不需要自己写状态机引擎。你只需要以状态为中心来组织流程逻辑,而不是以"操作步骤"为中心。


店群矩阵自动化突破运营极限!

以状态为中心的流程设计

传统写法(按步骤): 1. 从数据库取所有订单 2. 对每条订单判断状态 3. IF 待付款 → 发催付短信 4. ELIF 已付款 → 通知仓库 5. ELIF 已发货 → 更新物流 ... ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b069c9ded6684b5ca626f4cce84381dd.png#pic_center) 状态机写法(按状态): 状态A:待付款 → 超时30分钟?→ 发催付短信 → 待付款 状态B:已付款 → 推送到WMS → 已发货 状态C:已发货 → 查物流 → 已签收?→ 已完成

状态机写法的好处:每个状态的处理逻辑是独立的,加一个状态不影响其他状态。改"已付款"的处理逻辑,不用担心误伤"待付款"的处理。


实现:订单状态处理器

classOrderStateHandler:def__init__(self):self.handlers={'待付款':self.handle_pending_payment,'已付款':self.handle_paid,'已发货':self.handle_shipped,'已完成':self.handle_completed,'已取消':self.handle_cancelled,}defprocess_order(self,order):status=order['status']handler=self.handlers.get(status)ifhandler:print(f'订单{order["id"]}:状态={status},开始处理')new_status=handler(order)ifnew_statusandnew_status!=status:order['status']=new_statusprint(f' → 状态更新:{status}{new_status}')else:print(f'警告:未知状态{status}')defhandle_pending_payment(self,order):"""待付款:检查是否超时"""fromdatetimeimportdatetime created=datetime.strptime(order['created_time'],'%Y-%m-%d %H:%M:%S')elapsed=(datetime.now()-created).total_seconds()ifelapsed>1800:# 30分钟还没付款# 发催付通知print(f' 发催付短信给{order["phone"]}')return'待付款'# 状态不变,只是催付elifelapsed>3600:# 1小时自动取消# 取消订单,释放库存print(f' 自动取消订单,释放库存')return'已取消'returnNone# 不需要变更状态defhandle_paid(self,order):"""已付款:推送到仓库系统"""print(f' 推送订单到WMS:{order["id"]}')# 调用WMS API...return'已发货'defhandle_shipped(self,order):"""已发货:查物流,判断是否签收"""# 查物流APIlogistics=self.query_logistics(order['tracking_no'])iflogistics.get('status')=='签收':print(f' 已签收,订单完成')return'已完成'else:print(f' 物流状态:{logistics.get("status")}')returnNone# 状态不变defhandle_completed(self,order):"""已完成:什么也不做"""returnNonedefhandle_cancelled(self,order):"""已取消:什么也不做"""returnNonedefquery_logistics(self,tracking_no):# 模拟物流查询return{'status':'运输中'}# 使用handler=OrderStateHandler()orders=[{'id':1,'status':'待付款','phone':'138xxx','created_time':'2026-07-01 13:00:00'},{'id':2,'status':'已付款','phone':'139xxx','created_time':'2026-07-01 12:00:00'},{'id':3,'status':'已完成','phone':'137xxx','created_time':'2026-07-01 10:00:00'},]fororderinorders:handler.process_order(order)

在影刀中的实现

状态机模式在影刀中可以这样落地:

主流程:状态扫描器 1. 【读取数据库】→ 获取所有非终态的订单 终态 = ['已完成', '已取消'] 2. FOR EACH order IN orders: 【日志输出】f"处理订单 {order.id},状态:{order.status}" IF order.status == '待付款': 【运行子流程】handle_pending.flow ELIF order.status == '已付款': 【运行子流程】handle_paid.flow ELIF order.status == '已发货': 【运行子流程】handle_shipped.flow # 每个子流程可能更新状态,返回new_status IF new_status 和原状态不同: 【更新数据库】→ UPDATE order.status END FOR

每个子流程只干一件事:

handle_pending.flow: 1. 检查创建时间 2. 如果超时30分钟 → 发催付短信 3. 如果超时60分钟 → 取消订单,返回'已取消' 4. 否则 → 返回None(不更新状态) handle_paid.flow: 1. 调用WMS API推送订单 2. 推送成功 → 返回'已发货' 3. 推送失败 → 记录错误,返回None

状态转换图怎么画

设计状态机前,先画出状态转换图。不需要专业工具,在纸上画几个方框和箭头:

待付款 ──(超时)──→ 已取消 待付款 ──(付款)──→ 已付款 已付款 ──(推仓)──→ 已发货 已发货 ──(签收)──→ 已完成 已发货 ──(拒收)──→ 已取消

画完以后,每个箭头对应一个子流程。新增一个状态或转换只需要加一个箭头(子流程),不影响现有的。

temu店群自动化报活动案例


状态机的边界条件

做状态机最容易漏的是边界条件:

1. 并发修改。
A流程和B流程同时读到同一条订单,都判断为"待付款",都去发催付短信。客户连收两条一样的短信。

解决:处理前加乐观锁。

# 更新时检查状态是否还是原来的cursor.execute('UPDATE orders SET status = %s WHERE id = %s AND status = %s',(new_status,order_id,original_status))ifcursor.rowcount==0:print('状态已被其他流程修改,跳过')

2. 死循环。
状态从A→B→A→B循环,流程一直跑停不下来。

解决:加处理次数上限。每条记录每次扫描最多处理一次。

3. 终态节点。
“已完成”"已取消"这些状态不会再变化,应该从扫描范围里排除。否则你的流程每次都在扫描已完成的订单,白白浪费计算资源。


总结:状态机模式的核心是把"检查状态→执行动作→更新状态"这个循环标准化。每个状态的处理逻辑独立成子流程,加新状态不影响老状态。状态转换图画清楚再写代码,避免死循环和并发冲突。


作者:林焱

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询