window系统下 tinymce富文本编辑器在搜狗输入法下placeholder不消失现象

window 搜狗输入法下编辑器占位符和内容重叠问题

这种情况是,tinymce插件库存在一些兼容BUG,需要我们自行手写样式或者js替换掉placeholder,代码如下:
window系统下 tinymce富文本编辑器在搜狗输入法下placeholder不消失现象_第1张图片

    // 获取富文本框的内容
    const handleChange = (editorContent) => {
      // console.log('>>>>> TinymceEditor handleChange', editorContent);
      // console.log('>>>>> TinymceEditor handleChange', editorContent, editorRef.current);
      window.email____detail__content = editorContent;
      onChange(editorContent);
      if (window.tinymce?.Env.os.isWindows()) {
        if (editorContent) {
          editorRef.current?.getBody().removeAttribute('data-mce-placeholder');
        } else {
          editorRef.current
            ?.getBody()
            .setAttribute('data-mce-placeholder', placeholder || intl.formatMessage({ id: 'email.inputHolder' }));
        }
      }
    };

render区域代码:

<div className={cn(styles.TinymceEditorWrap, language)} style={style}>
        <Editor
          onScriptsLoad={() => {
            // 初始化字间距插件
            PluginManagerLetterSpacing();
          }}
          // tinymceScriptSrc={'./tinymce/tinymce.min.js'} // 本地开发可以采用这个
          tinymceScriptSrc={'https://vv-public-staticresource.vv.cn/tinymce/tinymce.min.js'}
          onInit={(evt, editor) => {
            editorRef.current = editor;
            editor.getBody().style.fontSize = '16px';
            // console.log('>>>>>>>>> onInit editor', editor);
          }}
          ref={ref}
          value={initData}
          style={contentStyle}
          init={{
            icons: 'vv',
            menubar: false, // 菜单栏
            statusbar: false, // 底部状态栏
            branding: false, // 是否显示版权信息
            resize: false,
            language,
            height,
            toolbar,
            // toolbar_mode: 'wrap', // 工具栏展开方式 'floating', 'sliding', 'scrolling', or 'wrap'。 Default 'floating'
            plugins,
            font_size_formats: '8px 10px 12px 14px 16px 18px 24px 36px 48px',
            font_size_input_default_unit: 'px',
            images_file_types: 'png,jpg,jpeg,gif',
            file_picker_types: 'image',
            automatic_uploads: true,
            images_upload_handler: myUploadFn,
            placeholder: placeholder || intl.formatMessage({ id: 'email.inputHolder' }),
            content_style:
              ".mce-content-body{font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;font-size: 16px;color: #49536C;line-height: 28px;font-weight: 400}" +
              '.mce-content-body[data-mce-placeholder]::before {color:#BCC1CD !important;}' +
              'img {max-width: 100%; height: auto;}' +
              ".divider{display:flex;justify-content:space-between;align-items:center;}.divider:before,.divider:after{content:'';width:50px;height:2px;background: #f0f0f0;}" +
              '.mce-item-table:not([border]),.mce-item-table:not([border]) caption,.mce-item-table:not([border]) td,.mce-item-table:not([border]) th,.mce-item-table[border="0"],.mce-item-table[border="0"] caption,.mce-item-table[border="0"] td,.mce-item-table[border="0"] th,table[style*="border-width:0px"],table[style*="border-width:0px"] caption,table[style*="border-width:0px"] td,table[style*="border-width:0px"] th{border:0 !important;}',
            // cache_suffix: '?v=4.1.6',
          }}
          onEditorChange={handleChange}
          onDragOver={onDragOver}
          onClick={handleCloseExpandedDom}
        />
      </div>

完整的富文本组件代码:

import styles from './index.module.less';
import { useIntl } from 'react-intl';
import cn from 'classnames';
import { forwardRef, memo, useEffect, useRef } from 'react';
import { message } from '@/components';
import { Editor } from '@tinymce/tinymce-react';

import { uploadFn } from './utils';
import PluginManagerLetterSpacing from './plugins/letterspacing';
import { useSafeState } from '@vv-desktop-web-core/hooks';
import { jsbridge } from '@vv-desktop-web-core/helpers';

/**
 * 需要返回什么功能按需添加
 * https://www.tiny.cloud/docs/tinymce/6/react-ref/
 * @param height
 * @param initData
 * @param onChange
 * @returns {JSX.Element}
 * @constructor
 */
