zoukankan      html  css  js  c++  java
  • react-draft-wysiwyg富文本组件

    import React, { useState, useEffect } from 'react'
    import { EditorState, convertToRaw, ContentState, Modifier } from 'draft-js'
    import { Input, message } from 'antd'
    // https://jpuri.github.io/react-draft-wysiwyg/#/docs
    import { Editor } from 'react-draft-wysiwyg'
    import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
    import draftToHtml from 'draftjs-to-html'
    import htmlToDraft from 'html-to-draftjs'
    import urls from '../../api/urls'
    import axios from 'axios'
    import { htmlFormat, addUploadToken } from '../../utils/tools'
    const { TextArea } = Input
    
    //image position is lost when converting from html to EditorState
    //参考链接:https://github.com/jpuri/html-to-draftjs/issues/101
    // https://github.com/jpuri/html-to-draftjs/blob/master/src/library/index.js
    export default function MyEditor(props) {
      const { value = {}, onChange } = props
    
      //把html字符传转换成富文本要求的格式
      const formatEditorState = (text) => {
        //解决image位置无法保存的bug
        const html = text ? htmlFormat(text) : ''
        const contentBlock = htmlToDraft(html, (nodeName, node) => {
          if (nodeName === 'img' && node instanceof HTMLImageElement) {
            const entityConfig = {}
            entityConfig.src = node.getAttribute
              ? node.getAttribute('src') || node.src
              : node.src
            entityConfig.alt = node.alt
            entityConfig.height = node.style.height
            entityConfig.width = node.style.width
            if (node.style.float) {
              entityConfig.alignment = node.style.float
            } else {
              if (node.style.textAlign) {
                entityConfig.alignment = node.style.textAlign
              }
            }
    
            return {
              type: 'IMAGE',
              mutability: 'MUTABLE',
              data: entityConfig,
            }
          }
        })
        const contentState = ContentState.createFromBlockArray(
          contentBlock.contentBlocks
        )
        const result = EditorState.createWithContent(contentState)
        return result
      }
      const [editorState, setEditorState] = useState(formatEditorState(value.text))
    
      const handleChange = (value) => {
        setEditorState(value)
        const html = draftToHtml(convertToRaw(editorState.getCurrentContent()))
        //提交给后端的是html字符串
        onChange({
          isChange: false,
          text: html,
        })
      }
    
      //图片上传
      const uploadImageCallBack = (file) => {
        return new Promise((resolve, reject) => {
          let formData = new FormData()
          formData.append('file', file)
          formData.append('ctype', 'course')
          axios(urls.light.uploadFile, {
            method: 'POST',
            data: formData,
            headers: {
              ...addUploadToken()
            },
          })
            .then((res) => {
              if (res.data.state === 1) {
                resolve({ data: { link: res.data.data.fileImg } })
              } else {
                message.error('图片上传失败', 2)
                reject(res)
              }
            })
            .catch((err) => {
              reject(err)
            })
        })
      }
    
    
      useEffect(() => {
        //课程图片列表上传的图片尾部有一个加号,点击加号会自动把图片插入到富文本框光标所在的位置
        if (value.isChange) {
          const contentState = Modifier.replaceText(
            editorState.getCurrentContent(),
            editorState.getSelection(),
            value.text,
          );
          const temp = EditorState.push(editorState, contentState, 'insert-characters')
          let html = draftToHtml(convertToRaw(temp.getCurrentContent()))
          html = html.replace(/&lt;/g, '<').replace(/&gt;/g, '>')
          setEditorState(formatEditorState(html))
          //提交给后端的是html字符串
          onChange({
            isChange: false,
            text: html,
          })
        }
      }, [value])
    
      return (
        <div>
          <Editor
            editorState={editorState}
            wrapperClassName="m-my-editor-wrapper"
            editorClassName="demo-editor"
            localization={{
              locale: 'zh',
            }}
            onEditorStateChange={handleChange}
            toolbar={{
              image: {
                urlEnabled: true,
                uploadEnabled: true,
                alignmentEnabled: true, // 是否显示排列按钮 相当于text-align
                uploadCallback: uploadImageCallBack,
                previewImage: true,
                inputAccept: 'image/*',
                alt: { present: false, mandatory: false, previewImage: true },
              },
            }}
          />
          <TextArea
            disabled
            value={draftToHtml(convertToRaw(editorState.getCurrentContent()))}
            autoSize={{ minRows: 5, maxRows: 10 }}
          ></TextArea>
        </div>
      )
    }
    

    htmlFormat:

    import { html2json, json2html } from 'html2json'
    
    
    //富文本html格式转换
    const htmlFormat = (data) => {
      const json = html2json(data)
      Array.isArray(json.child) &&
        json.child.forEach((item) => {
          if (item.tag === 'div') {
            item.tag = 'img'
            if (
              item.attr &&
              Array.isArray(item.child) &&
              item.child.length === 1 &&
              item.child[0].attr &&
              Array.isArray(item.child[0].attr.style)
            ) {
              const style = item.attr.style + item.child[0].attr.style.join('')
              item.attr = {
                ...item.child[0].attr,
              }
              item.attr.style = style
            }
          }
        })
    
      const html = json2html(json)
      return html
    }

  • 相关阅读:
    使用python执行系统命令——subprocess
    python与数据库交互的模块pymysql
    爬虫实战_爬取豆瓣图书利用csv库存储
    正则表达式_爬取中国古诗词网与豆瓣热门图书
    双文件上传详解
    三.基础部分+asp网站搭建
    二.Google黑客语法
    主动信息收集(二)
    一.搜索引擎如何使用
    记录学习——算法时间复杂度求法
  • 原文地址:https://www.cnblogs.com/xutongbao/p/15264343.html
Copyright © 2011-2022 走看看