Compare commits
106 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fb579a5771 | ||
![]() |
4e1e040936 | ||
![]() |
38e10896d4 | ||
![]() |
ba1595f75f | ||
![]() |
566514f729 | ||
![]() |
48c41f7948 | ||
![]() |
f67a4f33d5 | ||
![]() |
ae53d4e404 | ||
![]() |
504054b68e | ||
![]() |
ceb5a396d8 | ||
![]() |
be91cfbc4f | ||
![]() |
898ffbc822 | ||
![]() |
f321a71677 | ||
![]() |
246d2caf44 | ||
![]() |
d020c99db3 | ||
![]() |
44b74d53d9 | ||
![]() |
4e170dbd17 | ||
![]() |
f7c8d65ea9 | ||
![]() |
5b6e34f3fe | ||
![]() |
b79b226a74 | ||
![]() |
6ba18dfad2 | ||
![]() |
6630058508 | ||
![]() |
0bbb39696b | ||
![]() |
7fd87caa36 | ||
![]() |
2125966684 | ||
![]() |
4180cb2565 | ||
![]() |
dffad1e2c4 | ||
![]() |
3d70495836 | ||
![]() |
6372ccd877 | ||
![]() |
2ad466e617 | ||
![]() |
5ce104e820 | ||
![]() |
f56cb943ff | ||
![]() |
2b96f3b650 | ||
![]() |
d4020b93a3 | ||
![]() |
2f25a0892e | ||
![]() |
114387d030 | ||
![]() |
e3ab44e6d3 | ||
![]() |
0d918c9446 | ||
![]() |
002ad814e5 | ||
![]() |
b4a1e9bc4e | ||
![]() |
822ff3874a | ||
![]() |
78ca9bebc4 | ||
![]() |
7b7f13536f | ||
![]() |
766a01e766 | ||
![]() |
3196292c85 | ||
![]() |
f45b9315a9 | ||
![]() |
c3b36013d7 | ||
![]() |
17491ca7da | ||
![]() |
d1423eb6e8 | ||
![]() |
c190672603 | ||
![]() |
ddf521b62b | ||
![]() |
50c8470d73 | ||
![]() |
e9179ee084 | ||
![]() |
adb7ff5a03 | ||
![]() |
706410480b | ||
![]() |
61ecd0629f | ||
![]() |
84c85c3d12 | ||
![]() |
d8496f9e62 | ||
![]() |
1495a4c731 | ||
![]() |
0efe79ddb3 | ||
![]() |
068234b57c | ||
![]() |
dc1ce92194 | ||
![]() |
937e1745d2 | ||
![]() |
9f6f02ad24 | ||
![]() |
340e8c356b | ||
![]() |
65d3111e65 | ||
![]() |
22a8574824 | ||
![]() |
584477f711 | ||
![]() |
2ae7efce04 | ||
![]() |
b12edc9439 | ||
![]() |
c02297ab91 | ||
![]() |
b2b6dbd5ed | ||
![]() |
3f154e5fb5 | ||
![]() |
cff7b38058 | ||
![]() |
849493eea2 | ||
![]() |
8cace712ae | ||
![]() |
b44c8838c4 | ||
![]() |
901c7f6cd7 | ||
![]() |
870e81ab9d | ||
![]() |
d4ec2d104f | ||
![]() |
614448d07a | ||
![]() |
dcbe82f398 | ||
![]() |
afe70d39b9 | ||
![]() |
9118e07d7b | ||
![]() |
c0f05fcf8f | ||
![]() |
35445f37e1 | ||
![]() |
94c430f491 | ||
![]() |
97efb82971 | ||
![]() |
5f49a22a5e | ||
![]() |
85f4fc0df8 | ||
![]() |
04a7818608 | ||
![]() |
21c1df4f69 | ||
![]() |
0dfe4fb5c6 | ||
![]() |
9ca1fd42ae | ||
![]() |
5713d12ce1 | ||
![]() |
e01790aa23 | ||
![]() |
ecf0970ca4 | ||
![]() |
78e782dd01 | ||
![]() |
e4a5ae0c37 | ||
![]() |
c8e9e6361c | ||
![]() |
7c4fa5c516 | ||
![]() |
97b7f73ff2 | ||
![]() |
0b5c883012 | ||
![]() |
a9671b6227 | ||
![]() |
9ab22b1a1c | ||
![]() |
a931b7597c |
@@ -143,13 +143,17 @@ composer create-project jaguarjack/catchadmin:dev-master
|
||||
如果你觉得项目对你有帮助,可以请作者喝杯咖啡☕️!鼓励下
|
||||
<img src="https://cdn.learnku.com/uploads/images/202008/11/18206/e6qAAM8Bod.jpg!large">
|
||||
|
||||
### Who used
|
||||
- [uctoo 应用开发管理后台](https://gitee.com/uctoo/uctoo)
|
||||
|
||||
### Talking
|
||||
- [论坛讨论](http://bbs.catchadmin.com)
|
||||
- 可以提 `ISSUE`,请按照 `issue` 模板提问
|
||||
- 加入 Q 群 `302266230` 暗号 `catchadmin`。
|
||||
- 加入 Q 群 `302266230` 前请先 star 项目支持一下, 备注填写用户名 + 平台。例如: JaguarJack Github
|
||||
|
||||
### Thanks
|
||||
> 排名部分先后
|
||||
- 感谢 [JetBrains](https://www.jetbrains.com) 提供生产力巨高的 `PHPStorm`和`WebStorm`
|
||||
> 排名不分先后
|
||||
|
||||
- [top-think/think](https://github.com/top-think/think)
|
||||
- [element-admin](https://panjiachen.gitee.io/vue-element-admin-site/zh/)
|
||||
|
BIN
catch/.DS_Store
vendored
BIN
catch/.DS_Store
vendored
Binary file not shown.
47
catch/cms/tables/Category.php
Normal file
47
catch/cms/tables/Category.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace catchAdmin\cms\table;
|
||||
|
||||
use catcher\CatchTable;
|
||||
use catcher\library\table\Actions;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
|
||||
class Category extends CatchTable
|
||||
{
|
||||
public function table()
|
||||
{
|
||||
// TODO: Implement table() method.
|
||||
return $this->getTable('category')
|
||||
->header([
|
||||
HeaderItem::label('分类名称')->prop('name'),
|
||||
HeaderItem::label('自定义链接')->prop('url'),
|
||||
HeaderItem::label('栏目类型')->prop('type')->component('type'),
|
||||
HeaderItem::label('投稿')->prop('is_can_contribute')->withSwitchComponent(),
|
||||
HeaderItem::label('评论')->prop('is_can_comment')->withSwitchComponent(),
|
||||
HeaderItem::label('状态')->prop('status')->withSwitchComponent(),
|
||||
HeaderItem::label('权重')->prop('weight')->withEditNumberComponent(),
|
||||
HeaderItem::label('创建时间')->prop('created_at'),
|
||||
HeaderItem::label('操作')->actions([
|
||||
Actions::update(),
|
||||
Actions::delete()
|
||||
])
|
||||
])
|
||||
->withActions([
|
||||
Actions::create()
|
||||
])
|
||||
->withSearch([
|
||||
Search::label('分类名称')->name('请输入分类名称'),
|
||||
Search::label('状态')->name('请选择状态'),
|
||||
])
|
||||
->toTreeTable()
|
||||
->render();
|
||||
}
|
||||
|
||||
public function form()
|
||||
{
|
||||
// TODO: Implement form() method.
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -31,7 +31,7 @@ class DomainMenusSeed extends Seeder
|
||||
return array (
|
||||
0 =>
|
||||
array (
|
||||
'id' => 72,
|
||||
'id' => 82,
|
||||
'permission_name' => '域名管理',
|
||||
'parent_id' => 0,
|
||||
'level' => '',
|
||||
@@ -47,50 +47,53 @@ class DomainMenusSeed extends Seeder
|
||||
'hidden' => 1,
|
||||
'sort' => 1,
|
||||
'created_at' => 1601105834,
|
||||
'updated_at' => 1601105834,
|
||||
'deleted_at' => 0,
|
||||
),
|
||||
1 =>
|
||||
array (
|
||||
'id' => 73,
|
||||
'permission_name' => '域名设置',
|
||||
'parent_id' => 72,
|
||||
'level' => '72',
|
||||
'route' => '/domain/index',
|
||||
'icon' => 'el-icon-setting',
|
||||
'module' => 'domain',
|
||||
'creator_id' => 1,
|
||||
'permission_mark' => 'domain',
|
||||
'component' => 'domain',
|
||||
'redirect' => '',
|
||||
'keepalive' => 1,
|
||||
'type' => 1,
|
||||
'hidden' => 1,
|
||||
'sort' => 8,
|
||||
'created_at' => 1601105879,
|
||||
'updated_at' => 1601112604,
|
||||
'deleted_at' => 0,
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'id' => 84,
|
||||
'permission_name' => '域名记录',
|
||||
'parent_id' => 72,
|
||||
'level' => '72',
|
||||
'route' => '/domain/record/:domain',
|
||||
'icon' => 'el-icon-document',
|
||||
'module' => 'domain',
|
||||
'creator_id' => 1,
|
||||
'permission_mark' => 'domainRecord',
|
||||
'component' => 'domainRecord',
|
||||
'redirect' => '',
|
||||
'keepalive' => 1,
|
||||
'type' => 1,
|
||||
'hidden' => 2,
|
||||
'sort' => 1,
|
||||
'created_at' => 1601112569,
|
||||
'updated_at' => 1601112606,
|
||||
'updated_at' => 1612754299,
|
||||
'deleted_at' => 0,
|
||||
'children' =>
|
||||
array (
|
||||
0 =>
|
||||
array (
|
||||
'id' => 83,
|
||||
'permission_name' => '域名设置',
|
||||
'parent_id' => 82,
|
||||
'level' => '82',
|
||||
'route' => '/domain/index',
|
||||
'icon' => 'el-icon-setting',
|
||||
'module' => 'domain',
|
||||
'creator_id' => 1,
|
||||
'permission_mark' => 'domain',
|
||||
'component' => 'domain',
|
||||
'redirect' => '',
|
||||
'keepalive' => 1,
|
||||
'type' => 1,
|
||||
'hidden' => 1,
|
||||
'sort' => 8,
|
||||
'created_at' => 1601105879,
|
||||
'updated_at' => 1612754299,
|
||||
'deleted_at' => 0,
|
||||
),
|
||||
1 =>
|
||||
array (
|
||||
'id' => 84,
|
||||
'permission_name' => '域名记录',
|
||||
'parent_id' => 82,
|
||||
'level' => '82',
|
||||
'route' => '/domain/record/:domain',
|
||||
'icon' => 'el-icon-document',
|
||||
'module' => 'domain',
|
||||
'creator_id' => 1,
|
||||
'permission_mark' => 'domainRecord',
|
||||
'component' => 'domainRecord',
|
||||
'redirect' => '',
|
||||
'keepalive' => 1,
|
||||
'type' => 1,
|
||||
'hidden' => 2,
|
||||
'sort' => 1,
|
||||
'created_at' => 1601112569,
|
||||
'updated_at' => 1612754299,
|
||||
'deleted_at' => 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: JaguarJack [ njphper@gmail.com ]
|
||||
// +----------------------------------------------------------------------
|
||||
/* @var think\Route $router */
|
||||
|
||||
// you should use `$router`
|
||||
use catchAdmin\domain\controller\DomainRecord;
|
||||
|
@@ -29,7 +29,7 @@ class Index extends CatchController
|
||||
|
||||
$user = $auth->user();
|
||||
|
||||
$this->afterLoginSuccess($user);
|
||||
$this->afterLoginSuccess($user, $token);
|
||||
// 登录事件
|
||||
$this->loginEvent($user->username);
|
||||
|
||||
@@ -70,12 +70,16 @@ class Index extends CatchController
|
||||
*
|
||||
* @time 2020年09月09日
|
||||
* @param $user
|
||||
* @param $token
|
||||
* @return void
|
||||
*/
|
||||
protected function afterLoginSuccess($user)
|
||||
protected function afterLoginSuccess($user, $token)
|
||||
{
|
||||
$user->last_login_ip = request()->ip();
|
||||
$user->last_login_time = time();
|
||||
if ($user->hasField('remember_token')) {
|
||||
$user->remember_token = $token;
|
||||
}
|
||||
$user->save();
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,7 @@
|
||||
<?php
|
||||
|
||||
/* @var think\Route $router */
|
||||
|
||||
$router->group(function () use ($router){
|
||||
# 登入
|
||||
$router->post('login', '\catchAdmin\login\controller\Index@login');
|
||||
|
@@ -36,7 +36,7 @@ class CatchCrontabCommand extends Command
|
||||
->addOption('pid', '-p', Option::VALUE_REQUIRED, 'you can send signal to the process of pid')
|
||||
->addOption('static', '-s', Option::VALUE_REQUIRED, 'default static process number', 1)
|
||||
->addOption('dynamic', '-dy', Option::VALUE_REQUIRED, 'default dynamic process number', 10)
|
||||
->addOption('interval', '-i', Option::VALUE_REQUIRED, 'interval/seconds', 60)
|
||||
->addOption('interval', '-i', Option::VALUE_REQUIRED, 'interval/seconds', 5)
|
||||
->setDescription('start catch crontab schedule');
|
||||
}
|
||||
|
||||
|
128
catch/monitor/command/ScheduleCommand.php
Normal file
128
catch/monitor/command/ScheduleCommand.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | CatchAdmin [Just Like ~ ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: JaguarJack [ njphper@gmail.com ]
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace catchAdmin\monitor\command;
|
||||
|
||||
use catchAdmin\monitor\command\process\Process;
|
||||
use catchAdmin\monitor\model\Crontab;
|
||||
use catchAdmin\monitor\model\CrontabLog;
|
||||
use Cron\CronExpression;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
use think\facade\Log;
|
||||
|
||||
class ScheduleCommand extends Command
|
||||
{
|
||||
protected $pid;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
// 指令配置
|
||||
$this->setName('catch:schedule')
|
||||
->setDescription('catch schedule');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
try {
|
||||
foreach ($this->getExecuteAbleCommands() as $command) {
|
||||
|
||||
$process = new Process(function (Process $process) use ($command) {
|
||||
$this->executeCommand($command);
|
||||
$process->exit();
|
||||
});
|
||||
|
||||
$process->start();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('CatchSchedule Error:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行 command
|
||||
*
|
||||
* @time 2021年01月18日
|
||||
* @param $command
|
||||
* @return void
|
||||
*/
|
||||
protected function executeCommand($command)
|
||||
{
|
||||
$start = time();
|
||||
|
||||
$errorMessage = '';
|
||||
|
||||
try {
|
||||
$this->getConsole()->call($command->task);
|
||||
} catch (\Exception $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
}
|
||||
|
||||
$end = time();
|
||||
|
||||
// 插入 crontab 执行日志
|
||||
CrontabLog::insert([
|
||||
'crontab_id' => $command->id,
|
||||
'used_time' => $end - $start,
|
||||
'status' => $errorMessage ? CrontabLog::FAILED : CrontabLog::SUCCESS,
|
||||
'error_message' => $errorMessage,
|
||||
'created_at' => time(),
|
||||
'updated_at' => time(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可执行任务
|
||||
*
|
||||
* @time 2021年01月17日
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @return array
|
||||
*/
|
||||
protected function getExecuteAbleCommands()
|
||||
{
|
||||
$executeAbleCommands = [];
|
||||
|
||||
|
||||
Crontab::where('status', Crontab::ENABLE)
|
||||
->select()
|
||||
->each(function ($command) use (&$executeAbleCommands){
|
||||
if ($command->tactics == Crontab::EXECUTE_IMMEDIATELY) {
|
||||
$executeAbleCommands[] = $command;
|
||||
$command->tactics = Crontab::EXECUTE_NORMAL;
|
||||
return $command->save();
|
||||
}
|
||||
|
||||
$can = date('Y-m-d H:i',
|
||||
(new CronExpression(trim($command->cron)))
|
||||
->getNextRunDate(date('Y-m-d H:i:s'), 0, true)
|
||||
->getTimestamp()) == date('Y-m-d H:i', time());
|
||||
|
||||
if ($can) {
|
||||
// 如果任务只执行一次 之后禁用该任务
|
||||
if ($command->tactics === Crontab::EXECUTE_ONCE) {
|
||||
$command->tactics = Crontab::DISABLE;
|
||||
$command->save();
|
||||
}
|
||||
|
||||
$executeAbleCommands[] = $command;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return $executeAbleCommands;
|
||||
}
|
||||
}
|
@@ -116,7 +116,7 @@ trait RegisterSignal
|
||||
$process->exit();
|
||||
});
|
||||
|
||||
$process->start();
|
||||
$process->start();
|
||||
|
||||
Process::alarm($this->interval);
|
||||
});
|
||||
|
@@ -121,7 +121,7 @@ trait Store
|
||||
{
|
||||
$pidFile = config('catch.crontab.master_pid_file');
|
||||
|
||||
if (!file_exists($pidFile)) {
|
||||
if (!FileSystem::exists($pidFile)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ trait Store
|
||||
*/
|
||||
public function renderStatus()
|
||||
{
|
||||
return file_get_contents(self::statusPath());
|
||||
return FileSystem::sharedGet(self::statusPath());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -47,7 +47,7 @@ class Crontab extends CatchController
|
||||
*/
|
||||
public function save(Request $request)
|
||||
{
|
||||
CronExpression::factory($request->post('cron'));
|
||||
new CronExpression($request->post('cron'));
|
||||
|
||||
return CatchResponse::success($this->model->storeBy($request->post()));
|
||||
}
|
||||
@@ -73,7 +73,7 @@ class Crontab extends CatchController
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
CronExpression::factory($request->post('cron'));
|
||||
new CronExpression($request->post('cron'));
|
||||
|
||||
return CatchResponse::success($this->model->updateBy($id, $request->post()));
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ class Crontab extends Migrator
|
||||
->addColumn('group', 'boolean', ['null' => false,'default' => 1,'signed' => false,'comment' => '1 默认 2 系统',])
|
||||
->addColumn('task', 'string', ['limit' => 255,'null' => false,'default' => '','signed' => false,'comment' => '任务名称',])
|
||||
->addColumn('cron', 'string', ['limit' => 50,'null' => false,'default' => '','signed' => false,'comment' => 'cron 表达式',])
|
||||
->addColumn('tactics', 'boolean', ['null' => false,'default' => 1,'signed' => false,'comment' => '1 立即执行 2 执行一次 3 放弃执行',])
|
||||
->addColumn('tactics', 'boolean', ['null' => false,'default' => 1,'signed' => false,'comment' => '1 立即执行 2 执行一次 3 正常执行',])
|
||||
->addColumn('status', 'boolean', ['null' => false,'default' => 1,'signed' => false,'comment' => '1 正常 2 禁用',])
|
||||
->addColumn('remark', 'string', ['limit' => 1000,'null' => false,'default' => '','signed' => false,'comment' => '备注',])
|
||||
->addColumn('creator_id', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '创建人ID',])
|
||||
|
@@ -38,6 +38,5 @@ class Crontab extends Model
|
||||
|
||||
const EXECUTE_IMMEDIATELY = 1; // 立即执行
|
||||
const EXECUTE_ONCE = 2; // 执行一次
|
||||
const EXECUTE_FORBIDDEN = 3; // 停止执行
|
||||
|
||||
const EXECUTE_NORMAL = 3; // 正常执行
|
||||
}
|
@@ -47,7 +47,7 @@ class CrontabLog extends CatchModel
|
||||
return $this->catchLeftJoin(Crontab::class, 'id', 'crontab_id', ['name', 'group', 'task'])
|
||||
->catchSearch()
|
||||
->catchOrder()
|
||||
->field(['used_time', 'error_message', 'crontab_log.status', 'crontab_log.id', 'crontab_log.created_at'])
|
||||
->field(['used_time', 'error_message', $this->aliasField('status'), $this->aliasField('id'), $this->aliasField('created_at')])
|
||||
->paginate();
|
||||
}
|
||||
}
|
@@ -19,6 +19,6 @@ trait CrontabSearch
|
||||
|
||||
public function searchStatusAttr($query, $value, $data)
|
||||
{
|
||||
return $query->whereLike('status', $value);
|
||||
return $query->where('status', $value);
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,8 @@
|
||||
// | Author: JaguarJack [ njphper@gmail.com ]
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
/* @var think\Route $router */
|
||||
|
||||
// you should use `$router`
|
||||
$router->group('monitor', function () use ($router){
|
||||
// crontab路由
|
||||
@@ -16,7 +18,7 @@ $router->group('monitor', function () use ($router){
|
||||
$router->put('crontab/enable/<id>', '\catchAdmin\monitor\controller\Crontab@disOrEnable');
|
||||
|
||||
// crontab 日志
|
||||
$router->get('crontab/log', '\catchAdmin\monitor\controller\CrontabLog@index');
|
||||
$router->delete('crontab/log/<id>', '\catchAdmin\monitor\controller\CrontabLog@delete');
|
||||
$router->get('crontab/log/list', '\catchAdmin\monitor\controller\CrontabLog@index');
|
||||
$router->delete('crontab/log/list/<id>', '\catchAdmin\monitor\controller\CrontabLog@delete');
|
||||
|
||||
})->middleware('auth');
|
@@ -100,6 +100,7 @@ class Permission extends CatchController
|
||||
$permission = $this->permissions->findBy($id);
|
||||
|
||||
$params = $request->param();
|
||||
|
||||
// 按钮类型
|
||||
if ($params['type'] == Permissions::BTN_TYPE && $permission->parent_id) {
|
||||
$parentPermission = $this->permissions->findBy($permission->parent_id);
|
||||
@@ -175,33 +176,7 @@ class Permission extends CatchController
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$this->permissions->show($id);
|
||||
|
||||
return CatchResponse::success();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2020年06月05日
|
||||
* @param $id
|
||||
* @param ParseClass $parseClass
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @return Json
|
||||
*/
|
||||
public function getMethods($id, ParseClass $parseClass)
|
||||
{
|
||||
$permission = Permissions::where('id', $id)->find();
|
||||
$module = $permission->module;
|
||||
$controller = explode('@', $permission->permission_mark)[0];
|
||||
|
||||
try {
|
||||
$methods = $parseClass->setModule('catch')->setRule($module, $controller)->onlySelfMethods();
|
||||
return CatchResponse::success($methods);
|
||||
}catch (\Exception $e) {
|
||||
return CatchResponse::success([]);
|
||||
}
|
||||
return CatchResponse::success($this->permissions->show($id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,20 +1,19 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\controller;
|
||||
|
||||
use catchAdmin\permissions\model\Permissions;
|
||||
use catchAdmin\permissions\model\Roles;
|
||||
use catcher\base\CatchRequest as Request;
|
||||
use catcher\base\CatchController;
|
||||
use catcher\CatchResponse;
|
||||
use catcher\exceptions\FailedException;
|
||||
use catcher\Tree;
|
||||
use think\response\Json;
|
||||
use catchAdmin\permissions\model\Roles as RoleModel;
|
||||
|
||||
class Role extends CatchController
|
||||
{
|
||||
protected $role;
|
||||
|
||||
public function __construct(\catchAdmin\permissions\model\Roles $role)
|
||||
public function __construct(RoleModel $role)
|
||||
{
|
||||
$this->role = $role;
|
||||
}
|
||||
@@ -22,8 +21,7 @@ class Role extends CatchController
|
||||
/**
|
||||
*
|
||||
* @time 2019年12月09日
|
||||
* @param Request $request
|
||||
* @return string
|
||||
* @return string|Json
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
@@ -46,12 +44,13 @@ class Role extends CatchController
|
||||
}
|
||||
|
||||
$this->role->storeBy($params);
|
||||
$permissions = $params['permissions'];
|
||||
if (!empty($permissions)) {
|
||||
$this->role->attachPermissions(array_unique($permissions));
|
||||
// 分配权限
|
||||
if (count($params['permissions'])) {
|
||||
$this->role->attachPermissions(array_unique($params['permissions']));
|
||||
}
|
||||
if (!empty($params['permissions'])) {
|
||||
$this->role->attachDepartments($params['permissions']);
|
||||
// 分配部门
|
||||
if (isset($params['departments']) && count($params['departments'])) {
|
||||
$this->role->attachDepartments($params['departments']);
|
||||
}
|
||||
// 添加角色
|
||||
return CatchResponse::success();
|
||||
@@ -156,37 +155,4 @@ class Role extends CatchController
|
||||
|
||||
return CatchResponse::success();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年12月11日
|
||||
* @param Request $request
|
||||
* @param \catchAdmin\permissions\model\Permissions $permission
|
||||
* @return Json
|
||||
*/
|
||||
public function getPermissions(Request $request, \catchAdmin\permissions\model\Permissions $permission): Json
|
||||
{
|
||||
$parentRoleHasPermissionIds = [];
|
||||
if ($request->param('parent_id')) {
|
||||
$permissions = $this->role->findBy($request->param('parent_id'))->getPermissions();
|
||||
foreach ($permissions as $_permission) {
|
||||
$parentRoleHasPermissionIds[] = $_permission->pivot->permission_id;
|
||||
}
|
||||
}
|
||||
|
||||
$permissions = Tree::done(Permissions::whereIn('id', $parentRoleHasPermissionIds)->select()->toArray());
|
||||
|
||||
$permissionIds = [];
|
||||
if ($request->param('role_id')) {
|
||||
$roleHasPermissions = $this->role->findBy($request->param('role_id'))->getPermissions();
|
||||
foreach ($roleHasPermissions as $_permission) {
|
||||
$permissionIds[] = $_permission->pivot->permission_id;
|
||||
}
|
||||
}
|
||||
|
||||
return CatchResponse::success([
|
||||
'permissions' => $permissions,
|
||||
'hasPermissions' => $permissionIds,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ use catchAdmin\permissions\model\Roles;
|
||||
use catchAdmin\permissions\model\Users;
|
||||
use catchAdmin\permissions\request\CreateRequest;
|
||||
use catchAdmin\permissions\request\UpdateRequest;
|
||||
use catchAdmin\permissions\request\ProfileRequest;
|
||||
use catcher\base\CatchController;
|
||||
use catcher\CatchAuth;
|
||||
use catcher\CatchCacheKeys;
|
||||
@@ -67,15 +68,6 @@ class User extends CatchController
|
||||
return CatchResponse::success($user);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年12月06日
|
||||
* @throws \Exception
|
||||
* @return string
|
||||
*/
|
||||
public function create()
|
||||
{}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param CreateRequest $request
|
||||
@@ -109,12 +101,6 @@ class User extends CatchController
|
||||
return CatchResponse::success($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function edit($id){}
|
||||
/**
|
||||
*
|
||||
* @time 2019年12月04日
|
||||
@@ -124,7 +110,7 @@ class User extends CatchController
|
||||
*/
|
||||
public function update($id, UpdateRequest $request)
|
||||
{
|
||||
$this->user->updateBy($id, $request->param());
|
||||
$this->user->updateBy($id, $request->filterEmptyField()->param());
|
||||
|
||||
$user = $this->user->findBy($id);
|
||||
|
||||
@@ -185,51 +171,6 @@ class User extends CatchController
|
||||
return CatchResponse::success([], '操作成功');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年12月07日
|
||||
* @param $id
|
||||
* @return \think\response\Json
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
*/
|
||||
public function recover($id): \think\response\Json
|
||||
{
|
||||
$trashedUser = $this->user->findBy($id, ['*'], true);
|
||||
|
||||
if ($this->user->where('email', $trashedUser->email)->find()) {
|
||||
return CatchResponse::fail(sprintf('该恢复用户的邮箱 [%s] 已被占用', $trashedUser->email));
|
||||
}
|
||||
|
||||
return CatchResponse::success($this->user->recover($id));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年12月11日
|
||||
* @param Request $request
|
||||
* @param Roles $roles
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function getRoles(Request $request, Roles $roles): \think\response\Json
|
||||
{
|
||||
$roles = Tree::done($roles->getList());
|
||||
|
||||
$roleIds = [];
|
||||
if ($request->param('uid')) {
|
||||
$userHasRoles = $this->user->findBy($request->param('uid'))->getRoles();
|
||||
foreach ($userHasRoles as $role) {
|
||||
$roleIds[] = $role->pivot->role_id;
|
||||
}
|
||||
}
|
||||
|
||||
return CatchResponse::success([
|
||||
'roles' => $roles,
|
||||
'hasRoles' => $roleIds,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出
|
||||
*
|
||||
@@ -248,11 +189,11 @@ class User extends CatchController
|
||||
* 更新个人信息
|
||||
*
|
||||
* @time 2020年09月20日
|
||||
* @param Request $request
|
||||
* @param ProfileRequest $request
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function profile(Request $request)
|
||||
public function profile(ProfileRequest $request)
|
||||
{
|
||||
return CatchResponse::success($this->user->updateBy($request->user()->id, $request->param()));
|
||||
return CatchResponse::success($this->user->updateBy($request->user()->id, $request->filterEmptyField()->param()));
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CatchAdmin [Just Like ~ ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2017~{$year} http://catchadmin.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: JaguarJack [ njphper@gmail.com ]
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
use think\migration\Migrator;
|
||||
use think\migration\db\Column;
|
||||
|
||||
class AddUserRememberToken extends Migrator
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
|
||||
*
|
||||
* The following commands can be used in this method and Phinx will
|
||||
* automatically reverse them when rolling back:
|
||||
*
|
||||
* createTable
|
||||
* renameTable
|
||||
* addColumn
|
||||
* renameColumn
|
||||
* addIndex
|
||||
* addForeignKey
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change()
|
||||
{
|
||||
if ($this->hasTable('users')) {
|
||||
$table = $this->table('users');
|
||||
|
||||
$table->addColumn('remember_token', 'string', [
|
||||
'limit' => 512,
|
||||
'default' => '',
|
||||
'comment' => '用户token',
|
||||
'after' => 'avatar'])
|
||||
->update();
|
||||
}
|
||||
}
|
||||
}
|
@@ -39,4 +39,23 @@ class Department extends CatchModel
|
||||
->catchOrder()
|
||||
->select()->toTree();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取子部门IDS
|
||||
*
|
||||
* @time 2020年11月04日
|
||||
* @param $id
|
||||
* @throws DbException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getChildrenDepartmentIds($id)
|
||||
{
|
||||
$departmentIds = Department::field(['id', 'parent_id'])->select()->getAllChildrenIds([$id]);
|
||||
|
||||
$departmentIds[] = $id;
|
||||
|
||||
return $departmentIds;
|
||||
}
|
||||
}
|
||||
|
@@ -87,12 +87,18 @@ class Permissions extends CatchModel
|
||||
*/
|
||||
public static function onAfterInsert(Model $model)
|
||||
{
|
||||
$restful = intval($model->getData('restful'));
|
||||
|
||||
$model = self::where('id', $model->id)->find();
|
||||
|
||||
if ($model && $model->parent_id) {
|
||||
$parent = self::where('id', $model->parent_id)->find();
|
||||
|
||||
$level = $parent->level ? $parent->level . '-' . $parent->id : $parent->id;
|
||||
return $model->where('id', $model->id)->update([
|
||||
|
||||
$restful && self::createRestful($model, $level);
|
||||
|
||||
return $model->updateBy('id', [
|
||||
'level' => $level
|
||||
]);
|
||||
}
|
||||
@@ -101,6 +107,40 @@ class Permissions extends CatchModel
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建 restful 菜单
|
||||
*
|
||||
* @time 2021年04月20日
|
||||
* @param Model $model
|
||||
* @param $level
|
||||
* @return void
|
||||
*/
|
||||
protected static function createRestful(Model $model, $level)
|
||||
{
|
||||
$restful = [
|
||||
'index' => '列表',
|
||||
'save' => '保存',
|
||||
'update' => '更新',
|
||||
'delete' => '删除',
|
||||
];
|
||||
|
||||
foreach ($restful as $k => $r) {
|
||||
self::insert([
|
||||
'parent_id' => $model->id,
|
||||
'permission_name' => $r,
|
||||
'level' => $level . '-' . $model->id,
|
||||
'module' => $model->getData('module'),
|
||||
'creator_id' => $model->getData('creator_id'),
|
||||
'permission_mark' => $model->getData('permission_mark') . '@' . $k,
|
||||
'type' => self::BTN_TYPE,
|
||||
'created_at' => time(),
|
||||
'updated_at' => time(),
|
||||
'sort' => 1,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function show($id)
|
||||
{
|
||||
$permission = $this->findBy($id);
|
||||
|
@@ -35,8 +35,18 @@ class Roles extends CatchModel
|
||||
public function getList()
|
||||
{
|
||||
return $this->catchSearch()
|
||||
->with(['permissions', 'departments'])
|
||||
->order('id', 'desc')
|
||||
->select()
|
||||
->each(function (&$item){
|
||||
$permissions = $item->permissions->column('id');
|
||||
unset($item['permissions']);
|
||||
$item['_permissions'] = $permissions;
|
||||
|
||||
$departments = $item->departments->column('id');
|
||||
unset($item['departments']);
|
||||
$item['departments'] = $departments;
|
||||
})
|
||||
->toTree();
|
||||
}
|
||||
|
||||
|
@@ -5,6 +5,7 @@ use catchAdmin\permissions\model\search\UserSearch;
|
||||
use catcher\base\CatchModel;
|
||||
use catcher\exceptions\FailedException;
|
||||
use catcher\Utils;
|
||||
use think\Paginator;
|
||||
|
||||
class Users extends CatchModel
|
||||
{
|
||||
@@ -20,6 +21,7 @@ class Users extends CatchModel
|
||||
'password', // 用户密码
|
||||
'email', // 邮箱 登录
|
||||
'avatar', // 头像
|
||||
'remember_token',
|
||||
'creator_id', // 创建者ID
|
||||
'department_id', // 部门ID
|
||||
'status', // 用户状态 1 正常 2 禁用
|
||||
@@ -28,7 +30,6 @@ class Users extends CatchModel
|
||||
'created_at', // 创建时间
|
||||
'updated_at', // 更新时间
|
||||
'deleted_at', // 删除状态,0未删除 >0 已删除
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -47,16 +48,25 @@ class Users extends CatchModel
|
||||
* 用户列表
|
||||
*
|
||||
* @time 2019年12月08日
|
||||
* @throws \think\db\exception\DbException
|
||||
* @return \think\Paginator
|
||||
* @return array|\think\Paginator
|
||||
*@throws \think\db\exception\DbException
|
||||
*/
|
||||
public function getList(): \think\Paginator
|
||||
public function getList()
|
||||
{
|
||||
return $this->withoutField(['updated_at'], true)
|
||||
$users = $this->withoutField(['updated_at', 'password', 'remember_token'], true)
|
||||
->catchSearch()
|
||||
->catchLeftJoin(Department::class, 'id', 'department_id', ['department_name'])
|
||||
->with(['jobs', 'roles'])
|
||||
->order($this->aliasField('id'), 'desc')
|
||||
->paginate();
|
||||
->paginate()->toArray();
|
||||
|
||||
foreach ($users['data'] as &$user) {
|
||||
$user['roles'] = array_column($user['roles'], 'id');
|
||||
$user['jobs'] = array_column($user['jobs'], 'id');
|
||||
}
|
||||
|
||||
|
||||
return Paginator::make($users['data'], $users['per_page'], $users['current_page'], $users['total']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -20,10 +20,20 @@ trait UserSearch
|
||||
return $query->where($this->aliasField('status'), $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部门下的用户
|
||||
*
|
||||
* @time 2020年11月04日
|
||||
* @param $query
|
||||
* @param $value
|
||||
* @param $data
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @return mixed
|
||||
*/
|
||||
public function searchDepartmentIdAttr($query, $value, $data)
|
||||
{
|
||||
$departmentIds = Department::where('parent_id', $value)->column('id');
|
||||
$departmentIds[] = $value;
|
||||
return $query->whereIn($this->aliasField('department_id'), $departmentIds);
|
||||
return $query->whereIn($this->aliasField('department_id'), Department::getChildrenDepartmentIds($value));
|
||||
}
|
||||
}
|
||||
|
17
catch/permissions/request/ProfileRequest.php
Normal file
17
catch/permissions/request/ProfileRequest.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\request;
|
||||
|
||||
use catchAdmin\permissions\model\Users;
|
||||
use catcher\base\CatchRequest;
|
||||
|
||||
class ProfileRequest extends CatchRequest
|
||||
{
|
||||
protected function rules(): array
|
||||
{
|
||||
// TODO: Implement rules() method.
|
||||
return [
|
||||
'username|用户名' => 'require|max:20',
|
||||
'email|邮箱' => 'require|email|unique:'.Users::class . ',email,' . $this->user()->id,
|
||||
];
|
||||
}
|
||||
}
|
@@ -15,9 +15,4 @@ class UpdateRequest extends CatchRequest
|
||||
'email|邮箱' => 'require|email|unique:'.Users::class,
|
||||
];
|
||||
}
|
||||
|
||||
protected function message()
|
||||
{
|
||||
// TODO: Implement message() method.
|
||||
}
|
||||
}
|
||||
|
@@ -1,28 +1,24 @@
|
||||
<?php
|
||||
|
||||
/* @var think\Route $router */
|
||||
|
||||
$router->group(function () use ($router){
|
||||
// 角色
|
||||
$router->resource('roles', '\catchAdmin\permissions\controller\Role');
|
||||
// 角色列表
|
||||
$router->get('/role/get/permissions', '\catchAdmin\permissions\controller\Role@getPermissions');
|
||||
// 权限
|
||||
$router->resource('permissions', '\catchAdmin\permissions\controller\Permission');
|
||||
$router->put('permissions/show/<id>', '\catchAdmin\permissions\controller\Permission@show');
|
||||
$router->get('controller/methods/<id>', '\catchAdmin\permissions\controller\Permission@getMethods');
|
||||
|
||||
// 部门
|
||||
$router->resource('departments', '\catchAdmin\permissions\controller\Department');
|
||||
// 所有职位
|
||||
$router->get('jobs/all', '\catchAdmin\permissions\controller\Job@getAll');
|
||||
// 岗位
|
||||
$router->resource('jobs', '\catchAdmin\permissions\controller\Job');
|
||||
|
||||
$router->get('jobs/all', '\catchAdmin\permissions\controller\Job@getAll');
|
||||
|
||||
// 用户
|
||||
$router->resource('users', '\catchAdmin\permissions\controller\User');
|
||||
// 切换状态
|
||||
$router->put('users/switch/status/<id>', '\catchAdmin\permissions\controller\User@switchStatus');
|
||||
$router->put('users/recover/<id>', '\catchAdmin\permissions\controller\User@recover');
|
||||
$router->put('user/profile', '\catchAdmin\permissions\controller\User@profile');
|
||||
$router->get('users/get/roles', '\catchAdmin\permissions\controller\User@getRoles');
|
||||
$router->get('user/info', '\catchAdmin\permissions\controller\User@info');
|
||||
$router->get('user/export', '\catchAdmin\permissions\controller\User@export');
|
||||
})->middleware('auth');
|
50
catch/permissions/tables/Department.php
Normal file
50
catch/permissions/tables/Department.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables;
|
||||
|
||||
use catchAdmin\permissions\tables\forms\Factory;
|
||||
use catcher\CatchTable;
|
||||
use catcher\library\table\Actions;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
use catcher\library\table\Table;
|
||||
|
||||
class Department extends CatchTable
|
||||
{
|
||||
/**
|
||||
* table
|
||||
*
|
||||
* @time 2021年03月29日
|
||||
* @return array
|
||||
*/
|
||||
protected function table(): array
|
||||
{
|
||||
// TODO: Implement table() method.
|
||||
return $this->getTable('department')->header([
|
||||
HeaderItem::label('部门名称')->prop('department_name'),
|
||||
HeaderItem::label('排序')->prop('sort')->withEditNumberComponent(),
|
||||
HeaderItem::label('状态')->prop('status')->withSwitchComponent(),
|
||||
HeaderItem::label('创建时间')->prop('created_at'),
|
||||
HeaderItem::label('操作')->width(260)->actions([
|
||||
Actions::update(),
|
||||
Actions::delete(),
|
||||
])
|
||||
])->withApiRoute('departments')->withActions([
|
||||
Actions::create()
|
||||
])->withSearch([
|
||||
Search::label('部门名称')->text('department_name', '请输入部门名称'),
|
||||
Search::label('状态')->status()
|
||||
])->withDialogWidth('35%')
|
||||
->toTreeTable()->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* form 方式
|
||||
*
|
||||
* @time 2021年03月29日
|
||||
* @return array
|
||||
*/
|
||||
protected function form(): array
|
||||
{
|
||||
return Factory::create('department');
|
||||
}
|
||||
}
|
44
catch/permissions/tables/Job.php
Normal file
44
catch/permissions/tables/Job.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables;
|
||||
|
||||
|
||||
use catcher\CatchTable;
|
||||
use catchAdmin\permissions\tables\forms\Factory;
|
||||
use catcher\library\table\Actions;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
|
||||
class Job extends CatchTable
|
||||
{
|
||||
public function table()
|
||||
{
|
||||
return $this->getTable('job')
|
||||
->header([
|
||||
HeaderItem::label('')->type('selection'),
|
||||
HeaderItem::label('岗位名称')->prop('job_name'),
|
||||
HeaderItem::label('编码')->prop('coding'),
|
||||
HeaderItem::label('状态')->prop('status')->withSwitchComponent(),
|
||||
HeaderItem::label('创建时间')->prop('created_at'),
|
||||
HeaderItem::label('操作')->width(250)->actions([
|
||||
Actions::update(),
|
||||
Actions::delete()
|
||||
])
|
||||
])
|
||||
->withActions([
|
||||
Actions::create()
|
||||
])
|
||||
->withSearch([
|
||||
Search::label('岗位名称')->text('job_name', '岗位名称')
|
||||
])
|
||||
->withApiRoute('jobs')
|
||||
->selectionChange()
|
||||
->render();
|
||||
}
|
||||
|
||||
|
||||
public function form()
|
||||
{
|
||||
// TODO: Implement form() method.
|
||||
return Factory::create('job');
|
||||
}
|
||||
}
|
50
catch/permissions/tables/Permission.php
Normal file
50
catch/permissions/tables/Permission.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables;
|
||||
|
||||
|
||||
use catcher\CatchTable;
|
||||
use catchAdmin\permissions\tables\forms\Factory;
|
||||
use catcher\library\table\Actions;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
|
||||
class Permission extends CatchTable
|
||||
{
|
||||
public function table()
|
||||
{
|
||||
return $this->getTable('permission')
|
||||
->header([
|
||||
HeaderItem::label('菜单名称')->prop('permission_name'),
|
||||
HeaderItem::label('路由Path')->prop('route'),
|
||||
HeaderItem::label('权限标识')->prop('actionList')->width(250)->component('actions', 'actionList'),
|
||||
HeaderItem::label('状态')->prop('hidden')->component('status'),
|
||||
HeaderItem::label('创建时间')->prop('created_at'),
|
||||
HeaderItem::label('操作')->width(250)->actions([
|
||||
Actions::update(),
|
||||
Actions::delete()
|
||||
])
|
||||
])
|
||||
->withActions([
|
||||
Actions::create()
|
||||
])
|
||||
->withSearch([
|
||||
Search::label('菜单名称')->text('permission_name', '菜单名称')->clearable(true),
|
||||
Search::hidden('actionList', 'actionList')
|
||||
])
|
||||
->withFilterParams([
|
||||
'permission_name' => '',
|
||||
'actionList' => 'actionList'
|
||||
])
|
||||
->withDefaultQueryParams(['actionList'])
|
||||
->withApiRoute('permissions')
|
||||
->toTreeTable()
|
||||
->render();
|
||||
}
|
||||
|
||||
|
||||
public function form()
|
||||
{
|
||||
// TODO: Implement form() method.
|
||||
return Factory::create('permission');
|
||||
}
|
||||
}
|
43
catch/permissions/tables/Role.php
Normal file
43
catch/permissions/tables/Role.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables;
|
||||
|
||||
|
||||
use catcher\CatchTable;
|
||||
use catchAdmin\permissions\tables\forms\Factory;
|
||||
use catcher\library\table\Actions;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
|
||||
class Role extends CatchTable
|
||||
{
|
||||
public function table()
|
||||
{
|
||||
// TODO: Implement table() method.
|
||||
return $this->getTable('role')
|
||||
->header([
|
||||
HeaderItem::label('角色名称')->prop('role_name')->width(300),
|
||||
HeaderItem::label('角色标识')->prop('identify')->width(300),
|
||||
HeaderItem::label('角色描述')->prop('description'),
|
||||
HeaderItem::label('创建时间')->prop('created_at'),
|
||||
HeaderItem::label('操作')->width(250)->actions([
|
||||
Actions::update(), Actions::delete()
|
||||
])
|
||||
])
|
||||
->withSearch([
|
||||
Search::label('角色名称')->text('role_name', '角色名称'),
|
||||
])
|
||||
->withApiRoute('roles')
|
||||
->withActions([
|
||||
Actions::create()
|
||||
])->withDialogWidth('40%')
|
||||
->toTreeTable()
|
||||
->forceUpdate()
|
||||
->render();
|
||||
}
|
||||
|
||||
protected function form()
|
||||
{
|
||||
// TODO: Implement form() method.
|
||||
return Factory::create('role');
|
||||
}
|
||||
}
|
54
catch/permissions/tables/User.php
Normal file
54
catch/permissions/tables/User.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables;
|
||||
|
||||
|
||||
use catcher\CatchTable;
|
||||
use catchAdmin\permissions\tables\forms\Factory;
|
||||
use catcher\library\table\Actions;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
|
||||
class User extends CatchTable
|
||||
{
|
||||
public function table()
|
||||
{
|
||||
// TODO: Implement table() method.
|
||||
return $this->getTable('user')
|
||||
->header([
|
||||
HeaderItem::label('')->selection(),
|
||||
HeaderItem::label('用户名')->prop('username'),
|
||||
HeaderItem::label('邮箱')->prop('email'),
|
||||
HeaderItem::label('状态')->prop('status')->component('status', 'status'),
|
||||
HeaderItem::label('创建时间')->prop('created_at'),
|
||||
HeaderItem::label('操作')->width(200)->actions([
|
||||
Actions::update(), Actions::delete()
|
||||
])
|
||||
])
|
||||
->withSearch([
|
||||
Search::label('用户名')->text('username', '用户名'),
|
||||
Search::label('邮箱')->text('email', '邮箱'),
|
||||
Search::label('状态')->status(),
|
||||
Search::hidden('department_id', '')
|
||||
])
|
||||
->withApiRoute('users')
|
||||
->withActions([
|
||||
Actions::create(),
|
||||
Actions::export()
|
||||
])
|
||||
->withExportRoute('user/export')
|
||||
->withFilterParams([
|
||||
'username' => '',
|
||||
'email' => '',
|
||||
'status' => '',
|
||||
'department_id' => ''
|
||||
])
|
||||
->selectionChange()
|
||||
->render();
|
||||
}
|
||||
|
||||
protected function form()
|
||||
{
|
||||
// TODO: Implement form() method.
|
||||
return Factory::create('user');
|
||||
}
|
||||
}
|
32
catch/permissions/tables/forms/Department.php
Normal file
32
catch/permissions/tables/forms/Department.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables\forms;
|
||||
|
||||
use catchAdmin\permissions\model\Department as DepartmentModel;
|
||||
use catcher\library\form\Form;
|
||||
|
||||
class Department extends Form
|
||||
{
|
||||
public function fields(): array
|
||||
{
|
||||
return [
|
||||
// TODO: Implement fields() method
|
||||
Form::cascader('parent_id', '上级部门', [0])->options(
|
||||
DepartmentModel::field(['id', 'parent_id', 'department_name'])->select()->toTree()
|
||||
)->clearable(true)->filterable(true)->props([
|
||||
'props' => [
|
||||
'value' => 'id',
|
||||
'label' => 'department_name',
|
||||
'checkStrictly' => true
|
||||
],
|
||||
])->style(['width' => '100%']),
|
||||
Form::input('department_name', '部门名称')->required()->placeholder('请输入部门名称'),
|
||||
Form::input('principal', '部门负责人'),
|
||||
Form::input('mobile', '负责人联系方式'),
|
||||
Form::email('email', '邮箱'),
|
||||
Form::radio('status', '状态')->value(1)->options(
|
||||
Form::options()->add('启用', 1)->add('禁用', 2)->render()
|
||||
),
|
||||
Form::number('sort', '排序')->value(1)->min(1)->max(10000),
|
||||
];
|
||||
}
|
||||
}
|
12
catch/permissions/tables/forms/Factory.php
Normal file
12
catch/permissions/tables/forms/Factory.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables\forms;
|
||||
|
||||
use catcher\library\form\FormFactory;
|
||||
|
||||
class Factory extends FormFactory
|
||||
{
|
||||
public static function from(): string
|
||||
{
|
||||
return __NAMESPACE__;
|
||||
}
|
||||
}
|
23
catch/permissions/tables/forms/Job.php
Normal file
23
catch/permissions/tables/forms/Job.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables\forms;
|
||||
|
||||
use catcher\library\form\Form;
|
||||
|
||||
class Job extends Form
|
||||
{
|
||||
public function fields(): array
|
||||
{
|
||||
// TODO: Implement fields() method.
|
||||
return [
|
||||
self::input('job_name', '岗位名称')->required(),
|
||||
|
||||
self::input('coding', '岗位编码'),
|
||||
|
||||
self::radio('status', '状态')->value(1)->options(
|
||||
self::options()->add('启用', 1)->add('禁用', 2)->render()
|
||||
),
|
||||
|
||||
self::number('sort', '排序')->value(1)->min(1)->max(10000),
|
||||
];
|
||||
}
|
||||
}
|
155
catch/permissions/tables/forms/Permission.php
Normal file
155
catch/permissions/tables/forms/Permission.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables\forms;
|
||||
|
||||
use catchAdmin\permissions\model\Permissions;
|
||||
use catcher\CatchAdmin;
|
||||
use catcher\library\form\Form;
|
||||
|
||||
class Permission extends Form
|
||||
{
|
||||
public function fields(): array
|
||||
{
|
||||
$this->getModules();
|
||||
// TODO: Implement fields() method.
|
||||
return [
|
||||
self::cascader('parent_id', '父级菜单', [])->options(
|
||||
Permissions::where('type', Permissions::MENU_TYPE)->field(['id', 'permission_name', 'parent_id'])
|
||||
->select()->toTree()
|
||||
)->col(12)->props(self::props('permission_name', 'id', [
|
||||
'checkStrictly' => true
|
||||
]))->filterable(true)->clearable(true)->style(['width' => '100%']),
|
||||
|
||||
self::radio('type', '菜单类型')
|
||||
->button()
|
||||
->value(1)
|
||||
->options(
|
||||
self::options()->add('菜单', 1)->add('按钮', 2)->render()
|
||||
)->appendControl(
|
||||
1,
|
||||
[
|
||||
self::input('permission_name', '菜单名称')->required()->col(12),
|
||||
self::input('permission_mark', '权限标识')->required()->col(12),
|
||||
|
||||
self::select('module', '模块')
|
||||
->required()
|
||||
->style(['width' => '100%'])
|
||||
->allowCreate(true)
|
||||
->filterable(true)
|
||||
->clearable(true)
|
||||
->col(12)
|
||||
->options($this->getModules()),
|
||||
|
||||
self::input('icon', '菜单图标')
|
||||
->col(12)
|
||||
->style(['width' => '100%'])
|
||||
->clearable(true),
|
||||
|
||||
self::input('route', '菜单Path')->col(12),
|
||||
|
||||
self::cascader('component', '组件')
|
||||
->col(12)
|
||||
->options([])
|
||||
->style(['width' => '100%'])
|
||||
->showAllLevels(false),
|
||||
|
||||
self::input('redirect', 'Redirect')->col(12),
|
||||
self::number('sort', '排序')->value(1)->col(12),
|
||||
|
||||
self::radio('keepalive', 'Keepalive')
|
||||
->value(1)
|
||||
->col(12)
|
||||
->options(
|
||||
self::options()->add('启用', 1)
|
||||
->add('禁用', 2)
|
||||
->render()
|
||||
),
|
||||
|
||||
self::radio('hidden', 'Hidden')->value(1)->options(
|
||||
self::options()->add('显示', 1)->add('隐藏', 2)->render()
|
||||
)->col(12),
|
||||
|
||||
self::radio('restful', 'Restful 路由')->value(0)->options(
|
||||
self::options()->add('生成', 1)->add('不生成', 0)->render()
|
||||
)->col(12)
|
||||
]
|
||||
)
|
||||
->appendControl( 2,
|
||||
[
|
||||
self::select('permission_name', '菜单名称')
|
||||
->allowCreate(true)
|
||||
->filterable(true)
|
||||
->options(
|
||||
self::options()->add('列表', '列表')
|
||||
->add('创建', '创建')
|
||||
->add('更新', '更新')->add('读取', '读取')
|
||||
->add('删除', '删除')->add('禁用/启用', '禁用/启用')
|
||||
->add('导出', '导出')->add('导入', '导入')->render()
|
||||
)
|
||||
->required()->style(['width' => '100%'])->col(12),
|
||||
self::select('permission_mark', '权限标识')
|
||||
->allowCreate(true)
|
||||
->filterable(true)
|
||||
->options(
|
||||
self::options()->add('index', 'index')
|
||||
->add('save', 'save')
|
||||
->add('update', 'update')->add('read', 'read')
|
||||
->add('delete', 'delete')->add('disable', 'disable')
|
||||
->add('export', 'export')->add('import', 'import')->render()
|
||||
)
|
||||
->required()->col(12),
|
||||
self::number('sort', '排序')->value(1)->col(12),
|
||||
]
|
||||
)->col(12)
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取模块
|
||||
*
|
||||
* @time 2021年03月31日
|
||||
* @return array
|
||||
*/
|
||||
protected function getModules(): array
|
||||
{
|
||||
$modules = [];
|
||||
|
||||
foreach(CatchAdmin::getModulesDirectory() as $d) {
|
||||
$module = CatchAdmin::getModuleInfo($d);
|
||||
|
||||
if (in_array($module['alias'], ['login'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($module['enable']) {
|
||||
$modules[] = [
|
||||
'value' => $module['alias'],
|
||||
'label' => $module['name']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* icons
|
||||
*
|
||||
* @time 2021年03月31日
|
||||
* @return array
|
||||
*/
|
||||
protected function getIcons(): array
|
||||
{
|
||||
$icons = ['platform-eleme', 'eleme', 'delete-solid', 'delete', 's-tools', 'setting', 'user-solid', 'user', 'phone', 'phone-outline', 'more', 'more-outline', 'star-on', 'star-off', 's-goods', 'goods', 'warning', 'warning-outline', 'question', 'info', 'remove', 'circle-plus', 'success', 'error', 'zoom-in', 'zoom-out', 'remove-outline', 'circle-plus-outline', 'circle-check', 'circle-close', 's-help', 'help', 'minus', 'plus', 'check', 'close', 'picture', 'picture-outline', 'picture-outline-round', 'upload', 'upload2', 'download', 'camera-solid', 'camera', 'video-camera-solid', 'video-camera', 'message-solid', 'bell', 's-cooperation', 's-order', 's-platform', 's-fold', 's-unfold', 's-operation', 's-promotion', 's-home', 's-release', 's-ticket', 's-management', 's-open', 's-shop', 's-marketing', 's-flag', 's-comment', 's-finance', 's-claim', 's-custom', 's-opportunity', 's-data', 's-check', 's-grid', 'menu', 'share', 'd-caret', 'caret-left', 'caret-right', 'caret-bottom', 'caret-top', 'bottom-left', 'bottom-right', 'back', 'right', 'bottom', 'top', 'top-left', 'top-right', 'arrow-left', 'arrow-right', 'arrow-down', 'arrow-up', 'd-arrow-left', 'd-arrow-right', 'video-pause', 'video-play', 'refresh', 'refresh-right', 'refresh-left', 'finished', 'sort', 'sort-up', 'sort-down', 'rank', 'loading', 'view', 'c-scale-to-original', 'date', 'edit', 'edit-outline', 'folder', 'folder-opened', 'folder-add', 'folder-remove', 'folder-delete', 'folder-checked', 'tickets', 'document-remove', 'document-delete', 'document-copy', 'document-checked', 'document', 'document-add', 'printer', 'paperclip', 'takeaway-box', 'search', 'monitor', 'attract', 'mobile', 'scissors', 'umbrella', 'headset', 'brush', 'mouse', 'coordinate', 'magic-stick', 'reading', 'data-line', 'data-board', 'pie-chart', 'data-analysis', 'collection-tag', 'film', 'suitcase', 'suitcase-1', 'receiving', 'collection', 'files', 'notebook-1', 'notebook-2', 'toilet-paper', 'office-building', 'school', 'table-lamp', 'house', 'no-smoking', 'smoking', 'shopping-cart-full', 'shopping-cart-1', 'shopping-cart-2', 'shopping-bag-1', 'shopping-bag-2', 'sold-out', 'sell', 'present', 'box', 'bank-card', 'money', 'coin', 'wallet', 'discount', 'price-tag', 'news', 'guide', 'male', 'female', 'thumb', 'cpu', 'link', 'connection', 'open', 'turn-off', 'set-up', 'chat-round', 'chat-line-round', 'chat-square', 'chat-dot-round', 'chat-dot-square', 'chat-line-square', 'message', 'postcard', 'position', 'turn-off-microphone', 'microphone', 'close-notification', 'bangzhu', 'time', 'odometer', 'crop', 'aim', 'switch-button', 'full-screen', 'copy-document', 'mic', 'stopwatch', 'medal-1', 'medal', 'trophy', 'trophy-1', 'first-aid-kit', 'discover', 'place', 'location', 'location-outline', 'location-information', 'add-location', 'delete-location', 'map-location', 'alarm-clock', 'timer', 'watch-1', 'watch', 'lock', 'unlock', 'key', 'service', 'mobile-phone', 'bicycle', 'truck', 'ship', 'basketball', 'football', 'soccer', 'baseball', 'wind-power', 'light-rain', 'lightning', 'heavy-rain', 'sunrise', 'sunrise-1', 'sunset', 'sunny', 'cloudy', 'partly-cloudy', 'cloudy-and-sunny', 'moon', 'moon-night', 'dish', 'dish-1', 'food', 'chicken', 'fork-spoon', 'knife-fork', 'burger', 'tableware', 'sugar', 'dessert', 'ice-cream', 'hot-water', 'water-cup', 'coffee-cup', 'cold-drink', 'goblet', 'goblet-full', 'goblet-square', 'goblet-square-full', 'refrigerator', 'grape', 'watermelon', 'cherry', 'apple', 'pear', 'orange', 'coffee', 'ice-tea', 'ice-drink', 'milk-tea', 'potato-strips', 'lollipop', 'ice-cream-square', 'ice-cream-round'];
|
||||
|
||||
$options = self::options();
|
||||
|
||||
foreach ($icons as $icon) {
|
||||
$icon = 'el-icon-' . $icon;
|
||||
|
||||
$options->add(htmlspecialchars(sprintf('<i class=\"%s\"></i> %s', $icon, $icon)), $icon);
|
||||
}
|
||||
|
||||
return $options->render();
|
||||
}
|
||||
}
|
67
catch/permissions/tables/forms/Role.php
Normal file
67
catch/permissions/tables/forms/Role.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables\forms;
|
||||
|
||||
use catchAdmin\permissions\model\Department as DepartmentModel;
|
||||
use catchAdmin\permissions\model\Permissions;
|
||||
use catchAdmin\permissions\model\Roles;
|
||||
use catcher\library\form\Form;
|
||||
|
||||
class Role extends Form
|
||||
{
|
||||
public function fields(): array
|
||||
{
|
||||
// TODO: Implement fields() method.
|
||||
return [
|
||||
Form::cascader('parent_id', '上级角色', [])->options(
|
||||
Roles::field(['id', 'parent_id', 'role_name'])->select()->toTree()
|
||||
)->clearable(true)->filterable(true)->props([
|
||||
'props' => [
|
||||
'value' => 'id',
|
||||
'label' => 'role_name',
|
||||
'checkStrictly' => true
|
||||
],
|
||||
])->style(['width' => '100%']),
|
||||
|
||||
self::input('role_name', '角色名称')->required()
|
||||
->clearable(true)->placeholder('请填写角色名称'),
|
||||
|
||||
self::input('identify', '角色标识')
|
||||
->clearable(true)->required()
|
||||
->placeholder('请填写角色标识'),
|
||||
|
||||
self::textarea('description', '角色描述')
|
||||
->clearable(true)->placeholder('请填写角色描述'),
|
||||
|
||||
self::tree('_permissions', '角色权限', [])
|
||||
->props(self::props('permission_name', 'id', [],
|
||||
Permissions::field(['id', 'parent_id', 'permission_name'])->select()->toTree()
|
||||
))
|
||||
->required(),
|
||||
|
||||
self::select('data_range', '数据权限')
|
||||
->placeholder('请选择数据权限')
|
||||
->options(
|
||||
self::options()->add('请选择数据权限', 0)
|
||||
->add('全部数据权限', Roles::ALL_DATA)
|
||||
->add('自定义数据权限', Roles::SELF_CHOOSE)
|
||||
->add('仅本人数据权限', Roles::SELF_DATA)
|
||||
->add('本部门数据权限', Roles::DEPARTMENT_DATA)
|
||||
->add('部门以及以下数据权限', Roles::DEPARTMENT_DOWN_DATA)
|
||||
->render()
|
||||
)->style(['width' => '100%'])
|
||||
->appendControl(Roles::SELF_CHOOSE, [
|
||||
self::cascader('departments', '自定义权限')
|
||||
->options(
|
||||
DepartmentModel::field(['id', 'parent_id', 'department_name'])->select()->toTree()
|
||||
)
|
||||
->props(self::props('department_name', 'id', [
|
||||
'multiple' => true,
|
||||
'emitPath' => false
|
||||
]))
|
||||
->showAllLevels(false)
|
||||
->style(['width' => '100%']),
|
||||
])
|
||||
];
|
||||
}
|
||||
|
||||
}
|
42
catch/permissions/tables/forms/User.php
Normal file
42
catch/permissions/tables/forms/User.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
namespace catchAdmin\permissions\tables\forms;
|
||||
|
||||
use catchAdmin\permissions\model\Department as DepartmentModel;
|
||||
use catchAdmin\permissions\model\Job;
|
||||
use catchAdmin\permissions\model\Roles;
|
||||
use catcher\library\form\Form;
|
||||
|
||||
class User extends Form
|
||||
{
|
||||
public function fields(): array
|
||||
{
|
||||
// TODO: Implement fields() method.
|
||||
return [
|
||||
self::input('username', '昵称')->col(self::col(12))->clearable(true)->required(),
|
||||
|
||||
self::cascader('department_id', '部门', [])
|
||||
->col(self::col(12))
|
||||
->options(
|
||||
DepartmentModel::field(['id', 'parent_id', 'department_name'])->select()->toTree()
|
||||
)
|
||||
->props(self::props('department_name', 'id', [
|
||||
'checkStrictly' => true
|
||||
]))->clearable(true),
|
||||
|
||||
self::email('email', '邮箱')->col(self::col(12))->required()->clearable(true),
|
||||
|
||||
self::selectMultiple('jobs', '岗位', [])
|
||||
->col(self::col(12))->options(
|
||||
Job::where('status', Job::ENABLE)->field(['id as value', 'job_name as label'])->select()->toArray()
|
||||
)->clearable(true)->filterable(true),
|
||||
|
||||
self::input('password', '密码')->col(self::col(12))
|
||||
->placeholder('请输入密码')->clearable(true),
|
||||
|
||||
self::tree('roles', '角色', [])
|
||||
->props(self::props('role_name', 'id', [], Roles::field(['id', 'parent_id', 'role_name'])->select()->toTree()))
|
||||
->required(),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@@ -9,6 +9,8 @@
|
||||
// | Author: JaguarJack [ njphper@gmail.com ]
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
/* @var think\Route $router */
|
||||
|
||||
// you should use `$router`
|
||||
$router->group('sms', function () use ($router){
|
||||
// config路由
|
||||
|
@@ -4,8 +4,6 @@ namespace catchAdmin\system\controller;
|
||||
use catcher\base\CatchController;
|
||||
use catcher\CatchResponse;
|
||||
use catchAdmin\system\model\Attachments as AttachmentsModel;
|
||||
use catcher\Utils;
|
||||
use catcher\facade\FileSystem;
|
||||
|
||||
class Attachments extends CatchController
|
||||
{
|
||||
@@ -35,22 +33,6 @@ class Attachments extends CatchController
|
||||
*/
|
||||
public function delete($id, AttachmentsModel $model)
|
||||
{
|
||||
$attachments = $model->whereIn('id', Utils::stringToArrayBy($id))->select();
|
||||
|
||||
if ($model->deleteBy($id)) {
|
||||
foreach ($attachments as $attachment) {
|
||||
if ($attachment->driver == 'local') {
|
||||
$localPath = config('filesystem.disks.local.root') . DIRECTORY_SEPARATOR;
|
||||
$path = $localPath . str_replace('\\','\/', $attachment->path);
|
||||
if (FileSystem::exists($path)) {
|
||||
Filesystem::delete($path);
|
||||
}
|
||||
} else {
|
||||
Filesystem::delete($attachment->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CatchResponse::success();
|
||||
return CatchResponse::success($model->deletes($id));
|
||||
}
|
||||
}
|
||||
|
105
catch/system/controller/Excel.php
Normal file
105
catch/system/controller/Excel.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
namespace catchAdmin\system\controller;
|
||||
|
||||
use catcher\base\CatchController;
|
||||
use catcher\CatchResponse;
|
||||
use think\Request;
|
||||
|
||||
class Excel extends CatchController
|
||||
{
|
||||
/**
|
||||
* 导出
|
||||
*
|
||||
* @time 2021年04月22日
|
||||
* @param Request $request
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function export(Request $request): \think\response\Json
|
||||
{
|
||||
$fields = $this->resetFields(\json_decode($request->post('fields'), true));
|
||||
|
||||
$excel = app()->make($request->post('model'))
|
||||
->field(array_column($fields, 'field'))
|
||||
->select()
|
||||
->each(function (&$item, $key) use ($fields) {
|
||||
foreach ($fields as $field) {
|
||||
if (isset($field['options']) && count($field['options'])) {
|
||||
$options = $this->valueToLabel($field['options']);
|
||||
|
||||
$item[$field['field']] = $options[$item[$field['field']]] ?? '';
|
||||
}
|
||||
}
|
||||
})->export(array_column($fields, 'name'));
|
||||
|
||||
return CatchResponse::success($excel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入
|
||||
*
|
||||
* @time 2021年04月23日
|
||||
* @param Request $request
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function import(Request $request): \think\response\Json
|
||||
{
|
||||
return CatchResponse::success(app()->make($request->post('model'))
|
||||
->import(
|
||||
\json_decode($request->post('fields'), 'field'),
|
||||
$request->file('file')
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* value => label
|
||||
*
|
||||
* @time 2021年04月22日
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function valueToLabel(array $options): array
|
||||
{
|
||||
$p = [];
|
||||
foreach ($options as $option) {
|
||||
$p[$option['value']] = $option['label'];
|
||||
}
|
||||
|
||||
return $p;
|
||||
}
|
||||
|
||||
/**
|
||||
*label => value
|
||||
*
|
||||
* @time 2021年04月22日
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function labelToValue(array $options): array
|
||||
{
|
||||
$p = [];
|
||||
foreach ($options as $option) {
|
||||
$p[$option['label']] = $option['value'];
|
||||
}
|
||||
|
||||
return $p;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重组 fields
|
||||
*
|
||||
* @time 2021年04月22日
|
||||
* @param array $fields
|
||||
* @return array
|
||||
*/
|
||||
protected function resetFields(array $fields): array
|
||||
{
|
||||
$f = [];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$f[$field['field']] = $field;
|
||||
}
|
||||
|
||||
return $f;
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@ namespace catchAdmin\system\controller;
|
||||
|
||||
use catcher\base\CatchController;
|
||||
use catcher\CatchResponse;
|
||||
use catcher\generate\CreateModule;
|
||||
use catcher\generate\Generator;
|
||||
use think\Request;
|
||||
|
||||
@@ -25,4 +26,10 @@ class Generate extends CatchController
|
||||
{
|
||||
return CatchResponse::success($generator->preview($request->param()));
|
||||
}
|
||||
|
||||
|
||||
public function createModule(Request $request, CreateModule $module)
|
||||
{
|
||||
return CatchResponse::success($module->generate($request->post()));
|
||||
}
|
||||
}
|
||||
|
@@ -17,12 +17,12 @@ class Module extends CatchController
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function index()
|
||||
public function index(): Json
|
||||
{
|
||||
$modules = [];
|
||||
|
||||
foreach(CatchAdmin::getModulesDirectory() as $d) {
|
||||
$modules[] = json_decode(file_get_contents($d . 'module.json'), true);
|
||||
$modules[] = CatchAdmin::getModuleInfo($d);
|
||||
}
|
||||
|
||||
$hasModules = array_unique(Permissions::whereIn('id', request()->user()->getPermissionsBy())->column('module'));
|
||||
@@ -51,7 +51,7 @@ class Module extends CatchController
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
*/
|
||||
public function disOrEnable(string $module)
|
||||
public function disOrEnable(string $module): Json
|
||||
{
|
||||
$moduleInfo = CatchAdmin::getModuleInfo(CatchAdmin::directory() . $module);
|
||||
|
||||
@@ -71,7 +71,7 @@ class Module extends CatchController
|
||||
* @time 2020年09月21日
|
||||
* @return Json
|
||||
*/
|
||||
public function cache()
|
||||
public function cache(): Json
|
||||
{
|
||||
return CatchResponse::success(CatchAdmin::cacheServices());
|
||||
}
|
||||
@@ -82,7 +82,7 @@ class Module extends CatchController
|
||||
* @time 2020年09月21日
|
||||
* @return Json
|
||||
*/
|
||||
public function clear()
|
||||
public function clear(): Json
|
||||
{
|
||||
return !file_exists(CatchAdmin::getCacheServicesFile()) ?
|
||||
CatchResponse::fail('模块没有缓存') :
|
||||
|
@@ -15,6 +15,7 @@ use catcher\base\CatchController;
|
||||
use catcher\base\CatchRequest;
|
||||
use catcher\CatchResponse;
|
||||
use catcher\CatchUpload;
|
||||
use catcher\exceptions\FailedException;
|
||||
|
||||
class Upload extends CatchController
|
||||
{
|
||||
@@ -37,6 +38,10 @@ class Upload extends CatchController
|
||||
{
|
||||
$images = $request->file();
|
||||
|
||||
if (!$images) {
|
||||
throw new FailedException('请选择图片上传');
|
||||
}
|
||||
|
||||
return CatchResponse::success($upload->checkImages($images)->multiUpload($images['image']));
|
||||
}
|
||||
|
||||
|
@@ -746,28 +746,7 @@ class SystemMenusSeed extends Seeder
|
||||
'deleted_at' => 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
9 =>
|
||||
array (
|
||||
'id' => 116,
|
||||
'permission_name' => '表单构建',
|
||||
'parent_id' => 38,
|
||||
'level' => '38',
|
||||
'route' => '/system/form',
|
||||
'icon' => 'el-icon-knife-fork',
|
||||
'module' => 'system',
|
||||
'creator_id' => 1,
|
||||
'permission_mark' => 'form',
|
||||
'component' => 'form',
|
||||
'redirect' => '',
|
||||
'keepalive' => 1,
|
||||
'type' => 1,
|
||||
'hidden' => 1,
|
||||
'sort' => 1,
|
||||
'created_at' => 1600648935,
|
||||
'updated_at' => 1600648935,
|
||||
'deleted_at' => 0,
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@@ -3,8 +3,10 @@ namespace catchAdmin\system\model;
|
||||
|
||||
use catchAdmin\system\model\search\AttachmentsSearch;
|
||||
use catcher\base\CatchModel;
|
||||
use catcher\Utils;
|
||||
use think\file\UploadedFile;
|
||||
use think\Model;
|
||||
use think\facade\Filesystem;
|
||||
|
||||
class Attachments extends CatchModel
|
||||
{
|
||||
@@ -54,4 +56,37 @@ class Attachments extends CatchModel
|
||||
'path' => $data['path']
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @time 2021年03月01日
|
||||
* @param $id
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @return bool
|
||||
*/
|
||||
public function deletes($id): bool
|
||||
{
|
||||
Utils::setFilesystemConfig();
|
||||
|
||||
$this->whereIn('id', Utils::stringToArrayBy($id))
|
||||
->select()
|
||||
->each(function ($attachment){
|
||||
if ($attachment->delete()) {
|
||||
if ($attachment->driver == 'local') {
|
||||
$localPath = config('filesystem.disks.local.root') . DIRECTORY_SEPARATOR;
|
||||
$path = $localPath . str_replace('\\','\/', $attachment->path);
|
||||
if (file_exists($path)) {
|
||||
Filesystem::delete($path);
|
||||
}
|
||||
} else {
|
||||
Filesystem::delete($attachment->path);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -66,15 +66,13 @@ class Config extends CatchModel
|
||||
$config = [];
|
||||
foreach ($data as $key => $item) {
|
||||
foreach ($item as $k => $value) {
|
||||
if ($value) {
|
||||
$config[$key . '.' .$k] = [
|
||||
'pid' => $parentConfig['id'],
|
||||
'key' => $key . '.' . $k,
|
||||
'value' => $value,
|
||||
'created_at' => time(),
|
||||
'updated_at' => time(),
|
||||
];
|
||||
}
|
||||
$config[$key . '.' .$k] = [
|
||||
'pid' => $parentConfig['id'],
|
||||
'key' => $key . '.' . $k,
|
||||
'value' => $value,
|
||||
'created_at' => time(),
|
||||
'updated_at' => time(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,6 @@ class OperateLog extends \think\Model
|
||||
use BaseOptionsTrait;
|
||||
use OperateLogSearch;
|
||||
|
||||
|
||||
protected $name = 'operate_log';
|
||||
|
||||
protected $field = [
|
||||
@@ -42,4 +41,9 @@ class OperateLog extends \think\Model
|
||||
->order($this->aliasField('id'), 'desc')
|
||||
->paginate();
|
||||
}
|
||||
|
||||
protected function getCreatedAtAttr($value)
|
||||
{
|
||||
return date('Y-m-d H:i:s', $value);
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,6 @@ trait DeveloperSearch
|
||||
|
||||
public function searchStatusAttr($query, $value, $data)
|
||||
{
|
||||
return $query->where('driver', $value);
|
||||
return $query->where('status', $value);
|
||||
}
|
||||
}
|
@@ -1,4 +1,7 @@
|
||||
<?php
|
||||
|
||||
/* @var think\Route $router */
|
||||
|
||||
$router->group(function () use ($router) {
|
||||
// 登录日志
|
||||
$router->get('log/login', '\catchAdmin\system\controller\LoginLog@list');
|
||||
@@ -15,8 +18,10 @@ $router->group(function () use ($router) {
|
||||
$router->post('table/backup', '\catchAdmin\system\controller\DataDictionary@backup');
|
||||
|
||||
// 上传
|
||||
$router->post('upload/image', '\catchAdmin\system\controller\Upload@image');
|
||||
$router->post('upload/file', '\catchAdmin\system\controller\Upload@file');
|
||||
$router->group('upload', function () use ($router){
|
||||
$router->post('image', '\catchAdmin\system\controller\Upload@image');
|
||||
$router->post('file', '\catchAdmin\system\controller\Upload@file');
|
||||
})->middleware(\catcher\middlewares\JsonResponseMiddleware::class);
|
||||
|
||||
// 附件
|
||||
$router->resource('attachments', '\catchAdmin\system\controller\Attachments');
|
||||
@@ -28,6 +33,7 @@ $router->group(function () use ($router) {
|
||||
// 代码生成
|
||||
$router->post('generate', '\catchAdmin\system\controller\Generate@save');
|
||||
$router->post('generate/preview', '\catchAdmin\system\controller\Generate@preview'); // 预览
|
||||
$router->post('generate/create/module', '\catchAdmin\system\controller\Generate@createModule'); // 创建模块
|
||||
|
||||
// 敏感词
|
||||
$router->resource('sensitive/word', '\catchAdmin\system\controller\SensitiveWord');
|
||||
@@ -43,6 +49,17 @@ $router->group(function () use ($router) {
|
||||
$router->put('cache/modules', '\catchAdmin\system\controller\Module@cache');
|
||||
$router->delete('clear/modules', '\catchAdmin\system\controller\Module@clear');
|
||||
|
||||
// excel 导入&导出通用
|
||||
$router->post('excel/export', '\catchAdmin\system\controller\Excel@export');
|
||||
$router->post('excel/import', '\catchAdmin\system\controller\Excel@import');
|
||||
|
||||
})->middleware('auth');
|
||||
|
||||
// 获取 table
|
||||
$router->get('table/<module>/<tableClass>', function ($module, $tableClass){
|
||||
$table = sprintf('\\catchAdmin\\%s\\tables\\%s', $module, ucfirst($tableClass));
|
||||
|
||||
return (new $table)->render(request()->param('only'));
|
||||
});
|
||||
|
||||
|
||||
|
46
catch/system/tables/Database.php
Normal file
46
catch/system/tables/Database.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace catchAdmin\system\tables;
|
||||
|
||||
use catcher\CatchTable;
|
||||
use catcher\library\table\Actions;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
|
||||
|
||||
class Database extends CatchTable
|
||||
{
|
||||
protected function form()
|
||||
{
|
||||
// TODO: Implement form() method.
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function table()
|
||||
{
|
||||
// TODO: Implement table() method.
|
||||
return $this->getTable('database')
|
||||
->header([
|
||||
HeaderItem::label('表名')->prop('name'),
|
||||
HeaderItem::label('引擎')->prop('engine'),
|
||||
HeaderItem::label('字符集')->prop('collation'),
|
||||
HeaderItem::label('数据行数')->prop('rows'),
|
||||
HeaderItem::label('数据大小')->prop('data_length'),
|
||||
|
||||
HeaderItem::label('索引大小')->prop('index_length'),
|
||||
HeaderItem::label('注释')->prop('comment'),
|
||||
HeaderItem::label('创建时间')->prop('create_time'),
|
||||
HeaderItem::label('操作')->actions([
|
||||
Actions::view()
|
||||
]),
|
||||
])
|
||||
->withApiRoute('tables')
|
||||
->withSearch([
|
||||
Search::text('tablename', '请输入表名'),
|
||||
Search::select('engine', '请选择引擎', [
|
||||
['label' => 'MyISAM', 'value' => 'MyISAM'],
|
||||
['label' => 'InnoDB', 'value' => 'InnoDB']
|
||||
])
|
||||
])
|
||||
->render();
|
||||
}
|
||||
}
|
40
catch/system/tables/LoginLog.php
Normal file
40
catch/system/tables/LoginLog.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
namespace catchAdmin\system\tables;
|
||||
|
||||
use catchAdmin\system\tables\forms\Factory;
|
||||
use catcher\CatchTable;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
|
||||
|
||||
class LoginLog extends CatchTable
|
||||
{
|
||||
protected function form()
|
||||
{
|
||||
// TODO: Implement form() method.
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function table()
|
||||
{
|
||||
// TODO: Implement table() method.
|
||||
return $this->getTable('loginLog')
|
||||
->header([
|
||||
HeaderItem::label()->selection(),
|
||||
HeaderItem::label('登陆用户')->prop('login_name'),
|
||||
HeaderItem::label('登陆IP')->prop('login_ip'),
|
||||
HeaderItem::label('客户端')->prop('browser'),
|
||||
HeaderItem::label('系统')->prop('os'),
|
||||
HeaderItem::label('登陆状态')->prop('status')->component('status'),
|
||||
HeaderItem::label('登陆时间')->prop('login_at')->component('loginAt'),
|
||||
])
|
||||
->withApiRoute('log/login')
|
||||
->withSearch([
|
||||
Search::startAt(),
|
||||
Search::label('结束时间')->endAt()
|
||||
])
|
||||
->selectionChange()
|
||||
->render();
|
||||
|
||||
}
|
||||
}
|
46
catch/system/tables/OperateLog.php
Normal file
46
catch/system/tables/OperateLog.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace catchAdmin\system\tables;
|
||||
|
||||
use catcher\CatchTable;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
|
||||
|
||||
class OperateLog extends CatchTable
|
||||
{
|
||||
protected function form()
|
||||
{
|
||||
// TODO: Implement form() method.
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function table()
|
||||
{
|
||||
// TODO: Implement table() method.
|
||||
return $this->getTable('operateLog')
|
||||
->header([
|
||||
HeaderItem::label()->selection(),
|
||||
HeaderItem::label('编号')->prop('id'),
|
||||
HeaderItem::label('操作人')->prop('creator'),
|
||||
HeaderItem::label('操作模块')->prop('module'),
|
||||
HeaderItem::label('操作菜单')->prop('operate'),
|
||||
HeaderItem::label('菜单标识')->prop('route'),
|
||||
HeaderItem::label('请求方式')->prop('method'),
|
||||
HeaderItem::label('参数')->prop('params')->component('params'),
|
||||
])
|
||||
->withApiRoute('log/operate')
|
||||
->withSearch([
|
||||
Search::text('creator', '请输入操作人'),
|
||||
Search::text('module', '请输入模块'),
|
||||
Search::select('method', '请选择请求方法', [
|
||||
['label' => 'GET', 'value' => 'GET'],
|
||||
['label' => 'POST', 'value' => 'POST'],
|
||||
['label' => 'PUT', 'value' => 'PUT'],
|
||||
['label' => 'DELETE', 'value' => 'DELETE'],
|
||||
])
|
||||
])
|
||||
->selectionChange()
|
||||
->render();
|
||||
|
||||
}
|
||||
}
|
45
catch/system/tables/SensitiveWord.php
Normal file
45
catch/system/tables/SensitiveWord.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace catchAdmin\system\tables;
|
||||
|
||||
use catchAdmin\system\tables\forms\Factory;
|
||||
use catcher\CatchTable;
|
||||
use catcher\library\table\Actions;
|
||||
use catcher\library\table\HeaderItem;
|
||||
use catcher\library\table\Search;
|
||||
|
||||
class SensitiveWord extends CatchTable
|
||||
{
|
||||
protected function form()
|
||||
{
|
||||
// TODO: Implement form() method.
|
||||
return Factory::create('SensitiveWord');
|
||||
}
|
||||
|
||||
protected function table()
|
||||
{
|
||||
// TODO: Implement table() method.
|
||||
return $this->getTable('SensitiveWord')
|
||||
->header([
|
||||
HeaderItem::label()->selection(),
|
||||
HeaderItem::label('编号')->prop('id'),
|
||||
HeaderItem::label('敏感词')->prop('word'),
|
||||
HeaderItem::label('创建人')->prop('creator'),
|
||||
HeaderItem::label('创建时间')->prop('created_at'),
|
||||
HeaderItem::label('更新时间')->prop('updated_at'),
|
||||
HeaderItem::label('操作')->actions([
|
||||
Actions::update(),
|
||||
Actions::delete()
|
||||
])
|
||||
])
|
||||
->withActions([
|
||||
Actions::create()
|
||||
])
|
||||
->withDialogWidth('35%')
|
||||
->withApiRoute('sensitive/word')
|
||||
->withSearch([
|
||||
Search::text('word', '输入敏感词')
|
||||
])
|
||||
->selectionChange()
|
||||
->render();
|
||||
}
|
||||
}
|
12
catch/system/tables/forms/Factory.php
Normal file
12
catch/system/tables/forms/Factory.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace catchAdmin\system\tables\forms;
|
||||
|
||||
use catcher\library\form\FormFactory;
|
||||
|
||||
class Factory extends FormFactory
|
||||
{
|
||||
public static function from(): string
|
||||
{
|
||||
return __NAMESPACE__;
|
||||
}
|
||||
}
|
15
catch/system/tables/forms/SensitiveWord.php
Normal file
15
catch/system/tables/forms/SensitiveWord.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace catchAdmin\system\tables\forms;
|
||||
|
||||
use catchAdmin\permissions\model\Department as DepartmentModel;
|
||||
use catcher\library\form\Form;
|
||||
|
||||
class SensitiveWord extends Form
|
||||
{
|
||||
public function fields(): array
|
||||
{
|
||||
return [
|
||||
Form::input('word', '敏感词')->required()->placeholder('请输入敏感词'),
|
||||
];
|
||||
}
|
||||
}
|
@@ -9,6 +9,8 @@
|
||||
* @license https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt
|
||||
*/
|
||||
|
||||
/* @var think\Route $router */
|
||||
|
||||
$router->group('wechat', function () use ($router){
|
||||
// 公众号粉丝
|
||||
$router->group('official/users', function () use ($router){
|
||||
|
@@ -18,23 +18,27 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"topthink/framework": "6.0.4",
|
||||
"topthink/think-orm": "2.0.33",
|
||||
"topthink/framework": "6.0.6",
|
||||
"topthink/think-orm": "2.0.36",
|
||||
"topthink/think-migration": "^3.0",
|
||||
"thans/tp-jwt-auth": "1.1",
|
||||
"jaguarjack/think-filesystem-cloud": "dev-master",
|
||||
"thans/tp-jwt-auth": "^1.1",
|
||||
"overtrue/wechat": "^4.2",
|
||||
"phpoffice/phpspreadsheet": "^1.12",
|
||||
"dragonmantank/cron-expression": "^3.0",
|
||||
"dragonmantank/cron-expression": "3.1",
|
||||
"symfony/finder": "^4.4",
|
||||
"ext-json": "*",
|
||||
"overtrue/easy-sms": "^1.1",
|
||||
"jaguarjack/migration-generator": "dev-master"
|
||||
"jaguarjack/migration-generator": "dev-master",
|
||||
"lcobucci/jwt": "3.3",
|
||||
"jaguarjack/think-filesystem-cloud": "1.0",
|
||||
"topthink/think-view": "^1.0",
|
||||
"xaboy/form-builder": "~2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"topthink/think-trace":"^1.0",
|
||||
"topthink/think-trace": "^1.0",
|
||||
"symfony/var-dumper": "^5.1",
|
||||
"swoole/ide-helper": "^4.5"
|
||||
"swoole/ide-helper": "^4.5",
|
||||
"nikic/php-parser": "^4.10"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -49,7 +49,7 @@ return [
|
||||
// 是否严格检查字段是否存在
|
||||
'fields_strict' => true,
|
||||
// 是否需要断线重连
|
||||
'break_reconnect' => false,
|
||||
'break_reconnect' => true,
|
||||
// 监听SQL
|
||||
'trigger_sql' => true,
|
||||
// 开启字段缓存
|
||||
|
@@ -1,13 +1,15 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
use think\helper\Arr;
|
||||
use catcher\facade\FileSystem;
|
||||
|
||||
class CatchAdmin
|
||||
{
|
||||
public static $root = 'catch';
|
||||
|
||||
public const VERSION = '2.1.0';
|
||||
public const VERSION = '2.5.0';
|
||||
|
||||
|
||||
/**
|
||||
@@ -20,6 +22,20 @@ class CatchAdmin
|
||||
return app()->getRootPath() . self::$root . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 root
|
||||
*
|
||||
* @time 2021年03月28日
|
||||
* @param $root
|
||||
* @return CatchAdmin
|
||||
*/
|
||||
public static function setRoot($root): CatchAdmin
|
||||
{
|
||||
self::$root = $root;
|
||||
|
||||
return new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建目录
|
||||
*
|
||||
@@ -190,7 +206,7 @@ class CatchAdmin
|
||||
* @time 2020年06月23日
|
||||
* @return array
|
||||
*/
|
||||
public static function getEnabledService()
|
||||
public static function getEnabledService(): array
|
||||
{
|
||||
$services = [];
|
||||
|
||||
@@ -209,94 +225,68 @@ class CatchAdmin
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启模块
|
||||
* 获取模块 Json
|
||||
*
|
||||
* @time 2020年06月23日
|
||||
* @time 2021年02月08日
|
||||
* @param $module
|
||||
* @return bool
|
||||
* @return string
|
||||
*/
|
||||
public static function enableModule($module)
|
||||
public static function getModuleJson($module): string
|
||||
{
|
||||
$moduleJson = self::moduleDirectory($module) . 'module.json';
|
||||
|
||||
if (!file_exists($moduleJson)) {
|
||||
return true;
|
||||
if (is_dir($module)) {
|
||||
return $module . DIRECTORY_SEPARATOR . 'module.json';
|
||||
}
|
||||
|
||||
$info = \json_decode(file_get_contents($moduleJson), true);
|
||||
|
||||
$info['enable'] = true;
|
||||
|
||||
if (!is_writeable($moduleJson)) {
|
||||
chmod($moduleJson, 666);
|
||||
}
|
||||
|
||||
file_put_contents($moduleJson, \json_encode($info, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭模块
|
||||
*
|
||||
* @time 2020年06月23日
|
||||
* @param $module
|
||||
* @return bool
|
||||
*/
|
||||
public static function disableModule($module)
|
||||
{
|
||||
$moduleJson = self::moduleDirectory($module) . 'module.json';
|
||||
|
||||
if (!file_exists($moduleJson)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$info = \json_decode(file_get_contents($moduleJson), true);
|
||||
|
||||
$info['enable'] = false;
|
||||
|
||||
if (!is_writeable($moduleJson)) {
|
||||
chmod($moduleJson, 666);
|
||||
}
|
||||
|
||||
file_put_contents($moduleJson, \json_encode($info, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年11月30日
|
||||
* @return array
|
||||
*/
|
||||
protected static function getModuleViews(): array
|
||||
{
|
||||
$views = [];
|
||||
|
||||
foreach (self::getModulesDirectory() as $module) {
|
||||
if (is_dir($module . 'view')) {
|
||||
$moduleInfo = self::getModuleInfo($module);
|
||||
$moduleName = $moduleInfo['alias'] ?? Arr::last(explode('/', $module));
|
||||
$views[$moduleName] = $module . 'view' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
return $views;
|
||||
return self::moduleDirectory($module) . 'module.json';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模块信息
|
||||
*
|
||||
* @time 2019年11月30日
|
||||
* @time 2021年02月08日
|
||||
* @param $module
|
||||
* @return mixed
|
||||
* @return array
|
||||
*/
|
||||
public static function getModuleInfo($module)
|
||||
public static function getModuleInfo($module): array
|
||||
{
|
||||
if (file_exists($module . DIRECTORY_SEPARATOR . 'module.json')) {
|
||||
return \json_decode(file_get_contents($module. DIRECTORY_SEPARATOR . 'module.json'), true);
|
||||
$moduleJson = self::getModuleJson($module);
|
||||
|
||||
if (!file_exists($moduleJson)) {
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
|
||||
return \json_decode(FileSystem::sharedGet($moduleJson), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新模块信息
|
||||
*
|
||||
* @time 2021年02月08日
|
||||
* @param $module
|
||||
* @param $info
|
||||
* @return bool
|
||||
*/
|
||||
public static function updateModuleInfo($module, $info): bool
|
||||
{
|
||||
$moduleInfo = self::getModuleInfo($module);
|
||||
|
||||
if (!count($moduleInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($moduleInfo as $k => $v) {
|
||||
if (isset($info[$k])) {
|
||||
$moduleInfo[$k] = $info[$k];
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_writeable(self::getModuleJson($module))) {
|
||||
chmod(self::getModuleJson($module), 666);
|
||||
}
|
||||
|
||||
FileSystem::put(self::getModuleJson($module), \json_encode($moduleInfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -319,7 +309,7 @@ class CatchAdmin
|
||||
* @time 2019年11月30日
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getRoutes()
|
||||
public static function getRoutes(): array
|
||||
{
|
||||
if (file_exists(self::getCacheRoutesFile())) {
|
||||
return [self::getCacheRoutesFile()];
|
||||
@@ -328,19 +318,6 @@ class CatchAdmin
|
||||
return self::getModuleRoutes();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年11月30日
|
||||
* @return array|mixed
|
||||
*/
|
||||
public static function getViews()
|
||||
{
|
||||
if (file_exists(self::getCacheViewsFile())) {
|
||||
return self::getCacheViews();
|
||||
}
|
||||
|
||||
return self::getModuleViews();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -388,27 +365,6 @@ class CatchAdmin
|
||||
. var_export(self::getEnabledService(), true) . ';');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年11月30日
|
||||
* @return false|int
|
||||
*/
|
||||
public static function cacheViews()
|
||||
{
|
||||
return file_put_contents(self::getCacheViewsFile(), "<?php\r\n return "
|
||||
. var_export(self::getModuleViews(), true) . ';');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年11月30日
|
||||
* @return mixed
|
||||
*/
|
||||
protected static function getCacheViews()
|
||||
{
|
||||
return include self::getCacheViewsFile();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年11月30日
|
||||
@@ -418,22 +374,13 @@ class CatchAdmin
|
||||
{
|
||||
return include self::getCacheServicesFile();
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @time 2019年11月30日
|
||||
* @return mixed
|
||||
*/
|
||||
protected static function getCacheViewsFile()
|
||||
{
|
||||
return self::cacheDirectory() . 'views.php';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2019年11月30日
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getCacheServicesFile()
|
||||
public static function getCacheServicesFile(): string
|
||||
{
|
||||
return self::cacheDirectory() . 'services.php';
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
use catcher\event\LoadModuleRoutes;
|
||||
@@ -48,7 +50,7 @@ class CatchAdminService extends Service
|
||||
|
||||
$this->app->bind('catch\console', $catchConsole);
|
||||
|
||||
$this->commands($catchConsole->commands());
|
||||
$this->commands($catchConsole->defaultCommands());
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -101,7 +103,10 @@ class CatchAdminService extends Service
|
||||
{
|
||||
$connections = $this->app->config->get('database.connections');
|
||||
|
||||
$connections['mysql']['query'] = CatchQuery::class;
|
||||
// 支持多数据库配置注入 Query
|
||||
foreach ($connections as &$connection) {
|
||||
$connection['query'] = CatchQuery::class;
|
||||
}
|
||||
|
||||
$this->app->config->set([
|
||||
'connections' => $connections
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
use catchAdmin\permissions\model\Users;
|
||||
@@ -6,22 +8,33 @@ use catcher\exceptions\FailedException;
|
||||
use catcher\exceptions\LoginFailedException;
|
||||
use thans\jwt\facade\JWTAuth;
|
||||
use think\facade\Session;
|
||||
use think\helper\Str;
|
||||
|
||||
class CatchAuth
|
||||
{
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected $guard;
|
||||
|
||||
// 默认获取
|
||||
protected $username = 'email';
|
||||
|
||||
// 校验字段
|
||||
protected $password = 'password';
|
||||
|
||||
// 保存用户信息
|
||||
protected $user = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $checkPassword = true;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->auth = config('catch.auth');
|
||||
@@ -51,24 +64,20 @@ class CatchAuth
|
||||
*/
|
||||
public function attempt($condition)
|
||||
{
|
||||
try {
|
||||
$user = $this->authenticate($condition);
|
||||
if (!$user) {
|
||||
throw new LoginFailedException();
|
||||
}
|
||||
if ($user->status == Users::DISABLE) {
|
||||
throw new LoginFailedException('该用户已被禁用|' . $user->username, Code::USER_FORBIDDEN);
|
||||
}
|
||||
$user = $this->authenticate($condition);
|
||||
|
||||
if (!password_verify($condition['password'], $user->password)) {
|
||||
throw new LoginFailedException('登录失败|' . $user->username);
|
||||
}
|
||||
|
||||
return $this->{$this->getDriver()}($user);
|
||||
|
||||
} catch (\Exception $exception) {
|
||||
//
|
||||
if (!$user) {
|
||||
throw new LoginFailedException();
|
||||
}
|
||||
if ($user->status == Users::DISABLE) {
|
||||
throw new LoginFailedException('该用户已被禁用|' . $user->username, Code::USER_FORBIDDEN);
|
||||
}
|
||||
|
||||
if ($this->checkPassword && !password_verify($condition['password'], $user->password)) {
|
||||
throw new LoginFailedException('登录失败|' . $user->username);
|
||||
}
|
||||
|
||||
return $this->{$this->getDriver()}($user);
|
||||
}
|
||||
|
||||
|
||||
@@ -234,8 +243,10 @@ class CatchAuth
|
||||
{
|
||||
$where = [];
|
||||
|
||||
$fields = array_keys(app($this->getProvider()['model'])->getFields());
|
||||
|
||||
foreach ($condition as $field => $value) {
|
||||
if ($field != $this->password) {
|
||||
if (in_array($field, $fields) && $field != $this->password) {
|
||||
$where[$field] = $value;
|
||||
}
|
||||
}
|
||||
@@ -268,4 +279,17 @@ class CatchAuth
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 忽略密码认证
|
||||
*
|
||||
* @time 2021年01月27日
|
||||
* @return $this
|
||||
*/
|
||||
public function ignorePasswordVerify(): CatchAuth
|
||||
{
|
||||
$this->checkPassword = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @filename CacheKeys.php
|
||||
* @createdAt 2020/1/17
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | CatchAdmin [Just Like ~ ]
|
||||
// +----------------------------------------------------------------------
|
||||
@@ -13,7 +15,6 @@ namespace catcher;
|
||||
use catcher\library\Composer;
|
||||
use catcher\facade\FileSystem;
|
||||
use think\App;
|
||||
use think\console\Command;
|
||||
|
||||
class CatchConsole
|
||||
{
|
||||
@@ -34,18 +35,18 @@ class CatchConsole
|
||||
* @time 2020年07月02日
|
||||
* @return array
|
||||
*/
|
||||
public function commands()
|
||||
public function commands(): array
|
||||
{
|
||||
$commandFiles = FileSystem::allFiles($this->path);
|
||||
|
||||
$commands = [];
|
||||
|
||||
/* \Symfony\Component\Finder\SplFileInfo $command */
|
||||
/* \Symfony\Component\Finder\SplFileInfo $command */
|
||||
foreach ($commandFiles as $command) {
|
||||
if ($command->getExtension() === 'php') {
|
||||
$lastPath = str_replace($this->parseNamespace(), '',pathinfo($command, PATHINFO_DIRNAME));
|
||||
$lastPath = str_replace($this->parseNamespace(), '', pathinfo($command->getPathname(), PATHINFO_DIRNAME));
|
||||
$namespace = $this->namespace . str_replace(DIRECTORY_SEPARATOR, '\\', $lastPath) . '\\';
|
||||
$commandClass = $namespace . pathinfo($command, PATHINFO_FILENAME);
|
||||
$commandClass = $namespace . pathinfo($command->getPathname(), PATHINFO_FILENAME);
|
||||
$commands[] = $commandClass;
|
||||
}
|
||||
}
|
||||
@@ -59,20 +60,23 @@ class CatchConsole
|
||||
* @time 2020年07月19日
|
||||
* @return string
|
||||
*/
|
||||
protected function parseNamespace()
|
||||
protected function parseNamespace(): string
|
||||
{
|
||||
// 没有设置 namespace 默认使用 extend 目录
|
||||
if (!$this->namespace) {
|
||||
return root_path(). 'extend';
|
||||
$psr4 = (new Composer)->psr4Autoload();
|
||||
|
||||
if (strpos($this->namespace, '\\') === false) {
|
||||
$rootNamespace = $this->namespace . '\\';
|
||||
} else {
|
||||
$rootNamespace = substr($this->namespace, 0, strpos($this->namespace, '\\') + 1);
|
||||
}
|
||||
|
||||
$psr4 = (new Composer())->psr4Autoload();
|
||||
$path = root_path(). $psr4[$rootNamespace] . DIRECTORY_SEPARATOR;
|
||||
|
||||
$rootNamespace = substr($this->namespace, 0, strpos($this->namespace, '\\') + 1);
|
||||
if (strpos($this->namespace, '\\') !== false) {
|
||||
$path .= str_replace('\\', DIRECTORY_SEPARATOR, substr($this->namespace, strpos($this->namespace, '\\') + 1));
|
||||
}
|
||||
|
||||
return root_path(). $psr4[$rootNamespace] . DIRECTORY_SEPARATOR .
|
||||
|
||||
str_replace('\\', DIRECTORY_SEPARATOR, substr($this->namespace, strpos($this->namespace, '\\') + 1));
|
||||
return rtrim($path, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +86,7 @@ class CatchConsole
|
||||
* @param $path
|
||||
* @return $this
|
||||
*/
|
||||
public function path($path)
|
||||
public function path($path): CatchConsole
|
||||
{
|
||||
$this->path = $path;
|
||||
|
||||
@@ -96,11 +100,40 @@ class CatchConsole
|
||||
* @param $namespace
|
||||
* @return $this
|
||||
*/
|
||||
public function setNamespace($namespace)
|
||||
public function setNamespace($namespace): CatchConsole
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认 commands
|
||||
*
|
||||
* @time 2021年01月24日
|
||||
* @return array
|
||||
*/
|
||||
public function defaultCommands(): array
|
||||
{
|
||||
$defaultCommands = FileSystem::allFiles(__DIR__ . DIRECTORY_SEPARATOR . 'command');
|
||||
|
||||
$commands = [];
|
||||
|
||||
/* \Symfony\Component\Finder\SplFileInfo $command */
|
||||
foreach ($defaultCommands as $command) {
|
||||
if ($command->getExtension() === 'php') {
|
||||
|
||||
$filename = str_replace('.php', '', str_replace(__DIR__, '', $command->getPathname()));
|
||||
|
||||
$class = 'catcher' . str_replace(DIRECTORY_SEPARATOR, '\\', $filename);
|
||||
|
||||
if (class_exists($class)) {
|
||||
$commands[] = $class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
}
|
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
use app\ExceptionHandle;
|
||||
use catcher\exceptions\CatchException;
|
||||
use catcher\exceptions\FailedException;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
use catcher\library\excel\CatchExcel;
|
||||
use catcher\library\excel\Excel;
|
||||
use catcher\library\excel\ExcelContract;
|
||||
use think\facade\Cache;
|
||||
use think\helper\Str;
|
||||
use think\model\Collection;
|
||||
|
||||
class CatchModelCollection extends Collection
|
||||
@@ -18,9 +20,9 @@ class CatchModelCollection extends Collection
|
||||
* @param string $children
|
||||
* @return array
|
||||
*/
|
||||
public function toTree($pid = 0, $pidField = 'parent_id', $children = 'children')
|
||||
public function toTree($pid = 0, $pidField = 'parent_id', $children = 'children'): array
|
||||
{
|
||||
return Tree::done($this->items, $pid, $pidField, $children);
|
||||
return Tree::done($this->toArray(), $pid, $pidField, $children);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +36,7 @@ class CatchModelCollection extends Collection
|
||||
* @throws \PhpOffice\PhpSpreadsheet\Exception
|
||||
* @return mixed|string[]
|
||||
*/
|
||||
public function export($header, $path = '', $disk = 'local')
|
||||
public function export($header, $path = '', $disk = 'local'): array
|
||||
{
|
||||
$excel = new Class($header, $this->items) implements ExcelContract
|
||||
{
|
||||
@@ -79,8 +81,45 @@ class CatchModelCollection extends Collection
|
||||
* @return bool
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException
|
||||
*/
|
||||
public function cache($key, int $ttl = 0, string $store = 'redis')
|
||||
public function cache($key, int $ttl = 0, string $store = 'redis'): bool
|
||||
{
|
||||
return Cache::store($store)->set($key, $this->items, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前级别下的所有子级
|
||||
*
|
||||
* @time 2020年11月04日
|
||||
* @param array $ids
|
||||
* @param string $parentFields
|
||||
* @param string $column
|
||||
* @return array
|
||||
*/
|
||||
public function getAllChildrenIds(array $ids, $parentFields = 'parent_id', $column = 'id'): array
|
||||
{
|
||||
array_walk($ids, function (&$item){
|
||||
$item = intval($item);
|
||||
});
|
||||
|
||||
$childIds = $this->whereIn($parentFields, $ids)->column($column);
|
||||
|
||||
if (!empty($childIds)) {
|
||||
$childIds = array_merge($childIds, $this->getAllChildrenIds($childIds));
|
||||
}
|
||||
|
||||
return $childIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* implode
|
||||
*
|
||||
* @time 2021年02月24日
|
||||
* @param string $separator
|
||||
* @param string $column
|
||||
* @return string
|
||||
*/
|
||||
public function implode(string $column = '', string $separator = ','): string
|
||||
{
|
||||
return implode($separator, $column ? array_column($this->items, $column) : $this->items);
|
||||
}
|
||||
}
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
use catcher\base\CatchModel;
|
||||
@@ -11,7 +13,7 @@ class CatchQuery extends Query
|
||||
/**
|
||||
*
|
||||
* @time 2020年01月13日
|
||||
* @param string $model
|
||||
* @param mixed $model
|
||||
* @param string $joinField
|
||||
* @param string $currentJoinField
|
||||
* @param array $field
|
||||
@@ -19,29 +21,38 @@ class CatchQuery extends Query
|
||||
* @param array $bind
|
||||
* @return CatchQuery
|
||||
*/
|
||||
public function catchJoin(string $model, string $joinField, string $currentJoinField, array $field = [], string $type = 'INNER', array $bind = []): CatchQuery
|
||||
public function catchJoin($model, string $joinField, string $currentJoinField, array $field = [], string $type = 'INNER', array $bind = []): CatchQuery
|
||||
{
|
||||
$table = app($model)->getTable();
|
||||
$tableAlias = null;
|
||||
|
||||
if (is_string($model)) {
|
||||
$table = app($model)->getTable();
|
||||
} else {
|
||||
list($model, $tableAlias) = $model;
|
||||
$table = app($model)->getTable();
|
||||
}
|
||||
|
||||
// 合并字段
|
||||
$this->options['field'] = array_merge($this->options['field'] ?? [], array_map(function ($value) use ($table) {
|
||||
return $table . '.' . $value;
|
||||
$this->options['field'] = array_merge($this->options['field'] ?? [], array_map(function ($value) use ($table, $tableAlias) {
|
||||
return ($tableAlias ? : $table) . '.' . $value;
|
||||
}, $field));
|
||||
|
||||
return $this->join($table, sprintf('%s.%s=%s.%s', $table, $joinField, $this->getAlias(), $currentJoinField), $type, $bind);
|
||||
return $this->join($tableAlias ? sprintf('%s %s', $table, $tableAlias) : $table
|
||||
|
||||
, sprintf('%s.%s=%s.%s', $tableAlias ? $tableAlias : $table, $joinField, $this->getAlias(), $currentJoinField), $type, $bind);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2020年01月13日
|
||||
* @param string $model
|
||||
* @param mixed $model
|
||||
* @param string $joinField
|
||||
* @param string $currentJoinField
|
||||
* @param array $field
|
||||
* @param array $bind
|
||||
* @return CatchQuery
|
||||
*/
|
||||
public function catchLeftJoin(string $model, string $joinField, string $currentJoinField, array $field = [], array $bind = []): CatchQuery
|
||||
public function catchLeftJoin($model, string $joinField, string $currentJoinField, array $field = [], array $bind = []): CatchQuery
|
||||
{
|
||||
return $this->catchJoin($model, $joinField, $currentJoinField, $field,'LEFT', $bind);
|
||||
}
|
||||
@@ -49,14 +60,14 @@ class CatchQuery extends Query
|
||||
/**
|
||||
*
|
||||
* @time 2020年01月13日
|
||||
* @param string $model
|
||||
* @param mixed $model
|
||||
* @param string $joinField
|
||||
* @param string $currentJoinField
|
||||
* @param array $field
|
||||
* @param array $bind
|
||||
* @return CatchQuery
|
||||
*/
|
||||
public function catchRightJoin(string $model, string $joinField, string $currentJoinField, array $field = [], array $bind = []): CatchQuery
|
||||
public function catchRightJoin($model, string $joinField, string $currentJoinField, array $field = [], array $bind = []): CatchQuery
|
||||
{
|
||||
return $this->catchJoin($model, $joinField, $currentJoinField, $field,'RIGHT', $bind);
|
||||
}
|
||||
@@ -118,7 +129,8 @@ class CatchQuery extends Query
|
||||
|
||||
foreach ($params as $field => $value) {
|
||||
$method = 'search' . Str::studly($field) . 'Attr';
|
||||
if ($value && method_exists($this->model, $method)) {
|
||||
// value in [null, '']
|
||||
if ($value !== null && $value !== '' && method_exists($this->model, $method)) {
|
||||
$this->model->$method($this, $value, $params);
|
||||
}
|
||||
}
|
||||
@@ -126,6 +138,60 @@ class CatchQuery extends Query
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速搜索
|
||||
*
|
||||
* @param array $params
|
||||
* @return Query
|
||||
*/
|
||||
public function quickSearch($params = []): Query
|
||||
{
|
||||
$requestParams = \request()->param();
|
||||
|
||||
if (empty($params) && empty($requestParams)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
foreach ($requestParams as $field => $value) {
|
||||
if (isset($params[$field])) {
|
||||
// ['>', value] || value
|
||||
if (is_array($params[$field])) {
|
||||
$this->where($field, $params[$field][0], $params[$field][1]);
|
||||
} else {
|
||||
$this->where($field, $value);
|
||||
}
|
||||
} else {
|
||||
// 区间范围 start_数据库字段 & end_数据库字段
|
||||
$startPos = strpos($field, 'start_');
|
||||
if ($startPos === 0) {
|
||||
$this->where(str_replace('start_','', $field), '>=', strtotime($value));
|
||||
}
|
||||
$endPos = strpos($field, 'end_');
|
||||
if ($endPos === 0) {
|
||||
$this->where(str_replace('end_', '', $field), '>=', strtotime($value));
|
||||
}
|
||||
// 模糊搜索
|
||||
if (Str::contains($field, 'like')) {
|
||||
[$operate, $field] = explode('_', $field);
|
||||
if ($operate === 'like') {
|
||||
$this->whereLike($field, $value);
|
||||
} else if ($operate === '%like') {
|
||||
$this->whereLeftLike($field, $value);
|
||||
} else {
|
||||
$this->whereRightLike($field, $value);
|
||||
}
|
||||
}
|
||||
|
||||
// = 值搜索
|
||||
if ($value || is_numeric($value)) {
|
||||
$this->where($field, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @time 2020年01月13日
|
||||
@@ -166,6 +232,28 @@ class CatchQuery extends Query
|
||||
return parent::whereLike($field, $condition, $logic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @param $condition
|
||||
* @param string $logic
|
||||
* @return Query
|
||||
*/
|
||||
public function whereLeftLike(string $field, $condition, string $logic = 'AND'): Query
|
||||
{
|
||||
return $this->where($field, $condition, $logic, 'left');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @param $condition
|
||||
* @param string $logic
|
||||
* @return Query
|
||||
*/
|
||||
public function whereRightLike(string $field, $condition, string $logic = 'AND'): Query
|
||||
{
|
||||
return $this->where($field, $condition, $logic, 'right');
|
||||
}
|
||||
|
||||
/**
|
||||
* 额外的字段
|
||||
*
|
||||
@@ -211,6 +299,10 @@ class CatchQuery extends Query
|
||||
$this->order($this->getTable() . '.sort', $order);
|
||||
}
|
||||
|
||||
if (in_array('weight', array_keys($this->getFields()))) {
|
||||
$this->order($this->getTable() . '.weight', $order);
|
||||
}
|
||||
|
||||
$this->order($this->getTable() . '.' . $this->getPk(), $order);
|
||||
|
||||
return $this;
|
||||
@@ -230,4 +322,32 @@ class CatchQuery extends Query
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段增加
|
||||
*
|
||||
* @time 2020年11月04日
|
||||
* @param $field
|
||||
* @param int $amount
|
||||
* @throws \think\db\exception\DbException
|
||||
* @return int
|
||||
*/
|
||||
public function increment($field, $amount = 1)
|
||||
{
|
||||
return $this->inc($field, $amount)->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段减少
|
||||
*
|
||||
* @time 2020年11月04日
|
||||
* @param $field
|
||||
* @param int $amount
|
||||
* @throws \think\db\exception\DbException
|
||||
* @return int
|
||||
*/
|
||||
public function decrement($field, $amount = 1)
|
||||
{
|
||||
return $this->dec($field, $amount)->update();
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
use think\Paginator;
|
||||
use think\Response;
|
||||
use think\response\Json;
|
||||
|
||||
class CatchResponse
|
||||
@@ -19,11 +19,11 @@ class CatchResponse
|
||||
*/
|
||||
public static function success($data = [], $msg = 'success', $code = Code::SUCCESS): Json
|
||||
{
|
||||
return json([
|
||||
'code' => $code,
|
||||
'message' => $msg,
|
||||
'data' => $data,
|
||||
]);
|
||||
return json([
|
||||
'code' => $code,
|
||||
'message' => $msg,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,14 +35,14 @@ class CatchResponse
|
||||
*/
|
||||
public static function paginate(Paginator $list)
|
||||
{
|
||||
return json([
|
||||
'code' => Code::SUCCESS,
|
||||
'message' => 'success',
|
||||
'count' => $list->total(),
|
||||
'current' => $list->currentPage(),
|
||||
'limit' => $list->listRows(),
|
||||
'data' => $list->getCollection(),
|
||||
]);
|
||||
return json([
|
||||
'code' => Code::SUCCESS,
|
||||
'message' => 'success',
|
||||
'count' => $list->total(),
|
||||
'current' => $list->currentPage(),
|
||||
'limit' => $list->listRows(),
|
||||
'data' => $list->getCollection(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,9 +55,9 @@ class CatchResponse
|
||||
*/
|
||||
public static function fail($msg = '', $code = Code::FAILED): Json
|
||||
{
|
||||
return json([
|
||||
'code' => $code,
|
||||
'message' => $msg,
|
||||
]);
|
||||
return json([
|
||||
'code' => $code,
|
||||
'message' => $msg,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
45
extend/catcher/CatchTable.php
Normal file
45
extend/catcher/CatchTable.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace catcher;
|
||||
|
||||
use catcher\library\table\Table;
|
||||
|
||||
abstract class CatchTable
|
||||
{
|
||||
abstract protected function table();
|
||||
|
||||
|
||||
abstract protected function form();
|
||||
|
||||
/**
|
||||
* 渲染
|
||||
*
|
||||
* @time 2021年03月29日
|
||||
* @param $only => form || table
|
||||
* @return array|\think\response\Json
|
||||
*/
|
||||
public function render($only)
|
||||
{
|
||||
if ($only) {
|
||||
return CatchResponse::success([
|
||||
$only => $this->{$only}()
|
||||
]);
|
||||
}
|
||||
|
||||
return CatchResponse::success([
|
||||
'table' => $this->table(),
|
||||
'form' => $this->form()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表对象
|
||||
*
|
||||
* @time 2021年03月30日
|
||||
* @param string $tableName
|
||||
* @return Table
|
||||
*/
|
||||
protected function getTable(string $tableName): Table
|
||||
{
|
||||
return new Table($tableName);
|
||||
}
|
||||
}
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
use catchAdmin\system\model\Attachments;
|
||||
@@ -45,11 +47,6 @@ class CatchUpload
|
||||
*/
|
||||
protected $path = '';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->initDriver();
|
||||
}
|
||||
|
||||
/**
|
||||
* upload files
|
||||
*
|
||||
@@ -61,27 +58,47 @@ class CatchUpload
|
||||
*/
|
||||
public function upload(UploadedFile $file): string
|
||||
{
|
||||
$this->initUploadConfig();
|
||||
try {
|
||||
$this->initUploadConfig();
|
||||
|
||||
$path = Filesystem::disk($this->getDriver())->putFile($this->getPath(), $file);
|
||||
$path = Filesystem::disk($this->getDriver())->putFile($this->getPath(), $file);
|
||||
|
||||
if ($path) {
|
||||
if ($path) {
|
||||
|
||||
$url = self::getCloudDomain($this->getDriver()) . '/' . $this->getLocalPath($path);
|
||||
$url = self::getCloudDomain($this->getDriver()) . '/' . $this->getLocalPath($path);
|
||||
|
||||
event('attachment', [
|
||||
'path' => $path,
|
||||
'url' => $url,
|
||||
'driver' => $this->getDriver(),
|
||||
'file' => $file,
|
||||
]);
|
||||
event('attachment', [
|
||||
'path' => $path,
|
||||
'url' => $url,
|
||||
'driver' => $this->getDriver(),
|
||||
'file' => $file,
|
||||
]);
|
||||
|
||||
return $url;
|
||||
return $url;
|
||||
}
|
||||
|
||||
throw new FailedException('Upload Failed, Try Again!');
|
||||
|
||||
} catch (\Exception $exception) {
|
||||
throw new FailedException($exception->getMessage());
|
||||
}
|
||||
|
||||
throw new FailedException('Upload Failed, Try Again!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传到 Local
|
||||
*
|
||||
* @time 2021年04月21日
|
||||
* @param $file
|
||||
* @return string
|
||||
*/
|
||||
public function toLocal($file): string
|
||||
{
|
||||
$path = Filesystem::disk(self::LOCAL)->putFile($this->getPath(), $file);
|
||||
|
||||
return public_path() . $this->getLocalPath($path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 本地路径
|
||||
*
|
||||
@@ -89,7 +106,7 @@ class CatchUpload
|
||||
* @param $path
|
||||
* @return string
|
||||
*/
|
||||
protected function getLocalPath($path)
|
||||
protected function getLocalPath($path): string
|
||||
{
|
||||
if ($this->getDriver() === self::LOCAL) {
|
||||
|
||||
@@ -252,78 +269,9 @@ class CatchUpload
|
||||
* @time 2020年06月01日
|
||||
* @return void
|
||||
*/
|
||||
protected function initUploadConfig()
|
||||
public function initUploadConfig()
|
||||
{
|
||||
$configModel = app(Config::class);
|
||||
|
||||
$upload = $configModel->where('key', 'upload')->find();
|
||||
|
||||
if ($upload) {
|
||||
$disk = app()->config->get('filesystem.disks');
|
||||
|
||||
$uploadConfigs = $configModel->getConfig($upload->id);
|
||||
|
||||
// 重组
|
||||
$_config = [];
|
||||
if (!empty($uploadConfigs)) {
|
||||
foreach ($uploadConfigs as $key => $value) {
|
||||
list($object, $key) = explode('.', $key);
|
||||
$_config[$object][$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_config)) {
|
||||
// 读取上传可配置数据
|
||||
foreach ($_config as $key => &$config) {
|
||||
// $disk[$key]['type'] = $key;
|
||||
// 腾讯云配置处理
|
||||
if (strtolower($key) == 'qcloud') {
|
||||
$config['credentials'] = [
|
||||
'appId' => $config['app_id'] ?? '',
|
||||
'secretKey' => $config['secret_key'] ?? '',
|
||||
'secretId' => $config['secret_id'] ?? '',
|
||||
];
|
||||
$readFromCdn = $config['read_from_cdn'] ?? 0;
|
||||
$config['read_from_cdn'] = intval($readFromCdn) == 1;
|
||||
}
|
||||
// OSS 配置
|
||||
if (strtolower($key) == 'oss') {
|
||||
$isCname = $config['is_cname'] ?? 0;
|
||||
$config['is_cname'] = intval($isCname) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 合并数组
|
||||
array_walk($disk, function (&$item, $key) use ($_config) {
|
||||
if (!in_array($key, ['public', 'local'])) {
|
||||
if ($_config[$key] ?? false) {
|
||||
foreach ($_config[$key] as $k => $value) {
|
||||
$item[$k] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// 重新分配配置
|
||||
app()->config->set([
|
||||
'disk' => $disk,
|
||||
], 'filesystem');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
* @time 2020年09月07日
|
||||
* @return $this
|
||||
*/
|
||||
protected function initDriver()
|
||||
{
|
||||
if ($driver = Utils::config('site.upload')) {
|
||||
$this->driver = $driver;
|
||||
}
|
||||
|
||||
return $this;
|
||||
Utils::setFilesystemConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,11 +290,27 @@ class CatchUpload
|
||||
case CatchUpload::LOCAL:
|
||||
return $driver['domain'];
|
||||
case CatchUpload::OSS:
|
||||
return $driver['end_point'];
|
||||
return self::getOssDomain();
|
||||
case CatchUpload::QCLOUD:
|
||||
return $driver['cdn'];
|
||||
default:
|
||||
throw new FailedException(sprintf('Driver [%s] Not Supported.', $driver));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 OSS Domain
|
||||
*
|
||||
* @time 2021年01月20日
|
||||
* @return mixed|string
|
||||
*/
|
||||
protected static function getOssDomain(): string
|
||||
{
|
||||
$oss = \config('filesystem.disks.oss');
|
||||
if ($oss['is_cname'] === false) {
|
||||
return 'https://' . $oss['bucket'] . '.' . $oss['end_point'];
|
||||
}
|
||||
|
||||
return $oss['end_point'];
|
||||
}
|
||||
}
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
class Code
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | CatchAdmin [Just Like ~ ]
|
||||
// +----------------------------------------------------------------------
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
class Tree
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher;
|
||||
|
||||
use catchAdmin\system\model\Config;
|
||||
@@ -134,6 +136,10 @@ class Utils
|
||||
|
||||
$docComment = (new \ReflectionClass($controller))->getMethod($action)->getDocComment();
|
||||
|
||||
if (! $docComment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strpos($docComment, config('catch.permissions.method_auth_mark')) !== false;
|
||||
}
|
||||
|
||||
@@ -149,6 +155,31 @@ class Utils
|
||||
return \config('database.connections.mysql.prefix');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除表前缀
|
||||
*
|
||||
* @time 2020年12月01日
|
||||
* @param string $table
|
||||
* @return string|string[]
|
||||
*/
|
||||
public static function tableWithoutPrefix(string $table)
|
||||
{
|
||||
return str_replace(self::tablePrefix(), '', $table);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加表前缀
|
||||
*
|
||||
* @time 2020年12月26日
|
||||
* @param string $table
|
||||
* @return string
|
||||
*/
|
||||
public static function tableWithPrefix(string $table)
|
||||
{
|
||||
return Str::contains($table, self::tablePrefix()) ?
|
||||
$table : self::tablePrefix() . $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是超级管理员
|
||||
*
|
||||
@@ -183,4 +214,83 @@ class Utils
|
||||
{
|
||||
return root_path($path ? 'public/'. $path : 'public');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 过滤空字符字段
|
||||
*
|
||||
* @time 2021年01月16日
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
public static function filterEmptyValue($data)
|
||||
{
|
||||
foreach ($data as $k => $v) {
|
||||
if (!$v) {
|
||||
unset($data[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 filesystem config
|
||||
*
|
||||
* @time 2021年03月01日
|
||||
* @return void
|
||||
*/
|
||||
public static function setFilesystemConfig()
|
||||
{
|
||||
$configModel = app(Config::class);
|
||||
|
||||
$upload = $configModel->where('key', 'upload')->find();
|
||||
|
||||
if ($upload) {
|
||||
$disk = app()->config->get('filesystem.disks');
|
||||
|
||||
$uploadConfigs = $configModel->getConfig($upload->component);
|
||||
|
||||
if (!empty($uploadConfigs)) {
|
||||
// 读取上传可配置数据
|
||||
foreach ($uploadConfigs as $key => &$config) {
|
||||
// $disk[$key]['type'] = $key;
|
||||
// 腾讯云配置处理
|
||||
if (strtolower($key) == 'qcloud') {
|
||||
$config['credentials'] = [
|
||||
'appId' => $config['app_id'] ?? '',
|
||||
'secretKey' => $config['secret_key'] ?? '',
|
||||
'secretId' => $config['secret_id'] ?? '',
|
||||
];
|
||||
$readFromCdn = $config['read_from_cdn'] ?? 0;
|
||||
$config['read_from_cdn'] = intval($readFromCdn) == 1;
|
||||
}
|
||||
// OSS 配置
|
||||
if (strtolower($key) == 'oss') {
|
||||
$isCname = $config['is_cname'] ?? 0;
|
||||
$config['is_cname'] = intval($isCname) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 合并数组
|
||||
array_walk($disk, function (&$item, $key) use ($uploadConfigs) {
|
||||
if (!in_array($key, ['public', 'local'])) {
|
||||
if ($uploadConfigs[$key] ?? false) {
|
||||
foreach ($uploadConfigs[$key] as $k => $value) {
|
||||
$item[$k] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$default = Utils::config('site.upload');
|
||||
// 重新分配配置
|
||||
app()->config->set([
|
||||
'default' => $default ? : 'local',
|
||||
'disks' => $disk,
|
||||
], 'filesystem');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\base;
|
||||
|
||||
abstract class CatchController
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | CatchAdmin [Just Like ~ ]
|
||||
// +----------------------------------------------------------------------
|
||||
|
@@ -1,8 +1,11 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\base;
|
||||
|
||||
use catcher\CatchQuery;
|
||||
use catcher\traits\db\BaseOptionsTrait;
|
||||
use catcher\traits\db\RewriteTrait;
|
||||
use catcher\traits\db\TransTrait;
|
||||
use think\model\concern\SoftDelete;
|
||||
use catcher\traits\db\ScopeTrait;
|
||||
@@ -15,7 +18,7 @@ use catcher\traits\db\ScopeTrait;
|
||||
*/
|
||||
abstract class CatchModel extends \think\Model
|
||||
{
|
||||
use SoftDelete, TransTrait, BaseOptionsTrait, ScopeTrait;
|
||||
use SoftDelete, BaseOptionsTrait, ScopeTrait, RewriteTrait;
|
||||
|
||||
protected $createTime = 'created_at';
|
||||
|
||||
@@ -27,10 +30,22 @@ abstract class CatchModel extends \think\Model
|
||||
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
// 分页 Limit
|
||||
public const LIMIT = 10;
|
||||
|
||||
// 开启
|
||||
public const ENABLE = 1;
|
||||
// 禁用
|
||||
public const DISABLE = 2;
|
||||
|
||||
/**
|
||||
* 是否有 field
|
||||
*
|
||||
* @time 2020年11月23日
|
||||
* @param string $field
|
||||
* @return bool
|
||||
*/
|
||||
public function hasField(string $field)
|
||||
{
|
||||
return property_exists($this, 'field') && in_array($field, $this->field);
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @filename CatchRepository.php
|
||||
* @createdAt 2020/6/21
|
||||
|
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\base;
|
||||
|
||||
use app\Request;
|
||||
use catcher\exceptions\FailedException;
|
||||
use catcher\exceptions\ValidateFailedException;
|
||||
use think\App;
|
||||
use catcher\Utils;
|
||||
|
||||
class CatchRequest extends Request
|
||||
{
|
||||
@@ -87,4 +89,22 @@ class CatchRequest extends Request
|
||||
return parent::post($name, $default, $filter); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤空字段
|
||||
*
|
||||
* @time 2021年01月16日
|
||||
* @return $this
|
||||
*/
|
||||
public function filterEmptyField(): CatchRequest
|
||||
{
|
||||
if ($this->isGet()) {
|
||||
$this->get = Utils::filterEmptyValue($this->get);
|
||||
} elseif ($this->isPost()) {
|
||||
$this->post = Utils::filterEmptyValue($this->post);
|
||||
} else {
|
||||
$this->put = Utils::filterEmptyValue($this->put);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\base;
|
||||
|
||||
use think\Validate;
|
||||
|
@@ -178,9 +178,14 @@ class CreateModuleCommand extends Command
|
||||
{
|
||||
$moduleJson = FileSystem::sharedGet(__DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'module.stub');
|
||||
|
||||
$content = str_replace(['{NAME}','{DESCRIPTION}','{MODULE}', '{SERVICE}'],
|
||||
[$this->name, $this->description,
|
||||
$this->module, '\\\\'. str_replace('\\', '\\\\',$this->namespaces . ucfirst($this->module) . 'Service')], $moduleJson);
|
||||
$content = str_replace(['{NAME}','{DESCRIPTION}','{MODULE}', '{SERVICE}', '{KEYWORDS}'],
|
||||
[
|
||||
$this->name, $this->description,
|
||||
$this->module,
|
||||
'\\\\'. str_replace('\\', '\\\\',
|
||||
$this->namespaces . ucfirst($this->module) . 'Service'),
|
||||
''
|
||||
], $moduleJson);
|
||||
|
||||
FileSystem::put($this->moduleDir . 'module.json', $content);
|
||||
}
|
||||
|
@@ -3,16 +3,11 @@ declare (strict_types = 1);
|
||||
|
||||
namespace catcher\command\Tools;
|
||||
|
||||
use catcher\CatchAdmin;
|
||||
use catcher\facade\FileSystem;
|
||||
use catcher\library\BackUpDatabase;
|
||||
use catcher\library\Zip;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Argument;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use think\facade\Db;
|
||||
|
||||
class BackupCommand extends Command
|
||||
{
|
||||
|
34
extend/catcher/command/Tools/InitRootCommand.php
Normal file
34
extend/catcher/command/Tools/InitRootCommand.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace catcher\command\Tools;
|
||||
|
||||
use catchAdmin\permissions\model\Users;
|
||||
use catcher\library\BackUpDatabase;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Argument;
|
||||
use think\console\Output;
|
||||
|
||||
class InitRootCommand extends Command
|
||||
{
|
||||
protected $table;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
// 指令配置
|
||||
$this->setName('catch:initAdmin')
|
||||
->setDescription('backup data you need');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
if ($user = Users::where('id', config('catch.permissions.super_admin_id'))->find()) {
|
||||
|
||||
$user->password = 'catchadmin';
|
||||
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
}
|
167
extend/catcher/command/Tools/RegionCommand.php
Normal file
167
extend/catcher/command/Tools/RegionCommand.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace catcher\command\Tools;
|
||||
|
||||
use catcher\facade\FileSystem;
|
||||
use catcher\generate\support\Table;
|
||||
use catcher\generate\support\TableColumn;
|
||||
use catcher\library\Compress;
|
||||
use catcher\library\ProgressBar;
|
||||
use catcher\library\Zip;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Argument;
|
||||
use think\console\Output;
|
||||
use think\facade\Db;
|
||||
|
||||
class RegionCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
// 指令配置
|
||||
$this->setName('region')
|
||||
->addOption('rollback', '-r', Argument::REQUIRED, '删除 Region')
|
||||
->setDescription('create region data');
|
||||
}
|
||||
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
if ($input->hasOption('rollback')) {
|
||||
$this->deleteRegion();
|
||||
} else {
|
||||
|
||||
$output->info('start create region');
|
||||
|
||||
$this->createRegion();
|
||||
|
||||
$output->info('create region successfully');
|
||||
|
||||
$this->importRegionData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function createRegion()
|
||||
{
|
||||
$table = new Table('region');
|
||||
|
||||
if ($table::exist()) {
|
||||
$this->output->error('table [region] has existed!');
|
||||
exit;
|
||||
}
|
||||
|
||||
if (! $table::create('id', 'InnoDB', '地区表')) {
|
||||
$this->output->error('table [region] create failed!');
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$column = new TableColumn();
|
||||
|
||||
$table::addColumn($column->int('parent_id', 10)->setDefault(0)->setComment('父级'));
|
||||
$table::addColumn($column->tinyint('level', 1)->setDefault(1)->setComment('等级'));
|
||||
$table::addColumn($column->varchar('name', 50)->setDefault('')->setComment('地区名称'));
|
||||
$table::addColumn($column->varchar('initial', 100)->setDefault('')->setComment('首字母'));
|
||||
$table::addColumn($column->varchar('pinyin', 100)->setDefault('')->setComment('拼音'));
|
||||
$table::addColumn($column->varchar('city_code', 100)->setDefault('')->setComment('城市编码'));
|
||||
$table::addColumn($column->varchar('ad_code', 100)->setDefault('')->setComment('区域编码'));
|
||||
$table::addColumn($column->varchar('lng_lat', 500)->setDefault('')->setComment('中心经纬度'));
|
||||
|
||||
$table::addIndex(['level']);
|
||||
}
|
||||
|
||||
|
||||
protected function deleteRegion()
|
||||
{
|
||||
$table = new Table('region');
|
||||
|
||||
if (! $table::drop()) {
|
||||
$this->output->error('table [region] drop failed!');
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->output->info('table [region] has deleted!');
|
||||
}
|
||||
|
||||
protected function importRegionData()
|
||||
{
|
||||
try {
|
||||
$compress = new Compress();
|
||||
|
||||
$this->output->info('start downloading');
|
||||
|
||||
$regionZip = runtime_path() . DIRECTORY_SEPARATOR . 'region.zip';
|
||||
$regionJson = runtime_path() .DIRECTORY_SEPARATOR . 'region.json';
|
||||
|
||||
$compress->savePath($regionZip)
|
||||
->download('http://json.think-region.yupoxiong.com/region.json.zip');
|
||||
|
||||
if (!FileSystem::exists($regionZip)) {
|
||||
$this->output->error('import failed! Json data download failed');
|
||||
}
|
||||
|
||||
(new Zip)->make($regionZip, \ZipArchive::CREATE)
|
||||
->extractTo(runtime_path())->close();
|
||||
|
||||
$region = \json_decode(file_get_contents($regionJson, true));
|
||||
|
||||
|
||||
$this->output->info('start import region data');
|
||||
|
||||
|
||||
Db::startTrans();
|
||||
|
||||
$data = [];
|
||||
|
||||
$total = count($region);
|
||||
|
||||
$bar = new ProgressBar($this->output, $total);
|
||||
$bar->start();
|
||||
foreach ($region as $k => $r) {
|
||||
|
||||
$data[] = [
|
||||
'id' => $r->id,
|
||||
'parent_id' => $r->parent_id,
|
||||
'level' => $r->level,
|
||||
'name' => $r->name,
|
||||
'initial' => $r->initial,
|
||||
'pinyin' => $r->pinyin,
|
||||
'city_code' => $r->citycode,
|
||||
'ad_code' => $r->adcode,
|
||||
'lng_lat' => $r->lng_lat,
|
||||
];
|
||||
|
||||
|
||||
if (count($data) >= 500) {
|
||||
if (!Db::name('region')->insertAll($data)) {
|
||||
Db::rollback();
|
||||
break;
|
||||
}
|
||||
$data = [];
|
||||
$bar->advance(500);
|
||||
}
|
||||
|
||||
if ($total == $k+1) {
|
||||
if (!Db::name('region')->insertAll($data)) {
|
||||
Db::rollback();
|
||||
break;
|
||||
}
|
||||
$bar->advance(count($data));
|
||||
}
|
||||
}
|
||||
|
||||
$bar->finished();
|
||||
Db::commit();
|
||||
|
||||
unlink($regionZip);
|
||||
unlink($regionJson);
|
||||
$this->output->info(PHP_EOL . 'import region data successfully');
|
||||
} catch (\Exception $e) {
|
||||
$this->output->error($e->getMessage());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -116,7 +116,7 @@ class InstallProjectCommand extends Command
|
||||
|
||||
// 设置 app domain
|
||||
$appDomain = strtolower($this->output->ask($this->input, '👉 first, you should set app domain: '));
|
||||
if (strpos('http://', $appDomain) === false || strpos('https://', $appDomain) === false) {
|
||||
if (strpos($appDomain, 'http://') === false || strpos( $appDomain, 'https://') === false) {
|
||||
$appDomain = 'http://' . $appDomain;
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"alias": "{MODULE}",
|
||||
"description": "{DESCRIPTION}",
|
||||
"version": "1.0.0",
|
||||
"keywords": [],
|
||||
"keywords": [{KEYWORDS}],
|
||||
"order": 0,
|
||||
"services": [
|
||||
"{SERVICE}"
|
||||
|
@@ -10,6 +10,8 @@
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
// you should use `$router`
|
||||
/* @var think\Route $router */
|
||||
|
||||
$router->group(function () use ($router){
|
||||
})->middleware('auth');
|
||||
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\exceptions;
|
||||
|
||||
use Exception;
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\exceptions;
|
||||
|
||||
use catcher\Code;
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\exceptions;
|
||||
|
||||
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\exceptions;
|
||||
|
||||
use catcher\Code;
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\exceptions;
|
||||
|
||||
use catcher\Code;
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\exceptions;
|
||||
|
||||
use catcher\Code;
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @filename WechatResponseException.php
|
||||
* @createdAt 2020/6/21
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | CatchAdmin [Just Like ~ ]
|
||||
// +----------------------------------------------------------------------
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\facade;
|
||||
|
||||
use think\Facade;
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace catcher\facade;
|
||||
|
||||
use think\Facade;
|
||||
|
205
extend/catcher/generate/CreateModule.php
Normal file
205
extend/catcher/generate/CreateModule.php
Normal file
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
namespace catcher\generate;
|
||||
|
||||
|
||||
use catcher\CatchAdmin;
|
||||
use catcher\facade\FileSystem;
|
||||
use catcher\library\Composer;
|
||||
|
||||
class CreateModule
|
||||
{
|
||||
protected $module;
|
||||
|
||||
protected $moduleDir;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $stubDir;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $namespaces;
|
||||
|
||||
protected $name;
|
||||
|
||||
protected $description;
|
||||
|
||||
protected $dirs;
|
||||
|
||||
protected $keywords;
|
||||
|
||||
public function generate($params)
|
||||
{
|
||||
try {
|
||||
$this->module = $params['alias'];
|
||||
|
||||
$this->name = $params['name'];
|
||||
|
||||
$this->description = $params['description'] ?? '';
|
||||
|
||||
$this->keywords = $params['keywords'] ?? '';
|
||||
|
||||
$this->dirs = $params['dirs'];
|
||||
|
||||
$this->init();
|
||||
|
||||
} catch (\Exception $exception) {
|
||||
$this->rollback();
|
||||
dd($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
$this->moduleDir = CatchAdmin::moduleDirectory($this->module);
|
||||
|
||||
$this->stubDir =dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||
'command'.DIRECTORY_SEPARATOR.
|
||||
'stubs' . DIRECTORY_SEPARATOR;
|
||||
|
||||
$psr4 = (new Composer())->psr4Autoload();
|
||||
|
||||
foreach ($psr4 as $namespace => $des) {
|
||||
if ($des === CatchAdmin::$root) {
|
||||
$this->namespaces = $namespace . $this->module . '\\';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->createFile();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 模块文件
|
||||
*
|
||||
* @time 2020年06月25日
|
||||
* @return string[]
|
||||
*/
|
||||
protected function moduleFiles()
|
||||
{
|
||||
return [
|
||||
$this->moduleDir . ucfirst($this->module). 'Service.php',
|
||||
$this->moduleDir . 'module.json',
|
||||
$this->moduleDir . 'route.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建失败 rollback
|
||||
*
|
||||
* @time 2020年06月25日
|
||||
* @return void
|
||||
*/
|
||||
protected function rollback()
|
||||
{
|
||||
FileSystem::deleteDirectory($this->moduleDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模块文件夹
|
||||
*
|
||||
* @time 2020年06月25日
|
||||
* @return string[]
|
||||
*/
|
||||
protected function modulePath()
|
||||
{
|
||||
|
||||
$dirs = [];
|
||||
foreach (explode(',', $this->dirs) as $dir) {
|
||||
if ($dir == 'database') {
|
||||
$dirs[] = $this->moduleDir . 'database' . DIRECTORY_SEPARATOR . 'migrations';
|
||||
$dirs[] = $this->moduleDir . 'database' . DIRECTORY_SEPARATOR . 'seeds';
|
||||
} else {
|
||||
$dirs[] = $this->moduleDir . $dir;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建路径
|
||||
*
|
||||
* @time 2020年06月25日
|
||||
* @return void
|
||||
*/
|
||||
protected function createDir()
|
||||
{
|
||||
foreach ($this->modulePath() as $path)
|
||||
{
|
||||
CatchAdmin::makeDirectory($path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件
|
||||
*
|
||||
* @time 2020年06月25日
|
||||
* @return void
|
||||
*/
|
||||
protected function createFile()
|
||||
{
|
||||
$this->createDir();
|
||||
$this->createService();
|
||||
$this->createRoute();
|
||||
$this->createModuleJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 service
|
||||
*
|
||||
* @time 2020年06月25日
|
||||
* @return void
|
||||
*/
|
||||
protected function createService()
|
||||
{
|
||||
$service = FileSystem::sharedGet($this->stubDir . 'service.stub');
|
||||
|
||||
$content = str_replace(['{NAMESPACE}', '{SERVICE}'],
|
||||
[substr($this->namespaces, 0, -1),
|
||||
ucfirst($this->module) . 'Service'], $service);
|
||||
|
||||
FileSystem::put($this->moduleDir . ucfirst($this->module) . 'Service.php', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 module.json
|
||||
*
|
||||
* @time 2020年06月25日
|
||||
* @return void
|
||||
*/
|
||||
protected function createModuleJson()
|
||||
{
|
||||
$moduleJson = FileSystem::sharedGet( $this->stubDir . 'module.stub');
|
||||
|
||||
$keywords = '';
|
||||
foreach (explode(',',$this->keywords) as $k) {
|
||||
$keywords .= "\"{$k}\",";
|
||||
}
|
||||
|
||||
$content = str_replace(['{NAME}','{DESCRIPTION}','{MODULE}', '{KEYWORDS}','{SERVICE}'],
|
||||
[
|
||||
$this->name,
|
||||
$this->description,
|
||||
$this->module,
|
||||
trim($keywords, ','),
|
||||
'\\\\'. str_replace('\\', '\\\\',$this->namespaces . ucfirst($this->module) . 'Service')
|
||||
], $moduleJson);
|
||||
|
||||
FileSystem::put($this->moduleDir . 'module.json', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建路由文件
|
||||
*
|
||||
* @time 2020年06月25日
|
||||
* @return void
|
||||
*/
|
||||
protected function createRoute()
|
||||
{
|
||||
FileSystem::put($this->moduleDir . 'route.php', FileSystem::sharedGet($this->stubDir . 'route.stub'));
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user