背景

最近在做一个部门外部简略的知识库零碎,便于新人入职理解与一些常见问题的解答,知识库的模式是以文档为主,为了疾速实现文档性能,决定采纳markdown模式录入,生成本地文件后以html形式展示,档次清晰便于查看

表结构设计

文档信息表

DROP TABLE IF EXISTS `knowledge_documentinfo`;CREATE TABLE `knowledge_documentinfo` (  `ID` int(11) NOT NULL AUTO_INCREMENT,  `UnitGuid` varchar(50) DEFAULT NULL,  `AddDate` datetime DEFAULT NULL,  `DocName` varchar(50) DEFAULT NULL,  `DocType` int(11) DEFAULT NULL,  `DocRemark` varchar(500) DEFAULT NULL,  `DocTag` varchar(100) DEFAULT NULL,  `DocClass` int(11) DEFAULT NULL,  `GroupGuid` varchar(50) DEFAULT NULL,  `SortNum` int(11) DEFAULT NULL,  KEY `ID` (`ID`)) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4;

文档内容表

DROP TABLE IF EXISTS `knowledge_documentcontentinfo`;CREATE TABLE `knowledge_documentcontentinfo` (  `ID` int(11) NOT NULL AUTO_INCREMENT,  `UnitGuid` varchar(50) DEFAULT NULL,  `DocGuid` varchar(50) DEFAULT NULL,  `DocClass` int(11) DEFAULT NULL,  `DocContent` longtext,  KEY `ID` (`ID`)) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4;

前端集成

前端为了markdown编辑操作便捷,集成了toastui-edit编辑器,具备所见即所得模式,和typora一样的成果。因为咱们前端是本人开发,基于vue+html本地化形式开发,就简略封装了控件应用,同时须要援用zh-cn.js汉化,指定initialEditType模式为wysiwyg

template

<div v-if="!readonly" id="markdownedit"></div><div v-else id="markdownedit_viewer">  </div>

index.js

var mdeditortemplatepath = GetRootPath() + 'component/commonmdeditor/template.html';Vue.component('common-markdowneditor', function(resolve, reject) {    $.get(mdeditortemplatepath).then(function(res) {        resolve({            template: res,            model: {                prop: 'value', //要存在于props                event: 'change' //当组件的值产生扭转时要emit的事件名            },            props: {                value: {},                height: {                    default: '300px'                },                readonly: {                    default: false                }            },            data() {                return {                    editorID: getNewGuid(),                    editorImageStoreGroupType: "edtior",                    editContent: this.value,                    editorOption: {},                    editorEntity: null,                    editorViewEntity: null                }            },            watch: {                //组件输出同步到页面绑定的变量                editContent: function(newVal, oldVal) {                    this.$emit('change', newVal)                },                //页面变量同步到组件显示                value: function(newVal, oldVal) {                    //从页面向组件更新时                    if (this.editContent != newVal) {                        this.editContent = newVal;                        if (this.editorEntity != null) {                            this.editorEntity.setMarkdown(newVal, false)                        }                        if (this.editorViewEntity != null) {                            this.editorViewEntity.setMarkdown(newVal, false)                        }                    }                },            },            created() {                var page = this;            },            mounted() {                var page = this;                this.$nextTick(function() {                    if (!page.readonly) {                        page.editorEntity = new toastui.Editor({                            el: document.querySelector('#markdownedit'),                            height: this.height,                            initialValue: '',                            initialEditType: 'wysiwyg',                            hideModeSwitch: true,                            language: "zh-CN",                            events: {                                change: function() {                                    page.editContent = page.editorEntity.getMarkdown();                                }                            }                        })                        page.editorEntity.setMarkdown(page.editContent, true)                    } else {                        page.editorViewEntity =  toastui.Editor.factory({                            el: document.querySelector('#markdownedit_viewer'),                            viewer: true,                            initialValue: page.editContent                          });                    }                });            },            methods: {            },        })    });});

理论应用

 <common-markdowneditor v-model="form.docContent" ></common-markdowneditor>

后端集成

在把markdonw的内容保留到数据库后,同时同步生成本地markdown文件,为后续html展现做筹备

    public void creatMarkdownFile(DocumentContentInfoDO entity) {        if (entity.getDocClass() == DocEnum.DocClass.Markdown.get_value()) {            try {                //生成markdown文件                String dicPath = "tempfiles/markdown/";                String filePath = dicPath + entity.getDocGuid() + ".md";                File dicInfo = new File(dicPath);                if (!dicInfo.exists()) {                    dicInfo.mkdirs();                }                File file = new File(filePath);                if (file.exists()) {                    file.delete();                }                file.createNewFile();                BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(filePath)),"utf-8"));                out.write(entity.getDocContent());                out.close();            } catch (Exception e) {                e.printStackTrace();            }        }    }

文档显示

前端显示集成了docsify@4.js,通过动静的指定homepage主页markdown文件地址达到一个index.html页面依据文档标识显示不同内容的成果

<script>    var showDocUrl = apiFrameUrl + "/foundation/documentinfo/getMarkdownUrl";    var docTag = getUrlParam("docTag")    $(function() {        var data = {            docTag: docTag,        };        JsonAjax_Sync(JSON.stringify(data), showDocUrl, function(result, status) {            var mdFileUrl = GetRootPath() + result.data.obj;            window.$docsify = {                homepage: mdFileUrl            }        })    })</script>