首页 > 其他分享 >CodeMirror 基础配置指南

CodeMirror 基础配置指南

时间:2023-04-04 21:34:24浏览次数:42  
标签:指南 文件 在线 Ctrl 配置 编辑 path CodeMirror String


CodeMirror 基础配置指南

  • 需求背景
  • 在线编辑
  • 项目引入
  • 列表页面
  • 加载页面内容
  • 在线编辑页面
  • 在线编辑内容保存

需求背景

这里为什么会用到在线编辑功能呢?有这样的一个文件管理系统,实时上传js、css、html、shtml、txt等格式文件及文件夹,但是有时候发现上传的文件内容上有不对的地方,如果按传统的下载文件到本地,打开文件编辑保存,再次上传文件到对应路径这样一套操作下来的话会比较麻烦,耽误时间,而如果可以在线编辑有内容问题的文件的话,就可以省去很多步骤,直接在线修改并保存文件就可以了,是不是很方便,于是就产生了在线编辑的需求。

在线编辑

对于文件在线编辑,如果自行通过普通的html元素来加载并编辑的话,操作难度和代码识别度都很差劲,与其说是编辑代码,不如说是编译一堆字母,完全没有任何代码格式可言,这时就考虑到引用在线编辑插件来实现这一功能,通过网上搜索找到了应用的比较广泛比较稳定的CodeMirror在线编辑插件,CodeMirror插件官网地址:https://codemirror.net/

CodeMirror 基础配置指南_CodeMirror


这里我准备了我已经下载好的codemirror的插件包: 如果你没有积分又不愿意去官网下载的话可以私聊我,我这里给你提供codemirror插件包。

项目引入

这里首先说在线编辑页面,然后再说后台在线编辑处理的逻辑代码,所有代码仅供提供思路,勿要全盘拿过去复用,毕竟不同的代码架构跳转方式会有不同。

列表页面

CodeMirror 基础配置指南_css_02


在线编辑按钮对应的跳转代码

//在线编辑
    function codeonline(fileName){
        var title = $("#title").val();
        var platform = $("#platform").val();
        var url = prefix + "/codeOnline?path="+title+"&name="+fileName+"&platform="+platform;
        $.modal.openTab('在线编辑',url);
    }

加载页面内容

codeOnline方法下载腾讯云文件并读取文件内容返回到在线编辑页面

