feat: 实现TCP Server

This commit is contained in:
zimoyin
2026-03-02 21:59:43 +08:00
parent 043306819b
commit a79dfae57d
144 changed files with 15785 additions and 140 deletions
+131
View File
@@ -0,0 +1,131 @@
<?php
namespace app\flow;
use app\config\Config;
use app\utils\Logger;
/**
* 操作员会话管理器(进程内单例)
*
* 职责:记录每个读卡器上最近一次刷过的人员卡信息。
* 流程规则:
* 1. 先刷人员卡 → 记录到本管理器(以 readerId 为 key
* 2. 再刷内镜卡 → 从本管理器取出操作员信息,写入 ProcessContext,随即清除会话
* 3. 无论内镜卡刷卡结果正确还是错误,会话均立即清除,下次需重新刷人员卡
*/
class OperatorSessionManager
{
/**
* 单例实例
*/
private static ?self $instance = null;
/**
* 会话存储:[readerId => ['id'=>..., 'name'=>..., 'rfid'=>...]]
*/
private array $sessions = [];
/**
* 人员刷卡记录缓存记录多久
*/
public int $expire = 0;
/**
* 人员刷卡记录记录哪些读卡器的
* 设置为空则表示所有读卡器
*/
public array $recordReaders = [];
private function __construct()
{
$this->expire = Config::getInstance()->openCardRecordCacheTime;
$this->recordReaders = Config::getInstance()->openCardRecordReaders;
}
public static function getInstance(): self
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* 重置单例(测试用)
*/
public static function resetInstance(): void
{
self::$instance = null;
}
/**
* 记录某读卡器上的操作员信息
*
* @param string $readerId 读卡器ID
* @param string $userId 操作员ID
* @param string $userName 操作员姓名
* @param string $userRfid 操作员RFID
*/
public function setOperator(string $readerId, string $userId, string $userName, string $userRfid): void
{
$this->sessions[$readerId] = [
'id' => $userId,
'name' => $userName,
'rfid' => $userRfid,
'time' => time(),
];
}
/**
* 获取某读卡器上记录的操作员信息
*
* @param string $readerId 读卡器ID
* @return array|null ['id'=>..., 'name'=>..., 'rfid'=>...] 或 null(未登记)
*/
public function getOperator(string $readerId, string $readerType): ?array
{
$cache = $this->sessions[$readerId] ?? null;
$time = $cache['time'];
Logger::debug("OperatorSessionManager::getOperator($readerId, $readerType)");
if (empty($cache)) return null;
if ($this->expire > 0 && isset($time) && (time() - $time) <= $this->expire) {
if (in_array($readerType, $this->recordReaders) && empty($this->recordReaders)) {
return $cache;
}
}
return $this->pop($readerId);
}
/**
* 判断某读卡器是否已有操作员登记
*/
public function hasOperator(string $readerId): bool
{
return isset($this->sessions[$readerId]);
}
/**
* 清除某读卡器的操作员会话(内镜卡刷卡后立即调用)
*/
public function clearOperator(string $readerId): void
{
unset($this->sessions[$readerId]);
}
/**
* 清除所有会话(测试用)
*/
public function clearAll(): void
{
$this->sessions = [];
}
public function pop(string $readerId): ?array
{
$op = $this->getOperator($readerId);
$this->clearOperator($readerId);
return $op;
}
}