基本 通知功能
This commit is contained in:
parent
98e42bb9a6
commit
6131da2cf5
88
app/Http/Controllers/Admin/NotificationController.php
Normal file
88
app/Http/Controllers/Admin/NotificationController.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\SendCommonNotificationsJob;
|
||||
use App\Models\Host;
|
||||
use App\Models\Module;
|
||||
use App\Models\User;
|
||||
use GeneaLabs\LaravelModelCaching\CachedBuilder;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class NotificationController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$modules = Module::all();
|
||||
|
||||
$users = $this->query($request)->paginate(20)->withQueryString();
|
||||
|
||||
return view('admin.notifications.create', compact('modules', 'users'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'title' => 'required',
|
||||
'content' => 'required',
|
||||
'user_id' => 'nullable',
|
||||
'module_id' => 'nullable',
|
||||
'user' => 'nullable',
|
||||
]);
|
||||
|
||||
dispatch(new SendCommonNotificationsJob($request->toArray(), $request->input('title'), $request->input('content')));
|
||||
|
||||
return back()->with('success', '通知发送成功。')->withInput();
|
||||
}
|
||||
|
||||
public function query(Request|array $request): User|CachedBuilder
|
||||
{
|
||||
if ($request instanceof Request) {
|
||||
$request = $request->all();
|
||||
}
|
||||
|
||||
if (!empty($request['user_id'])) {
|
||||
$users = User::where('id', $request['user_id']);
|
||||
} else {
|
||||
$users = User::query();
|
||||
|
||||
if (!empty($request['user'])) {
|
||||
$user = $request['user'];
|
||||
|
||||
if ($user == 'active') {
|
||||
// 寻找有 host 的用户
|
||||
$users = $users->whereHas('hosts');
|
||||
} else if ($user == 'normal') {
|
||||
$users = $users->whereNull('banned_at');
|
||||
} else if ($user == 'banned') {
|
||||
$users = $users->whereNotNull('banned_at');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($request['module_id'])) {
|
||||
// 从 hosts 中找到 module_id,然后找到拥有此 host 的用户
|
||||
$users = $users->whereHas('hosts', function ($query) use ($request) {
|
||||
$query->where('module_id', $request['module_id']);
|
||||
});
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
}
|
57
app/Jobs/SendCommonNotificationsJob.php
Normal file
57
app/Jobs/SendCommonNotificationsJob.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Http\Controllers\Admin\NotificationController;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CommonNotification;
|
||||
use GeneaLabs\LaravelModelCaching\CachedBuilder;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SendCommonNotificationsJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected array $requests;
|
||||
protected User|CachedBuilder $users;
|
||||
protected string $title, $content;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $requests, $title, $content)
|
||||
{
|
||||
$this->requests = $requests;
|
||||
$this->title = $title;
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
//
|
||||
|
||||
$notificationController = new NotificationController();
|
||||
|
||||
$users = $notificationController->query($this->requests);
|
||||
|
||||
// chunk
|
||||
$users->chunk(100, function ($users) {
|
||||
foreach ($users as $user) {
|
||||
$user->notify(new CommonNotification($this->title, $this->content));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
69
app/Notifications/CommonNotification.php
Normal file
69
app/Notifications/CommonNotification.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CommonNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public string $title;
|
||||
public string $content;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $title, string $content)
|
||||
{
|
||||
$this->title = $title;
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
*
|
||||
* @return MailMessage
|
||||
*/
|
||||
public function toMail($notifiable): MailMessage
|
||||
{
|
||||
return (new MailMessage)->subject($this->title)->markdown('mail.common', [
|
||||
'title' => $this->title,
|
||||
'content' => $this->content,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
127
resources/views/admin/notifications/create.blade.php
Normal file
127
resources/views/admin/notifications/create.blade.php
Normal file
@ -0,0 +1,127 @@
|
||||
@extends('layouts.admin')
|
||||
|
||||
@section('title', '通知')
|
||||
|
||||
@section('content')
|
||||
<h3>通知</h3>
|
||||
|
||||
|
||||
@if (Request::isNotFilled('user_id'))
|
||||
<h5>首先,我们得先筛选出要通知哪些用户。</h5>
|
||||
|
||||
<form action="#" method="get">
|
||||
<div class="form-group">
|
||||
<label for="user">用户</label>
|
||||
<select name="user" id="user" class="form-control">
|
||||
<option value="all" @if(Request::get('user') == 'all') selected @endif>全部</option>
|
||||
<option value="normal" @if(Request::get('user') == 'normal') selected @endif>正常没有被封禁的用户
|
||||
</option>
|
||||
<option value="active" @if(Request::get('user') == 'active') selected @endif>有主机的用户</option>
|
||||
<option value="banned" @if(Request::get('user') == 'banned') selected @endif>封禁的用户</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="module_id">在哪些模块拥有主机的</label>
|
||||
<select name="module_id" id="module_id" class="form-control">
|
||||
<option value="">无</option>
|
||||
@foreach ($modules as $module)
|
||||
<option value="{{ $module->id }}"
|
||||
@if(Request::get('module_id') == $module->id) selected @endif>{{ $module->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<p>这两个搜搜条件只能二选一。</p>
|
||||
|
||||
<button type="submit" class="btn btn-primary mt-1">筛选并确定条件</button>
|
||||
</form>
|
||||
|
||||
@endif
|
||||
|
||||
@if (count($users))
|
||||
<h5 class="mt-4">筛选出的用户,接下来我们得选择通知方式。</h5>
|
||||
{{-- 用户列表 --}}
|
||||
<div class="overflow-auto mt-3">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<th>ID</th>
|
||||
<th>用户名</th>
|
||||
<th>邮箱</th>
|
||||
<th>余额</th>
|
||||
<th>用户组</th>
|
||||
<th>注册时间</th>
|
||||
<th>操作</th>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach ($users as $user)
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ route('admin.users.show', $user) }}" title="切换到 {{ $user->name }}">
|
||||
{{ $user->id }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ route('admin.users.edit', $user) }}"
|
||||
title="显示和编辑 {{ $user->name }} 的资料">
|
||||
{{ $user->name }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $user->email }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $user->balance }} 元
|
||||
</td>
|
||||
<td>
|
||||
@if ($user->user_group_id)
|
||||
<a href="{{ route('admin.user-groups.show', $user->user_group_id) }}">
|
||||
{{ $user->user_group->name }}
|
||||
</a>
|
||||
@else
|
||||
无
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
{{ $user->created_at }}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ route('admin.users.edit', $user) }}" class="btn btn-primary btn-sm">编辑</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{-- 分页 --}}
|
||||
{{ $users->links() }}
|
||||
|
||||
@endif
|
||||
|
||||
|
||||
<form method="POST" action="{{ route('admin.notifications.store')}}">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="user" value="{{ Request::get('user') }}">
|
||||
<input type="hidden" name="module_id" value="{{ Request::get('module_id') }}">
|
||||
<input type="hidden" name="user_id" value="{{ Request::get('user_id') }}">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="title">标题</label>
|
||||
<input type="text" name="title" id="title" class="form-control" value="{{ old('title') }}">
|
||||
</div>
|
||||
|
||||
{{-- 通知内容 --}}
|
||||
<div class="form-group mt-4">
|
||||
<label for="content">通知内容 支持 Markdown</label>
|
||||
<textarea name="content" id="content" class="form-control" rows="10">{{ old('content') }}</textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary mt-3">发送</button>
|
||||
<span class="text-muted d-block">通知一旦发送,将无法撤销!</span>
|
||||
</form>
|
||||
|
||||
@endsection
|
@ -49,6 +49,9 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('admin.transactions') }}">交易记录</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('admin.notifications.create') }}">通知</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('admin.admins.index') }}">管理员</a>
|
||||
</li>
|
||||
|
7
resources/views/mail/common.blade.php
Normal file
7
resources/views/mail/common.blade.php
Normal file
@ -0,0 +1,7 @@
|
||||
@component('mail::message')
|
||||
# {{ $title }}
|
||||
|
||||
{{ $content }}
|
||||
|
||||
<br />
|
||||
@endcomponent
|
@ -7,6 +7,7 @@
|
||||
use App\Http\Controllers\Admin\HomeController;
|
||||
use App\Http\Controllers\Admin\HostController;
|
||||
use App\Http\Controllers\Admin\ModuleController;
|
||||
use App\Http\Controllers\Admin\NotificationController;
|
||||
use App\Http\Controllers\Admin\UserController;
|
||||
use App\Http\Controllers\Admin\UserGroupController;
|
||||
use App\Http\Controllers\Admin\WorkOrderController;
|
||||
@ -45,6 +46,8 @@
|
||||
|
||||
Route::resource('devices', DeviceController::class)->only(['index', 'destroy']);
|
||||
|
||||
Route::resource('notifications', NotificationController::class)->only(['create', 'store']);
|
||||
|
||||
|
||||
Route::view('commands', 'admin.commands')->name('commands');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user