You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Nova Table Metric添加删除行动作遇问题求助

Laravel Nova Table Metric 添加带输入框的删除动作方案

因为pavloniym/nova-action-buttons仅支持资源表格视图,不兼容Table Metric,这里提供三个可行的实现方案:


方案一:自定义Vue组件对接Nova原生Action系统

这个方案复用Nova自带的Action模态框和API,体验最贴近原生Nova操作:

  1. 创建Vue按钮组件
    在resources/js/components/DeleteOrderButton.vue中编写组件:
<template>
  <button @click="triggerDelete" class="btn btn-danger btn-sm ml-2">
    删除订单
  </button>
</template>

<script>
export default {
  props: ['resourceId'],
  methods: {
    async triggerDelete() {
      // 加载DeleteOrder动作的配置
      const actionRes = await Nova.request().get('/nova-api/orders/actions/delete-order');
      const actionFields = actionRes.data.fields;

      // 弹出Nova原生表单模态框
      const { response } = await Nova.modal(
        '删除订单',
        Nova.form(actionFields, {
          resourceName: 'orders',
          resourceId: this.resourceId,
          actionId: 'delete-order',
        })
      );

      if (response) {
        // 提交动作请求
        await Nova.request().post('/nova-api/orders/actions/delete-order', {
          resources: [this.resourceId],
          ...response.data,
        });

        // 刷新当前Metric数据
        Nova.refreshMetrics();
        Nova.success('订单已删除');
      }
    }
  }
};
</script>
  1. 注册组件到Nova
    在app/Providers/NovaServiceProvider.php的boot方法中添加组件注册:
use Laravel\Nova\Nova;
use Laravel\Nova\Events\ServingNova;

public function boot()
{
    parent::boot();

    Nova::serving(function (ServingNova $event) {
        Nova::script('delete-order-button', public_path('js/delete-order-button.js'));
    });
}
  1. 编译组件并在Table Metric中使用
    执行npm run prod编译组件,然后在你的Table Metric类中添加自定义按钮:
use Laravel\Nova\Metrics\Table;
use Laravel\Nova\Http\Requests\NovaRequest;

class OrdersInInvoiceWithExpireDate extends Table
{
    public function calculate(NovaRequest $request)
    {
        return $this->count($request, Order::class)
            ->rows(function ($order) {
                return [
                    'id' => $order->id,
                    'number' => $order->number,
                    // 其他字段...
                    'actions' => implode('', [
                        $this->editButton($order),
                        "<delete-order-button :resource-id=\"{$order->id}\"></delete-order-button>"
                    ]),
                ];
            });
    }

    public function columns()
    {
        return [
            'id' => '订单ID',
            'number' => '订单编号',
            // 其他列...
            'actions' => '操作',
        ];
    }

    // 允许渲染HTML内容
    public function allowHtml()
    {
        return true;
    }
}

方案二:基于Nova Inline Action实现(Nova 4+)

如果你的Nova版本是4.x及以上,可以用Inline Action特性,只需少量代码适配:

  1. 修改DeleteOrder动作类
    让动作实现InlineAction接口:
use Laravel\Nova\Actions\Action;
use Laravel\Nova\Actions\InlineAction;
use Laravel\Nova\Fields\Textarea;
use Laravel\Nova\Http\Requests\NovaRequest;

class DeleteOrder extends Action implements InlineAction
{
    public $name = '删除订单';

    public function fields(NovaRequest $request)
    {
        return [
            Textarea::make('备注', 'note')->required(),
        ];
    }

    public function handle(NovaRequest $request, $model)
    {
        $model->delete();
        \Log::info('订单删除日志', ['order_id' => $model->id, 'note' => $request->note]);

        return Action::message('订单已成功删除');
    }

    public function uriKey()
    {
        return 'delete-order';
    }
}
  1. 添加按钮并绑定触发逻辑
    在Table Metric的行操作中添加按钮,同时注册JS逻辑:
