From 2be627dd8d4b7278f5ddc928fafd470dd991dfab Mon Sep 17 00:00:00 2001 From: liutk <961510893@qq.com> Date: Sat, 21 Feb 2026 19:10:22 +0800 Subject: [PATCH] 0.1 --- app/Admin/Controllers/ArticleController.php | 8 +- .../Controllers/ProjectAdvanceController.php | 90 ++++++++++++++++++ .../Controllers/ProjectArticleController.php | 90 ++++++++++++++++++ .../Controllers/ProjectCateController.php | 70 ++++++++++++++ .../Controllers/ProjectFlowController.php | 90 ++++++++++++++++++ .../Controllers/ProjectPhotoController.php | 90 ++++++++++++++++++ app/Admin/routes.php | 7 ++ app/Models/Filters/ProjectArticleFilter.php | 32 +++++++ app/Models/Filters/ProjectCateFilter.php | 24 +++++ app/Models/ProjectArticle.php | 81 ++++++++++++++++ app/Models/ProjectCate.php | 35 +++++++ app/Services/Admin/ProjectArticleService.php | 94 +++++++++++++++++++ app/Services/Admin/ProjectCateService.php | 60 ++++++++++++ ...2_01_173657_create_project_cates_table.php | 32 +++++++ ...6_174806_create_project_articles_table.php | 43 +++++++++ database/seeders/AdminMenuSeeder.php | 47 +++++++--- lang/zh_CN/admin.php | 27 +++++- lang/zh_CN/menu.php | 16 +++- 18 files changed, 917 insertions(+), 19 deletions(-) create mode 100644 app/Admin/Controllers/ProjectAdvanceController.php create mode 100644 app/Admin/Controllers/ProjectArticleController.php create mode 100644 app/Admin/Controllers/ProjectCateController.php create mode 100644 app/Admin/Controllers/ProjectFlowController.php create mode 100644 app/Admin/Controllers/ProjectPhotoController.php create mode 100644 app/Models/Filters/ProjectArticleFilter.php create mode 100644 app/Models/Filters/ProjectCateFilter.php create mode 100644 app/Models/ProjectArticle.php create mode 100644 app/Models/ProjectCate.php create mode 100644 app/Services/Admin/ProjectArticleService.php create mode 100644 app/Services/Admin/ProjectCateService.php create mode 100644 database/migrations/2026_02_01_173657_create_project_cates_table.php create mode 100644 database/migrations/2026_02_06_174806_create_project_articles_table.php diff --git a/app/Admin/Controllers/ArticleController.php b/app/Admin/Controllers/ArticleController.php index 3087182..84e5b71 100644 --- a/app/Admin/Controllers/ArticleController.php +++ b/app/Admin/Controllers/ArticleController.php @@ -61,9 +61,9 @@ class ArticleController extends AdminController ->columns([ amis()->TableColumn('id', __('admin.id'))->sortable(true), amis()->TableColumn('title', __('admin.articles.title'))->width('300px'), - amis()->TableColumn('category', __('admin.articles.category'))->type('mapping') - ->map(Keyword::allChildrenOfKey('article_category')->pluck('name', 'key')->toArray()) - ->itemSchema(amis()->Tag()->label('${item}')->color(Admin::setting()->get('system_theme_setting')['theme_color'] ?? '#1677ff')), + // amis()->TableColumn('category', __('admin.articles.category'))->type('mapping') + // ->map(Keyword::allChildrenOfKey('article_category')->pluck('name', 'key')->toArray()) + // ->itemSchema(amis()->Tag()->label('${item}')->color(Admin::setting()->get('system_theme_setting')['theme_color'] ?? '#1677ff')), // amis()->TableColumn('tags', __('admin.articles.tags'))->type('mapping')->map(Keyword::tagsMap('article_tag')), amis()->TableColumn('cover_url', __('admin.articles.cover'))->type('image')->height('50px')->width('50px')->enlargeAble(true), amis()->TableColumn('published_at', __('admin.articles.published_at'))->remark(__('admin.articles.published_at_remark')), @@ -85,7 +85,7 @@ class ArticleController extends AdminController amis()->Grid()->columns([ amis()->Wrapper()->body([ amis()->TextControl('title', __('admin.articles.title'))->required(true), - Components::make()->parentControl(admin_url('api/keywords/tree-list?parent_name=article_category&has_owner=0'), 'category', __('admin.articles.category'), 'name', 'key'), + // Components::make()->parentControl(admin_url('api/keywords/tree-list?parent_name=article_category&has_owner=0'), 'category', __('admin.articles.category'), 'name', 'key'), // Components::make()->keywordsTagControl('t_ids', __('admin.articles.tags'), 'article_tag'), Components::make()->cropImageControl('cover', __('admin.articles.cover')), Components::make()->sortControl('sort', __('admin.articles.sort')), diff --git a/app/Admin/Controllers/ProjectAdvanceController.php b/app/Admin/Controllers/ProjectAdvanceController.php new file mode 100644 index 0000000..7e992f5 --- /dev/null +++ b/app/Admin/Controllers/ProjectAdvanceController.php @@ -0,0 +1,90 @@ +baseCRUD()->tableLayout('fixed') + ->headerToolbar([ + $this->createTypeButton('drawer', 'md'), + ...$this->baseHeaderToolBar(), + ]) + ->filter($this->baseFilter()->body([ + amis()->GroupControl()->mode('horizontal')->body([ + // amis()->TextControl('id', __('admin.project_articles.id'))->columnRatio(3) + // ->placeholder(__('admin.id')), + amis()->TextControl('title', __('admin.project_articles.title'))->columnRatio(3) + ->placeholder(__('admin.project_articles.title')), + amis()->selectControl('cate', __('admin.project_articles.cate'))->options(ProjectCate::get()->pluck('title', 'id'))->columnRatio(3) + ->placeholder(__('admin.project_articles.cate')), + ]), + ])) + ->columns([ + // amis()->TableColumn('id', __('admin.id'))->sortable(true)->width('50px'), + amis()->TableColumn('title', __('admin.project_articles.title'))->width('300px'), + amis()->TableColumn('cate', __('admin.project_articles.cate'))->type('mapping') + ->map(ProjectCate::get()->pluck('title', 'id')->toArray()) + ->itemSchema(amis()->Tag()->label('${item}')->color(Admin::setting()->get('system_theme_setting')['theme_color'] ?? '#1677ff')), + // amis()->TableColumn('tags', __('admin.articles.tags'))->type('mapping')->map(Keyword::tagsMap('article_tag')), + amis()->TableColumn('cover_url', __('admin.project_articles.cover'))->type('image')->height('50px')->width('150px')->enlargeAble(true), + // amis()->TableColumn('published_at', __('admin.project_articles.published_at'))->remark(__('admin.project_articles.published_at_remark')), + amis()->TableColumn('is_enable', __('admin.project_articles.is_enable'))->type('switch'), + // amis()->TableColumn('is_recommend', __('admin.articles.is_recommend'))->type('switch'), + amis()->TableColumn('created_at', __('admin.created_at'))->type('datetime')->sortable(true), + amis()->Operation()->label(__('admin.actions'))->buttons([ + $this->rowEditTypeButton('drawer', 'md'), + $this->rowDeleteButton(), + ]) + ]); + + return $this->baseList($crud); + } + + public function form($isEdit = false): Form + { + return $this->baseForm()->panelClassName('px-0')->body([ + amis()->Grid()->columns([ + amis()->Wrapper()->body([ + amis()->TextControl('title', __('admin.project_articles.title'))->required(true), + amis()->TextareaControl('description', __('admin.project_articles.description')), + amis()->selectControl('cate', __('admin.project_articles.cate'))->options(ProjectCate::get()->pluck('title', 'id'))->required(true), + amis()->TextControl('type', __('admin.project_articles.type'))->value(ProjectArticle::TYPE_ADVANCE)->hidden(true), + // Components::make()->keywordsTagControl('t_ids', __('admin.articles.tags'), 'article_tag'), + Components::make()->cropImageControl('cover', __('admin.project_articles.cover'))->required(true), + Components::make()->sortControl('sort', __('admin.project_articles.sort')), + // amis()->DateTimeControl('published_at', __('admin.project_articles.published_at'))->format('YYYY-MM-DD HH:mm:ss')->description(__('admin.project_articles.published_at_remark')), + amis()->SwitchControl('is_enable', __('admin.project_articles.is_enable'))->value(false), + // amis()->SwitchControl('is_recommend', __('admin.project_articles.is_recommend'))->value(false), + // Components::make()->fileControl('appendixes', __('admin.articles.appendixes'), '.png,.jpg')->multiple(true), + ]) + // amis()->Wrapper()->body([ + // Components::make()->fuEditorControl('content', __('admin.project_articles.content'))->required(true), + // ])->md(8) + ]), + ]); + } + + public function detail(): Form + { + return $this->baseDetail()->body([]); + } +} diff --git a/app/Admin/Controllers/ProjectArticleController.php b/app/Admin/Controllers/ProjectArticleController.php new file mode 100644 index 0000000..aad21f1 --- /dev/null +++ b/app/Admin/Controllers/ProjectArticleController.php @@ -0,0 +1,90 @@ +baseCRUD()->tableLayout('fixed') + ->headerToolbar([ + $this->createTypeButton('drawer', 'xl'), + ...$this->baseHeaderToolBar(), + ]) + ->filter($this->baseFilter()->body([ + amis()->GroupControl()->mode('horizontal')->body([ + // amis()->TextControl('id', __('admin.project_articles.id'))->columnRatio(3) + // ->placeholder(__('admin.id')), + amis()->TextControl('title', __('admin.project_articles.title'))->columnRatio(3) + ->placeholder(__('admin.project_articles.title')), + amis()->selectControl('cate', __('admin.project_articles.cate'))->options(ProjectCate::get()->pluck('title', 'id'))->columnRatio(3) + ->placeholder(__('admin.project_articles.cate')), + ]), + ])) + ->columns([ + // amis()->TableColumn('id', __('admin.id'))->sortable(true)->width('50px'), + amis()->TableColumn('title', __('admin.project_articles.title'))->width('300px'), + amis()->TableColumn('cate', __('admin.project_articles.cate'))->type('mapping') + ->map(ProjectCate::get()->pluck('title', 'id')->toArray()) + ->itemSchema(amis()->Tag()->label('${item}')->color(Admin::setting()->get('system_theme_setting')['theme_color'] ?? '#1677ff')), + // amis()->TableColumn('tags', __('admin.articles.tags'))->type('mapping')->map(Keyword::tagsMap('article_tag')), + amis()->TableColumn('cover_url', __('admin.project_articles.cover'))->type('image')->height('50px')->width('150px')->enlargeAble(true), + // amis()->TableColumn('published_at', __('admin.project_articles.published_at'))->remark(__('admin.project_articles.published_at_remark')), + amis()->TableColumn('is_enable', __('admin.project_articles.is_enable'))->type('switch'), + // amis()->TableColumn('is_recommend', __('admin.articles.is_recommend'))->type('switch'), + amis()->TableColumn('created_at', __('admin.created_at'))->type('datetime')->sortable(true), + amis()->Operation()->label(__('admin.actions'))->buttons([ + $this->rowEditTypeButton('drawer', 'xl'), + $this->rowDeleteButton(), + ]) + ]); + + return $this->baseList($crud); + } + + public function form($isEdit = false): Form + { + return $this->baseForm()->panelClassName('px-0')->body([ + amis()->Grid()->columns([ + amis()->Wrapper()->body([ + amis()->TextControl('title', __('admin.project_articles.title'))->required(true), + amis()->TextareaControl('description', __('admin.project_articles.description')), + amis()->selectControl('cate', __('admin.project_articles.cate'))->options(ProjectCate::get()->pluck('title', 'id'))->required(true), + amis()->TextControl('type', __('admin.project_articles.type'))->value(ProjectArticle::TYPE_ARTICLE)->hidden(true), + // Components::make()->keywordsTagControl('t_ids', __('admin.articles.tags'), 'article_tag'), + Components::make()->cropImageControl('cover', __('admin.project_articles.cover'))->required(true), + Components::make()->sortControl('sort', __('admin.project_articles.sort')), + // amis()->DateTimeControl('published_at', __('admin.project_articles.published_at'))->format('YYYY-MM-DD HH:mm:ss')->description(__('admin.project_articles.published_at_remark')), + amis()->SwitchControl('is_enable', __('admin.project_articles.is_enable'))->value(false), + // amis()->SwitchControl('is_recommend', __('admin.project_articles.is_recommend'))->value(false), + // Components::make()->fileControl('appendixes', __('admin.articles.appendixes'), '.xsl,.xlsx,.txt,.doc,.docx,.pdf,.pptx'), + ])->md(4), + amis()->Wrapper()->body([ + Components::make()->fuEditorControl('content', __('admin.project_articles.content'))->required(true), + ])->md(8) + ]), + ]); + } + + public function detail(): Form + { + return $this->baseDetail()->body([]); + } +} diff --git a/app/Admin/Controllers/ProjectCateController.php b/app/Admin/Controllers/ProjectCateController.php new file mode 100644 index 0000000..ad8562d --- /dev/null +++ b/app/Admin/Controllers/ProjectCateController.php @@ -0,0 +1,70 @@ +baseCRUD()->tableLayout('fixed') + ->headerToolbar([ + $this->createTypeButton('drawer', 'md'), + ...$this->baseHeaderToolBar(), + ]) + ->filter($this->baseFilter()->body([ + amis()->GroupControl()->mode('horizontal')->body([ + // amis()->TextControl('id', __('admin.project_cates.id'))->columnRatio(3) + // ->placeholder(__('admin.id')), + amis()->TextControl('title', __('admin.project_cates.title'))->columnRatio(3) + ->placeholder(__('admin.project_cates.title')), + ]), + ])) + ->columns([ + amis()->TableColumn('id', 'ID')->sortable()->width('50px'), + amis()->TableColumn('title', __('admin.project_cates.title')), + amis()->TableColumn('cover_url', __('admin.project_cates.cover'))->type('image')->height('50px')->width('250px')->enlargeAble(true), + // amis()->TableColumn('description', __('admin.project_cates.description')), + amis()->TableColumn('created_at', __('admin.created_at'))->set('type', 'datetime')->sortable()->width('150px'), + amis()->Operation()->label(__('admin.actions'))->buttons([ + $this->rowEditTypeButton('drawer', 'md'), + $this->rowDeleteButton(), + ]) + ]); + + return $this->baseList($crud); + } + + public function form($isEdit = false): Form + { + return $this->baseForm()->panelClassName('px-0')->body([ + amis()->Grid()->columns([ + amis()->Wrapper()->body([ + amis()->TextControl('title', __('admin.project_cates.title'))->required(true), + Components::make()->cropImageControl('cover', __('admin.project_cates.cover'))->required(true), + amis()->TextareaControl('description', __('admin.project_cates.description')), + Components::make()->sortControl('sort', __('admin.project_cates.sort')), + ]) + ]), + ]); + } + + public function detail(): Form + { + return $this->baseDetail()->body([]); + } +} diff --git a/app/Admin/Controllers/ProjectFlowController.php b/app/Admin/Controllers/ProjectFlowController.php new file mode 100644 index 0000000..f7b5e0c --- /dev/null +++ b/app/Admin/Controllers/ProjectFlowController.php @@ -0,0 +1,90 @@ +baseCRUD()->tableLayout('fixed') + ->headerToolbar([ + $this->createTypeButton('drawer', 'md'), + ...$this->baseHeaderToolBar(), + ]) + ->filter($this->baseFilter()->body([ + amis()->GroupControl()->mode('horizontal')->body([ + // amis()->TextControl('id', __('admin.project_articles.id'))->columnRatio(3) + // ->placeholder(__('admin.id')), + amis()->TextControl('title', __('admin.project_articles.title'))->columnRatio(3) + ->placeholder(__('admin.project_articles.title')), + amis()->selectControl('cate', __('admin.project_articles.cate'))->options(ProjectCate::get()->pluck('title', 'id'))->columnRatio(3) + ->placeholder(__('admin.project_articles.cate')), + ]), + ])) + ->columns([ + // amis()->TableColumn('id', __('admin.id'))->sortable(true)->width('50px'), + amis()->TableColumn('title', __('admin.project_articles.title'))->width('300px'), + amis()->TableColumn('cate', __('admin.project_articles.cate'))->type('mapping') + ->map(ProjectCate::get()->pluck('title', 'id')->toArray()) + ->itemSchema(amis()->Tag()->label('${item}')->color(Admin::setting()->get('system_theme_setting')['theme_color'] ?? '#1677ff')), + // amis()->TableColumn('tags', __('admin.articles.tags'))->type('mapping')->map(Keyword::tagsMap('article_tag')), + amis()->TableColumn('cover_url', __('admin.project_articles.cover'))->type('image')->height('50px')->width('150px')->enlargeAble(true), + // amis()->TableColumn('published_at', __('admin.project_articles.published_at'))->remark(__('admin.project_articles.published_at_remark')), + amis()->TableColumn('is_enable', __('admin.project_articles.is_enable'))->type('switch'), + // amis()->TableColumn('is_recommend', __('admin.articles.is_recommend'))->type('switch'), + amis()->TableColumn('created_at', __('admin.created_at'))->type('datetime')->sortable(true), + amis()->Operation()->label(__('admin.actions'))->buttons([ + $this->rowEditTypeButton('drawer', 'md'), + $this->rowDeleteButton(), + ]) + ]); + + return $this->baseList($crud); + } + + public function form($isEdit = false): Form + { + return $this->baseForm()->panelClassName('px-0')->body([ + amis()->Grid()->columns([ + amis()->Wrapper()->body([ + amis()->TextControl('title', __('admin.project_articles.title'))->required(true), + // amis()->TextareaControl('description', __('admin.project_articles.description')), + amis()->selectControl('cate', __('admin.project_articles.cate'))->options(ProjectCate::get()->pluck('title', 'id'))->required(true), + amis()->TextControl('type', __('admin.project_articles.type'))->value(ProjectArticle::TYPE_FLOW)->hidden(true), + // Components::make()->keywordsTagControl('t_ids', __('admin.articles.tags'), 'article_tag'), + Components::make()->cropImageControl('cover', __('admin.project_articles.cover'))->required(true), + Components::make()->sortControl('sort', __('admin.project_articles.sort')), + // amis()->DateTimeControl('published_at', __('admin.project_articles.published_at'))->format('YYYY-MM-DD HH:mm:ss')->description(__('admin.project_articles.published_at_remark')), + amis()->SwitchControl('is_enable', __('admin.project_articles.is_enable'))->value(false), + // amis()->SwitchControl('is_recommend', __('admin.project_articles.is_recommend'))->value(false), + // Components::make()->fileControl('appendixes', __('admin.articles.appendixes'), '.xsl,.xlsx,.txt,.doc,.docx,.pdf,.pptx'), + ]) + // amis()->Wrapper()->body([ + // Components::make()->fuEditorControl('content', __('admin.project_articles.content'))->required(true), + // ])->md(8) + ]), + ]); + } + + public function detail(): Form + { + return $this->baseDetail()->body([]); + } +} diff --git a/app/Admin/Controllers/ProjectPhotoController.php b/app/Admin/Controllers/ProjectPhotoController.php new file mode 100644 index 0000000..e1f07d3 --- /dev/null +++ b/app/Admin/Controllers/ProjectPhotoController.php @@ -0,0 +1,90 @@ +baseCRUD()->tableLayout('fixed') + ->headerToolbar([ + $this->createTypeButton('drawer', 'md'), + ...$this->baseHeaderToolBar(), + ]) + ->filter($this->baseFilter()->body([ + amis()->GroupControl()->mode('horizontal')->body([ + // amis()->TextControl('id', __('admin.project_articles.id'))->columnRatio(3) + // ->placeholder(__('admin.id')), + amis()->TextControl('title', __('admin.project_articles.title'))->columnRatio(3) + ->placeholder(__('admin.project_articles.title')), + amis()->selectControl('cate', __('admin.project_articles.cate'))->options(ProjectCate::get()->pluck('title', 'id'))->columnRatio(3) + ->placeholder(__('admin.project_articles.cate')), + ]), + ])) + ->columns([ + // amis()->TableColumn('id', __('admin.id'))->sortable(true)->width('50px'), + amis()->TableColumn('title', __('admin.project_articles.title'))->width('300px'), + amis()->TableColumn('cate', __('admin.project_articles.cate'))->type('mapping') + ->map(ProjectCate::get()->pluck('title', 'id')->toArray()) + ->itemSchema(amis()->Tag()->label('${item}')->color(Admin::setting()->get('system_theme_setting')['theme_color'] ?? '#1677ff')), + // amis()->TableColumn('tags', __('admin.articles.tags'))->type('mapping')->map(Keyword::tagsMap('article_tag')), + amis()->TableColumn('cover_url', __('admin.project_articles.cover'))->type('image')->height('50px')->width('150px')->enlargeAble(true), + // amis()->TableColumn('published_at', __('admin.project_articles.published_at'))->remark(__('admin.project_articles.published_at_remark')), + amis()->TableColumn('is_enable', __('admin.project_articles.is_enable'))->type('switch'), + // amis()->TableColumn('is_recommend', __('admin.articles.is_recommend'))->type('switch'), + amis()->TableColumn('created_at', __('admin.created_at'))->type('datetime')->sortable(true), + amis()->Operation()->label(__('admin.actions'))->buttons([ + $this->rowEditTypeButton('drawer', 'md'), + $this->rowDeleteButton(), + ]) + ]); + + return $this->baseList($crud); + } + + public function form($isEdit = false): Form + { + return $this->baseForm()->panelClassName('px-0')->body([ + amis()->Grid()->columns([ + amis()->Wrapper()->body([ + amis()->TextControl('title', __('admin.project_articles.title'))->required(true), + // amis()->TextareaControl('description', __('admin.project_articles.description')), + amis()->selectControl('cate', __('admin.project_articles.cate'))->options(ProjectCate::get()->pluck('title', 'id'))->required(true), + amis()->TextControl('type', __('admin.project_articles.type'))->value(ProjectArticle::TYPE_PHOTO)->hidden(true), + // Components::make()->keywordsTagControl('t_ids', __('admin.articles.tags'), 'article_tag'), + Components::make()->cropImageControl('cover', __('admin.project_articles.cover'))->required(true), + Components::make()->sortControl('sort', __('admin.project_articles.sort')), + // amis()->DateTimeControl('published_at', __('admin.project_articles.published_at'))->format('YYYY-MM-DD HH:mm:ss')->description(__('admin.project_articles.published_at_remark')), + amis()->SwitchControl('is_enable', __('admin.project_articles.is_enable'))->value(false), + // amis()->SwitchControl('is_recommend', __('admin.project_articles.is_recommend'))->value(false), + // Components::make()->fileControl('appendixes', __('admin.articles.appendixes'), '.png,.jpg')->multiple(true), + ]) + // amis()->Wrapper()->body([ + // Components::make()->fuEditorControl('content', __('admin.project_articles.content'))->required(true), + // ])->md(8) + ]), + ]); + } + + public function detail(): Form + { + return $this->baseDetail()->body([]); + } +} diff --git a/app/Admin/routes.php b/app/Admin/routes.php index b080bf1..ca0d8ce 100644 --- a/app/Admin/routes.php +++ b/app/Admin/routes.php @@ -32,6 +32,13 @@ Route::group([ $router->resource('ads', \App\Admin\Controllers\AdController::class); + //新站调整; + $router->resource('project_cates', \App\Admin\Controllers\ProjectCateController::class); + $router->resource('project_articles', \App\Admin\Controllers\ProjectArticleController::class); + $router->resource('project_flows', \App\Admin\Controllers\ProjectFlowController::class); + $router->resource('project_photos', \App\Admin\Controllers\ProjectPhotoController::class); + $router->resource('project_advances', \App\Admin\Controllers\ProjectAdvanceController::class); + //修改上传 $router->post('upload_file', [\App\Admin\Controllers\IndexController::class, 'uploadFile']); $router->post('upload_image', [\App\Admin\Controllers\IndexController::class, 'uploadImage']); diff --git a/app/Models/Filters/ProjectArticleFilter.php b/app/Models/Filters/ProjectArticleFilter.php new file mode 100644 index 0000000..dece9ec --- /dev/null +++ b/app/Models/Filters/ProjectArticleFilter.php @@ -0,0 +1,32 @@ +where('id', $id); + } + /** + * 标题 + */ + public function title($title) + { + return $this->where('title','like', '%'.$title.'%'); + } + + /** + * 类型 + */ + public function type($type) + { + return $this->where('type', $type); + } +} diff --git a/app/Models/Filters/ProjectCateFilter.php b/app/Models/Filters/ProjectCateFilter.php new file mode 100644 index 0000000..e2ef993 --- /dev/null +++ b/app/Models/Filters/ProjectCateFilter.php @@ -0,0 +1,24 @@ +where('id', $id); + } + /** + * 标题 + */ + public function title($title) + { + return $this->where('title','like', '%'.$title.'%'); + } +} diff --git a/app/Models/ProjectArticle.php b/app/Models/ProjectArticle.php new file mode 100644 index 0000000..24447f2 --- /dev/null +++ b/app/Models/ProjectArticle.php @@ -0,0 +1,81 @@ +format('Y-m-d H:i:s'); + } + + protected $appends = ['tags', 'cover_url']; + + protected $casts = [ + 'created_at' => 'datetime:Y-m-d H:i:s', + 'updated_at' => 'datetime:Y-m-d H:i:s', + 'published_at' => 'datetime:Y-m-d H:i:s', + 'is_enable' => 'boolean', + 'is_recommend' => 'boolean', + 'appendixes' => 'array', + ]; + + protected $fillable = [ + 'title', + 'description', + 'content', + 'cover', + 'cate', + 'type', + 't_ids', + 'published_at', + 'is_enable', + 'is_recommend', + 'sort', + 'appendixes', + ]; + + protected function coverUrl():Attribute { + return Attribute::make( + get: fn($value) => $this->cover ? (Str::startsWith($this->cover, ['http://', 'https://']) ? $this->cover : Storage::url($this->cover)) : null, + ); + } + + public function scopeRecommend($q){ + $q->where('is_recommend', true); + } + + public function scopeShow($q){ + $q->where('is_enable', true)->where('published_at', '<=', now()); + } + + public function scopeSort($q) + { + $q->orderBy('is_recommend', 'desc') + ->orderBy('sort', 'asc') + ->orderBy('published_at', 'desc') + ->orderBy('created_at', 'desc'); + } + + protected function tags():Attribute + { + return Attribute::make( + get: fn($value) => $this->t_ids ? explode(',', $this->t_ids) : [], + ); + } +} diff --git a/app/Models/ProjectCate.php b/app/Models/ProjectCate.php new file mode 100644 index 0000000..40e02ff --- /dev/null +++ b/app/Models/ProjectCate.php @@ -0,0 +1,35 @@ +format('Y-m-d H:i:s'); + } + + protected $casts = [ + 'created_at' => 'datetime:Y-m-d H:i:s', + 'updated_at' => 'datetime:Y-m-d H:i:s', + ]; + + protected function coverUrl():Attribute { + return Attribute::make( + get: fn($value) => $this->cover ? (Str::startsWith($this->cover, ['http://', 'https://']) ? $this->cover : Storage::url($this->cover)) : null, + ); + } +} diff --git a/app/Services/Admin/ProjectArticleService.php b/app/Services/Admin/ProjectArticleService.php new file mode 100644 index 0000000..2562406 --- /dev/null +++ b/app/Services/Admin/ProjectArticleService.php @@ -0,0 +1,94 @@ +current(); + $query= parent::listQuery(); + if(Str::contains($currentUrl, 'project_articles')){ + $query->where('type', ProjectArticle::TYPE_ARTICLE); + }elseif(Str::contains($currentUrl, 'project_flows')){ + $query->where('type', ProjectArticle::TYPE_FLOW); + }elseif(Str::contains($currentUrl, 'project_photos')){ + $query->where('type', ProjectArticle::TYPE_PHOTO); + }elseif(Str::contains($currentUrl, 'project_advances')){ + $query->where('type', ProjectArticle::TYPE_ADVANCE); + } + return $query; + } + + public function store($data): bool + { + $columns = $this->getTableColumns(); + $model = $this->getModel(); + + $isEnable = Arr::get($data, 'is_enabled'); + $publishedAt = Arr::get($data, 'published_at'); + if ($isEnable && empty($publishedAt)) { + $data['published_at'] = now(); + } + + $data['cover'] = $this->saveImage('cover', 'project_articles/cover')[0] ?? ''; + $data['appendixes'] = $this->saveFile('appendixes', 'project_articles/appendixes'); + + foreach ($data as $k => $v) { + if (!in_array($k, $columns)) { + continue; + } + + $model->setAttribute($k, $v); + } + + return $model->save(); + } + + public function update($primaryKey, $data): bool + { + $columns = $this->getTableColumns(); + $model = $this->query()->whereKey($primaryKey)->first(); + + $isEnable = Arr::get($data, 'is_enable'); + $publishedAt = Arr::get($data, 'published_at'); + + if ($isEnable && empty($publishedAt) && empty($model->published_at)) { + $data['published_at'] = now(); + } + + if(isset($data['cover'])){ + $data['cover'] = $this->saveImage('cover', 'project_articles/covers')[0] ?? ''; + } + + if(isset($data['appendixes'])){ + $data['appendixes'] = $this->saveFile('appendixes', 'project_articles/appendixes'); + } + + foreach ($data as $k => $v) { + if (!in_array($k, $columns)) { + continue; + } + + $model->setAttribute($k, $v); + } + + return $model->save(); + } +} \ No newline at end of file diff --git a/app/Services/Admin/ProjectCateService.php b/app/Services/Admin/ProjectCateService.php new file mode 100644 index 0000000..bad3cc4 --- /dev/null +++ b/app/Services/Admin/ProjectCateService.php @@ -0,0 +1,60 @@ +getTableColumns(); + $model = $this->getModel(); + + $data['cover'] = $this->saveImage('cover', 'project_cates/cover')[0] ?? ''; + + foreach ($data as $k => $v) { + if (!in_array($k, $columns)) { + continue; + } + + $model->setAttribute($k, $v); + } + + return $model->save(); + } + + public function update($primaryKey, $data): bool + { + $columns = $this->getTableColumns(); + $model = $this->query()->whereKey($primaryKey)->first(); + + + if(isset($data['cover'])){ + $data['cover'] = $this->saveImage('cover', 'project_cates/cover')[0] ?? ''; + } + + foreach ($data as $k => $v) { + if (!in_array($k, $columns)) { + continue; + } + + $model->setAttribute($k, $v); + } + + return $model->save(); + } +} \ No newline at end of file diff --git a/database/migrations/2026_02_01_173657_create_project_cates_table.php b/database/migrations/2026_02_01_173657_create_project_cates_table.php new file mode 100644 index 0000000..947f265 --- /dev/null +++ b/database/migrations/2026_02_01_173657_create_project_cates_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('title')->comment('标题'); + $table->text('description')->nullable()->comment('简介'); + $table->string('cover')->nullable()->comment('封面'); + $table->unsignedInteger('sort')->default(0)->comment('排序'); + $table->text('content')->nullable()->comment('内容'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('project_cates'); + } +}; diff --git a/database/migrations/2026_02_06_174806_create_project_articles_table.php b/database/migrations/2026_02_06_174806_create_project_articles_table.php new file mode 100644 index 0000000..797eedb --- /dev/null +++ b/database/migrations/2026_02_06_174806_create_project_articles_table.php @@ -0,0 +1,43 @@ +id(); + $table->string('title')->comment('标题'); + $table->text('description')->nullable()->comment('简介'); + $table->text('content')->nullable()->comment('内容'); + $table->string('cover')->nullable()->comment('封面'); + + $table->unsignedInteger('cate')->nullable()->comment('业务范围'); + $table->unsignedTinyInteger('type')->nullable()->comment('分类:1业务子类,2服务流程,3相关图片,4核心优势,5服务案例'); + $table->string('t_ids')->nullable()->comment('标签'); + + $table->timestamp('published_at')->nullable()->comment('发布时间'); + $table->unsignedTinyInteger('is_enable')->default(1)->comment('显示开关'); + + $table->unsignedTinyInteger('is_recommend')->default(0)->comment('推荐开关'); + $table->unsignedInteger('sort')->default(0)->comment('排序'); + + $table->text('appendixes')->nullable()->comment('附件'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('project_articles'); + } +}; diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php index 64d4d73..dd546a2 100644 --- a/database/seeders/AdminMenuSeeder.php +++ b/database/seeders/AdminMenuSeeder.php @@ -20,22 +20,43 @@ class AdminMenuSeeder extends Seeder // $menus = [ ['title' => 'index', 'icon' => 'line-md:home-twotone-alt', 'url' => '/index', 'is_home'=>1, 'order'=>1], - ['title' => 'admin_system', 'icon' => 'material-symbols:settings-outline', 'url' => '/system', 'order'=>2, + ['title'=>'projects', 'icon'=>'ic:outline-article','url'=>'/projects', 'order'=>2, //业务范围 + 'children'=>[ + ['title'=> 'project_cates', 'icon'=>'', 'url'=>'/project_cates', 'order'=>1, ], + ['title'=> 'project_articles', 'icon'=>'', 'url'=>'/project_articles', 'order'=>2], + ['title'=> 'project_flows', 'icon'=>'', 'url'=>'/project_flows', 'order'=>3], + ['title'=> 'project_photos', 'icon'=>'', 'url'=>'/project_photos', 'order'=>4], + ['title'=> 'project_advances', 'icon'=>'', 'url'=>'/project_advances', 'order'=>5], + ] + ], + ['title' => 'web_content', 'icon' => 'ic:outline-collections-bookmark', 'url' => '/web_content', 'order'=>3, + 'children' =>[ + ['title'=>'news', 'icon'=>'','url'=>'/articles', 'order'=>1], + ['title'=>'ads', 'icon'=>'','url'=>'/ads', 'order'=>2], + ] + ], + ['title' => 'admin_system', 'icon' => 'material-symbols:settings-outline', 'url' => '/system', 'order'=>4, 'children' => [ - ['title' => 'admin_users', 'icon' => 'ph:user-gear', 'url' => '/system/admin_users', 'order'=>1], - ['title' => 'admin_roles', 'icon' => 'carbon:user-role', 'url' => '/system/admin_roles', 'order'=>2], - ['title' => 'admin_permission', 'icon' => 'carbon:user-role', 'url' => '/system/admin_permissions', 'order'=>3], - ['title' => 'admin_menu', 'icon' => 'fluent-mdl2:permissions', 'url' => '/system/admin_menus', 'order'=>4], - ['title' => 'admin_setting', 'icon' => 'akar-icons:settings-horizontal', 'url' => '/system/settings', 'order'=>5], - ['title' => 'keywords', 'icon' => 'ph:codesandbox-logo-light', 'url' => '/system/keywords', 'order'=>6] + ['title' => 'admin_users', 'icon' => '', 'url' => '/system/admin_users', 'order'=>1], + ['title' => 'admin_roles', 'icon' => '', 'url' => '/system/admin_roles', 'order'=>2], + ['title' => 'admin_permission', 'icon' => '', 'url' => '/system/admin_permissions', 'order'=>3], + ['title' => 'admin_menu', 'icon' => '', 'url' => '/system/admin_menus', 'order'=>4], + ['title' => 'admin_setting', 'icon' => '', 'url' => '/system/settings', 'order'=>5], + ['title' => 'keywords', 'icon' => '', 'url' => '/system/keywords', 'order'=>6] ], ], - ['title' => 'web_content', 'icon' => 'ic:outline-collections-bookmark', 'url' => '', 'order'=>3, - 'children' =>[ - ['title'=>'articles', 'icon'=>'ic:outline-article','url'=>'/articles', 'order'=>1], - ['title'=>'ads', 'icon'=>'lets-icons:img-box','url'=>'/ads', 'order'=>2], - ] - ] + + + // ['title'=>'case_studies', 'icon'=>'lets-icons:img-box','url'=>'', 'order'=>2, + // 'children'=>[ + // ['title'=> 'case_study_tags', 'icon'=>'lets-icons:img-box','url'=>'/case_study_tags', 'order'=>1 ], + // ['title'=> 'case_study_articles', 'icon'=>'lets-icons:img-box','url'=>'/case_study_articles', 'order'=>2 ], + // ] + // ], + // ['title'=> 'news', 'icon'=>'lets-icons:img-box','url'=>'/news', 'order'=>3], + // ['title'=> 'contacts', 'icon'=>'lets-icons:img-box','url'=>'/contacts', 'order'=>4], + // ['title'=> 'friend_links' , 'icon'=>'lets-icons:img-box','url'=>'/contacts', 'order'=>5] + ]; DB::table('admin_menus')->truncate(); try { diff --git a/lang/zh_CN/admin.php b/lang/zh_CN/admin.php index aec6253..40c488c 100644 --- a/lang/zh_CN/admin.php +++ b/lang/zh_CN/admin.php @@ -303,5 +303,30 @@ return [ 'mini_id' => '小程序ID', 'mini_link'=> '小程序路径' ], - ] + ], + 'project_cates' => [ + 'id' => '主键ID', + 'title' => '标题', + 'description'=> '简介', + 'content' => '内容', + 'cover' =>'封面', + 'sort' => '排序' + ], + 'project_articles' => [ + 'id' => '主键ID', + 'title' => '标题', + 'description'=> '简介', + 'content' => '内容', + 'cover' =>'封面', + 'cate' => '业务范围', + 'tags' => '标签', + 't_ids' => '标签', + 'published_at' => '定时发布', + 'published_at_g' => '发布时间', + 'is_enable' => '显示', + 'is_recommend' => '推荐', + 'sort' => '排序', + 'appendixes' => '附件', + 'published_at_remark' => '*若未设置发布时间且操作设置为显示,则默认生成发布时间', + ], ]; diff --git a/lang/zh_CN/menu.php b/lang/zh_CN/menu.php index dbedcd6..3b8358d 100644 --- a/lang/zh_CN/menu.php +++ b/lang/zh_CN/menu.php @@ -12,5 +12,19 @@ return [ 'keywords' => '数据字典', 'web_content' => '内容管理', 'articles' => '文章管理', - 'ads' => '广告管理', + 'ads' => '广告管理', + + 'web_manager' => '网站管理', + 'projects' => '主营业务', + 'project_cates' => '业务范围', + 'project_articles' => '服务子类', + 'project_flows' => '服务流程', + 'project_photos' => '相关图片', + 'project_advances' => '核心优势', + 'case_studies' => '服务案例', + 'case_study_tags' => '案例标签', + 'case_study_articles' => '案例内容', + 'news' => '企业资讯', + 'contacts' => '在线询价', + 'friend_links' => '合作伙伴' ];