article todo
parent
21cd0da1a7
commit
4995c1c367
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\TableColumn;
|
||||
use Slowlyo\OwlAdmin\Renderers\TextControl;
|
||||
use Slowlyo\OwlAdmin\Renderers\{Form, Page};
|
||||
use Slowlyo\OwlAdmin\Renderers\{TableColumn, TextControl, Image, ImageControl, DateTimeControl, SwitchControl, Tabs, Tab};
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use App\Services\Admin\ArticleService;
|
||||
use App\Admin\Components;
|
||||
|
|
@ -14,26 +12,19 @@ class ArticleController extends AdminController
|
|||
{
|
||||
protected string $serviceName = ArticleService::class;
|
||||
|
||||
protected string $pageTitle = '文章管理';//待完善-todo
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
->filterTogglable(false)
|
||||
->headerToolbar([
|
||||
$this->createButton(true, 'lg'),
|
||||
...$this->baseHeaderToolBar(),
|
||||
])
|
||||
->columns([
|
||||
TableColumn::make()->name('id')->label('ID')->sortable(true),
|
||||
TableColumn::make()->name('title')->label('标题'),
|
||||
TableColumn::make()->name('category_id')->label('分类')->className('text-primary'),
|
||||
TableColumn::make()->name('sub_title')->label('副标题'),
|
||||
TableColumn::make()->name('is_enable')->type('switch')->label('显示'),
|
||||
TableColumn::make()->name('published_at')->label('发布时间')->type('datetime')->sortable(true),
|
||||
TableColumn::make()->name('created_at')->label('创建时间')->type('datetime')->sortable(true),
|
||||
TableColumn::make()->name('updated_at')->label('更新时间')->type('datetime')->sortable(true),
|
||||
$this->rowActions(true, 'lg'),
|
||||
TableColumn::make()->name('id')->label(__('article.id'))->sortable(true),
|
||||
TableColumn::make()->name('title')->label(__('article.title')),
|
||||
TableColumn::make()->name('category.name')->label(__('article.category_id'))->className('text-primary'),
|
||||
Image::make()->name('cover')->label(__('article.cover'))->width(100),
|
||||
TableColumn::make()->name('sub_title')->label(__('article.sub_title')),
|
||||
TableColumn::make()->name('is_enable')->type('switch')->label(__('article.is_enable')),
|
||||
TableColumn::make()->name('published_at')->label(__('article.published_at')),
|
||||
$this->rowActions(),
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
|
|
@ -41,25 +32,34 @@ class ArticleController extends AdminController
|
|||
|
||||
public function form(): Form
|
||||
{
|
||||
return $this->baseForm()->body([
|
||||
TextControl::make()->name('title')->label('标题')->required(true),
|
||||
TextControl::make()->name('sub_title')->label('副标题'),
|
||||
\amisMake()->ImageControl()->name('cover')->label('封面')->autoUpload(true),
|
||||
Components::make()->parentControl('', 'category_id', '分类'),
|
||||
Components::make()->fuEditorControl(),
|
||||
Components::make()->sortControl(),
|
||||
\amisMake()->DateTimeControl()->name('published_at')->label('发布时间')->description('*不填写则默认为创建时间'),
|
||||
\amisMake()->SwitchControl()->name('is_enable')->label('显示'),
|
||||
]);
|
||||
return $this->baseForm()->title('')->body(
|
||||
Tabs::make()->tabs([
|
||||
Tab::make()->title('基本信息')->body([
|
||||
TextControl::make()->name('title')->label(__('article.title'))->required(true),
|
||||
Components::make()->parentControl(admin_url('api/article-categories/tree-list'), 'category_id', __('article.category_id'))->required(true),
|
||||
TextControl::make()->name('sub_title')->label(__('article.sub_title')),
|
||||
ImageControl::make()->name('cover')->label(__('article.cover'))->autoUpload(true),
|
||||
Components::make()->sortControl('sort', __('article.sort')),
|
||||
DateTimeControl::make()->name('published_at')->label(__('article.published_at'))->value(now())->format('YYYY-MM-DD HH:mm:ss')->description('*不填写则默认为创建时间'),
|
||||
SwitchControl::make()->name('is_enable')->label(__('article.is_enable'))->value(true),
|
||||
]),
|
||||
Tab::make()->title('内容')->body(Components::make('content', __('article.content'))->fuEditorControl())
|
||||
]));
|
||||
}
|
||||
|
||||
public function detail(): Form
|
||||
{
|
||||
return $this->baseDetail()->body([
|
||||
TextControl::make()->static(true)->name('id')->label('ID'),
|
||||
TextControl::make()->static(true)->name('title')->label('标题'),
|
||||
TextControl::make()->static(true)->name('created_at')->label('创建时间'),
|
||||
TextControl::make()->static(true)->name('updated_at')->label('更新时间')
|
||||
]);
|
||||
return $this->baseDetail()->title('')->body(
|
||||
Tabs::make()->tabs(
|
||||
Tab::make()->title('基本信息')->body([
|
||||
TextControl::make()->static(true)->name('id')->label(__('article.id')),
|
||||
TextControl::make()->static(true)->name('title')->label(__('article.title')),
|
||||
TextControl::make()->static(true)->name('category.name')->label(__('article.category_id')),
|
||||
TextControl::make()->static(true)->name('title')->label(__('article.sub_title')),
|
||||
TextControl::make()->static(true)->name('created_at')->label(__('article.created_at')),
|
||||
]),
|
||||
Tab::make()->title('内容')->body('1234567')
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,21 +2,48 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use EloquentFilter\Filterable;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
/**
|
||||
* 文章
|
||||
*/
|
||||
class Article extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Filterable;
|
||||
|
||||
protected $fillable = [];
|
||||
protected $fillable = ['author', 'category_id', 'category_path', 'content', 'cover', 'is_enable', 'is_recommend', 'published_at', 'sort', 'sub_title', 'title'];
|
||||
|
||||
protected function serializeDate(\DateTimeInterface $date){
|
||||
return $date->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',
|
||||
'published_at' => 'datetime:Y-m-d H:i:s',
|
||||
'is_enable' => 'boolean',
|
||||
'is_recommend' => 'boolean',
|
||||
];
|
||||
|
||||
protected function cover(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn($value) => $value ? (Str::startsWith($value, ['http://', 'https://']) ? $value : Storage::url($value)) : '',
|
||||
);
|
||||
}
|
||||
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(ArticleCategory::class, 'category_id');
|
||||
}
|
||||
|
||||
public function scopeSort($q)
|
||||
{
|
||||
return $q->orderBy('sort', 'desc')->orderBy('published_at', 'desc');
|
||||
}
|
||||
|
||||
public function scopeShow($q)
|
||||
{
|
||||
return $q->where('is_enable', 1)->where(fn ($q1) => $q1->whereNull('published_at')->orWhere('published_at', '<=', now()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,33 @@
|
|||
namespace App\Services\Admin;
|
||||
|
||||
use App\Models\Article;
|
||||
use Slowlyo\OwlAdmin\Services\AdminService;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @method Article getModel()
|
||||
* @method Article|\Illuminate\Database\Query\Builder query()
|
||||
*/
|
||||
class ArticleService extends AdminService
|
||||
class ArticleService extends BaseService
|
||||
{
|
||||
protected array $withRelationships = ['category'];
|
||||
|
||||
protected string $modelName = Article::class;
|
||||
|
||||
public function listQuery()
|
||||
{
|
||||
$model = $this->getModel();
|
||||
$filter = $this->getModelFilter();
|
||||
|
||||
$query = $this->query();
|
||||
if($this->withRelationships){
|
||||
$query->with($this->withRelationships);
|
||||
}
|
||||
|
||||
if ($filter) {
|
||||
$query->filter(request()->input(), $filter);
|
||||
}
|
||||
|
||||
return $query->sort();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ use Slowlyo\OwlAdmin\Services\AdminService;
|
|||
*/
|
||||
class BaseService extends AdminService
|
||||
{
|
||||
protected array $withRelationships = array();
|
||||
protected array $withRelationships = [];
|
||||
|
||||
protected string $modelFilterName = '';
|
||||
|
||||
public function getTree()
|
||||
{
|
||||
|
|
@ -33,8 +35,15 @@ class BaseService extends AdminService
|
|||
$query->with($this->withRelationships);
|
||||
}
|
||||
|
||||
return $query
|
||||
->filter(request()->input(), $filter)
|
||||
->orderByDesc($model->getUpdatedAtColumn() ?? $model->getKeyName());
|
||||
if ($filter) {
|
||||
$query->filter(request()->input(), $filter);
|
||||
}
|
||||
|
||||
return $query->orderByDesc($model->getUpdatedAtColumn() ?? $model->getKeyName());
|
||||
}
|
||||
|
||||
public function getDetail($id)
|
||||
{
|
||||
return $this->query()->with($this->withRelationships)->find($id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ return new class extends Migration
|
|||
// 可能用到的额外字段
|
||||
$table->string('cover')->nullable()->comment('封面');
|
||||
$table->string('author')->nullable()->comment('作者/来源');
|
||||
$table->string('category_path')->nullable()->comment('上级分类');
|
||||
$table->string('category_path')->nullable()->comment('所有上级分类id');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'created_at' => '创建时间',
|
||||
'author' => '作者',
|
||||
'category_id' => '分类',
|
||||
'category_path' => '',
|
||||
'content' => '内容',
|
||||
'cover' => '封面图',
|
||||
'is_enable' => '显示',
|
||||
'is_recommend' => '推荐',
|
||||
'published_at' => '发布时间',
|
||||
'sort' => '排序(倒序)',
|
||||
'sub_title' => '副标题',
|
||||
'title' => '标题',
|
||||
];
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<link rel="icon" href="/admin/logo.png"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
||||
<title></title>
|
||||
<title>Document</title>
|
||||
<script type="module" crossorigin src="/admin/assets/index.ea99f164.js"></script>
|
||||
<link rel="stylesheet" href="/admin/assets/index.32057522.css">
|
||||
</head>
|
||||
|
|
|
|||
Loading…
Reference in New Issue