mindoc-org / mindoc

Golang实现的基于beego框架的接口在线文档管理系统
https://mindoc.com.cn/docs/mindochelp
Apache License 2.0
7.35k stars 1.91k forks source link

思维导图实现(很笨的办法) #565

Open cnspray opened 4 years ago

cnspray commented 4 years ago

一、增加按钮

<a href="javascript:;" data-toggle="tooltip" data-title="流程图/组织架构图/思维导图"><i class="fa fa-sitemap item" name="mindmap" unselectable="on"></i></a>

增加一个div,用于按钮帮助

<div style="display:none;" id="mindmaphelp">
>[warning]mindmap 参数说明:
语法:描述写在` ```mindmap` 和` ``` `之间
各`选项`用“选项名”:“选项值”分开,各选项间用空格分割
`size:`指定显示流程图的大小,可选值为“mindmap-sm”、“mindmap-md”、“mindmap-lg”
`Theme:`流程图主题,可选项为:“classic”、“classic-compact”、“fish”、“fresh-blue”、“fresh-blue-compat”、“fresh-green”、“fresh-green-compat”、“fresh-pink”、“fresh-pink-compat”、“fresh-purple”、“fresh-purple-compat”、“fresh-red”、“fresh-red-compat”、“fresh-soil”、“fresh-soil-compat”、“snow”、“snow-compact”、“tianpan”、“tianpan-compact”、“wire”,默认值为“fresh-blue”。
`Template:`流程图模板,支持“default”、"fresh-blue"、“filetree”、"fish-bone"、“right”、“structure”、“tianpan”,默认值为"fresh-blue"。
`protocol:`指定的用于解析数据的数据协议(默认内置三种数据协议 “json”、“text” 和 “markdown”的支持),改造后,支持markdown中的“list”写法,如`- 根节点`,一共四种支持。
`tmpshow`这个参数主要用于显示输入原始数据,建议使用list写法的时候开启,默认隐藏,只支持"true"。

