import React , { useEffect , useRef , useState } from 'react' ; import QiniuUploadImage from '@app/components/qiniu-upload-image' ; import './styles/index.scss' ; interface Props { onChange ? : ( html : string ) => void ; onSubmit : ( html : string ) => { } ; content : string ; placeholder : string ; editorStyle : object ; onLoad : ( controller : any ) => { } ; } const Editor = ( { onChange = ( ) => { } , onSubmit , content , placeholder , editorStyle = { } , onLoad } ) => { const editorRef = useRef ( ) ; const [ submitting , setSubmitting ] = useState ( false ) ; const onInput = ( e ) => { let content = e . target . innerHTML ; if ( content == '<br>' ) content = '' ; onChange ( content ) ; if ( ! content ) editorRef . current . innerHTML = '' ; } ; const clearContent = function ( ) { editorRef . current . innerHTML = '' ; } ; const blur = function ( ) { editorRef . current . blur ( ) ; } ; const focus = function ( ) { editorRef . current . focus ( ) ; } ; function getTargetNode ( ele , target ) { if ( ! ele || ele === document ) return false ; return ele === target ? true : getTargetNode ( ele . parentNode , target ) ; } const innterHTML = ( html ) => { const $editor = editorRef . current ; let selection = window . getSelection ( ) ; if ( selection && selection . focusNode && $editor == selection . focusNode . parentNode ) { let range = selection . getRangeAt ( 0 ) ; let fragment = range . createContextualFragment ( html ) ; range . insertNode ( fragment . lastChild ) ; } else { $editor . innerHTML = $editor . innerHTML + html ; } setTimeout ( ( ) => { onChange ( $editor . innerHTML ) ; } ) ; } ; const addImage = ( src ) => { innterHTML ( "<img src=\"" + src + "\" />" ) ; } ; useEffect ( ( ) => { if ( ( typeof Range !== "undefined" ) && ! Range . prototype . createContextualFragment ) { Range . prototype . createContextualFragment = function ( html ) { var frag = document . createDocumentFragment ( ) , div = document . createElement ( "div" ) ; frag . appendChild ( div ) ; div . outerHTML = html ; return frag ; } ; } if ( content ) innterHTML ( content ) ; if ( onLoad ) { onLoad ( { clearContent , blur , focus , innterHTML , addImage } ) ; } editorRef . current . addEventListener ( "paste" , function ( e ) { var content ; e . preventDefault ( ) ; var clipboardData = window . clipboardData ; if ( ! clipboardData ) { clipboardData = e . clipboardData ; } if ( clipboardData . files && clipboardData . files . length > 0 ) { } if ( clipboardData . items && clipboardData . items . length > 0 ) { } content = clipboardData . getData ( 'text/plain' ) ; document . execCommand ( 'insertText' , false , content ) ; } ) ; } , [ ] ) ; const submit = async ( ) => { if ( submitting ) return ; setSubmitting ( true ) ; await onSubmit ( editorRef . current . innerHTML ) ; setSubmitting ( false ) ; } ; return ( < > < div styleName = "header" className = "border-bottom" > < QiniuUploadImage beforeUpload = { ( files ) => { } } upload = { ( url , file ) => { addImage ( url ) ; } } text = { < span styleName = "add-image" > < svg > < use xlinkHref = "/feather-sprite.svg#image" / > < /svg> 插入图片 < /span>}/ > < /div> { } < div ref = { editorRef } styleName = "editor" contentEditable = "true" placeholder = { placeholder } onInput = { onInput } style = { editorStyle } > < /div> < div className = "d-flex justify-content-between border-top" styleName = "footer" > < div > < /div> < div > < button type = "button" className = "btn btn-block btn-primary rounded-pill btn-sm pl-3 pr-3" onClick = { submit } > { submitting ? '提交中...' : '提交' } < /button> < /div> < /div> < />); } ; export default Editor ;