ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

react+quill封装的富文本编辑器(附带转接oss上传图片)

2021-05-21 09:04:15  阅读:194  来源: 互联网

标签:picker 文本编辑 oss snow react font data ql before


ps:老早之前写了一个simditor富文本,但是在实际的使用中bug很多,故重新寻觅了新的富文本,使用效果有待考量,但是功能自己感觉比simditor要好很多,可以自定义的内容比较开放。
###效果图
image.png
###1.js文件 npm i quill 本文使用的版本是"quill": “^1.3.7”

import React, { Component } from 'react';
import Quill from "quill";
import $ from "jquery";
import config from '../../config.js';
import { Button, Upload } from 'antd';
require("quill/dist/quill.snow.css");
import styles from './QuillRichText.less';
import request from '../../utils/request';
import { getUid } from '../../utils/auth';
import moment from 'moment';
/**
 * 取值 let goods_desc = $(".detailContainer").find(".simditor-body").html();
 */
let ossConfig;
class QuillRichText extends Component {
    state = {
        textContent:''
    }
    componentDidMount = () => {
        this.initEditor();
    };

    //初始化编辑器
    initEditor = () => {
        let that = this;
        // Add fonts to whitelist
        /*----自定义字体 ----*/
        //1.需先引入需要展示的字体样式  然后加入到字体白名单里
        const Font = Quill.import('formats/font');
        // We do not add Aref Ruqaa since it is the default
        let fonts = [
        'SimSun',
        'SimHei',
        'Microsoft-YaHei',
        'KaiTi',
        'FangSong',
        'Arial',
        'Times-New-Roman',
        'monospace',
        'serif',
        'consolas'
        ];
        Font.whitelist = fonts; //将字体加入到白名单
        Quill.register(Font, true);
        let toolbarOptions = [
            ['bold', 'italic', 'underline'],        // toggled buttons
            [{ 'list': 'bullet' }],  
            ["link","image"],              // custom button values
            [{ 'size': ['small', false, 'large', 'huge'] }],  // custom dropdown
            [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
            [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
            [{ 'font': fonts},'video']
          ];
        //   "SimSun","SimHei","Microsoft-YaHei","KaiTi","FangSong","Arial","Times New Roman","sans-serif"
        let config = {
            debug: 'info',
            modules: {
                toolbar: toolbarOptions 
            },
            placeholder: '请输入内容...',
            readOnly: false,
            theme: 'snow'
        };
        this.editor = new Quill('#editor', config);// 初始化编辑器
        Quill.debug("error");//只开启error提示  默认的console还是会打印 没有找到更好的解决办法
        let toolbar = this.editor.getModule('toolbar');
        // console.log(this.props)
        this.editor.container.firstChild.innerHTML = this.props.value; //赋值富文本  此处用于父组件传值给子组件quill(主要用于编辑页面,只做添加页面此处可忽略)
        //点击quill的上传图片转接到oss上传的图标上
        toolbar.addHandler('image', () => {
            $('.editUpload .ant-upload').click()
        });
    };

    //富文本图片上传至oss上
    beforeGoodsUpload=(file)=> {
        let files = [];
        this.setState({
            fileList: [...files]
        })
         return false;
    }
    //图片oss上传   此处大致讲解  不明白的看我之前发布的关于oss上传的文章
    uploadGoodsPic(index,file){
        const UID = getUid();
        const isJPG = file.file.type === 'image/jpeg';
        const isPNG = file.file.type === 'image/png';
        const isLt2M = file.file.size / 1024 / 1024 < 5;
        if (!isJPG && !isPNG) {
            message.error('只能上传jpg|png|jpeg');
            return;
        }else{
            if (!isLt2M) {
                message.error('图片尺寸必须小于 5MB!');
                return;
            }
        }
        let param_first = {
            uid:UID
        };
        
        /**** oss上传****/
        request(`*********`, {  //获取oss上传所需的参数接口  后端提供
                method: 'POST',
                headers: config.headers,
                body:config.parseJson(param_first)
        }).then((res) => {
            ossConfig = {
                policy:res.data.policy,
                OSSAccessKeyId:res.data.accessid,
                callback:res.data.callback,
                signature:res.data.signature,
                url:res.data.host,
                dir:res.data.dir,
            };
            const photo = file.fileList[0].originFileObj;  // 获取图片对象
            let pointIndex = photo.name.lastIndexOf('.');
            let suffixName = photo['name'].substring(pointIndex);//后缀名
            const photoName = moment().format('YYYYMMDDHHmmss') + (Math.floor(Math.random() * 3665668)) +  suffixName;  // 原图片的名称
            // const photoName = photo.name;  // 原图片的名称
            const key = ossConfig.dir + UID  + photoName;  // 存储到oss的图片名称 自己定,必须确保唯一性,不然会覆盖oss中原有的文件
            const policy = ossConfig.policy; // 服务器端同事调oss的API,通过接口返回给前端的 policy
            const OSSAccessKeyId = ossConfig.OSSAccessKeyId;  // 服务器端同事调oss的API,通过接口返回给前端的 OSSAccessKeyId
            const callback = ossConfig.callback;  // 服务器端同事调oss的API,通过接口返回给前端的 callback。这个是需要 oss 触发这个回调来通知服务器操作结果。
            const signature = ossConfig.signature;  // 服务器端同事调oss的API,通过接口返回给前端的 signature。这个就是签名,最关键的。
            const url = ossConfig.url;
            const dir = ossConfig.dir;
            // biu一下,提交给oss
            let param = {
                name:photoName,
                key,
                policy:policy,
                OSSAccessKeyId:OSSAccessKeyId,
                success_action_status:'200',
                callback:callback,
                signature:signature,
                file:photo
            };
            const formData = new FormData();
            Object.keys(param).forEach((key) => {
              formData.append(key, param[key]);
            });
            request(url, {
                method: 'POST',
                headers: {
                },
                body: formData,
            }).then((res) => {
                //把上传到oss上的图片赋值给quill编辑器
                let quill = this.editor;
                let range = quill.selection.savedRange.index;
                if(range || range == 0){
                    quill.insertEmbed(range,'image',res.data.data.full_url);
                }
                quill.setSelection(quill.getSelection().index+1);
            })
        });
    }

    render() {
        let placeholder = ''
        const { value,pla } = this.props;
        // pla ? placeholder = pla : placeholder = '请输入内容'
        return (
            <div className="quillRich">
                <div id="editor" ref="editor">
                </div>
                {/* 此处上传隐藏 只做上传使用 */}
                <Upload 
                    name="goods" 
                    listType="picture-card" 
                    showUploadList="false" 
                    className="editUpload"
                    action=""
                    beforeUpload={this.beforeGoodsUpload}
                    onChange={this.uploadGoodsPic.bind(this,0)}
                    headers={config.headerAuth}
                    showUploadList={false}
                    accept=".png,.jpg,.jpeg"
                    >  
                </Upload>
            </div>
        );
    }
}

export default QuillRichText;

###2.less文件 覆盖quill一些自带的样式

    .ql-toolbar{
        width: 100%!important;
        border: none!important;
        border-bottom:1px solid #E4E4E4!important;
    }
    #editor,.ql-editor{
        border: none!important;
        max-height: 440px!important;
    }
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
        content: "宋体";
        font-family: "SimSun";
    }
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
        content: "黑体";
        font-family: "SimHei";
    }
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
        content: "微软雅黑";
        font-family: "Microsoft YaHei";
    }
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
        content: "楷体";
        font-family: "KaiTi";
    }
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
        content: "仿宋";
        font-family: "FangSong";
    }
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
        content: "Arial";
        font-family: "Arial";
    }
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
        content: "Times New Roman";
        font-family: "Times New Roman";
    }
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
        content: "sans-serif";
        font-family: "sans-serif";
    }
    
    .ql-font-SimSun {
        font-family: "SimSun";
    }
    .ql-font-SimHei {
        font-family: "SimHei";
    }
    .ql-font-Microsoft-YaHei {
        font-family: "Microsoft YaHei";
    }
    .ql-font-KaiTi {
        font-family: "KaiTi";
    }
    .ql-font-FangSong {
        font-family: "FangSong";
    }
    .ql-font-Arial {
        font-family: "Arial";
    }
    .ql-font-Times-New-Roman {
        font-family: "Times New Roman";
    }
    .ql-font-sans-serif {
        font-family: "sans-serif";
    }
    .ql-snow .ql-tooltip[data-mode=link]::before{
        content: "\94FE\63A5";
    }
    .ql-snow .ql-tooltip.ql-editing a.ql-action::after{
        content: "\786E\5B9A";
    }
    .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before, 
    .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before{
        content: "\5C0F\53F7\5B57\4F53";
    }
    .ql-snow .ql-picker.ql-size .ql-picker-label::before,
    .ql-snow .ql-picker.ql-size .ql-picker-item::before{
        content: "\6B63\5E38\5927\5C0F";
    }
    .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
    .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before{
        content: "\5927\53F7\5B57\4F53";
    }
    .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before, 
    .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before{
        content: "\8D85\5927\5B57\4F53";
    }
    .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, 
    .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before{
        content: "\6807\9898\0020\0031";
    }
    .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, 
    .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before{
        content: "\6807\9898\0020\0032";
    }
    .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, 
    .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before{
        content: "\6807\9898\0020\0033";
    }
    .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, 
    .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before{
        content: "\6807\9898\0020\0034";
    }
    .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, 
    .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before{
        content: "\6807\9898\0020\0035";
    }
    .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, 
    .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before{
        content: "\6807\9898\0020\0036";
    }
    .ql-snow .ql-picker.ql-header .ql-picker-label::before, 
    .ql-snow .ql-picker.ql-header .ql-picker-item::before{
        content: "\666E\901A\6587\672C";
    }
    .ql-snow .ql-tooltip::before{
        content: "\8BBF\95EE\94FE\63A5";
    }
    .ql-snow .ql-tooltip a.ql-action::after{
        content: "\7F16\8F91";
    }
    .ql-snow .ql-tooltip a.ql-remove::before{
        content: "\79FB\9664\000A";
    }
    .ql-snow .ql-tooltip[data-mode=video]::before{
        content: "\89C6\9891\94FE\63A5";
    }
}

###3.自定义字体 font.less文件

/*font汉化*/
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
  content: "宋体";
  font-family: "SimSun";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
  content: "黑体";
  font-family: "SimHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
  content: "微软雅黑";
  font-family: "Microsoft YaHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
  content: "楷体";
  font-family: "KaiTi";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
  content: "仿宋";
  font-family: "FangSong";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
  content: "Arial";
  font-family: "Arial";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
  content: "Times New Roman";
  font-family: "Times New Roman";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
  content: "sans-serif";
  font-family: "sans-serif";
}

.ql-font-SimSun {
  font-family: "SimSun";
}
.ql-font-SimHei {
  font-family: "SimHei";
}
.ql-font-Microsoft-YaHei {
  font-family: "Microsoft YaHei";
}
.ql-font-KaiTi {
  font-family: "KaiTi";
}
.ql-font-FangSong {
  font-family: "FangSong";
}
.ql-font-Arial {
  font-family: "Arial";
}
.ql-font-Times-New-Roman {
  font-family: "Times New Roman";
}
.ql-font-sans-serif {
  font-family: "sans-serif";
}

标签:picker,文本编辑,oss,snow,react,font,data,ql,before
来源: https://blog.csdn.net/baidu_41457482/article/details/117106642

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有