# new-admin **Repository Path**: tlan_turing/new-admin ## Basic Information - **Project Name**: new-admin - **Description**: 1 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-05-07 - **Last Updated**: 2025-05-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 项目介绍 - SAAS 项目后台 - 项目由 前台 、后台、中后台结构 - 前台 - 用户、会员显示端; - 主要负责 如cms/shop/会员管理等 - 中后台 - 商户登录入口 - 主要负责 安装、卸载插件、应用管理 - 管理用户、插件、应用的配置、列表显示等 - 后台 - 主控端口 - 主要负责管理商户的插件、应用分配、购买、时长 - 创建、发布插件、控制版本 ## 安装 ## 目录结构 ``` . ├── .idea/ # IDE配置文件 ├── app/ # 应用目录 ├── config/ # 配置文件目录 ├── composer.json # Composer依赖定义 ├── composer.lock # Composer依赖锁定文件 ├── vendor/ # Composer依赖包目录 │ ├── autoload.php # Composer自动加载文件 │ ├── services.php # 服务发现文件 │ ├── topthink/ # ThinkPHP框架核心包 │ │ ├── framework/ # ThinkPHP框架核心 │ │ ├── think-orm/ # ORM组件 │ │ ├── think-helper/ # 助手函数 │ │ ├── think-dumper/ # 调试工具 │ │ ├── think-validate/ # 验证组件 │ │ ├── think-container/ # 容器组件 │ │ ├── think-multi-app/ # 多应用支持 │ │ ├── think-filesystem/ # 文件系统组件 │ │ ├── think-trace/ # 追踪工具 │ │ └── think-swoole/ # Swoole扩展支持 │ ├── adminmatrix/ # 自定义adminmatrix相关包 │ │ ├── matrix_admin/ # 管理后台核心包 │ │ ├── matrix_plugin/ # 插件系统包 │ │ └── matrix_migration/ # 数据迁移包 │ └── bin/ # 可执行文件目录 ├── public/ # 公共资源目录 ├── runtime/ # 运行时目录 ├── route/ # 路由配置目录 ├── view/ # 视图文件目录 ├── extend/ # 扩展目录 ├── template/ # 模板目录 │ └── admin/ # 管理后台模板 ├── think # 命令行入口文件 ├── LICENSE.txt # 许可证文件 ├── .gitignore # Git忽略文件 ├── .example.env # 环境变量示例文件 ├── .travis.yml # Travis CI配置文件 └── README.md # 项目说明文件 ``` ## 版本日志 - 2025年5月6日 - 创建thinkphp 初始化版本 - 创建template/admin 后台管理 - [x] 完成前后台搭建 ## 安装配置 ### 宝塔配置 - 使用thinkphp 异步项目 - > 启动命令 php think swoole - php 版本 8.4 #### 配置文件 - 配置文件 -> nginx配置文件 ```angular2html # ▼ 新增 WebSocket 代理配置 ▼ location /ws { proxy_pass http://127.0.0.1:7788; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # ▲ 结束 WebSocket 配置 ▲ ``` - 配置文件 -> 伪静态 ``` location ~* (runtime|application)/{ return 403; } location / { if (!-e $request_filename){ rewrite ^(.*)$ /index.php?s=$1 last; break; } proxy_pass http://127.0.0.1:9501; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 安装程序专用路由 location /install { try_files $uri $uri/ /install/index.php?$query_string; } ``` # swoole ## Matrix Swoole 使用指南 Matrix Swoole 是基于 ThinkPHP Swoole 扩展开发的组件,提供了 WebSocket 服务、异步任务处理、协程等功能。 ### 配置说明 在项目的 `config/swoole.php` 文件中可以配置 Swoole 相关参数: ```php return [ 'http' => [ 'enable' => true, // 是否启用 HTTP 服务器 'host' => '0.0.0.0', // 监听地址 'port' => 8080, // 监听端口 'worker_num' => swoole_cpu_num(), // 工作进程数量 'options' => [], // 额外的 Swoole 配置 ], 'websocket' => [ 'enable' => false, // 是否启用 WebSocket 服务器 'route' => true, // 是否启用路由 'handler' => \adminmatrix\swoole\websocket\Handler::class, // WebSocket 处理器 'ping_interval' => 25000, // 心跳间隔 (ms) 'ping_timeout' => 60000, // 心跳超时 (ms) 'room' => [ // 房间配置 'type' => 'table', // 存储类型: table 或 redis 'table' => [ // 使用内存表存储 'room_rows' => 8192, 'room_size' => 2048, 'client_rows' => 4096, 'client_size' => 2048, ], 'redis' => [ // 使用 Redis 存储 'host' => '127.0.0.1', 'port' => 6379, 'max_active' => 3, 'max_wait_time' => 5, ], ], 'listen' => [], // 事件监听器 'subscribe' => [], // 订阅配置 ], // ... 其他配置 ]; ``` ### 启动服务 使用以下命令启动 Swoole 服务: ```bash php think swoole ``` 启动后,会显示服务信息,包括 HTTP 和 WebSocket 监听地址、端口等。 ### WebSocket 使用 #### 1. 开启 WebSocket 服务 在 `config/swoole.php` 中启用 WebSocket: ```php 'websocket' => [ 'enable' => true, // ... 其他配置 ], ``` #### 2. 自定义 WebSocket 处理器 创建自定义 WebSocket 处理器: ```php fd} 连接成功\n"; // 调用父类方法触发事件 parent::onOpen($request); } /** * 收到消息时触发 */ public function onMessage(Frame $frame) { echo "收到客户端 {$frame->fd} 的消息: {$frame->data}\n"; // 解析消息(JSON格式) $data = json_decode($frame->data, true); // 根据消息类型处理 if (!empty($data['type'])) { switch ($data['type']) { case 'chat': // 处理聊天消息 $this->handleChatMessage($frame->fd, $data['data'] ?? []); break; case 'join_room': // 处理加入房间请求 $this->handleJoinRoom($frame->fd, $data['data']['room'] ?? ''); break; // 其他消息类型... } } // 调用父类方法触发事件 parent::onMessage($frame); } /** * 连接关闭时触发 */ public function onClose() { echo "客户端连接关闭\n"; // 调用父类方法触发事件 parent::onClose(); } /** * 处理聊天消息 */ protected function handleChatMessage($fd, $data) { // 获取 Swoole Server 实例 $server = app('swoole.server'); // 广播消息到指定房间 $roomId = $data['room'] ?? ''; if ($roomId) { // 获取房间管理器 $room = app(\adminmatrix\swoole\websocket\Room::class); // 获取房间内所有客户端 $clients = $room->getClients($roomId); // 构建响应消息 $response = json_encode([ 'type' => 'chat', 'data' => [ 'user' => $data['user'] ?? 'anonymous', 'message' => $data['message'] ?? '', 'time' => date('Y-m-d H:i:s') ] ]); // 发送给房间内所有客户端 foreach ($clients as $clientId) { $server->push($clientId, $response); } } } /** * 处理加入房间请求 */ protected function handleJoinRoom($fd, $roomId) { if (empty($roomId)) { return; } // 获取房间管理器 $room = app(\adminmatrix\swoole\websocket\Room::class); // 将客户端加入房间 $room->add($fd, $roomId); // 通知客户端已加入房间 $server = app('swoole.server'); $server->push($fd, json_encode([ 'type' => 'room_joined', 'data' => [ 'room' => $roomId, 'time' => date('Y-m-d H:i:s') ] ])); } } ``` 然后在配置中使用该处理器: ```php 'websocket' => [ 'enable' => true, 'handler' => \app\websocket\MyHandler::class, // ... 其他配置 ], ``` #### 3. 前端 WebSocket 客户端示例 ```javascript // 建立 WebSocket 连接 const ws = new WebSocket('ws://example.com/ws'); // 连接建立时触发 ws.onopen = function() { console.log('WebSocket 连接已建立'); // 发送加入房间请求 ws.send(JSON.stringify({ type: 'join_room', data: { room: 'room1' } })); }; // 收到消息时触发 ws.onmessage = function(event) { try { const data = JSON.parse(event.data); console.log('收到消息:', data); // 根据消息类型处理 switch (data.type) { case 'chat': // 显示聊天消息 displayChatMessage(data.data); break; case 'room_joined': console.log('已加入房间:', data.data.room); break; // 处理其他消息类型... } } catch (e) { console.error('消息解析错误:', e); } }; // 连接关闭时触发 ws.onclose = function() { console.log('WebSocket 连接已关闭'); }; // 连接出错时触发 ws.onerror = function(error) { console.error('WebSocket 错误:', error); }; // 发送聊天消息 function sendChatMessage(message) { if (ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: 'chat', data: { room: 'room1', user: '用户名', message: message } })); } else { console.error('WebSocket 连接未建立'); } } // 显示聊天消息 function displayChatMessage(data) { const messageContainer = document.getElementById('messages'); const messageElement = document.createElement('div'); messageElement.className = 'message'; messageElement.innerHTML = ` ${data.user}: ${data.message} ${data.time} `; messageContainer.appendChild(messageElement); // 滚动到底部 messageContainer.scrollTop = messageContainer.scrollHeight; } ``` ### 异步任务处理 Matrix Swoole 支持使用 Task 处理异步任务,适用于耗时操作如发送邮件、处理大量数据等。 #### 1. 配置 Task 确保在 `config/swoole.php` 中启用了 Task: ```php return [ // ... 其他配置 'server' => [ // ... 服务器配置 'options' => [ // ... 其他选项 'task_worker_num' => swoole_cpu_num(), // 任务工作进程数 ], ], ]; ``` #### 2. 发送异步任务 在控制器或服务中发送异步任务: ```php doSendEmail('user@example.com', '通知邮件', '这是一封测试邮件'); return true; }); // 异步任务方式二:使用事件 Event::trigger('send_email', [ 'to' => 'user@example.com', 'subject' => '通知邮件', 'content' => '这是一封测试邮件' ]); return json(['code' => 0, 'msg' => $result]); } /** * 处理大量数据 */ public function processData() { // 同步获取数据 $dataIds = [1, 2, 3, 4, 5]; // 假设这是要处理的数据ID列表 // 批量提交异步任务 foreach ($dataIds as $id) { Task::async(function () use ($id) { // 处理单个数据的耗时操作 $this->processItem($id); return "数据 {$id} 处理完成"; }, function ($result) { // 任务完成后的回调函数 echo $result . "\n"; }); } return json(['code' => 0, 'msg' => '数据处理已提交']); } /** * 实际发送邮件的方法 */ protected function doSendEmail($to, $subject, $content) { // 模拟耗时操作 sleep(2); // 记录日志 file_put_contents( runtime_path() . 'email.log', date('Y-m-d H:i:s') . " 发送邮件到:{$to}, 标题:{$subject}\n", FILE_APPEND ); } /** * 处理单个数据项 */ protected function processItem($id) { // 模拟耗时操作 sleep(rand(1, 3)); // 记录日志 file_put_contents( runtime_path() . 'process.log', date('Y-m-d H:i:s') . " 处理数据 ID: {$id}\n", FILE_APPEND ); } } ``` #### 3. 监听事件处理异步任务 在 `app/event.php` 中注册事件监听器: ```php [ ], 'listen' => [ 'send_email' => [ 'app\\listener\\SendEmailListener', ], // 其他事件... ], ]; ``` 创建对应的监听器: ```php 'api.example.com', 'path' => '/user', 'port' => 443], ['host' => 'api.example.com', 'path' => '/products', 'port' => 443], ['host' => 'api.example.com', 'path' => '/orders', 'port' => 443], ]; // 并发请求 foreach ($apis as $index => $api) { // 创建协程 Coroutine::create(function () use ($channel, $api, $index) { // 创建HTTP客户端 $client = new Client($api['host'], $api['port'], $api['port'] === 443); // 发起请求 $client->get($api['path']); // 将结果放入通道 $channel->push([ 'index' => $index, 'status' => $client->statusCode, 'body' => $client->body, ]); // 关闭连接 $client->close(); }); } // 收集结果 $results = []; for ($i = 0; $i < count($apis); $i++) { $results[] = $channel->pop(); } // 关闭通道 $channel->close(); $endTime = microtime(true); $executionTime = round($endTime - $startTime, 3); return json([ 'code' => 0, 'execution_time' => $executionTime . 's', 'data' => $results, ]); } /** * 协程数据库操作 */ public function dbCoroutine() { $startTime = microtime(true); // 协程通道 $channel = new Coroutine\Channel(2); // 创建两个协程 Coroutine::create(function () use ($channel) { // 在协程中执行数据库查询 $users = Db::table('user')->where('status', 1)->select(); $channel->push(['type' => 'users', 'data' => $users]); }); Coroutine::create(function () use ($channel) { // 在另一个协程中执行不同的查询 $orders = Db::table('order')->where('status', 'paid')->select(); $channel->push(['type' => 'orders', 'data' => $orders]); }); // 收集结果 $result1 = $channel->pop(); $result2 = $channel->pop(); // 关闭通道 $channel->close(); $endTime = microtime(true); $executionTime = round($endTime - $startTime, 3); return json([ 'code' => 0, 'execution_time' => $executionTime . 's', 'data' => [ $result1['type'] => $result1['data'], $result2['type'] => $result2['data'], ], ]); } } ``` ### 注意事项 1. **全局变量**:在 Swoole 环境下,应避免依赖全局变量和静态变量,因为这些变量可能会在多个请求之间共享。 2. **连接复用**:数据库连接、Redis 连接等应该使用 Swoole 的连接池功能,避免每次请求都创建新连接。 3. **协程安全**:在使用协程时,需要确保代码是协程安全的,特别是涉及到共享资源的操作。 4. **异常处理**:在协程和异步任务中,应妥善处理异常,避免未捕获的异常导致工作进程退出。 5. **内存泄漏**:长时间运行的 Swoole 服务需要特别注意内存泄漏问题,确保资源能够正确释放。