Describe the bug
下面是vue-codemirror的使用
<style>
.el-form-item--mini .el-form-item__content,
.el-form-item--mini .el-form-item__label,
.el-form-item__content {
line-height: 20px;
}
.velocity-tip {
color: #606266;
font-size: 13px;
font-weight: normal;
}
.velocity-var {
}
.velocity-var li {
font-size: 14px;
color: #606266;
line-height: 26px;
}
.velocity-var a {
color: #409eff;
font-weight: 500;
}
.velocity-var a:hover {
color: rgba(64, 158, 255, 0.75);
}
.hasFix {
position: fixed;
top: 0;
}
.el-dropdown-link {
cursor: pointer;
color: #409eff;
}
.el-icon-arrow-down {
font-size: 12px;
}
span.split {
color: #ccc;
margin: 0 3px;
}
</style>
<script>
import { codemirror } from "vue-codemirror";
import "codemirror/theme/neat.css";
import "codemirror/theme/darcula.css";
import "codemirror/theme/material.css";
/** 搜索 替换框置顶*/
import "codemirror/addon/scroll/annotatescrollbar.js";
import "codemirror/addon/search/matchesonscrollbar.js";
import "codemirror/addon/search/match-highlighter.js";
import "codemirror/addon/search/jump-to-line.js";
import "codemirror/addon/dialog/dialog.js";
import "codemirror/addon/dialog/dialog.css";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/search.js";
require("codemirror/mode/velocity/velocity");
import "codemirror/theme/ambiance.css";
import "codemirror/lib/codemirror.css";
import "codemirror/addon/hint/show-hint.css";
require("codemirror/addon/edit/matchbrackets");
require("codemirror/addon/selection/active-line");
require("codemirror/mode/sql/sql");
require("codemirror/addon/hint/show-hint");
require("codemirror/addon/hint/sql-hint");
require("codemirror/mode/clike/clike.js");
require("codemirror/addon/edit/closebrackets.js");
import "codemirror/mode/javascript/javascript.js";
import "codemirror/addon/lint/lint.css";
import "codemirror/addon/lint/lint.js";
import "codemirror/addon/selection/active-line.js";
const TEMPLATE_CODE_THEME = "gen.template.code.theme";
export default {
components: { codemirror },
props: {
formData: {
type: Object,
default: () => ({ content: "", labeName: "" }),
},
isNoEdit: {
type: Boolean,
default: false,
},
maxHeight: {
type: String,
default: "calc(-203px + 100vh)",
},
},
inject: ["developLowCodeIndex"],
data() {
return {
error_Msg: "",
codeThemeList: ["neat", "darcula", "material"],
shortcutKeyList: [
"保存(Ctrl+S)",
"删除当行(Ctrl+D)",
"复制当行(Ctrl+C)",
"剪切当行(Ctrl+X)",
"替换(Ctrl+Shift+F)",
],
//code mirror配置
cmOptions: {
value: "",
mode: "text/x-java",
theme: "neat",
readOnly: false,
tabSize: 4, // tab的空格个数
indentUnit: 2, // 一个块(编辑语言中的含义)应缩进多少个空格
autocorrect: true, // 自动更正
spellcheck: true, // 拼写检查
lint: true, // 检查格式
lineNumbers: true, //是否显示行数
lineWrapping: true, //是否自动换行
styleActiveLine: true, //line选择是是否高亮
// keyMap: 'intellij', // sublime编辑器效果
matchBrackets: true, //括号匹配
autoCloseBrackets: true, // 在键入时将自动关闭括号和引号
matchTags: { bothTags: true }, // 将突出显示光标周围的标签
foldGutter: true, // 可将对象折叠,与下面的gutters一起使用
gutters: [
"CodeMirror-lint-markers",
"CodeMirror-linenumbers",
"CodeMirror-foldgutter",
],
highlightSelectionMatches: {
minChars: 2,
style: "matchhighlight",
showToken: true,
},
hintOptions: {
// 自定义提示选项
completeSingle: false, // 当匹配只有一项的时候是否自动补全
tables: {}, // 代码提示
},
},
marks: [],
errorsLists: [],
};
},
mounted() {
//初始化代码主题
this.cmOptions.theme = this.getAttr(TEMPLATE_CODE_THEME) || "neat";
this.$nextTick(() => {
this.$refs.editor.codemirror.on("inputRead", (cm, event) => {
if (this.isNoEdit) {
if (/^[a-zA-Z\.=]$/gi.test(event.text[0])) {
cm.showHint();
}
} else {
const index = this.formData.labeName.lastIndexOf(".");
const code = this.formData.labeName.slice(index);
if (code === ".java") {
if (/^[a-zA-Z\.=]$/gi.test(event.text[0])) {
cm.showHint();
}
}
}
});
this.$refs.editor.codemirror.on("blur", () => {
if (this.formData.content) {
this.$emit("fatherMethod", false);
} else {
this.$emit("fatherMethod", true);
}
});
this.$refs.editor.codemirror.on("mousedown", (cm, event) => {
const editorTop = cm.getScrollerElement().getBoundingClientRect().top;
const clickY = event.clientY - editorTop;
// 计算点击位置对应的行号
const line = cm.lineAtHeight(clickY, "local");
console.log(`点击处的行数是: ${line + 1}`);
const obj = this.errorsLists.find(
(item) => item.lineNumber == line + 1
);
if (obj) {
if (
["/developLowCode", "/sourceCodePreview"].includes(this.$route.path)
) {
this.developLowCodeIndex.$refs.dialogue.sendText(obj.errorMsg);
} else if (this.$route.path == "/develop_LowCode") {
this.developLowCodeIndex.developLowCodeIndex.$refs.dialogue.sendText(
obj.errorMsg
);
}
}
});
});
},
methods: {
addErrorMarkers(errors) {
if (errors?.length) {
this.error_Msg = "";
const nolineNumber = errors.filter((item) => !item.lineNumber);
nolineNumber.forEach((list) => {
this.error_Msg += list.errorMsg;
});
const havelineNumber = errors.filter((item) => item.lineNumber);
this.errorsLists = havelineNumber;
if (this.errorsLists.length) {
const cm = this.$refs.editor.codemirror;
this.errorsLists.forEach((error) => {
cm.setGutterMarker(
+error.lineNumber - 1,
"CodeMirror-lint-markers",
this.makeCircleMarker(
`行号:${error.lineNumber}\n错误信息:${error.errorMsg.replace(
/\n/g,
""
)}`
)
);
this.addRedBackground(cm, +error.lineNumber);
});
}
}
},
addRedBackground(cm, lineNumber) {
const start = { line: lineNumber - 1, ch: 0 };
const end = { line: lineNumber, ch: 0 };
cm.markText(start, end, {
className: "red-background",
});
},
makeCircleMarker(msg) {
const circle = document.createElement("div");
circle.style.backgroundColor = "red";
circle.style.borderRadius = "50%";
circle.style.width = "8px";
circle.style.height = "8px";
circle.style.marginTop = "4px";
circle.style.marginLeft = "15px";
circle.style.cursor = "pointer";
circle.style.opacity = "0.7";
circle.title = msg;
return circle;
},
markText(val) {
let str = "";
const filterSpace = val.replace(/^\s+|\s+$/g, "");
const index1 = filterSpace.indexOf("\r");
const index2 = filterSpace.indexOf("\n");
if (index1 > 0) {
str = filterSpace.slice(0, index1);
} else {
if (index2 > 0) {
str = filterSpace.slice(0, index2);
} else {
str = filterSpace;
}
}
const newVal = str.split("").map((v) => {
if (
[
"$",
"(",
")",
"*",
"+",
".",
"[",
"]",
"?",
"/",
"^",
"{",
"}",
].includes(v)
) {
return `\\${v}`;
} else {
return v;
}
});
const reg = new RegExp(newVal.join("").trim(), "g");
this.marks.forEach((item) => item.clear());
this.marks = [];
let index = 0;
this.$refs.editor.codemirror?.eachLine((line) => {
Array.from(line.text.matchAll(reg)).forEach((item) => {
//this.codeEditor 为ready事件返回的编辑器实例 在另一篇文章中有获取方式
const mark = this.$refs.editor.codemirror?.markText(
{ line: index, ch: item.index },
{ line: index, ch: item.index + item[0].length },
{
className: "custom-keyword",
}
);
mark && this.marks.push(mark);
});
index++;
});
},
changeCodeTheme(theme) {
this.cmOptions.theme = theme;
this.setAttr(TEMPLATE_CODE_THEME, theme);
},
},
};
</script>
<style scoped lang="scss">
::v-deep .CodeMirror {
height: inherit !important;
border: 1px solid #eee !important;
}
.isfullscreen {
position: absolute;
right: 50px;
top: 15px;
}
::v-deep .CodeMirror-wrap {
// pointer-events: none;
}
::v-deep .cm-s-neat span.custom-keyword {
color: rgb(255, 186, 0) !important;
font-weight: 600;
}
::v-deep .red-background {
background-color: red !important;
cursor: pointer;
}
.el-icon-warning {
font-size: 15px;
margin-top: -10px;
}
</style>
Reproduction
.
System Info
win11,Google Chrome,"vue-codemirror": "^4.0.6"
Used Package Manager
npm
Validations