46 Commits
v2.2 ... v2.5

Author SHA1 Message Date
JaguarJack
068234b57c update:auth增加忽略密码验证,适配第三方登陆 2021-01-27 14:01:17 +08:00
JaguarJack
dc1ce92194 update 2021-01-24 20:27:27 +08:00
JaguarJack
937e1745d2 update:更新默认加载commands 2021-01-24 20:24:43 +08:00
JaguarJack
9f6f02ad24 update:更新上传路由 2021-01-20 20:30:04 +08:00
JaguarJack
340e8c356b fixed:捕获异常以Json方式返回 2021-01-20 20:12:08 +08:00
JaguarJack
65d3111e65 fixed:修复oss上传 2021-01-20 20:09:06 +08:00
JaguarJack
22a8574824 fixed:空值配置无法更新 2021-01-20 19:53:19 +08:00
JaguarJack
584477f711 update:更新包 2021-01-20 19:20:09 +08:00
JaguarJack
2ae7efce04 add:新增初始化管理密码命令 2021-01-20 19:19:28 +08:00
JaguarJack
b12edc9439 update:更新调度 2021-01-18 09:29:02 +08:00
JaguarJack
c02297ab91 更新:支持app commands 自动载入 2021-01-17 20:51:05 +08:00
JaguarJack
b2b6dbd5ed Merge branch 'master' of https://github.com/yanwenwu/catch-admin 2021-01-17 11:22:13 +08:00
JaguarJack
3f154e5fb5 更新:定时任务重新修改 2021-01-17 11:21:52 +08:00
JaguarJack
cff7b38058 update:开启短线重连 2021-01-17 11:17:37 +08:00
JaguarJack
849493eea2 add:新增请求过滤空值方法 2021-01-17 09:39:18 +08:00
JaguarJack
8cace712ae update readme 2020-12-27 13:20:44 +08:00
JaguarJack
b44c8838c4 add:新增隐藏字段功能 2020-12-27 12:33:30 +08:00
JaguarJack
901c7f6cd7 update:更新定时任务搜索 2020-12-26 22:27:06 +08:00
JaguarJack
870e81ab9d add:新增快速搜索 2020-12-26 22:26:36 +08:00
JaguarJack
d4ec2d104f fixed:修改命令行无法生成model field 2020-12-26 20:56:10 +08:00
JaguarJack
614448d07a update:更新监控路由 2020-12-26 20:54:34 +08:00
JaguarJack
dcbe82f398 fixed:修复创建模块 2020-12-13 10:16:46 +08:00
JaguarJack
afe70d39b9 fixed:修复CatchJoin无法连接同一个模型两次 2020-12-13 10:16:28 +08:00
JaguarJack
9118e07d7b fixed 2020-12-04 21:09:50 +08:00
JaguarJack
c0f05fcf8f fixed:模型生成数据库字段注释标记错误 2020-12-01 17:58:53 +08:00
JaguarJack
35445f37e1 fixed:模型name属性多加了表前缀 2020-12-01 17:55:36 +08:00
JaguarJack
94c430f491 update 2020-11-29 09:29:14 +08:00
JaguarJack
97efb82971 update:强制依赖jwt包 2020-11-29 09:18:07 +08:00
JaguarJack
5f49a22a5e add:新增用户token字段 2020-11-23 19:57:49 +08:00
JaguarJack
85f4fc0df8 update:个人信息校验邮箱唯一性 2020-11-21 20:07:36 +08:00
JaguarJack
04a7818608 fixed bug 2020-11-21 12:33:55 +08:00
JaguarJack
21c1df4f69 update:class增加when方法 2020-11-19 19:11:18 +08:00
JaguarJack
0dfe4fb5c6 fixed 2020-11-19 17:44:11 +08:00
JaguarJack
9ca1fd42ae update 2020-11-19 17:31:57 +08:00
JaguarJack
5713d12ce1 updae:基于AST重构代码生成 2020-11-19 17:31:31 +08:00
JaguarJack
e01790aa23 update:composer新增查找package方法 2020-11-19 17:31:04 +08:00
JaguarJack
ecf0970ca4 fixed:修复搜索参数值为0时导致搜索错误 2020-11-19 17:30:30 +08:00
JaguarJack
78e782dd01 fixed:云上传配置无法生效 2020-11-19 09:42:54 +08:00
JaguarJack
e4a5ae0c37 add:新增创建模块 2020-11-14 18:24:33 +08:00
JaguarJack
c8e9e6361c add:新增字段自增/减少方法 2020-11-04 14:09:23 +08:00
JaguarJack
7c4fa5c516 update:优化用户的部门搜索,减少SQL 2020-11-04 10:06:23 +08:00
JaguarJack
97b7f73ff2 add:新增模型获取所有子节点方法 2020-11-04 10:05:50 +08:00
JaguarJack
0b5c883012 update:支持无限级部门搜索 2020-11-04 08:20:15 +08:00
JaguarJack
a9671b6227 update:更新路由 2020-11-03 08:12:10 +08:00
JaguarJack
9ab22b1a1c update:移除角色与部门关联 2020-10-29 08:13:20 +08:00
JaguarJack
a931b7597c update:升级tp核心 2020-10-29 08:01:27 +08:00
102 changed files with 2105 additions and 316 deletions

View File

@@ -146,9 +146,10 @@ composer create-project jaguarjack/catchadmin:dev-master
### Talking ### Talking
- [论坛讨论](http://bbs.catchadmin.com) - [论坛讨论](http://bbs.catchadmin.com)
- 可以提 `ISSUE`,请按照 `issue` 模板提问 - 可以提 `ISSUE`,请按照 `issue` 模板提问
- 加入 Q 群 `302266230` 暗号 `catchadmin`。 - 加入 Q 群 `302266230` 前请先 star 项目支持一下, 备注填写用户名 + 平台。例如: JaguarJack Github
### Thanks ### Thanks
- 感谢 [JetBrains](https://www.jetbrains.com) 提供生产力巨高的 `PHPStorm`和`WebStorm`
> 排名部分先后 > 排名部分先后
- [top-think/think](https://github.com/top-think/think) - [top-think/think](https://github.com/top-think/think)

View File

@@ -29,7 +29,7 @@ class Index extends CatchController
$user = $auth->user(); $user = $auth->user();
$this->afterLoginSuccess($user); $this->afterLoginSuccess($user, $token);
// 登录事件 // 登录事件
$this->loginEvent($user->username); $this->loginEvent($user->username);
@@ -70,12 +70,16 @@ class Index extends CatchController
* *
* @time 2020年09月09日 * @time 2020年09月09日
* @param $user * @param $user
* @param $token
* @return void * @return void
*/ */
protected function afterLoginSuccess($user) protected function afterLoginSuccess($user, $token)
{ {
$user->last_login_ip = request()->ip(); $user->last_login_ip = request()->ip();
$user->last_login_time = time(); $user->last_login_time = time();
if ($user->hasField('remember_token')) {
$user->remember_token = $token;
}
$user->save(); $user->save();
} }

View File

@@ -36,7 +36,7 @@ class CatchCrontabCommand extends Command
->addOption('pid', '-p', Option::VALUE_REQUIRED, 'you can send signal to the process of pid') ->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('static', '-s', Option::VALUE_REQUIRED, 'default static process number', 1)
->addOption('dynamic', '-dy', Option::VALUE_REQUIRED, 'default dynamic process number', 10) ->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'); ->setDescription('start catch crontab schedule');
} }

View File

@@ -0,0 +1,127 @@
<?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)
->where('tactics', '<>', Crontab::EXECUTE_FORBIDDEN)
->select()
->each(function ($command) use (&$executeAbleCommands){
if ($command->tactics == Crontab::EXECUTE_IMMEDIATELY) {
$executeAbleCommands[] = $command;
return true;
}
$can = date('Y-m-d H:i', CronExpression::factory(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) {
Crontab::where('id', $command->id)->update([
'status' => Crontab::DISABLE,
]);
}
$executeAbleCommands[] = $command;
}
return true;
});
return $executeAbleCommands;
}
}

View File

