mirror of
https://github.com/lsky-org/lsky-pro.git
synced 2025-01-08 11:57:52 +08:00
✨ 策略列表
This commit is contained in:
parent
2ee532b313
commit
2ea34bcb77
60
app/Http/Controllers/Admin/StrategyController.php
Normal file
60
app/Http/Controllers/Admin/StrategyController.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\StrategyRequest;
|
||||
use App\Models\Strategy;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class StrategyController extends Controller
|
||||
{
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$strategies = Strategy::query()->when($request->query('keywords'), function (Builder $builder, $keywords) {
|
||||
$builder->whereRaw("concat(ifnull(name,''),ifnull(intro,'')) like ?",["%{$keywords}%"]);
|
||||
})->withCount('images')->withSum('images', 'size')->latest()->paginate();
|
||||
return view('admin.strategy.index', compact('strategies'));
|
||||
}
|
||||
|
||||
public function add(): View
|
||||
{
|
||||
return view('admin.strategy.add');
|
||||
}
|
||||
|
||||
public function edit(Request $request): View
|
||||
{
|
||||
$strategy = Strategy::query()->findOrFail($request->route('id'));
|
||||
return view('admin.strategy.edit', compact('strategy'));
|
||||
}
|
||||
|
||||
public function create(StrategyRequest $request): Response
|
||||
{
|
||||
$group = new Strategy();
|
||||
$group->fill($request->validated());
|
||||
$group->save();
|
||||
return $this->success('创建成功');
|
||||
}
|
||||
|
||||
public function update(StrategyRequest $request): Response
|
||||
{
|
||||
/** @var Strategy $group */
|
||||
$group = Strategy::query()->findOrFail($request->route('id'));
|
||||
$group->fill($request->validated());
|
||||
if (!$group->save()) {
|
||||
return $this->error('保存失败');
|
||||
}
|
||||
return $this->success('保存成功');
|
||||
}
|
||||
|
||||
public function delete(Request $request): Response
|
||||
{
|
||||
if ($group = Strategy::query()->find($request->route('id'))) {
|
||||
$group->delete();
|
||||
}
|
||||
return $this->success('删除成功');
|
||||
}
|
||||
}
|
19
app/Http/Requests/Admin/StrategyRequest.php
Normal file
19
app/Http/Requests/Admin/StrategyRequest.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Admin;
|
||||
|
||||
use App\Http\Requests\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StrategyRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\Strategy\LocalOption;
|
||||
use App\Enums\StrategyKey;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
@ -41,6 +42,18 @@ class Strategy extends Model
|
||||
'configs' => 'collection',
|
||||
];
|
||||
|
||||
const DRIVERS = [
|
||||
StrategyKey::Local => '本地',
|
||||
StrategyKey::S3 => 'Amazon S3',
|
||||
StrategyKey::Oss => '阿里云 OSS',
|
||||
StrategyKey::Cos => '腾讯云 COS',
|
||||
StrategyKey::Kodo => '七牛云 Kodo',
|
||||
StrategyKey::Uss => '又拍云 USS',
|
||||
StrategyKey::Sftp => 'SFTP',
|
||||
StrategyKey::Ftp => 'FTP',
|
||||
StrategyKey::Webdav => 'WebDav',
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $strategy) {
|
||||
|
76
resources/views/admin/strategy/add.blade.php
Normal file
76
resources/views/admin/strategy/add.blade.php
Normal file
@ -0,0 +1,76 @@
|
||||
<x-app-layout>
|
||||
<div class="my-6 md:my-10">
|
||||
<div class="md:mt-0 md:col-span-2">
|
||||
<form action="{{ route('admin.group.create') }}" method="POST">
|
||||
<div class="overflow-hidden rounded-md">
|
||||
<div class="px-4 py-5 bg-white sm:p-6 space-y-4">
|
||||
|
||||
<div class="col-span-6">
|
||||
<label for="name" class="block text-sm font-medium text-gray-700"><span class="text-red-600">*</span>名称</label>
|
||||
<input type="text" name="name" id="name" placeholder="请输入策略名称" autocomplete="name" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md">
|
||||
</div>
|
||||
|
||||
<div class="col-span-6">
|
||||
<label for="intro" class="block text-sm font-medium text-gray-700">简介</label>
|
||||
<textarea id="intro" name="intro" rows="3" class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 mt-1 block w-full sm:text-sm border border-gray-300 rounded-md" placeholder="请输入简介,可为空"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="key" class="block text-sm font-medium text-gray-700">储存策略</label>
|
||||
<select id="key" name="key" autocomplete="key" class="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
|
||||
@foreach(\App\Models\Strategy::DRIVERS as $key => $driver)
|
||||
<option value="{{ $key }}" {{ $loop->first ? 'selected' : '' }}>{{ $driver }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-span-6">
|
||||
<div class="mb-4 hidden" data-driver="{{ \App\Enums\StrategyKey::Local }}">
|
||||
<div class="col-span-6 sm:col-span-3 mb-4">
|
||||
<label for="configs[domain]" class="block text-sm font-medium text-gray-700"><span class="text-red-600">*</span>访问域名</label>
|
||||
<input type="text" name="configs[domain]" id="configs[domain]" autocomplete="text" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" placeholder="请输入图片访问域名">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
|
||||
<x-button type="button" class="bg-gray-500" onclick="history.go(-1)">取消</x-button>
|
||||
<x-button>确认创建</x-button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
// 设置选中驱动
|
||||
let setSelected = function () {
|
||||
$('[data-driver]').each(function () {
|
||||
$(this)[$('#key').val() == $(this).data('driver') ? 'show' : 'hide']();
|
||||
});
|
||||
};
|
||||
|
||||
setSelected();
|
||||
|
||||
$('#key').change(function () {
|
||||
setSelected();
|
||||
});
|
||||
|
||||
$('form').submit(function (e) {
|
||||
e.preventDefault();
|
||||
axios.post(this.action, $(this).serialize()).then(response => {
|
||||
if (response.data.status) {
|
||||
toastr.success(response.data.message);
|
||||
setTimeout(function () {
|
||||
window.location.href = '{{ route('admin.strategies') }}';
|
||||
}, 3000);
|
||||
} else {
|
||||
toastr.error(response.data.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
</x-app-layout>
|
3
resources/views/admin/strategy/edit.blade.php
Normal file
3
resources/views/admin/strategy/edit.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<x-app-layout>
|
||||
edit
|
||||
</x-app-layout>
|
67
resources/views/admin/strategy/index.blade.php
Normal file
67
resources/views/admin/strategy/index.blade.php
Normal file
@ -0,0 +1,67 @@
|
||||
@section('title', '角色组管理')
|
||||
|
||||
<x-app-layout>
|
||||
<div class="my-6 md:my-10">
|
||||
<div class="mb-3 flex justify-between w-full">
|
||||
<x-button type="button" onclick="window.location.href = '{{ route('admin.strategy.create') }}'">创建储存策略</x-button>
|
||||
<form class="h-9.5" action="{{ route('admin.strategies') }}" method="get">
|
||||
<x-input class="text-sm h-full px-2" name="keywords" placeholder="输入关键字回车搜索..." value="{{ request('keywords') }}" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<x-table :columns="['ID', '名称', '驱动', '图片数量', '已使用储存', '操作']">
|
||||
@foreach($strategies as $strategy)
|
||||
<tr data-id="{{ $strategy->id }}">
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ $strategy->id }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap name">{{ $strategy->name }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span class="rounded-md bg-blue-500 text-sm text-white p-1">
|
||||
{{ \App\Models\Strategy::DRIVERS[$strategy->key] }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ $strategy->images_count }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ \App\Utils::formatSize($strategy->images_sum_size * 1024) }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium space-x-2">
|
||||
<a href="{{ route('admin.strategy.edit', ['id' => $strategy->id]) }}" class="text-indigo-600 hover:text-indigo-900">编辑</a>
|
||||
<a href="javascript:void(0)" data-operate="delete" class="text-red-600 hover:text-red-900">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table>
|
||||
@if($strategies->isEmpty())
|
||||
<x-no-data message="没有找到任何储存策略"/>
|
||||
@else
|
||||
<div class="mt-4">
|
||||
{{ $strategies->links() }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$('[data-operate="delete"]').click(function () {
|
||||
Swal.fire({
|
||||
title: `确认删除储存策略【${$(this).closest('tr').find('td.name').text()}】吗?`,
|
||||
text: "如果某个组下面没有储存策略,该组下面的用户则会默认使用本地储存。",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '确认删除',
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
let id = $(this).closest('tr').data('id');
|
||||
axios.delete(`/admin/strategies/${id}`).then(response => {
|
||||
if (response.data.status) {
|
||||
history.go(0);
|
||||
} else {
|
||||
toastr.error(response.data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
</x-app-layout>
|
@ -60,7 +60,7 @@
|
||||
<x-slot name="icon"><i class="fas fa-images text-blue-500"></i></x-slot>
|
||||
<x-slot name="name">图片管理</x-slot>
|
||||
</x-nav-link>
|
||||
<x-nav-link :active="request()->is('admin/strategies*')">
|
||||
<x-nav-link :href="route('admin.strategies')" :active="request()->is('admin/strategies*')">
|
||||
<x-slot name="icon"><i class="fas fa-hdd text-blue-500"></i></x-slot>
|
||||
<x-slot name="name">储存策略</x-slot>
|
||||
</x-nav-link>
|
||||
|
@ -19,6 +19,7 @@ use App\Http\Controllers\User\AlbumController;
|
||||
use App\Http\Controllers\User\ProfileController;
|
||||
|
||||
use App\Http\Controllers\Admin\GroupController as AdminGroupController;
|
||||
use App\Http\Controllers\Admin\StrategyController as AdminStrategyController;
|
||||
|
||||
Route::get('/', fn () => view('welcome'))->name('/');
|
||||
Route::post('upload', [Controller::class, 'upload']);
|
||||
@ -51,6 +52,15 @@ Route::group(['prefix' => 'admin', 'middleware' => ['auth.admin']], function ()
|
||||
Route::put('{id}', [AdminGroupController::class, 'update'])->name('admin.group.update');
|
||||
Route::delete('{id}', [AdminGroupController::class, 'delete'])->name('admin.group.delete');
|
||||
});
|
||||
|
||||
Route::group(['prefix' => 'strategies'], function () {
|
||||
Route::get('', [AdminStrategyController::class, 'index'])->name('admin.strategies');
|
||||
Route::get('create', [AdminStrategyController::class, 'add'])->name('admin.strategy.add');
|
||||
Route::post('create', [AdminStrategyController::class, 'create'])->name('admin.strategy.create');
|
||||
Route::get('{id}', [AdminStrategyController::class, 'edit'])->name('admin.strategy.edit');
|
||||
Route::put('{id}', [AdminStrategyController::class, 'update'])->name('admin.strategy.update');
|
||||
Route::delete('{id}', [AdminStrategyController::class, 'delete'])->name('admin.strategy.delete');
|
||||
});
|
||||
});
|
||||
|
||||
require __DIR__.'/image.php';
|
||||
|
Loading…
Reference in New Issue
Block a user