/**
     * 获取待编辑文件内容
     */
    @RequestMapping("/codeOnline")
    @RequiresPermissions("project:publishCosFiles:codeOnline")
    public String codeOnline(HttpServletRequest request,ModelMap mmap){
        //获取存储路径
        String path = request.getParameter("path");
        mmap.put("path",path);
        //获取文件名称
        String name = request.getParameter("name");
        mmap.put("name",name);
        //获取平台
        String platform = request.getParameter("platform");
        mmap.put("platform",platform);
        String text1path = null;
        try {
            //临时文件存放目录
            String profile = ConfigConstant.cosTempPath;
            //版本库没有  原始文件地址
            String versionkey = path + name;
            if (Constants.Platform.COS.getValue().equals(Integer.valueOf(platform))) {
                CosClientUtil cosClientUtil = new CosClientUtil();
                try {
                    //下载到服务器临时目录的文件路径及名称
                    text1path = profile + name;
                    //开始下载
                    cosClientUtil.download(versionkey, text1path);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                text1path = path+ "/"+name;
            }
            //逐行读取文件内容
            BufferedReader reader;
            StringBuffer sb = new StringBuffer();
            mmap.put("filearea","");
            try {
                reader = new BufferedReader(new InputStreamReader(
                        new FileInputStream(text1path), "utf-8"));
                while (reader.ready()) {
                    sb.append(reader.readLine()+"\r\n");
                }
                reader.close();
                mmap.put("filearea",sb.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (Constants.Platform.COS.getValue().equals(Integer.valueOf(platform))) {
                //删除下载的临时文件
                if (StringUtils.isNotEmpty(text1path)) {
                    boolean delete = new File(text1path).delete();
                }
            }
        }
        return prefix + "/codeOnline";
    }

在线编辑页面

在线编辑页面样式及js代码如下

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <th:block th:include="include :: header('在线编辑')"/>
    <th:block th:include="include :: select2-css" />
    <th:block th:include="include :: bootstrap-select-css" />
    <link rel="stylesheet" th:href="@{/codemirror-5.65.11/theme/darcula.css}">
    <link th:href="@{/codemirror-5.65.11/lib/codemirror.css}" rel="stylesheet"/>
    <!--引入js,绑定Vim-->
    <link rel="stylesheet" th:href="@{/codemirror-5.65.11/addon/dialog/dialog.css}">
    <!--支持代码折叠-->
    <link rel="stylesheet" th:href="@{/codemirror-5.65.11/addon/fold/foldgutter.css}"/>
    <!--全屏模式-->
    <link rel="stylesheet" th:href="@{/codemirror-5.65.11/addon/display/fullscreen.css}">
    <!--自动补全-->
    <link rel="stylesheet" th:href="@{/codemirror-5.65.11/addon/hint/show-hint.css}">
    <style>
        /*设置编辑框大小*/
        /*.CodeMirror{border:1px solid black;font-size:15px;width:100px;height:100px;}*/
    </style>
</head>
<body class="white-bg">
<!--<div class="ibox-content">
    <div class="form-group">
        <label class="font-noraml">选择主题:</label>
        <select id="theme" class="form-control" onclick="changeval();">
            <option value="">--请选择--</option>
            <option value="3024-day">3024-day</option>
            <option value="3024-night">3024-night</option>
            <option value="abbott">abbott</option>
            <option value="abcdef">abcdef</option>
            <option value="ambiance">ambiance</option>
            <option value="ambiance-mobile">ambiance-mobile</option>
            <option value="ayu-dark">ayu-dark</option>
            <option value="ayu-mirage">ayu-mirage</option>
            <option value="base16-dark">base16-dark</option>
            <option value="base16-light">base16-light</option>
            <option value="bespin">bespin</option>
            <option value="blackboard">blackboard</option>
            <option value="cobalt">cobalt</option>
            <option value="colorforth">colorforth</option>
            <option value="darcula">darcula</option>
            <option value="dracula">dracula</option>
            <option value="duotone-dark">duotone-dark</option>
            <option value="duotone-light">duotone-light</option>
            <option value="eclipse">eclipse</option>
            <option value="elegant">elegant</option>
            <option value="erlang-dark">erlang-dark</option>
            <option value="gruvbox-dark">gruvbox-dark</option>
            <option value="hopscotch">hopscotch</option>
            <option value="icecoder">icecoder</option>
            <option value="idea">idea</option>
            <option value="isotope">isotope</option>
            <option value="juejin">juejin</option>
            <option value="lesser-dark">lesser-dark</option>
            <option value="liquibyte">liquibyte</option>
            <option value="lucario">lucario</option>
            <option value="material">material</option>
            <option value="material-darker">material-darker</option>
            <option value="material-ocean">material-ocean</option>
            <option value="material-palenight">material-palenight</option>
            <option value="mbo">mbo</option>
            <option value="mdn-like">mdn-like</option>
            <option value="midnight">midnight</option>
            <option value="monokai">monokai</option>
            <option value="moxer">moxer</option>
            <option value="neat">neat</option>
            <option value="neo">neo</option>
            <option value="night">night</option>
            <option value="nord">nord</option>
            <option value="oceanic-next">oceanic-next</option>
            <option value="panda-syntax">panda-syntax</option>
            <option value="paraiso-dark">paraiso-dark</option>
            <option value="paraiso-light">paraiso-light</option>
            <option value="pastel-on-dark">pastel-on-dark</option>
            <option value="railscasts">railscasts</option>
            <option value="rubyblue">rubyblue</option>
            <option value="seti">seti</option>
            <option value="shadowfox">shadowfox</option>
            <option value="solarized">solarized</option>
            <option value="ssms">ssms</option>
            <option value="the-matrix">the-matrix</option>
            <option value="tomorrow-night-bright">tomorrow-night-bright</option>
            <option value="tomorrow-night-eighties">tomorrow-night-eighties</option>
            <option value="ttcn">ttcn</option>
            <option value="twilight">twilight</option>
            <option value="vibrant-ink">vibrant-ink</option>
            <option value="xq-dark">xq-dark</option>
            <option value="xq-light">xq-light</option>
            <option value="yeti">yeti</option>
            <option value="yonce">yonce</option>
            <option value="zenburn">zenburn</option>
        </select>
    </div>
</div>-->
<div class="container-div ui-layout-center">
    <div class="row">

        <div class="col-sm-12 my-search-collapse">
            <div class="select-list">
                <div style="color:red;" th:if="${platform} == 1">当前文件:[[${path}]][[${name}]]</div>
                <div style="color:red;" th:if="${platform} != 1">当前文件:[[${path}]]/[[${name}]]</div>
            </div>
        </div>

        <div class="col-sm-12 search-collapse">
            <div class="ibox-content">
                <div class="form-group">
                    <label style="float: left;padding-top: 10px;"><font color="red" style="padding-right: 5px;">*</font></fon>备注:
                    </label>
                    <div class="col-sm-8">
                        <input id="remark" name="remark" placeholder="请在保存之前填写" class="form-control"/>
                    </div>
                    <div class="col-sm-3" style="padding-top: 7px;float: right;">
                        <a href="#" title="Ctrl+A: selectAll(全选)
Ctrl+D: deleteLine(删除整行)
Alt+G: jumpToLine(跳转指定行)
Ctrl+Z: undo(撤销)
Ctrl+Home: goDocStart(光标定位到文档开始)
Ctrl+End: goDocEnd(光标定位到文档结束)
Ctrl+Up: goLineUp(光标上移一行)
Ctrl+Down: goLineDown(光标下移一行)
Ctrl+Left: goGroupLeft(光标左移)
Ctrl+Right: goGroupRight(光标右移)
Alt+Left: goLineStart(光标左移)
Alt+Right: goLineEnd(光标右移)
Ctrl+Backspace: delGroupBefore(删除光标前一个词)
Ctrl+Delete: delGroupAfter(删除光标后一个词)
Ctrl+F: find(查找)
Ctrl+G: findNext(查找下一个)
Ctrl+U: undoSelection(撤销)
Shift+Ctrl+U: redoSelection(重做)
Alt+U: redoSelection(重做)">快捷键操作<i class="fa fa-question"></i></a>
                    </div>
                </div>
            </div>
            <div style="padding-top:10px;">
                <div class="col-sm-offset-5 col-sm-10">
                    <button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保
                        存</button> 
                    <button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭
                    </button>
                </div>
            </div>
        </div>

        <div id="tableDiv" class="col-sm-12 select-table table-striped" style="height: calc(100% - 140px);overflow: auto;padding-right:15px;">
            <div style="padding-top:10px;padding-right:15px;">
                <form style="margin-top: 20px;margin-left: 20px;" id="form-code-edit">
                    <input type="hidden" name="fileName" id="fileName" th:value="${name}"/>
                    <input type="hidden" name="versionId" id="versionId" th:value="${versionId}"/>
                    <input type="hidden" name="platform" id="platform" th:value="${platform}"/>
                    <input type="hidden" name="path" id="path" th:value="${path}"/>
                    <textarea id="filearea" name="filearea">[[${filearea}]]</textarea>
                </form>
            </div>
        </div>

    </div>
</div>

<div th:include="include::footer"></div>
<script th:src="@{/codemirror-5.65.11/lib/codemirror.js}"></script>
<!--引入js,sublime-->
<script th:src="@{/codemirror-5.65.11/keymap/sublime.js}"></script>
<!--光标定位-->
<script th:src="@{/codemirror-5.65.11/addon/search/searchcursor.js}"></script>
<script th:src="@{/codemirror-5.65.11/addon/search/jump-to-line.js}"></script>
<!--支持代码折叠-->
<script th:src="@{/codemirror-5.65.11/addon/fold/foldcode.js}"></script>
<script th:src="@{/codemirror-5.65.11/addon/fold/foldgutter.js}"></script>
<script th:src="@{/codemirror-5.65.11/addon/fold/brace-fold.js}"></script>
<script th:src="@{/codemirror-5.65.11/addon/fold/comment-fold.js}"></script>
<!--全屏模式-->
<script th:src="@{/codemirror-5.65.11/addon/display/fullscreen.js}"></script>
<!--括号匹配-->
<script th:src="@{/codemirror-5.65.11/addon/edit/matchbrackets.js}"></script>
<!--自动补全-->
<script th:src="@{/codemirror-5.65.11/addon/hint/show-hint.js}"></script>
<script th:src="@{/codemirror-5.65.11/addon/hint/javascript-hint.js}"></script>
<script th:src="@{/codemirror-5.65.11/addon/hint/html-hint.js}"></script>
<script th:src="@{/codemirror-5.65.11/addon/hint/css-hint.js}"></script>
<!--js高亮-->
<script th:src="@{/codemirror-5.65.11/mode/javascript/javascript.js}"></script>
<!--选中词高亮-->
<script th:src="@{/codemirror-5.65.11/addon/search/match-highlighter.js}"></script>
<script type="text/javascript">
    var prefix = ctx + "project/publishCosFiles";
    //根据DOM元素的id构造出一个编辑器
    var editor=CodeMirror.fromTextArea(document.getElementById("filearea"),{
        mode:"text/javascript",
        //行号
        lineNumbers:true,
        //设置主题
        theme:"darcula",
        //绑定sublime
        keyMap:"sublime",
        //代码折叠
        lineWrapping:true,
        foldGutter: true,
        gutters:["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
        //全屏模式
        fullScreen:true,
        //括号匹配
        matchBrackets:true,
        //智能提示 //ctrl-space唤起智能提示
        extraKeys:{"Tab":"autocomplete","Ctrl-D":"deleteLine", "Ctrl-Up": "goLineUp", "Ctrl-Down":
                "goLineDown"},
        highlightSelectionMatches:true
    });

    function submitHandler() {
        //该方法得到的结果是经过转义的数据
        var toTextArea = editor.getValue();
        if (toTextArea != "") {
            $("#filearea").text(toTextArea);
        }else {
            $.modal.alertWarning("文件内容已被人工删除,请注意!");
            return false;
        }
        var remark = $("#remark").val();
        if (remark == "" || remark == undefined) {
            $.modal.alertWarning("请添加备注!");
            return false;
        }
        //console.log($("#filearea").val());
        var data = $('#form-code-edit').serializeArray();
        data.push({"name": "remark", "value": remark});
        $.operate.saveTab(prefix + "/saveCode", data);
    }

    //设置主题
    function changeval() {
        var val = $("#theme").val();
        editor.setOption("theme",val);
    }

    /*function myAlert() {
        $.modal.msg("Ctrl+A: selectAll(全选)\n" +
            "Ctrl+D: deleteLine(删除整行)\n" +
            "Ctrl+Z: undo(撤销)\n" +
            "Ctrl+Home: goDocStart(光标定位到文档开始)\n" +
            "Ctrl+End: goDocEnd(光标定位到文档结束)\n" +
            "Ctrl+Up: goLineUp(光标上移一行)\n" +
            "Ctrl+Down: goLineDown(光标下移一行)\n" +
            "Ctrl+Left: goGroupLeft(光标左移)\n" +
            "Ctrl+Right: goGroupRight(光标右移)\n" +
            "Alt+Left: goLineStart(光标左移)\n" +
            "Alt+Right: goLineEnd(光标右移)\n" +
            "Ctrl+Backspace: delGroupBefore(删除光标前一个词)\n" +
            "Ctrl+Delete: delGroupAfter(删除光标后一个词)\n" +
            "Ctrl+F: find(查找)\n" +
            "Ctrl+G: findNext(查找下一个)\n" +
            "Ctrl+U: undoSelection(撤销)\n" +
            "Shift+Ctrl+U: redoSelection(重做)\n" +
            "Alt+U: redoSelection(重做)");
    }*/

    //获取Codemirror的值
    //该方法得到的结果是经过转义的数据
    //editor.getValue();
    //该方法得到的结果是未经过转义的数据
    //editor.toTextArea();
    //editor.getTextArea().value;
    //如果是通过 JS 进行表单提交,可以在提交的 JS 代码中这样使用:

    //将 Codemirror 的内容赋值给 Textarea
    //$("#content").text(editor.getValue());
</script>
</body>
</html>

页面展示效果图如图可以看到

CodeMirror 基础配置指南_在线编辑_03


当前页面支持的快捷键主要有以下功能

CodeMirror 基础配置指南_编辑页面_04

在线编辑内容保存

最后在说一下在线编辑内容的保存,保存操作这里主要分为两步,首先获取页面提交的字符串内容,然后写入本地临时文件,再将临时文件上传到腾讯云即可,在线编辑上传内容方法如下,但是这里的方法主要是在线编辑相关业务代码,涉及到业务相关的代码已经删除,方便大家理解单纯的在线编辑内容上传

/**
     * 保存在线编辑内容
     *
     * @param request
     * @return
     */
    @RequiresPermissions("project:publishCosFiles:codeOnline")
    @PostMapping("/saveCode")
    @ResponseBody
    public AjaxResult saveCode(HttpServletRequest request) {
        String filearea = request.getParameter("filearea");
        String fileName = request.getParameter("fileName");
        String path = request.getParameter("path");

        try {
            //保存文件编辑内容并上传
            streamService.editUpload(filearea,fileName,path);
            return AjaxResult.success("上传成功!");
        }catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("上传失败!");
        }
    }

在线编辑实际保存操作方法

/**
	 * 编辑后执行腾讯云COS上传
	 * @param filearea  文件内容字符串
	 * @param fileName   文件名称
	 */
	@Override
	public void editUpload(String filearea, String fileName, String path){
		String key = null;
		try {
			//临时文件存放目录  写入改写后的文件
			String profile = ConfigConstant.cosTempPath;
			//临时文件全路径
			key = profile + fileName;
			FileWriter writer = new FileWriter(key);
			writer.write(filearea);
			writer.flush();
			writer.close();

			if("1".equals(platform)){
				//腾讯云文件名需要追加具体路径
				String uploadFileName = path + fileName;
				//腾讯云平台
				CosClientUtil cosClientUtil = new CosClientUtil();

				//临时文件写入成功之后进入后续上传文件到腾讯云操作
				try {
					//上传本地临时文件到腾讯云
					cosClientUtil.uploadFile(uploadFileName, key);
				} catch (Exception se) {
					se.printStackTrace();
				}
			}else {
				//移动token为现有文件
				File file = new File(key);
				File currentFile = new File( path + "/" + fileName);
				//删除现有文件
				IoUtil.getFile(fileName,path).delete();
				Files.copy(file.toPath(), currentFile.toPath());
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new BusinessException("编辑保存过程异常",e);
		}finally {
			//由于此处文件内容写在临时文件中,所以使用完之后需要删除下载的临时文件
			if (com.ruoyi.common.utils.StringUtils.isNotEmpty(key)) {
				boolean delete = new File(key).delete();
			}
		}
	}

到此整个在线编辑的前后端数据交互及在线编辑后文件上传已经完成了,欢迎有问题的小伙伴咨询哈。


标签:指南,文件,在线,Ctrl,配置,编辑,path,CodeMirror,String
From: https://blog.51cto.com/u_10917175/6169675

相关文章

  • flask框架01 flask与pythonweb框架介绍 flask快速使用 登录显示用户信息案列 配置
    今日内容详细目录今日内容详细1Flask和pythonweb框架介绍1.1flask介绍2flask快速使用3登录,显示用户信息小案例3.1login.html3.2home.html3.3detail.html3.4py文件4配置文件方式5路由系统5.1转换器1Flask和pythonweb框架介绍pythonweb框架的本质都一样1.同步框架......
  • SpringBoot 配置类解析
    作者:LiWanghongSpringBoot作为Java领域非常流行的开源框架,集成了大量常用的第三方库配置,SpringBoot应用中这些第三方库几乎可以是零配置的开箱即用,大部分的SpringBoot应用都只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。SpringBoot上手快,但是如果你的项目中业务场......
  • 【flask】蓝图的使用方式 g对象的使用 flask配置数据库连接池
    目录上节回顾今日内容1蓝图的使用2g对象g对象vsrequest对象3数据库连接池上节回顾全局request对象。线程会处理请求,确保线程中的数据不错乱。django_session表:#1cbv使用 -写一个类继承MethodView,写get,post。。。-类属性decorators=[auth,]可以加装饰器......
  • 重装系统之后的Django项目配置(WSL)
    重装系统之后的Django项目配置(WSL)升级固态硬盘之后,只能重装系统,这样一来就得重新来配置项目的开发环境。Linux环境下Django项目需要用到python解释器,在开发过程中,不同的项目可能会用到不同版本的库,为了防止环境下包的版本冲突,选择在windows的linux子环境中来安装多版本的pytho......
  • Mac | 解决 MacOS 配置 Maven 出现的 Java_Home Error
    1.错误信息2.解决方案2.1对于Windows系统下解决方案https://blog.csdn.net/frankarmstrong/article/details/69945774,在MacOS下并不奏效2.2对于MacOS系统下的解决方案code~/.bash_profile#使用VSCode打开环境变量文件#配置Java_Home内容exportJAVA_HOME=$......
  • nginx 配置小程序校验文件
    1、参考nginx配置小程序校验文件location/riAwbtUM3G.txt{default_typetext/html;return200"43191f769a41f4035dbc1e6d9d0cfa32";}......
  • VsCode安装和配置c/c++环境
    vscode是代码编译器,同时它提供了许多插件,可以帮助你方便的编写代码。通过配置vscode的开发环境,可以实现多种语言编译。总而言之,装了一个vscode就相当于装了多个IDE(集成开发环境)。后面,我们编写C语言代码就要依靠vscode了。一、下载vscode网址:VisualStudioCode-CodeEditing.......
  • 项目管理工具——Jira使用和配置
    摘要链接:https://pan.baidu.com/s/1_PgOuOWsS1lnHIIyI0y4pA 提取码:v0dy本博文将介绍在软件开发中的常用的软件管理工具。Jira是Atlassian公司出品的一款事务管理软件(缺陷管理类的软件)。无论是“需求”,还是“BUG”,或是“任务”,都是“事务”的一种,所以Jira可以胜任非常多的角色:需求......
  • 软件测试报告需要包括哪些内容?测试人员收藏这份必备指南!!!
    软件测试报告是软件开发生命周期的重要组成部分,是测试人员编写的文档,用于记录测试的过程和结果,对发现的问题和缺陷进行分析,为纠正软件的存在的质量问题提供依据,同时为软件验收和交付打下基础。软件测试报告通常包括以下内容:1、项目背景:介绍测试报告的编写目的、测试系统名......
  • 7-springcloud-eureka-3-搭建与配置eureka服务注册中心
    SpringCloud要使用Eureka注册中心非常简单和方便,SpringCloud中的Eureka服务注册中心实际上也是一个SpringBoot工程,我们只需通过引入相关依赖和注解配置就能让SpringBoot构建的微服务应用轻松地与Eureka进行整合。具体步骤如下:1、创建一个SpringBoot项目,并且添......