123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- import { Editor } from '@tinymce/tinymce-react';
- import React, { useRef, useEffect, useState, useCallback } from 'react';
- import SmMaterialModal from '@/components/MaterialModal/smModalBox'
- import WeChatImgCard from "@/components/WeChatImgCard"
- import Alink from '@/components/Alink'
- // https://mmbiz.qpic.cn/mmbiz_png/Bic8GaUSeMXaRjA1qiaGAu35ssNpnPejMzyY4c0HHPrO1kjh93uWIE4F9aQUfIsEiakib5TWfHls8GLHEPXOIQiaiakg/640?wx_fmt=png
- //https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/B9B6AEB034044B5E9A7FC05227060789.jpg
- export default function TEditor(props: {
- dispatch: (arg: any) => void,
- setLoding: (arg: boolean) => void,
- isOk: (arg: any) => void,
- content: string,
- actionId: any
- }) {
- let { dispatch, setLoding, isOk, content, actionId } = props
- let [value, setValue] = useState<any>(null)
- let [imgVisible, setImgVisible] = useState(false)
- let [wImgVisible, setWImgVisible] = useState(false)
- let [wCardVisible, setWCardVisible] = useState(false)
- let [wAVisible, setWAVisible] = useState(false)
- const editorRef: any = useRef(null);
- // console.log('传进来的content====>',content)
- /**==================实时处理html===================*/
- const disposeHtml = useCallback((html) => {
- console.log(333333, '执行HTML处理方法')
- // =================处理腾讯的图片,解决非法引用看不到图的问题==========================
- // 筛选出是腾讯的图片,并查看是否带了随机数,以免加载失败
- // let imgArr = html?.match(/(<img .*(\B>))/ig)?.filter((img: string ) => !img.includes('aliyuncs.com') && img.search(/=?\w{0,4}\?v/)!== -1)
- // imgArr?.forEach((img: any) => {
- // // let src = img.match(/src=.*=png/)[0]
- // console.log('img====>', img)
- // let src = img.match(/(src=.*=\w{3,4})|(src=.*\/[0-9]{0,3}")/)[0]
- // console.log('src====>', src)
- // // 不存在no-referrer执行添加
- // if (!img.includes('referrerpolicy="no-referrer"')) {
- // console.log('修改IMG1')
- // html = html.replace(src, `${src + '?v' + Math.random() * 10}" referrerpolicy="no-referrer"`)
- // } else {
- // console.log('修改IMG2')
- // html = html.replace(src, src + '?v' + Math.random() * 10)
- // }
- // })
- // 处理小程序卡片假如没有外层加上外层好在本地展示
- let mp_miniprogram = html?.match(/(<mp-miniprogram .*>\s?<\/mp-miniprogram>)/)
- mp_miniprogram?.forEach((mp: any) => {
- if (!mp.includes('data-bd="true"')) {
- let imgSrc = mp?.match(/(http.*\.\w{3,4})/)[0]
- let newMp = mp.replace('<mp-miniprogram', `<mp-miniprogram data-bd="true"`)
- html = html.replace(mp, `
- <div class='mp-miniprogram'>
- ${newMp}
- <img src='${imgSrc}' />
- </div>
- `)
- }
- })
- console.log(content !== html)
- //存放处理后的html
- if (content !== html) {
- // console.log('setValue=====>',html)
- console.log(444444, '改变后的HTML和当前存放的HTML不同替换旧的HTML')
- setValue(html)
- }
- }, [content])
- /**====================处理保存的html=======================*/
- const disposeSaverHtml = useCallback((html) => {
- console.log(5555555, '焦点脱离,处理HTML并保存内容dispatch=====>')
- let divStr = html?.match(/<div\s?class="mp-miniprogram">.*<img\s?src=.*\.\w{3,4}">\s?<\/div>/)
- divStr?.forEach((div: any) => {
- let mpStr = div?.match(/(<mp-miniprogram .*>\s?<\/mp-miniprogram>)/)[0]
- mpStr = mpStr?.replace(`data-bd="true"`, '')
- html = html?.replace(div, mpStr)
- })
- console.log('html====>', html)
- dispatch({ type: 'pushData', params: { menuId: actionId, content: html || '<p></p>' } })
- }, [actionId])
- useEffect(() => {
- // actionId的监听因为content可能一样为默认值所以监听actionId的变化来强行执行
- console.log(1111111111, 'props.content改变')
- setValue(content)
- }, [content, actionId])
- // 腾讯图片出去referrer请求头
- useEffect(() => {
- let meta = document.createElement('meta')
- meta.name = 'referrer'
- meta.content = 'no-referrer'
- document.head.appendChild(meta)
- return () => {
- let m = document.head.querySelector('[name="referrer"]')
- if (m) {
- document.head.removeChild(m)
- }
- }
- }, [])
- // console.log('value======>',value)
- return <>
- <Editor
- apiKey='wkn1n49be4rmnjq9h33nzp15z9n9v5jn2n4dr3kav8bx7y4y'
- // 初始化
- onInit={(evt, editor) => {
- editorRef.current = editor
- setLoding(false)
- isOk(editor);
- // editor.ui.registry.addButton
- }}
- // initialValue={content}
- value={value}
- onBlur={() => {
- // 假如焦点丢失时最后数据与数据存放中的数据不同执行保存
- if (value !== content || content === '') {
- disposeSaverHtml(value)
- }
- }}
- // 编辑变化
- onEditorChange={(html, editor) => {
- console.log(22222222, '监听到html变化,执行处理HTML函数方法', html)
- // console.log('html===>',html)
- //每次html变化去处理函数处理html
- disposeHtml(html)
- }}
- init={{
- height: 730,
- menubar: true,
- language: 'zh-Hans',
- language_url: 'http://test.zanxiangnet.com/aaplugin/zh-Hans.js',
- extended_valid_elements: 'img[src|_src|referrerpolicy|style|class],mp-miniprogram[data-*]',//自定义标签支持属性
- custom_elements: 'mp-miniprogram',
- branding: false,//右下角支持关闭
- typeahead_urls: false,//输入地址时的自动完成
- plugins: [//头部文字插件
- 'advlist', 'autolink', 'lists', 'link', 'charmap', 'preview',
- 'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',
- 'insertdatetime', 'emoticons', 'table', 'code', 'wordcount', 'image', 'paste', 'help'
- ],
- // 图标插件按钮
- toolbar: 'undo redo blocks fontsize|bold italic forecolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent paste |img wImg wCard wA',//工具栏
- toolbar_mode: 'wrap',//工具换行
- paste_webkit_styles: 'all',
- content_style: `
- body { font-family:Helvetica,Arial,sans-serif; font-size:14px ;}
- .mp-miniprogram{
- width:200px;
- height:200px;
- }
- .mp-miniprogram img{
- width:100%;
- }
- `,
- setup(ed) {
- // 图
- ed.ui.registry.addButton('img', {
- text: '图片',
- onAction: () => {
- setImgVisible(true)
- }
- })
- // 小程序图片链插件
- ed.ui.registry.addButton('wImg', {
- text: '小程序图片',
- onAction: () => {
- setWImgVisible(true)
- }
- })
- // 小程序卡片链插件
- ed.ui.registry.addButton('wCard', {
- text: '小程序卡片',
- onAction: () => {
- setWCardVisible(true)
- }
- })
- // A链接功能插件
- ed.ui.registry.addButton('wA', {
- text: 'A链接',
- onAction: () => {
- setWAVisible(true)
- }
- })
- }
- // '' +
- // 'alignright alignjustify | bullist numlist outdent indent | ' +
- // 'removeformat |code| emoticons|media| image|help'
- }}
- />
- {/* 图片选择 */}
- <SmMaterialModal
- mediaType={1}
- onCancel={() => { setImgVisible(false) }}
- title='选择图片'
- visible={imgVisible}
- onOk={(props: any) => {
- let url = props.url
- editorRef.current.insertContent(`<img
- style='max-width:100%'
- src=\"${url}\"
- alt=\"\"
- data-w=\"auto\"
- data-ratio=\"0.66796875\"
- data-type=\"${url.replace(/http[s]?:\/\/\S*(wx_fmt=|\.)/ig, '') === 'gif' ? 'png' : url.replace(/http[s]?:\/\/\S*(wx_fmt=|\.)/ig, '')}\"
- />`)
- setImgVisible(false)
- }}
- // isShowWx={isShowWx}
- isAllData
- noFile={true}
- />
- {/* 小程序图片链 */}
- {
- wImgVisible && <WeChatImgCard
- onCancel={() => {
- setWImgVisible(false)
- }}
- title='小程序图片链'
- visible={wImgVisible}
- onOk={(props: { img: string, appid: string, appPath: string, href?: string }) => {
- editorRef.current.insertContent(`<a data-miniprogram-appid=\"${props.appid}\" data-miniprogram-path=\"${props.appPath}\" href=\"${props.href}\"><img src=\"${props.img}\" alt=\"\" data-width=\"null\" data-ratio=\"NaN\"/></a>`)
- setWImgVisible(false)
- }}
- weCathType='img'
- isOnUserId={false}
- />
- }
- {/* 小程序卡片链 */}
- {
- wCardVisible && <WeChatImgCard
- onCancel={() => {
- setWCardVisible(false)
- }}
- title='小程序卡片链'
- visible={wCardVisible}
- onOk={(props: { img: string, appid: string, appPath: string, cardTitle?: string }) => {
- editorRef.current.insertContent(`
- <div class='mp-miniprogram'>
- <mp-miniprogram data-bd="true" data-miniprogram-appid=\"${props?.appid}\" data-miniprogram-path=\"${props?.appPath}\" data-miniprogram-title=\"${props?.cardTitle}\" data-miniprogram-type=\"card\" data-miniprogram-servicetype=\"0\" data-miniprogram-imageurl=\"${props?.img}\"></mp-miniprogram>
- <img src='${props.img}' />
- </div>
- `)
- setWCardVisible(false)
- }}
- weCathType='card'
- isOnUserId={false}
- />
- }
- {/*A链 */}
- {
- wAVisible && <Alink
- onCancel={() => { setWAVisible(false) }}
- title='A链接'
- visible={wAVisible}
- onOk={(props: string) => {
- editorRef.current.insertContent(props)
- setWAVisible(false)
- }}
- weCathType='card'
- isOnUserId={false}
- />
- }
- </>
- }
- // /**图片上传插件*/
|