WangEditor5-解析Word

发布时间 2023-09-04 10:15:59作者: ajie20999

WangEditor5-解析Word

wangEditor官网https://www.wangeditor.com/v5/toolbar-config.html
解析并不是全部解析,如字体颜色等信息会丢失

yarn add @wangeditor/editor
yarn add @wangeditor/editor-for-react
# 用于解析Word
yarn add mammoth

1、创建工具栏类

import { IButtonMenu, IDomEditor } from '@wangeditor/editor';
import { word } from '../icon';
class WordMenu implements IButtonMenu {
    title: string;
    tag: string;
    iconSvg: string;
    constructor() {
        this.title = '解析word到编辑器' // 自定义菜单标题
        /**
         * 图标这里我的图标是在阿里妈妈适量图标库获取的https://www.iconfont.cn/
         * 搜索对应的图标赋值svg代码放到方法返回即可
         * icon/index.ts源码
         * export const word = () => `<svg>...</svg>`
         */
        this.iconSvg = word() // 图标
        this.tag = 'button'
    }

    /**
     * 获取编辑器内容源码
     * @param editor
     */
    getValue(editor: IDomEditor): string | boolean {
        return false;
    }

    /**
     * 菜单是否需要激活,当切换为源码时菜单激活
     * @param editor
     * @param active 激活状态
     */
    isActive(editor: IDomEditor, active?: boolean): boolean {
        return false;
    }

    /**
     * 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
     * @param editor
     */
    isDisabled(editor: IDomEditor): boolean {
        return false;
    }

    /**
     * 点击菜单时触发的函数
     * @param editor
     * @param value
     */
    exec(editor: IDomEditor, value: string | boolean) {
        if (this.isDisabled(editor)) return
        editor.emit('clickWord');
    }
}

export default WordMenu;

2、工具栏方法实现

import mammoth from "mammoth";
import WordMenu from "./word";

/**
 * 解析word为html
 * @param file
 */
export const analysisWord = (file: any): Promise<string> => {
    return new Promise((resolve) => {
        const reader = new FileReader();
        reader.onload = (evt: any) => {
            mammoth
                .convertToHtml({arrayBuffer: evt.target.result, buffer: undefined, path: ""})
                .then((res) => {
                    resolve(res.value);
                });
        }
        // 启动读取指定的 Blob 或 File 内容
        reader.readAsArrayBuffer(file);
    });
}

export const wordConf = { 
    // 工具栏中的唯一key
    key: 'word', 
    // 组件
    factory: () => new WordMenu() 
};

3、页面具体代码

在组件初始化时注册
上传需要触发文件选择,所以给一个input type='file’隐藏起来
点击导入word时触发选择

import { IDomEditor, Boot } from '@wangeditor/editor';
import { Editor, Toolbar } from '@wangeditor/editor-for-react';
import '@wangeditor/editor/dist/css/style.css';
import React, {useEffect, useState, useRef} from 'react';
import {analysisWord, wordConf} from "./props";

const WangEditor = ({ value = '', mode = 'default', onChange, toolbarConfig = {} }: any) => {
    /***********自定义变量-------开始*************/
    // editor 实例
    const [editor, setEditor] = useState<IDomEditor | null>(null);
    // 编辑器内容
    const [html, setHtml] = useState<string>(value || '');
    const file = useRef<HTMLInputElement>(null);
    /***********自定义变量-------结束*************/

    /***********生命周期函数-------开始*************/
    // 及时销毁 editor
    useEffect(() => {
        if (editor?.isFocused()) {
            editor?.blur();
        }
        return () => {
            // eslint-disable-next-line eqeqeq
            if (editor == null) return;
            editor.destroy();
            setEditor(null);
        };
    }, [editor]);

    const onCreated = (editor: IDomEditor) => {
        /*
         * 在组件创建时初始化注册菜单,注意菜单不可以重复注册否则会报异常
         * Unhandled Rejection (Error): Duplicated key 'source' in menu items
         */
        if (!editor.getAllMenuKeys().includes('word')) {
            Boot.registerMenu(wordConf);
        }
        setEditor(editor);
        // 监听点击word事件
        editor?.on('clickWord', () => {
            // 开启进度条
            editor.showProgressBar(20)
            // 选择文件
            file.current?.click();
        });
    }
    
    /**
     * 文件上传回调,解析word
     * @param event 文件对象
     */
    const handleChange = async (event: any) => {
        const res = await analysisWord(event.target.files[0]);
        // 这里直接插入即可
        editor?.dangerouslyInsertHtml(res);
        // 进度条借宿
        editor?.showProgressBar(100);
        // 将文件上传框value给情况
        event.target.value = '';
    }

    /***********生命周期函数-------结束*************/
    return (
        <div>
            <input type='file' accept='.doc,.docx' ref={file} onChange={handleChange} style={{ display: "none" }}/>
            <Toolbar
                editor={editor}
                defaultConfig={{
                    ...toolbarConfig,
                    // 添加自定义菜单
                    insertKeys: {
                        index: editor?.getAllMenuKeys().length || 0,
                        keys: ['word'],
                    }
                }}
                mode={mode}
            />
            <Editor value={html} onCreated={onCreated} />
        </div>
    );
};

export default WangEditor;

效果:https://blog.csdn.net/Ajie246862/article/details/132624660