liutk 2026-02-22 23:01:55 +08:00
parent 2b4e16cfde
commit 137512b735
16 changed files with 553 additions and 18 deletions

View File

@ -30,10 +30,8 @@ class ArticleController extends AdminController
->placeholder(__('admin.id')), ->placeholder(__('admin.id')),
amis()->TextControl('title', __('admin.articles.title')) amis()->TextControl('title', __('admin.articles.title'))
->placeholder(__('admin.articles.title')), ->placeholder(__('admin.articles.title')),
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()->keywordsTagControl('t_ids', __('admin.articles.tags'), 'article_tag'),
]),
amis()->GroupControl()->mode('horizontal')->body([
amis()->SelectControl('enable', __('admin.articles.is_enable')) amis()->SelectControl('enable', __('admin.articles.is_enable'))
->columnRatio(3) ->columnRatio(3)
->options([ ->options([
@ -44,10 +42,10 @@ class ArticleController extends AdminController
->options([ ->options([
1=>'开启',0=>'关闭' 1=>'开启',0=>'关闭'
]), ]),
amis()->InputDatetimeRange()->label(__('admin.articles.published_at'))->name('published_at'),
]), ]),
amis()->GroupControl()->mode('horizontal')->body([ amis()->GroupControl()->mode('horizontal')->body([
amis()->InputDatetimeRange()->label(__('admin.created_at'))->name('created_at')->columnRatio(6), amis()->InputDatetimeRange()->label(__('admin.articles.published_at'))->name('published_at'),
amis()->InputDatetimeRange()->label(__('admin.created_at'))->name('created_at'),
]), ]),
])) ]))
->itemBadge([//行角标 ->itemBadge([//行角标

View File

@ -0,0 +1,95 @@
<?php
namespace App\Admin\Controllers;
use App\Casts\Storage;
use Slowlyo\OwlAdmin\Admin;
use Slowlyo\OwlAdmin\Renderers\Page;
use Slowlyo\OwlAdmin\Renderers\Form;
use Slowlyo\OwlAdmin\Controllers\AdminController;
use App\Services\Admin\HonorService;
use App\Admin\Components;
use App\Models\Keyword;
use App\Traits\CustomActionTrait;
class HonorController extends AdminController
{
use CustomActionTrait;
protected string $serviceName = HonorService::class;
public function list():Page
{
$crud = $this->baseCRUD()->tableLayout('fixed')
->headerToolbar([
$this->createTypeButton('drawer', 'md'),
...$this->baseHeaderToolBar(),
])
->filter($this->baseFilter()->body([
amis()->GroupControl()->mode('horizontal')->body([
amis()->TextControl('title', __('admin.honors.title'))
->placeholder(__('admin.honors.title')),
amis()->selectControl('cate', __('admin.honors.category'))->options(Keyword::allChildrenOfKey('honors')->pluck('name', 'id'))
->placeholder(__('admin.honors.category')),
amis()->SelectControl('enable', __('admin.honors.is_enable'))
->columnRatio(3)
->options([
1=>'开启',0=>'关闭'
]),
amis()->SelectControl('recommend', __('admin.honors.is_recommend'))
->columnRatio(3)
->options([
1=>'开启',0=>'关闭'
]),
]),
]))
->itemBadge([//行角标
'text' => __('admin.honors.is_recommend'),
'mode' => 'ribbon',
'position' => 'top-left',
'badgeLevel' => 'danger',
'visibleOn' => '${is_recommend > 0}',
'size' => 15
])
->columns([
amis()->TableColumn('id', __('admin.id'))->sortable(true),
amis()->TableColumn('title', __('admin.honors.title'))->width('300px'),
amis()->TableColumn('category', __('admin.honors.category'))->type('mapping')
->map(Keyword::allChildrenOfKey('honors')->pluck('name', 'id')->toArray())
->itemSchema(amis()->Tag()->label('${item}')->color(Admin::setting()->get('system_theme_setting')['theme_color'] ?? '#1677ff')),
amis()->TableColumn('cover_url', __('admin.articles.cover'))->type('image')->height('50px')->width('50px')->enlargeAble(true),
amis()->TableColumn('awarded_date', __('admin.honors.awarded_date')),
amis()->TableColumn('is_enable', __('admin.honors.is_enable'))->type('switch'),
amis()->TableColumn('is_recommend', __('admin.honors.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(): Form
{
return $this->baseForm()->panelClassName('px-0')->body([
amis()->Grid()->columns([
amis()->Wrapper()->body([
amis()->TextControl('title', __('admin.honors.title'))->required(true),
amis()->selectControl('cate', __('admin.honors.category'))->options(Keyword::allChildrenOfKey('honors')->pluck('name', 'id'))->required(true),
Components::make()->cropImageControl('cover', __('admin.honors.cover'))->required(true),
amis()->DateControl('awarded_date', __('admin.honors.awarded_date'))->format('YYYY-MM-DD')->required(true),
Components::make()->sortControl('sort', __('admin.honors.sort')),
amis()->SwitchControl('is_enable', __('admin.honors.is_enable'))->value(false),
amis()->SwitchControl('is_recommend', __('admin.honors.is_recommend'))->value(false),
]),
]),
]);
}
public function detail(): Form
{
return $this->baseDetail()->body([]);
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace App\Admin\Controllers;
use Slowlyo\OwlAdmin\Renderers\Page;
use Slowlyo\OwlAdmin\Renderers\Form;
use Slowlyo\OwlAdmin\Controllers\AdminController;
use App\Services\Admin\TimelineService;
use App\Traits\CustomActionTrait;
use App\Admin\Components;
use Slowlyo\OwlAdmin\Admin;
/**
* 发展历程
*
* @property ProjectArticleService $service
*/
class TimelineController extends AdminController
{
use CustomActionTrait;
protected string $serviceName = TimelineService::class;
public function list(): Page
{
$crud = $this->baseCRUD()->tableLayout('fixed')
->headerToolbar([
$this->createTypeButton('drawer', 'md'),
...$this->baseHeaderToolBar(),
])
->filter($this->baseFilter()->body([
amis()->GroupControl()->mode('horizontal')->body([
amis()->TextControl('title', __('admin.timelines.title'))->columnRatio(3)
->placeholder(__('admin.timelines.title')),
]),
]))
->columns([
// amis()->TableColumn('id', __('admin.id'))->sortable(true)->width('50px'),
amis()->TableColumn('title', __('admin.timelines.title'))->width('300px'),
amis()->TableColumn('cover_url', __('admin.timelines.cover'))->type('image')->height('50px')->width('150px')->enlargeAble(true),
amis()->TableColumn('awarded_date', __('admin.timelines.awarded_date')),
amis()->TableColumn('is_enable', __('admin.timelines.is_enable'))->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.timelines.title'))->required(true),
amis()->TextareaControl('description', __('admin.timelines.description')),
Components::make()->cropImageControl('cover', __('admin.timelines.cover')),
amis()->DateControl('awarded_date', __('admin.timelines.awarded_date'))->format('YYYY-MM-DD')->required(true),
Components::make()->sortControl('sort', __('admin.timelines.sort')),
amis()->SwitchControl('is_enable', __('admin.timelines.is_enable'))->value(false),
])
]),
]);
}
public function detail(): Form
{
return $this->baseDetail()->body([]);
}
}

View File

@ -40,6 +40,8 @@ Route::group([
$router->resource('project_advances', \App\Admin\Controllers\ProjectAdvanceController::class); $router->resource('project_advances', \App\Admin\Controllers\ProjectAdvanceController::class);
$router->resource('case_studies', \App\Admin\Controllers\CaseStudyController::class); $router->resource('case_studies', \App\Admin\Controllers\CaseStudyController::class);
$router->resource('friend_links', \App\Admin\Controllers\FriendLinkController::class); $router->resource('friend_links', \App\Admin\Controllers\FriendLinkController::class);
$router->resource('honors', \App\Admin\Controllers\HonorController::class);
$router->resource('timelines', \App\Admin\Controllers\TimelineController::class);
//修改上传 //修改上传
$router->post('upload_file', [\App\Admin\Controllers\IndexController::class, 'uploadFile']); $router->post('upload_file', [\App\Admin\Controllers\IndexController::class, 'uploadFile']);

View File

@ -0,0 +1,40 @@
<?php
namespace App\Models\Filters;
use Illuminate\Support\Arr;
use EloquentFilter\ModelFilter;
class HonorFilter extends ModelFilter
{
/**
* 主键
*/
public function id($id)
{
return $this->where('id', $id);
}
/**
* 标题
*/
public function title($title)
{
return $this->where('title','like', '%'.$title.'%');
}
/**
* 获取分类下的荣誉
*/
public function category($category)
{
return $this->where('category', $category);
}
public function enable($enable){
return $this->where('is_enable', $enable);
}
public function recommend($recommend){
return $this->where('is_recommend', $recommend);
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Models\Filters;
use Illuminate\Support\Arr;
use EloquentFilter\ModelFilter;
class TimelineFilter extends ModelFilter
{
/**
* 主键
*/
public function id($id)
{
return $this->where('id', $id);
}
/**
* 标题
*/
public function title($title)
{
return $this->where('title','like', '%'.$title.'%');
}
public function enable($enable){
return $this->where('is_enable', $enable);
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use EloquentFilter\Filterable;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Casts\Attribute;
class Honor extends Model
{
use HasFactory;
use Filterable;
protected function serializeDate(\DateTimeInterface $date)
{
return $date->format('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,
);
}
public function scopeRecommend($q){
$q->where('is_recommend', true);
}
public function scopeShow($q){
$q->where('is_enable', true);
}
public function scopeSort($q)
{
$q->orderBy('awarded_date', 'desc')
->orderBy('sort', 'asc')
->orderBy('created_at', 'desc');
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use EloquentFilter\Filterable;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Casts\Attribute;
class Timeline extends Model
{
use HasFactory;
use Filterable;
protected function serializeDate(\DateTimeInterface $date)
{
return $date->format('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,
);
}
public function scopeShow($q){
$q->where('is_enable', true);
}
public function scopeSort($q)
{
$q->orderBy('awarded_date', 'desc')
->orderBy('sort', 'asc')
->orderBy('created_at', 'desc');
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace App\Services\Admin;
use App\Models\Filters\HonorFilter;
use App\Models\Honor;
use App\Traits\UploadTrait;
use Illuminate\Support\Arr;
/**
* @method Article getModel()
* @method Article|\Illuminate\Database\Query\Builder query()
*/
class HonorService extends BaseService
{
use UploadTrait;
protected string $modelName = Honor::class;
protected string $modelFilterName = HonorFilter::class;
protected bool $modelSortAble = true;
public function store($data): bool
{
$columns = $this->getTableColumns();
$model = $this->getModel();
$data['cover'] = $this->saveImage('cover', 'honors/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', 'honors/cover')[0] ?? '';
}
foreach ($data as $k => $v) {
if (!in_array($k, $columns)) {
continue;
}
$model->setAttribute($k, $v);
}
return $model->save();
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace App\Services\Admin;
use App\Models\Filters\TimelineFilter;
use App\Models\Timeline;
use App\Traits\UploadTrait;
use Illuminate\Support\Arr;
/**
* @method Article getModel()
* @method Article|\Illuminate\Database\Query\Builder query()
*/
class TimelineService extends BaseService
{
use UploadTrait;
protected string $modelName = Timeline::class;
protected string $modelFilterName = TimelineFilter::class;
protected bool $modelSortAble = true;
public function store($data): bool
{
$columns = $this->getTableColumns();
$model = $this->getModel();
$data['cover'] = $this->saveImage('cover', 'honors/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', 'honors/cover')[0] ?? '';
}
foreach ($data as $k => $v) {
if (!in_array($k, $columns)) {
continue;
}
$model->setAttribute($k, $v);
}
return $model->save();
}
}

View File

@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('honors', function (Blueprint $table) {
$table->id();
$table->string('title')->comment('标题');
$table->string('cover')->nullable()->comment('封面');
$table->unsignedInteger('category')->nullable()->comment('分类');
$table->date('awarded_date')->nullable()->comment('获得日期');
$table->unsignedTinyInteger('is_enable')->default(1)->comment('显示开关');
$table->unsignedTinyInteger('is_recommend')->default(0)->comment('推荐开关');
$table->unsignedInteger('sort')->default(0)->comment('排序');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('honors');
}
};

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('timelines', function (Blueprint $table) {
$table->id();
$table->string('title')->comment('标题');
$table->text('description')->nullable()->comment('简介');
$table->string('cover')->nullable()->comment('封面');
$table->date('awarded_date')->nullable()->comment('日期');
$table->unsignedTinyInteger('is_enable')->default(1)->comment('显示开关');
$table->unsignedInteger('sort')->default(0)->comment('排序');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('timelines');
}
};

View File

@ -29,11 +29,14 @@ class AdminMenuSeeder extends Seeder
['title'=> 'project_advances', 'icon'=>'', 'url'=>'/project_advances', 'order'=>5], ['title'=> 'project_advances', 'icon'=>'', 'url'=>'/project_advances', 'order'=>5],
] ]
], ],
['title'=>'case_studies', 'icon'=>'carbon:cloud-satellite-services','url'=>'/case_studies', 'order'=>3], // ['title'=>'case_studies', 'icon'=>'carbon:cloud-satellite-services','url'=>'/case_studies', 'order'=>3],
['title' => 'web_content', 'icon' => 'ic:outline-collections-bookmark', 'url' => '/web_content', 'order'=>4, ['title' => 'web_content', 'icon' => 'ic:outline-collections-bookmark', 'url' => '/web_content', 'order'=>4,
'children' =>[ 'children' =>[
['title'=>'news', 'icon'=>'','url'=>'/articles', 'order'=>1], ['title'=>'news', 'icon'=>'','url'=>'/articles', 'order'=>1],
['title'=>'ads', 'icon'=>'','url'=>'/ads', 'order'=>2], ['title'=>'honors', 'icon'=>'','url'=>'/honors', 'order'=>2],
['title'=>'case_studies', 'icon'=>'','url'=>'/case_studies', 'order'=>3],
['title'=>'timelines', 'icon'=>'','url'=>'/timelines', 'order'=>4],
['title'=>'ads', 'icon'=>'','url'=>'/ads', 'order'=>5],
] ]
], ],
['title'=> 'contacts', 'icon'=>'fluent-mdl2:chat-invite-friend','url'=>'/contacts', 'order'=>5], ['title'=> 'contacts', 'icon'=>'fluent-mdl2:chat-invite-friend','url'=>'/contacts', 'order'=>5],
@ -48,9 +51,6 @@ class AdminMenuSeeder extends Seeder
['title' => 'keywords', 'icon' => '', 'url' => '/system/keywords', 'order'=>6] ['title' => 'keywords', 'icon' => '', 'url' => '/system/keywords', 'order'=>6]
], ],
], ],
]; ];
DB::table('admin_menus')->truncate(); DB::table('admin_menus')->truncate();
try { try {

View File

@ -18,14 +18,18 @@ class KeywordSeeder extends Seeder
Keyword::truncate(); Keyword::truncate();
$list = [ $list = [
// ['key' => 'article_category', 'name' => '文章分类', 'list' => [ // ['key' => 'article_category', 'name' => '文章分类', 'list' => [
// 'examples'=>'案例', 'services' =>'服务', 'news'=> '资讯动态' // 'news'=> '企业资讯', 'honors'=>'资质荣誉',
// ]], // ]],
['key' => 'case_study_tag', 'name' => '服务案例标签', 'list' => [//标签value填写色号指定标签颜色
]],
['key' => 'banner_address', 'name' => '广告位置', 'list' => [ ['key' => 'banner_address', 'name' => '广告位置', 'list' => [
'index-top'=>'首页', 'companny-top' =>'关于我们', 'project-top'=>'业务范围', 'examples-top'=> '案例展示', 'news-top'=>'资讯动态','contactus-top'=>'联系我们' 'index-top'=>'首页', 'companny-top' =>'关于我们', 'project-top'=>'业务范围', 'examples-top'=> '案例展示', 'news-top'=>'资讯动态','contactus-top'=>'联系我们'
]], ]],
['key' => 'honors', 'name' => '资质荣誉', 'list' => [
]],
['key' => 'case_study_tag', 'name' => '服务案例标签', 'list' => [//标签value填写色号指定标签颜色
]],
]; ];
foreach ($list as $item) { foreach ($list as $item) {

View File

@ -353,5 +353,25 @@ return [
'sort' => '排序', 'sort' => '排序',
'is_enable' => '显示', 'is_enable' => '显示',
'link'=>'链接地址' 'link'=>'链接地址'
] ],
'honors' => [
'id' => '主键ID',
'title' => '标题',
'cover' =>'封面',
'category' => '分类',
'awarded_date' => '获奖日期',
'is_enable' => '显示',
'is_recommend' => '推荐',
'sort' => '排序',
],
'timelines' => [
'id' => '主键ID',
'title' => '标题',
'description'=> '简介',
'cover' =>'封面',
'awarded_date' => '日期',
'is_enable' => '显示',
'is_recommend' => '推荐',
'sort' => '排序',
],
]; ];

View File

@ -12,7 +12,7 @@ return [
'keywords' => '数据字典', 'keywords' => '数据字典',
'web_content' => '内容管理', 'web_content' => '内容管理',
'articles' => '文章管理', 'articles' => '文章管理',
'ads' => '广告管理', 'ads' => 'Banner管理',
'web_manager' => '网站管理', 'web_manager' => '网站管理',
'projects' => '主营业务', 'projects' => '主营业务',
@ -24,6 +24,8 @@ return [
'case_studies' => '服务案例', 'case_studies' => '服务案例',
'case_study_tags' => '案例标签', 'case_study_tags' => '案例标签',
'case_study_articles' => '案例内容', 'case_study_articles' => '案例内容',
'honors' => '荣誉资质',
'timelines' => '发展历程',
'news' => '企业资讯', 'news' => '企业资讯',
'contacts' => '在线询价', 'contacts' => '在线询价',
'friend_links' => '合作伙伴' 'friend_links' => '合作伙伴'