ai-chore(config): 调整流程配置及改进测试代码
- 将 FLOW_USE_CUSTOM_PROCESS 从 true 改为 false,禁用自定义流程 - 在 BlockTest 测试用例中改用 setBlockMode 方法设置阻断模式 - 设置统一的错误处理,将错误转为异常抛出 - 重命名 BlockTest 测试文件路径,优化测试组织结构 - 更新 IDE php include paths,调整依赖包引用顺序 - 删除无用的 tests/flow/Test.php 测试文件 - 微调 start.php、webman、windows.php 配置或代码模块
This commit is contained in:
@@ -7,6 +7,9 @@ DB_PASSWORD = user
|
||||
DB_DEBUG = false
|
||||
|
||||
|
||||
BLOCK_MODE = false
|
||||
|
||||
|
||||
FLOW_PROCESS_CONFIG_KEY = standard
|
||||
FLOW_USE_CUSTOM_PROCESS = false
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
+3
-1
@@ -2,4 +2,6 @@
|
||||
|
||||
内镜未刷取出就操作
|
||||
|
||||
刷两次代表加强洗
|
||||
刷两次代表加强洗
|
||||
|
||||
网关阻断
|
||||
@@ -4,6 +4,7 @@ namespace app\flow;
|
||||
|
||||
use app\config\Config;
|
||||
use app\flow\config\ProcessConfig;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\net\PacketContext;
|
||||
use app\utils\Logger;
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ class FlowProcessor
|
||||
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(
|
||||
$context = $context->builder()->withOperator(new \app\flow\context\bean\OperatorInfo(
|
||||
id: $op['id'],
|
||||
name: $op['name'],
|
||||
rfid: $op['rfid']
|
||||
|
||||
@@ -103,7 +103,13 @@ class OperatorSessionManager
|
||||
*/
|
||||
public function hasOperator(string $readerId): bool
|
||||
{
|
||||
return isset($this->sessions[$readerId]);
|
||||
$cache = $this->sessions[$readerId] ?? null;
|
||||
if (empty($cache)) return false;
|
||||
// 如果时间过去了,返回没有
|
||||
if ($this->expire > 0 && isset($cache['time']) && (time() - $cache['time']) > $this->expire) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +130,7 @@ class OperatorSessionManager
|
||||
|
||||
public function pop(string $readerId): ?array
|
||||
{
|
||||
$op = $this->getOperator($readerId);
|
||||
$op = $this->sessions[$readerId] ?? null;
|
||||
$this->clearOperator($readerId);
|
||||
return $op;
|
||||
}
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
namespace app\flow\context;
|
||||
|
||||
use app\flow\config\ProcessConfig;
|
||||
use app\flow\vo\EndoscopeInfo;
|
||||
use app\flow\vo\ExecutionResult;
|
||||
use app\flow\vo\MorningWashStatus;
|
||||
use app\flow\vo\OperatorInfo;
|
||||
use app\flow\vo\ProcessStatus;
|
||||
use app\flow\vo\ReaderInfo;
|
||||
use app\flow\vo\ReminderStatus;
|
||||
use app\flow\vo\StorageStatus;
|
||||
use app\flow\vo\VoiceState;
|
||||
use app\flow\context\bean\EndoscopeInfo;
|
||||
use app\flow\context\bean\ExecutionResult;
|
||||
use app\flow\context\bean\MorningWashStatus;
|
||||
use app\flow\context\bean\OperatorInfo;
|
||||
use app\flow\context\bean\ProcessStatus;
|
||||
use app\flow\context\bean\ReaderInfo;
|
||||
use app\flow\context\bean\ReminderStatus;
|
||||
use app\flow\context\bean\StorageStatus;
|
||||
use app\flow\context\bean\VoiceState;
|
||||
use app\model\EctActions;
|
||||
use app\net\PacketContext;
|
||||
|
||||
/**
|
||||
@@ -206,9 +207,9 @@ readonly class ProcessContext
|
||||
|
||||
/**
|
||||
* 获取上一个操作记录
|
||||
* @return \app\model\EctActions|null 上一个操作记录 (来源: ProcessStatus)
|
||||
* @return EctActions|null 上一个操作记录 (来源: ProcessStatus)
|
||||
*/
|
||||
public function getPreviousAction(): ?\app\model\EctActions
|
||||
public function getPreviousAction(): ?EctActions
|
||||
{
|
||||
return $this->processStatus->previousAction;
|
||||
}
|
||||
|
||||
@@ -4,18 +4,18 @@ namespace app\flow\context;
|
||||
|
||||
use app\config\Config;
|
||||
use app\flow\config\ProcessConfig;
|
||||
use app\flow\vo\EndoscopeInfo;
|
||||
use app\flow\vo\ExecutionResult;
|
||||
use app\flow\vo\MorningWashStatus;
|
||||
use app\flow\vo\OperatorInfo;
|
||||
use app\flow\vo\ProcessStatus;
|
||||
use app\flow\vo\ReaderInfo;
|
||||
use app\flow\vo\ReminderStatus;
|
||||
use app\flow\vo\StorageStatus;
|
||||
use app\flow\vo\VoiceState;
|
||||
use app\flow\context\bean\EndoscopeInfo;
|
||||
use app\flow\context\bean\ExecutionResult;
|
||||
use app\flow\context\bean\MorningWashStatus;
|
||||
use app\flow\context\bean\OperatorInfo;
|
||||
use app\flow\context\bean\ProcessStatus;
|
||||
use app\flow\context\bean\ReaderInfo;
|
||||
use app\flow\context\bean\ReminderStatus;
|
||||
use app\flow\context\bean\StorageStatus;
|
||||
use app\flow\context\bean\VoiceState;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\BatchNo;
|
||||
use app\flow\context\bean\BatchNo;
|
||||
use app\model\EctActions;
|
||||
use app\net\PacketContext;
|
||||
use app\repository\EctActionsRepository;
|
||||
@@ -79,6 +79,7 @@ class ProcessContextBuilder
|
||||
$builder = new self();
|
||||
$builder->packetContext = $packetContext;
|
||||
$builder->engineConfig = $additionalData['engineConfig'] ?? null;
|
||||
if (empty($builder->engineConfig)) Logger::warn("fromPacketContext 需要通过 additionalData 传递 engineConfig");
|
||||
|
||||
// 获取原始卡号和读卡器编号
|
||||
$cardNo = $packetContext->packet->card ?? '';
|
||||
@@ -228,6 +229,7 @@ class ProcessContextBuilder
|
||||
|
||||
// 查询今日洗消记录数(晨洗判断)
|
||||
$todayWashRecords = $actionsRepo->countTodayActions($this->endoscope->id, $this->morningStartTime, [0, 7, 8]);
|
||||
Logger::debug("{} 内镜今日洗消记录数: {}", [$this->endoscope->name,$todayWashRecords]);
|
||||
$this->morningWash = new MorningWashStatus(
|
||||
needMorningWash: $this->morningWash->needMorningWash,
|
||||
morningWashed: $this->morningWash->morningWashed,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
use app\config\Config;
|
||||
use app\repository\EctActionsRepository;
|
||||
@@ -14,7 +14,9 @@ readonly class BatchNo
|
||||
public function __construct(
|
||||
/** 批次号值 */
|
||||
public string $value = '',
|
||||
) {}
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建空批次号
|
||||
@@ -60,7 +62,7 @@ readonly class BatchNo
|
||||
|
||||
/**
|
||||
* 解析批次号结构
|
||||
*
|
||||
*
|
||||
* @return array{date: string, machineId: string, sequence: int, dateFormatted: string}
|
||||
*/
|
||||
public function parse(): array
|
||||
@@ -86,6 +88,20 @@ readonly class BatchNo
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析批次号结构
|
||||
* @deprecated
|
||||
* @return array{date: string, machineId: string, sequence: int, dateFormatted: string}
|
||||
*/
|
||||
public static function parseBatchNo(string $batchNo): array
|
||||
{
|
||||
$batch = BatchNo::fromString($batchNo);
|
||||
if (!$batch->isValid()) {
|
||||
throw new \InvalidArgumentException('Invalid batch string: ' . $batchNo);
|
||||
}
|
||||
return $batch->parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证批次号格式是否有效
|
||||
*/
|
||||
@@ -123,12 +139,23 @@ readonly class BatchNo
|
||||
/**
|
||||
* 获取日期部分
|
||||
*/
|
||||
public function getDate(): string
|
||||
public function getDateStr(): string
|
||||
{
|
||||
$parsed = $this->parse();
|
||||
return $parsed['dateFormatted'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取时间戳
|
||||
* @return int|false
|
||||
*/
|
||||
public function getTimestamp(): int|false
|
||||
{
|
||||
$parsed = $this->parse();
|
||||
return strtotime($parsed['dateFormatted']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取机器ID
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
use app\flow\enum\VoiceMessage;
|
||||
|
||||
@@ -20,7 +20,7 @@ readonly class CanHandleResult
|
||||
/**
|
||||
* 创建可以处理的结果
|
||||
*/
|
||||
public static function yes(): self
|
||||
public static function canHandle(): self
|
||||
{
|
||||
return new self(canHandle: true);
|
||||
}
|
||||
@@ -28,7 +28,7 @@ readonly class CanHandleResult
|
||||
/**
|
||||
* 创建不能处理的结果
|
||||
*/
|
||||
public static function no(?VoiceMessage $expectedNextStep = null): self
|
||||
public static function cannotHandle(?VoiceMessage $expectedNextStep = null): self
|
||||
{
|
||||
return new self(
|
||||
canHandle: false,
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
/**
|
||||
* 内镜信息值对象
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
use app\flow\enum\DbOperationType;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
/**
|
||||
* 晨洗状态值对象
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
/**
|
||||
* 操作员信息值对象
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
use app\model\EctActions;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
/**
|
||||
* 读卡器信息值对象
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
/**
|
||||
* 提醒状态值对象
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
/**
|
||||
* 存储状态值对象
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace app\flow\vo;
|
||||
namespace app\flow\context\bean;
|
||||
|
||||
use app\flow\enum\VoiceMessage;
|
||||
|
||||
@@ -44,7 +44,9 @@ enum VoiceMessage: string
|
||||
case PLEASE_SWIPE_MORNING_WASH = '请刷消毒或机洗,开启晨洗流程';
|
||||
// 流程链未初始化
|
||||
case PROCESS_CHAIN_NOT_INITIALIZED = '流程链未初始化';
|
||||
case UNKNOWN_ERROR = '未知错误';
|
||||
|
||||
// 未知错误,通常是无节点匹配的时候
|
||||
case UNKNOWN_ERROR = '未知错误,无匹配的节点';
|
||||
|
||||
// 卡号未绑定
|
||||
case CARD_NOT_BOUND = '卡号未绑定';
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\config\StepConfig;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\strategies\ProcessStrategyInterface;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
@@ -302,9 +302,9 @@ abstract class AbstractProcessNode implements ProcessNodeInterface
|
||||
public function canHandle(ProcessContext $context): CanHandleResult
|
||||
{
|
||||
if ($context->getCurrentStep() === $this->getCode()) {
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\repository\EctActionsRepository;
|
||||
use app\utils\Logger;
|
||||
|
||||
@@ -39,9 +39,9 @@ class CloseNode extends AbstractProcessNode
|
||||
public function canHandle(ProcessContext $context): CanHandleResult
|
||||
{
|
||||
if (!$context->isSuccess() || $context->isDatabaseOperationNeeded() || !empty($context->getVoice()->message)) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
|
||||
/**
|
||||
* 消毒节点
|
||||
@@ -36,22 +36,22 @@ class DisinfectNode extends AbstractProcessNode
|
||||
{
|
||||
// 如果内镜未取出
|
||||
if ($context->getStorage()->isInStorage) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
}
|
||||
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
if ($context->getCurrentStep() === RinseNode::getName()) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_DISINFECT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_DISINFECT);
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 上一个步骤必须是漂洗 或者 晨洗
|
||||
if (!$this->isRequiredNode($context->getCurrentStep(), [RinseNode::getName(), MorningWashNode::getName()])) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
@@ -40,23 +40,23 @@ class DryNode extends AbstractProcessNode
|
||||
{
|
||||
// 如果内镜未取出
|
||||
if ($context->getStorage()->isInStorage) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
}
|
||||
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
if ($context->getCurrentStep() === FinalRinseNode::getName()) {
|
||||
if (!$context->isSuccess()) Logger::debug("[DryNode] 刷卡错误,当前步骤是终末漂洗,但是刷的读卡器类型不是终末漂洗,对用户进行语音提示刷终末漂洗读卡器");
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_DRY);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_DRY);
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 上一个步骤必须是终末漂洗
|
||||
if (!$this->isRequiredNode($context->getCurrentStep(), [FinalRinseNode::getName()])) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_DISINFECT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_DISINFECT);
|
||||
}
|
||||
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\repository\EctActionsRepository;
|
||||
use app\utils\Logger;
|
||||
|
||||
@@ -40,9 +40,9 @@ class DuplicateCheckNode extends AbstractProcessNode
|
||||
public function canHandle(ProcessContext $context): CanHandleResult
|
||||
{
|
||||
if ($context->getPreviousAction()?->process_name === $context->getReader()->type) {
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
|
||||
/**
|
||||
* 结束节点
|
||||
@@ -36,26 +36,25 @@ class EndNode extends AbstractProcessNode
|
||||
{
|
||||
// 如果内镜未取出
|
||||
if ($context->getStorage()->isInStorage) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
}
|
||||
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
if ($context->getCurrentStep() === DryNode::getName() && $context->getCurrentStep() === FinalRinseNode::getName()) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_END);
|
||||
if ($context->getCurrentStep() === DryNode::getName() || $context->getCurrentStep() === FinalRinseNode::getName()) {
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_END);
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 上一个步骤必须是干燥、终末漂洗或机洗
|
||||
$validSteps = ['干燥', '终末漂洗', '机洗'];
|
||||
if ($this->isRequiredNode($context->getCurrentStep(), ['干燥', '终末漂洗', '机洗'])) {
|
||||
if (!$this->isRequiredNode($context->getCurrentStep(), ['干燥', '终末漂洗', '机洗'])) {
|
||||
if ($context->getCurrentStep() === FinalRinseNode::getName()) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_WASH);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_WASH);
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
@@ -39,22 +39,22 @@ class FinalRinseNode extends AbstractProcessNode
|
||||
{
|
||||
// 如果内镜未取出
|
||||
if ($context->getStorage()->isInStorage) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
}
|
||||
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
if ($context->getCurrentStep() === DisinfectNode::getName()) {
|
||||
if (!$context->isSuccess()) Logger::debug("[FinalRinseNode] 刷卡错误,当前步骤是消毒,但是刷的读卡器类型不是消毒,对用户进行语音提示刷消毒读卡器");
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_FINAL_RINSE);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_FINAL_RINSE);
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 上一个步骤必须是消毒或机洗
|
||||
if ($this->isRequiredNode($context->getCurrentStep(), ['消毒', '机洗'])) {
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
|
||||
/**
|
||||
* 机洗节点
|
||||
@@ -36,30 +36,30 @@ class MachineWashNode extends AbstractProcessNode
|
||||
{
|
||||
// 如果内镜未取出
|
||||
if ($context->getStorage()->isInStorage) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
}
|
||||
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
if ($context->getCurrentStep() === WashNode::getName()) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MACHINE_WASH);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MACHINE_WASH);
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 需要晨洗但未完成:提示先进行晨洗
|
||||
if ($context->getMorningWash()->needMorningWash && !$context->getMorningWash()->morningWashed) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MORNING_WASH);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MORNING_WASH);
|
||||
}
|
||||
|
||||
// 机洗可以在多个步骤后执行:空步骤(新流程)、结束、内镜取出、清洗,晨洗
|
||||
if (!$this->isRequiredNode($context->getCurrentStep(), ['', '结束', '内镜取出', '清洗', MachineWashNode::getName()])) {
|
||||
if ($context->getCurrentStep() === EndNode::getName()) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MACHINE_WASH);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MACHINE_WASH);
|
||||
}
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_END);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_END);
|
||||
}
|
||||
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\vo\MorningWashStatus;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\flow\context\bean\MorningWashStatus;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
@@ -38,19 +38,19 @@ class MorningWashNode extends AbstractProcessNode
|
||||
{
|
||||
// 如果内镜未取出
|
||||
if ($context->getStorage()->isInStorage) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
}
|
||||
|
||||
// 只有需要晨洗且未完成晨洗时才处理
|
||||
if (!$context->getMorningWash()->needMorningWash || $context->getMorningWash()->morningWashed) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 检查当前读卡器类型是否匹配
|
||||
if (!$this->isRequiredNode($context->getReader()->type, ['漂洗', '机洗'])){
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MORNING_WASH);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MORNING_WASH);
|
||||
}
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace app\flow\nodes;
|
||||
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
|
||||
/**
|
||||
* 流程节点接口
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
|
||||
/**
|
||||
* 漂洗节点
|
||||
@@ -38,24 +38,24 @@ class RinseNode extends AbstractProcessNode
|
||||
{
|
||||
// 如果内镜未取出
|
||||
if ($context->getStorage()->isInStorage) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
}
|
||||
|
||||
// 期望当前读卡器为漂洗
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
// 当前步骤是清洗且读卡器不符:说明清洗完了应该刷漂洗
|
||||
if ($context->getCurrentStep() === WashNode::getName()) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_RINSE);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_RINSE);
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 上一个步骤必须是清洗
|
||||
if (!$this->isRequiredNode($context->getCurrentStep(), [WashNode::getName()])) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_WASH);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_WASH);
|
||||
}
|
||||
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,8 +6,8 @@ use app\config\Config;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\vo\StorageStatus;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\flow\context\bean\StorageStatus;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
@@ -44,12 +44,12 @@ class StorageInNode extends AbstractProcessNode
|
||||
|
||||
// 单读卡器模式不处理,由 StorageNode 统一处理
|
||||
if ($singleReaderMode) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 读卡器不是内镜放入类型,不处理
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 获取内镜当前存储状态
|
||||
@@ -58,17 +58,17 @@ class StorageInNode extends AbstractProcessNode
|
||||
// 如果内镜已在库中,则当前应该是出库操作,不处理
|
||||
if ($isInStorage) {
|
||||
Logger::debug('[StorageInNode] 内镜已在库中,转由出库节点处理');
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 检查前置步骤要求
|
||||
$validSteps = ['', '结束', '内镜取出', '测漏正常', '测漏异常'];
|
||||
if (!in_array($context->getCurrentStep(), $validSteps)) {
|
||||
Logger::debug('[StorageInNode] 当前步骤 {} 不符合入库条件', [$context->getCurrentStep()]);
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,8 +6,8 @@ use app\config\Config;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\vo\StorageStatus;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\flow\context\bean\StorageStatus;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
@@ -47,12 +47,12 @@ class StorageNode extends AbstractProcessNode
|
||||
|
||||
// 非单读卡器模式不处理
|
||||
if (!$singleReaderMode) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 读卡器类型必须是'内镜放入'或'内镜取出'
|
||||
if (!in_array($context->getReader()->type, ['内镜放入', '内镜取出'])) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
$isInStorage = $context->getStorage()->isInStorage;
|
||||
@@ -62,18 +62,18 @@ class StorageNode extends AbstractProcessNode
|
||||
$validSteps = ['内镜放入', '结束'];
|
||||
if (!in_array($context->getCurrentStep(), $validSteps)) {
|
||||
Logger::debug('[StorageNode] 当前步骤 {} 不符合出库条件', [$context->getCurrentStep()]);
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
} else {
|
||||
// 内镜不在库中,执行入库
|
||||
$validSteps = ['', '结束', '内镜取出', '测漏正常', '测漏异常'];
|
||||
if (!in_array($context->getCurrentStep(), $validSteps)) {
|
||||
Logger::debug('[StorageNode] 当前步骤 {} 不符合入库条件', [$context->getCurrentStep()]);
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
}
|
||||
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,8 +6,8 @@ use app\config\Config;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\vo\StorageStatus;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\flow\context\bean\StorageStatus;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
@@ -44,12 +44,12 @@ class StorageOutNode extends AbstractProcessNode
|
||||
|
||||
// 单读卡器模式不处理,由 StorageNode 统一处理
|
||||
if ($singleReaderMode) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 读卡器不是内镜取出类型,不处理
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 获取内镜当前存储状态
|
||||
@@ -58,17 +58,17 @@ class StorageOutNode extends AbstractProcessNode
|
||||
// 如果内镜不在库中,则当前应该是入库操作,不处理
|
||||
if (!$isInStorage) {
|
||||
Logger::debug('[StorageOutNode] 内镜不在库中,转由入库节点处理');
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
// 检查前置步骤要求:必须在库中才能出库
|
||||
$validSteps = ['内镜放入', '结束'];
|
||||
if (!in_array($context->getCurrentStep(), $validSteps)) {
|
||||
Logger::debug('[StorageOutNode] 当前步骤 {} 不符合出库条件', [$context->getCurrentStep()]);
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@ use app\config\Config;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
|
||||
/**
|
||||
* 虚拟清洗机节点
|
||||
@@ -37,18 +37,18 @@ class VirtualWashMachineNode extends AbstractProcessNode
|
||||
{
|
||||
// 如果内镜未取出
|
||||
if ($context->getStorage()->isInStorage) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
}
|
||||
|
||||
// 如果不是机洗
|
||||
if ($context->getReader()->type !== MachineWashNode::getName()) {
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
if (Config::getInstance()->enableVirtualCleanerParser) {
|
||||
return CanHandleResult::yes();
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace app\flow\nodes;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\VoiceMessage;
|
||||
use app\flow\vo\CanHandleResult;
|
||||
use app\flow\context\bean\CanHandleResult;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
@@ -39,26 +39,28 @@ class WashNode extends AbstractProcessNode
|
||||
|
||||
// 如果内镜未取出
|
||||
if ($context->getStorage()->isInStorage) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_STORAGE_OUT);
|
||||
}
|
||||
|
||||
// 读卡器不是本节点,不处理
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
return CanHandleResult::no();
|
||||
}
|
||||
|
||||
|
||||
// 需要晨洗但未完成:提示先进行晨洗
|
||||
if ($context->getMorningWash()->needMorningWash && !$context->getMorningWash()->morningWashed) {
|
||||
return CanHandleResult::no(VoiceMessage::PLEASE_SWIPE_MORNING_WASH);
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_MORNING_WASH);
|
||||
}
|
||||
|
||||
$validCurrentSteps = ['', '结束', '内镜取出', '内镜放入', '测漏正常', '晨洗'];
|
||||
if (!in_array($context->getCurrentStep(), $validCurrentSteps)) {
|
||||
// 读卡器是清洗但步骤不对(如终末漂洗时刷清洗),提示应该先刷结束
|
||||
return CanHandleResult::no();
|
||||
return CanHandleResult::cannotHandle();
|
||||
}
|
||||
|
||||
return CanHandleResult::yes();
|
||||
// 读卡器不是本节点,不处理
|
||||
if (!$this->isMatchReaderType($context)) {
|
||||
return CanHandleResult::cannotHandle(VoiceMessage::PLEASE_SWIPE_WASH);
|
||||
}
|
||||
|
||||
return CanHandleResult::canHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@ use app\flow\config\MorningMode;
|
||||
use app\flow\config\MorningWashConfig;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\nodes\ProcessNodeInterface;
|
||||
use app\flow\vo\MorningWashStatus;
|
||||
use app\flow\context\bean\MorningWashStatus;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,15 +59,16 @@ class TimeValidationStrategy extends AbstractStrategy
|
||||
|
||||
/**
|
||||
* 执行时间验证
|
||||
* 验证上一步骤(currentStep)的时长是否达标
|
||||
*/
|
||||
protected function doExecute(ProcessContext $context, ProcessNodeInterface $node): ProcessContext
|
||||
{
|
||||
$stepCode = $node->getCode();
|
||||
$currentStep = $context->getCurrentStep();
|
||||
// 验证的是上一步骤(currentStep)的时长,而不是当前节点
|
||||
$stepCode = $context->getCurrentStep();
|
||||
$processType = $context->getProcessType();
|
||||
|
||||
Logger::debug("开始执行时间验证策略,步骤:{$stepCode},流程类型:{$processType}");
|
||||
$configDuration = $this->timeValidationConfig->getDuration($stepCode,$processType);
|
||||
$configDuration = $this->timeValidationConfig->getDuration($stepCode, $processType);
|
||||
|
||||
Logger::debug("步骤:{$stepCode},流程类型:{$processType},配置时长:{$configDuration}s");
|
||||
if ($configDuration > 0) {
|
||||
@@ -76,7 +77,7 @@ class TimeValidationStrategy extends AbstractStrategy
|
||||
} else {
|
||||
Logger::debug("步骤:{$stepCode},流程类型:{$processType},无配置时长,从数据库查询");
|
||||
// 从数据库按流程类型精确查询
|
||||
$requiredDuration = $this->getDurationFromDb($stepCode, $context->getProcessType());
|
||||
$requiredDuration = $this->getDurationFromDb($stepCode, $processType);
|
||||
if ($requiredDuration > 0) {
|
||||
$context = $context->builder()->withStepDuration($stepCode, $requiredDuration)->build();
|
||||
} else {
|
||||
@@ -116,11 +117,13 @@ class TimeValidationStrategy extends AbstractStrategy
|
||||
/**
|
||||
* 判断策略是否适用
|
||||
* 只有在 timeValidationConfig 中登记的步骤才参与时间验证
|
||||
* 验证的是上一步骤(currentStep)的时长
|
||||
*/
|
||||
public function isApplicable(ProcessContext $context, ProcessNodeInterface $node): bool
|
||||
{
|
||||
if ($context->getCurrentStep() != $context->getPreviousAction()?->process_name) return false;
|
||||
if (!$this->timeValidationConfig->hasStep($node->getCode(), $context->getProcessType())) return false;
|
||||
// 检查的是 currentStep(上一步骤)是否有时间配置
|
||||
if (!$this->timeValidationConfig->hasStep($context->getCurrentStep(), $context->getProcessType())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace app\repository;
|
||||
|
||||
use app\flow\context\bean\BatchNo;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\enum\DbOperationType;
|
||||
use app\model\EctActions;
|
||||
@@ -99,9 +100,9 @@ class EctActionsRepository extends BaseRepository
|
||||
$count = 0;
|
||||
$today = date('Ymd');
|
||||
$query->lazy()->each(function (EctActions $record) use (&$count, $today) {
|
||||
$batchInfo = ProcessContext::parseBatchNo($record->op_batchno);
|
||||
$dateTime = strtotime($batchInfo['date']);
|
||||
if (empty($batchInfo['date']) || $dateTime === false) return;
|
||||
$batchInfo = BatchNo::fromString($record->op_batchno);
|
||||
$dateTime = $batchInfo->getTimestamp();
|
||||
if (empty($batchInfo->getDateStr()) || $dateTime === false) return;
|
||||
$recordDate = date('Ymd', $dateTime);
|
||||
if ($recordDate >= $today) {
|
||||
$count += 1;
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
namespace tests\flow;
|
||||
|
||||
use app\flow\config\ProcessConfig;
|
||||
use app\flow\context\bean\EndoscopeInfo;
|
||||
use app\flow\context\bean\ExecutionResult;
|
||||
use app\flow\context\bean\MorningWashStatus;
|
||||
use app\flow\context\bean\OperatorInfo;
|
||||
use app\flow\context\bean\ProcessStatus;
|
||||
use app\flow\context\bean\ReaderInfo;
|
||||
use app\flow\context\bean\ReminderStatus;
|
||||
use app\flow\context\bean\StorageStatus;
|
||||
use app\flow\context\bean\VoiceState;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\vo\EndoscopeInfo;
|
||||
use app\flow\vo\ExecutionResult;
|
||||
use app\flow\vo\MorningWashStatus;
|
||||
use app\flow\vo\OperatorInfo;
|
||||
use app\flow\vo\ProcessStatus;
|
||||
use app\flow\vo\ReaderInfo;
|
||||
use app\flow\vo\ReminderStatus;
|
||||
use app\flow\vo\StorageStatus;
|
||||
use app\flow\vo\VoiceState;
|
||||
use app\model\EctActions;
|
||||
|
||||
/**
|
||||
@@ -284,6 +284,7 @@ class VirtualContextBuilder
|
||||
$action->op_batchno = $batchNo ?: $this->processStatus->batchNo;
|
||||
$action->op_starttime = date('Y-m-d H:i:s', time() - 60);
|
||||
$action->op_endtime = $opEndtime;
|
||||
$action->action_type = $this->mapActionType($this->processStatus->processType);
|
||||
$action->action_type_name = $this->processStatus->processType;
|
||||
|
||||
$this->processStatus = new ProcessStatus(
|
||||
@@ -297,6 +298,23 @@ class VirtualContextBuilder
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 映射流程类型到 action_type 数字
|
||||
*/
|
||||
private function mapActionType(string $processType): int
|
||||
{
|
||||
return match ($processType) {
|
||||
'手工洗' => 1,
|
||||
'机洗' => 2,
|
||||
'手工洗(加强)' => 3,
|
||||
'机洗(加强)' => 4,
|
||||
'手工洗(晨洗)' => 5,
|
||||
'机洗(晨洗)' => 6,
|
||||
'晨洗' => 7,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置晨洗状态 - 需要晨洗
|
||||
*/
|
||||
|
||||
@@ -5,9 +5,9 @@ namespace tests\flow;
|
||||
use app\flow\config\ProcessConfig;
|
||||
use app\flow\context\ProcessContext;
|
||||
use app\flow\ProcessEngine;
|
||||
use app\flow\vo\EndoscopeInfo;
|
||||
use app\flow\vo\OperatorInfo;
|
||||
use app\flow\vo\ReaderInfo;
|
||||
use app\flow\context\bean\EndoscopeInfo;
|
||||
use app\flow\context\bean\OperatorInfo;
|
||||
use app\flow\context\bean\ReaderInfo;
|
||||
use app\utils\Logger;
|
||||
|
||||
/**
|
||||
@@ -166,6 +166,11 @@ class VirtualityFlowProcessor
|
||||
$builder->currentStep($currentState->getCurrentStep())
|
||||
->batchNo($currentState->getBatchNo())
|
||||
->processType($currentState->getProcessType());
|
||||
|
||||
// 设置 previousAction:上一步骤名称就是当前状态的 currentStep
|
||||
if (!empty($currentState->getCurrentStep())) {
|
||||
$builder->previousAction($currentState->getCurrentStep(), $currentState->getBatchNo());
|
||||
}
|
||||
} else {
|
||||
// 新流程
|
||||
$builder->newProcess();
|
||||
@@ -185,6 +190,14 @@ class VirtualityFlowProcessor
|
||||
// 执行流程
|
||||
$result = $this->engine->execute($context);
|
||||
|
||||
// 确保 previousAction 在结果中正确设置
|
||||
// 如果执行成功且有上一步骤信息,确保 previousAction 被保留
|
||||
if ($result->isSuccess() && $context->getPreviousAction() !== null && $result->getPreviousAction() === null) {
|
||||
$result = $result->builder()
|
||||
->withPreviousAction($context->getPreviousAction())
|
||||
->build();
|
||||
}
|
||||
|
||||
// 保存状态
|
||||
$this->endoscopeStates[$endoscopeData['id']] = $result;
|
||||
$this->history[] = $result;
|
||||
@@ -214,8 +227,9 @@ class VirtualityFlowProcessor
|
||||
Logger::info("当前流程:{}", [$result->getProcessType()]);
|
||||
Logger::info("当前批次号:{}", [$result->getBatchNo()]);
|
||||
Logger::info("当前步骤:{}", [$result->getCurrentStep()]);
|
||||
Logger::info("上一个步骤类型:{}", [$result->getPreviousAction()->action_type??"null"]);
|
||||
Logger::info("上一个步骤类型:{}", [$result->getPreviousAction()->action_type_name?? "null"]);
|
||||
Logger::info("上一个步骤:{}", [$result->getPreviousAction()->process_name??"null"]);
|
||||
Logger::info("时长:{}", [$result->getDuration()?? "null"]);
|
||||
Logger::info("当前语音:{$result->getFullVoice()}\n");
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -80,11 +80,14 @@ class BlockTest extends TestCase
|
||||
Config::getInstance()->setBlockMode(true);
|
||||
|
||||
// 创建一个时间不足的场景(只有5秒)
|
||||
// 关键:设置 previousAction 和 processType 使得时间验证策略生效
|
||||
$context = $this->processor->createContextBuilder()
|
||||
->endoscope('胃镜1')
|
||||
->reader('漂洗')
|
||||
->operator('操作员1')
|
||||
->currentStep('清洗')
|
||||
->previousAction('清洗') // 上一步也是清洗,表示重复刷同一步骤
|
||||
->processType('手工洗') // 必须设置流程类型,否则 hasStep 返回 false
|
||||
->duration(5) // 只有5秒,时间不足
|
||||
->batchNo(date('Ymd') . '010001')
|
||||
->build();
|
||||
@@ -112,6 +115,8 @@ class BlockTest extends TestCase
|
||||
->reader('漂洗')
|
||||
->operator('操作员1')
|
||||
->currentStep('清洗')
|
||||
->previousAction('清洗') // 设置 previousAction 使时间验证生效
|
||||
->processType('手工洗') // 必须设置流程类型
|
||||
->duration(5) // 只有5秒,时间不足
|
||||
->batchNo(date('Ymd') . '010001')
|
||||
->build();
|
||||
@@ -161,6 +166,8 @@ class BlockTest extends TestCase
|
||||
->reader('漂洗')
|
||||
->operator('操作员1')
|
||||
->currentStep('清洗')
|
||||
->previousAction('清洗') // 设置 previousAction 使时间验证生效
|
||||
->processType('手工洗') // 必须设置流程类型
|
||||
->duration(120) // 120秒,时间充足
|
||||
->batchNo(date('Ymd') . '010001')
|
||||
->build();
|
||||
|
||||
Reference in New Issue
Block a user