...
 
Commits (4)
    https://gitcode.net/kanyxmo/mineadmin/-/commit/e92b6c5e615cd325a540ae07a712f5d178a52f61 fix and refactor 2023-05-24T16:00:19+08:00 X.Mo root@imoi.cn https://gitcode.net/kanyxmo/mineadmin/-/commit/38d40fcc265e2c85c5bb12a2809e0ee5cdba37d5 fix: 移除配置项添加时,后端验证value必填 2023-05-24T16:10:28+08:00 X.Mo root@imoi.cn https://gitcode.net/kanyxmo/mineadmin/-/commit/a15778717c35bf0ff65d55b3347434589784e3e1 add: reboot.php 2023-05-25T14:58:13+08:00 X.Mo root@imoi.cn https://gitcode.net/kanyxmo/mineadmin/-/commit/7089d0e6781a869a50702b7bd32dfc70ecc49dae update 2023-05-25T15:16:44+08:00 X.Mo root@imoi.cn
......@@ -14,7 +14,7 @@
<img src="https://gitee.com/xmo/MineAdmin/badge/star.svg?theme=dark" />
<img src="https://gitee.com/xmo/MineAdmin/badge/fork.svg?theme=dark" />
<img src="https://svg.hamm.cn/badge.svg?key=License&value=Apache-2.0&color=da4a00" />
<img src="https://svg.hamm.cn/badge.svg?key=MineAdmin&value=v1.1.2" />
<img src="https://svg.hamm.cn/badge.svg?key=MineAdmin&value=v1.3.0" />
</p>
PHP有很多优秀的后台管理系统,但基于Swoole的后台管理系统没找到合适我自己的。
所以就开发了一套后台管理系统。系统可以用于网站管理后台、CMS、CRM、OA、ERP等。
......@@ -28,27 +28,14 @@ PHP有很多优秀的后台管理系统,但基于Swoole的后台管理系统
- 腾讯云特惠专场:[点击进入](http://txy.mineadmin.com)
- 阿里云特惠专场:[点击进入](http://aly.mineadmin.com)
## 配置Json来使用Vue完成CRUD操作
在传统的前后端分离架构下,前端必须要配置专业的前端开发人员来完成业务,这对于PHPer习惯前后端一把梭来说比较费事。
在JQuery逐渐没落的大趋势下,使用Vue成为趋势,但从JQ到Vue转变最难的是思想。
MineAdmin强调快速开发,为了适应现代开发模式并且兼顾传统一把梭,特开发出了crud和form两个组件,
只需要像过去配置json的方式即可完成对后端的接口联调,从而快速完成CRUD,大大替开发人员节省了时间。
让刚接触VUE的同学也能上手vue,体验vue的好处。
大神则可以自由发挥是决定使用crud组件,还是使用原生UI库来完成功能。
## 兔小巢
给大家提供一个可以交流的地方:[http://ask.mineadmin.com](http://ask.mineadmin.com)
## 前端仓库地址
移步前端仓库
- [Github MineAdmin-Vue](https://github.com/kanyxmo/MineAdmin-Vue)
- [Gitee MineAdmin-Vue](https://gitee.com/xmo/MineAdmin-vue)
## 官方交流群
> 以下QQ群为 MineAdmin 爱好者建立用于交流学习,请勿相信任何收费事项
## 官方交流群
> QQ群用于交流学习,请勿水群
<img src="https://svg.hamm.cn/badge.svg?key=QQ群&value=150105478" />
......@@ -86,6 +73,7 @@ MineAdmin强调快速开发,为了适应现代开发模式并且兼顾传统
- pcntl
- Mysql >= 5.7
- Redis >= 4.0
- Git >= 2.x
## 下载项目
......@@ -98,7 +86,9 @@ composer config -g repo.packagist composer https://mirrors.tencent.com/composer/
composer install
```
## 后端安装
## 项目安装
> 从 **`1.3.0`** 版本开始在安装后端项目后,会多一个步骤,询问是否在根目录建立 `web` 目录并下载前端项目代码
打开终端,执行安装命令,按照提示,一步步完成`.env`文件的配置
```shell
......@@ -152,11 +142,8 @@ php bin/hyperf.php mine:install
## 演示图片
<img src="https://s1.ax1x.com/2022/07/31/vklKzR.jpg" />
<img src="https://s1.ax1x.com/2022/07/31/vklGdO.jpg" />
<img src="https://s1.ax1x.com/2022/07/31/vkl8eK.jpg" />
<img src="https://s1.ax1x.com/2022/07/31/vkl1L6.jpg" />
<img src="https://s1.ax1x.com/2022/07/31/vklwQI.jpg" />
<img src="https://s1.ax1x.com/2022/07/31/vkldSA.jpg" />
<img src="https://s1.ax1x.com/2022/07/31/vklNJH.jpg" />
<img src="https://s1.ax1x.com/2022/07/31/vklJoD.jpg" />
<img src="https://s1.ax1x.com/2022/07/31/vkllsx.jpg" />
......
......@@ -16,7 +16,6 @@ use App\Setting\Model\SettingDatasource;
use Hyperf\Database\Model\Builder;
use Hyperf\DbConnection\Db;
use Mine\Abstracts\AbstractMapper;
use Mine\Annotation\Transaction;
use Mine\Exception\MineException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
......@@ -93,7 +92,7 @@ class SettingDatasourceMapper extends AbstractMapper
*/
public function createTable(string $sql): bool
{
return Db::connection()->getPdo()->exec($sql) > 0;
return Db::connection('default')->getPdo()->exec($sql) > 0;
}
public function connectionDb(Object|array $params): \PDO
......
......@@ -15,7 +15,6 @@ class SettingConfigRequest extends MineFormRequest
return [
'group_id' => 'required',
'key' => 'required|max:32',
'value' => 'required|max:255',
'name' => 'required|max:255',
'input_type' => '',
'config_select_data' => '',
......@@ -51,7 +50,6 @@ class SettingConfigRequest extends MineFormRequest
return [
'group_id' => '组ID',
'key' => '配置键名',
'value' => '配置值',
'name' => '配置名称',
];
}
......
......@@ -42,6 +42,6 @@ class CreateSystemPostTable extends Migration
*/
public function down(): void
{
Schema::dropIfExists('system_job');
Schema::dropIfExists('system_post');
}
}
......@@ -6,7 +6,7 @@ namespace App\System\Listener;
use App\System\Model\SystemUploadfile;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
use League\Flysystem\FileNotFoundException;
use League\Flysystem\FilesystemException;
use Mine\Event\RealDeleteUploadFile;
/**
......@@ -24,14 +24,15 @@ class DeleteUploadFileListener implements ListenerInterface
}
/**
* @param RealDeleteUploadFile $event
* @param object $event
* @throws FilesystemException
*/
public function process(object $event): void
{
$filePath = $this->getFilePath($event->getModel());
try {
$event->getFilesystem()->delete($filePath);
} catch (FileNotFoundException $e) {
} catch (\Exception $e) {
// 文件删除失败,跳过删除数据
$event->setConfirm(false);
}
......
......@@ -147,9 +147,19 @@ class SystemUserMapper extends AbstractMapper
*/
public function handleSearch(Builder $query, array $params): Builder
{
if (isset($params['dept_id']) && is_string($params['dept_id'])) {
$query->join('system_user_dept as dept', 'system_user.id', '=', 'dept.user_id');
$query->where('dept.dept_id', '=', $params['dept_id']);
if (!empty($params['dept_id']) && is_string($params['dept_id'])) {
$query->selectRaw(Db::raw('DISTINCT system_user.*'))
->join('system_user_dept as dept', 'system_user.id', '=', 'dept.user_id')
->whereIn('dept.dept_id', SystemDept::query()
->where(function ($query) use ($params) {
$query->where('id', '=', $params['dept_id'])
->orWhere('level', 'like', $params['dept_id'] . ',%')
->orWhere('level', 'like', '%,' . $params['dept_id'])
->orWhere('level', 'like', '%,' . $params['dept_id'] . ',%');
})
->pluck('id')
->toArray()
);
}
if (isset($params['username'])) {
$query->where('username', 'like', '%'.$params['username'].'%');
......
......@@ -15,7 +15,17 @@ class ServerMonitorService
try {
if (PHP_OS == 'Linux') {
$cpu = $this->getCpuUsage();
preg_match('/(\d+)/', shell_exec('cat /proc/cpuinfo | grep "cache size"'), $cache);
preg_match('/(\d+)/', shell_exec('cat /proc/cpuinfo | grep "cache size"') ?? '', $cache);
if (count($cache) == 0) {
// aarch64 有可能是arm架构
$cache = trim(shell_exec("lscpu | grep L3 | awk '{print \$NF}'") ?? '');
if ($cache == '') {
$cache = trim(shell_exec("lscpu | grep L2 | awk '{print \$NF}'") ?? '');
}
if ($cache != '') {
$cache = [0, intval(str_replace(['K', 'B'], '', strtoupper($cache)))];
}
}
} else {
$cpuUsage = shell_exec('top -l 1 | head -n 10 | grep CPU');
preg_match('/(\d+\.\d+)%\suser/', $cpuUsage, $cpu);
......@@ -45,7 +55,24 @@ class ServerMonitorService
public function getCpuName(): string
{
if (PHP_OS == 'Linux') {
preg_match('/^\s+\d\s+(.+)/', shell_exec('cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c'), $matches);
preg_match('/^\s+\d\s+(.+)/', shell_exec('cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c') ?? '', $matches);
if (count($matches) == 0) {
// aarch64 有可能是arm架构
$name = trim(shell_exec("lscpu| grep Architecture | awk '{print $2}'") ?? '');
if ($name != '') {
$mfMhz = trim(shell_exec("lscpu| grep 'MHz' | awk '{print \$NF}' | head -n1") ?? '');
$mfGhz = trim(shell_exec("lscpu| grep 'GHz' | awk '{print \$NF}' | head -n1") ?? '');
if ($mfMhz == '' && $mfGhz == '') {
return $name;
} else if ($mfGhz != '') {
return $name .' @ ' . $mfGhz .'GHz';
} else if ($mfMhz != '') {
return $name .' @ ' . round(intval($mfMhz) / 1000, 2) .'GHz';
}
} else {
return '未知';
}
}
return $matches[1] ?? "未知";
} else {
return shell_exec('sysctl -n machdep.cpu.brand_string');
......@@ -58,7 +85,8 @@ class ServerMonitorService
public function getCpuPhysicsCores(): string
{
if (PHP_OS == 'Linux') {
return str_replace("\n", '', shell_exec('cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l'));
$num = str_replace("\n", '', shell_exec('cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l'));
return intval($num) == 0 ? '1' : $num;
} else {
return trim(shell_exec('sysctl -n hw.physicalcpu'));
}
......@@ -102,7 +130,7 @@ class ServerMonitorService
protected function calculationCpu(): array
{
$mode = '/(cpu)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)/';
$string = shell_exec('more /proc/stat | grep cpu');
$string = shell_exec('cat /proc/stat | grep cpu');
preg_match_all($mode, $string, $matches);
$total = $matches[2][0] + $matches[3][0] + $matches[4][0] + $matches[5][0] + $matches[6][0] + $matches[7][0] + $matches[8][0] + $matches[9][0];
......
......@@ -210,7 +210,7 @@ class SystemAppService extends AbstractService
if ($apiData['app_id'] != $appInfo['app_id']) {
return MineCode::API_UNBIND_APP;
}
} else if (! $this->checkAppHasBindApi($appId, (int) $appInfo['id'])) {
} else if (! $this->checkAppHasBindApi($apiData['app_id'], (int) $appInfo['id'])) {
return MineCode::API_UNBIND_APP;
}
......
......@@ -13,11 +13,9 @@ use Mine\Event\UserAdd;
use Mine\Event\UserDelete;
use Mine\Exception\MineException;
use Mine\Exception\NormalStatusException;
use Mine\Helper\MineCaptcha;
use Mine\MineRequest;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\SimpleCache\CacheInterface;
use Psr\SimpleCache\InvalidArgumentException;
/**
......@@ -73,23 +71,6 @@ class SystemUserService extends AbstractService
$this->container = $container;
}
/**
* 获取验证码
* @return string
* @throws InvalidArgumentException
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function getCaptcha(): string
{
$cache = container()->get(CacheInterface::class);
$captcha = new MineCaptcha();
$info = $captcha->getCaptchaInfo();
$key = $this->request->ip() .'-'. \Mine\Helper\Str::lower($info['code']);
$cache->set(sprintf('captcha:%s', $key), $info['code'], 60);
return $info['image'];
}
/**
* 获取用户信息
* @return array
......
<?php
/**
* MineAdmin is committed to providing solutions for quickly building web applications
* Please view the LICENSE file that was distributed with this source code,
* For the full copyright and license information.
* Thank you very much for using MineAdmin.
*
* @Author X.Mo<root@imoi.cn>
* @Link https://gitee.com/xmo/MineAdmin
*/
/**
* 强制重启服务脚本,并清理缓存代理类
*/
$pid = shell_exec(sprintf('cat %s/../runtime/hyperf.pid', __DIR__));
$rebootCmd = sprintf('rm -rf %s/../runtime/container/* && php %s/hyperf.php start > /dev/null 2>/dev/null &', __DIR__, __DIR__);
if (shell_exec(sprintf('ps -ef | grep -v grep | grep %s', $pid))) {
shell_exec("kill -9 {$pid}");
shell_exec($rebootCmd);
} else {
shell_exec($rebootCmd);
}
\ No newline at end of file
......@@ -10,19 +10,19 @@
"description": "Quickly build a background management system for web applications",
"license": "Apache-2.0",
"require": {
"xmo/mine": "dev-main",
"xmo/mine-office": "dev-main",
"xmo/mine-core": "1.3.*",
"xmo/mine-office": "1.3.*",
"xmo/jwt-auth": "0.6.*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.9",
"friendsofphp/php-cs-fixer": "^3.0",
"hyperf/devtool": "3.0.*",
"hyperf/ide-helper": "3.0.*",
"hyperf/testing": "3.0.*",
"hyperf/watcher": "3.0.*",
"mockery/mockery": "^1.0",
"phpstan/phpstan": "^0.12",
"swoole/ide-helper": "^4.5"
"phpstan/phpstan": "^1.0",
"swoole/ide-helper": "^5.0"
},
"suggest": {
"ext-openssl": "Required to use HTTPS.",
......@@ -62,20 +62,10 @@
],
"test": "co-phpunit --prepend test/bootstrap.php -c phpunit.xml --colors=always",
"cs-fix": "php-cs-fixer fix $1",
"analyse": "phpstan analyse --memory-limit 300M -l 0 -c phpstan.neon ./app ./config ./mine",
"analyse": "phpstan analyse --memory-limit 300M -l 0 -c phpstan.neon ./app ./config ./vendor/xmo",
"start": [
"Composer\\Config::disableProcessTimeout",
"php ./bin/hyperf.php start"
]
},
"repositories": {
"mine": {
"type": "path",
"url": "/opt/mine"
},
"mine-office": {
"type": "path",
"url": "/opt/office"
}
}
}
此差异已折叠。
......@@ -12,5 +12,4 @@ declare(strict_types=1);
return [
Hyperf\Database\Commands\Ast\ModelUpdateVisitor::class => Mine\MineModelVisitor::class,
Hyperf\HttpServer\CoreMiddleware::class => Mine\Middlewares\HttpCoreMiddleware::class,
// Mine\Interfaces\UserServiceInterface::class => App\System\Service\Dependencies\UserAuthService::class,
];
......@@ -16,7 +16,7 @@ use Hyperf\Di\Container;
use Hyperf\Di\Definition\DefinitionSourceFactory;
use Hyperf\Context\ApplicationContext;
$container = new Container((new DefinitionSourceFactory(true))());
$container = new Container((new DefinitionSourceFactory())());
if (! $container instanceof \Psr\Container\ContainerInterface) {
throw new RuntimeException('The dependency injection container is invalid.');
......