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

求助:Laravel Nova 4表单添加自定义按钮实现保存后复制记录

Laravel Nova 4 添加「保存并复制」自定义按钮方案

以下是实现表单底部自定义按钮,保存当前记录后自动填充数据到新创建表单的具体步骤:


步骤1:创建前端自定义按钮组件

在项目的 resources/js/components 目录下新建 SaveAndDuplicateButton.vue 文件,实现保存后跳转并预填数据的逻辑:

<template>
  <NovaButton
    type="primary"
    :disabled="form.processing"
    @click="handleSaveAndDuplicate"
  >
    保存并复制
  </NovaButton>
</template>

<script setup>
import { useForm } from '@nova-ui/framework'

const form = useForm()

async function handleSaveAndDuplicate() {
  // 先提交保存当前记录
  await form.submit()

  // 过滤无需复制的系统字段
  const payload = Object.fromEntries(
    Object.entries(form.value).filter(([key]) => !['id', 'created_at', 'updated_at', 'deleted_at'].includes(key))
  )

  // 生成带预填参数的创建页面链接并跳转
  const queryString = new URLSearchParams(payload).toString()
  window.location.href = `/nova/resources/${form.resourceName}/create?${queryString}`
}
</script>

在 resources/js/app.js 中注册该组件:

import SaveAndDuplicateButton from './components/SaveAndDuplicateButton'

Nova.booting((app) => {
  app.component('save-and-duplicate-button', SaveAndDuplicateButton)
})

运行 npm run dev 编译前端资源。


步骤2:在Resource中添加自定义按钮

打开对应的Nova Resource文件(如 app/Nova/YourResource.php),重写 formActions 方法,将自定义按钮添加到表单操作栏:

use Laravel\Nova\Actions\Action;
use Laravel\Nova\Http\Requests\NovaRequest;

class YourResource extends Resource
{
    // ... 其他配置代码

    public function formActions(NovaRequest $request)
    {
        return [
            // 保留默认保存按钮
            Action::make('保存')
                ->submit('save'),
            
            // 添加自定义「保存并复制」按钮
            Action::make('保存并复制')
                ->component('save-and-duplicate-button'),
            
            // 可选:保留默认「保存并新增」按钮
            Action::make('保存并新增')
                ->submit('saveAndContinue'),
        ];
    }
}

步骤3:处理特殊字段(可选)

Nova默认会自动匹配URL参数与表单字段名完成填充,但部分特殊字段需要额外处理:

  • 关联字段:直接传递关联ID(如 category_id=1)即可自动选中对应模型;
  • 文件字段:无法通过URL参数传递,会自动留空,需用户重新上传;
  • 敏感字段:在前端过滤逻辑中添加字段名(如 password),避免复制敏感数据。

可选优化:后端处理复制逻辑(更可靠)

如果需要处理复杂的复制规则(如关联模型复制、字段默认值修改),可以通过后端接口实现:

  1. 在 routes/web.php 中添加Nova专用路由:
use Illuminate\Support\Facades\Route;
use Laravel\Nova\Http\Requests\NovaRequest;

Route::post('/nova/resources/{resource}/{id}/duplicate', function (NovaRequest $request, $resource, $id) {
    $model = $request->findModelOrFail($id);
    
    // 复制模型并过滤系统字段
    $duplicate = $model->replicate([
        'created_at', 'updated_at', 'deleted_at'
        // 可添加其他无需复制的字段
    ]);

    // 可选:修改复制后的字段默认值
    // $duplicate->status = 'draft';
    
    // 生成预填参数并跳转至创建页面
    $query = http_build_query($duplicate->toArray());
    return redirect()->route('nova.pages.create', [
        'resource' => $resource,
        'query' => $query,
    ]);
})->middleware(['nova'])->name('nova.resources.duplicate');
  1. 修改前端按钮的点击逻辑,调用后端接口:
async function handleSaveAndDuplicate() {
  await form.submit()

  if (form.mode.value === 'update') {
    // 更新页面调用后端复制接口
    const response = await fetch(`/nova/resources/${form.resourceName}/${form.value.id}/duplicate`, {
      method: 'POST',
      headers: {
        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
        'Accept': 'application/json',
      },
    })
    const data = await response.json()
    window.location.href = data.redirectUrl
  } else {
    // 创建页面沿用前端逻辑
    const payload = Object.fromEntries(
      Object.entries(form.value).filter(([key]) => !['id', 'created_at', 'updated_at', 'deleted_at'].includes(key))
    )
    const queryString = new URLSearchParams(payload).toString()
    window.location.href = `/nova/resources/${form.resourceName}/create?${queryString}`
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 00:02:08