article-caetgory
parent
26a9d2458c
commit
24a19ccfd7
|
|
@ -2,14 +2,13 @@
|
|||
|
||||
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\{Component, TableColumn, TextControl, Button, Image, Status, NumberControl, SwitchControl, ImageControl};
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use App\Services\Admin\ArticleCategoryService;
|
||||
use App\Admin\Components;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class ArticleCategoryController extends AdminController
|
||||
{
|
||||
|
|
@ -23,22 +22,22 @@ class ArticleCategoryController extends AdminController
|
|||
->footerToolbar([])
|
||||
->headerToolbar([
|
||||
$this->createButton(true),
|
||||
amis('reload')->align('right'),
|
||||
amis('filter-toggler')->align('right'),
|
||||
...$this->baseHeaderToolBar(),
|
||||
])
|
||||
->filter($this->baseFilter()->actions([])->body([
|
||||
TextControl::make()->name('name')->label(__('article-category.name'))->size('md'),
|
||||
Components::make()->parentControl(admin_url('api/article-categories/tree-list'), 'parent_path')->size('lg'),
|
||||
Button::make()->label(__('admin.reset'))->actionType('clear-and-submit'),
|
||||
Component::make()->setType('submit')->label(__('admin.search'))->level('primary'),
|
||||
]))
|
||||
->quickSaveItemApi(admin_url('quick-edit/article-categories/$id'))
|
||||
->quickSaveApi(admin_url('quick-edit/article-categories'))
|
||||
->columns([
|
||||
['name' => 'id', 'label' => __('article-category.id')],
|
||||
['name' => 'name', 'label' => __('article-category.name')],
|
||||
['name' => 'icon', 'label' => __('article-category.icon'), 'type' => 'image', 'width' => 60],
|
||||
['name' => 'sort', 'label' => __('article-category.sort')],
|
||||
['name' => 'is_enable', 'label' => __('article-category.is_enable'), 'type' => 'switch', 'quickEdit' => [
|
||||
'type' => 'switch',
|
||||
'mode' => 'inline',
|
||||
'onText' => __('admin.switch.on'),
|
||||
'offText' => __('admin.switch.off'),
|
||||
'saveImmediately' => true,
|
||||
]],
|
||||
TableColumn::make()->name('id')->label(__('article-category.id')),
|
||||
TableColumn::make()->name('name')->label(__('article-category.name')),
|
||||
TableColumn::make()->name('icon')->label(__('article-category.icon'))->type('image')->width(60),
|
||||
TableColumn::make()->name('sort')->label(__('article-category.sort'))->align('center')->quickEdit(Components::make()->sortControl('sort', __('article-category.sort'))),
|
||||
TableColumn::make()->name('is_enable')->label(__('article-category.is_enable'))->type('switch')->quickEdit(SwitchControl::make()->mode('inline')->onText(__('admin.extensions.status_map.enabled'))->offText(__('admin.extensions.status_map.disabled'))->saveImmediately(true)),
|
||||
$this->rowActions(true),
|
||||
]);
|
||||
|
||||
|
|
@ -47,21 +46,27 @@ class ArticleCategoryController extends AdminController
|
|||
|
||||
public function form(): Form
|
||||
{
|
||||
return $this->baseForm()->body([
|
||||
TextControl::make()->name('name')->label('名称')->required(true),
|
||||
amisMake()->ImageControl()->name('icon')->label('icon')->autoUpload(true),
|
||||
return $this->baseForm()->title('')->body([
|
||||
TextControl::make()->name('name')->label(__('article-category.name'))->required(true),
|
||||
ImageControl::make()->name('icon')->label(__('article-category.name'))->autoUpload(true),
|
||||
Components::make()->parentControl(admin_url('api/article-categories/tree-list')),
|
||||
Components::make()->sortControl(),
|
||||
amisMake()->SwitchControl()->name('is_enable')->value(true)->label('显示'),
|
||||
Components::make()->sortControl('sort', __('article-category.sort')),
|
||||
SwitchControl::make()->name('is_enable')->label(__('article-category.is_enable'))->onText(__('admin.extensions.status_map.enabled'))->offText(__('admin.extensions.status_map.disabled'))->value(true),
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail(): Form
|
||||
{
|
||||
return $this->baseDetail()->body([
|
||||
['name' => 'id', 'type' => 'static', 'label' => __('article-category.id')],
|
||||
['name' => 'name', 'type' => 'static', 'label' => __('article-category.name')],
|
||||
['name' => 'created_at', 'type' => 'static', 'label' => __('article-category.created_at')],
|
||||
TextControl::make()->name('id')->label(__('article-category.id'))->static(true),
|
||||
TextControl::make()->name('name')->label(__('article-category.name'))->static(true),
|
||||
TextControl::make()->name('icon')->label(__('article-category.icon'))->static(true)->staticSchema(Image::make()),
|
||||
TextControl::make()->name('sort')->label(__('article-category.sort'))->static(true),
|
||||
TextControl::make()->name('is_enable')->label(__('article-category.is_enable'))->static(true)->staticSchema(Status::make()->source([
|
||||
['label' => __('admin.extensions.status_map.disabled'), 'icon' => 'fa fa-close', 'color' => '#cc292e'],
|
||||
['label' => __('admin.extensions.status_map.enabled'), 'icon' => 'fa fa-check', 'color' => '#30bf13'],
|
||||
])),
|
||||
TextControl::make()->name('created_at')->label(__('article-category.created_at'))->static(true),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -70,10 +75,17 @@ class ArticleCategoryController extends AdminController
|
|||
return $this->service->getTree();
|
||||
}
|
||||
|
||||
public function quickSave(Request $request)
|
||||
public function multipleUpdate(Request $request)
|
||||
{
|
||||
logger('1', $request->all());
|
||||
|
||||
$diff = $request->input('rowsDiff');
|
||||
foreach ($diff as $item) {
|
||||
$this->service->update(data_get($item, 'id'), Arr::except($item, ['id']));
|
||||
}
|
||||
return $this->response()->success();
|
||||
}
|
||||
|
||||
protected function switchFiled($name = 'is_enable')
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ Route::group([
|
|||
// 文章分类
|
||||
$router->resource('article-categories', \App\Admin\Controllers\ArticleCategoryController::class);
|
||||
$router->post('quick-edit/article-categories/{article_category}', [\App\Admin\Controllers\ArticleCategoryController::class, 'update']);
|
||||
$router->post('quick-edit/article-categories', [\App\Admin\Controllers\ArticleCategoryController::class, 'multipleUpdate']);
|
||||
//文章管理
|
||||
$router->resource('articles', \App\Admin\Controllers\ArticleController::class);
|
||||
//图片位置
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
|
||||
class ArticleCategoryFilter 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 = [];
|
||||
|
||||
public function name($v)
|
||||
{
|
||||
$this->whereLike('name', $v);
|
||||
}
|
||||
|
||||
public function parentId($v)
|
||||
{
|
||||
$this->where('parent_id', $v);
|
||||
}
|
||||
|
||||
public function parentPath($v)
|
||||
{
|
||||
$this->where('path', 'like', '%-'.$v.'-%');
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,9 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use EloquentFilter\Filterable;
|
||||
|
||||
/**
|
||||
* 文章
|
||||
*/
|
||||
class Article extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
|
|||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* 文章分类
|
||||
*/
|
||||
class ArticleCategory extends Model
|
||||
{
|
||||
use Filterable;
|
||||
|
|
@ -36,4 +39,14 @@ class ArticleCategory extends Model
|
|||
{
|
||||
return $this->hasMany(static::class, 'parent_id');
|
||||
}
|
||||
|
||||
public function scopeSort($q)
|
||||
{
|
||||
return $q->orderBy('sort', 'desc');
|
||||
}
|
||||
|
||||
public function scopeShow($q)
|
||||
{
|
||||
return $q->where('is_enable', 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,22 +2,23 @@
|
|||
|
||||
namespace App\Services\Admin;
|
||||
|
||||
use App\Models\ArticleCategory;
|
||||
use Slowlyo\OwlAdmin\Services\AdminService;
|
||||
use App\Models\{ArticleCategory, Article};
|
||||
use Illuminate\Http\Request;
|
||||
use App\Filters\ArticleCategoryFilter;
|
||||
|
||||
/**
|
||||
* @method ArticleCategory getModel()
|
||||
* @method ArticleCategory|\Illuminate\Database\Query\Builder query()
|
||||
*/
|
||||
class ArticleCategoryService extends AdminService
|
||||
class ArticleCategoryService extends BaseService
|
||||
{
|
||||
protected string $modelName = ArticleCategory::class;
|
||||
protected string $modelFilterName = ArticleCategoryFilter::class;
|
||||
|
||||
public function getTree()
|
||||
{
|
||||
$list = $this->query()->orderByDesc('sort')->get()->toArray();
|
||||
return array2tree($list);
|
||||
$list = $this->query()->filter(request()->all(), $this->modelFilterName)->sort()->get()->toArray();
|
||||
return array2tree($list, request('parent_path', 0));
|
||||
}
|
||||
|
||||
public function list()
|
||||
|
|
@ -38,8 +39,31 @@ class ArticleCategoryService extends AdminService
|
|||
return parent::store($data);
|
||||
}
|
||||
|
||||
public function update($primaryKey, $data): bool
|
||||
{
|
||||
$pid = data_get($data, 'parent_id', 0);
|
||||
if ($pid && $parent = ArticleCategory::find($pid)) {
|
||||
$data['level'] = $parent->level + 1;
|
||||
$data['path'] = $parent->path . $parent->id . '-';
|
||||
} else {
|
||||
$data['level'] = 1;
|
||||
$data['path'] = '-';
|
||||
}
|
||||
return parent::update($primaryKey, $data);
|
||||
}
|
||||
|
||||
public function delete(string $ids): mixed
|
||||
{
|
||||
return $this->query()->whereIn($this->primaryKey(), explode(',', $ids))->delete();
|
||||
$id = collect(explode(',', $ids));
|
||||
// 所有下级ID
|
||||
foreach ($id as $value) {
|
||||
$item_ids = ArticleCategory::where('path', 'like', '%-'.$value.'-%')->pluck('id');
|
||||
$id = $id->merge($item_ids);
|
||||
}
|
||||
$id = $id->unique();
|
||||
if (Article::whereIn('category_id', $id)->exists()) {
|
||||
return $this->setError('请先删除分类下的文章');
|
||||
}
|
||||
return $this->query()->whereIn($this->primaryKey(), $id)->delete();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\ArticleCategory;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class ArticleSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$categoryList = [
|
||||
['name' => '家用电器', 'children' => [
|
||||
['name' => '电视', 'children' => [
|
||||
['name' => '4K高清'],
|
||||
['name' => '智慧屏'],
|
||||
['name' => 'OLED电视'],
|
||||
]],
|
||||
['name' => '冰箱', 'children' => [
|
||||
['name' => '对开门'],
|
||||
['name' => '冰柜'],
|
||||
['name' => '双门'],
|
||||
]],
|
||||
['name' => '空调', 'children' => [
|
||||
['name' => '空调挂机'],
|
||||
['name' => '空调柜机'],
|
||||
['name' => '中央空调'],
|
||||
]],
|
||||
]],
|
||||
['name' => '数码手机', 'children' => [
|
||||
['name' => '手机通讯', 'children' => [
|
||||
['name' => '游戏手机'],
|
||||
['name' => '5G手机'],
|
||||
['name' => '全面屏手机'],
|
||||
]],
|
||||
['name' => '手机配件', 'children' => [
|
||||
['name' => '手机壳'],
|
||||
['name' => '手机膜'],
|
||||
['name' => '数据线'],
|
||||
]],
|
||||
['name' => '智能设备', 'children' => [
|
||||
['name' => '智能手表'],
|
||||
['name' => '监控摄像'],
|
||||
['name' => '智能家居'],
|
||||
]],
|
||||
]],
|
||||
['name' => '电脑办公', 'children' => [
|
||||
['name' => '电脑整机', 'children' => [
|
||||
['name' => '台式机'],
|
||||
['name' => '笔记本'],
|
||||
['name' => '一体机'],
|
||||
]],
|
||||
['name' => '电脑配件', 'children' => [
|
||||
['name' => 'CPU'],
|
||||
['name' => '显卡'],
|
||||
['name' => '显示器'],
|
||||
]],
|
||||
['name' => '外设产品', 'children' => [
|
||||
['name' => '鼠标'],
|
||||
['name' => '键盘'],
|
||||
['name' => 'U盘'],
|
||||
]],
|
||||
]],
|
||||
];
|
||||
ArticleCategory::truncate();
|
||||
$this->createCategory($categoryList, 0);
|
||||
}
|
||||
|
||||
protected function createCategory($list, $pid = 0)
|
||||
{
|
||||
$sort = count($list);
|
||||
foreach($list as $index => $item) {
|
||||
$params = Arr::except($item, ['children']);
|
||||
$parent = null;
|
||||
if ($pid) {
|
||||
$parent = ArticleCategory::find($pid);
|
||||
}
|
||||
$model = ArticleCategory::create(array_merge([
|
||||
'sort' => $sort--,
|
||||
'parent_id' => $parent ? $parent->id : 0,
|
||||
'level' => $parent ? $parent->level + 1 : 1,
|
||||
'path' => ($parent ? $parent->path . $parent->id : '') . '-',
|
||||
], $params));
|
||||
$children = data_get($item, 'children');
|
||||
if ($children && count($children) > 0) {
|
||||
$this->createCategory($children, $model->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -187,9 +187,5 @@ return [
|
|||
'page_no_data' => '本页无数据',
|
||||
'selected_rows_no_data' => '请选择要导出的数据',
|
||||
'please_install_laravel_excel' => '请先安装 laravel-excel 扩展',
|
||||
],
|
||||
'switch' => [
|
||||
'on' => '开启',
|
||||
'off' => '关闭',
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ return [
|
|||
'id' => 'ID',
|
||||
'name' => '名称',
|
||||
'icon' => '图片',
|
||||
'sort' => '排序',
|
||||
'sort' => '排序(倒序)',
|
||||
'is_enable' => '状态',
|
||||
'created_at' => '创建时间',
|
||||
'parent_id' => '父级',
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in New Issue