const TinymceEditor = forwardRef(
  (
    {
      height = '100%',
      initData = '',
      onChange,
      onDragOver = () => {},
      style = {},
      contentStyle = {},
      placeholder = '',
    },
    ref,
  ) => {
    const intl = useIntl();
    // 部分被css重置的文案是写在css里的,依据class language区分
    const [language, setLanguage] = useSafeState('zh-CN');
    const editorRef = useRef();
    // eslint-disable-next-line no-param-reassign
    height = typeof height === 'number' ? `${height}px` : height;

    // console.log('>>>>>> TinymceEditor 组件', 'initData', initData);

    // 不允许添加尺寸大于50M的图片
    const myValidateFn = (file) => {
      if (file.size > 1024 * 1024 * 50) {
        message.error('Size is greater than 50M!');
        return false;
      }
      return true;
    };

    const myUploadFn = (blobInfo) => {
      return new Promise((resolve, reject) => {
        const file = blobInfo.blob();
        const { type } = file;
        if (!myValidateFn(file)) {
          // eslint-disable-next-line prefer-promise-reject-errors
          reject('Size is greater than 50M!');
          return;
        }
        // 图片大小 <500k 则走base64方式,>= 则走oos方式
        if (file.size < 1024 * 500) {
          const img = `data:${type};base64,${blobInfo.base64()}`;
          resolve(img);
        } else {
          uploadFn({
            file,
            onChange: (d) => console.log('>>>>>>> onChange', d),
            onSuccess: (d) => {
              resolve(d);
            },
            onError: () => {
              reject('上传失败');
            },
            onProgress: (d) => console.log('>>>>>>> onProgress', d),
          });
        }
      });
    };

    // https://www.tiny.cloud/docs/tinymce/6/plugins/
    const plugins = ['link', 'image', 'code', 'media', 'emoticons', 'lists', 'letterspacing'];

    // https://www.tiny.cloud/docs/tinymce/6/toolbar-configuration-options/#toolbar
    // https://www.tiny.cloud/docs/tinymce/6/available-toolbar-buttons/
    const toolbar =
      'undo redo | fontsize | lineheight | letterspacing | ' +
      'forecolor bold italic underline strikethrough | ' +
      'superscript subscript removeformat emoticons | ' +
      'indent outdent alignleft aligncenter alignright alignjustify | ' +
      'blocks | ' +
      'bullist numlist blockquote code | ' +
      'image link unlink hr | remove';

    // 获取富文本框的内容
    const handleChange = (editorContent) => {
      // console.log('>>>>> TinymceEditor handleChange', editorContent, editorRef.current);
      window.email____detail__content = editorContent;
      onChange(editorContent);
      if (window.tinymce?.Env.os.isWindows()) {
        if (editorContent) {
          editorRef.current?.getBody().removeAttribute('data-mce-placeholder');
        } else {
          editorRef.current
            ?.getBody()
            .setAttribute('data-mce-placeholder', placeholder || intl.formatMessage({ id: 'email.inputHolder' }));
        }
      }
    };

    // 非toolbar区域,需要关闭toolbar浮窗
    const handleCloseExpandedDom = () => {
      const expandedDom = document.querySelector('.tox-tbtn.tox-tbtn--enabled');
      if (expandedDom) {
        expandedDom.click();
      }
    };

    useEffect(() => {
      const language1 = jsbridge?.getLocale();
      if (language1 && language1?.includes('en')) {
        setLanguage('en');
      }
    }, []);

    return (
      <div className={cn(styles.TinymceEditorWrap, language)} style={style}>
        <Editor
          onScriptsLoad={() => {
            // 初始化字间距插件
            PluginManagerLetterSpacing();
          }}
          // tinymceScriptSrc={'./tinymce/tinymce.min.js'} // 本地开发可以采用这个
          tinymceScriptSrc={'https://xx.xx.xx/tinymce/tinymce.min.js'} // cdn资源存放访问地址
          onInit={(evt, editor) => {
            editorRef.current = editor;
            editor.getBody().style.fontSize = '16px';
            // console.log('>>>>>>>>> onInit editor', editor);
          }}
          ref={ref}
          value={initData}
          style={contentStyle}
          init={{
            icons: 'vv',
            menubar: false, // 菜单栏
            statusbar: false, // 底部状态栏
            branding: false, // 是否显示版权信息
            resize: false,
            language,
            height,
            toolbar,
            // toolbar_mode: 'wrap', // 工具栏展开方式 'floating', 'sliding', 'scrolling', or 'wrap'。 Default 'floating'
            plugins,
            font_size_formats: '8px 10px 12px 14px 16px 18px 24px 36px 48px',
            font_size_input_default_unit: 'px',
            images_file_types: 'png,jpg,jpeg,gif',
            file_picker_types: 'image',
            automatic_uploads: true,
            images_upload_handler: myUploadFn,
            placeholder: placeholder || intl.formatMessage({ id: 'email.inputHolder' }),
            content_style:
              ".mce-content-body{font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;font-size: 16px;color: #49536C;line-height: 28px;font-weight: 400}" +
              '.mce-content-body[data-mce-placeholder]::before {color:#BCC1CD !important;}' +
              'img {max-width: 100%; height: auto;}' +
              ".divider{display:flex;justify-content:space-between;align-items:center;}.divider:before,.divider:after{content:'';width:50px;height:2px;background: #f0f0f0;}" +
              '.mce-item-table:not([border]),.mce-item-table:not([border]) caption,.mce-item-table:not([border]) td,.mce-item-table:not([border]) th,.mce-item-table[border="0"],.mce-item-table[border="0"] caption,.mce-item-table[border="0"] td,.mce-item-table[border="0"] th,table[style*="border-width:0px"],table[style*="border-width:0px"] caption,table[style*="border-width:0px"] td,table[style*="border-width:0px"] th{border:0 !important;}',
            // cache_suffix: '?v=4.1.6',
          }}
          onEditorChange={handleChange}
          onDragOver={onDragOver}
          onClick={handleCloseExpandedDom}
        />
      </div>
    );
  },
);

export default memo(TinymceEditor);

你可能感兴趣的:(electron)