// Table Metric的rows方法中
'actions' => implode('', [
    $this->editButton($order),
    "<button class=\"inline-delete-btn btn btn-danger btn-sm ml-2\" data-id=\"{$order->id}\">删除订单</button>"
]),

创建resources/js/nova-delete-action.js并注册到Nova:

document.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll('.inline-delete-btn').forEach(btn => {
        btn.addEventListener('click', async (e) => {
            e.preventDefault();
            const orderId = btn.dataset.id;

            // 加载动作配置并弹出模态框
            const actionRes = await Nova.request().get('/nova-api/orders/actions/delete-order');
            const { response } = await Nova.modal(
                actionRes.data.name,
                Nova.form(actionRes.data.fields, {
                    resourceName: 'orders',
                    resourceId: orderId,
                    actionId: 'delete-order',
                })
            );

            if (response) {
                await Nova.request().post('/nova-api/orders/actions/delete-order', {
                    resources: [orderId],
                    ...response.data,
                });
                Nova.refreshMetrics();
            }
        });
    });
});

在NovaServiceProvider中注册该JS文件:

Nova::script('nova-delete-action', public_path('js/nova-delete-action.js'));

方案三:纯自定义AJAX删除逻辑

完全脱离Nova的Action系统,自己实现模态框和删除接口,灵活性最高:

  1. 创建删除接口
    在routes/nova.php中添加路由:
use App\Http\Controllers\Nova\DeleteOrderController;

Route::post('/delete-order', [DeleteOrderController::class, '__invoke'])->name('nova.delete-order');

创建控制器app/Http/Controllers/Nova/DeleteOrderController.php:

use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class DeleteOrderController extends Controller
{
    public function __invoke(Request $request)
    {
        $request->validate([
            'order_id' => 'required|exists:orders,id',
            'note' => 'required|string',
        ]);

        $order = Order::findOrFail($request->order_id);
        $order->delete();

        Log::info('订单删除记录', [
            'order_id' => $order->id,
            'note' => $request->note,
            'operator' => auth()->user()->name,
        ]);

        return response()->json(['success' => true, 'message' => '订单已删除']);
    }
}
  1. 添加按钮和模态框
    在Table Metric的行操作中添加按钮:
'actions' => implode('', [
    $this->editButton($order),
    "<button class=\"custom-delete-btn btn btn-danger btn-sm ml-2\" data-id=\"{$order->id}\">删除订单</button>"
]),

在Nova的自定义布局或通过JS注入模态框:

<div id="delete-modal" class="modal fade" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">确认删除订单</h5>
        <button type="button" class="close" data-dismiss="modal">&times;</button>
      </div>
      <div class="modal-body">
        <textarea id="delete-note" class="form-control" placeholder="请输入删除备注" required></textarea>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
        <button type="button" class="btn btn-danger" id="confirm-delete">确认删除</button>
      </div>
    </div>
  </div>
</div>

<script>
let currentOrderId = null;

document.addEventListener('DOMContentLoaded', () => {
    // 打开模态框
    document.querySelectorAll('.custom-delete-btn').forEach(btn => {
        btn.addEventListener('click', () => {
            currentOrderId = btn.dataset.id;
            $('#delete-modal').modal('show');
        });
    });

    // 提交删除
    document.getElementById('confirm-delete').addEventListener('click', async () => {
        const note = document.getElementById('delete-note').value.trim();
        if (!note) return;

        try {
            const res = await fetch('/nova/delete-order', {
                method: 'POST',
                headers: {
                    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    order_id: currentOrderId,
                    note: note,
                }),
            });

            const data = await res.json();
            if (data.success) {
                $('#delete-modal').modal('hide');
                Nova.refreshMetrics();
                Nova.success(data.message);
            } else {
                Nova.error('删除失败,请重试');
            }
        } catch (err) {
            Nova.error('请求出错,请检查网络');
        }
    });
});
</script>

将上述HTML和JS编译后注册到Nova即可。


内容的提问来源于stack exchange,提问作者mstdmstd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:10:58