diff --git a/app/Admin/Actions/Grid/ArticleList.php b/app/Admin/Actions/Grid/ArticleList.php new file mode 100644 index 00000000..52481f3b --- /dev/null +++ b/app/Admin/Actions/Grid/ArticleList.php @@ -0,0 +1,65 @@ +getKey()); + + return $this->response() + // ->success('Processed successfully: '.$this->getKey()) + ->redirect(admin_route('articles.index', ['category' =>$this->getKey()])); + } + + /** + * @return string|array|void + */ + public function confirm() + { + // return ['Confirm?', 'contents']; + } + + /** + * @param Model|Authenticatable|HasPermissions|null $user + * + * @return bool + */ + protected function authorize($user): bool + { + return true; + } + + /** + * @return array + */ + protected function parameters() + { + return []; + } +} diff --git a/app/Admin/Controllers/ArticleCategoryController.php b/app/Admin/Controllers/ArticleCategoryController.php new file mode 100644 index 00000000..67369d02 --- /dev/null +++ b/app/Admin/Controllers/ArticleCategoryController.php @@ -0,0 +1,116 @@ +column('id')->sortable(); + $grid->column('name')->tree(); + $grid->column('is_show') + ->if(function () { + return Admin::user()->can('dcat.admin.article_categories.edit'); + }) + ->then(function (Column $column) { + $column->switch(); + }) + ->else(function (Column $column) { + $column->bool(); + }); + $grid->column('is_recommend') + ->if(function () { + return Admin::user()->can('dcat.admin.article_categories.edit'); + }) + ->then(function (Column $column) { + $column->switch(); + }) + ->else(function (Column $column) { + $column->bool(); + }); + $grid->column('sort'); + $grid->column('created_at')->sortable(); + //排序 + $grid->model()->orderBy('created_at', 'desc'); + + /** 操作 **/ + //新增 + if (Admin::user()->can('dcat.admin.article_categories.create')) { + $grid->disableCreateButton(false); + $grid->enableDialogCreate(); + } + //修改 + $grid->showQuickEditButton(Admin::user()->can('dcat.admin.article_categories.edit')); + //删除以及自定义操作 + $grid->actions(function (Grid\Displayers\Actions $actions) { + $actions->disableDelete(Admin::user()->cannot('dcat.admin.article_categories.destroy')); + if (Admin::user()->can('dcat.admin.articles.index')) { + $actions->prepend(new ArticleList()); + } + }); + + /** 查询 **/ + $grid->filter(function (Grid\Filter $filter) { + $filter->panel(); + $filter->equal('name')->width(3); + }); + }); + } + + /** + * Make a show builder. + * + * @param mixed $id + * + * @return Show + */ + protected function detail($id) + { + return Show::make($id, new ArticleCategory(), function (Show $show) { + $show->field('id'); + $show->field('name'); + $show->field('parent_id'); + $show->field('is_show'); + $show->field('is_recommend'); + $show->field('sort'); + $show->field('created_at'); + $show->field('updated_at'); + }); + } + + /** + * Make a form builder. + * + * @return Form + */ + protected function form() + { + return Form::make(new ArticleCategory(), function (Form $form) { + $form->display('id'); + $form->select('parent_id')->options(ArticleCategoryModel::selectOptions()); + $form->text('name')->required(); + $form->switch('is_show'); + $form->switch('is_recommend'); + $form->number('sort')->default(0); + + $form->display('created_at'); + $form->display('updated_at'); + }); + } +} diff --git a/app/Admin/Controllers/ArticleController.php b/app/Admin/Controllers/ArticleController.php new file mode 100644 index 00000000..1b5b4b0c --- /dev/null +++ b/app/Admin/Controllers/ArticleController.php @@ -0,0 +1,144 @@ +column('id')->sortable(); + $grid->column('title'); + $grid->column('category.name')->label(); + // $grid->column('author_name'); + $grid->column('subtitle')->limit(20); + $grid->column('cover_src_path')->images(100, 100); + $grid->column('jump_type')->using([ + '0'=>__('admin_message.article.jump_type.radio.0'), + '1'=>__('admin_message.article.jump_type.radio.1'), + '2'=>__('admin_message.article.jump_type.radio.2'), + ])->label(); + $grid->column('jump_link'); + $grid->column('is_show') + ->if(function () { + return Admin::user()->can('dcat.admin.articles.edit'); + }) + ->then(function (Column $column) { + $column->switch(); + }) + ->else(function (Column $column) { + $column->bool(); + }); + $grid->column('is_recommend') + ->if(function () { + return Admin::user()->can('dcat.admin.articles.edit'); + }) + ->then(function (Column $column) { + $column->switch(); + }) + ->else(function (Column $column) { + $column->bool(); + }); + $grid->column('created_at')->sortable(); + + //排序 + $grid->model()->orderBy('created_at', 'desc'); + + /** 操作 **/ + //新增 + if (Admin::user()->can('dcat.admin.articles.create')) { + $grid->disableCreateButton(false); + $grid->enableDialogCreate(); + } + //修改 + $grid->showQuickEditButton(Admin::user()->can('dcat.admin.articles.edit')); + //删除以及自定义操作 + $grid->actions(function (Grid\Displayers\Actions $actions) { + $actions->disableDelete(Admin::user()->cannot('dcat.admin.articles.destroy')); + }); + + /** 查询 **/ + $grid->filter(function (Grid\Filter $filter) { + $filter->panel(); + $filter->where('category', function ($query) { + $query->whereIn('category_id', ArticleCategory::descendantsAndSelf($this->input, ['id'])->pluck('id')); + }, __('article.fields.category.name'))->select(ArticleCategory::selectOptions())->width(3); + $filter->like('title')->width(3); + }); + }); + } + + /** + * Make a show builder. + * + * @param mixed $id + * + * @return Show + */ + protected function detail($id) + { + return Show::make($id, new Article(), function (Show $show) { + $show->field('id'); + $show->field('category_id'); + $show->field('title'); + $show->field('author_name'); + $show->field('subtitle'); + $show->field('cover_src_path'); + $show->field('content'); + $show->field('jump_type'); + $show->field('jump_link'); + $show->field('created_at'); + $show->field('updated_at'); + }); + } + + /** + * Make a form builder. + * + * @return Form + */ + protected function form() + { + return Form::make(new Article(), function (Form $form) { + $form->display('id'); + $form->select('category_id')->options(ArticleCategory::selectOptions()); + $form->text('title')->required(); + // $form->text('author_name'); + $form->text('subtitle'); + $form->image('cover_src_path') + ->move('articles/'.Carbon::now()->toDateString()) + ->saveFullUrl() + ->removable(false) + ->autoUpload(); + $form->editor('content'); + $form->radio('jump_type')->options([ + '0'=>__('admin_message.article.jump_type.radio.0'), + '1'=>__('admin_message.article.jump_type.radio.1'), + '2'=>__('admin_message.article.jump_type.radio.2'), + ])->default(0); + $form->text('jump_link'); + $form->switch('is_show'); + $form->switch('is_recommend'); + $form->number('sort')->default(0); + + $form->display('created_at'); + $form->display('updated_at'); + }); + } +} diff --git a/app/Admin/Repositories/Article.php b/app/Admin/Repositories/Article.php new file mode 100644 index 00000000..a49ec453 --- /dev/null +++ b/app/Admin/Repositories/Article.php @@ -0,0 +1,16 @@ +disableRowSelector(); $grid->disableCreateButton(); @@ -34,3 +38,11 @@ Form::resolving(function (Form $form) { $form->disableViewButton(); $form->disableViewCheck(); }); + + +Editor::resolving(function (Editor $editor) { + // 设置默认配置 + $editor->options([ + 'branding'=> false, + ]); +}); diff --git a/app/Admin/routes.php b/app/Admin/routes.php index 5555bfcd..b4345a6b 100644 --- a/app/Admin/routes.php +++ b/app/Admin/routes.php @@ -23,5 +23,11 @@ Route::group([ $router->resource('ads', 'AdController')->only([ 'index', 'create', 'store', 'edit', 'update', 'destroy', - ])->names('ads'); + ]); + + $router->resource('article-categories', 'ArticleCategoryController')->only([ + 'index', 'create', 'store', 'edit', 'update', 'destroy', + ])->names('article_categories'); + + $router->resource('articles', 'ArticleController'); }); diff --git a/app/Models/Article.php b/app/Models/Article.php new file mode 100644 index 00000000..c9853c4a --- /dev/null +++ b/app/Models/Article.php @@ -0,0 +1,17 @@ +belongsTo(ArticleCategory::class, 'category_id'); + } +} diff --git a/app/Models/ArticleCategory.php b/app/Models/ArticleCategory.php new file mode 100644 index 00000000..9e7165db --- /dev/null +++ b/app/Models/ArticleCategory.php @@ -0,0 +1,28 @@ +parent_id; + } +} diff --git a/composer.json b/composer.json index bf945fc0..38ce153e 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,7 @@ "dcat/laravel-admin": "2.1.5-beta", "fruitcake/laravel-cors": "^2.0", "guzzlehttp/guzzle": "^7.0.1", + "kalnoy/nestedset": "^6.0", "laravel/framework": "^8.65", "laravel/tinker": "^2.5" }, diff --git a/composer.lock b/composer.lock index c958dcc6..72222b75 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bfd9585c5d4eb94110fb7e44b04a9953", + "content-hash": "b3f1c661b5bcaf6d0066e81774a3a2ad", "packages": [ { "name": "asm89/stack-cors", @@ -1474,6 +1474,75 @@ ], "time": "2021-10-06T17:43:30+00:00" }, + { + "name": "kalnoy/nestedset", + "version": "v6.0.0", + "source": { + "type": "git", + "url": "https://github.com/lazychaser/laravel-nestedset.git", + "reference": "f5351234588a20b14134980552b1bf6dccb3e733" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lazychaser/laravel-nestedset/zipball/f5351234588a20b14134980552b1bf6dccb3e733", + "reference": "f5351234588a20b14134980552b1bf6dccb3e733", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "illuminate/database": "^7.0|^8.0", + "illuminate/events": "^7.0|^8.0", + "illuminate/support": "^7.0|^8.0", + "php": ">=7.1.3" + }, + "require-dev": { + "phpunit/phpunit": "7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "v5.0.x-dev" + }, + "laravel": { + "providers": [ + "Kalnoy\\Nestedset\\NestedSetServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Kalnoy\\Nestedset\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alexander Kalnoy", + "email": "lazychaser@gmail.com" + } + ], + "description": "Nested Set Model for Laravel 5.7 and up", + "keywords": [ + "database", + "hierarchy", + "laravel", + "nested sets", + "nsm" + ], + "support": { + "issues": "https://github.com/lazychaser/laravel-nestedset/issues", + "source": "https://github.com/lazychaser/laravel-nestedset/tree/v6.0.0" + }, + "time": "2021-05-28T07:08:55+00:00" + }, { "name": "laravel/framework", "version": "v8.70.2", diff --git a/database/migrations/2021_11_19_143318_create_article_categories_table.php b/database/migrations/2021_11_19_143318_create_article_categories_table.php new file mode 100644 index 00000000..489ac9ce --- /dev/null +++ b/database/migrations/2021_11_19_143318_create_article_categories_table.php @@ -0,0 +1,36 @@ +id(); + $table->string('name')->nullable()->comment('分类名称'); + $table->tinyInteger('is_show')->default(0)->comment('是否显示:0不显示,1显示'); + $table->tinyInteger('is_recommend')->default(0)->comment('是否推荐:0不推荐,1推荐'); + $table->integer('sort')->default(0)->comment('排序'); + $table->nestedSet(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('article_categories'); + } +} diff --git a/database/migrations/2021_11_19_143916_create_articles_table.php b/database/migrations/2021_11_19_143916_create_articles_table.php new file mode 100644 index 00000000..806ff377 --- /dev/null +++ b/database/migrations/2021_11_19_143916_create_articles_table.php @@ -0,0 +1,42 @@ +id(); + $table->bigInteger('category_id')->default(0)->comment('分类ID'); + $table->string('title')->comment('文章标题'); + $table->string('author_name')->nullable()->comment('作者名称'); + $table->string('subtitle')->nullable()->comment('副标题'); + $table->string('cover_src_path')->nullable()->comment('文章封面图'); + $table->text('content')->nullable()->comment('文章内容'); + $table->tinyInteger('jump_type')->default(0)->comment('跳转类型:0不跳转,1跳转应用内页,2H5链接'); + $table->string('jump_link')->nullable()->comment('跳转地址'); + $table->tinyInteger('is_show')->default(0)->comment('是否显示:0不显示,1显示'); + $table->tinyInteger('is_recommend')->default(0)->comment('是否推荐:0不推荐,1推荐'); + $table->integer('sort')->default(0)->comment('排序'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('articles'); + } +} diff --git a/database/seeders/AdminPermissionSeeder.php b/database/seeders/AdminPermissionSeeder.php index f3c1abed..4f871ebb 100644 --- a/database/seeders/AdminPermissionSeeder.php +++ b/database/seeders/AdminPermissionSeeder.php @@ -58,6 +58,10 @@ class AdminPermissionSeeder extends Seeder 'name'=>'广告内容', 'curd' => ['index', 'create', 'store', 'edit', 'update', 'destroy'], ], + 'article_categories' =>[ + 'name'=>'文章分类', + 'curd' => ['index', 'create', 'store', 'edit', 'update', 'destroy'], + ], ]; try { DB::begintransaction(); diff --git a/dcat_admin_ide_helper.php b/dcat_admin_ide_helper.php index e4cb4968..430a2627 100644 --- a/dcat_admin_ide_helper.php +++ b/dcat_admin_ide_helper.php @@ -16,9 +16,9 @@ namespace Dcat\Admin { * @property Grid\Column|Collection id * @property Grid\Column|Collection is_show * @property Grid\Column|Collection key + * @property Grid\Column|Collection name * @property Grid\Column|Collection updated_at * @property Grid\Column|Collection detail - * @property Grid\Column|Collection name * @property Grid\Column|Collection type * @property Grid\Column|Collection version * @property Grid\Column|Collection is_enabled @@ -44,6 +44,14 @@ namespace Dcat\Admin { * @property Grid\Column|Collection jump_type * @property Grid\Column|Collection sort * @property Grid\Column|Collection src_path + * @property Grid\Column|Collection _lft + * @property Grid\Column|Collection _rgt + * @property Grid\Column|Collection is_recommend + * @property Grid\Column|Collection author_name + * @property Grid\Column|Collection category_id + * @property Grid\Column|Collection content + * @property Grid\Column|Collection cover_src_path + * @property Grid\Column|Collection subtitle * @property Grid\Column|Collection connection * @property Grid\Column|Collection exception * @property Grid\Column|Collection failed_at @@ -56,9 +64,9 @@ namespace Dcat\Admin { * @method Grid\Column|Collection id(string $label = null) * @method Grid\Column|Collection is_show(string $label = null) * @method Grid\Column|Collection key(string $label = null) + * @method Grid\Column|Collection name(string $label = null) * @method Grid\Column|Collection updated_at(string $label = null) * @method Grid\Column|Collection detail(string $label = null) - * @method Grid\Column|Collection name(string $label = null) * @method Grid\Column|Collection type(string $label = null) * @method Grid\Column|Collection version(string $label = null) * @method Grid\Column|Collection is_enabled(string $label = null) @@ -84,6 +92,14 @@ namespace Dcat\Admin { * @method Grid\Column|Collection jump_type(string $label = null) * @method Grid\Column|Collection sort(string $label = null) * @method Grid\Column|Collection src_path(string $label = null) + * @method Grid\Column|Collection _lft(string $label = null) + * @method Grid\Column|Collection _rgt(string $label = null) + * @method Grid\Column|Collection is_recommend(string $label = null) + * @method Grid\Column|Collection author_name(string $label = null) + * @method Grid\Column|Collection category_id(string $label = null) + * @method Grid\Column|Collection content(string $label = null) + * @method Grid\Column|Collection cover_src_path(string $label = null) + * @method Grid\Column|Collection subtitle(string $label = null) * @method Grid\Column|Collection connection(string $label = null) * @method Grid\Column|Collection exception(string $label = null) * @method Grid\Column|Collection failed_at(string $label = null) @@ -101,9 +117,9 @@ namespace Dcat\Admin { * @property Show\Field|Collection id * @property Show\Field|Collection is_show * @property Show\Field|Collection key + * @property Show\Field|Collection name * @property Show\Field|Collection updated_at * @property Show\Field|Collection detail - * @property Show\Field|Collection name * @property Show\Field|Collection type * @property Show\Field|Collection version * @property Show\Field|Collection is_enabled @@ -129,6 +145,14 @@ namespace Dcat\Admin { * @property Show\Field|Collection jump_type * @property Show\Field|Collection sort * @property Show\Field|Collection src_path + * @property Show\Field|Collection _lft + * @property Show\Field|Collection _rgt + * @property Show\Field|Collection is_recommend + * @property Show\Field|Collection author_name + * @property Show\Field|Collection category_id + * @property Show\Field|Collection content + * @property Show\Field|Collection cover_src_path + * @property Show\Field|Collection subtitle * @property Show\Field|Collection connection * @property Show\Field|Collection exception * @property Show\Field|Collection failed_at @@ -141,9 +165,9 @@ namespace Dcat\Admin { * @method Show\Field|Collection id(string $label = null) * @method Show\Field|Collection is_show(string $label = null) * @method Show\Field|Collection key(string $label = null) + * @method Show\Field|Collection name(string $label = null) * @method Show\Field|Collection updated_at(string $label = null) * @method Show\Field|Collection detail(string $label = null) - * @method Show\Field|Collection name(string $label = null) * @method Show\Field|Collection type(string $label = null) * @method Show\Field|Collection version(string $label = null) * @method Show\Field|Collection is_enabled(string $label = null) @@ -169,6 +193,14 @@ namespace Dcat\Admin { * @method Show\Field|Collection jump_type(string $label = null) * @method Show\Field|Collection sort(string $label = null) * @method Show\Field|Collection src_path(string $label = null) + * @method Show\Field|Collection _lft(string $label = null) + * @method Show\Field|Collection _rgt(string $label = null) + * @method Show\Field|Collection is_recommend(string $label = null) + * @method Show\Field|Collection author_name(string $label = null) + * @method Show\Field|Collection category_id(string $label = null) + * @method Show\Field|Collection content(string $label = null) + * @method Show\Field|Collection cover_src_path(string $label = null) + * @method Show\Field|Collection subtitle(string $label = null) * @method Show\Field|Collection connection(string $label = null) * @method Show\Field|Collection exception(string $label = null) * @method Show\Field|Collection failed_at(string $label = null) diff --git a/public/admin/css/app.css b/public/admin/css/app.css new file mode 100644 index 00000000..704bd10c --- /dev/null +++ b/public/admin/css/app.css @@ -0,0 +1 @@ +.tox {z-index:99999999} diff --git a/resources/lang/zh_CN/admin_message.php b/resources/lang/zh_CN/admin_message.php index 1a2a5295..48aa37db 100644 --- a/resources/lang/zh_CN/admin_message.php +++ b/resources/lang/zh_CN/admin_message.php @@ -15,4 +15,13 @@ return [ ], ], ], + 'article'=>[ + 'jump_type'=>[ + 'radio'=>[ + '0'=>'无跳转', + '1'=>'跳转应用内页', + '2'=>'跳转外部网页', + ], + ], + ], ]; diff --git a/resources/lang/zh_CN/article-category.php b/resources/lang/zh_CN/article-category.php new file mode 100644 index 00000000..e61ec139 --- /dev/null +++ b/resources/lang/zh_CN/article-category.php @@ -0,0 +1,17 @@ + [ + 'ArticleCategory' => '文章分类', + 'article-categories' => '文章分类', + ], + 'fields' => [ + 'name' => '名称', + 'parent_id' => '父级', + 'is_show' => '显示', + 'is_recommend' => '推荐', + 'sort' => '排序', + ], + 'options' => [ + ], +]; diff --git a/resources/lang/zh_CN/article.php b/resources/lang/zh_CN/article.php new file mode 100644 index 00000000..d45e6b31 --- /dev/null +++ b/resources/lang/zh_CN/article.php @@ -0,0 +1,26 @@ + [ + 'Article' => '文章管理', + 'articles' => '文章管理', + ], + 'fields' => [ + 'category_id' => '分类', + 'title' => '文章标题', + 'author_name' => '作者名称', + 'subtitle' => '副标题', + 'cover_src_path' => '文章封面图', + 'content' => '文章内容', + 'jump_type' => '跳转类型', + 'jump_link' => '跳转地址', + 'is_show' => '显示', + 'is_recommend' => '推荐', + 'sort' => '排序', + 'category' => [ + 'name' => '分类', + ], + ], + 'options' => [ + ], +];