1
0
Fork 0
master
panliang 2023-12-01 11:02:18 +08:00
parent fa8b07eb58
commit 5202921132
14 changed files with 279 additions and 25 deletions

View File

@ -77,14 +77,6 @@ class Components extends BaseRenderer
->excludeKeys(['group-video']);
}
/**
* 字典表下拉框
*/
public function keywordTypeControl($type)
{
return amisMake()->SelectControl()->source(admin_url('api/keywords/list').'?type_key='.$type);
}
/**
* switch
*

View File

@ -0,0 +1,70 @@
<?php
namespace App\Admin\Controllers;
use App\Admin\Components;
use App\Admin\Services\ArticleService;
use Slowlyo\OwlAdmin\Controllers\AdminController;
use Slowlyo\OwlAdmin\Renderers\Form;
use Slowlyo\OwlAdmin\Renderers\Page;
class ArticleController extends AdminController
{
protected string $serviceName = ArticleService::class;
public function list(): Page
{
$crud = $this->baseCRUD()
->filterTogglable(false)
->columnsTogglable(false)
->headerToolbar([
$this->createButton(true, 'lg'),
])
->filter($this->baseFilter()->actions([])->body([
amisMake()->TextControl()->name('title')->label(__('article.title'))->size('md')->clearable(),
// amisMake()->Button()->label(__('admin.reset'))->actionType('clear-and-submit'),
amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'),
]))
->quickSaveItemApi(admin_url('quick-edit/article/$id'))
->columns([
amisMake()->TableColumn()->name('id')->label(__('article.id'))->sortable(true),
amisMake()->TableColumn()->name('title')->label(__('article.title')),
amisMake()->TableColumn()->name('category.name')->label(__('article.category_id'))->className('text-primary'),
amisMake()->Image()->name('cover')->label(__('article.cover'))->width(100),
amisMake()->TableColumn()->name('sort')->label(__('article.sort'))->align('center')->quickEdit(Components::make()->sortControl('sort', __('article.sort'))->saveImmediately(true)),
Components::make()->switchControl('table')->name('is_enable')->label(__('article.is_enable')),
amisMake()->TableColumn()->name('published_at')->label(__('article.published_at')),
$this->rowActions(true, 'lg'),
]);
return $this->baseList($crud);
}
public function form(): Form
{
return $this->baseForm()->title('')->body([
amisMake()->TextControl()->name('title')->label(__('article.title'))->required(true),
Components::make()->parentControl(admin_url('api/keywords/tree-list'), 'category_id', __('article.category_id'))->onlyLeaf(true)->required(),
amisMake()->ImageControl()->name('cover')->label(__('article.cover'))->autoUpload(true),
Components::make()->sortControl('sort', __('article.sort')),
amisMake()->DateTimeControl()->name('published_at')->label(__('article.published_at'))->value(now())->format('YYYY-MM-DD HH:mm:ss')->description('*不填写则默认为创建时间'),
Components::make()->switchControl('form')->name('is_enable')->label(__('article.is_enable'))->value(true),
Components::make()->fuEditorControl('content', __('article.content')),
]);
}
public function detail(): Form
{
return $this->baseDetail()->title('')->body([
amisMake()->TextControl()->static(true)->name('id')->label(__('article.id')),
amisMake()->TextControl()->static(true)->name('title')->label(__('article.title')),
amisMake()->TextControl()->static(true)->name('category.name')->label(__('article.category_id')),
amisMake()->TextControl()->name('cover')->label(__('article.cover'))->static(true)->staticSchema(amisMake()->Image()),
amisMake()->TextControl()->static(true)->name('sort')->label(__('article.sort')),
Components::make()->switchControl('show')->name('is_enable')->label(__('article.is_enable')),
amisMake()->TextControl()->static(true)->name('published_at')->label(__('article.published_at')),
amisMake()->TextControl()->static(true)->name('created_at')->label(__('article.created_at')),
Components::make()->fuEditorControl('content', __('article.content'))->static(true),
]);
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace App\Admin\Services;
use App\ModelFilters\ArticleFilter;
use App\Models\Article;
use App\Models\Keyword;
use Illuminate\Support\Facades\Validator;
class ArticleService extends BaseService
{
protected array $withRelationships = ['category'];
protected string $modelName = Article::class;
protected string $modelFilterName = ArticleFilter::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();
}
public function resloveData($data)
{
$cid = data_get($data, 'category_id');
if ($cid && $category = Keyword::find($cid)) {
$data['category_path'] = $category->path.$category->id.'-';
}
if (! data_get($data, 'published_at')) {
$data['published_at'] = now();
}
return $data;
}
public function validate($data, $model = null)
{
$createRules = [
];
$updateRules = [
];
$validator = Validator::make($data, $model ? $updateRules : $createRules, [
]);
if ($validator->fails()) {
return $validator->errors()->first();
}
return true;
}
}

View File

@ -2,6 +2,7 @@
namespace App\Admin\Services;
use Illuminate\Database\Eloquent\Model;
use Slowlyo\OwlAdmin\Services\AdminService;
/**
@ -80,7 +81,7 @@ class BaseService extends AdminService
{
$data = $this->resloveData($data);
$model = $this->query()->whereKey($primaryKey)->firstOrFail();
$validate = $this->validate($data, $model->id);
$validate = $this->validate($data, $model);
if ($validate !== true) {
$this->setError($validate);
return false;
@ -102,7 +103,7 @@ class BaseService extends AdminService
/**
* 处理表单数据
*
*
* @param array $data
* @return array
*/
@ -113,19 +114,19 @@ class BaseService extends AdminService
/**
* 表单验证
*
*
* @param array $data
* @param int $id : 添加, 非空: 修改
* @param Model $model : 添加, 非空: 修改
* @return mixed true: 验证通过, string: 错误提示
*/
public function validate($data, $id = null)
public function validate($data, $model = null)
{
return true;
}
/**
* 删除的前置方法
*
*
* @param array $ids 主键id
* @return mixed true: 继续后续操作, string: 中断操作, 返回错误提示
*/