```mindmap size:mindmap-md  Theme:fresh-blue  Template:default  protocol:markdown  tmpshow:false

二、按钮方法

else if (name=="mindmap"){//流程图说明 var cm = window.editor.cm; var selection = cm.getSelection(); var cursor = cm.getCursor(); if (selection === "") { cm.replaceSelection("\n"+$("#mindmaphelp").text() + selection+"\n\n"); cm.setCursor(cursor.line+11, 0); cm. focus() ; }else { var selectionText = selection.split("\n"); for (var i = 0, len = selectionText.length; i < len; i++) { selectionText[i] = (selectionText[i] === "") ? "" : $("#mindmaphelp").text() + selectionText[i]; } cm.replaceSelection(selectionText.join("\n\n")); cm.setCursor(cursor.line+11, 0); cm. focus() ; } }

三、引入百度的kityminder.core.min.js和kity.min.js,引入自已写的mindmap.min.js

// 将 li 节点转换为 JSON 数据 function li2jsonData(liNode) { var liData; var aNode = liNode.children("a:first"); if (aNode.length !== 0) { liData = { "data": { "text": aNode.text(), "hyperlink": aNode.attr("href") } }; } else { liData = { "data": { "text": liNode[0].childNodes[0].nodeValue.trim() } }; }

liNode.find("> ul > li").each(function() {
    if (!liData.hasOwnProperty("children")) {
        liData.children = [];
    }
    liData.children.push(li2jsonData($(this)));
});

return liData;

}

function drawMindMap(div) { //各参数解析开始 var lang = $(div).find(".mindmapoption").text(); var sizeps = lang.match(/(?<=size:)(mindmap-sm|mindmap-md|mindmap-lg)(?= )/i); var Templateps = lang.match(/(?<=Template:)(fresh-blue|filetree|fish-bone|right|structure|tianpan)(?= )/i); var Themeps = lang.match(/(?<=Theme:)(classic|classic-compact|fish|fresh-blue|fresh-blue-compat|fresh-green|fresh-green-compat|fresh-pink|fresh-pink-compat|fresh-purple|fresh-purple-compat|fresh-red|fresh-red-compat|fresh-soil|fresh-soil-compat|snow|snow-compact|tianpan|tianpan-compact|wire)(?= )/i); var protocolps = lang.match(/(?<=protocol:)(json|text|markdown|list)(?= )/i); var tmpshowps = lang.match(/(?<=tmpshow:)(true)(?= )/i); var size = (sizeps !== null) ? sizeps[0] : "mindmap-md"; var Theme = (Themeps !== null) ? Themeps[0] : "default"; var protocol = (protocolps !== null) ? protocolps[0] : "markdown"; var Template = (Templateps !== null) ? Templateps[0] : "default"; var tmpshow = (tmpshowps !== null) ? "": "style=\"display:none;\""; //参数解析结束 var markdownText = $(div).find(".mindmaptmp").text().trim(); if (protocol == "list") { var ulElement = $(div).find(".mindmaptmp").find(">ul:first"); var mmData = { "root": {} }; var minder = new kityminder.Minder({ renderTo: div }); try { mmData.root = li2jsonData(ulElement.children("li:first")); mmData.template = Template; mmData.theme = Theme; minder.importData('json', JSON.stringify(mmData)); minder.disable(); / minder.setTemplate(Template); minder.setTheme(Theme); / minder.execCommand('hand'); } catch(e) { console.log(e); }

    $(ulElement).hide();
} else {
    var minder = new kityminder.Minder({
        renderTo: div
    });
    var markdownText = $(div).find(".mindmaptmp").text().trim();
    try {
        minder.importData('json', markdownText);
        minder.disable();
        //以下两句,在运行时没什么效果,包含useTemplate
        /*minder.setTemplate(Template);
    minder.setTheme(Theme); */
        minder.execCommand('hand');
    } catch(e) {
        console.log(e);
    }

}

}


四、修改editor.md的代码块
    markedRenderer.code = function (code, lang, escaped) { 

        if (lang === "seq" || lang === "sequence")
        {
            return "<div class=\"sequence-diagram\">" + code + "</div>";
        } 
        else if ( lang === "flow")
        {
            return "<div class=\"flowchart\">" + code + "</div>";
        } 
        else if ( lang === "math" || lang === "latex" || lang === "katex")
        {
            return "<p class=\"" + editormd.classNames.tex + "\">" + code + "</p>";
        } 
        else if (/^mindmap/i.test(lang))
        {
            lang=lang+" ";//加一个空格,便于解析各参数使用

            //各参数解析开始
            var sizeps = lang.match(/(?<=size:)(mindmap-sm|mindmap-md|mindmap-lg)(?= )/i);
            var Templateps = lang.match(/(?<=Template:)(fresh-blue|filetree|fish-bone|right|structure|tianpan)(?= )/i);
            var Themeps = lang.match(/(?<=Theme:)(classic|classic-compact|fish|fresh-blue|fresh-blue-compat|fresh-green|fresh-green-compat|fresh-pink|fresh-pink-compat|fresh-purple|fresh-purple-compat|fresh-red|fresh-red-compat|fresh-soil|fresh-soil-compat|snow|snow-compact|tianpan|tianpan-compact|wire)(?= )/i);
            var protocolps=lang.match(/(?<=protocol:)(json|text|markdown|list)(?= )/i);
            var tmpshowps=lang.match(/(?<=tmpshow:)(true)(?= )/i);
            var size=(sizeps!== null)?sizeps[0]:"mindmap-md";
            var Theme=(Themeps!== null)?Themeps[0]:"fresh-blue";
            var protocol=(protocolps!== null)?protocolps[0]:"markdown";
            var Template=(Templateps!== null)?Templateps[0]:"default";
            var tmpshow=(tmpshowps!== null)?"":"style=\"display:none;\"";
            //参数解析结束

            //生成两个div,其中一个存放参数,一个存放待生成的数据。
            if(protocol=="list"){
                code=marked(code);
            }else {
            //先将code解析为json数据,并添加主题和模板,如果不先解析,按照官方文档,使用minder.execCommand('Template', "right");或minder.useTemplate;minder.setTemplate;等均没有效果,需要单独添加一个按钮或标签,等加载完才可以改变,有点无语。
            var minder=new kityminder.Minder();
            try {
            var tmpcode = minder.decodeData(protocol,code);
            tmpcode=tmpcode.fulfillValue;
            tmpcode.template=Template;
            tmpcode.theme=Theme;
            code=JSON.stringify(tmpcode);
            }catch(e)
            {
            }}
            var mindmapoption="<div class=\"mindmapoption\" style=\"display:none;\" >" +  lang + "</div>";
            var midmaptmpdiv="<div class=\"mindmaptmp\"" +tmpshow+" >" +  code + "</div>";
            return "<div class=\"mindmap "+size+"\">"+mindmapoption+midmaptmpdiv+"</div>";              

        }
        else 
        {

            return marked.Renderer.prototype.code.apply(this, arguments);
        }
    };
五、在flowChartAndSequenceDiagramRender中去解析
        try {
        $('.mindmap').each(function() {
            drawMindMap(this);
        });             

        } catch (e) {
            console.log(e);

        }

六、前台阅读界面,在加载完成后,再去解析一次,否则图不能拖动。

七、css文件

.km-view { font-family: "STHeitiSC-Light", "STHeiti", "Hei", "Heiti SC", "Microsoft Yahei", Arial, sans-serif; -webkit-user-select: none; user-select: none; position: relative; }

.km-view .km-receiver { position: absolute; left: -99999px; top: -99999px; width: 20px; height: 20px; outline: none; margin: 0; }

.km-view image { cursor: zoom-in; }

.km-image-viewer { position: fixed; z-index: 99999; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, .75); }

.km-image-viewer .km-image-viewer-container { position: absolute; top: 0; bottom: 0; left: 0; right: 0; text-align: center; white-space: nowrap; overflow: auto; }

.km-image-viewer .km-image-viewer-container::before { content: ''; display: inline-block; height: 100%; width: 0; font-size: 0; vertical-align: middle; }

.km-image-viewer .km-image-viewer-container img { cursor: zoom-out; vertical-align: middle; }

.km-image-viewer .km-image-viewer-container img.limited { cursor: zoom-in; max-width: 100%; max-height: 100%; }

.km-image-viewer .km-image-viewer-toolbar { z-index: 1; background: rgba(0, 0, 0, .75); text-align: right; transition: all .25s; }

.km-image-viewer .km-image-viewer-toolbar.hidden { transform: translate(0, -100%); opacity: 0; }

.km-image-viewer .km-image-viewer-btn { cursor: pointer; outline: 0; border: 0; width: 44px; height: 44px; background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjY0IiBoZWlnaHQ9Ijg4IiB2aWV3Qm94PSIwIDAgMjY0IDg4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjx0aXRsZT5kZWZhdWx0LXNraW4gMjwvdGl0bGU+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48Zz48cGF0aCBkPSJNNjcuMDAyIDU5LjV2My43NjhjLTYuMzA3Ljg0LTkuMTg0IDUuNzUtMTAuMDAyIDkuNzMyIDIuMjItMi44MyA1LjU2NC01LjA5OCAxMC4wMDItNS4wOThWNzEuNUw3MyA2NS41ODUgNjcuMDAyIDU5LjV6IiBpZD0iU2hhcGUiIGZpbGw9IiNmZmYiLz48ZyBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTMgMjl2LTVoMnYzaDN2MmgtNXpNMTMgMTVoNXYyaC0zdjNoLTJ2LTV6TTMxIDE1djVoLTJ2LTNoLTN2LTJoNXpNMzEgMjloLTV2LTJoM3YtM2gydjV6IiBpZD0iU2hhcGUiLz48L2c+PGcgZmlsbD0iI2ZmZiI+PHBhdGggZD0iTTYyIDI0djVoLTJ2LTNoLTN2LTJoNXpNNjIgMjBoLTV2LTJoM3YtM2gydjV6TTcwIDIwdi01aDJ2M2gzdjJoLTV6TTcwIDI0aDV2MmgtM3YzaC0ydi01eiIvPjwvZz48cGF0aCBkPSJNMjAuNTg2IDY2bC01LjY1Ni01LjY1NiAxLjQxNC0xLjQxNEwyMiA2NC41ODZsNS42NTYtNS42NTYgMS40MTQgMS40MTRMMjMuNDE0IDY2bDUuNjU2IDUuNjU2LTEuNDE0IDEuNDE0TDIyIDY3LjQxNGwtNS42NTYgNS42NTYtMS40MTQtMS40MTRMMjAuNTg2IDY2eiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMTEuNzg1IDY1LjAzTDExMCA2My41bDMtMy41aC0xMHYtMmgxMGwtMy0zLjUgMS43ODUtMS40NjhMMTE3IDU5bC01LjIxNSA2LjAzeiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xNTIuMjE1IDY1LjAzTDE1NCA2My41bC0zLTMuNWgxMHYtMmgtMTBsMy0zLjUtMS43ODUtMS40NjhMMTQ3IDU5bDUuMjE1IDYuMDN6IiBmaWxsPSIjZmZmIi8+PGc+PHBhdGggaWQ9IlJlY3RhbmdsZS0xMSIgZmlsbD0iI2ZmZiIgZD0iTTE2MC45NTcgMjguNTQzbC0zLjI1LTMuMjUtMS40MTMgMS40MTQgMy4yNSAzLjI1eiIvPjxwYXRoIGQ9Ik0xNTIuNSAyN2MzLjAzOCAwIDUuNS0yLjQ2MiA1LjUtNS41cy0yLjQ2Mi01LjUtNS41LTUuNS01LjUgMi40NjItNS41IDUuNSAyLjQ2MiA1LjUgNS41IDUuNXoiIGlkPSJPdmFsLTEiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMTUwIDIxaDV2MWgtNXoiLz48L2c+PGc+PHBhdGggZD0iTTExNi45NTcgMjguNTQzbC0xLjQxNCAxLjQxNC0zLjI1LTMuMjUgMS40MTQtMS40MTQgMy4yNSAzLjI1eiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMDguNSAyN2MzLjAzOCAwIDUuNS0yLjQ2MiA1LjUtNS41cy0yLjQ2Mi01LjUtNS41LTUuNS01LjUgMi40NjItNS41IDUuNSAyLjQ2MiA1LjUgNS41IDUuNXoiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMTA2IDIxaDV2MWgtNXoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMTA5LjA0MyAxOS4wMDhsLS4wODUgNS0xLS4wMTcuMDg1LTV6Ii8+PC9nPjwvZz48L2c+PC9zdmc+"); }

.km-image-viewer .km-image-viewer-toolbar { position: absolute; top: 0; left: 0; right: 0; }

.km-image-viewer .km-image-viewer-close { background-position: 0 -44px; }

.mindmap { width: inherit; border: 1px solid #ccc; }

.mindmap-sm { height: 300px; }

.mindmap-md { height: 500px; }

.mindmap-lg { height: 800px; }

dandycheung commented 4 years ago

解决问题的方法,用 PR 通知作者会比较好。

cnspray commented 4 years ago

https://github.com/pandao/editor.md/issues/790 是否考虑加入导入word文档和支持从office文档粘贴转换为markdown的功能?

3xxx commented 2 years ago

https://github.com/mindoc-org/mindoc/issues/603 按照这个方式可以。另外,本身它就支持mermaid各种思维导图

graph TD
      B["fa:fa-twitter for peace"]
      B-->C[fa:fa-ban forbidden]
      B-->D(fa:fa-spinner);