generated from panliang/owl-admin-starter
banner
parent
d6574cb1a7
commit
eda3248af3
|
|
@ -4,6 +4,8 @@ namespace App\Admin\Controllers;
|
|||
|
||||
use App\Admin\Components;
|
||||
use App\Admin\Services\ArticleService;
|
||||
use App\Models\Article;
|
||||
use App\Models\PartyCate;
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
|
|
@ -12,6 +14,8 @@ class ArticleController extends AdminController
|
|||
{
|
||||
protected string $serviceName = ArticleService::class;
|
||||
|
||||
protected $categoryOptions;
|
||||
protected $partyCateOptions;
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
|
|
@ -22,6 +26,7 @@ class ArticleController extends AdminController
|
|||
])
|
||||
->filter($this->baseFilter()->actions([])->body([
|
||||
amisMake()->TextControl()->name('title')->label(__('article.title'))->size('md')->clearable(),
|
||||
amisMake()->SelectControl()->name('category_id')->label(__('article.category_id'))->options($this->getCategoryOptions())->size('md')->clearable(),
|
||||
// amisMake()->Button()->label(__('admin.reset'))->actionType('clear-and-submit'),
|
||||
amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'),
|
||||
]))
|
||||
|
|
@ -44,7 +49,8 @@ class ArticleController extends AdminController
|
|||
{
|
||||
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()->SelectControl()->name('category_id')->label(__('article.category_id'))->options($this->getCategoryOptions())->required(),
|
||||
amisMake()->SelectControl()->name('party_cate_id')->label(__('article.party_cate_id'))->options($this->getPartyCateOptions()),
|
||||
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('*不填写则默认为创建时间'),
|
||||
|
|
@ -67,4 +73,22 @@ class ArticleController extends AdminController
|
|||
Components::make()->fuEditorControl('content', __('article.content'))->static(true),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getCategoryOptions()
|
||||
{
|
||||
if (!$this->categoryOptions) {
|
||||
$this->categoryOptions = Article::getCategoryList()->map(fn($item) => ['value' => $item->id, 'label' => $item->name]);
|
||||
}
|
||||
|
||||
return $this->categoryOptions;
|
||||
}
|
||||
|
||||
public function getPartyCateOptions()
|
||||
{
|
||||
if (!$this->partyCateOptions) {
|
||||
$this->partyCateOptions = PartyCate::select(['id as value', 'name as label'])->get();;
|
||||
}
|
||||
|
||||
return $this->partyCateOptions;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use App\Admin\Components;
|
||||
use App\Admin\Services\BannerService;
|
||||
use App\Enums\TargetType;
|
||||
use App\Models\Banner;
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
|
||||
class BannerController extends AdminController
|
||||
{
|
||||
protected string $serviceName = BannerService::class;
|
||||
|
||||
protected $placeOptions;
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
->filterTogglable(false)
|
||||
->columnsTogglable(false)
|
||||
->headerToolbar([
|
||||
$this->createButton(true),
|
||||
])
|
||||
->quickSaveItemApi(admin_url('quick-edit/banner/$id'))
|
||||
->filter($this->baseFilter()->actions()->body([
|
||||
amisMake()->SelectControl()->name('place_id')->label(__('banner.place_id'))->options($this->getPlaceOptions())->size('md')->clearable(),
|
||||
amisMake()->TextControl()->name('title')->label(__('banner.title'))->size('md')->clearable(),
|
||||
amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'),
|
||||
]))
|
||||
->columns([
|
||||
amisMake()->TableColumn()->name('id')->label(__('banner.id')),
|
||||
amisMake()->TableColumn()->name('place_id')->label(__('banner.place_id')),
|
||||
amisMake()->TableColumn()->name('title')->label(__('banner.title')),
|
||||
amisMake()->Image()->name('picture')->label(__('banner.picture'))->width(30),
|
||||
amisMake()
|
||||
->TableColumn()
|
||||
->name('sort')
|
||||
->label(__('banner.sort'))
|
||||
->align('center')
|
||||
->quickEdit(Components::make()->sortControl('sort', __('banner.sort'))->saveImmediately(true)),
|
||||
Components::make()->switchControl('table')->name('is_enable')->label(__('article.is_enable')),
|
||||
$this->rowActions(true),
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
return $this->baseForm()->title('')->body([
|
||||
amisMake()->SelectControl()->name('place_id')->label(__('banner.place_id'))->options($this->getPlaceOptions())->required(true),
|
||||
amisMake()->TextControl()->name('title')->label(__('banner.title'))->required(true),
|
||||
amisMake()->ImageControl()->name('picture')->label(__('banner.picture'))->autoUpload(true),
|
||||
// {target_type: app/h5, target_url: ''}
|
||||
amisMake()
|
||||
->ComboControl()
|
||||
->scaffold(['target_type' => TargetType::App, 'target_url' => ''])
|
||||
->subFormMode('horizontal')
|
||||
->multiLine()
|
||||
->name('link_config')
|
||||
->label(__('banner.link_config'))
|
||||
->items([
|
||||
amisMake()->SelectControl()->name('target_type')->label(__('banner.target_type'))->options(TargetType::map()),
|
||||
amisMake()->TextControl()->name('target_url')->label(__('banner.target_url')),
|
||||
]),
|
||||
Components::make()->sortControl('sort', __('banner.sort')),
|
||||
amisMake()->TextareaControl()->name('description')->label(__('banner.description')),
|
||||
amisMake()->DateTimeControl()->name('published_at')->label(__('banner.published_at'))->value(now())->format('YYYY-MM-DD HH:mm:ss')->description('*默认当前时间'),
|
||||
Components::make()->switchControl('form')->name('is_enable')->label(__('banner.is_enable'))->value(true),
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail(): Form
|
||||
{
|
||||
return $this->baseDetail()->title('')->body([
|
||||
amisMake()->TextControl()->name('place.name')->label(__('banner.place_id'))->static(),
|
||||
amisMake()->TextControl()->name('title')->label(__('banner.title'))->static(),
|
||||
amisMake()->TextControl()->name('picture')->label(__('banner.picture'))->static()->staticSchema(amisMake()->image()),
|
||||
amisMake()
|
||||
->ComboControl()
|
||||
->subFormMode('horizontal')
|
||||
->multiLine()
|
||||
->static(true)
|
||||
->name('link_config')
|
||||
->label(__('banner.link_config'))
|
||||
->items([
|
||||
amisMake()->SelectControl()->name('target_type')->label(__('banner.target_type'))->options(TargetType::map())->static(true),
|
||||
amisMake()->TextControl()->name('target_url')->label(__('banner.target_url'))->static(true),
|
||||
]),
|
||||
amisMake()->TextControl()->name('sort')->label(__('banner.sort'))->static(true),
|
||||
amisMake()->TextControl()->name('description')->label(__('banner.description'))->static(true),
|
||||
amisMake()->TextControl()->name('published_at')->label(__('banner.published_at'))->static(true),
|
||||
Components::make()->switchControl('show')->name('is_enable')->label(__('banner.is_enable')),
|
||||
amisMake()->TextControl()->name('created_at')->label(__('banner.created_at'))->static(true),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getPlaceOptions()
|
||||
{
|
||||
if (!$this->placeOptions) {
|
||||
$this->placeOptions = Banner::getPlaceList()->map(fn($item) => ['value' => $item->id, 'label' => $item->name]);
|
||||
}
|
||||
|
||||
return $this->placeOptions;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Services;
|
||||
|
||||
use App\ModelFilters\BannerFilter;
|
||||
use App\Models\Banner;
|
||||
|
||||
class BannerService extends BaseService
|
||||
{
|
||||
protected array $withRelationships = ['place'];
|
||||
|
||||
protected string $modelName = Banner::class;
|
||||
|
||||
protected string $modelFilterName = BannerFilter::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->orderBy('place_id')->sort();
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,11 @@
|
|||
namespace App\Admin\Services;
|
||||
|
||||
use App\ModelFilters\PartyCateFilter;
|
||||
use App\Models\Keyword;
|
||||
use App\Models\PartyCate;
|
||||
use App\Models\PartyUser;
|
||||
use App\Models\UserScore;
|
||||
use Slowlyo\OwlAdmin\Models\AdminPermission;
|
||||
use Slowlyo\OwlAdmin\Services\AdminPermissionService;
|
||||
|
||||
class PartyCateService extends BaseService
|
||||
{
|
||||
|
|
@ -16,6 +17,29 @@ class PartyCateService extends BaseService
|
|||
|
||||
protected string $modelFilterName = PartyCateFilter::class;
|
||||
|
||||
public function store($data): bool
|
||||
{
|
||||
$data = $this->resloveData($data);
|
||||
|
||||
$validate = $this->validate($data);
|
||||
if ($validate !== true) {
|
||||
$this->setError($validate);
|
||||
return false;
|
||||
}
|
||||
|
||||
$info = $this->modelName::create($data);
|
||||
|
||||
// 创建权限
|
||||
$parent = AdminPermission::firstOrCreate(['slug' => 'party_cate'], ['name' => '党支部']);
|
||||
AdminPermissionService::make()->store([
|
||||
'slug' => 'party_cate_' . $info->id,
|
||||
'name' => $info->name,
|
||||
'parent_id' => $parent->id
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function preDelete(array $ids)
|
||||
{
|
||||
$userIds = PartyUser::whereIn('cate_id', $ids)->pluck('id');
|
||||
|
|
@ -23,6 +47,8 @@ class PartyCateService extends BaseService
|
|||
PartyUser::whereIn('cate_id', $ids)->delete();
|
||||
// 删除党员下面的审核记录
|
||||
UserScore::whereIn('user_id', $userIds)->delete();
|
||||
// 删除权限
|
||||
AdminPermission::whereIn('slug', array_map(fn ($v) => 'party_cate_' . $v, $ids))->delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ Route::group([
|
|||
// 字典表
|
||||
$router->resource('keywords', \App\Admin\Controllers\KeywordsController::class)->names('admin.keywords');
|
||||
|
||||
// 广告
|
||||
$router->resource('banner', \App\Admin\Controllers\BannerController::class)->names('admin.banner');
|
||||
$router->post('quick-edit/banner/{banner}', [\App\Admin\Controllers\BannerController::class, 'update']);
|
||||
|
||||
// 文章
|
||||
$router->resource('articles', \App\Admin\Controllers\ArticleController::class)->names('admin.article');
|
||||
$router->post('quick-edit/article/{article}', [\App\Admin\Controllers\ArticleController::class, 'update']);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
enum TargetType: string
|
||||
{
|
||||
case App = 'app';
|
||||
case Web = 'web';
|
||||
|
||||
public static function map()
|
||||
{
|
||||
return [
|
||||
self::App->value => '内部跳转',
|
||||
self::Web->value => '外部链接',
|
||||
];
|
||||
}
|
||||
|
||||
public function text()
|
||||
{
|
||||
return data_get(self::map(), $this->value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\ModelFilters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
|
||||
class BannerFilter 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 = [];
|
||||
}
|
||||
|
|
@ -31,6 +31,11 @@ class Article extends Model
|
|||
'published_at' => 'datetime',
|
||||
];
|
||||
|
||||
public static function getCategoryList()
|
||||
{
|
||||
return Keyword::where('key', 'like', 'category_%')->get();
|
||||
}
|
||||
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(Keyword::class, 'category_id');
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use EloquentFilter\Filterable;
|
||||
use App\Traits\HasDateTimeFormatter;
|
||||
use App\Casts\StorageFile;
|
||||
|
||||
/**
|
||||
* 广告
|
||||
*/
|
||||
class Banner extends Model
|
||||
{
|
||||
use Filterable, HasDateTimeFormatter;
|
||||
|
||||
protected $fillable = ['title', 'picture', 'description', 'place_id', 'path', 'published_at', 'is_enable', 'sort', 'link_config'];
|
||||
|
||||
protected $casts = [
|
||||
'picture' => StorageFile::class,
|
||||
'link_config' => 'array',
|
||||
];
|
||||
|
||||
public static function getPlaceList()
|
||||
{
|
||||
return Keyword::where('key', 'like', 'banner_%')->get();
|
||||
}
|
||||
|
||||
public function place()
|
||||
{
|
||||
return $this->belongsTo(Keyword::class, 'place_id');
|
||||
}
|
||||
|
||||
public function scopeSort($q)
|
||||
{
|
||||
return $q->orderBy('sort', 'desc');
|
||||
}
|
||||
|
||||
public function scopeEnable($q)
|
||||
{
|
||||
return $q->where('is_enable', 1)->where('published_at', '<=', now());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?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('banners', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title')->nullable()->comment('标题');
|
||||
$table->string('picture')->nullable()->comment('图片');
|
||||
$table->text('description')->nullable()->comment('描述');
|
||||
$table->unsignedBigInteger('place_id')->comment('位置, keywords.id');
|
||||
$table->string('path')->default('-')->comment('位置, 所有上级, -1-2-3-');
|
||||
$table->timestamp('published_at')->nullable()->comment('发布时间');
|
||||
$table->unsignedTinyInteger('is_enable')->default(1)->comment('是否显示');
|
||||
$table->unsignedInteger('sort')->default(0)->comment('排序(倒序)');
|
||||
$table->json('link_config')->nullable()->comment('跳转配置');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('banners');
|
||||
}
|
||||
};
|
||||
|
|
@ -22,7 +22,8 @@ class AdminMenuSeeder extends Seeder
|
|||
['title' => '支部管理', 'icon' => 'icon-park:flag', 'url' => '/party-cate'],
|
||||
['title' => '党员管理', 'icon' => 'icon-park:every-user', 'url' => '/party-user'],
|
||||
['title' => '审核评定', 'icon' => 'icon-park:internal-data', 'url' => '/user-score'],
|
||||
['title' => '文章管理', 'icon' => 'icon-park:web-page', 'url' => '/articles'],
|
||||
['title' => '信息管理', 'icon' => 'icon-park:web-page', 'url' => '/articles'],
|
||||
['title' => '广告管理', 'icon' => 'icon-park:picture-one', 'url' => '/banner'],
|
||||
['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'],
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ class AdminSeeder extends Seeder
|
|||
|
||||
AdminPermission::query()->truncate();
|
||||
AdminPermission::query()->insert($permissions);
|
||||
AdminPermission::create([
|
||||
'name' => '党支部',
|
||||
'slug' => 'party_cate',
|
||||
'order' => count($permissions) + 1,
|
||||
]);
|
||||
|
||||
DB::table('admin_permission_menu')->truncate();
|
||||
foreach ($permissions as $item) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,13 @@ class KeywordSeeder extends Seeder
|
|||
['key' => 'score_cate_3', 'name' => '政治担当'],
|
||||
['key' => 'score_cate_4', 'name' => '政治能力'],
|
||||
['key' => 'score_cate_5', 'name' => '政治自律'],
|
||||
]],
|
||||
['key' => 'banner', 'name' => '广告位', 'children' => [
|
||||
['key' => 'banner_1', 'name' => '首页广告'],
|
||||
]],
|
||||
['key' => 'category', 'name' => '文章分类', 'children' => [
|
||||
['key' => 'category_1', 'name' => '共性指标'],
|
||||
['key' => 'category_2', 'name' => '进阶指标'],
|
||||
]]
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ return [
|
|||
'published_at' => '发布时间',
|
||||
'sort' => '排序(正序)',
|
||||
'title' => '标题',
|
||||
'party_cate_id' => '党支部',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'created_at' => '创建时间',
|
||||
'is_enable' => '显示',
|
||||
'link_config' => '跳转',
|
||||
'title' => '标题',
|
||||
'description' => '描述',
|
||||
'picture' => '图片',
|
||||
'place_id' => '位置',
|
||||
'published_at' => '发布时间',
|
||||
'sort' => '排序(正序)',
|
||||
'target_type' => '类型',
|
||||
'target_url' => '地址',
|
||||
];
|
||||
|
|
@ -12,8 +12,5 @@ class ExampleTest extends TestCase
|
|||
*/
|
||||
public function test_the_application_returns_a_successful_response(): void
|
||||
{
|
||||
$response = $this->get('/');
|
||||
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ class ExampleTest extends TestCase
|
|||
*/
|
||||
public function test_that_true_is_true(): void
|
||||
{
|
||||
$ids = ['1', '2'];
|
||||
$a = array_map(fn ($v) => 'party_cate_' . $v, $ids);
|
||||
dump($a);
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue