This commit is contained in:
zimoyin
2026-03-13 20:27:18 +08:00
parent 9ddec3dfb9
commit 18254d82f5
9 changed files with 102 additions and 10 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ DB_PASSWORD = user
DB_DEBUG = false DB_DEBUG = false
BLOCK_MODE = false BLOCK_MODE = true
FLOW_PROCESS_CONFIG_KEY = standard FLOW_PROCESS_CONFIG_KEY = standard
File diff suppressed because one or more lines are too long
+16 -4
View File
@@ -3,7 +3,6 @@
namespace app\config; namespace app\config;
class Config class Config
{ {
/** /**
@@ -84,9 +83,20 @@ class Config
get => $this->blockMode; get => $this->blockMode;
} }
public function setBlockMode(bool $value)
/**
* @param bool $value
* @return void
* @deprecated 禁止使用,改方法仅仅用于 test 方法
*/
public function setBlockMode(bool $value): void
{ {
echo "\033[31m获取禁止修改热修改阻断模式,这只是用于测试方法\033[0m\n"; $stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
$isContainTests = false;
foreach ($stack as $item) if (str_contains($item['file'] ?? '', 'tests')) {
$isContainTests = true;
}
if (!$isContainTests) throw new \RuntimeException('禁止修改阻断模式');
$this->blockMode = $value; $this->blockMode = $value;
} }
@@ -146,7 +156,9 @@ class Config
$this->enableVirtualCleanerParser = self::getBoolEnv('ENABLE_VIRTUAL_CLEANER_PARSER', false); $this->enableVirtualCleanerParser = self::getBoolEnv('ENABLE_VIRTUAL_CLEANER_PARSER', false);
} }
private function __clone() {} private function __clone()
{
}
private function detectCircularDependency(): void private function detectCircularDependency(): void
{ {
@@ -150,6 +150,19 @@ class ProcessContextBuilder
$builder->isOperatorCard = $context->isOperatorCard(); $builder->isOperatorCard = $context->isOperatorCard();
$builder->stepDurations = $context->getStepDurations(); $builder->stepDurations = $context->getStepDurations();
// 遍历当前类的属性,检查哪些未被修改(对比默认值)
$reflection = new \ReflectionClass($builder);
$unmodifiedProperties = [];
foreach ($reflection->getProperties() as $property) {
$property->setAccessible(true); // 允许访问私有/受保护属性
$defaultValue = $reflection->getDefaultProperties()[$property->getName()] ?? null;
if ($property->getValue($builder) === $defaultValue) {
$unmodifiedProperties[] = $property->getName();
}
}
if (empty($unmodifiedProperties)){
Logger::warn("from ProcessContext 创建 ProcessContextBuilder 时存在未修改的属性");
}
return $builder; return $builder;
} }
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace flow;
class PartTimeFlowProcessor
{
}
+7 -1
View File
@@ -199,12 +199,18 @@ class VirtualContextBuilder
*/ */
public function currentStep(string $step): self public function currentStep(string $step): self
{ {
// 自动从环境配置加载该步骤的时长(如果未手动设置)
$duration = $this->processStatus->duration;
if ($duration === null && isset($this->stepDurations[$step])) {
$duration = $this->stepDurations[$step];
}
$this->processStatus = new ProcessStatus( $this->processStatus = new ProcessStatus(
currentStep: $step, currentStep: $step,
processType: $this->processStatus->processType, processType: $this->processStatus->processType,
batchNo: $this->processStatus->batchNo, batchNo: $this->processStatus->batchNo,
actionStartTime: $this->processStatus->actionStartTime, actionStartTime: $this->processStatus->actionStartTime,
duration: $this->processStatus->duration, duration: $duration,
previousAction: $this->processStatus->previousAction previousAction: $this->processStatus->previousAction
); );
return $this; return $this;
+9 -2
View File
@@ -4,6 +4,7 @@ namespace tests\flow;
use app\flow\config\ProcessConfig; use app\flow\config\ProcessConfig;
use app\flow\context\ProcessContext; use app\flow\context\ProcessContext;
use app\flow\enum\VoiceMessage;
use app\flow\ProcessEngine; use app\flow\ProcessEngine;
use app\flow\context\bean\EndoscopeInfo; use app\flow\context\bean\EndoscopeInfo;
use app\flow\context\bean\OperatorInfo; use app\flow\context\bean\OperatorInfo;
@@ -160,16 +161,22 @@ class VirtualityFlowProcessor
if (isset($this->operatorSessions[$readerData['id']])) { if (isset($this->operatorSessions[$readerData['id']])) {
$opData = $this->operatorSessions[$readerData['id']]; $opData = $this->operatorSessions[$readerData['id']];
$builder->customOperator($opData['id'], $opData['name'], $opData['rfid']); $builder->customOperator($opData['id'], $opData['name'], $opData['rfid']);
} else {
// 获取上一个记录的操作员
$opData = $currentState->getOperator();
$builder->customOperator($opData->id, $opData->name, $opData->rfid);
} }
// 继承之前的流程状态 // 继承之前的流程状态
if ($currentState !== null) { if ($currentState !== null) {
$st = strtotime($currentState->getActionStartTime()); $st = strtotime($currentState->getActionStartTime());
$duration = time() - $st; $duration = time() - $st;
if (empty($st) || $duration <= 0) $duration = null; if (empty($st) || $duration < 0) $duration = null;
$builder->currentStep($currentState->getCurrentStep()) $builder->currentStep($currentState->getCurrentStep())
->batchNo($currentState->getBatchNo()) ->batchNo($currentState->getBatchNo())
->setDuration($duration) ->setDuration($duration)
->actionStartTime(date("Y-m-d H:i:s"))
->processType($currentState->getProcessType()); ->processType($currentState->getProcessType());
// 设置 previousAction:上一步骤名称就是当前状态的 currentStep // 设置 previousAction:上一步骤名称就是当前状态的 currentStep
@@ -186,7 +193,7 @@ class VirtualityFlowProcessor
// 未刷人员卡检查 // 未刷人员卡检查
if (!$context->hasOperator() && !isset($this->operatorSessions[$readerData['id']])) { if (!$context->hasOperator() && !isset($this->operatorSessions[$readerData['id']])) {
$result = $context->createModifyBuilder() $result = $context->createModifyBuilder()
->error(\app\flow\enum\VoiceMessage::PLEASE_SWIPE_OPERATOR) ->error(VoiceMessage::PLEASE_SWIPE_OPERATOR)
->build(); ->build();
$this->history[] = $result; $this->history[] = $result;
return $result; return $result;
+3 -1
View File
@@ -94,7 +94,9 @@ class BlockTest extends TestCase
$engine = ProcessEngine::createStandard(); $engine = ProcessEngine::createStandard();
$result = $engine->execute($context); $result = $engine->execute($context);
// 输出语音
Logger::info("测试时间验证策略阻断 - 阻断模式开启 success:{}",[$result->isSuccess()]);
Logger::info($result->getFullVoice());
// 阻断模式下,时间不足应该导致流程失败 // 阻断模式下,时间不足应该导致流程失败
$this->assertFalse($result->isSuccess(), '阻断模式下,时长不足应失败'); $this->assertFalse($result->isSuccess(), '阻断模式下,时长不足应失败');
} }
+44
View File
@@ -76,6 +76,50 @@ class ManualWashTest extends TestCase
// 验证最终步骤成功 // 验证最终步骤成功
$this->assertTrue($result5->isSuccess(), '干燥步骤 isSuccess() 应为 true'); $this->assertTrue($result5->isSuccess(), '干燥步骤 isSuccess() 应为 true');
} }
/**
* 测试完整手工洗流程:清洗 -> 漂洗 -> 消毒 -> 终末漂洗 -> 干燥
* 使用真实环境引擎执行
*/
public function testCompleteManualWashProcess2(): void
{
$operator = '操作员 1';
$endoscope = '胃镜 1';
// 步骤 1:清洗
$result1 = $this->processor->swipe($operator, $endoscope, '清洗');
$this->assertSuccess($result1, '清洗步骤应成功');
$this->assertStep($result1, '清洗');
$this->assertNeedDatabaseOperation($result1);
$batchNo = $result1->getBatchNo();
$this->assertNotEmpty($batchNo, '应生成批次号');
// 步骤 2:漂洗
$result2 = $this->processor->swipe($operator, $endoscope, '漂洗');
$this->assertSuccess($result2, '漂洗步骤应成功');
$this->assertStep($result2, '漂洗');
$this->assertBatchNoEquals($result2, $batchNo, '批次号应保持一致');
// 步骤 3:消毒
$result3 = $this->processor->swipe($operator, $endoscope, '消毒');
$this->assertSuccess($result3, '消毒步骤应成功');
$this->assertStep($result3, '消毒');
$this->assertBatchNoEquals($result3, $batchNo, '批次号应保持一致');
// 步骤 4:终末漂洗
$result4 = $this->processor->swipe($operator, $endoscope, '终末漂洗');
$this->assertSuccess($result4, '终末漂洗步骤应成功');
$this->assertStep($result4, '终末漂洗');
$this->assertBatchNoEquals($result4, $batchNo, '批次号应保持一致');
// 步骤 5:干燥
$result5 = $this->processor->swipe($operator, $endoscope, '干燥');
$this->assertSuccess($result5, '干燥步骤应成功');
$this->assertStep($result5, '干燥');
$this->assertBatchNoEquals($result5, $batchNo, '批次号应保持一致');
// 验证最终步骤成功
$this->assertTrue($result5->isSuccess(), '干燥步骤 isSuccess() 应为 true');
}
/** /**
* 测试使用便捷方法执行完整手工洗流程 * 测试使用便捷方法执行完整手工洗流程