View File

@ -33,7 +33,7 @@ class KeywordService extends BaseService
/**
* 删除的前置方法
*
*
* @param array $ids 主键id
* @return mixed true: 继续后续操作, string: 中断操作, 返回错误提示
*/
@ -49,16 +49,16 @@ class KeywordService extends BaseService
return true;
}
public function validate($data, $id = null)
public function validate($data, $model = null)
{
$createRules = [
'key' => ['required', Rule::unique('keywords', 'key')],
'name' => ['required'],
];
$updateRules = [
'key' => [Rule::unique('keywords', 'key')->ignore($id)]
'key' => [Rule::unique('keywords', 'key')->ignore($model->id)]
];
$validator = Validator::make($data, $id ? $updateRules : $createRules, [
$validator = Validator::make($data, $model ? $updateRules : $createRules, [
'key.unique' => ':input 已经存在'
]);
if ($validator->fails()) {

View File

@ -11,7 +11,7 @@ Route::group([
$router->resource('dashboard', \App\Admin\Controllers\HomeController::class);
$router->get('menus', [\App\Admin\Controllers\HomeController::class, 'menus']);
$router->get('login', [App\Admin\Controllers\AuthController::class, 'loginPage']);
$router->resource('system/settings', \App\Admin\Controllers\SettingController::class);
@ -28,4 +28,7 @@ Route::group([
// 字典表
$router->resource('keywords', \App\Admin\Controllers\KeywordsController::class)->names('admin.keywords');
$router->resource('articles', \App\Admin\Controllers\ArticleController::class);
$router->post('quick-edit/article/{article}', [\App\Admin\Controllers\ArticleController::class, 'update']);
});

View File

@ -0,0 +1,16 @@
<?php
namespace App\ModelFilters;
use EloquentFilter\ModelFilter;
class ArticleFilter extends ModelFilter
{
/**
* Related Models that have ModelFilters as well as the method on the ModelFilter
* As [relationMethod => [input_key1, input_key2]].
*
* @var array
*/
public $relations = [];
}

View File

@ -25,11 +25,6 @@ class KeywordFilter extends ModelFilter
$this->whereLike('key', $key);
}
public function typeKey($key)
{
$this->where('type_key', $key);
}
public function name($key)
{
$this->whereLike('name', $key);

View File

@ -0,0 +1,48 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use EloquentFilter\Filterable;
use App\Traits\HasDateTimeFormatter;
use App\Casts\StorageFile;
/**
* 文章
*/
class Article extends Model
{
use Filterable, HasDateTimeFormatter;
protected $fillable = [
'category_id', 'category_path', 'key',
'title', 'cover', 'description', 'author', 'content',
'files', 'medias', 'extension',
'is_enable', 'is_recommend',
'published_at', 'remarks', 'sort',
'party_cate_id',
];
protected $casts = [
'cover' => StorageFile::class,
'files' => 'array',
'medias' => 'array',
'extension' => 'array',
'published_at' => 'datetime',
];
public function category()
{
return $this->belongsTo(Keyword::class, 'category_id');
}
public function scopeSort($q)
{
return $q->orderBy('sort', 'asc')->latest('published_at')->latest('id');
}
public function scopePublish($q)
{
return $q->where('published_at', '<=', now())->where('is_enable', 1);
}
}

View File

@ -31,7 +31,7 @@ return [
// 是否开启验证码
'login_captcha' => env('ADMIN_LOGIN_CAPTCHA', true),
// 是否开启鉴权
'enable' => true,
'enable' => false,
// 用户模型
'model' => \Slowlyo\OwlAdmin\Models\AdminUser::class,
'controller' => \Slowlyo\OwlAdmin\Controllers\AuthController::class,

View File

@ -0,0 +1,49 @@
<?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('articles', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('category_id')->comment('分类ID');
$table->string('category_path')->default('-')->comment('分类 path');
$table->string('title')->comment('文章标题');
$table->string('key')->nullable('用于指定查询某一篇文章');
$table->string('description')->nullable()->comment('描述');
$table->string('author')->nullable()->comment('作者');
$table->string('cover')->nullable()->comment('封面');
$table->longText('content')->nullable()->comment('文章内容');
$table->json('medias')->nullable()->comment('媒体[{name,url,type}]');
$table->json('files')->nullable()->comment('附件[{name,url,type}]');
$table->timestamp('published_at')->nullable()->comment('发布时间');
$table->unsignedInteger('sort')->default(1)->comment('排序(asc)');
$table->string('remarks')->nullable()->comment('备注');
$table->unsignedTinyInteger('is_recommend')->default(0)->comment('推荐状态');
$table->unsignedTinyInteger('is_enable')->default(1)->comment('可用状态');
$table->json('extension')->nullable()->comment('扩展字段');
$table->unsignedBigInteger('party_cate_id')->nullable()->comment('党支部ID');
$table->timestamps();
$table->comment('文章');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('articles');
}
};

View File

@ -19,6 +19,7 @@ class AdminMenuSeeder extends Seeder
// 图标: https://iconpark.oceanengine.com/official
$menus = [
['title' => '主页', 'icon' => 'icon-park:home-two', 'url' => '/dashboard', 'is_home' => 1],
['title' => '文章管理', 'icon' => 'icon-park:web-page', 'url' => '/articles'],
['title' => '系统管理', 'icon' => 'icon-park:setting', 'url' => '/system', 'children' => [
['title' => '用户管理', 'icon' => 'icon-park:people-plus', 'url' => '/system/admin_users'],
['title' => '角色管理', 'icon' => 'icon-park:people-plus-one', 'url' => '/system/admin_roles'],

View File

@ -0,0 +1,17 @@
<?php
return [
'id' => 'ID',
'created_at' => '创建时间',
'description' => '描述',
'author' => '作者',
'category_id' => '分类',
'category_path' => '分类',
'content' => '内容',
'cover' => '封面图',
'is_enable' => '显示',
'is_recommend' => '推荐',
'published_at' => '发布时间',
'sort' => '排序(正序)',
'title' => '标题',
];