1
0
Fork 0

Compare commits

..

No commits in common. "e09755a197d5e507df7054edae7438c4f2e460f7" and "4296f6609066927b1c37d784d6613e6f837c01de" have entirely different histories.

14 changed files with 7 additions and 605 deletions

View File

@ -1,18 +0,0 @@
<?php
namespace App\Admin;
use Slowlyo\OwlAdmin\Renderers\BaseRenderer;
class Components extends BaseRenderer {
public function parentControl($apiUrl = '', $name ='parent_id', $labelField = 'name', $valueField = 'id')
{
return amisMake()->TreeSelectControl()
->name('parent_id')->label('父级')
->showIcon(false)
->labelField($labelField)
->valueField($valueField)
->value(0)->source($apiUrl);
}
}

View File

@ -1,79 +0,0 @@
<?php
namespace App\Admin\Controllers;
use Slowlyo\OwlAdmin\Renderers\Page;
use Slowlyo\OwlAdmin\Renderers\Form;
use Slowlyo\OwlAdmin\Renderers\Operation;
use Slowlyo\OwlAdmin\Renderers\TableColumn;
use Slowlyo\OwlAdmin\Renderers\TextControl;
use Slowlyo\OwlAdmin\Services\AdminRoleService;
use Slowlyo\OwlAdmin\Renderers\TreeSelectControl;
use Slowlyo\OwlAdmin\Renderers\CheckboxesControl;
use Slowlyo\OwlAdmin\Services\AdminPermissionService;
use Slowlyo\OwlAdmin\Controllers\AdminRoleController as BaseRoleController;
class AdminRoleController extends BaseRoleController
{
public function list(): Page
{
$crud = $this->baseCRUD()
->headerToolbar([
$this->createButton(true, 'lg'),
'bulkActions',
amis('reload')->align('right'),
amis('filter-toggler')->align('right'),
])
->filterTogglable(false)
->columns([
TableColumn::make()->label('ID')->name('id')->sortable(true),
TableColumn::make()->label(__('admin.admin_role.name'))->name('name'),
TableColumn::make()->label(__('admin.admin_role.slug'))->name('slug')->type('tag'),
TableColumn::make()->label(__('admin.created_at'))->name('created_at')->type('datetime')->sortable(true),
TableColumn::make()->label(__('admin.updated_at'))->name('updated_at')->type('datetime')->sortable(true),
Operation::make()->label(__('admin.actions'))->buttons([
$this->rowEditButton(true, 'lg'),
$this->rowDeleteButton()->visibleOn('${slug != "administrator"}'),
]),
]);
return $this->baseList($crud);
}
public function form(): Form
{
return $this->baseForm()->body([
TextControl::make()->label(__('admin.admin_role.name'))->name('name')->required(true)->size('lg'),
TextControl::make()
->label(__('admin.admin_role.slug'))
->name('slug')
->description(__('admin.admin_role.slug_description'))
->required(true)->size('lg'),
CheckboxesControl::make()
->name('permissions')
->label(__('admin.admin_role.permissions'))
->options(AdminPermissionService::make()->getTree())
// ->checkAll(true)
->labelField('name')
->valueField('id')
->joinValues(false)
->extractValue(true)
// TreeSelectControl::make()
// ->name('permissions')
// ->label(__('admin.admin_role.permissions'))
// ->multiple(true)
// ->options(AdminPermissionService::make()->getTree())
// ->searchable(true)
// ->labelField('name')
// ->valueField('id')
// ->autoCheckChildren(false)
// ->joinValues(false)
// ->extractValue(true),
]);
}
public function detail(): Form
{
return $this->baseDetail()->body([]);
}
}

View File

