要实现一个基于 ThinkPHP 6.1 的排队叫号系统,我们可以按照以下步骤进行开发。系统将使用 Redis 作为队列存储,WebSocket 实现实时推送,并提供 API 接口供用户和管理员操作。
1. 环境准备
首先,确保你已经安装了以下组件:
PHP 7.4+
ThinkPHP 6.1
Redis
MySQL(可选,用于持久化历史记录)
WebSocket 服务器(如 Swoole 或 Workerman)
2. 安装依赖
在 ThinkPHP 6.1 项目中,安装 Redis 和 WebSocket 相关的扩展包。
composer require topthink/think-redis
composer require workerman/workerman
3. 配置 Redis
在 config/cache.php 中配置 Redis 连接:
return [
'default' => 'redis',
'stores' => [
'redis' => [
'type' => 'redis',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'persistent' => false,
],
],
];
4. 创建队列管理类
创建一个队列管理类 app\service\QueueService.php,用于管理 Redis 队列。
namespace app\service;
usethink\facade\Cache;
class QueueService
{
protected$queueKey = 'queue:numbers';
protected$webSocketService;
publicfunction __construct()
{
$this->webSocketService = newWebSocketService();
}
// 取号
publicfunction getNumber()
{
$number = Cache::incr('queue:counter');
Cache::rPush($this->queueKey, $number);
return$number;
}
// 叫号
publicfunction callNumber()
{
$number = Cache::lPop($this->queueKey);
if ($number) {
// 推送叫号信息到 WebSocket
$this->webSocketService->pushToAll(['type' => 'call', 'number' => $number]);
}
return$number;
}
// 获取当前排队状态
publicfunction getQueueStatus()
{
returnCache::lRange($this->queueKey, 0, -1);
}
}
5. 创建 WebSocket 服务类
在 app\service 目录下创建一个 WebSocketService.php 文件,用于封装 WebSocket 服务器的逻辑。
namespace app\service;
useWorkerman\Worker;
useWorkerman\Connection\TcpConnection;
class WebSocketService
{
protected$worker;
publicfunction __construct($address = 'websocket://0.0.0.0:2346')
{
$this->worker = newWorker($address);
$this->worker->onConnect = function(TcpConnection $connection) {
echo"New connection\n";
};
$this->worker->onMessage = function(TcpConnection $connection, $data) {
// 处理客户端发送的消息
$connection->send(json_encode(['type' => 'message', 'content' => 'Hello']));
};
$this->worker->onClose = function(TcpConnection $connection) {
echo"Connection closed\n";
};
}
// 启动 WebSocket 服务器
publicfunction start()
{
Worker::runAll();
}
// 推送消息到所有客户端
publicfunction pushToAll($message)
{
foreach ($this->worker->connections as$connection) {
$connection->send(json_encode($message));
}
}
}
6. 创建 API 接口
在 app\controller\QueueController.php 中创建 API 接口。
namespace app\controller;
useapp\service\QueueService;
usethink\facade\Request;
class QueueController
{
protected$queueService;
publicfunction __construct()
{
$this->queueService = newQueueService();
}
// 取号
publicfunction getNumber()
{
$number = $this->queueService->getNumber();
returnjson(['code' => 200, 'message' => '取号成功', 'number' => $number]);
}
// 叫号
publicfunction callNumber()
{
$number = $this->queueService->callNumber();
returnjson(['code' => 200, 'message' => '叫号成功', 'number' => $number]);
}
// 查看当前排队状态
publicfunction getQueueStatus()
{
$status = $this->queueService->getQueueStatus();
returnjson(['code' => 200, 'message' => '获取成功', 'status' => $status]);
}
}`
7. 路由配置
在 route/route.php 中配置路由。
use think\facade\Route;
Route::get('queue/getNumber', 'QueueController/getNumber');
Route::get('queue/callNumber', 'QueueController/callNumber');
Route::get('queue/getQueueStatus', 'QueueController/getQueueStatus');
8. 前端实现
在前端页面中,使用 WebSocket 连接服务器,并实时接收叫号信息。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>排队叫号系统</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
<style>
body {
background-color: #f8f9fa;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
}
.card {
margin-top: 20px;
box-shadow: 04px8pxrgba(0, 0, 0, 0.1);
}
.card-header {
background-color: #007bff;
color: white;
font-size: 1.5rem;
font-weight: bold;
}
.btn-primary {
background-color: #007bff;
border-color: #007bff;
}
.btn-primary:hover {
background-color: #0056b3;
border-color: #0056b3;
}
.btn-success {
background-color: #28a745;
border-color: #28a745;
}
.btn-success:hover {
background-color: #218838;
border-color: #218838;
}
.status-box {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 04px8pxrgba(0, 0, 0, 0.1);
margin-top: 20px;
}
.status-boxh3 {
margin-bottom: 15px;
font-size: 1.25rem;
color: #333;
}
.status-boxul {
list-style-type: none;
padding: 0;
}
.status-boxulli {
padding: 10px;
border-bottom: 1px solid #eee;
font-size: 1rem;
color: #555;
}
.status-boxulli:last-child {
border-bottom: none;
}
</style>
</head>
<body>
<div class="container">
<div class="card">
<div class="card-header text-center">
排队叫号系统
</div>
<div class="card-body">
<div class="d-grid gap-2">
<button class="btn btn-primary btn-lg" onclick="getNumber()">
<i class="fas fa-ticket-alt"></i> 取号
</button>
<button class="btn btn-success btn-lg" onclick="callNumber()">
<i class="fas fa-bullhorn"></i> 叫号
</button>
</div>
<div class="status-box">
<h3>当前排队状态</h3>
<ul id="status"></ul>
</div>
</div>
</div>
</div>
<script>
const ws = newWebSocket('ws://127.0.0.1:2346');
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
if (data.type === 'call') {
alert(`叫号:${data.number}`);
}
};
functiongetNumber() {
fetch('api/queue/getNumber')
.then(response => response.json())
.then(data => {
alert(`取号成功:${data.number}`);
});
}
functioncallNumber() {
fetch('api/queue/callNumber')
.then(response => response.json())
.then(data => {
alert(`叫号成功:${data.number}`);
});
}
functiongetQueueStatus() {
fetch('api/queue/getQueueStatus')
.then(response => response.json())
.then(data => {
const statusList = document.getElementById('status');
statusList.innerHTML = data.status.map(number =>`<li>号码:${number}</li>`).join('');
});
}
// 定时获取排队状态
setInterval(getQueueStatus, 5000);
</script>
<!-- Bootstrap JS and dependencies -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.min.js"></script>
</body>
</html>
9. 运行 WebSocket 服务器
在命令行中运行 WebSocket 服务器:
php websocket.php start
10. 运行 ThinkPHP 项目
启动 ThinkPHP 项目:
php websocket.php start
关注公众号回复“激活码”,获取2025年最新IDEA激活码