@@ -121,7 +121,7 @@ trait Store
{ {
$pidFile = config('catch.crontab.master_pid_file'); $pidFile = config('catch.crontab.master_pid_file');
if (!file_exists($pidFile)) { if (!FileSystem::exists($pidFile)) {
return 0; return 0;
} }
@@ -136,7 +136,7 @@ trait Store
*/ */
public function renderStatus() public function renderStatus()
{ {
return file_get_contents(self::statusPath()); return FileSystem::sharedGet(self::statusPath());
} }
/** /**

View File

@@ -19,6 +19,6 @@ trait CrontabSearch
public function searchStatusAttr($query, $value, $data) public function searchStatusAttr($query, $value, $data)
{ {
return $query->whereLike('status', $value); return $query->where('status', $value);
} }
} }

View File

@@ -16,7 +16,7 @@ $router->group('monitor', function () use ($router){
$router->put('crontab/enable/<id>', '\catchAdmin\monitor\controller\Crontab@disOrEnable'); $router->put('crontab/enable/<id>', '\catchAdmin\monitor\controller\Crontab@disOrEnable');
// crontab 日志 // crontab 日志
$router->get('crontab/log', '\catchAdmin\monitor\controller\CrontabLog@index'); $router->get('crontab/log/list', '\catchAdmin\monitor\controller\CrontabLog@index');
$router->delete('crontab/log/<id>', '\catchAdmin\monitor\controller\CrontabLog@delete'); $router->delete('crontab/log/list/<id>', '\catchAdmin\monitor\controller\CrontabLog@delete');
})->middleware('auth'); })->middleware('auth');

View File

@@ -9,12 +9,13 @@ use catcher\CatchResponse;
use catcher\exceptions\FailedException; use catcher\exceptions\FailedException;
use catcher\Tree; use catcher\Tree;
use think\response\Json; use think\response\Json;
use catchAdmin\permissions\model\Roles as RoleModel;
class Role extends CatchController class Role extends CatchController
{ {
protected $role; protected $role;
public function __construct(\catchAdmin\permissions\model\Roles $role) public function __construct(RoleModel $role)
{ {
$this->role = $role; $this->role = $role;
} }
@@ -22,7 +23,6 @@ class Role extends CatchController
/** /**
* *
* @time 2019年12月09日 * @time 2019年12月09日
* @param Request $request
* @return string * @return string
*/ */
public function index() public function index()
@@ -50,9 +50,7 @@ class Role extends CatchController
if (!empty($permissions)) { if (!empty($permissions)) {
$this->role->attachPermissions(array_unique($permissions)); $this->role->attachPermissions(array_unique($permissions));
} }
if (!empty($params['permissions'])) {
$this->role->attachDepartments($params['permissions']);
}
// 添加角色 // 添加角色
return CatchResponse::success(); return CatchResponse::success();
} }
@@ -61,7 +59,6 @@ class Role extends CatchController
{ {
$role = $this->role->findBy($id); $role = $this->role->findBy($id);
$role->permissions = $role->getPermissions(); $role->permissions = $role->getPermissions();
$role->departments = $role->getDepartments();
return CatchResponse::success($role); return CatchResponse::success($role);
} }
@@ -104,28 +101,6 @@ class Role extends CatchController
$role->attachPermissions(array_unique($attachIds)); $role->attachPermissions(array_unique($attachIds));
} }
// 更新department
$hasDepartmentIds = $role->getDepartments()->column('id');
$departmentIds = $request->param('departments',[]);
// 已存在部门 IDS
$existedDepartmentIds = [];
foreach ($hasDepartmentIds as $hasDepartmentId) {
if (in_array($hasDepartmentId, $departmentIds)) {
$existedDepartmentIds[] = $hasDepartmentId;
}
}
$attachDepartmentIds = array_diff($departmentIds, $existedDepartmentIds);
$detachDepartmentIds = array_diff($hasDepartmentIds, $existedDepartmentIds);
if (!empty($detachDepartmentIds)) {
$role->detachDepartments($detachDepartmentIds);
}
if (!empty($attachDepartmentIds)) {
$role->attachDepartments(array_unique($attachDepartmentIds));
}
return CatchResponse::success(); return CatchResponse::success();
} }
@@ -147,8 +122,6 @@ class Role extends CatchController
$role = $this->role->findBy($id); $role = $this->role->findBy($id);
// 删除权限 // 删除权限
$role->detachPermissions(); $role->detachPermissions();
// 删除部门关联
$role->detachDepartments();
// 删除用户关联 // 删除用户关联
$role->users()->detach(); $role->users()->detach();
// 删除 // 删除

View File

@@ -8,6 +8,7 @@ use catchAdmin\permissions\model\Roles;
use catchAdmin\permissions\model\Users; use catchAdmin\permissions\model\Users;
use catchAdmin\permissions\request\CreateRequest; use catchAdmin\permissions\request\CreateRequest;
use catchAdmin\permissions\request\UpdateRequest; use catchAdmin\permissions\request\UpdateRequest;
use catchAdmin\permissions\request\ProfileRequest;
use catcher\base\CatchController; use catcher\base\CatchController;
use catcher\CatchAuth; use catcher\CatchAuth;
use catcher\CatchCacheKeys; use catcher\CatchCacheKeys;
@@ -67,15 +68,6 @@ class User extends CatchController
return CatchResponse::success($user); return CatchResponse::success($user);
} }
/**
*
* @time 2019年12月06日
* @throws \Exception
* @return string
*/
public function create()
{}
/** /**
* *
* @param CreateRequest $request * @param CreateRequest $request
@@ -109,12 +101,6 @@ class User extends CatchController
return CatchResponse::success($user); return CatchResponse::success($user);
} }
/**
* @param $id
* @return string
* @throws \Exception
*/
public function edit($id){}
/** /**
* *
* @time 2019年12月04日 * @time 2019年12月04日
@@ -124,7 +110,7 @@ class User extends CatchController
*/ */
public function update($id, UpdateRequest $request) public function update($id, UpdateRequest $request)
{ {
$this->user->updateBy($id, $request->param()); $this->user->updateBy($id, $request->filterEmptyField()->param());
$user = $this->user->findBy($id); $user = $this->user->findBy($id);
@@ -248,10 +234,10 @@ class User extends CatchController
* 更新个人信息 * 更新个人信息
* *
* @time 2020年09月20日 * @time 2020年09月20日
* @param Request $request * @param ProfileRequest $request
* @return \think\response\Json * @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->param()));
} }

View File

@@ -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();
}
}
}

View File

@@ -39,4 +39,23 @@ class Department extends CatchModel
->catchOrder() ->catchOrder()
->select()->toTree(); ->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;
}
} }

View File

