# 内镜清洗流程管理系统 - 使用与配置 ## 一、快速开始 ### 1.1 基础使用示例 ```php use app\flow\FlowProcessor; use app\flow\config\ProcessConfig; use app\net\PacketContext; // 接收刷卡数据 public function onMessage(TcpConnection $connection, $data): void { // 1. 解析数据包 $packet = PacketParserFactory::parse($data); $packetContext = new PacketContext($connection, $packet); // 2. 创建流程处理器(使用标准配置) $config = ProcessConfig::createStandard(); $processor = new FlowProcessor($config); // 3. 处理流程 $result = $processor->process($packetContext); // 4. 输出结果 if ($result->success) { echo "语音播报: " . $result->getFullVoice(); echo "当前步骤: " . $result->currentStep; echo "批次号: " . $result->batchNo; } else { echo "错误: " . $result->errorMessage; } } ``` ## 二、配置方式 ### 2.1 预置配置 ```php use app\flow\config\ProcessConfig; // 标准完整流程 $config = ProcessConfig::createStandard(); // 无晨洗流程 $config = ProcessConfig::createNoMorningWash(); // 简化流程(只清洗) $config = ProcessConfig::createSimple(); // 机洗流程 $config = ProcessConfig::createMachineWash(); // 无干燥流程 $config = ProcessConfig::createNoDry(); // 仅干燥流程 $config = ProcessConfig::createDryOnly(); ``` ### 2.2 自定义配置 ```php use app\flow\config\ProcessConfig; $config = new ProcessConfig([ // 定义的 steps 是带有顺序的 // 流程步骤配置 'steps' => [ ['code' => '清洗', 'class' => 'WashNode', 'enabled' => true], ['code' => '消毒', 'class' => 'DisinfectNode', 'enabled' => true], ['code' => '结束', 'class' => 'EndNode', 'enabled' => true], ], // 晨洗配置 'morning_wash' => [ 'mode' => 'storage_time', // 根据存储时间判断 'storage_threshold' => 4, // 4小时阈值 'morning_start_time' => '06:00:00', ], // 时间验证配置 'time_validation' => [ 'durations' => [ '清洗' => 300, // 5分钟 '消毒' => 600, // 10分钟(自定义) ], ], // 语音模板配置 'voice_templates' => [ 'custom' => [ '清洗' => '第一步清洗开始', '消毒' => '第三步消毒开始,请确保消毒时间', ], ], ]); ``` ### 2.3 动态调整配置 ```php use app\flow\ProcessEngine; $engine = ProcessEngine::createStandard(); // 禁用某些步骤 $engine->disableNode('干燥'); $engine->disableNode('终末漂洗'); // 启用步骤 $engine->enableNode('干燥'); // 设置自定义语音 $engine->setStepVoice('清洗', '请开始清洗'); // 设置晨洗模式 $engine->setMorningWashMode('none'); ``` ## 三、晨洗模式配置 ### 3.1 不需要晨洗 ```php $config = new ProcessConfig([ 'morning_wash' => [ 'mode' => 'none', ], ]); ``` ### 3.2 所有镜子都需要晨洗 ```php $config = new ProcessConfig([ 'morning_wash' => [ 'mode' => 'all', ], ]); ``` ### 3.3 根据存储时间判断(义乌模式) ```php $config = new ProcessConfig([ 'morning_wash' => [ 'mode' => 'storage_time', 'storage_threshold' => 4, // 超过4小时需要晨洗 'morning_start_time' => '06:00:00', ], ]); ``` ### 3.4 每天第一次需要晨洗(忠县模式) ```php $config = new ProcessConfig([ 'morning_wash' => [ 'mode' => 'daily_first', 'morning_start_time' => '06:00:00', ], ]); ``` ### 3.5 特定类型镜子需要晨洗 ```php $config = new ProcessConfig([ 'morning_wash' => [ 'mode' => 'specific_types', 'specific_types' => ['胃镜', '十二指肠镜'], ], ]); ``` ## 四、医院特殊流程配置 ### 4.1 机洗后不允许刷终末漂洗 ```php use app\flow\ProcessEngine; $engine = ProcessEngine::createStandard(); // 获取终末漂洗节点并配置 $finalRinseNode = $engine->getNode('终末漂洗'); $finalRinseNode->setAllowAfterMachineWash(false); ``` **效果**:机洗完成后,刷卡到终末漂洗读卡器会提示错误,只能刷干燥或结束。 ### 4.2 机洗后必须直接刷干燥 ```php $dryNode = $engine->getNode('干燥'); $dryNode->setRequireDirectAfterMachineWash(true); ``` **效果**:机洗完成后,必须刷干燥或结束,不能刷其他步骤。 ### 4.3 自定义步骤时间 ```php use app\flow\strategies\TimeValidationStrategy; $strategy = new TimeValidationStrategy([ 'durations' => [ '清洗' => 600, // 10分钟 '消毒' => 900, // 15分钟 ], ]); $engine->addStrategy('time_validation', $strategy); ``` ### 4.4 自定义语音模板 ```php $engine->setStepVoice('清洗', '第一步:请开始清洗内镜'); $engine->setStepVoice('消毒', '第三步:消毒时间必须达到5分钟'); $engine->setStepVoice('结束', '清洗流程完成,请妥善保管'); ``` ## 五、从配置文件加载 ### 5.1 创建配置文件 ```php // config/flow/hospital_a.php return [ 'name' => '医院A-无晨洗流程', 'morning_wash' => [ 'mode' => 'none', ], 'steps' => [ ['code' => '清洗', 'class' => 'WashNode', 'enabled' => true], ['code' => '漂洗', 'class' => 'RinseNode', 'enabled' => true], ['code' => '消毒', 'class' => 'DisinfectNode', 'enabled' => true], ['code' => '终末漂洗', 'class' => 'FinalRinseNode', 'enabled' => true], ['code' => '干燥', 'class' => 'DryNode', 'enabled' => true], ['code' => '结束', 'class' => 'EndNode', 'enabled' => true], ], ]; ``` ### 5.2 加载配置 ```php $config = ProcessConfig::fromFile(__DIR__ . '/config/flow/hospital_a.php'); $processor = new FlowProcessor($config); ``` ## 六、全局配置类(Config.php) ### 6.1 配置类说明 系统提供全局配置单例类 `app\config\Config`,用于统一管理数据库配置和自定义流程配置: ```php use app\config\Config; // 获取配置实例 $config = Config::getInstance(); // 获取数据库配置 $databaseConfig = $config->database; // 获取自定义流程配置(从 app/config/custom_process_config.php 加载) $customProcess = $config->customProcess; ``` ### 6.2 配置文件位置 自定义流程配置文件位于:`app/config/custom_process_config.php` 该文件返回一个数组,包含多种预设的医院流程配置: ```php return [ 'standard' => [...], // 标准完整流程 'no_morning_wash' => [...], // 无晨洗流程 'partial_morning_wash' => [...], // 部分镜子晨洗(义乌模式) 'no_dry' => [...], // 无干燥流程 'dry_only' => [...], // 仅干燥流程 'machine_wash' => [...], // 机洗流程 'simple' => [...], // 简化流程 'custom_voice' => [...], // 自定义语音流程 ]; ``` ### 6.3 使用全局配置创建流程 ```php use app\config\Config; use app\flow\ProcessConfig; use app\flow\FlowProcessor; // 获取全局配置 $globalConfig = Config::getInstance(); // 从全局配置中获取特定医院配置 $hospitalConfig = $globalConfig->customProcess['no_morning_wash'] ?? null; if ($hospitalConfig) { // 创建流程配置 $processConfig = ProcessConfig::fromArray($hospitalConfig); // 创建流程处理器 $processor = new FlowProcessor($processConfig); // 处理刷卡请求... } ``` ### 6.4 配置优先级 配置加载优先级(从高到低): 1. 代码中动态设置的配置(`$engine->setStepVoice()`) 2. 从配置文件加载的配置(`ProcessConfig::fromFile()`) 3. 全局配置类中的配置(`Config::getInstance()->customProcess`) 4. 默认配置(`ProcessConfig::createStandard()`) ## 七、多医院配置示例 ```php class HospitalFlowManager { protected array $processors = []; public function __construct() { // 医院A:标准流程 $this->processors['hospital_a'] = new FlowProcessor( ProcessConfig::createStandard() ); // 医院B:无晨洗 $this->processors['hospital_b'] = new FlowProcessor( ProcessConfig::createNoMorningWash() ); // 医院C:义乌模式 $configC = new ProcessConfig([ 'morning_wash' => [ 'mode' => 'storage_time', 'storage_threshold' => 4, ], ]); $this->processors['hospital_c'] = new FlowProcessor($configC); // 医院D:机洗流程 $this->processors['hospital_d'] = new FlowProcessor( ProcessConfig::createMachineWash() ); } public function process(string $hospitalId, PacketContext $packetContext): ProcessContext { $processor = $this->processors[$hospitalId] ?? $this->processors['hospital_a']; return $processor->process($packetContext); } } ``` ## 八、处理结果 ### 8.1 成功结果 ```php $result = $processor->process($packetContext); if ($result->isSuccess()) { // 基础信息 $result->endoscopeId; // 内镜ID $result->endoscopeName; // 内镜名称 $result->currentStep; // 当前步骤 $result->processType; // 流程类型 $result->batchNo; // 批次号 // 语音播报 $voice = $result->getFullVoice(); // 完整语音(含内镜名称) $voice = $result->voiceMessage; // 仅流程语音 // 数据库标记 $result->needDbInsert; // 是否需要插入数据库 $result->dbOperation; // insert / update // WebSocket标记 $result->needWebSocketNotify; // 是否需要发送通知 } ``` ### 8.2 失败结果 ```php if (!$result->isSuccess()) { $errorMessage = $result->errorMessage; // 错误信息 $voice = $result->voiceMessage; // 错误语音 // 常见错误: // - "刷错,清洗剩余180秒"(时间未到) // - "刷卡错误,请刷消毒"(步骤错误) // - "内镜未绑定"(数据错误) } ``` ## 九、数据库表结构参考 ### 9.1 流程配置表(ect_meta_process) ```sql CREATE TABLE `ect_meta_process` ( `process_id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, `process_name` varchar(255) COMMENT '流程名称(清洗/消毒/干燥等)', `process_duration` int COMMENT '流程时长(秒)', `process_type` varchar(20) COMMENT '洗消类型(手工洗/机洗等)', `optional` int COMMENT '0=选配 1=必配', `process_order` int COMMENT '顺序', `status` int COMMENT '1=启用 0=禁用', PRIMARY KEY (`process_id`) ); ``` ### 9.2 操作记录表(ect_actions) ```sql CREATE TABLE `ect_actions` ( `action_id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, `batch_no` varchar(50) COMMENT '批次号(同一次清洗流程相同)', `action_type` int COMMENT '操作类型', `action_type_name` varchar(50) COMMENT '操作类型名称', `process_name` varchar(50) COMMENT '流程名称(清洗/消毒等)', `reader_id` bigint COMMENT '读卡器ID', `reader_no` varchar(50) COMMENT '读卡器编号', `endoscope_id` bigint COMMENT '内镜ID', `endoscope_rfid` varchar(50) COMMENT '内镜RFID', `endoscope_name` varchar(100) COMMENT '内镜名称', `op_starttime` datetime COMMENT '操作开始时间', `op_endtime` datetime COMMENT '操作结束时间', `created_at` datetime, PRIMARY KEY (`action_id`) ); ``` ## 十、常见问题 ### Q1: 如何跳过某个步骤? ```php $engine->disableNode('干燥'); ``` ### Q2: 如何修改步骤时间? ```php $config = new ProcessConfig([ 'time_validation' => [ 'durations' => ['消毒' => 600], ], ]); ``` ### Q3: 批次号如何保证分布式一致? 系统会从数据库查询该内镜未完成的流程批次号,如果存在则使用已有批次号,不存在则生成新的。 ### Q4: 如何添加自定义语音? ```php $engine->setStepVoice('清洗', '自定义语音内容'); ``` ### Q5: 如何支持新的流程类型? 1. 创建新的节点类继承 `AbstractProcessNode` 2. 在配置中添加步骤 3. 实现 `canHandle()` 和 `doHandle()` 方法