# 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 服务需要特别注意内存泄漏问题,确保资源能够正确释放。