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

Rails项目中Summernote选图后自动插入,如何改为点击插入按钮触发?

解决Summernote选择图片后自动插入的问题

我明白你遇到的问题——默认情况下Summernote选择图片后会直接上传插入,跳过了「确认插入」的步骤,确实不符合预期的交互逻辑。我们可以通过自定义图片上传弹窗和按钮逻辑来解决这个问题,具体修改如下:

步骤1:替换默认图片按钮为自定义按钮

首先在Summernote初始化配置中,把工具栏里的默认picture按钮替换成我们自己的customPicture按钮,这样就能完全接管图片上传的流程:

$(document).ready(function($) {
  $(".summernote_custom").summernote({
    height: 200,
    styleTags: ['p', 'h1', 'h2'],
    toolbar: [
      ['style', ['bold', 'italic', 'underline', 'clear']],
      ['para', ['ul', 'ol', 'paragraph','style']],
      ['fontname', ['fontname']],
      ['fontsize',['fontsize']],
      ['insert', ['customPicture','link']] // 替换默认picture为自定义按钮
    ],
    dialogsInBody: true,
    buttons: {
      customPicture: function(context) {
        var ui = $.summernote.ui;
        
        // 创建自定义图片按钮
        var button = ui.button({
          contents: '<i class="note-icon-picture"/>',
          tooltip: '插入图片',
          click: function() {
            // 点击按钮时打开自定义弹窗
            openCustomImageDialog(context);
          }
        });
        
        return button.render();
      }
    }
  });
});

步骤2:编写自定义图片上传弹窗

接下来创建一个包含「文件选择、预览、确认插入」的自定义弹窗,让用户可以先预览图片,再手动触发上传插入:

function openCustomImageDialog(context) {
  // 构建Bootstrap模态框(如果项目没用到Bootstrap,可自行替换为原生弹窗)
  var $dialog = $('<div class="modal fade" tabindex="-1" role="dialog">' +
    '<div class="modal-dialog" role="document">' +
      '<div class="modal-content">' +
        '<div class="modal-header">' +
          '<h5 class="modal-title">插入图片</h5>' +
          '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
            '<span aria-hidden="true">&times;</span>' +
          '</button>' +
        '</div>' +
        '<div class="modal-body">' +
          '<input type="file" id="customImageInput" accept="image/*" style="margin-bottom:10px;">' +
          '<img id="imagePreview" src="#" alt="预览图片" style="max-width:100%;display:none;">' +
        '</div>' +
        '<div class="modal-footer">' +
          '<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>' +
          '<button type="button" class="btn btn-primary" id="uploadAndInsertBtn">插入图片</button>' +
        '</div>' +
      '</div>' +
    '</div>' +
  '</div>');
  
  // 文件选择后显示预览
  $dialog.find('#customImageInput').on('change', function(e) {
    var file = e.target.files[0];
    if (file) {
      var reader = new FileReader();
      reader.onload = function(event) {
        $dialog.find('#imagePreview').attr('src', event.target.result).show();
      };
      reader.readAsDataURL(file);
    }
  });
  
  // 点击「插入图片」按钮时触发上传和插入
  $dialog.find('#uploadAndInsertBtn').on('click', function() {
    var file = $dialog.find('#customImageInput')[0].files[0];
    if (!file) {
      alert('请先选择图片文件');
      return;
    }
    
    // 调用上传函数,成功后插入图片
    uploadImage(file, context.invoke('editor'), function(imageUrl) {
      context.invoke('editor.insertImage', imageUrl, function($image) {
        $image.css('width', '100%');
        $image.attr('data-filename', 'retriever');
      });
      $dialog.modal('hide'); // 关闭弹窗
    });
  });
  
  // 显示弹窗
  $dialog.modal('show');
  
  // 弹窗关闭后清理DOM元素
  $dialog.on('hidden.bs.modal', function() {
    $(this).remove();
  });
}

步骤3:修改上传函数支持回调

最后调整uploadImage函数,添加回调参数,确保只有上传成功后才会执行图片插入操作:

function uploadImage(image, editor, successCallback) {
  var data = new FormData();
  data.append("image", image);
  data.append("name", "resource");
  
  $.ajax({
    data: data,
    type: "POST",
    url: "#{ajax_upload_doctor_attachments_path}",
    cache: false,
    contentType: false,
    processData: false,
    success: function(data) {
      var imageUrl = "#{HOST}" + data.url;
      if (successCallback) {
        successCallback(imageUrl); // 上传成功后执行插入回调
      }
    },
    error: function(data) {
      console.log(data);
      alert('图片上传失败,请重试');
    }
  });
}

原理说明

通过替换默认的图片按钮,我们完全绕过了Summernote自带的自动上传插入逻辑,转而使用自定义的交互流程:用户点击图片按钮→选择文件预览→手动确认插入→上传图片并插入到编辑器。这样就实现了「等待点击插入按钮再触发上传」的需求。

如果你的项目没有使用Bootstrap,可以把弹窗部分改成原生JavaScript的弹窗(比如自定义div的显示隐藏),核心逻辑保持一致即可。

内容的提问来源于stack exchange,提问作者Muhammad Faisal Iqbal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:37:04