• SpringBoot集成markdown实现文档管理


    背景

    最近在做一个部门内部简单的知识库系统,便于新人入职了解与一些常见问题的解答,知识库的形式是以文档为主,为了快速实现文档功能,决定采用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>
    

  • 相关阅读:
    ajax数据查看工具(chrome插件)
    JavaScript性能优化小知识总结
    jsonp
    学习Javascript闭包(Closure)
    浅析闭包和内存泄露的问题
    设备像素比
    【前端福利】用grunt搭建自动化的web前端开发环境-完整教程
    java开发的web下载大数据时的异常处理
    Node.js中的exports与module.exports的区分
    Task与Thread间的区别
  • 原文地址:https://www.cnblogs.com/yanpeng19940119/p/15255662.html
Copyright © 2020-2023  润新知