@@ -20,6 +20,7 @@ class Users extends CatchModel
'password', // 用户密码 'password', // 用户密码
'email', // 邮箱 登录 'email', // 邮箱 登录
'avatar', // 头像 'avatar', // 头像
'remember_token',
'creator_id', // 创建者ID 'creator_id', // 创建者ID
'department_id', // 部门ID 'department_id', // 部门ID
'status', // 用户状态 1 正常 2 禁用 'status', // 用户状态 1 正常 2 禁用
@@ -28,7 +29,6 @@ class Users extends CatchModel
'created_at', // 创建时间 'created_at', // 创建时间
'updated_at', // 更新时间 'updated_at', // 更新时间
'deleted_at', // 删除状态0未删除 >0 已删除 'deleted_at', // 删除状态0未删除 >0 已删除
]; ];
/** /**

View File

@@ -20,10 +20,20 @@ trait UserSearch
return $query->where($this->aliasField('status'), $value); 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) public function searchDepartmentIdAttr($query, $value, $data)
{ {
$departmentIds = Department::where('parent_id', $value)->column('id'); return $query->whereIn($this->aliasField('department_id'), Department::getChildrenDepartmentIds($value));
$departmentIds[] = $value;
return $query->whereIn($this->aliasField('department_id'), $departmentIds);
} }
} }

View 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,
];
}
}

View File

@@ -15,9 +15,4 @@ class UpdateRequest extends CatchRequest
'email|邮箱' => 'require|email|unique:'.Users::class, 'email|邮箱' => 'require|email|unique:'.Users::class,
]; ];
} }
protected function message()
{
// TODO: Implement message() method.
}
} }

View File

@@ -11,11 +11,10 @@ $router->group(function () use ($router){
// 部门 // 部门
$router->resource('departments', '\catchAdmin\permissions\controller\Department'); $router->resource('departments', '\catchAdmin\permissions\controller\Department');
// 所有职位
$router->get('jobs/all', '\catchAdmin\permissions\controller\Job@getAll');
// 岗位 // 岗位
$router->resource('jobs', '\catchAdmin\permissions\controller\Job'); $router->resource('jobs', '\catchAdmin\permissions\controller\Job');
$router->get('jobs/all', '\catchAdmin\permissions\controller\Job@getAll');
// 用户 // 用户
$router->resource('users', '\catchAdmin\permissions\controller\User'); $router->resource('users', '\catchAdmin\permissions\controller\User');
// 切换状态 // 切换状态

View File

@@ -3,6 +3,7 @@ namespace catchAdmin\system\controller;
use catcher\base\CatchController; use catcher\base\CatchController;
use catcher\CatchResponse; use catcher\CatchResponse;
use catcher\generate\CreateModule;
use catcher\generate\Generator; use catcher\generate\Generator;
use think\Request; use think\Request;
@@ -25,4 +26,10 @@ class Generate extends CatchController
{ {
return CatchResponse::success($generator->preview($request->param())); return CatchResponse::success($generator->preview($request->param()));
} }
public function createModule(Request $request, CreateModule $module)
{
return CatchResponse::success($module->generate($request->post()));
}
} }

View File

@@ -15,6 +15,7 @@ use catcher\base\CatchController;
use catcher\base\CatchRequest; use catcher\base\CatchRequest;
use catcher\CatchResponse; use catcher\CatchResponse;
use catcher\CatchUpload; use catcher\CatchUpload;
use catcher\exceptions\FailedException;
class Upload extends CatchController class Upload extends CatchController
{ {
@@ -37,6 +38,10 @@ class Upload extends CatchController
{ {
$images = $request->file(); $images = $request->file();
if (!$images) {
throw new FailedException('请选择图片上传');
}
return CatchResponse::success($upload->checkImages($images)->multiUpload($images['image'])); return CatchResponse::success($upload->checkImages($images)->multiUpload($images['image']));
} }

View File

@@ -66,7 +66,6 @@ class Config extends CatchModel
$config = []; $config = [];
foreach ($data as $key => $item) { foreach ($data as $key => $item) {
foreach ($item as $k => $value) { foreach ($item as $k => $value) {
if ($value) {
$config[$key . '.' .$k] = [ $config[$key . '.' .$k] = [
'pid' => $parentConfig['id'], 'pid' => $parentConfig['id'],
'key' => $key . '.' . $k, 'key' => $key . '.' . $k,
@@ -76,7 +75,6 @@ class Config extends CatchModel
]; ];
} }
} }
}
$this->where('pid', $parentConfig->id) $this->where('pid', $parentConfig->id)
->select() ->select()

View File

@@ -15,8 +15,10 @@ $router->group(function () use ($router) {
$router->post('table/backup', '\catchAdmin\system\controller\DataDictionary@backup'); $router->post('table/backup', '\catchAdmin\system\controller\DataDictionary@backup');
// 上传 // 上传
$router->post('upload/image', '\catchAdmin\system\controller\Upload@image'); $router->group('upload', function () use ($router){
$router->post('upload/file', '\catchAdmin\system\controller\Upload@file'); $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'); $router->resource('attachments', '\catchAdmin\system\controller\Attachments');
@@ -28,6 +30,7 @@ $router->group(function () use ($router) {
// 代码生成 // 代码生成
$router->post('generate', '\catchAdmin\system\controller\Generate@save'); $router->post('generate', '\catchAdmin\system\controller\Generate@save');
$router->post('generate/preview', '\catchAdmin\system\controller\Generate@preview'); // 预览 $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'); $router->resource('sensitive/word', '\catchAdmin\system\controller\SensitiveWord');

View File

@@ -18,23 +18,25 @@
], ],
"require": { "require": {
"php": ">=7.1.0", "php": ">=7.1.0",
"topthink/framework": "6.0.4", "topthink/framework": "6.0.6",
"topthink/think-orm": "2.0.33", "topthink/think-orm": "2.0.33",
"topthink/think-migration": "^3.0", "topthink/think-migration": "^3.0",
"thans/tp-jwt-auth": "1.1", "thans/tp-jwt-auth": "1.1",
"jaguarjack/think-filesystem-cloud": "dev-master",
"overtrue/wechat": "^4.2", "overtrue/wechat": "^4.2",
"phpoffice/phpspreadsheet": "^1.12", "phpoffice/phpspreadsheet": "^1.12",
"dragonmantank/cron-expression": "^3.0", "dragonmantank/cron-expression": "^3.0",
"symfony/finder": "^4.4", "symfony/finder": "^4.4",
"ext-json": "*", "ext-json": "*",
"overtrue/easy-sms": "^1.1", "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"
}, },
"require-dev": { "require-dev": {
"topthink/think-trace": "^1.0", "topthink/think-trace": "^1.0",
"symfony/var-dumper": "^5.1", "symfony/var-dumper": "^5.1",
"swoole/ide-helper": "^4.5" "swoole/ide-helper": "^4.5",
"nikic/php-parser": "^4.10"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@@ -49,7 +49,7 @@ return [
// 是否严格检查字段是否存在 // 是否严格检查字段是否存在
'fields_strict' => true, 'fields_strict' => true,
// 是否需要断线重连 // 是否需要断线重连
'break_reconnect' => false, 'break_reconnect' => true,
// 监听SQL // 监听SQL
'trigger_sql' => true, 'trigger_sql' => true,
// 开启字段缓存 // 开启字段缓存

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
use think\helper\Arr; use think\helper\Arr;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
use catcher\event\LoadModuleRoutes; use catcher\event\LoadModuleRoutes;
@@ -48,7 +50,7 @@ class CatchAdminService extends Service
$this->app->bind('catch\console', $catchConsole); $this->app->bind('catch\console', $catchConsole);
$this->commands($catchConsole->commands()); $this->commands($catchConsole->defaultCommands());
} }
} }
/** /**

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
use catchAdmin\permissions\model\Users; use catchAdmin\permissions\model\Users;
@@ -10,18 +12,30 @@ use think\helper\Str;
class CatchAuth class CatchAuth
{ {
/**
* @var mixed
*/
protected $auth; protected $auth;
/**
* @var mixed
*/
protected $guard; protected $guard;
// 默认获取 // 默认获取
protected $username = 'email'; protected $username = 'email';
// 校验字段 // 校验字段
protected $password = 'password'; protected $password = 'password';
// 保存用户信息 // 保存用户信息
protected $user = []; protected $user = [];
/**
* @var bool
*/
protected $checkPassword = true;
public function __construct() public function __construct()
{ {
$this->auth = config('catch.auth'); $this->auth = config('catch.auth');
@@ -52,7 +66,9 @@ class CatchAuth
public function attempt($condition) public function attempt($condition)
{ {
try { try {
$user = $this->authenticate($condition); $user = $this->authenticate($condition);
if (!$user) { if (!$user) {
throw new LoginFailedException(); throw new LoginFailedException();
} }
@@ -60,7 +76,7 @@ class CatchAuth
throw new LoginFailedException('该用户已被禁用|' . $user->username, Code::USER_FORBIDDEN); throw new LoginFailedException('该用户已被禁用|' . $user->username, Code::USER_FORBIDDEN);
} }
if (!password_verify($condition['password'], $user->password)) { if ($this->checkPassword && !password_verify($condition['password'], $user->password)) {
throw new LoginFailedException('登录失败|' . $user->username); throw new LoginFailedException('登录失败|' . $user->username);
} }
@@ -268,4 +284,17 @@ class CatchAuth
return $this; return $this;
} }
/**
* 忽略密码认证
*
* @time 2021年01月27日
* @return $this
*/
public function ignorePasswordVerify(): CatchAuth
{
$this->checkPassword = false;
return $this;
}
} }

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
/** /**
* @filename CacheKeys.php * @filename CacheKeys.php
* @createdAt 2020/1/17 * @createdAt 2020/1/17

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
@@ -13,7 +15,6 @@ namespace catcher;
use catcher\library\Composer; use catcher\library\Composer;
use catcher\facade\FileSystem; use catcher\facade\FileSystem;
use think\App; use think\App;
use think\console\Command;
class CatchConsole class CatchConsole
{ {
@@ -34,7 +35,7 @@ class CatchConsole
* @time 2020年07月02日 * @time 2020年07月02日
* @return array * @return array
*/ */
public function commands() public function commands(): array
{ {
$commandFiles = FileSystem::allFiles($this->path); $commandFiles = FileSystem::allFiles($this->path);
@@ -43,9 +44,9 @@ class CatchConsole
/* \Symfony\Component\Finder\SplFileInfo $command */ /* \Symfony\Component\Finder\SplFileInfo $command */
foreach ($commandFiles as $command) { foreach ($commandFiles as $command) {
if ($command->getExtension() === 'php') { 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) . '\\'; $namespace = $this->namespace . str_replace(DIRECTORY_SEPARATOR, '\\', $lastPath) . '\\';
$commandClass = $namespace . pathinfo($command, PATHINFO_FILENAME); $commandClass = $namespace . pathinfo($command->getPathname(), PATHINFO_FILENAME);
$commands[] = $commandClass; $commands[] = $commandClass;
} }
} }
@@ -59,20 +60,23 @@ class CatchConsole
* @time 2020年07月19日 * @time 2020年07月19日
* @return string * @return string
*/ */
protected function parseNamespace() protected function parseNamespace(): string
{ {
// 没有设置 namespace 默认使用 extend 目录 $psr4 = (new Composer)->psr4Autoload();
if (!$this->namespace) {
return root_path(). 'extend'; 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 . return rtrim($path, '/');
str_replace('\\', DIRECTORY_SEPARATOR, substr($this->namespace, strpos($this->namespace, '\\') + 1));
} }
/** /**
@@ -82,7 +86,7 @@ class CatchConsole
* @param $path * @param $path
* @return $this * @return $this
*/ */
public function path($path) public function path($path): CatchConsole
{ {
$this->path = $path; $this->path = $path;
@@ -96,11 +100,40 @@ class CatchConsole
* @param $namespace * @param $namespace
* @return $this * @return $this
*/ */
public function setNamespace($namespace) public function setNamespace($namespace): CatchConsole
{ {
$this->namespace = $namespace; $this->namespace = $namespace;
return $this; 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;
}
} }

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
use app\ExceptionHandle; use app\ExceptionHandle;

View File

@@ -1,7 +1,8 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
use catcher\library\excel\CatchExcel;
use catcher\library\excel\Excel; use catcher\library\excel\Excel;
use catcher\library\excel\ExcelContract; use catcher\library\excel\ExcelContract;
use think\facade\Cache; use think\facade\Cache;
@@ -83,4 +84,28 @@ class CatchModelCollection extends Collection
{ {
return Cache::store($store)->set($key, $this->items, $ttl); 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_walk($ids, function (&$item){
$item = intval($item);
});
$childDepartmentIds = $this->whereIn($parentFields, $ids)->column($column);
if (!empty($childDepartmentIds)) {
$childDepartmentIds = array_merge($childDepartmentIds, $this->getAllChildrenIds($childDepartmentIds));
}
return $childDepartmentIds;
}
} }

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
use catcher\base\CatchModel; use catcher\base\CatchModel;
@@ -11,7 +13,7 @@ class CatchQuery extends Query
/** /**
* *
* @time 2020年01月13日 * @time 2020年01月13日
* @param string $model * @param mixed $model
* @param string $joinField * @param string $joinField
* @param string $currentJoinField * @param string $currentJoinField
* @param array $field * @param array $field
@@ -19,29 +21,38 @@ class CatchQuery extends Query
* @param array $bind * @param array $bind
* @return CatchQuery * @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
{ {
$tableAlias = null;
if (is_string($model)) {
$table = app($model)->getTable(); $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) { $this->options['field'] = array_merge($this->options['field'] ?? [], array_map(function ($value) use ($table, $tableAlias) {
return $table . '.' . $value; return ($tableAlias ? : $table) . '.' . $value;
}, $field)); }, $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日 * @time 2020年01月13日
* @param string $model * @param mixed $model
* @param string $joinField * @param string $joinField
* @param string $currentJoinField * @param string $currentJoinField
* @param array $field * @param array $field
* @param array $bind * @param array $bind
* @return CatchQuery * @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); return $this->catchJoin($model, $joinField, $currentJoinField, $field,'LEFT', $bind);
} }
@@ -49,14 +60,14 @@ class CatchQuery extends Query
/** /**
* *
* @time 2020年01月13日 * @time 2020年01月13日
* @param string $model * @param mixed $model
* @param string $joinField * @param string $joinField
* @param string $currentJoinField * @param string $currentJoinField
* @param array $field * @param array $field
* @param array $bind * @param array $bind
* @return CatchQuery * @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); return $this->catchJoin($model, $joinField, $currentJoinField, $field,'RIGHT', $bind);
} }
@@ -118,7 +129,8 @@ class CatchQuery extends Query
foreach ($params as $field => $value) { foreach ($params as $field => $value) {
$method = 'search' . Str::studly($field) . 'Attr'; $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); $this->model->$method($this, $value, $params);
} }
} }
@@ -126,6 +138,57 @@ class CatchQuery extends Query
return $this; 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);
}
}
// = 值搜索
$this->where($field, $value);
}
}
return $this;
}
/** /**
* *
* @time 2020年01月13日 * @time 2020年01月13日
@@ -166,6 +229,28 @@ class CatchQuery extends Query
return parent::whereLike($field, $condition, $logic); 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');
}
/** /**
* 额外的字段 * 额外的字段
* *
@@ -230,4 +315,32 @@ class CatchQuery extends Query
return $this; 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();
}
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
use think\Paginator; use think\Paginator;
use think\Response;
use think\response\Json; use think\response\Json;
class CatchResponse class CatchResponse

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
use catchAdmin\system\model\Attachments; use catchAdmin\system\model\Attachments;
@@ -61,6 +63,7 @@ class CatchUpload
*/ */
public function upload(UploadedFile $file): string public function upload(UploadedFile $file): string
{ {
try {
$this->initUploadConfig(); $this->initUploadConfig();
$path = Filesystem::disk($this->getDriver())->putFile($this->getPath(), $file); $path = Filesystem::disk($this->getDriver())->putFile($this->getPath(), $file);
@@ -80,6 +83,10 @@ class CatchUpload
} }
throw new FailedException('Upload Failed, Try Again!'); throw new FailedException('Upload Failed, Try Again!');
} catch (\Exception $exception) {
throw new FailedException($exception->getMessage());
}
} }
/** /**
@@ -261,20 +268,11 @@ class CatchUpload
if ($upload) { if ($upload) {
$disk = app()->config->get('filesystem.disks'); $disk = app()->config->get('filesystem.disks');
$uploadConfigs = $configModel->getConfig($upload->id); $uploadConfigs = $configModel->getConfig($upload->component);
// 重组
$_config = [];
if (!empty($uploadConfigs)) { 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) { foreach ($uploadConfigs as $key => &$config) {
// $disk[$key]['type'] = $key; // $disk[$key]['type'] = $key;
// 腾讯云配置处理 // 腾讯云配置处理
if (strtolower($key) == 'qcloud') { if (strtolower($key) == 'qcloud') {
@@ -294,18 +292,19 @@ class CatchUpload
} }
// 合并数组 // 合并数组
array_walk($disk, function (&$item, $key) use ($_config) { array_walk($disk, function (&$item, $key) use ($uploadConfigs) {
if (!in_array($key, ['public', 'local'])) { if (!in_array($key, ['public', 'local'])) {
if ($_config[$key] ?? false) { if ($uploadConfigs[$key] ?? false) {
foreach ($_config[$key] as $k => $value) { foreach ($uploadConfigs[$key] as $k => $value) {
$item[$k] = $value; $item[$k] = $value;
} }
} }
} }
}); });
// 重新分配配置 // 重新分配配置
app()->config->set([ app()->config->set([
'disk' => $disk, 'disks' => $disk,
], 'filesystem'); ], 'filesystem');
} }
} }
@@ -342,11 +341,27 @@ class CatchUpload
case CatchUpload::LOCAL: case CatchUpload::LOCAL:
return $driver['domain']; return $driver['domain'];
case CatchUpload::OSS: case CatchUpload::OSS:
return $driver['end_point']; return self::getOssDomain();
case CatchUpload::QCLOUD: case CatchUpload::QCLOUD:
return $driver['cdn']; return $driver['cdn'];
default: default:
throw new FailedException(sprintf('Driver [%s] Not Supported.', $driver)); 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'];
}
} }

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
class Code class Code

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
class Tree class Tree

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher; namespace catcher;
use catchAdmin\system\model\Config; use catchAdmin\system\model\Config;
@@ -149,6 +151,31 @@ class Utils
return \config('database.connections.mysql.prefix'); 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 +210,23 @@ class Utils
{ {
return root_path($path ? 'public/'. $path : 'public'); 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;
}
} }

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\base; namespace catcher\base;
abstract class CatchController abstract class CatchController

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,8 +1,11 @@
<?php <?php
declare(strict_types=1);
namespace catcher\base; namespace catcher\base;
use catcher\CatchQuery; use catcher\CatchQuery;
use catcher\traits\db\BaseOptionsTrait; use catcher\traits\db\BaseOptionsTrait;
use catcher\traits\db\RewriteTrait;
use catcher\traits\db\TransTrait; use catcher\traits\db\TransTrait;
use think\model\concern\SoftDelete; use think\model\concern\SoftDelete;
use catcher\traits\db\ScopeTrait; use catcher\traits\db\ScopeTrait;
@@ -15,7 +18,7 @@ use catcher\traits\db\ScopeTrait;
*/ */
abstract class CatchModel extends \think\Model abstract class CatchModel extends \think\Model
{ {
use SoftDelete, TransTrait, BaseOptionsTrait, ScopeTrait; use SoftDelete, TransTrait, BaseOptionsTrait, ScopeTrait, RewriteTrait;
protected $createTime = 'created_at'; protected $createTime = 'created_at';
@@ -27,10 +30,22 @@ abstract class CatchModel extends \think\Model
protected $autoWriteTimestamp = true; protected $autoWriteTimestamp = true;
// 分页 Limit
public const LIMIT = 10; public const LIMIT = 10;
// 开启 // 开启
public const ENABLE = 1; public const ENABLE = 1;
// 禁用 // 禁用
public const DISABLE = 2; 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) : false;
}
} }

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
/** /**
* @filename CatchRepository.php * @filename CatchRepository.php
* @createdAt 2020/6/21 * @createdAt 2020/6/21

View File

@@ -1,10 +1,12 @@
<?php <?php
declare(strict_types=1);
namespace catcher\base; namespace catcher\base;
use app\Request; use app\Request;
use catcher\exceptions\FailedException; use catcher\exceptions\FailedException;
use catcher\exceptions\ValidateFailedException; use catcher\exceptions\ValidateFailedException;
use think\App; use catcher\Utils;
class CatchRequest extends Request class CatchRequest extends Request
{ {
@@ -87,4 +89,22 @@ class CatchRequest extends Request
return parent::post($name, $default, $filter); // TODO: Change the autogenerated stub 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;
}
} }

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\base; namespace catcher\base;
use think\Validate; use think\Validate;

View File

@@ -178,9 +178,14 @@ class CreateModuleCommand extends Command
{ {
$moduleJson = FileSystem::sharedGet(__DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'module.stub'); $moduleJson = FileSystem::sharedGet(__DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'module.stub');
$content = str_replace(['{NAME}','{DESCRIPTION}','{MODULE}', '{SERVICE}'], $content = str_replace(['{NAME}','{DESCRIPTION}','{MODULE}', '{SERVICE}', '{KEYWORDS}'],
[$this->name, $this->description, [
$this->module, '\\\\'. str_replace('\\', '\\\\',$this->namespaces . ucfirst($this->module) . 'Service')], $moduleJson); $this->name, $this->description,
$this->module,
'\\\\'. str_replace('\\', '\\\\',
$this->namespaces . ucfirst($this->module) . 'Service'),
''
], $moduleJson);
FileSystem::put($this->moduleDir . 'module.json', $content); FileSystem::put($this->moduleDir . 'module.json', $content);
} }

View File

@@ -3,16 +3,11 @@ declare (strict_types = 1);
namespace catcher\command\Tools; namespace catcher\command\Tools;
use catcher\CatchAdmin;
use catcher\facade\FileSystem;
use catcher\library\BackUpDatabase; use catcher\library\BackUpDatabase;
use catcher\library\Zip;
use think\console\Command; use think\console\Command;
use think\console\Input; use think\console\Input;
use think\console\input\Argument; use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output; use think\console\Output;
use think\facade\Db;
class BackupCommand extends Command class BackupCommand extends Command
{ {

View 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();
}
}
}

View File

@@ -3,7 +3,7 @@
"alias": "{MODULE}", "alias": "{MODULE}",
"description": "{DESCRIPTION}", "description": "{DESCRIPTION}",
"version": "1.0.0", "version": "1.0.0",
"keywords": [], "keywords": [{KEYWORDS}],
"order": 0, "order": 0,
"services": [ "services": [
"{SERVICE}" "{SERVICE}"

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\exceptions; namespace catcher\exceptions;
use Exception; use Exception;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\exceptions; namespace catcher\exceptions;
use catcher\Code; use catcher\Code;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\exceptions; namespace catcher\exceptions;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\exceptions; namespace catcher\exceptions;
use catcher\Code; use catcher\Code;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\exceptions; namespace catcher\exceptions;
use catcher\Code; use catcher\Code;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\exceptions; namespace catcher\exceptions;
use catcher\Code; use catcher\Code;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
/** /**
* @filename WechatResponseException.php * @filename WechatResponseException.php
* @createdAt 2020/6/21 * @createdAt 2020/6/21

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\facade; namespace catcher\facade;
use think\Facade; use think\Facade;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\facade; namespace catcher\facade;
use think\Facade; use think\Facade;

View 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'));
}
}

View File

@@ -8,10 +8,14 @@ use catcher\generate\factory\Migration;
use catcher\generate\factory\Model; use catcher\generate\factory\Model;
use catcher\generate\factory\Route; use catcher\generate\factory\Route;
use catcher\generate\factory\SQL; use catcher\generate\factory\SQL;
use catcher\library\Composer;
use think\facade\Db; use think\facade\Db;
class Generator class Generator
{ {
const NEED_PACKAGE = 'nikic/php-parser';
/** /**
* generate * generate
* *
@@ -21,6 +25,13 @@ class Generator
*/ */
public function done($params) public function done($params)
{ {
// 判断是否安装了扩展包
if (!(new Composer)->hasPackage(self::NEED_PACKAGE)) {
throw new FailedException(
sprintf('you must use [ composer require --dev %s]', self::NEED_PACKAGE)
);
}
$params = \json_decode($params['data'], true); $params = \json_decode($params['data'], true);
[$controller, $model] = $this->parseParams($params); [$controller, $model] = $this->parseParams($params);

View File

@@ -0,0 +1,141 @@
<?php
namespace catcher\generate\build;
use catcher\CatchAdmin;
use catcher\facade\FileSystem;
use catcher\generate\build\classes\Classes;
use PhpParser\BuilderFactory;
use PhpParser\PrettyPrinter\Standard;
class CatchBuild
{
protected $astBuilder;
protected $outPath;
protected $filename;
public function __construct()
{
$this->astBuilder = app(BuilderFactory::class);
}
/**
* 命名空间
*
* @time 2020年11月19日
* @param string $namespace
* @return $this
*/
public function namespace(string $namespace)
{
$this->astBuilder = $this->astBuilder->namespace($namespace);
return $this;
}
/**
* use 方法体
*
* @time 2020年11月19日
* @param $use
* @return $this
*/
public function use($use)
{
$this->astBuilder->addStmt($use);
return $this;
}
/**
* class 模版
*
* @time 2020年11月19日
* @param Classes $class
* @param \Closure $function
* @return $this
*/
public function class(Classes $class, \Closure $function)
{
$function($class);
$this->astBuilder->addStmt($class->build());
return $this;
}
/**
* 条件
*
* @time 2020年11月19日
* @param $condition
* @param \Closure $closure
* @return $this
*/
public function when($condition, \Closure $closure)
{
if ($condition && $closure instanceof \Closure) {
$closure($this);
}
return $this;
}
/**
* 获取内容
*
* @time 2020年11月19日
* @return string
*/
public function getContent()
{
$stmts = array($this->astBuilder->getNode());
$prettyPrinter = new Standard();
return $prettyPrinter->prettyPrintFile($stmts);
}
/**
* 输出
*
* @time 2020年11月19日
* @return string
*/
public function output()
{
return FileSystem::put($this->outPath . $this->filename, $this->getContent());
}
/**
* 输出 Path
*
* @time 2020年11月19日
* @param $path
* @return $this
*/
public function path($path)
{
CatchAdmin::makeDirectory($path);
$this->outPath = $path;
return $this;
}
/**
* 设置文件名
*
* @time 2020年11月19日
* @param $name
* @return mixed
*/
public function filename($name)
{
$this->filename = $name;
return $this;
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace catcher\generate\build\classes;
use PhpParser\BuilderFactory;
class Classes
{
protected $classBuild;
public function __construct(string $name)
{
$this->classBuild = (new BuilderFactory())->class($name);
}
/**
* 设置 comment
*
* @time 2020年11月19日
* @param string $comment
* @return $this
*/
public function docComment($comment="\r\n")
{
$this->classBuild->setDocComment($comment);
return $this;
}
/**
* @time 2020年11月17日
* @param $extend
* @return $this
*/
public function extend($extend)
{
$this->classBuild->extend($extend);
return $this;
}
/**
* @time 2020年11月17日
* @param $interfaces
* @return $this
*/
public function implement($interfaces)
{
$this->classBuild->implement($interfaces);
return $this;
}
/**
* @time 2020年11月17日
* @return $this
*/
public function abstract()
{
$this->classBuild->makeAbstract();
return $this;
}
/**
* @time 2020年11月17日
* @return $this
*/
public function final()
{
$this->classBuild->makeFinal();
return $this;
}
public function build()
{
return $this->classBuild;
}
public function addMethod(Methods $method)
{
$this->classBuild->addStmt($method->build());
return $this;
}
public function addProperty(Property $property)
{
$this->classBuild->addStmt($property->build());
return $this;
}
public function addTrait(Traits $trait)
{
$this->classBuild->addStmt($trait->build());
return $this;
}
/**
* when
*
* @time 2020年11月19日
* @param $condition
* @param \Closure $closure
* @return $this
*/
public function when($condition, \Closure $closure)
{
if ($condition) {
$closure($this);
}
return $this;
}
}

View File

@@ -0,0 +1,158 @@
<?php
namespace catcher\generate\build\classes;
use catcher\generate\build\traits\CatchMethodReturn;
use PhpParser\BuilderFactory;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\Expression;
class Methods
{
use CatchMethodReturn;
protected $methodBuild;
public function __construct(string $name)
{
$this->methodBuild = (new BuilderFactory())->method($name);
}
public function public()
{
$this->methodBuild->makePublic();
return $this;
}
public function protected()
{
$this->methodBuild->makeProtected();
return $this;
}
public function private()
{
$this->methodBuild->makePrivate();
return $this;
}
/**
* set params
*
* @time 2020年11月16日
* @param $type
* @param $param
* @param $default
* @return $this
*/
public function param($param, $type = null, $default = null)
{
$param = (new BuilderFactory())->param($param);
if ($type) {
$param = $param->setType($type);
}
if ($default) {
$param = $param->setDefault($default);
}
$this->methodBuild->addParam(
$param
);
return $this;
}
/**
* 定义
*
* @time 2020年11月18日
* @param $variable
* @param $value
* @return $this
*/
public function declare($variable, $value)
{
$smt = new Expression(
new Assign(
new PropertyFetch(
new Variable('this'),
new Identifier($variable)
),
new Variable($value)
)
);
$this->methodBuild->addStmt($smt);
return $this;
}
/**
* 返回值
*
* @time 2020年11月16日
* @param $returnType
* @return $this
*/
public function returnType($returnType)
{
$this->methodBuild->setReturnType($returnType);
return $this;
}
/**
* 注释
*
* @time 2020年11月16日
* @param $comment
* @return $this
*/
public function docComment(string $comment)
{
$this->methodBuild->setDocComment($comment);
return $this;
}
/**
* 抽象
*
* @time 2020年11月17日
* @return $this
*/
public function toAbstract()
{
$this->methodBuild->makeAbstract();
return $this;
}
/**
* final
*
* @time 2020年11月17日
* @return $this
*/
public function toFinal()
{
$this->methodBuild->makeFinal();
return $this;
}
public function build()
{
return $this->methodBuild;
}
}

View File

@@ -0,0 +1,97 @@
<?php
namespace catcher\generate\build\classes;
use PhpParser\BuilderFactory;
class Property
{
protected $propertyBuild;
public function __construct(string $name)
{
$this->propertyBuild = (new BuilderFactory())->property($name);
}
/**
* @time 2020年11月17日
* @return $this
*/
public function public()
{
$this->propertyBuild->makePublic();
return $this;
}
/**
* @time 2020年11月17日
* @return $this
*/
public function protected()
{
$this->propertyBuild->makeProtected();
return $this;
}
/**
* @time 2020年11月17日
* @return $this
*/
public function private()
{
$this->propertyBuild->makePrivate();
return $this;
}
/**
* 注释
*
* @time 2020年11月16日
* @param $comment
* @return $this
*/
public function static($comment)
{
$this->propertyBuild->makeStatic();
return $this;
}
/**
* set default
*
* @time 2020年11月16日
* @param $value
* @return $this
*/
public function default($value)
{
$this->propertyBuild->setDefault($value);
return $this;
}
public function type($type)
{
$this->propertyBuild->setType($type);
return $this;
}
public function docComment($comment)
{
$this->propertyBuild->setDocComment($comment);
return $this;
}
public function build()
{
return $this->propertyBuild;
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace catcher\generate\build\classes;
use PhpParser\BuilderFactory;
class Traits
{
protected $traitBuild;
protected $build;
public function use(...$names)
{
$this->build = new BuilderFactory;
$this->traitBuild = call_user_func_array([$this->build, 'useTrait'], $names);
return $this;
}
public function and($name)
{
$this->traitBuild->and($name);
return $this;
}
/**
* with
*
* @time 2020年11月19日
* @param \Closure|null $closure
* @return $this
*/
public function with(\Closure $closure = null)
{
if ($closure instanceof \Closure) {
$this->traitBuild->withe($closure($this));
return $this;
}
return $this;
}
/**
* @time 2020年11月19日
* @param $name
* @param null $method
* @return $this
*/
public function adaptation($name, $method = null)
{
$this->build = $this->build->traitUseAdaptation($name. $method);
return $this;
}
/**
* @time 2020年11月19日
* @param $name
* @return $this
*/
public function as($name)
{
$this->build->as($name);
return $this;
}
/**
* @time 2020年11月19日
* @param $name
* @return $this
*/
public function insteadof($name)
{
$this->build->insteadof($name);
return $this;
}
public function build()
{
return $this->traitBuild;
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace catcher\generate\build\classes;
use PhpParser\BuilderFactory;
class Uses
{
public function name(string $name, string $as = '')
{
$build = (new BuilderFactory())->use($name);
if ($as) {
$build->as($as);
}
return $build;
}
public function function(string $function)
{
return (new BuilderFactory())->useFunction($function);
}
public function const(string $const)
{
return (new BuilderFactory())->useConst($const);
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace catcher\generate\build\traits;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Return_;
trait CatchMethodReturn
{
/**
* 列表
*
* @time 2020年11月18日
* @param $model
* @return $this
*/
public function index($model)
{
$class = new Name('CatchResponse');
$arg = new Arg(new MethodCall(
new PropertyFetch(
new Variable('this'), new Identifier($model)
),
new Identifier('getList')
));
$this->methodBuild->addStmt(new Return_(new StaticCall($class, 'paginate', [$arg])));
return $this;
}
/**
* 保存
*
* @time 2020年11月18日
* @param $model
* @return $this
*/
public function save($model)
{
$arg = new Arg(new MethodCall(
new PropertyFetch(
new Variable('this'), new Identifier($model)
),
new Identifier('storeBy'), [new Arg(new MethodCall(new Variable('request'), new Identifier('post')))]
));
$class = new Name('CatchResponse');
$this->methodBuild->addStmt(new Return_(new StaticCall($class, 'success', [$arg])));
return $this;
}
/**
* 更新
*
* @time 2020年11月18日
* @param $model
* @return $this
*/
public function update($model)
{
$arg = new Arg(new MethodCall(
new PropertyFetch(
new Variable('this'), new Identifier($model)
),
new Identifier('updateBy'), [
new Arg(new Variable('id')),
new Arg(new MethodCall(new Variable('request'), new Identifier('post')))
]
));
$class = new Name('CatchResponse');
$this->methodBuild->addStmt(new Return_(new StaticCall($class, 'success', [$arg])));
return $this;
}
public function read($model)
{
$arg = new Arg(new MethodCall(
new PropertyFetch(
new Variable('this'), new Identifier($model)
),
new Identifier('findBy'), [
new Arg(new Variable('id'))
]
));
$class = new Name('CatchResponse');
$this->methodBuild->addStmt(new Return_(new StaticCall($class, 'success', [$arg])));
return $this;
}
/**
* 删除
*
* @time 2020年11月18日
* @param $model
* @return $this
*/
public function delete($model)
{
$arg = new Arg(new MethodCall(
new PropertyFetch(
new Variable('this'), new Identifier($model)
),
new Identifier('deleteBy'), [
new Arg(new Variable('id'))
]
));
$class = new Name('CatchResponse');
$this->methodBuild->addStmt(new Return_(new StaticCall($class, 'success', [$arg])));
return $this;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace catcher\generate\build\types;
use PhpParser\Comment\Doc;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Expr\Array_;
class Arr
{
public function build($fields)
{
$items = [];
foreach ($fields as $field) {
$arrItem = new ArrayItem(new String_($field['name']));
if ($field['comment']) {
$arrItem->setDocComment(
new Doc('// ' . $field['comment'])
);
}
$items[] = $arrItem;
}
return new Array_($items);
}
}

View File

@@ -1,14 +1,35 @@
<?php <?php
namespace catcher\generate\factory; namespace catcher\generate\factory;
use catcher\CatchAdmin;
use catcher\exceptions\FailedException; use catcher\exceptions\FailedException;
use catcher\generate\template\Controller as Template; use catcher\facade\FileSystem;
use catcher\generate\build\classes\Methods;
use catcher\generate\build\CatchBuild;
use catcher\generate\build\classes\Classes;
use catcher\generate\build\classes\Property;
use catcher\generate\build\classes\Uses;
use PhpParser\BuilderFactory;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\ClosureUse;
use PhpParser\PrettyPrinter\Standard;
use think\helper\Str; use think\helper\Str;
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter;
use PhpParser\Node;
class Controller extends Factory class Controller extends Factory
{ {
protected $methods = []; protected $methods = [];
protected $uses = [
'catcher\base\CatchRequest as Request',
'catcher\CatchResponse',
'catcher\base\CatchController'
];
/** /**
* *
* @time 2020年04月27日 * @time 2020年04月27日
@@ -19,7 +40,8 @@ class Controller extends Factory
{ {
// 写入成功之后 // 写入成功之后
$controllerPath = $this->getGeneratePath($params['controller']); $controllerPath = $this->getGeneratePath($params['controller']);
if (file_put_contents($controllerPath, $this->getContent($params))) {
if (FileSystem::put($controllerPath, $this->getContent($params))) {
return $controllerPath; return $controllerPath;
} }
@@ -39,109 +61,135 @@ class Controller extends Factory
throw new FailedException('params has lost'); throw new FailedException('params has lost');
} }
$template = new Template();
// parse controller // parse controller
[$className, $namespace] = $this->parseFilename($params['controller']); [$className, $namespace] = $this->parseFilename($params['controller']);
[$model, $modelNamespace] = $this->parseFilename($params['model']);
$asModel = lcfirst(Str::contains($model, 'Model') ? : $model . 'Model');
if (!$className) { if (!$className) {
throw new FailedException('未填写控制器名称'); throw new FailedException('未填写控制器名称');
} }
// parse model $use = new Uses();
[$model, $modelNamespace] = $this->parseFilename($params['model']); $class = new Classes($className);
$use = implode(';',[ return (new CatchBuild())->namespace($namespace)
'use ' . $params['model'] .' as '. $model . 'Model', ->use($use->name('catcher\base\CatchRequest', 'Request'))
]) . ';'; ->use($use->name('catcher\CatchResponse'))
->use($use->name('catcher\base\CatchController'))
$content = $template->header() . ->use($use->name($modelNamespace . '\\' . ucfirst($model), $asModel))
$template->nameSpace($namespace) . ->class($class->extend('CatchController')->docComment(), function (Classes $class) use ($asModel) {
str_replace('{USE}', $model ? $use : '', $template->uses()) . foreach ($this->getMethods($asModel) as $method) {
$template->createClass($className); $class->addMethod($method);
return str_replace('{CONTENT}', ($model ? $template->construct($model.'Model') : '') . rtrim($this->content($params, $template), "\r\n"), $content);
} }
$class->addProperty(
(new Property($asModel))->protected()
);
})
->getContent();
}
/** /**
* parse use * 方法集合
* *
* @time 2020年04月28 * @time 2020年11月19
* @param $params * @param $model
* @return string * @return array
*/ */
protected function parseUse($params) protected function getMethods($model)
{ {
$date = date('Y年m月d日 H:i');
}
/**
* content
*
* @time 2020年04月27日
* @param $params
* @param $template
* @return string
*/
protected function content($params, $template)
{
$content = '';
if ($params['restful']) {
$methods = $this->restful();
$this->methods = array_merge($this->methods, $methods);
foreach ($methods as $method) {
$content .= $template->{$method[0]}();
}
}
/**
if (!empty($params['other_function'])) {
$others = $this->parseOtherMethods($params['other_function']);
$this->methods = array_merge($this->methods, $others);
foreach ($others as $other) {
$content .= $template->otherFunction($other[0], $other[1]);
}
}*/
return $content;
}
/**
* parse $method
* class_method/http_method
* @time 2020年04月27日
* @param $methods
* @return false|string[]
*/
public function parseOtherMethods($methods)
{
$_methods = [];
foreach ($methods as $method) {
if (Str::contains($method, '/')) {
$_methods[] = explode('/', $method);
} else {
// 默认使用 Get 方式
$_methods[] = [$method, 'get'];
}
}
return $_methods;
}
/**
* restful 路由
*
* @time 2020年04月27日
* @return \string[][]
*/
public function restful()
{
return [ return [
['index', 'get'], (new Methods('__construct'))
['save', 'post'], ->public()
['read', 'get'], ->param($model, ucfirst($model))
['update', 'put'], ->docComment("\r\n")
['delete', 'delete'], ->declare($model, $model),
(new Methods('index'))->public()
->param('request', 'Request')
->docComment(
<<<TEXT
/**
* 列表
* @time $date
* @param Request \$request
*/
TEXT
)
->returnType('\think\Response')->index($model),
(new Methods('save'))
->public()
->param('request', 'Request')
->docComment(
<<<TEXT
/**
* 保存信息
* @time $date
* @param Request \$request
*/
TEXT
)
->returnType('\think\Response')
->save($model),
(new Methods('read'))->public()
->param('id')
->docComment(
<<<TEXT
/**
* 读取
* @time $date
* @param \$id
*/
TEXT
)
->returnType('\think\Response')->read($model),
(new Methods('update'))->public()
->param('request', 'Request')
->param('id')
->docComment(
<<<TEXT
/**
* 更新
* @time $date
* @param Request \$request
* @param \$id
*/
TEXT
)
->returnType('\think\Response')->update($model),
(new Methods('delete'))->public()
->param('id')
->docComment(
<<<TEXT
/**
* 删除
* @time $date
* @param \$id
*/
TEXT
)
->returnType('\think\Response')->delete($model),
]; ];
} }
} }

View File

@@ -42,7 +42,7 @@ abstract class Factory
CatchAdmin::makeDirectory($filePath); CatchAdmin::makeDirectory($filePath);
return $filePath . DIRECTORY_SEPARATOR . $filename . '.php'; return $filePath . DIRECTORY_SEPARATOR . ucfirst($filename ). '.php';
} }
/** /**

View File

@@ -2,21 +2,35 @@
namespace catcher\generate\factory; namespace catcher\generate\factory;
use catcher\exceptions\FailedException; use catcher\exceptions\FailedException;
use catcher\generate\template\Model as Template; use catcher\facade\FileSystem;
use catcher\generate\build\CatchBuild;
use catcher\generate\build\classes\Classes;
use catcher\generate\build\classes\Property;
use catcher\generate\build\classes\Traits;
use catcher\generate\build\classes\Uses;
use catcher\generate\build\types\Arr;
use catcher\traits\db\BaseOptionsTrait;
use catcher\traits\db\ScopeTrait;
use catcher\Utils; use catcher\Utils;
use Phinx\Util\Util;
use think\facade\Db; use think\facade\Db;
use think\helper\Str; use think\helper\Str;
class Model extends Factory class Model extends Factory
{ {
/**
* done
*
* @time 2020年11月19日
* @param $params
* @return string
*/
public function done($params) public function done($params)
{ {
$content = $this->getContent($params); $content = $this->getContent($params);
$modelPath = $this->getGeneratePath($params['model']); $modelPath = $this->getGeneratePath($params['model']);
file_put_contents($modelPath, $content); FileSystem::put($modelPath, $content);
if (!file_exists($modelPath)) { if (!file_exists($modelPath)) {
throw new FailedException('create model failed'); throw new FailedException('create model failed');
@@ -34,12 +48,9 @@ class Model extends Factory
*/ */
public function getContent($params) public function getContent($params)
{ {
// TODO: Implement done() method.
$template = new Template();
$extra = $params['extra']; $extra = $params['extra'];
$table = $params['table']; $table = Utils::tableWithPrefix($params['table']);
[$modelName, $namespace] = $this->parseFilename($params['model']); [$modelName, $namespace] = $this->parseFilename($params['model']);
@@ -53,43 +64,34 @@ class Model extends Factory
throw new FailedException('model name not set'); throw new FailedException('model name not set');
} }
$content = $template->useTrait($extra['soft_delete']) . $softDelete = $extra['soft_delete'];
$template->name(str_replace(Utils::tablePrefix(), '', $table)) .
$template->field($this->parseField($table));
$class = $template->header() . return (new CatchBuild)->namespace($namespace)
$template->nameSpace($namespace) . ->use((new Uses())->name('catcher\base\CatchModel', 'Model'))
$template->uses($extra['soft_delete']) . ->when(!$softDelete, function (CatchBuild $build){
$template->createModel($modelName, $table); $build->use((new Uses())->name(BaseOptionsTrait::class));
$build->use((new Uses())->name(ScopeTrait::class));
return str_replace('{CONTENT}', $content, $class); })
->class((new Classes($modelName))->extend('Model')->docComment(),
function (Classes $class) use ($softDelete, $table) {
if (!$softDelete) {
$class->addTrait(
(new Traits())->use('BaseOptionsTrait', 'ScopeTrait')
);
} }
/** $class->addProperty(
* parse field (new Property('name'))->default(
* Utils::tableWithoutPrefix($table)
* @time 2020年04月28日 )->docComment('// 表名')
* @param $table );
* @return string
*/
protected function parseField($table)
{
if (!$this->hasTableExists($table)) {
return false;
}
$columns = Db::query('show full columns from ' . $table); $class->when($this->hasTableExists($table), function ($class) use ($table){
$class->addProperty(
$new = []; (new Property('field'))->default(
foreach ($columns as $field) { (new Arr)->build(Db::getFields($table))
$new[$field['Field']] = $field['Comment']; )->docComment('// 数据库字段映射'));
} });
})->getContent();
$fields = [];
foreach ($new as $field => $comment) {
$fields[] = sprintf("'%s', // %s", $field, $comment);
}
return implode("\r\n\t\t", $fields);
} }
} }

View File

@@ -1,6 +1,7 @@
<?php <?php
namespace catcher\generate\factory; namespace catcher\generate\factory;
use catcher\facade\FileSystem;
use catcher\generate\template\Content; use catcher\generate\template\Content;
class Route extends Factory class Route extends Factory
@@ -34,11 +35,12 @@ class Route extends Factory
$comment = '// ' . $this->controllerName . '路由'; $comment = '// ' . $this->controllerName . '路由';
array_unshift($route, $comment); array_unshift($route, $comment);
if (file_exists($router)) { if (file_exists($router)) {
return file_put_contents($router, $this->parseRoute($router, $route)); return FileSystem::put($router, $this->parseRoute($router, $route));
} }
return file_put_contents($router, $this->header() . $comment. implode(';'. PHP_EOL , $route) . ';'); return FileSystem::put($router, $this->header() . $comment. implode(';'. PHP_EOL , $route) . ';');
} }
protected function parseRoute($path, $route) protected function parseRoute($path, $route)

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
@@ -14,22 +16,71 @@ use catcher\facade\FileSystem;
class Composer class Composer
{ {
/**
* psr4
*
* @time 2020年11月19日
* @return mixed
*/
public function psr4Autoload() public function psr4Autoload()
{ {
return $this->composerContent()['autoload']['psr-4']; return $this->content()['autoload']['psr-4'];
} }
/**
* require
*
* @time 2020年11月19日
* @return mixed
*/
public function requires() public function requires()
{ {
return $this->composerContent()['require']; return $this->content()['require'];
} }
protected function composerContent() /**
* require dev
*
* @time 2020年11月19日
* @return mixed
*/
public function requireDev()
{ {
return \json_decode(FileSystem::get($this->composerJsonPath()), true); return $this->content()['require-dev'];
} }
protected function composerJsonPath() /**
* composer has package
*
* @time 2020年11月19日
* @param $name
* @return bool
*/
public function hasPackage($name)
{
$packages = array_merge($this->requires(), $this->requireDev());
return in_array($name, array_keys($packages));
}
/**
* composer content
*
* @time 2020年11月19日
* @return mixed
*/
protected function content()
{
return \json_decode(FileSystem::sharedGet($this->path()), true);
}
/**
* composer path
*
* @time 2020年11月19日
* @return string
*/
protected function path()
{ {
return root_path() . 'composer.json'; return root_path() . 'composer.json';
} }

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\library; namespace catcher\library;
use catcher\CatchAdmin; use catcher\CatchAdmin;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
/** /**
* @filename Errors.php * @filename Errors.php
* @createdAt 2020/6/21 * @createdAt 2020/6/21

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,6 +1,8 @@
<?php <?php
namespace catcher\library;
declare(strict_types=1);
namespace catcher\library;
use think\exception\ClassNotFoundException; use think\exception\ClassNotFoundException;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
/** /**
* @filename ProgressBar.php * @filename ProgressBar.php
* @createdAt 2020/6/20 * @createdAt 2020/6/20

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\library; namespace catcher\library;
use catcher\CatchCacheKeys; use catcher\CatchCacheKeys;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
/** /**
* @filename WeChat.php * @filename WeChat.php
* @date 2020/6/7 * @date 2020/6/7

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\library\client; namespace catcher\library\client;
use catcher\exceptions\FailedException; use catcher\exceptions\FailedException;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\library\client; namespace catcher\library\client;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\library\excel; namespace catcher\library\excel;
use catcher\CatchUpload; use catcher\CatchUpload;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\library\excel; namespace catcher\library\excel;
interface ExcelContract interface ExcelContract

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\library\excel; namespace catcher\library\excel;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\library\excel; namespace catcher\library\excel;
trait MacroExcel trait MacroExcel

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\library\excel; namespace catcher\library\excel;
interface ShouldTaskContract interface ShouldTaskContract

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | CatchAdmin [Just Like ] // | CatchAdmin [Just Like ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------

View File

@@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace catcher\traits\db; namespace catcher\traits\db;

View File

@@ -0,0 +1,56 @@
<?php
namespace catcher\traits\db;
/**
* 重写 think\Model 的方法
*
* Trait RewriteTrait
* @package catcher\traits\db
*/
trait RewriteTrait
{
/**
* 初始化
*
* CatchModel constructor.
* @param array $data
*/
public function __construct(array $data = [])
{
parent::__construct($data);
$this->hidden = array_merge($this->hidden, $this->defaultHiddenFields());
}
/**
* hidden model fields
*
* @return array
*/
protected function defaultHiddenFields(): array
{
return [$this->deleteTime];
}
/**
* 重写 hidden 方法,支持合并 hidden 属性
*
* @param array $hidden
* @return $this
*/
public function hidden(array $hidden = [])
{
/**
* 合并属性
*/
if (!count($this->hidden)) {
$this->hidden = array_merge($this->hidden, $hidden);
return $this;
}
$this->hidden = $hidden;
return $this;
}
}

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
/** /**
* @filename ScopeTrait.php * @filename ScopeTrait.php
* @createdAt 2020/6/21 * @createdAt 2020/6/21

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\traits\db; namespace catcher\traits\db;
use think\facade\Db; use think\facade\Db;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\validates; namespace catcher\validates;
use catcher\library\Trie; use catcher\library\Trie;

View File

@@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace catcher\validates; namespace catcher\validates;
class Sometimes implements ValidateInterface class Sometimes implements ValidateInterface

Some files were not shown because too many files have changed in this diff Show More