这里介绍一个富文本编辑器:Tinymce

接下来就是把Voyager所用的Tinymce主题移植到laravel-admin

1. 准备资源 (下方有下载地址)

2.构建拓展组件

<?php

namespace App\Agent\Extensions\Form;

use App\Agent\Form\Field;
class Tinymce extends Field
{
    protected $view = 'agent.ex.tinymce';

    protected static $js = [
        '/vendor/tinymce/tinymce.js',
    ];

    public function render()
    {
        $this->script = <<<EOT
        
tinymce.init({
    menubar: false,
    selector:'textarea.{$this->getElementClassString()}',
    skin: 'voyager',
    min_height: 600,
    resize: 'vertical',
    plugins: 'link, image, code, youtube, giphy, table, textcolor, lists, codesample',
    extended_valid_elements : 'input[id|name|value|type|class|style|required|placeholder|autocomplete|onclick]',
    file_browser_callback: function(field_name, url, type, win) {
        if(type =='image'){
          $('#upload_file').trigger('click')
        }
    },
    toolbar: 'styleselect bold italic underline | forecolor backcolor | alignleft aligncenter alignright | bullist numlist outdent indent | link image table youtube giphy | code codesample',
    convert_urls: false,
    image_caption: true,
    image_title: true,
    init_instance_callback: function (editor) {
        if (typeof tinymce_init_callback !== "undefined") {
            tinymce_init_callback(editor);
        }
    }
  });

EOT;
        return parent::render();
    }
}

视图部分:

<div class="form-group {!! !$errors->has($errorKey) ?: 'has-error' !!}">

    <label for="{{$id}}" class="col-sm-2 control-label">{{$label}}</label>

    <div class="col-sm-8">

        @include('agent::form.error')

        <textarea class="form-control {{ $class }}" name="{{$name}}" placeholder="{{ $placeholder }}" {!! $attributes !!} >{{ old($column, $value) }}</textarea>

        @include('agent::form.help-block')

    </div>
</div>
再在bootstrap.php中注册:
<?php


use App\Agent\Form;
use App\Agent\Extensions\Form\Tinymce;

Form::extend('tiny', Tinymce::class);

就能在form里使用$form->tiny()来使用Tinymce了。 但是使用时你会发现图片上传没有反应,怎么回事呢? 问题出在

$('#upload_file').trigger('click')

这一句 这是voyager-tinymce使用的图片上传方法,点击触发一个表单外的input file框,再通过这个事件的回调来上传图片和显示图片。 那怎么修改呢?
在视图-content.blade.php中,在 {!! $content !!} 下加入这个input file框

<section class="content">

        @include('agent::partials.error')
        @include('agent::partials.success')
        @include('agent::partials.exception')
        @include('agent::partials.toastr')

        {!! $content !!}

        <input name="image" multiple id="upload_file" type="file" style="display: none">
    </section>

然后修改Tinymce.php类:

<?php
/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2018/8/9
 * Time: 9:45
 */

namespace App\Agent\Extensions\Form;

use App\Agent\Form\Field;
class Tinymce extends Field
{
    protected $view = 'agent.ex.tinymce';

    protected static $js = [
        '/vendor/tinymce/tinymce.js',
    ];

    public function render()
    {
        $this->script = <<<EOT
        
tinymce.init({
    menubar: false,
    selector:'textarea.{$this->getElementClassString()}',
    skin: 'voyager',
    min_height: 600,
    resize: 'vertical',
    plugins: 'link, image, code, youtube, giphy, table, textcolor, lists, codesample',
    extended_valid_elements : 'input[id|name|value|type|class|style|required|placeholder|autocomplete|onclick]',
    file_browser_callback: function(field_name, url, type, win) {
        if(type =='image'){
          $('#upload_file').trigger('click').change(function(){
          let formData = new FormData(), self = $(this);
            formData.append('image', $('#upload_file')[0].files[0]);
          $.ajax({
                url: '/api/v2/upload',
                type: "POST",
                data: formData,
                dataType: 'json',
                processData: false,
                contentType: false,
                success: function (res) {
                    if (res.status == 1) {
                        toastr.success('上传成功');
                        $('.mce-btn.mce-open').parent().find('.mce-textbox').val(res.data);
                        self.val('')
                    }else if (res.status == 2) {
                        toastr.success('上传失败');
                    }else if (res.status == 3) {
                        toastr.success('文件类型错误');
                    }
                }
            });
          });
        }
    },
    toolbar: 'styleselect bold italic underline | forecolor backcolor | alignleft aligncenter alignright | bullist numlist outdent indent | link image table youtube giphy | code codesample',
    convert_urls: false,
    image_caption: true,
    image_title: true,
    init_instance_callback: function (editor) {
        if (typeof tinymce_init_callback !== "undefined") {
            tinymce_init_callback(editor);
        }
    }
  });

EOT;
        return parent::render();
    }
}

其中

$.ajax({
                url: '/api/v2/upload',
                type: "POST",
                data: formData,
                dataType: 'json',
                processData: false,
                contentType: false,
                success: function (res) {
                    if (res.status == 1) {
                        toastr.success('上传成功');
                        $('.mce-btn.mce-open').parent().find('.mce-textbox').val(res.data);
                        self.val('')
                    }else if (res.status == 2) {
                        toastr.success('上传失败');
                    }else if (res.status == 3) {
                        toastr.success('文件类型错误');
                    }
                }
            });

就是上传图片并显示在编辑器里的ajax方法 后端处理:

public function upload()
    {
        $fullFilename = null;
        $resizeWidth = 1800;
        $resizeHeight = null;
        $file = $this->request->file('image');
        $path = 'uploads/'.date('Y-m').'/';

        $filename = basename(md5($file->getClientOriginalName()), '.'.$file->getClientOriginalExtension());
        $filename_counter = 1;

        // Make sure the filename does not exist, if it does make sure to add a number to the end 1, 2, 3, etc...
        while (Storage::disk(config('admin.upload.disk'))->exists($path.$filename.'.'.$file->getClientOriginalExtension())) {
            $filename = basename(md5($file->getClientOriginalName()), '.'.$file->getClientOriginalExtension()).(string) ($filename_counter++);
        }

        $fullPath = $path.$filename.'.'.$file->getClientOriginalExtension();

        $ext = $file->guessClientExtension();

        if (in_array($ext, ['jpeg', 'jpg', 'png', 'gif'])) {

            $image = Image::make($file)
                ->resize($resizeWidth, $resizeHeight, function (Constraint $constraint) {
                    $constraint->aspectRatio();
                    $constraint->upsize();
                })
                ->encode($file->getClientOriginalExtension(), 75);

            // move uploaded file from temp to uploads directory
            if (Storage::disk(config('admin.upload.disk'))->put($fullPath, (string) $image, 'public')) {
                $status = '1';
                $fullFilename = $fullPath;
            } else {
                $status = '2';
                $fullFilename = '';
            }
        } else {
            $status = '3';
            $fullFilename = '';
        }

        // echo out script that TinyMCE can handle and update the image in the editor
        return json_encode(['data' => disk($fullFilename), 'status' => $status]);
    }

图片文件名处理的很粗糙,可以根据自己项目更改 注意要安装 Intervention/Image 这个composer 包 类要引入以下几个类

use Illuminate\Support\Facades\Storage;
use Intervention\Image\Constraint;
use Intervention\Image\Facades\Image;

最后添加一个post路由就完成了图片上传

 

资源包下载 tinymce


心意难顺
活着难受,死又不敢