PHP项目Laravel Nova动作批量操作

wen PHP项目 3

本文目录导读:

PHP项目Laravel Nova动作批量操作

  1. 创建自定义动作
  2. 定义动作类
  3. 在资源中注册动作
  4. 动作的高级配置
  5. 前端批量操作配置
  6. 自定义按钮行为
  7. 权限控制示例
  8. 前端模板中的按钮
  9. 常见问题处理

在 Laravel Nova 中实现动作的批量操作,可以通过以下步骤来完成:

创建自定义动作

创建一个 Nova 动作:

php artisan nova:action UpdateStatus

定义动作类

<?php
namespace App\Nova\Actions;
use Illuminate\Bus\Queueable;
use Laravel\Nova\Actions\Action;
use Illuminate\Support\Collection;
use Laravel\Nova\Fields\ActionFields;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Laravel\Nova\Fields\Select;
use Laravel\Nova\Fields\Text;
class UpdateStatus extends Action
{
    use InteractsWithQueue, Queueable, SerializesModels;
    public $name = '更新状态';
    /**
     * 执行动作
     */
    public function handle(ActionFields $fields, Collection $models)
    {
        // 处理选中的多个模型
        foreach ($models as $model) {
            // 批量更新状态
            $model->update([
                'status' => $fields->status
            ]);
        }
        return Action::message('状态更新成功!');
    }
    /**
     * 定义动作的字段
     */
    public function fields()
    {
        return [
            Select::make('状态', 'status')
                ->options([
                    'active' => '启用',
                    'inactive' => '禁用',
                    'pending' => '待审核',
                ])
                ->rules('required'),
        ];
    }
}

在资源中注册动作

<?php
namespace App\Nova;
use App\Nova\Actions\UpdateStatus;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Resource;
class User extends Resource
{
    public static $model = \App\Models\User::class;
    public function actions(Request $request)
    {
        return [
            (new UpdateStatus)
                ->canSee(fn ($request) => $request->user()->hasPermissionTo('update-status'))
                ->canRun(fn ($request, $user) => $request->user()->hasPermissionTo('update-status')),
            (new SendEmail)
                ->onlyOnDetail(), // 只在详情页显示
            (new ExportUsers)
                ->exceptOnIndex(), // 不在列表页显示
            (new DeleteUsers)
                ->canRun(function ($request, $user) {
                    return $request->user()->isAdmin();
                })
                ->confirmText('确定要删除选中的用户吗?')
                ->confirmButtonText('删除')
                ->cancelButtonText('取消'),
        ];
    }
}

动作的高级配置

批量操作与队列

<?php
namespace App\Nova\Actions;
use Illuminate\Bus\Queueable;
use Laravel\Nova\Actions\Action;
use Illuminate\Support\Collection;
use Laravel\Nova\Fields\ActionFields;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
class ProcessLargeData extends Action
{
    use InteractsWithQueue, Queueable, SerializesModels;
    public $timeout = 120; // 超时时间(秒)
    public $tries = 3;     // 重试次数
    public function handle(ActionFields $fields, Collection $models)
    {
        foreach ($models as $model) {
            // 处理大量数据时,可以使用队列
            dispatch(new ProcessModelJob($model));
        }
        return Action::message('数据已在后台处理中');
    }
    public function fields()
    {
        return [];
    }
    // 使动作可以在队列中运行
    public function shouldQueue(ActionFields $fields, Collection $models)
    {
        return count($models) > 10; // 当模型数量大于10时使用队列
    }
}

前端批量操作配置

在资源中启用批量操作

public function actions(Request $request)
{
    return [
        (new UpdateStatus)
            ->sole()                    // 只能选择单个记录时使用
            ->showOnIndex()             // 在索引页显示
            ->showOnDetail()            // 在详情页显示
            ->showOnCreation()          // 在创建页显示
            ->confirmText('确定要执行此操作吗?')
            ->confirmButtonText('确认执行')
            ->cancelButtonText('取消'),
    ];
}

自定义按钮行为

<?php
namespace App\Nova\Actions;
class ExportData extends Action
{
    public function handle(ActionFields $fields, Collection $models)
    {
        // 导出选中数据
        $selectedIds = $models->pluck('id')->toArray();
        // 导出处理逻辑
        $exportUrl = route('export.data', ['ids' => implode(',', $selectedIds)]);
        return Action::redirect($exportUrl);
    }
    public function fields()
    {
        return [
            Text::make('导出文件名', 'filename')
                ->default('export_' . date('Ymd_His')),
        ];
    }
}

权限控制示例

public function actions(Request $request)
{
    return [
        (new UpdateStatus)
            ->canSee(function ($request) {
                return $request->user()->isAdmin() || $request->user()->role === 'manager';
            })
            ->canRun(function ($request, $user) {
                return $request->user()->isAdmin() || 
                       ($request->user()->role === 'manager' && $user->department_id === $request->user()->department_id);
            }),
    ];
}

前端模板中的按钮

在资源的 index 或 detail 视图中:

{{-- 在资源索引表格中 --}}
<div class="flex items-center">
    <input type="checkbox" class="action-select-all">
    <button @click="selectedResources.length > 0" class="btn btn-primary">
        批量操作
    </button>
</div>

常见问题处理

处理大量数据

public function handle(ActionFields $fields, Collection $models)
{
    if ($models->count() > 50) {
        // 批量处理时限制数量
        return Action::danger('每次最多只能处理50条记录');
    }
    // 使用 chunk 分批处理
    $models->chunk(100)->each(function ($chunk) {
        foreach ($chunk as $model) {
            // 处理逻辑
        }
    });
}

记录操作日志

public function handle(ActionFields $fields, Collection $models)
{
    $user = auth()->user();
    foreach ($models as $model) {
        ActivityLog::create([
            'user_id' => $user->id,
            'action' => 'bulk_update',
            'model_type' => get_class($model),
            'model_id' => $model->id,
            'changes' => json_encode($fields->toArray()),
        ]);
    }
}

这样,你就可以在 Laravel Nova 中实现强大的批量操作功能了,记得在 NovaServiceProvider 或资源模型中注册这些动作。

抱歉,评论功能暂时关闭!