1
0
Fork 0
master
panliang 2023-12-01 21:04:56 +08:00
parent d6574cb1a7
commit eda3248af3
17 changed files with 352 additions and 6 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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']);

View File

@ -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);
}
}

View File

@ -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 = [];
}

View File

@ -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');

View File

@ -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());
}
}

View File

@ -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');
}
};

View File

@ -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'],

View File

@ -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) {

View File

@ -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' => '进阶指标'],
]]
];

View File

@ -14,4 +14,5 @@ return [
'published_at' => '发布时间',
'sort' => '排序(正序)',
'title' => '标题',
'party_cate_id' => '党支部',
];

View File

@ -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' => '地址',
];

View File

@ -12,8 +12,5 @@ class ExampleTest extends TestCase
*/
public function test_the_application_returns_a_successful_response(): void
{
$response = $this->get('/');
$response->assertStatus(200);
}
}

View File

@ -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);
}
}