@ -25,7 +25,7 @@ class HomeController extends AdminController
{
$page = $this->basePage()->css($this->css())->body([
Grid::make()->columns([
// $this->frameworkInfo()->md(5),
$this->frameworkInfo()->md(5),
Flex::make()->items([
$this->pieChart(),
$this->cube(),
@ -35,7 +35,7 @@ class HomeController extends AdminController
$this->lineChart()->md(8),
Flex::make()->className('h-full')->items([
$this->clock(),
// $this->giteeWidget(),
$this->giteeWidget(),
])->direction('column'),
]),
]);

View File

@ -1,60 +0,0 @@
<?php
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\Controllers\AdminController;
use App\Services\Admin\KeywordService;
use App\Admin\Components;
use Illuminate\Http\Request;
class KeywordController extends AdminController
{
protected string $serviceName = KeywordService::class;
protected string $pageTitle = '字典管理';
public function list(): Page
{
$crud = $this->baseCRUD()
//关闭查询
->filterTogglable(false)
//去掉分页-start
->loadDataOnce(true)
->footerToolbar([])
//去掉分页-end
->headerToolbar([
$this->createButton(true),
amis('reload')->align('right'),
amis('filter-toggler')->align('right'),
])
->columns([
// TableColumn::make()->name('id')->label('ID')->sortable(true),
TableColumn::make()->name('name')->label('名称'),
TableColumn::make()->name('key')->label('KEY'),
TableColumn::make()->name('value')->label('值'),
TableColumn::make()->name('created_at')->label('创建时间')->type('datetime')->sortable(true),
$this->rowActionsOnlyEditAndDelete(true),
]);
return $this->baseList($crud);
}
public function form(): Form
{
return $this->baseForm()->body([
Components::make()->parentControl(admin_url('api/keywords/tree-list')),
TextControl::make()->name('name')->label('名称')->required(true),
TextControl::make()->name('key')->label('KEY')->required(true),
TextControl::make()->name('value')->label('值')->required(true),
amisMake()->NumberControl()->name('sort')->value(0)->min()->label('排序'),
]);
}
public function getTreeList(Request $request){
return $this->service->getTree();
}
}

View File

@ -8,17 +8,8 @@ Route::group([
'prefix' => config('admin.route.prefix'),
'middleware' => config('admin.route.middleware'),
], function (Router $router) {
$router->group([
'prefix' => 'api',
], function (Router $router) {
$router->get('keywords/tree-list', '\App\Admin\Controllers\KeywordController@getTreeList')->name('api.keywords.tree-list');
});
$router->resource('dashboard', \App\Admin\Controllers\HomeController::class);
$router->resource('keywords', \App\Admin\Controllers\KeywordController::class);
$router->resource('system/re-roles', \App\Admin\Controllers\AdminRoleController::class);
$router->resource('system/settings', \App\Admin\Controllers\SettingController::class);
});

View File

@ -1,47 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use EloquentFilter\Filterable;
class Keyword extends Model
{
use HasFactory;
use Filterable;
protected $fillable = ['name', 'key', 'value', 'parent_id', 'type_key', 'path', 'sort', 'level'];
protected static function boot()
{
parent::boot();
// 监听 Keyword 的创建事件,用于初始化 path 和 level 字段值
static::creating(function ($keyword) {
// 如果创建的是一个根类目
if (! $keyword->parent_id) {
// 将层级设为 1
$keyword->level = 1;
// 将 path 设为 -
$keyword->path = '-';
} else {
// 将层级设为父类目的层级 + 1
$keyword->level = $keyword->parent->level + 1;
$keyword->type_key = $keyword->parent->key;
// 将 path 值设为父类目的 path 追加父类目 ID 以及最后跟上一个 - 分隔符
$keyword->path = $keyword->parent->path.$keyword->parent_id.'-';
}
});
}
public function parent()
{
return $this->belongsTo(static::class, 'parent_id');
}
public function children()
{
return $this->hasMany(static::class, 'parent_id');
}
}

View File

@ -1,67 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Database\Events\TransactionBeginning;
use Illuminate\Database\Events\TransactionCommitted;
use Illuminate\Database\Events\TransactionRolledBack;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\ServiceProvider;
class QueryLoggerServiceProvider extends ServiceProvider
{
/**
* {@inheritdoc}
*/
public function boot()
{
if (! config('app.debug')) {
return;
}
$this->app['events']->listen([
QueryExecuted::class,
TransactionBeginning::class,
TransactionCommitted::class,
TransactionRolledBack::class,
], function ($event) {
Log::debug(match (true) {
$event instanceof TransactionBeginning => 'begin transaction',
$event instanceof TransactionCommitted => 'commit transaction',
$event instanceof TransactionRolledBack => 'rollback transaction',
default => $this->prepareSql($event),
});
});
}
/**
* @param \Illuminate\Database\Events\QueryExecuted $query
* @return string
*/
protected function prepareSql(QueryExecuted $query): string
{
$sql = str_replace(['%', '?'], ['%%', '%s'], $query->sql);
$bindings = $query->connection->prepareBindings($query->bindings);
if (count($bindings)) {
$sql = vsprintf($sql, array_map([$query->connection->getPdo(), 'quote'], $bindings));
}
return sprintf('[%s] %s', $this->formatDuration($query->time), $sql);
}
/**
* @param float $milliseconds
* @return string
*/
protected function formatDuration($milliseconds): string
{
return match (true) {
$milliseconds >= 1000 => round($milliseconds / 1000, 2).'s',
$milliseconds < 0.01 => round($milliseconds * 1000).'μs',
default => $milliseconds.'ms',
};
}
}

View File

@ -1,114 +0,0 @@
<?php
namespace App\Services\Admin;
use Illuminate\Support\Arr;
use App\Models\Keyword;
use Slowlyo\OwlAdmin\Services\AdminService;
/**
* @method Keyword getModel()
* @method Keyword|\Illuminate\Database\Query\Builder query()
*/
class KeywordService extends AdminService
{
protected string $modelName = Keyword::class;
public function getTree()
{
$list = $this->query()->orderByDesc('sort')->get()->toArray();
return array2tree($list);
}
public function parentIsChild($id, $parent_id): bool
{
$parent = $this->query()->find($parent_id);
do {
if ($parent->parent_id == $id) {
return true;
}
// 如果没有parent 则为顶级 退出循环
$parent = $parent->parent;
} while ($parent);
return false;
}
public function list()
{
return ['items' => $this->getTree()];
}
public function store($data): bool
{
if ($this->hasRepeated($data)) {
return false;
}
$columns = $this->getTableColumns();
$model = $this->getModel();
foreach ($data as $k => $v) {
if (!in_array($k, $columns)) {
continue;
}
$model->setAttribute($k, $v);
}
return $model->save();
}
public function update($primaryKey, $data): bool
{
if ($this->hasRepeated($data, $primaryKey)) {
return false;
}
$columns = $this->getTableColumns();
$parent_id = Arr::get($data, 'parent_id');
if ($parent_id != 0) {
if ($this->parentIsChild($primaryKey, $parent_id)) {
$this->setError('父级不允许设置为当前子权限');
return false;
}
}
$model = $this->query()->whereKey($primaryKey)->first();
foreach ($data as $k => $v) {
if (!in_array($k, $columns)) {
continue;
}
$model->setAttribute($k, $v);
}
return $model->save();
}
public function hasRepeated($data, $id = 0): bool
{
$query = $this->query()->when($id, fn($query) => $query->where('id', '<>', $id));
if ((clone $query)->where('key', $data['key'])->exists()) {
$this->setError('KEY重复');
return true;
}
return false;
}
public function delete(string $ids): mixed
{
$ids = explode(',', $ids);
if(count($ids) == 1){
$this->query()->where('path', 'like', '%-'.$ids[0].'-%')->delete();
}
return $this->query()->whereIn('id', $ids)->delete();
}
}

View File

@ -10,8 +10,7 @@
"laravel/framework": "^9.19",
"laravel/sanctum": "^3.0",
"laravel/tinker": "^2.7",
"slowlyo/owl-admin": "^2.1",
"tucker-eric/eloquentfilter": "^3.2"
"slowlyo/owl-admin": "^2.1"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",
@ -67,7 +66,7 @@
"repositories": {
"packagist": {
"type": "composer",
"url": "https://mirrors.aliyun.com/composer/"
"url": "https://packagist.phpcomposer.com"
}
}
}

73
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "0955c00d24fb997149c86a6cf19f653a",
"content-hash": "a5b72c385ebe487317edadb68fb376ab",
"packages": [
{
"name": "brick/math",
@ -3983,77 +3983,6 @@
"homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
"time": "2023-01-03T09:29:04+00:00"
},
{
"name": "tucker-eric/eloquentfilter",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/Tucker-Eric/EloquentFilter.git",
"reference": "faaad783b7f23af7ba7e23baaa56d71af51504a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Tucker-Eric/EloquentFilter/zipball/faaad783b7f23af7ba7e23baaa56d71af51504a9",
"reference": "faaad783b7f23af7ba7e23baaa56d71af51504a9",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"illuminate/config": "~6.0|~7.0|~8.0|~9.0|~10.0",
"illuminate/console": "~6.0|~7.0|~8.0|~9.0|~10.0",
"illuminate/database": "~6.0|~7.0|~8.0|~9.0|~10.0",
"illuminate/filesystem": "~6.0|~7.0|~8.0|~9.0|~10.0",
"illuminate/pagination": "~6.0|~7.0|~8.0|~9.0|~10.0",
"illuminate/support": "~6.0|~7.0|~8.0|~9.0|~10.0",
"php": ">=7.2"
},
"require-dev": {
"mockery/mockery": "^1.3",
"phpunit/phpunit": "^8"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"EloquentFilter\\ServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"EloquentFilter\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Eric Tucker",
"email": "tucker.ericm@gmail.com"
}
],
"description": "An Eloquent way to filter Eloquent Models",
"keywords": [
"eloquent",
"filter",
"laravel",
"model",
"query",
"search"
],
"support": {
"issues": "https://github.com/Tucker-Eric/EloquentFilter/issues",
"source": "https://github.com/Tucker-Eric/EloquentFilter/tree/3.2.0"
},
"time": "2023-02-07T18:34:53+00:00"
},
{
"name": "vlucas/phpdotenv",
"version": "v5.5.0",

View File

@ -2,7 +2,7 @@
return [
// 应用名称
'name' => '农业园区平台',
'name' => 'Owl Admin',
// 应用 logo
'logo' => '/admin/logo.png',

View File

@ -196,7 +196,7 @@ return [
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\QueryLoggerServiceProvider::class,
],
/*

View File

@ -1,39 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('keywords', function (Blueprint $table) {
$table->id();
$table->string('key')->unique();
$table->string('name')->comment('名字');
$table->string('value')->nullable();
$table->string('type_key')->nullable();
$table->unsignedInteger('sort')->default(0)->comment('排序');
$table->unsignedBigInteger('parent_id')->default(0)->comment('上级ID');
$table->unsignedInteger('level')->default(1)->comment('层级');
$table->string('path')->default('-')->comment('所有的父级ID');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('keywords');
}
};

View File

@ -1,93 +0,0 @@
<?php
namespace Database\Seeders;
use Slowlyo\OwlAdmin\Models\AdminMenu;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Throwable;
class AdminMenuSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//
$menus = [
['title' => '主页', 'icon' => 'icon-park:home-two', 'url' => '/dashboard', 'is_home'=>1],
['title' => '公众号管理', 'icon' => 'icon-park:wechat', 'url' => '',
'children' => [
['title' => '公告管理', 'icon' => 'icon-park:volume-notice', 'url' => '/notices'],
['title' => '文章分类', 'icon' => 'icon-park:book-one', 'url' => '/article-categories'],
['title' => '文章管理', 'icon' => 'icon-park:file-search', 'url' => '/articles'],
['title' => '图片位置', 'icon' => 'icon-park:graphic-design-two', 'url' => '/banner-addresses'],
['title' => '图片管理', 'icon' => 'icon-park:picture-album', 'url' => '/banners'],
]
],
['title' => '区域管理', 'icon' => 'icon-park:category-management', 'url' => '',
'children' => [
['title' => '分类管理', 'icon' => 'icon-park:graphic-stitching-four', 'url' => '/region-categories'],
['title' => '实验田', 'icon' => 'icon-park:freezing-line-column', 'url' => '/regions'],
]
],
['title' => '育秧中心', 'icon' => 'icon-park:lotus', 'url' => '',
'children' => [
['title' => '大棚控制', 'icon' => 'icon-park:link-one', 'url' => 'https://www.baidu.com', 'url_type'=>2],
['title' => '育秧列表', 'icon' => 'icon-park:more-app', 'url' => '/yuyang1'],
]
],
['title' => '实验稻田', 'icon' => 'icon-park:four-leaves', 'url' => '',
'children' => [
['title' => '农机控制', 'icon' => 'icon-park:link-one', 'url' => 'https://www.baidu.com', 'url_type'=>2],
['title' => '稻田列表', 'icon' => 'icon-park:more-app', 'url' => '/daotian2'],
]
],
['title' => '设备管理', 'icon' => 'icon-park:devices', 'url' => '/devices'],
['title' => '友情链接', 'icon' => 'icon-park:copy-link', 'url' => '/friend-links'],
['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/re-roles'],
['title' => '权限管理', 'icon' => 'icon-park:key-one', 'url' => '/system/admin_permissions'],
['title' => '菜单管理', 'icon' => 'icon-park:menu-fold-one', 'url' => '/system/admin_menus'],
['title' => '字典管理', 'icon' => 'icon-park:arrow-keys', 'url' => '/keywords'],
],
],
];
DB::table('admin_menus')->truncate();
try {
DB::begintransaction();
$this->createMenus($menus);
DB::commit();
} catch (Throwable $th) {
DB::rollBack();
report($th);
}
}
public function createMenus(array $menus, $pid = 0)
{
foreach ($menus as $menu) {
$mm = AdminMenu::create([
'title' => $menu['title'],
'icon' => $menu['icon'],
'url' => $menu['url'],
'parent_id' => $pid,
'url_type' => $menu['url_type'] ?? 1,
'visible' => $menu['visible'] ?? 1,
'is_home' => $menu['is_home'] ?? 0,
]);
if (isset($menu['children'])) {
$this->createMenus($menu['children'], $mm->id);
}
}
}
}