add code
8
.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
/runtime
|
||||
/.idea
|
||||
/.vscode
|
||||
/vendor
|
||||
*.log
|
||||
.env
|
||||
/tests/tmp
|
||||
/tests/.phpunit.result.cache
|
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 walkor<walkor@workerman.net> and contributors (see https://github.com/walkor/webman/contributors)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
59
README.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
<div style="padding:18px;max-width: 1024px;margin:0 auto;background-color:#fff;color:#333">
|
||||
<h1>webman</h1>
|
||||
|
||||
基于<a href="https://www.workerman.net" target="__blank">workerman</a>开发的超高性能PHP框架
|
||||
|
||||
|
||||
<h1>学习</h1>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/webman" target="__blank">主页 / Home page</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/doc/webman" target="__blank">文档 / Document</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/doc/webman/install.html" target="__blank">安装 / Install</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/questions" target="__blank">问答 / Questions</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/apps" target="__blank">市场 / Apps</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/sponsor" target="__blank">赞助 / Sponsors</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/doc/webman/thanks.html" target="__blank">致谢 / Thanks</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div style="float:left;padding-bottom:30px;">
|
||||
|
||||
<h1>赞助商</h1>
|
||||
|
||||
<h4>特别赞助</h4>
|
||||
<a href="https://www.crmeb.com/?form=workerman" target="__blank">
|
||||
<img src="https://www.workerman.net/img/sponsors/6429/20230719111500.svg" width="200">
|
||||
</a>
|
||||
|
||||
<h4>铂金赞助</h4>
|
||||
<a href="https://www.fadetask.com/?from=workerman" target="__blank"><img src="https://www.workerman.net/img/sponsors/1/20230719084316.png" width="200"></a>
|
||||
<a href="https://www.yilianyun.net/?from=workerman" target="__blank" style="margin-left:20px;"><img src="https://www.workerman.net/img/sponsors/6218/20230720114049.png" width="200"></a>
|
||||
|
||||
<h4>金牌赞助</h4>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div style="clear: both">
|
||||
<h1>LICENSE</h1>
|
||||
The webman is open-sourced software licensed under the MIT.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
26
app/controller/DepartmentController.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
namespace app\controller;
|
||||
|
||||
use app\service\DepartmentService;
|
||||
use app\util\Result;
|
||||
use support\Request;
|
||||
|
||||
class DepartmentController
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var Result
|
||||
*/
|
||||
private $result;
|
||||
/**
|
||||
* @Inject
|
||||
* @var DepartmentService
|
||||
*/
|
||||
private $departmentService;
|
||||
public function list(Request $request)
|
||||
{
|
||||
$info = $this->departmentService->allList();
|
||||
if ($info['result']) return json(retData($this->result::SUCCESS, $info['msg'], $info['data']));
|
||||
return json(retData($this->result::ERROR, $info['msg']));
|
||||
}
|
||||
}
|
31
app/controller/FileController.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use app\util\Result;
|
||||
use support\Request;
|
||||
|
||||
class FileController
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var Result
|
||||
*/
|
||||
private $result;
|
||||
|
||||
public function upload(Request $request)
|
||||
{
|
||||
$file = $request->file('file');
|
||||
if ($file && $file->isValid()) {
|
||||
$name = md5(uniqid());
|
||||
$file->move(public_path() . '/upload/' . $name . '.' . $file->getUploadExtension());
|
||||
$data = [
|
||||
'id' => $name,
|
||||
'src' => $request->header('x-forwarded-proto') ?? 'http' . '://' . $request->host() . '/upload/' . $name . '.' . $file->getUploadExtension(),
|
||||
'fileName' => $name
|
||||
];
|
||||
return json(retData($this->result::SUCCESS, 'upload success', $data));
|
||||
}
|
||||
return json(retData($this->result::ERROR, 'file not found'));
|
||||
}
|
||||
}
|
30
app/controller/IndexController.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use think\facade\Db;
|
||||
|
||||
class IndexController
|
||||
{
|
||||
protected $noNeedLogin = ['json'];
|
||||
public function index(Request $request)
|
||||
{
|
||||
static $readme;
|
||||
if (!$readme) {
|
||||
$readme = file_get_contents(base_path('README.md'));
|
||||
}
|
||||
return $readme;
|
||||
}
|
||||
|
||||
public function view(Request $request)
|
||||
{
|
||||
return view('index/view', ['name' => 'webman']);
|
||||
}
|
||||
|
||||
public function json(Request $request)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
39
app/controller/MenuController.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
namespace app\controller;
|
||||
|
||||
use app\service\MenuService;
|
||||
use app\util\Result;
|
||||
use support\Request;
|
||||
use DI\Annotation\Inject;
|
||||
class MenuController
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var Result
|
||||
*/
|
||||
private $result;
|
||||
/**
|
||||
* @Inject
|
||||
* @var MenuService
|
||||
*/
|
||||
private $menuService;
|
||||
public function getMenu(Request $request)
|
||||
{
|
||||
$info = $this->menuService->getList();
|
||||
if ($info['result']) return json(retData($this->result::SUCCESS, $info['msg'], $info['data']));
|
||||
return json(retData($this->result::ERROR, $info['msg']));
|
||||
}
|
||||
|
||||
public function my(Request $request)
|
||||
{
|
||||
$info = $this->menuService->getList();
|
||||
if ($info['result']) return json(retData($this->result::SUCCESS, $info['msg'], $info['data']));
|
||||
return json(retData($this->result::ERROR, $info['msg']));
|
||||
}
|
||||
public function list(Request $request)
|
||||
{
|
||||
$info = $this->menuService->getList($request->uid);
|
||||
if ($info['result']) return json(retData($this->result::SUCCESS, $info['msg'], $info['data']));
|
||||
return json(retData($this->result::ERROR, $info['msg']));
|
||||
}
|
||||
}
|
56
app/controller/RoleController.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
namespace app\controller;
|
||||
|
||||
use app\service\RoleService;
|
||||
use app\util\Result;
|
||||
use support\Request;
|
||||
|
||||
class RoleController
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var RoleService
|
||||
*/
|
||||
private $roleService;
|
||||
/**
|
||||
* @Inject
|
||||
* @var Result
|
||||
*/
|
||||
private $result;
|
||||
|
||||
/**
|
||||
* User: 高军
|
||||
* Date: 2024/5/8
|
||||
* QQ: 2926804347
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
* Notes:
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$info = $this->roleService->allList();
|
||||
if ($info['result']) return json(retData($this->result::SUCCESS, $info['msg'], $info['data']));
|
||||
return json(retData($this->result::ERROR, $info['msg']));
|
||||
}
|
||||
|
||||
/**
|
||||
* User: 高军
|
||||
* Date: 2024/5/8
|
||||
* QQ: 2926804347
|
||||
* @param array $param
|
||||
* @return array
|
||||
* Notes:
|
||||
*/
|
||||
public function getList(array $param):array
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function save(Request $request)
|
||||
{
|
||||
$param = $request->post();
|
||||
$info = $this->roleService->save($param);
|
||||
if ($info['result']) return json(retData($this->result::SUCCESS, $info['msg'], $info['data']));
|
||||
return json(retData($this->result::ERROR, $info['msg']));
|
||||
}
|
||||
}
|
36
app/controller/RoleMenuController.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
namespace app\controller;
|
||||
|
||||
use app\service\RoleMenuService;
|
||||
use app\util\Result;
|
||||
use support\Request;
|
||||
|
||||
class RoleMenuController
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var Result
|
||||
*/
|
||||
private $result;
|
||||
/**
|
||||
* @Inject
|
||||
* @var RoleMenuService
|
||||
*/
|
||||
private $roleMenuService;
|
||||
|
||||
protected $noNeedLogin = [];
|
||||
|
||||
|
||||
public function save(Request $request)
|
||||
{
|
||||
$param = $request->post();
|
||||
$info = $this->roleMenuService->save($param);
|
||||
if ($info['result']) return json(retData($this->result::SUCCESS, $info['msg'], $info['data']));
|
||||
return json(retData($this->result::ERROR, $info['msg']));
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
return json(retData(0, 'ahahah'));
|
||||
}
|
||||
}
|
43
app/controller/UserController.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
namespace app\controller;
|
||||
|
||||
use app\service\UserService;
|
||||
use app\util\Result;
|
||||
use support\Request;
|
||||
|
||||
class UserController
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var Result
|
||||
*/
|
||||
private $result;
|
||||
/**
|
||||
* @Inject
|
||||
* @var UserService
|
||||
*/
|
||||
private $userService;
|
||||
|
||||
protected $noNeedLogin = ['token', 'test'];
|
||||
public function token(Request $request)
|
||||
{
|
||||
$param = $request->post();
|
||||
if (empty($param['username']) || empty($param['password'])) return json(retData($this->result::ERROR, '账号密码不能为空'));
|
||||
$info = $this->userService->login($param['username'], $param['password']);
|
||||
if ($info['result']) return json(retData($this->result::SUCCESS, $info['msg'], $info['data']));
|
||||
return json(retData($this->result::ERROR, $info['msg']));
|
||||
}
|
||||
|
||||
public function list(Request $request)
|
||||
{
|
||||
$param = $request->get();
|
||||
$info = $this->userService->getList($param);
|
||||
if ($info['result']) return json(retData($this->result::SUCCESS, $info['msg'], $info['data']));
|
||||
return json(retData($this->result::ERROR, $info['msg']));
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
return json(retData(0, 'ahahah'));
|
||||
}
|
||||
}
|
14
app/functions.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* Here is your custom functions.
|
||||
*/
|
||||
|
||||
function show(bool $bool, string $msg, array $data = []):array
|
||||
{
|
||||
return ['result' => $bool, 'msg' => $msg, 'data' => $data];
|
||||
}
|
||||
|
||||
function retData(int $code, string $msg, array $data = []):array
|
||||
{
|
||||
return ['code' => $code, 'msg' => $msg, 'data' => $data];
|
||||
}
|
25
app/middleware/AccessControl.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
class AccessControl implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler) : Response
|
||||
{
|
||||
// 如果是options请求则返回一个空响应,否则继续向洋葱芯穿越,并得到一个响应
|
||||
$response = $request->method() == 'OPTIONS' ? response('') : $handler($request);
|
||||
|
||||
// 给响应添加跨域相关的http头
|
||||
$response->withHeaders([
|
||||
'Access-Control-Allow-Credentials' => 'true',
|
||||
'Access-Control-Allow-Origin' => $request->header('origin', '*'),
|
||||
'Access-Control-Allow-Methods' => $request->header('access-control-request-method', '*'),
|
||||
'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', '*'),
|
||||
]);
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
35
app/middleware/AuthCheck.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
namespace app\middleware;
|
||||
|
||||
use ReflectionClass;
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
class AuthCheck implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler) : Response
|
||||
{
|
||||
// 通过反射获取控制器哪些方法不需要登录
|
||||
$controller = new ReflectionClass($request->controller);
|
||||
$noNeedLogin = $controller->getDefaultProperties()['noNeedLogin'] ?? [];
|
||||
|
||||
// 访问的方法需要登录
|
||||
if (!in_array($request->action, $noNeedLogin)) {
|
||||
try {
|
||||
$uid = \Tinywan\Jwt\JwtToken::getCurrentId();
|
||||
if ($uid != 0) {
|
||||
$request->uid = $uid;
|
||||
return $handler($request);
|
||||
}
|
||||
}catch (\Exception $e) {
|
||||
return Response(json_encode(['code' => 0, 'msg' => $e->getMessage()], 256));
|
||||
}
|
||||
}else{
|
||||
return $handler($request);
|
||||
}
|
||||
|
||||
// 不需要登录,请求继续向洋葱芯穿越
|
||||
return $handler($request);
|
||||
}
|
||||
}
|
42
app/middleware/StaticFile.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
/**
|
||||
* Class StaticFile
|
||||
* @package app\middleware
|
||||
*/
|
||||
class StaticFile implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $next): Response
|
||||
{
|
||||
// Access to files beginning with. Is prohibited
|
||||
if (strpos($request->path(), '/.') !== false) {
|
||||
return response('<h1>403 forbidden</h1>', 403);
|
||||
}
|
||||
/** @var Response $response */
|
||||
$response = $next($request);
|
||||
// Add cross domain HTTP header
|
||||
/*$response->withHeaders([
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Credentials' => 'true',
|
||||
]);*/
|
||||
return $response;
|
||||
}
|
||||
}
|
18
app/model/Department.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class Department extends Model
|
||||
{
|
||||
protected $table = 'eb_department';
|
||||
protected $primaryKey = 'id';
|
||||
public $timestamps = false;
|
||||
|
||||
public function allList():array
|
||||
{
|
||||
$info = $this->field('id, name, parent_id')->select()->toArray();
|
||||
if ($info) return show(true, '获取成功', ['rows' => $info]);
|
||||
return show(false, '暂无查询到数据');
|
||||
}
|
||||
}
|
21
app/model/Menu.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class Menu extends Model
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'eb_menu';
|
||||
protected $primaryKey = 'id';
|
||||
public $timestamps = false;
|
||||
|
||||
public function getList()
|
||||
{
|
||||
$info = $this->field('id, parent_id, title, path, name, type, icon, component')->where('delete_time', 0)->where('type', 'menu')->select()->toArray();
|
||||
if ($info) return show(true, '获取成功', $info);
|
||||
return show(false, '暂无查询到的数据');
|
||||
}
|
||||
}
|
39
app/model/Role.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class Role extends Model
|
||||
{
|
||||
protected $table = 'eb_role';
|
||||
protected $primaryKey = 'id';
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* User: 高军
|
||||
* Date: 2024/5/8
|
||||
* QQ: 2926804347
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* Notes:
|
||||
*/
|
||||
public function allList():array
|
||||
{
|
||||
$info = $this->select()->toArray();
|
||||
if ($info) return show(true, '获取成功', ['rows' => $info]);
|
||||
return show(false, '暂无数据');
|
||||
}
|
||||
public function saveData(array $param):array
|
||||
{
|
||||
if (!empty($param['id'])) {
|
||||
$info = $this->update($param);
|
||||
}else{
|
||||
$param['create_time'] = date('Y-m-d H:i:s', time());
|
||||
$info = $this::create($param);
|
||||
}
|
||||
if ($info) return show(true, '保存成功');
|
||||
return show(false, '保存失败,请重试');
|
||||
}
|
||||
}
|
25
app/model/RoleMenu.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class RoleMenu extends Model
|
||||
{
|
||||
protected $table = 'eb_role_menu';
|
||||
protected $primaryKey = 'id';
|
||||
public $timestamps = false;
|
||||
|
||||
public function saveData(array $param):array
|
||||
{
|
||||
$info = $this->saveAll($param);
|
||||
if ($info) return show(true, '保存成功');
|
||||
return show(false, '保存失败,请重试');
|
||||
}
|
||||
|
||||
public function delByRoleId(int $roleId):array
|
||||
{
|
||||
$info = $this->where('role_id', $roleId)->where('delete_time', 0)->update(['delete_time' => time()]);
|
||||
if ($info) return show(true, '保存成功');
|
||||
return show(false, '保存失败,请重试');
|
||||
}
|
||||
}
|
29
app/model/Test.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
class Test extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'test';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
}
|
49
app/model/User.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
protected $table = 'eb_user';
|
||||
protected $primaryKey = 'id';
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* User: 高军
|
||||
* Date: 2024/5/8
|
||||
* QQ: 2926804347
|
||||
* @param string $userName
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* Notes:
|
||||
*/
|
||||
public function getInfoByUserName(string $userName):array
|
||||
{
|
||||
$info = $this->where('delete_time', 0)->where('user_name', $userName)->find();
|
||||
if ($info) return show(true, '获取成功', $info->toArray());
|
||||
return show(false, '暂无查询到的数据');
|
||||
}
|
||||
|
||||
/**
|
||||
* User: 高军
|
||||
* Date: 2024/5/8
|
||||
* QQ: 2926804347
|
||||
* @param array $param
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* Notes:
|
||||
*/
|
||||
public function getList(array $param):array
|
||||
{
|
||||
$offset = ($param['page'] - 1) * $param['pageSize'];
|
||||
$data = $this->limit($offset, $param['pageSize'])->select()->toArray();
|
||||
$count = $this->count();
|
||||
if ($data) return show(true, '获取成功', ['rows' => $data, 'total' => $count]);
|
||||
return show(false, '暂无数据');
|
||||
}
|
||||
}
|
17
app/service/DepartmentService.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
namespace app\service;
|
||||
|
||||
use app\model\Department;
|
||||
|
||||
class DepartmentService
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var Department
|
||||
*/
|
||||
private $department;
|
||||
public function allList():array
|
||||
{
|
||||
return $this->department->allList();
|
||||
}
|
||||
}
|
110
app/service/MenuService.php
Normal file
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace app\service;
|
||||
|
||||
use app\model\Menu;
|
||||
|
||||
class MenuService
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var Menu
|
||||
*/
|
||||
private $menu;
|
||||
|
||||
public function getList(int $userId = 0)
|
||||
{
|
||||
$info = $this->menu->getList();
|
||||
if ($info['result']) {
|
||||
$data = $this->package($info['data']);
|
||||
$arr = $this->buildTree($data);
|
||||
$tempArr['menu'] = $arr;
|
||||
}
|
||||
$tempArr['permissions'] = ["list.add", "list.delete", "user.edit", "user.delete"];
|
||||
$tempArr['dashboardGrid'] = ["welcome", "ver", "time", "progress", "echarts", "about"];
|
||||
$info['data'] = $tempArr;
|
||||
return $info;
|
||||
}
|
||||
|
||||
public function myMenu(int $userId = 0):array {
|
||||
$info = $this->menu->getList();
|
||||
return $info;
|
||||
$arr = [];
|
||||
if ($info['result']) {
|
||||
$data = $this->package($info['data']);
|
||||
$arr = $this->buildTree($data);
|
||||
}
|
||||
$info['data'] = $arr;
|
||||
return $info;
|
||||
}
|
||||
|
||||
public function package(array $data): array
|
||||
{
|
||||
$arr = [];
|
||||
foreach ($data as $v) {
|
||||
$arr[] = [
|
||||
'id' => $v['id'],
|
||||
'parent_id' => $v['parent_id'],
|
||||
'name' => $v['name'],
|
||||
'path' => $v['path'],
|
||||
'meta' => [
|
||||
'title' => $v['title'],
|
||||
'icon' => $v['icon'],
|
||||
'type' => 'menu'
|
||||
],
|
||||
'component' => $v['component']
|
||||
];
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
public function buildTree(array $array, int $parentId = 0): array
|
||||
{
|
||||
$tree = [];
|
||||
foreach ($array as $element) {
|
||||
if ($element['parent_id'] == $parentId) {
|
||||
$children = $this->buildTree($array, $element['id']);
|
||||
if ($children) {
|
||||
$element['children'] = $children;
|
||||
}
|
||||
$tree[] = $element;
|
||||
}
|
||||
}
|
||||
return $tree;
|
||||
}
|
||||
|
||||
public function add($data)
|
||||
{
|
||||
$data = json_decode($data, true);
|
||||
foreach ($data as $k => $v) {
|
||||
$arr = [
|
||||
'parent_id' => 0,
|
||||
'name' => $v['name'],
|
||||
'path' => $v['path'],
|
||||
'title' => $v['meta']['title'],
|
||||
'icon' => $v['meta']['icon'],
|
||||
'type' => 'menu',
|
||||
'component' => $v['component'] ?? ''
|
||||
];
|
||||
$id = $this->menu->insertGetId($arr);
|
||||
if (isset($v['children'])) $this->buld($id, $v['children']);
|
||||
}
|
||||
}
|
||||
|
||||
public function buld($pid, $data)
|
||||
{
|
||||
foreach ($data as $v) {
|
||||
$arr = [
|
||||
'parent_id' => $pid,
|
||||
'name' => $v['name'],
|
||||
'path' => $v['path'],
|
||||
'title' => $v['meta']['title'],
|
||||
'icon' => $v['meta']['icon'] ?? '',
|
||||
'type' => 'menu',
|
||||
'component' => $v['component'] ?? ''
|
||||
];
|
||||
$id = $this->menu->insertGetId($arr);
|
||||
if (isset($v['children'])) $this->buld($id, $v['children']);
|
||||
}
|
||||
}
|
||||
}
|
29
app/service/RoleMenuService.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace app\service;
|
||||
|
||||
use app\model\RoleMenu;
|
||||
|
||||
class RoleMenuService
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var RoleMenu
|
||||
*/
|
||||
private $roleMenu;
|
||||
|
||||
|
||||
public function save(array $param): array
|
||||
{
|
||||
$arr = [];
|
||||
foreach ($param['menu_ids'] as $v) {
|
||||
$arr[] = [
|
||||
'role_id' => $param['role_id'],
|
||||
'menu_id' => $v,
|
||||
'create_time' => time()
|
||||
];
|
||||
}
|
||||
$this->roleMenu->delByRoleId($param['role_id']);
|
||||
return $this->roleMenu->saveData($arr);
|
||||
}
|
||||
}
|
22
app/service/RoleService.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
namespace app\service;
|
||||
|
||||
use app\model\Role;
|
||||
|
||||
class RoleService
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var Role
|
||||
*/
|
||||
private $role;
|
||||
public function allList():array
|
||||
{
|
||||
return $this->role->allList();
|
||||
}
|
||||
|
||||
public function save(array $param):array
|
||||
{
|
||||
return $this->role->saveData($param);
|
||||
}
|
||||
}
|
61
app/service/UserService.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace app\service;
|
||||
|
||||
use app\model\User;
|
||||
|
||||
class UserService
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* User: 高军
|
||||
* Date: 2024/5/8
|
||||
* QQ: 2926804347
|
||||
* @param string $userName
|
||||
* @param string $pwd
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* Notes:
|
||||
*/
|
||||
public function login(string $userName, string $pwd): array
|
||||
{
|
||||
$userInfo = $this->user->getInfoByUserName($userName);
|
||||
if (!$userInfo['result']) return $userInfo;
|
||||
if (!password_verify($pwd, $userInfo['data']['pass_word'])) return show(false, '用户名或密码错误');
|
||||
$tokenData = [
|
||||
'id' => $userInfo['data']['id'],
|
||||
'name' => $userInfo['data']['nickname'],
|
||||
'email' => $userInfo['data']['email']
|
||||
];
|
||||
$token = \Tinywan\Jwt\JwtToken::generateToken($tokenData);
|
||||
unset($userInfo['data']['pass_word']);
|
||||
$data = [
|
||||
'token' => $token,
|
||||
'userInfo' => $userInfo['data']
|
||||
];
|
||||
return show(true, '登录成功', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* User: 高军
|
||||
* Date: 2024/5/8
|
||||
* QQ: 2926804347
|
||||
* @param array $param
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* Notes:
|
||||
*/
|
||||
public function getList(array $param):array
|
||||
{
|
||||
return $this->user->getList($param);
|
||||
}
|
||||
}
|
8
app/util/Result.php
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
namespace app\util;
|
||||
|
||||
class Result
|
||||
{
|
||||
const SUCCESS = 200;
|
||||
const ERROR = 0;
|
||||
}
|
14
app/view/index/view.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="/favicon.ico"/>
|
||||
<title>webman</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
hello <?=htmlspecialchars($name)?>
|
||||
</body>
|
||||
</html>
|
BIN
build/php8.2.micro.sfx
Normal file
BIN
build/php8.2.micro.sfx.zip
Normal file
BIN
build/webman.phar
Normal file
63
composer.json
Normal file
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"name": "workerman/webman",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"high performance",
|
||||
"http service"
|
||||
],
|
||||
"homepage": "https://www.workerman.net",
|
||||
"license": "MIT",
|
||||
"description": "High performance HTTP Service Framework.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "walkor",
|
||||
"email": "walkor@workerman.net",
|
||||
"homepage": "https://www.workerman.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "walkor@workerman.net",
|
||||
"issues": "https://github.com/walkor/webman/issues",
|
||||
"forum": "https://wenda.workerman.net/",
|
||||
"wiki": "https://workerman.net/doc/webman",
|
||||
"source": "https://github.com/walkor/webman"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"workerman/webman-framework": "^1.5.0",
|
||||
"monolog/monolog": "^2.0",
|
||||
"webman/think-orm": "^1.1",
|
||||
"psr/container": "1.1.1",
|
||||
"php-di/php-di": "6",
|
||||
"doctrine/annotations": "1.14",
|
||||
"tinywan/jwt": "^1.9",
|
||||
"webman/console": "^1.3",
|
||||
"vlucas/phpdotenv": "^5.6"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": "./",
|
||||
"app\\": "./app",
|
||||
"App\\": "./app",
|
||||
"app\\View\\Components\\": "./app/view/components"
|
||||
},
|
||||
"files": [
|
||||
"./support/helpers.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"post-package-install": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"post-package-update": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"pre-package-uninstall": [
|
||||
"support\\Plugin::uninstall"
|
||||
]
|
||||
}
|
||||
}
|
2383
composer.lock
generated
Normal file
26
config/app.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\Request;
|
||||
|
||||
return [
|
||||
'debug' => true,
|
||||
'error_reporting' => E_ALL,
|
||||
'default_timezone' => 'Asia/Shanghai',
|
||||
'request_class' => Request::class,
|
||||
'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public',
|
||||
'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime',
|
||||
'controller_suffix' => 'Controller',
|
||||
'controller_reuse' => false,
|
||||
];
|
21
config/autoload.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'files' => [
|
||||
base_path() . '/app/functions.php',
|
||||
base_path() . '/support/Request.php',
|
||||
base_path() . '/support/Response.php',
|
||||
]
|
||||
];
|
19
config/bootstrap.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
support\bootstrap\Session::class,
|
||||
support\bootstrap\LaravelDb::class,
|
||||
Webman\ThinkOrm\ThinkOrm::class,
|
||||
];
|
19
config/container.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
$builder = new \DI\ContainerBuilder();
|
||||
$builder->addDefinitions(config('dependence', []));
|
||||
$builder->useAutowiring(true);
|
||||
$builder->useAnnotations(true);
|
||||
return $builder->build();
|
||||
//return new Webman\Container;
|
15
config/database.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
15
config/dependence.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
17
config/exception.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'' => support\exception\Handler::class,
|
||||
];
|
32
config/log.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'handlers' => [
|
||||
[
|
||||
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/webman.log',
|
||||
7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s', true],
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
20
config/middleware.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'' => [
|
||||
\app\middleware\AccessControl::class,
|
||||
\app\middleware\AuthCheck::class
|
||||
]
|
||||
];
|
83
config/plugin/tinywan/jwt/app.php
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'enable' => true,
|
||||
'jwt' => [
|
||||
/** 算法类型 HS256、HS384、HS512、RS256、RS384、RS512、ES256、ES384、Ed25519 */
|
||||
'algorithms' => 'HS256',
|
||||
|
||||
/** access令牌秘钥 */
|
||||
'access_secret_key' => '2022d3d3LmJq',
|
||||
|
||||
/** access令牌过期时间,单位:秒。默认 2 小时 */
|
||||
'access_exp' => 7200,
|
||||
|
||||
/** refresh令牌秘钥 */
|
||||
'refresh_secret_key' => '2022KTxigxc9o50c',
|
||||
|
||||
/** refresh令牌过期时间,单位:秒。默认 7 天 */
|
||||
'refresh_exp' => 604800,
|
||||
|
||||
/** refresh 令牌是否禁用,默认不禁用 false */
|
||||
'refresh_disable' => false,
|
||||
|
||||
/** 令牌签发者 */
|
||||
'iss' => 'webman.tinywan.cn',
|
||||
|
||||
/** 某个时间点后才能访问,单位秒。(如:30 表示当前时间30秒后才能使用) */
|
||||
'nbf' => 0,
|
||||
|
||||
/** 时钟偏差冗余时间,单位秒。建议这个余地应该不大于几分钟 */
|
||||
'leeway' => 60,
|
||||
|
||||
/** 是否允许单设备登录,默认不允许 false */
|
||||
'is_single_device' => false,
|
||||
|
||||
/** 缓存令牌时间,单位:秒。默认 7 天 */
|
||||
'cache_token_ttl' => 604800,
|
||||
|
||||
/** 缓存令牌前缀,默认 JWT:TOKEN: */
|
||||
'cache_token_pre' => 'JWT:TOKEN:',
|
||||
|
||||
/** 缓存刷新令牌前缀,默认 JWT:REFRESH_TOKEN: */
|
||||
'cache_refresh_token_pre' => 'JWT:REFRESH_TOKEN:',
|
||||
|
||||
/** 用户信息模型 */
|
||||
'user_model' => function ($uid) {
|
||||
return [];
|
||||
},
|
||||
|
||||
/** 是否支持 get 请求获取令牌 */
|
||||
'is_support_get_token' => false,
|
||||
/** GET 请求获取令牌请求key */
|
||||
'is_support_get_token_key' => 'authorization',
|
||||
|
||||
/** access令牌私钥 */
|
||||
'access_private_key' => <<<EOD
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
...
|
||||
-----END RSA PRIVATE KEY-----
|
||||
EOD,
|
||||
|
||||
/** access令牌公钥 */
|
||||
'access_public_key' => <<<EOD
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
...
|
||||
-----END PUBLIC KEY-----
|
||||
EOD,
|
||||
|
||||
/** refresh令牌私钥 */
|
||||
'refresh_private_key' => <<<EOD
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
...
|
||||
-----END RSA PRIVATE KEY-----
|
||||
EOD,
|
||||
|
||||
/** refresh令牌公钥 */
|
||||
'refresh_public_key' => <<<EOD
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
...
|
||||
-----END PUBLIC KEY-----
|
||||
EOD,
|
||||
],
|
||||
];
|
24
config/plugin/webman/console/app.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
return [
|
||||
'enable' => true,
|
||||
|
||||
'build_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build',
|
||||
|
||||
'phar_filename' => 'webman.phar',
|
||||
|
||||
'bin_filename' => 'webman.bin',
|
||||
|
||||
'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.
|
||||
|
||||
'private_key_file' => '', // The file path for certificate or OpenSSL private key file.
|
||||
|
||||
'exclude_pattern' => '#^(?!.*(composer.json|/.github/|/.idea/|/.git/|/.setting/|/runtime/|/vendor-bin/|/build/|/vendor/webman/admin/))(.*)$#',
|
||||
|
||||
'exclude_files' => [
|
||||
'.env', 'LICENSE', 'composer.json', 'composer.lock', 'start.php', 'webman.phar', 'webman.bin'
|
||||
],
|
||||
|
||||
'custom_ini' => '
|
||||
memory_limit = 256M
|
||||
',
|
||||
];
|
42
config/process.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
global $argv;
|
||||
|
||||
return [
|
||||
// File update detection and automatic reload
|
||||
'monitor' => [
|
||||
'handler' => process\Monitor::class,
|
||||
'reloadable' => false,
|
||||
'constructor' => [
|
||||
// Monitor these directories
|
||||
'monitorDir' => array_merge([
|
||||
app_path(),
|
||||
config_path(),
|
||||
base_path() . '/process',
|
||||
base_path() . '/support',
|
||||
base_path() . '/resource',
|
||||
base_path() . '/.env',
|
||||
], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')),
|
||||
// Files with these suffixes will be monitored
|
||||
'monitorExtensions' => [
|
||||
'php', 'html', 'htm', 'env'
|
||||
],
|
||||
'options' => [
|
||||
'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/',
|
||||
'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
22
config/redis.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'host' => '127.0.0.1',
|
||||
'password' => null,
|
||||
'port' => 6379,
|
||||
'database' => 0,
|
||||
],
|
||||
];
|
21
config/route.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Route;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
31
config/server.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'listen' => 'http://0.0.0.0:8787',
|
||||
'transport' => 'tcp',
|
||||
'context' => [],
|
||||
'name' => 'webman',
|
||||
'count' => cpu_count() * 4,
|
||||
'user' => '',
|
||||
'group' => '',
|
||||
'reusePort' => false,
|
||||
'event_loop' => '',
|
||||
'stop_timeout' => 2,
|
||||
'pid_file' => runtime_path() . '/webman.pid',
|
||||
'status_file' => runtime_path() . '/webman.status',
|
||||
'stdout_file' => runtime_path() . '/logs/stdout.log',
|
||||
'log_file' => runtime_path() . '/logs/workerman.log',
|
||||
'max_package_size' => 10 * 1024 * 1024
|
||||
];
|
65
config/session.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Session\FileSessionHandler;
|
||||
use Webman\Session\RedisSessionHandler;
|
||||
use Webman\Session\RedisClusterSessionHandler;
|
||||
|
||||
return [
|
||||
|
||||
'type' => 'file', // or redis or redis_cluster
|
||||
|
||||
'handler' => FileSessionHandler::class,
|
||||
|
||||
'config' => [
|
||||
'file' => [
|
||||
'save_path' => runtime_path() . '/sessions',
|
||||
],
|
||||
'redis' => [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'auth' => '',
|
||||
'timeout' => 2,
|
||||
'database' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
],
|
||||
'redis_cluster' => [
|
||||
'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
|
||||
'timeout' => 2,
|
||||
'auth' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
]
|
||||
],
|
||||
|
||||
'session_name' => 'PHPSID',
|
||||
|
||||
'auto_update_timestamp' => false,
|
||||
|
||||
'lifetime' => 7*24*60*60,
|
||||
|
||||
'cookie_lifetime' => 365*24*60*60,
|
||||
|
||||
'cookie_path' => '/',
|
||||
|
||||
'domain' => '',
|
||||
|
||||
'http_only' => true,
|
||||
|
||||
'secure' => false,
|
||||
|
||||
'same_site' => '',
|
||||
|
||||
'gc_probability' => [1, 1000],
|
||||
|
||||
];
|
23
config/static.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Static file settings
|
||||
*/
|
||||
return [
|
||||
'enable' => true,
|
||||
'middleware' => [ // Static file Middleware
|
||||
//app\middleware\StaticFile::class,
|
||||
],
|
||||
];
|
36
config/thinkorm.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'default' => 'mysql',
|
||||
'connections' => [
|
||||
'mysql' => [
|
||||
// 数据库类型
|
||||
'type' => 'mysql',
|
||||
// 服务器地址
|
||||
'hostname' => getenv('DB_HOST'),
|
||||
// 数据库名
|
||||
'database' => getenv('DB_NAME'),
|
||||
// 数据库用户名
|
||||
'username' => getenv('DB_USER'),
|
||||
// 数据库密码
|
||||
'password' => getenv('DB_PASSWORD'),
|
||||
// 数据库连接端口
|
||||
'hostport' => getenv('DB_PORT'),
|
||||
// 数据库连接参数
|
||||
'params' => [
|
||||
// 连接超时3秒
|
||||
\PDO::ATTR_TIMEOUT => 3,
|
||||
],
|
||||
// 数据库编码默认采用utf8
|
||||
'charset' => 'utf8',
|
||||
// 数据库表前缀
|
||||
'prefix' => '',
|
||||
// 断线重连
|
||||
'break_reconnect' => true,
|
||||
// 关闭SQL监听日志
|
||||
'trigger_sql' => false,
|
||||
// 自定义分页类
|
||||
'bootstrap' => ''
|
||||
],
|
||||
],
|
||||
];
|
25
config/translation.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Multilingual configuration
|
||||
*/
|
||||
return [
|
||||
// Default language
|
||||
'locale' => 'zh_CN',
|
||||
// Fallback language
|
||||
'fallback_locale' => ['zh_CN', 'en'],
|
||||
// Folder where language files are stored
|
||||
'path' => base_path() . '/resource/translations',
|
||||
];
|
22
config/view.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\view\Raw;
|
||||
use support\view\Twig;
|
||||
use support\view\Blade;
|
||||
use support\view\ThinkPHP;
|
||||
|
||||
return [
|
||||
'handler' => Raw::class
|
||||
];
|
803
menu.json
Normal file
|
@ -0,0 +1,803 @@
|
|||
[
|
||||
{
|
||||
"name": "home",
|
||||
"path": "/home",
|
||||
"meta": {
|
||||
"title": "首页",
|
||||
"icon": "el-icon-eleme-filled",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"name": "dashboard",
|
||||
"path": "/dashboard",
|
||||
"meta": {
|
||||
"title": "控制台",
|
||||
"icon": "el-icon-menu",
|
||||
"affix": true
|
||||
},
|
||||
"component": "home"
|
||||
},
|
||||
{
|
||||
"name": "userCenter",
|
||||
"path": "/usercenter",
|
||||
"meta": {
|
||||
"title": "帐号信息",
|
||||
"icon": "el-icon-user",
|
||||
"tag": "NEW"
|
||||
},
|
||||
"component": "userCenter"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vab",
|
||||
"path": "/vab",
|
||||
"meta": {
|
||||
"title": "组件",
|
||||
"icon": "el-icon-takeaway-box",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/vab/mini",
|
||||
"name": "minivab",
|
||||
"meta": {
|
||||
"title": "原子组件",
|
||||
"icon": "el-icon-magic-stick",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/mini"
|
||||
},
|
||||
{
|
||||
"path": "/vab/iconfont",
|
||||
"name": "iconfont",
|
||||
"meta": {
|
||||
"title": "扩展图标",
|
||||
"icon": "el-icon-orange",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/iconfont"
|
||||
},
|
||||
{
|
||||
"path": "/vab/data",
|
||||
"name": "vabdata",
|
||||
"meta": {
|
||||
"title": "Data 数据展示",
|
||||
"icon": "el-icon-histogram",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/vab/chart",
|
||||
"name": "chart",
|
||||
"meta": {
|
||||
"title": "图表 Echarts",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/chart"
|
||||
},
|
||||
{
|
||||
"path": "/vab/statistic",
|
||||
"name": "statistic",
|
||||
"meta": {
|
||||
"title": "统计数值",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/statistic"
|
||||
},
|
||||
{
|
||||
"path": "/vab/video",
|
||||
"name": "scvideo",
|
||||
"meta": {
|
||||
"title": "视频播放器",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/video"
|
||||
},
|
||||
{
|
||||
"path": "/vab/qrcode",
|
||||
"name": "qrcode",
|
||||
"meta": {
|
||||
"title": "二维码",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/qrcode"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/vab/form",
|
||||
"name": "vabform",
|
||||
"meta": {
|
||||
"title": "Form 数据录入",
|
||||
"icon": "el-icon-edit",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/vab/tableselect",
|
||||
"name": "tableselect",
|
||||
"meta": {
|
||||
"title": "表格选择器",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/tableselect"
|
||||
},
|
||||
{
|
||||
"path": "/vab/formtable",
|
||||
"name": "formtable",
|
||||
"meta": {
|
||||
"title": "表单表格",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/formtable"
|
||||
},
|
||||
{
|
||||
"path": "/vab/selectFilter",
|
||||
"name": "selectFilter",
|
||||
"meta": {
|
||||
"title": "分类筛选器",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/selectFilter"
|
||||
},
|
||||
{
|
||||
"path": "/vab/filterbar",
|
||||
"name": "filterBar",
|
||||
"meta": {
|
||||
"title": "过滤器v2",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/filterBar"
|
||||
},
|
||||
{
|
||||
"path": "/vab/upload",
|
||||
"name": "upload",
|
||||
"meta": {
|
||||
"title": "上传",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/upload"
|
||||
},
|
||||
{
|
||||
"path": "/vab/select",
|
||||
"name": "scselect",
|
||||
"meta": {
|
||||
"title": "异步选择器",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/select"
|
||||
},
|
||||
{
|
||||
"path": "/vab/iconselect",
|
||||
"name": "iconSelect",
|
||||
"meta": {
|
||||
"title": "图标选择器",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/iconselect"
|
||||
},
|
||||
{
|
||||
"path": "/vab/cron",
|
||||
"name": "cron",
|
||||
"meta": {
|
||||
"title": "Cron规则生成器",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/cron"
|
||||
},
|
||||
{
|
||||
"path": "/vab/editor",
|
||||
"name": "editor",
|
||||
"meta": {
|
||||
"title": "富文本编辑器",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/editor"
|
||||
},
|
||||
{
|
||||
"path": "/vab/codeeditor",
|
||||
"name": "codeeditor",
|
||||
"meta": {
|
||||
"title": "代码编辑器",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/codeeditor"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/vab/feedback",
|
||||
"name": "vabfeedback",
|
||||
"meta": {
|
||||
"title": "Feedback 反馈",
|
||||
"icon": "el-icon-mouse",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/vab/drag",
|
||||
"name": "drag",
|
||||
"meta": {
|
||||
"title": "拖拽排序",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/drag"
|
||||
},
|
||||
{
|
||||
"path": "/vab/contextmenu",
|
||||
"name": "contextmenu",
|
||||
"meta": {
|
||||
"title": "右键菜单",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/contextmenu"
|
||||
},
|
||||
{
|
||||
"path": "/vab/cropper",
|
||||
"name": "cropper",
|
||||
"meta": {
|
||||
"title": "图像剪裁",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/cropper"
|
||||
},
|
||||
{
|
||||
"path": "/vab/fileselect",
|
||||
"name": "fileselect",
|
||||
"meta": {
|
||||
"title": "资源库选择器(弃用)",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/fileselect"
|
||||
},
|
||||
{
|
||||
"path": "/vab/dialog",
|
||||
"name": "dialogExtend",
|
||||
"meta": {
|
||||
"title": "弹窗扩展",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/dialog"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/vab/others",
|
||||
"name": "vabothers",
|
||||
"meta": {
|
||||
"title": "Others 其他",
|
||||
"icon": "el-icon-more-filled",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/vab/print",
|
||||
"name": "print",
|
||||
"meta": {
|
||||
"title": "打印",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/print"
|
||||
},
|
||||
{
|
||||
"path": "/vab/watermark",
|
||||
"name": "watermark",
|
||||
"meta": {
|
||||
"title": "水印",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/watermark"
|
||||
},
|
||||
{
|
||||
"path": "/vab/importexport",
|
||||
"name": "importexport",
|
||||
"meta": {
|
||||
"title": "文件导出导入",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/importexport"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/vab/list",
|
||||
"name": "list",
|
||||
"meta": {
|
||||
"title": "Table 数据列表",
|
||||
"icon": "el-icon-fold",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/vab/table/base",
|
||||
"name": "tableBase",
|
||||
"meta": {
|
||||
"title": "基础数据列表",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/table/base"
|
||||
},
|
||||
{
|
||||
"path": "/vab/table/thead",
|
||||
"name": "tableThead",
|
||||
"meta": {
|
||||
"title": "多级表头",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/table/thead"
|
||||
},
|
||||
{
|
||||
"path": "/vab/table/column",
|
||||
"name": "tableCustomColumn",
|
||||
"meta": {
|
||||
"title": "动态列",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/table/column"
|
||||
},
|
||||
{
|
||||
"path": "/vab/table/remote",
|
||||
"name": "tableRemote",
|
||||
"meta": {
|
||||
"title": "远程排序过滤",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/table/remote"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/vab/workflow",
|
||||
"name": "workflow",
|
||||
"meta": {
|
||||
"title": "工作流设计器",
|
||||
"icon": "el-icon-share",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/workflow"
|
||||
},
|
||||
{
|
||||
"path": "/vab/formrender",
|
||||
"name": "formRender",
|
||||
"meta": {
|
||||
"title": "动态表单(Beta)",
|
||||
"icon": "el-icon-message-box",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "vab/form"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "template",
|
||||
"path": "/template",
|
||||
"meta": {
|
||||
"title": "模板",
|
||||
"icon": "el-icon-files",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/template/layout",
|
||||
"name": "layoutTemplate",
|
||||
"meta": {
|
||||
"title": "布局",
|
||||
"icon": "el-icon-grid",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/template/layout/blank",
|
||||
"name": "blank",
|
||||
"meta": {
|
||||
"title": "空白模板",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/layout/blank"
|
||||
},
|
||||
{
|
||||
"path": "/template/layout/layoutTCB",
|
||||
"name": "layoutTCB",
|
||||
"meta": {
|
||||
"title": "上中下布局",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/layout/layoutTCB"
|
||||
},
|
||||
{
|
||||
"path": "/template/layout/layoutLCR",
|
||||
"name": "layoutLCR",
|
||||
"meta": {
|
||||
"title": "左中右布局",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/layout/layoutLCR"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/template/list",
|
||||
"name": "list",
|
||||
"meta": {
|
||||
"title": "列表",
|
||||
"icon": "el-icon-document",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/template/list/crud",
|
||||
"name": "listCrud",
|
||||
"meta": {
|
||||
"title": "CRUD",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/list/crud",
|
||||
"children": [
|
||||
{
|
||||
"path": "/template/list/crud/detail/:id?",
|
||||
"name": "listCrud-detail",
|
||||
"meta": {
|
||||
"title": "新增/编辑",
|
||||
"hidden": true,
|
||||
"active": "/template/list/crud",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/list/crud/detail"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/template/list/tree",
|
||||
"name": "listTree",
|
||||
"meta": {
|
||||
"title": "左树右表",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/list/tree"
|
||||
},
|
||||
{
|
||||
"path": "/template/list/tab",
|
||||
"name": "listTab",
|
||||
"meta": {
|
||||
"title": "分类表格",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/list/tab"
|
||||
},
|
||||
{
|
||||
"path": "/template/list/son",
|
||||
"name": "listSon",
|
||||
"meta": {
|
||||
"title": "子母表",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/list/son"
|
||||
},
|
||||
{
|
||||
"path": "/template/list/widthlist",
|
||||
"name": "widthlist",
|
||||
"meta": {
|
||||
"title": "定宽列表",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/list/width"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/template/other",
|
||||
"name": "other",
|
||||
"meta": {
|
||||
"title": "其他",
|
||||
"icon": "el-icon-folder",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/template/other/stepform",
|
||||
"name": "stepform",
|
||||
"meta": {
|
||||
"title": "分步表单",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "template/other/stepform"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "other",
|
||||
"path": "/other",
|
||||
"meta": {
|
||||
"title": "其他",
|
||||
"icon": "el-icon-more-filled",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/other/directive",
|
||||
"name": "directive",
|
||||
"meta": {
|
||||
"title": "指令",
|
||||
"icon": "el-icon-price-tag",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "other/directive"
|
||||
},
|
||||
{
|
||||
"path": "/other/viewTags",
|
||||
"name": "viewTags",
|
||||
"meta": {
|
||||
"title": "标签操作",
|
||||
"icon": "el-icon-files",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "other/viewTags",
|
||||
"children": [
|
||||
{
|
||||
"path": "/other/fullpage",
|
||||
"name": "fullpage",
|
||||
"meta": {
|
||||
"title": "整页路由",
|
||||
"icon": "el-icon-monitor",
|
||||
"fullpage": true,
|
||||
"hidden": true,
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "other/fullpage"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/other/verificate",
|
||||
"name": "verificate",
|
||||
"meta": {
|
||||
"title": "表单验证",
|
||||
"icon": "el-icon-open",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "other/verificate"
|
||||
},
|
||||
{
|
||||
"path": "/other/loadJS",
|
||||
"name": "loadJS",
|
||||
"meta": {
|
||||
"title": "异步加载JS",
|
||||
"icon": "el-icon-location-information",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "other/loadJS"
|
||||
},
|
||||
{
|
||||
"path": "/link",
|
||||
"name": "link",
|
||||
"meta": {
|
||||
"title": "外部链接",
|
||||
"icon": "el-icon-link",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "https://baidu.com",
|
||||
"name": "百度",
|
||||
"meta": {
|
||||
"title": "百度",
|
||||
"type": "link"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "https://www.google.cn",
|
||||
"name": "谷歌",
|
||||
"meta": {
|
||||
"title": "谷歌",
|
||||
"type": "link"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/iframe",
|
||||
"name": "Iframe",
|
||||
"meta": {
|
||||
"title": "Iframe",
|
||||
"icon": "el-icon-position",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "https://v3.cn.vuejs.org",
|
||||
"name": "vue3",
|
||||
"meta": {
|
||||
"title": "VUE 3",
|
||||
"type": "iframe"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "https://element-plus.gitee.io",
|
||||
"name": "elementplus",
|
||||
"meta": {
|
||||
"title": "Element Plus",
|
||||
"type": "iframe"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "https://lolicode.gitee.io/scui-doc",
|
||||
"name": "scuidoc",
|
||||
"meta": {
|
||||
"title": "SCUI文档",
|
||||
"type": "iframe"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "test",
|
||||
"path": "/test",
|
||||
"meta": {
|
||||
"title": "实验室",
|
||||
"icon": "el-icon-mouse",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/test/autocode",
|
||||
"name": "autocode",
|
||||
"meta": {
|
||||
"title": "代码生成器",
|
||||
"icon": "sc-icon-code",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "test/autocode/index",
|
||||
"children": [
|
||||
{
|
||||
"path": "/test/autocode/table",
|
||||
"name": "autocode-table",
|
||||
"meta": {
|
||||
"title": "CRUD代码生成",
|
||||
"hidden": true,
|
||||
"active": "/test/autocode",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "test/autocode/table"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/test/codebug",
|
||||
"name": "codebug",
|
||||
"meta": {
|
||||
"title": "异常处理",
|
||||
"icon": "sc-icon-bug-line",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "test/codebug"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "setting",
|
||||
"path": "/setting",
|
||||
"meta": {
|
||||
"title": "配置",
|
||||
"icon": "el-icon-setting",
|
||||
"type": "menu"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"path": "/setting/system",
|
||||
"name": "system",
|
||||
"meta": {
|
||||
"title": "系统设置",
|
||||
"icon": "el-icon-tools",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/system"
|
||||
},
|
||||
{
|
||||
"path": "/setting/user",
|
||||
"name": "user",
|
||||
"meta": {
|
||||
"title": "用户管理",
|
||||
"icon": "el-icon-user-filled",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/user"
|
||||
},
|
||||
{
|
||||
"path": "/setting/role",
|
||||
"name": "role",
|
||||
"meta": {
|
||||
"title": "角色管理",
|
||||
"icon": "el-icon-notebook",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/role"
|
||||
},
|
||||
{
|
||||
"path": "/setting/dept",
|
||||
"name": "dept",
|
||||
"meta": {
|
||||
"title": "部门管理",
|
||||
"icon": "sc-icon-organization",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/dept"
|
||||
},
|
||||
{
|
||||
"path": "/setting/dic",
|
||||
"name": "dic",
|
||||
"meta": {
|
||||
"title": "字典管理",
|
||||
"icon": "el-icon-document",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/dic"
|
||||
},
|
||||
{
|
||||
"path": "/setting/table",
|
||||
"name": "tableSetting",
|
||||
"meta": {
|
||||
"title": "表格列管理",
|
||||
"icon": "el-icon-scale-to-original",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/table"
|
||||
},
|
||||
{
|
||||
"path": "/setting/menu",
|
||||
"name": "settingMenu",
|
||||
"meta": {
|
||||
"title": "菜单管理",
|
||||
"icon": "el-icon-fold",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/menu"
|
||||
},
|
||||
{
|
||||
"path": "/setting/task",
|
||||
"name": "task",
|
||||
"meta": {
|
||||
"title": "计划任务",
|
||||
"icon": "el-icon-alarm-clock",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/task"
|
||||
},
|
||||
{
|
||||
"path": "/setting/client",
|
||||
"name": "client",
|
||||
"meta": {
|
||||
"title": "应用管理",
|
||||
"icon": "el-icon-help-filled",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/client"
|
||||
},
|
||||
{
|
||||
"path": "/setting/log",
|
||||
"name": "log",
|
||||
"meta": {
|
||||
"title": "系统日志",
|
||||
"icon": "el-icon-warning",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "setting/log"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/other/about",
|
||||
"name": "about",
|
||||
"meta": {
|
||||
"title": "关于",
|
||||
"icon": "el-icon-info-filled",
|
||||
"type": "menu"
|
||||
},
|
||||
"component": "other/about"
|
||||
}
|
||||
]
|
243
process/Monitor.php
Normal file
|
@ -0,0 +1,243 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace process;
|
||||
|
||||
use FilesystemIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use SplFileInfo;
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
|
||||
/**
|
||||
* Class FileMonitor
|
||||
* @package process
|
||||
*/
|
||||
class Monitor
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $paths = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $extensions = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public static $lockFile = __DIR__ . '/../runtime/monitor.lock';
|
||||
|
||||
/**
|
||||
* Pause monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function pause()
|
||||
{
|
||||
file_put_contents(static::$lockFile, time());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function resume(): void
|
||||
{
|
||||
clearstatcache();
|
||||
if (is_file(static::$lockFile)) {
|
||||
unlink(static::$lockFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether monitor is paused
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPaused(): bool
|
||||
{
|
||||
clearstatcache();
|
||||
return file_exists(static::$lockFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* FileMonitor constructor.
|
||||
* @param $monitorDir
|
||||
* @param $monitorExtensions
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct($monitorDir, $monitorExtensions, array $options = [])
|
||||
{
|
||||
static::resume();
|
||||
$this->paths = (array)$monitorDir;
|
||||
$this->extensions = $monitorExtensions;
|
||||
if (!Worker::getAllWorkers()) {
|
||||
return;
|
||||
}
|
||||
$disableFunctions = explode(',', ini_get('disable_functions'));
|
||||
if (in_array('exec', $disableFunctions, true)) {
|
||||
echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n";
|
||||
} else {
|
||||
if ($options['enable_file_monitor'] ?? true) {
|
||||
Timer::add(1, function () {
|
||||
$this->checkAllFilesChange();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$memoryLimit = $this->getMemoryLimit($options['memory_limit'] ?? null);
|
||||
if ($memoryLimit && ($options['enable_memory_monitor'] ?? true)) {
|
||||
Timer::add(60, [$this, 'checkMemory'], [$memoryLimit]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $monitorDir
|
||||
* @return bool
|
||||
*/
|
||||
public function checkFilesChange($monitorDir): bool
|
||||
{
|
||||
static $lastMtime, $tooManyFilesCheck;
|
||||
if (!$lastMtime) {
|
||||
$lastMtime = time();
|
||||
}
|
||||
clearstatcache();
|
||||
if (!is_dir($monitorDir)) {
|
||||
if (!is_file($monitorDir)) {
|
||||
return false;
|
||||
}
|
||||
$iterator = [new SplFileInfo($monitorDir)];
|
||||
} else {
|
||||
// recursive traversal directory
|
||||
$dirIterator = new RecursiveDirectoryIterator($monitorDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new RecursiveIteratorIterator($dirIterator);
|
||||
}
|
||||
$count = 0;
|
||||
foreach ($iterator as $file) {
|
||||
$count ++;
|
||||
/** var SplFileInfo $file */
|
||||
if (is_dir($file->getRealPath())) {
|
||||
continue;
|
||||
}
|
||||
// check mtime
|
||||
if (in_array($file->getExtension(), $this->extensions, true) && $lastMtime < $file->getMTime()) {
|
||||
$var = 0;
|
||||
exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var);
|
||||
$lastMtime = $file->getMTime();
|
||||
if ($var) {
|
||||
continue;
|
||||
}
|
||||
echo $file . " update and reload\n";
|
||||
// send SIGUSR1 signal to master process for reload
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
posix_kill(posix_getppid(), SIGUSR1);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$tooManyFilesCheck && $count > 1000) {
|
||||
echo "Monitor: There are too many files ($count files) in $monitorDir which makes file monitoring very slow\n";
|
||||
$tooManyFilesCheck = 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAllFilesChange(): bool
|
||||
{
|
||||
if (static::isPaused()) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->paths as $path) {
|
||||
if ($this->checkFilesChange($path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $memoryLimit
|
||||
* @return void
|
||||
*/
|
||||
public function checkMemory($memoryLimit)
|
||||
{
|
||||
if (static::isPaused() || $memoryLimit <= 0) {
|
||||
return;
|
||||
}
|
||||
$ppid = posix_getppid();
|
||||
$childrenFile = "/proc/$ppid/task/$ppid/children";
|
||||
if (!is_file($childrenFile) || !($children = file_get_contents($childrenFile))) {
|
||||
return;
|
||||
}
|
||||
foreach (explode(' ', $children) as $pid) {
|
||||
$pid = (int)$pid;
|
||||
$statusFile = "/proc/$pid/status";
|
||||
if (!is_file($statusFile) || !($status = file_get_contents($statusFile))) {
|
||||
continue;
|
||||
}
|
||||
$mem = 0;
|
||||
if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) {
|
||||
$mem = $match[1];
|
||||
}
|
||||
$mem = (int)($mem / 1024);
|
||||
if ($mem >= $memoryLimit) {
|
||||
posix_kill($pid, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory limit
|
||||
* @return float
|
||||
*/
|
||||
protected function getMemoryLimit($memoryLimit)
|
||||
{
|
||||
if ($memoryLimit === 0) {
|
||||
return 0;
|
||||
}
|
||||
$usePhpIni = false;
|
||||
if (!$memoryLimit) {
|
||||
$memoryLimit = ini_get('memory_limit');
|
||||
$usePhpIni = true;
|
||||
}
|
||||
|
||||
if ($memoryLimit == -1) {
|
||||
return 0;
|
||||
}
|
||||
$unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]);
|
||||
if ($unit === 'g') {
|
||||
$memoryLimit = 1024 * (int)$memoryLimit;
|
||||
} else if ($unit === 'm') {
|
||||
$memoryLimit = (int)$memoryLimit;
|
||||
} else if ($unit === 'k') {
|
||||
$memoryLimit = ((int)$memoryLimit / 1024);
|
||||
} else {
|
||||
$memoryLimit = ((int)$memoryLimit / (1024 * 1024));
|
||||
}
|
||||
if ($memoryLimit < 30) {
|
||||
$memoryLimit = 30;
|
||||
}
|
||||
if ($usePhpIni) {
|
||||
$memoryLimit = (int)(0.8 * $memoryLimit);
|
||||
}
|
||||
return $memoryLimit;
|
||||
}
|
||||
}
|
12
public/404.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>404 Not Found - webman</title>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<h1>404 Not Found</h1>
|
||||
</center>
|
||||
<hr>
|
||||
<center>webman</center>
|
||||
</body>
|
||||
</html>
|
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
public/upload/1db32242bd37b55e47044ee247efbc6b.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
public/upload/5a9c5229b86b7356a61e028ea84de595.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
public/upload/9ea0d97468af1cb2b93d1533554ccd75.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
public/upload/cbee89969a0dd40a1a5215b69c8966a4.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
public/upload/e1ad5490fd1834263593fb148bbad54f.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
public/upload/f89bb898e2777183308b98a25fd25413.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
4
start.php
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
support\App::run();
|
24
support/Request.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support;
|
||||
|
||||
/**
|
||||
* Class Request
|
||||
* @package support
|
||||
*/
|
||||
class Request extends \Webman\Http\Request
|
||||
{
|
||||
|
||||
}
|
24
support/Response.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support;
|
||||
|
||||
/**
|
||||
* Class Response
|
||||
* @package support
|
||||
*/
|
||||
class Response extends \Webman\Http\Response
|
||||
{
|
||||
|
||||
}
|
133
support/bootstrap.php
Normal file
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use support\Log;
|
||||
use Webman\Bootstrap;
|
||||
use Webman\Config;
|
||||
use Webman\Middleware;
|
||||
use Webman\Route;
|
||||
use Webman\Util;
|
||||
|
||||
$worker = $worker ?? null;
|
||||
|
||||
set_error_handler(function ($level, $message, $file = '', $line = 0) {
|
||||
if (error_reporting() & $level) {
|
||||
throw new ErrorException($message, 0, $level, $file, $line);
|
||||
}
|
||||
});
|
||||
|
||||
if ($worker) {
|
||||
register_shutdown_function(function ($startTime) {
|
||||
if (time() - $startTime <= 0.1) {
|
||||
sleep(1);
|
||||
}
|
||||
}, time());
|
||||
}
|
||||
|
||||
if (class_exists('Dotenv\Dotenv') && file_exists(base_path(false) . '/.env')) {
|
||||
if (method_exists('Dotenv\Dotenv', 'createUnsafeMutable')) {
|
||||
Dotenv::createUnsafeMutable(base_path(false))->load();
|
||||
} else {
|
||||
Dotenv::createMutable(base_path(false))->load();
|
||||
}
|
||||
}
|
||||
|
||||
Config::clear();
|
||||
support\App::loadAllConfig(['route']);
|
||||
if ($timezone = config('app.default_timezone')) {
|
||||
date_default_timezone_set($timezone);
|
||||
}
|
||||
|
||||
foreach (config('autoload.files', []) as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['autoload']['files'] ?? [] as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
}
|
||||
foreach ($projects['autoload']['files'] ?? [] as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
}
|
||||
|
||||
Middleware::load(config('middleware', []));
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project) || $name === 'static') {
|
||||
continue;
|
||||
}
|
||||
Middleware::load($project['middleware'] ?? []);
|
||||
}
|
||||
Middleware::load($projects['middleware'] ?? [], $firm);
|
||||
if ($staticMiddlewares = config("plugin.$firm.static.middleware")) {
|
||||
Middleware::load(['__static__' => $staticMiddlewares], $firm);
|
||||
}
|
||||
}
|
||||
Middleware::load(['__static__' => config('static.middleware', [])]);
|
||||
|
||||
foreach (config('bootstrap', []) as $className) {
|
||||
if (!class_exists($className)) {
|
||||
$log = "Warning: Class $className setting in config/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $className */
|
||||
$className::start($worker);
|
||||
}
|
||||
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['bootstrap'] ?? [] as $className) {
|
||||
if (!class_exists($className)) {
|
||||
$log = "Warning: Class $className setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $className */
|
||||
$className::start($worker);
|
||||
}
|
||||
}
|
||||
foreach ($projects['bootstrap'] ?? [] as $className) {
|
||||
/** @var string $className */
|
||||
if (!class_exists($className)) {
|
||||
$log = "Warning: Class $className setting in plugin/$firm/config/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $className */
|
||||
$className::start($worker);
|
||||
}
|
||||
}
|
||||
|
||||
$directory = base_path() . '/plugin';
|
||||
$paths = [config_path()];
|
||||
foreach (Util::scanDir($directory) as $path) {
|
||||
if (is_dir($path = "$path/config")) {
|
||||
$paths[] = $path;
|
||||
}
|
||||
}
|
||||
Route::load($paths);
|
||||
|
528
support/helpers.php
Normal file
|
@ -0,0 +1,528 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\Container;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use support\Translation;
|
||||
use support\view\Blade;
|
||||
use support\view\Raw;
|
||||
use support\view\ThinkPHP;
|
||||
use support\view\Twig;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Webman\App;
|
||||
use Webman\Config;
|
||||
use Webman\Route;
|
||||
use Workerman\Protocols\Http\Session;
|
||||
use Workerman\Worker;
|
||||
|
||||
// Project base path
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
|
||||
/**
|
||||
* return the program execute directory
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function run_path(string $path = ''): string
|
||||
{
|
||||
static $runPath = '';
|
||||
if (!$runPath) {
|
||||
$runPath = is_phar() ? dirname(Phar::running(false)) : BASE_PATH;
|
||||
}
|
||||
return path_combine($runPath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* if the param $path equal false,will return this program current execute directory
|
||||
* @param string|false $path
|
||||
* @return string
|
||||
*/
|
||||
function base_path($path = ''): string
|
||||
{
|
||||
if (false === $path) {
|
||||
return run_path();
|
||||
}
|
||||
return path_combine(BASE_PATH, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* App path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function app_path(string $path = ''): string
|
||||
{
|
||||
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function public_path(string $path = ''): string
|
||||
{
|
||||
static $publicPath = '';
|
||||
if (!$publicPath) {
|
||||
$publicPath = \config('app.public_path') ?: run_path('public');
|
||||
}
|
||||
return path_combine($publicPath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Config path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function config_path(string $path = ''): string
|
||||
{
|
||||
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function runtime_path(string $path = ''): string
|
||||
{
|
||||
static $runtimePath = '';
|
||||
if (!$runtimePath) {
|
||||
$runtimePath = \config('app.runtime_path') ?: run_path('runtime');
|
||||
}
|
||||
return path_combine($runtimePath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate paths based on given information
|
||||
* @param string $front
|
||||
* @param string $back
|
||||
* @return string
|
||||
*/
|
||||
function path_combine(string $front, string $back): string
|
||||
{
|
||||
return $front . ($back ? (DIRECTORY_SEPARATOR . ltrim($back, DIRECTORY_SEPARATOR)) : $back);
|
||||
}
|
||||
|
||||
/**
|
||||
* Response
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param string $body
|
||||
* @return Response
|
||||
*/
|
||||
function response(string $body = '', int $status = 200, array $headers = []): Response
|
||||
{
|
||||
return new Response($status, $headers, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Json response
|
||||
* @param $data
|
||||
* @param int $options
|
||||
* @return Response
|
||||
*/
|
||||
function json($data, int $options = JSON_UNESCAPED_UNICODE): Response
|
||||
{
|
||||
return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml response
|
||||
* @param $xml
|
||||
* @return Response
|
||||
*/
|
||||
function xml($xml): Response
|
||||
{
|
||||
if ($xml instanceof SimpleXMLElement) {
|
||||
$xml = $xml->asXML();
|
||||
}
|
||||
return new Response(200, ['Content-Type' => 'text/xml'], $xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Jsonp response
|
||||
* @param $data
|
||||
* @param string $callbackName
|
||||
* @return Response
|
||||
*/
|
||||
function jsonp($data, string $callbackName = 'callback'): Response
|
||||
{
|
||||
if (!is_scalar($data) && null !== $data) {
|
||||
$data = json_encode($data);
|
||||
}
|
||||
return new Response(200, [], "$callbackName($data)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect response
|
||||
* @param string $location
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return Response
|
||||
*/
|
||||
function redirect(string $location, int $status = 302, array $headers = []): Response
|
||||
{
|
||||
$response = new Response($status, ['Location' => $location]);
|
||||
if (!empty($headers)) {
|
||||
$response->withHeaders($headers);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* View response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @param string|null $plugin
|
||||
* @return Response
|
||||
*/
|
||||
function view(string $template, array $vars = [], string $app = null, string $plugin = null): Response
|
||||
{
|
||||
$request = \request();
|
||||
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
|
||||
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
|
||||
return new Response(200, [], $handler::render($template, $vars, $app, $plugin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
* @throws Throwable
|
||||
*/
|
||||
function raw_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Raw::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Blade view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function blade_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Blade::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Think view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function think_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], ThinkPHP::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Twig view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
* @throws LoaderError
|
||||
* @throws RuntimeError
|
||||
* @throws SyntaxError
|
||||
*/
|
||||
function twig_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Twig::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request
|
||||
* @return \Webman\Http\Request|Request|null
|
||||
*/
|
||||
function request()
|
||||
{
|
||||
return App::request();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config
|
||||
* @param string|null $key
|
||||
* @param $default
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
function config(string $key = null, $default = null)
|
||||
{
|
||||
return Config::get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create url
|
||||
* @param string $name
|
||||
* @param ...$parameters
|
||||
* @return string
|
||||
*/
|
||||
function route(string $name, ...$parameters): string
|
||||
{
|
||||
$route = Route::getByName($name);
|
||||
if (!$route) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$parameters) {
|
||||
return $route->url();
|
||||
}
|
||||
|
||||
if (is_array(current($parameters))) {
|
||||
$parameters = current($parameters);
|
||||
}
|
||||
|
||||
return $route->url($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Session
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return mixed|bool|Session
|
||||
*/
|
||||
function session($key = null, $default = null)
|
||||
{
|
||||
$session = \request()->session();
|
||||
if (null === $key) {
|
||||
return $session;
|
||||
}
|
||||
if (is_array($key)) {
|
||||
$session->put($key);
|
||||
return null;
|
||||
}
|
||||
if (strpos($key, '.')) {
|
||||
$keyArray = explode('.', $key);
|
||||
$value = $session->all();
|
||||
foreach ($keyArray as $index) {
|
||||
if (!isset($value[$index])) {
|
||||
return $default;
|
||||
}
|
||||
$value = $value[$index];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
return $session->get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translation
|
||||
* @param string $id
|
||||
* @param array $parameters
|
||||
* @param string|null $domain
|
||||
* @param string|null $locale
|
||||
* @return string
|
||||
*/
|
||||
function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string
|
||||
{
|
||||
$res = Translation::trans($id, $parameters, $domain, $locale);
|
||||
return $res === '' ? $id : $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locale
|
||||
* @param string|null $locale
|
||||
* @return string
|
||||
*/
|
||||
function locale(string $locale = null): string
|
||||
{
|
||||
if (!$locale) {
|
||||
return Translation::getLocale();
|
||||
}
|
||||
Translation::setLocale($locale);
|
||||
return $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* 404 not found
|
||||
* @return Response
|
||||
*/
|
||||
function not_found(): Response
|
||||
{
|
||||
return new Response(404, [], file_get_contents(public_path() . '/404.html'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy dir
|
||||
* @param string $source
|
||||
* @param string $dest
|
||||
* @param bool $overwrite
|
||||
* @return void
|
||||
*/
|
||||
function copy_dir(string $source, string $dest, bool $overwrite = false)
|
||||
{
|
||||
if (is_dir($source)) {
|
||||
if (!is_dir($dest)) {
|
||||
mkdir($dest);
|
||||
}
|
||||
$files = scandir($source);
|
||||
foreach ($files as $file) {
|
||||
if ($file !== "." && $file !== "..") {
|
||||
copy_dir("$source/$file", "$dest/$file", $overwrite);
|
||||
}
|
||||
}
|
||||
} else if (file_exists($source) && ($overwrite || !file_exists($dest))) {
|
||||
copy($source, $dest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove dir
|
||||
* @param string $dir
|
||||
* @return bool
|
||||
*/
|
||||
function remove_dir(string $dir): bool
|
||||
{
|
||||
if (is_link($dir) || is_file($dir)) {
|
||||
return unlink($dir);
|
||||
}
|
||||
$files = array_diff(scandir($dir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
(is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file");
|
||||
}
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind worker
|
||||
* @param $worker
|
||||
* @param $class
|
||||
*/
|
||||
function worker_bind($worker, $class)
|
||||
{
|
||||
$callbackMap = [
|
||||
'onConnect',
|
||||
'onMessage',
|
||||
'onClose',
|
||||
'onError',
|
||||
'onBufferFull',
|
||||
'onBufferDrain',
|
||||
'onWorkerStop',
|
||||
'onWebSocketConnect',
|
||||
'onWorkerReload'
|
||||
];
|
||||
foreach ($callbackMap as $name) {
|
||||
if (method_exists($class, $name)) {
|
||||
$worker->$name = [$class, $name];
|
||||
}
|
||||
}
|
||||
if (method_exists($class, 'onWorkerStart')) {
|
||||
call_user_func([$class, 'onWorkerStart'], $worker);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start worker
|
||||
* @param $processName
|
||||
* @param $config
|
||||
* @return void
|
||||
*/
|
||||
function worker_start($processName, $config)
|
||||
{
|
||||
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
|
||||
$propertyMap = [
|
||||
'count',
|
||||
'user',
|
||||
'group',
|
||||
'reloadable',
|
||||
'reusePort',
|
||||
'transport',
|
||||
'protocol',
|
||||
];
|
||||
$worker->name = $processName;
|
||||
foreach ($propertyMap as $property) {
|
||||
if (isset($config[$property])) {
|
||||
$worker->$property = $config[$property];
|
||||
}
|
||||
}
|
||||
|
||||
$worker->onWorkerStart = function ($worker) use ($config) {
|
||||
require_once base_path('/support/bootstrap.php');
|
||||
if (isset($config['handler'])) {
|
||||
if (!class_exists($config['handler'])) {
|
||||
echo "process error: class {$config['handler']} not exists\r\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = Container::make($config['handler'], $config['constructor'] ?? []);
|
||||
worker_bind($worker, $instance);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get realpath
|
||||
* @param string $filePath
|
||||
* @return string
|
||||
*/
|
||||
function get_realpath(string $filePath): string
|
||||
{
|
||||
if (strpos($filePath, 'phar://') === 0) {
|
||||
return $filePath;
|
||||
} else {
|
||||
return realpath($filePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is phar
|
||||
* @return bool
|
||||
*/
|
||||
function is_phar(): bool
|
||||
{
|
||||
return class_exists(Phar::class, false) && Phar::running();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cpu count
|
||||
* @return int
|
||||
*/
|
||||
function cpu_count(): int
|
||||
{
|
||||
// Windows does not support the number of processes setting.
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
return 1;
|
||||
}
|
||||
$count = 4;
|
||||
if (is_callable('shell_exec')) {
|
||||
if (strtolower(PHP_OS) === 'darwin') {
|
||||
$count = (int)shell_exec('sysctl -n machdep.cpu.core_count');
|
||||
} else {
|
||||
$count = (int)shell_exec('nproc');
|
||||
}
|
||||
}
|
||||
return $count > 0 ? $count : 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request parameters, if no parameter name is passed, an array of all values is returned, default values is supported
|
||||
* @param string|null $param param's name
|
||||
* @param mixed|null $default default value
|
||||
* @return mixed|null
|
||||
*/
|
||||
function input(string $param = null, $default = null)
|
||||
{
|
||||
return is_null($param) ? request()->all() : request()->input($param, $default);
|
||||
}
|
6
test.php
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
$arr = unpack("C3", "PHP");
|
||||
var_export($arr);
|
||||
var_dump(implode(',', $arr));
|
||||
echo pack("C3",80,72,80);
|
57
webman
Normal file
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use Webman\Config;
|
||||
use Webman\Console\Command;
|
||||
use Webman\Console\Util;
|
||||
use support\Container;
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
if (!in_array($argv[1] ?? '', ['start', 'restart', 'stop', 'status', 'reload', 'connections'])) {
|
||||
require_once __DIR__ . '/support/bootstrap.php';
|
||||
} else {
|
||||
if (class_exists('Support\App')) {
|
||||
Support\App::loadAllConfig(['route']);
|
||||
} else {
|
||||
Config::reload(config_path(), ['route', 'container']);
|
||||
}
|
||||
}
|
||||
|
||||
$cli = new Command();
|
||||
$cli->setName('webman cli');
|
||||
$cli->installInternalCommands();
|
||||
if (is_dir($command_path = Util::guessPath(app_path(), '/command', true))) {
|
||||
$cli->installCommands($command_path);
|
||||
}
|
||||
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
if (isset($projects['app'])) {
|
||||
if ($command_str = Util::guessPath(base_path() . "/plugin/$firm", 'command')) {
|
||||
$command_path = base_path() . "/plugin/$firm/$command_str";
|
||||
$cli->installCommands($command_path, "plugin\\$firm\\$command_str");
|
||||
}
|
||||
}
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['command'] ?? [] as $class_name) {
|
||||
$reflection = new \ReflectionClass($class_name);
|
||||
if ($reflection->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
$properties = $reflection->getStaticProperties();
|
||||
$name = $properties['defaultName'];
|
||||
if (!$name) {
|
||||
throw new RuntimeException("Command {$class_name} has no defaultName");
|
||||
}
|
||||
$description = $properties['defaultDescription'] ?? '';
|
||||
$command = Container::get($class_name);
|
||||
$command->setName($name)->setDescription($description);
|
||||
$cli->add($command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$cli->run();
|
3
windows.bat
Normal file
|
@ -0,0 +1,3 @@
|
|||
CHCP 65001
|
||||
php windows.php
|
||||
pause
|
118
windows.php
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
/**
|
||||
* Start file for windows
|
||||
*/
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use process\Monitor;
|
||||
use support\App;
|
||||
use Workerman\Worker;
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
|
||||
if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
|
||||
Dotenv::createUnsafeImmutable(base_path())->load();
|
||||
} else {
|
||||
Dotenv::createMutable(base_path())->load();
|
||||
}
|
||||
}
|
||||
|
||||
App::loadAllConfig(['route']);
|
||||
|
||||
$errorReporting = config('app.error_reporting');
|
||||
if (isset($errorReporting)) {
|
||||
error_reporting($errorReporting);
|
||||
}
|
||||
|
||||
$runtimeProcessPath = runtime_path() . DIRECTORY_SEPARATOR . '/windows';
|
||||
if (!is_dir($runtimeProcessPath)) {
|
||||
mkdir($runtimeProcessPath);
|
||||
}
|
||||
$processFiles = [
|
||||
__DIR__ . DIRECTORY_SEPARATOR . 'start.php'
|
||||
];
|
||||
foreach (config('process', []) as $processName => $config) {
|
||||
$processFiles[] = write_process_file($runtimeProcessPath, $processName, '');
|
||||
}
|
||||
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['process'] ?? [] as $processName => $config) {
|
||||
$processFiles[] = write_process_file($runtimeProcessPath, $processName, "$firm.$name");
|
||||
}
|
||||
}
|
||||
foreach ($projects['process'] ?? [] as $processName => $config) {
|
||||
$processFiles[] = write_process_file($runtimeProcessPath, $processName, $firm);
|
||||
}
|
||||
}
|
||||
|
||||
function write_process_file($runtimeProcessPath, $processName, $firm): string
|
||||
{
|
||||
$processParam = $firm ? "plugin.$firm.$processName" : $processName;
|
||||
$configParam = $firm ? "config('plugin.$firm.process')['$processName']" : "config('process')['$processName']";
|
||||
$fileContent = <<<EOF
|
||||
<?php
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use Workerman\Worker;
|
||||
use Workerman\Connection\TcpConnection;
|
||||
use Webman\Config;
|
||||
use support\App;
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (is_callable('opcache_reset')) {
|
||||
opcache_reset();
|
||||
}
|
||||
|
||||
App::loadAllConfig(['route']);
|
||||
|
||||
worker_start('$processParam', $configParam);
|
||||
|
||||
if (DIRECTORY_SEPARATOR != "/") {
|
||||
Worker::\$logFile = config('server')['log_file'] ?? Worker::\$logFile;
|
||||
TcpConnection::\$defaultMaxPackageSize = config('server')['max_package_size'] ?? 10*1024*1024;
|
||||
}
|
||||
|
||||
Worker::runAll();
|
||||
|
||||
EOF;
|
||||
$processFile = $runtimeProcessPath . DIRECTORY_SEPARATOR . "start_$processParam.php";
|
||||
file_put_contents($processFile, $fileContent);
|
||||
return $processFile;
|
||||
}
|
||||
|
||||
if ($monitorConfig = config('process.monitor.constructor')) {
|
||||
$monitor = new Monitor(...array_values($monitorConfig));
|
||||
}
|
||||
|
||||
function popen_processes($processFiles)
|
||||
{
|
||||
$cmd = '"' . PHP_BINARY . '" ' . implode(' ', $processFiles);
|
||||
$descriptorspec = [STDIN, STDOUT, STDOUT];
|
||||
$resource = proc_open($cmd, $descriptorspec, $pipes, null, null, ['bypass_shell' => true]);
|
||||
if (!$resource) {
|
||||
exit("Can not execute $cmd\r\n");
|
||||
}
|
||||
return $resource;
|
||||
}
|
||||
|
||||
$resource = popen_processes($processFiles);
|
||||
echo "\r\n";
|
||||
while (1) {
|
||||
sleep(1);
|
||||
if (!empty($monitor) && $monitor->checkAllFilesChange()) {
|
||||
$status = proc_get_status($resource);
|
||||
$pid = $status['pid'];
|
||||
shell_exec("taskkill /F /T /PID $pid");
|
||||
proc_close($resource);
|
||||
$resource = popen_processes($processFiles);
|
||||
}
|
||||
}
|