+ '
';
}
+
+ /**
+ * form btn
+ *
+ * @time 2019年12月06日
+ * @param $filter
+ * @param string $position
+ * @return string
+ */
+ public function formBtn($filter, $position = 'text-right')
+ {
+ $this->btn = sprintf('
+
+
+
', $position, $filter);
+
+ return $this;
+ }
+
+ public function verify($rule, $equalTo = [])
+ {
+ if (empty($equalTo)) {
+ $this->fields[$this->name] = array_merge($this->fields[$this->name], [
+ 'verify' => sprintf('lay-verType="tips" lay-verify="%s"', $rule),
+ ]);
+ } else {
+ [$id, $msg] = $equalTo;
+
+ $this->fields[$this->name] = array_merge($this->fields[$this->name], [
+ 'verify' => sprintf(' lay-verType="tips" lay-verify="%s" lay-equalTo="#%s"
+ lay-equalToText="%s" ', $rule, $id, $msg),
+ ]);
+ }
+
+ return $this;
+ }
+
private function textField($field)
{
return
- sprintf('
',
+ sprintf('
',
$field['name'],
- $field['class'],
+ $field['id'] ?? '',
+ $field['class'] ?? '',
$field['default'] ?? '',
$field['readonly'] ?? '',
$field['placeholder'] ?? '',
- $field['disabled'] ?? ''
+ $field['disabled'] ?? '',
+ $field['verify'] ?? ''
);
}
@@ -162,6 +251,16 @@ class CatchForm
return $select . '';
}
+ private function passwordField($field)
+ {
+ return sprintf('
',
+ $field['name'],
+ $field['id'] ?? '',
+ $field['verify'] ?? '',
+ $field['placeholder'] ?? ''
+ );
+ }
+
private function radioField()
{}
diff --git a/extend/catcher/base/BaseModel.php b/extend/catcher/base/BaseModel.php
index ad4e984..0098352 100644
--- a/extend/catcher/base/BaseModel.php
+++ b/extend/catcher/base/BaseModel.php
@@ -11,10 +11,18 @@ abstract class BaseModel extends \think\Model
use TransTrait;
use BaseOptionsTrait;
- protected $createTime = 'create_at';
+ protected $createTime = 'created_at';
- protected $updateTime = 'update_at';
+ protected $updateTime = 'updated_at';
- protected $deleteTime = 'delete_at';
+ protected $deleteTime = 'deleted_at';
+ protected $autoWriteTimestamp = true;
+
+ protected $limit = 10;
+
+ // 开启
+ public const ENABLE = 1;
+ // 禁用
+ public const DISABLE = 2;
}
diff --git a/extend/catcher/base/BaseValidate.php b/extend/catcher/base/BaseValidate.php
index db644e2..d4f3465 100644
--- a/extend/catcher/base/BaseValidate.php
+++ b/extend/catcher/base/BaseValidate.php
@@ -1,7 +1,7 @@
newValidates())) {
foreach ($this->newValidates() as $validate) {
@@ -28,10 +32,15 @@ abstract class BaseValidate extends Validate
}
}
-
- private function newValidates()
+ /**
+ *
+ * @time 2019年12月07日
+ * @return array
+ */
+ private function newValidates(): array
{
return [
+ new Sometimes(),
];
}
}
diff --git a/extend/catcher/traits/db/BaseOptionsTrait.php b/extend/catcher/traits/db/BaseOptionsTrait.php
index 380e5d8..8371038 100644
--- a/extend/catcher/traits/db/BaseOptionsTrait.php
+++ b/extend/catcher/traits/db/BaseOptionsTrait.php
@@ -19,7 +19,7 @@ trait BaseOptionsTrait
}
if ($this->save()) {
- return $this->id;
+ return $this->{$this->getPk()};
}
return false;
@@ -42,7 +42,7 @@ trait BaseOptionsTrait
}
if ($model->save()) {
- $model->id;
+ return $model->id;
}
return false;
@@ -53,21 +53,37 @@ trait BaseOptionsTrait
* @time 2019年12月03日
* @param $id
* @param array $field
+ * @param bool $trash
* @return mixed
*/
- public function findBy($id, array $field = ['*'])
+ public function findBy($id, array $field = ['*'], $trash = false)
{
- return static::where($this->getPk(), $id)->select($field)->find();
+ if ($trash) {
+ return static::onlyTrashed()->find($id);
+ }
+
+ return static::where($this->getPk(), $id)->field($field)->find();
}
/**
*
* @time 2019年12月03日
* @param $id
+ * @param $force
* @return mixed
*/
- public function deleteBy($id)
+ public function deleteBy($id, $force = false)
{
- return static::destory($id);
+ return static::destroy($id, $force);
+ }
+
+ /**
+ * @time 2019年12月07日
+ * @param $id
+ * @return mixed
+ */
+ public function recover($id)
+ {
+ return static::onlyTrashed()->find($id)->restore();
}
}
diff --git a/extend/catcher/validates/Sometimes.php b/extend/catcher/validates/Sometimes.php
new file mode 100644
index 0000000..2025cdc
--- /dev/null
+++ b/extend/catcher/validates/Sometimes.php
@@ -0,0 +1,28 @@
+ 'module',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Module Stubs
+ |--------------------------------------------------------------------------
+ |
+ | Default module stubs.
+ |
+ */
+
+ 'stubs' => [
+ 'enabled' => false,
+ 'path' => base_path() . '/vendor/nwidart/laravel-modules/src/Commands/stubs',
+ 'files' => [
+ 'routes/web' => 'Routes/web.php',
+ 'routes/api' => 'Routes/api.php',
+ 'views/index' => 'Resources/views/index.blade.php',
+ 'views/master' => 'Resources/views/layouts/master.blade.php',
+ 'scaffold/config' => 'Config/config.php',
+ 'composer' => 'composer.json',
+ 'assets/js/app' => 'Resources/assets/js/app.js',
+ 'assets/sass/app' => 'Resources/assets/sass/app.scss',
+ 'webpack' => 'webpack.mix.js',
+ 'package' => 'package.json',
+ ],
+ 'replacements' => [
+ 'routes/web' => ['LOWER_NAME', 'STUDLY_NAME'],
+ 'routes/api' => ['LOWER_NAME'],
+ 'webpack' => ['LOWER_NAME'],
+ 'json' => ['LOWER_NAME', 'STUDLY_NAME', 'MODULE_NAMESPACE', 'PROVIDER_NAMESPACE'],
+ 'views/index' => ['LOWER_NAME'],
+ 'views/master' => ['LOWER_NAME', 'STUDLY_NAME'],
+ 'scaffold/config' => ['STUDLY_NAME'],
+ 'composer' => [
+ 'LOWER_NAME',
+ 'STUDLY_NAME',
+ 'VENDOR',
+ 'AUTHOR_NAME',
+ 'AUTHOR_EMAIL',
+ 'MODULE_NAMESPACE',
+ 'PROVIDER_NAMESPACE',
+ ],
+ ],
+ 'gitkeep' => true,
+ ],
+ 'paths' => [
+ /*
+ |--------------------------------------------------------------------------
+ | Modules path
+ |--------------------------------------------------------------------------
+ |
+ | This path used for save the generated module. This path also will be added
+ | automatically to list of scanned folders.
+ |
+ */
+
+ 'module' => root_path('module'),
+ /*
+ |--------------------------------------------------------------------------
+ | Modules assets path
+ |--------------------------------------------------------------------------
+ |
+ | Here you may update the modules assets path.
+ |
+ */
+
+ 'assets' => public_path('module'),
+ /*
+ |--------------------------------------------------------------------------
+ | The migrations path
+ |--------------------------------------------------------------------------
+ |
+ | Where you run 'module:publish-migration' command, where do you publish the
+ | the migration files?
+ |
+ */
+
+ 'migration' => root_path('database/migrations'),
+ /*
+ |--------------------------------------------------------------------------
+ | Generator path
+ |--------------------------------------------------------------------------
+ | Customise the paths where the folders will be generated.
+ | Set the generate key to false to not generate that folder
+ */
+ 'generator' => [
+ 'config' => ['path' => 'Config', 'generate' => true],
+ 'command' => ['path' => 'Console', 'generate' => true],
+ 'migration' => ['path' => 'Database/Migrations', 'generate' => true],
+ 'seeder' => ['path' => 'Database/Seeders', 'generate' => true],
+ 'factory' => ['path' => 'Database/factories', 'generate' => true],
+ 'model' => ['path' => 'Entities', 'generate' => true],
+ 'routes' => ['path' => 'Routes', 'generate' => true],
+ 'controller' => ['path' => 'Http/Controllers', 'generate' => true],
+ 'filter' => ['path' => 'Http/Middleware', 'generate' => true],
+ 'request' => ['path' => 'Http/Requests', 'generate' => true],
+ 'provider' => ['path' => 'Providers', 'generate' => true],
+ 'assets' => ['path' => 'Resources/assets', 'generate' => true],
+ 'lang' => ['path' => 'Resources/lang', 'generate' => true],
+ 'views' => ['path' => 'Resources/views', 'generate' => true],
+ 'test' => ['path' => 'Tests/Unit', 'generate' => true],
+ 'test-feature' => ['path' => 'Tests/Feature', 'generate' => true],
+ 'repository' => ['path' => 'Repositories', 'generate' => false],
+ 'event' => ['path' => 'Events', 'generate' => false],
+ 'listener' => ['path' => 'Listeners', 'generate' => false],
+ 'policies' => ['path' => 'Policies', 'generate' => false],
+ 'rules' => ['path' => 'Rules', 'generate' => false],
+ 'jobs' => ['path' => 'Jobs', 'generate' => false],
+ 'emails' => ['path' => 'Emails', 'generate' => false],
+ 'notifications' => ['path' => 'Notifications', 'generate' => false],
+ 'resource' => ['path' => 'Transformers', 'generate' => false],
+ ],
+ ],
+ /*
+ |--------------------------------------------------------------------------
+ | Scan Path
+ |--------------------------------------------------------------------------
+ |
+ | Here you define which folder will be scanned. By default will scan vendor
+ | directory. This is useful if you host the package in packagist website.
+ |
+ */
+
+ 'scan' => [
+ 'enabled' => false,
+ 'paths' => [
+ base_path('vendor/*/*'),
+ ],
+ ],
+ /*
+ |--------------------------------------------------------------------------
+ | Composer File Template
+ |--------------------------------------------------------------------------
+ |
+ | Here is the config for composer.json file, generated by this package
+ |
+ */
+
+ 'composer' => [
+ 'vendor' => 'nwidart',
+ 'author' => [
+ 'name' => 'Nicolas Widart',
+ 'email' => 'n.widart@gmail.com',
+ ],
+ ],
+ /*
+ |--------------------------------------------------------------------------
+ | Caching
+ |--------------------------------------------------------------------------
+ |
+ | Here is the config for setting up caching feature.
+ |
+ */
+ 'cache' => [
+ 'enabled' => false,
+ 'key' => 'laravel-modules',
+ 'lifetime' => 60,
+ ],
+ /*
+ |--------------------------------------------------------------------------
+ | Choose what laravel-modules will register as custom namespaces.
+ | Setting one to false will require you to register that part
+ | in your own Service Provider class.
+ |--------------------------------------------------------------------------
+ */
+ 'register' => [
+ 'translations' => true,
+ /**
+ * load files on boot or register method
+ *
+ * Note: boot not compatible with asgardcms
+ *
+ * @example boot|register
+ */
+ 'files' => 'register',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Activators
+ |--------------------------------------------------------------------------
+ |
+ | You can define new types of activators here, file, database etc. The only
+ | required parameter is 'class'.
+ | The file activator will store the activation status in storage/installed_modules
+ */
+ 'activators' => [
+ 'file' => [
+ 'class' => FileActivator::class,
+ 'statuses-file' => base_path('modules_statuses.json'),
+ 'cache-key' => 'activator.installed',
+ 'cache-lifetime' => 604800,
+ ],
+ ],
+
+ 'activator' => 'file',
+];
diff --git a/extend/think-module/src/ThinkModuleService.php b/extend/think-module/src/ThinkModuleService.php
new file mode 100644
index 0000000..b83c46f
--- /dev/null
+++ b/extend/think-module/src/ThinkModuleService.php
@@ -0,0 +1,17 @@
+commands([
+ CreateModuleCommand::class,
+ DiscoverModuleServiceCommand::class,
+ ]);
+ }
+}
diff --git a/extend/think-module/src/command/CreateModuleCommand.php b/extend/think-module/src/command/CreateModuleCommand.php
new file mode 100644
index 0000000..02d118e
--- /dev/null
+++ b/extend/think-module/src/command/CreateModuleCommand.php
@@ -0,0 +1,131 @@
+setName('module:create')
+ ->addArgument('module', Argument::REQUIRED, 'module name')
+ ->setDescription('create module service');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $this->module = strtolower($input->getArgument('module'));
+
+ $this->moduleDir = CatchAdmin::moduleDirectory($this->module);
+
+ $this->namespaces = CatchAdmin::NAME . '\\\\' . $this->module . '\\\\';
+
+ $this->createController();
+ $this->createRequest();
+ $this->createModel();
+ // $this->createService();
+ $this->createView();
+ $this->createValidate();
+ $this->createRoute();
+ $this->moduleJson();
+
+ $output->warning('module created');
+ }
+
+
+ protected function createController()
+ {
+ mkdir($this->moduleDir . 'controller' . DIRECTORY_SEPARATOR);
+ return file_put_contents($this->moduleDir . 'controller' . DIRECTORY_SEPARATOR . 'Index.php', str_replace(
+ ['{CLASS}', '{NAMESPACE}', '{MODULE}'],
+ ['Index', $this->namespaces . 'controller', $this->module],
+ file_get_contents(__DIR__ . DIRECTORY_SEPARATOR .'stubs'.DIRECTORY_SEPARATOR. 'controller.stub')
+ ));
+ }
+
+
+ protected function createModel()
+ {
+
+ }
+
+ protected function createView()
+ {
+ mkdir($this->moduleDir . DIRECTORY_SEPARATOR . 'view');
+
+ file_put_contents($this->moduleDir . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR . 'index.html', '');
+ file_put_contents($this->moduleDir . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR . 'create.html', '');
+ file_put_contents($this->moduleDir . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR . 'edit.html', '');
+ }
+
+ protected function createValidate()
+ {
+ $validatePath = $this->moduleDir . DIRECTORY_SEPARATOR . 'validate' . DIRECTORY_SEPARATOR;
+ mkdir($validatePath);
+ file_put_contents($validatePath . 'CreateValidate.php', str_replace(
+ ['{Namespace}', '{Class}'],
+ [$this->namespaces . 'validate', 'Create'],
+ file_get_contents(__DIR__ . 'stubs' . DIRECTORY_SEPARATOR . 'validate.stub')));
+
+ file_put_contents($validatePath . 'UpdateValidate.php', str_replace(
+ ['{Namespace}', '{Class}'],
+ [$this->namespaces . 'validate', 'Update'],
+ file_get_contents(__DIR__ . 'stubs' . DIRECTORY_SEPARATOR . 'validate.stub')));
+ }
+
+ protected function createRequest()
+ {
+ $requestPath = $this->moduleDir . DIRECTORY_SEPARATOR . 'request' . DIRECTORY_SEPARATOR;
+ mkdir($requestPath);
+ file_put_contents($validatePath . 'CreateRequest.php', str_replace(
+ ['{Namespace}', '{Class}'],
+ [$this->namespaces . 'request', 'Create'],
+ file_get_contents(__DIR__ . 'stubs' . DIRECTORY_SEPARATOR . 'request.stub')));
+
+ file_put_contents($validatePath . 'UpdateRequest.php', str_replace(
+ ['{Namespace}', '{Class}'],
+ [$this->namespaces . 'request', 'Update'],
+ file_get_contents(__DIR__ . 'stubs' . DIRECTORY_SEPARATOR . 'request.stub')));
+ }
+
+ protected function database()
+ {
+ mkdir($this->moduleDir . DIRECTORY_SEPARATOR . 'database');
+ mkdir($this->moduleDir . DIRECTORY_SEPARATOR . 'database'.DIRECTORY_SEPARATOR.'migrations');
+ mkdir($this->moduleDir . DIRECTORY_SEPARATOR . 'database'.DIRECTORY_SEPARATOR . 'seeds');
+ }
+
+ protected function moduleJson()
+ {
+ file_put_contents($this->moduleDir.DIRECTORY_SEPARATOR .'module.json', str_replace(
+ ['{MODULE}', '{SERVICE}'],
+ [$this->module, $this->namespaces. ucfirst($this->module) . 'Service'],
+ file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'module.stub')));
+ }
+
+ protected function createRoute()
+ {
+ file_put_contents($this->moduleDir.DIRECTORY_SEPARATOR .'route.php',
+ file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'route.stub'));
+ }
+
+ protected function createService()
+ {
+ file_put_contents($this->moduleDir.DIRECTORY_SEPARATOR . ucfirst($this->module) . 'Service.php', str_replace(
+ ['{CLASS}', '{NAMESPACE}'],
+ [ucfirst($this->module), $this->namespaces . '\\' . $this->module],
+ file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'provider.stub')));
+ }
+
+
+}
diff --git a/extend/think-module/src/command/DiscoverModuleServiceCommand.php b/extend/think-module/src/command/DiscoverModuleServiceCommand.php
new file mode 100644
index 0000000..090eced
--- /dev/null
+++ b/extend/think-module/src/command/DiscoverModuleServiceCommand.php
@@ -0,0 +1,83 @@
+setName('module:service')
+ ->setDescription('discover module service');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $this->getModuleServices();
+
+ $output->writeln('module service generator succeed!');
+ }
+
+ /**
+ * 获取模块
+ *
+ * @time 2019年11月27日
+ * @return bool
+ * @throws \ReflectionException
+ */
+ protected function getModuleServices(): bool
+ {
+ $modules = glob(root_path('module') .'*');
+ $moduleServices = [];
+
+ foreach ($modules as $module) {
+ if (file_exists($module . DIRECTORY_SEPARATOR . 'module.json')) {
+ $moduleJson = file_get_contents($module . DIRECTORY_SEPARATOR . 'module.json');
+ $moduleServices = array_merge($moduleServices, \json_decode($moduleJson, true)['services']);
+ }
+ }
+
+ $moduleServices = $this->checkModuleService($moduleServices);
+
+ $header = '// This file is automatically generated at:' . date('Y-m-d H:i:s') . PHP_EOL . 'declare (strict_types = 1);' . PHP_EOL;
+
+ $content =
+ 'app->getRootPath() . 'module/services.php', $content);
+
+ return true;
+ }
+
+ /**
+ *
+ * @time 2019年11月29日
+ * @param $moduleServices
+ * @throws \ReflectionException
+ * @return mixed
+ */
+ protected function checkModuleService($moduleServices)
+ {
+ $new = [];
+
+ foreach ($moduleServices as $key => $service) {
+ $selfReflection = new \ReflectionClass($service);
+ // if service set property 'cache' && set cache => false
+ // the service will not be cached
+ // finally will boot it
+ if ($selfReflection->hasProperty('cache') && !$selfReflection->getProperty('cache')) {
+ $new[$service] = true;
+ } else {
+ $new[$service] = false;
+ }
+ }
+
+ return $new;
+ }
+}
diff --git a/extend/think-module/src/command/stubs/command.stub b/extend/think-module/src/command/stubs/command.stub
new file mode 100644
index 0000000..367b248
--- /dev/null
+++ b/extend/think-module/src/command/stubs/command.stub
@@ -0,0 +1,21 @@
+setName('')
+ ->setDescription('');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ }
+}
diff --git a/extend/think-module/src/command/stubs/composer.stub b/extend/think-module/src/command/stubs/composer.stub
new file mode 100644
index 0000000..c482da5
--- /dev/null
+++ b/extend/think-module/src/command/stubs/composer.stub
@@ -0,0 +1,25 @@
+{
+ "name": "$VENDOR$/$LOWER_NAME$",
+ "description": "",
+ "authors": [
+ {
+ "name": "$AUTHOR_NAME$",
+ "email": "$AUTHOR_EMAIL$"
+ }
+ ],
+ "extra": {
+ "laravel": {
+ "providers": [
+ "$MODULE_NAMESPACE$\\$STUDLY_NAME$\\$PROVIDER_NAMESPACE$\\$STUDLY_NAME$ServiceProvider"
+ ],
+ "aliases": {
+
+ }
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "$MODULE_NAMESPACE$\\$STUDLY_NAME$\\": ""
+ }
+ }
+}
diff --git a/extend/think-module/src/command/stubs/controller.stub b/extend/think-module/src/command/stubs/controller.stub
new file mode 100644
index 0000000..93e64c2
--- /dev/null
+++ b/extend/think-module/src/command/stubs/controller.stub
@@ -0,0 +1,35 @@
+fetch('{MODULE}::index');
+ }
+
+ public function create()
+ {
+ return $this->fetch('{MODULE}::create');
+ }
+
+ public function save()
+ {}
+
+ public function read()
+ {}
+
+ public function edit()
+ {
+ return $this->fetch('{MODULE}::edit');
+ }
+
+ public function update()
+ {}
+
+ public function delete()
+ {}
+
+}
\ No newline at end of file
diff --git a/extend/think-module/src/command/stubs/event.stub b/extend/think-module/src/command/stubs/event.stub
new file mode 100644
index 0000000..f6232f4
--- /dev/null
+++ b/extend/think-module/src/command/stubs/event.stub
@@ -0,0 +1,11 @@
+loadRoutesFrom(__DIR__ . DIRECTORY_SEPARATOR . 'route.php');
+
+ $this->loadViewFrom();
+ }
+
+ protected function loadViewFrom(): void
+ {
+ moduleViewPathManager()->set('login', __DIR__ . DIRECTORY_SEPARATOR . 'view' .DIRECTORY_SEPARATOR);
+ }
+}
diff --git a/extend/think-module/src/command/stubs/request.stub b/extend/think-module/src/command/stubs/request.stub
new file mode 100644
index 0000000..9d56612
--- /dev/null
+++ b/extend/think-module/src/command/stubs/request.stub
@@ -0,0 +1,17 @@
+get('index', 'controller@method');
+
diff --git a/extend/think-module/src/command/stubs/seeder.stub b/extend/think-module/src/command/stubs/seeder.stub
new file mode 100644
index 0000000..6982f54
--- /dev/null
+++ b/extend/think-module/src/command/stubs/seeder.stub
@@ -0,0 +1,19 @@
+