ai-refactor(flow): 调整抽象流程节点实现和依赖路径

- 修改 AbstractProcessNode 中 ProcessContext 的命名空间引用为 app\flow\context\ProcessContext
- 引入 app\flow\vo\CanHandleResult 用于节点处理结果表示
- 更新前置策略执行后对成功状态的判断,改为调用 isSuccess() 方法
- 增加日志记录细节,便于调试策略执行中断时的错误信息
- 优化代码注释,提升代码可读性和维护性
This commit is contained in:
zimoyin
2026-03-11 00:48:10 +08:00
parent d303f3501f
commit e040fccba6
45 changed files with 819 additions and 2718 deletions
+47 -42
View File
@@ -3,6 +3,9 @@
namespace app\flow;
use app\flow\config\ProcessConfig;
use app\flow\context\ProcessContext;
use app\flow\context\ProcessContextBuilder;
use app\flow\enum\VoiceMessage;
use app\flow\OperatorSessionManager;
use app\net\PacketContext;
use app\repository\EctActionsRepository;
@@ -44,65 +47,67 @@ class FlowProcessor
public function process(PacketContext $packetContext, bool $isExecuteHandleResult = true): ProcessContext
{
// 从 PacketContext 创建 ProcessContext
$context = ProcessContext::fromPacketContext($packetContext,["engineConfig"=>$this->engine->getConfig()]);
$context = ProcessContextBuilder::fromPacketContext($packetContext, ["engineConfig" => $this->engine->getConfig()])->build();
Logger::debug("[{}] card: {} reader({}): {} {}: {} step: {}", [
$context->isOperatorCard ? '人员卡' : '内镜卡',
$context->cardNo,
empty($context->readerNo) ? '(未绑定)' : $context->readerNo,
$context->readerNo,
$context->isOperatorCard ? 'user' : 'endoscope',
$context->isOperatorCard ? $context->operatorName : ($context->endoscopeName ?: $context->endoscopeId ?: '(未绑定)'),
$context->currentStep ?: '(新流程)',
$context->isOperatorCard() ? '人员卡' : '内镜卡',
$context->isOperatorCard() ? $context->getOperator()->rfid : $context->getEndoscope()->cardNo,
empty($context->getReader()->no) ? '(未绑定)' : $context->getReader()->no,
$context->getReader()->no,
$context->isOperatorCard() ? 'user' : 'endoscope',
$context->isOperatorCard() ? $context->getOperator()->name : ($context->getEndoscope()->name ?: $context->getEndoscope()->id ?: '(未绑定)'),
$context->getCurrentStep() ?: '(新流程)',
]);
// 读卡器未绑定
if (empty($context->readerId)) {
Logger::error('读卡器未绑定,放弃处理 card={}', [$context->cardNo]);
$context->setError(VoiceMessage::READER_NOT_BOUND);
if (empty($context->getReader()->id)) {
Logger::error('读卡器未绑定,放弃处理 card={}', [$context->isOperatorCard() ? $context->getOperator()->rfid : $context->getEndoscope()->cardNo]);
$context = $context->builder()->error(VoiceMessage::READER_NOT_BOUND)->build();
$this->sendVoice($context);
return $context;
}
// 如果是人员卡,记录操作员信息后直接返回,不走流程链
if ($context->isOperatorCard) {
if ($context->isOperatorCard()) {
$mgr = OperatorSessionManager::getInstance();
$mgr->setOperator(
$context->readerId,
$context->operatorId,
$context->operatorName,
$context->operatorRfid
$context->getReader()->id,
$context->getOperator()->id,
$context->getOperator()->name,
$context->getOperator()->rfid
);
$context->setError(VoiceMessage::PLEASE_SWIPE_ENDOSCOPE);
$context = $context->builder()->error(VoiceMessage::PLEASE_SWIPE_ENDOSCOPE)->build();
$this->sendVoice($context);
return $context;
}
// 如果内镜未绑定,返回错误
if (empty($context->endoscopeId)) {
Logger::error('内镜未绑定,放弃处理 card={}', [$context->cardNo]);
$context->setError(VoiceMessage::CARD_NOT_BOUND);
if ($context->getEndoscope()->isEmpty()) {
Logger::error('内镜未绑定,放弃处理 card={}', [$context->getEndoscope()->cardNo]);
$context = $context->builder()->error(VoiceMessage::CARD_NOT_BOUND)->build();
$this->sendVoice($context);
return $context;
}
// 内镜卡:从 OperatorSessionManager 补充操作员信息
$mgr = OperatorSessionManager::getInstance();
if ($mgr->hasOperator($context->readerId) || $context->hasOperator()) {
if ($mgr->hasOperator($context->readerId)) {
$op = $mgr->getOperator($context->readerId, $context->readerType);
$context->operatorId = $op['id'];
$context->operatorName = $op['name'];
$context->operatorRfid = $op['rfid'];
if ($mgr->hasOperator($context->getReader()->id) || $context->hasOperator()) {
if ($mgr->hasOperator($context->getReader()->id)) {
$op = $mgr->getOperator($context->getReader()->id, $context->getReader()->type);
$context = $context->builder()->withOperator(new \app\flow\vo\OperatorInfo(
id: $op['id'],
name: $op['name'],
rfid: $op['rfid']
))->build();
}
} else {
// 未刷人员卡
Logger::warn('未刷人员卡 reader={} card={}', [
$context->readerId,
$context->cardNo,
$context->getReader()->id,
$context->getEndoscope()->cardNo,
]);
// 处理这个错误
$context->setError(VoiceMessage::PLEASE_SWIPE_OPERATOR);
$context = $context->builder()->error(VoiceMessage::PLEASE_SWIPE_OPERATOR)->build();
$this->handleResult($context);
return $context;
}
@@ -114,7 +119,7 @@ class FlowProcessor
if ($isExecuteHandleResult) $this->handleResult($result);
// 判断人员是否没有
if (empty($result->operatorId)) {
if (!$result->getOperator()->isValid()) {
Logger::error('[FlowProcessor] 结果集中人员不存在');
}
@@ -126,14 +131,14 @@ class FlowProcessor
*/
protected function handleResult(ProcessContext $context): void
{
if ($context->success) {
if ($context->isSuccess()) {
$repo = EctActionsRepository::new();
// 更新上一次的操作结束时间
$this->updateLastOperationEndTime($context, $repo);
// 数据库操作
if ($context->needDatabaseOperation) {
if ($context->needDatabaseOperation()) {
$this->saveToDatabase($context, $repo);
}
@@ -142,10 +147,10 @@ class FlowProcessor
$this->sendVoice($context);
// WebSocket通知
if ($context->needWebSocketNotify) {
if ($context->needWebSocketNotify()) {
Logger::debug('[FlowProcessor] 发送 WebSocket 通知 endoscope={} step={}', [
$context->endoscopeName,
$context->currentStep,
$context->getEndoscope()->name,
$context->getCurrentStep(),
]);
$this->sendWebSocketNotification($context);
}
@@ -153,7 +158,7 @@ class FlowProcessor
// 执行失败,播报错误信息
Logger::warn('流程失败,播报错误 voice={} error={}', [
$context->getFullVoice(),
$context->errorMessage,
$context->getVoice()->errorMessage,
]);
$this->sendVoice($context);
}
@@ -168,11 +173,11 @@ class FlowProcessor
*/
protected function updateLastOperationEndTime(ProcessContext $context, EctActionsRepository $actionsRepo): void
{
$lastAction = $context->previousAction;
$lastAction = $context->getPreviousAction();
$oldActionStartTime = $lastAction->op_starttime;
// 仅当旧批次未结束且流程类型不一致时更新
if ($lastAction->op_endtime === null && $lastAction->process_name != $context->readerType) {
if ($lastAction->op_endtime === null && $lastAction->process_name != $context->getReader()->type) {
$oldBatchNo = $lastAction->op_batchno;
$oldActionEndTime = date('Y-m-d H:i:s');
$oldDuration = strtotime($oldActionEndTime) - strtotime($oldActionStartTime);
@@ -189,12 +194,12 @@ class FlowProcessor
*/
protected function saveToDatabase(ProcessContext $context, EctActionsRepository $actionsRepo): void
{
$opuserType = $this->getOpusesType($context->operatorId);
$opuserType = $this->getOpusesType($context->getOperator()->id);
Logger::debug('[FlowProcessor] 写库 op={} step={} batch={}', [
$context->dbOperation,
$context->currentStep,
$context->batchNo,
$context->getDbOperations(),
$context->getCurrentStep(),
$context->getBatchNo(),
]);
try {