代码:
<template><CodeMirrorref="codeMirror":value="codeVal":languageSingle="languageSingle":readOnly="!isEdit"@submitCode="submitCode"></CodeMirror>
</template><script setup>
import { getFuncInfo, editFuncInfo } from "@/api/algorithm.js";
import CodeMirror from "@/components/CodeMirror/index.vue";
import { message } from "ant-design-vue";
import { ref, onMounted } from "vue";
const formData = ref({});
const props = defineProps({id: { type: String },isEdit: { type: Boolean, default: false },
});
const codeVal = ref("");
const formdata = ref({});
const languageSingle = ref({});
function dealData(res) {if (JSON.stringify(res) !== "{}") {if (res.algorithmBody !== null) {const algorithmBody = JSON.parse(res.algorithmBody);codeVal.value = algorithmBody.content;languageSingle.value = {val: algorithmBody.typeMode,label: algorithmBody.type,};}} else {console.log("ccc");languageSingle.value = {};}
}
function submitCode(type, typeMode, content) {const params = {type: type,typeMode: typeMode,content: content,};editFuncInfo({ id: formData.value.id, algorithmBody: JSON.stringify(params) }).then((res) => {if (JSON.stringify(res) !== "") {message.success("保存成功");dealData(res);} else {message.error("保存失败");}}).catch((err) => {message.error("保存失败");});
}
onMounted(() => {console.log("基本信息");getData();
});
const dataOld = ref();
const getData = () => {getFuncInfo({ id: props.id }).then((res) => {formData.value.groupName = res.algorithmGroup.name;formData.value = { ...formData.value, ...res };dataOld.value = { ...formData.value, ...res };dealData(res);});
};
</script>
<style lang="less" scoped>
.json_box {padding: 20px 15px;border: 1px solid #e8e8e8;min-height: calc(100vh - 280px);
}
:deep(.jv-container .jv-code) {padding: 0 !important;
}
</style>
codeMirror组件
<template><div class="in-coder-panel"><div class="select-box">选择语言:<a-selectclass="code-mode-select"@change="changeMode"v-model:value="language":disabled="single || readOnly"><a-select-option v-for="i in modes" :key="i.value" :value="i.value">{{ i.label }}</a-select-option></a-select><span class="run_btn" v-show="!readOnly"><!-- <a-icon type="play-circle" theme="filled" title="运行" /> --><span class="saveBtn" @click="saveCode">保存</span></span><!-- <a-icon class="run_btn" type="play-circle" theme="filled" title="运行" v-if="!readOnly"/> --></div><textarea ref="textarea"></textarea></div>
</template><script setup>
import { ref, onMounted, watch } from "vue";
// 引入全局实例
import _CodeMirror from "codemirror";
// import { Codemirror } from "vue-codemirror";
// // 核心样式
import "codemirror/lib/codemirror.css";
// 引入主题后还需要在 options 中指定主题才会生效
import "codemirror/theme/eclipse.css";
// import 'codemirror/addon/hint/show-hint.css'
// import 'codemirror/addon/hint/show-hint.js'
// 折叠
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/foldcode";
import "codemirror/addon/fold/foldgutter";
import "codemirror/addon/fold/brace-fold";
import "codemirror/addon/fold/comment-fold";
// 需要引入具体的语法高亮库才会有对应的语法高亮效果
// codemirror 官方其实支持通过 /addon/mode/loadmode.js 和 /mode/meta.js 来实现动态加载对应语法高亮库
// 但 vue 貌似没有无法在实例初始化后再动态加载对应 JS ,所以此处才把对应的 JS 提前引入
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/css/css.js";
import "codemirror/mode/xml/xml.js";
import "codemirror/mode/clike/clike.js";
import "codemirror/mode/markdown/markdown.js";
import "codemirror/mode/python/python.js";
import "codemirror/mode/r/r.js";
import "codemirror/mode/shell/shell.js";
import "codemirror/mode/sql/sql.js";
import "codemirror/mode/swift/swift.js";
import "codemirror/mode/vue/vue.js";
import { message } from "ant-design-vue";
const props = defineProps({value: {type: String,default: "",},languageSingle: {type: Object,default: () => {return {};}, // text/**//x-sql},readOnly: {type: Boolean,default: false,},single: {type: Boolean,default: false,},
});
// 尝试获取全局实例
const CodeMirror = ref(window.CodeMirror || _CodeMirror);
const code = ref();
const mode = ref("javascript");
const coder = ref(null);
const languageType = ref("");
const language = ref("");
const options = ref({// 缩进格式tabSize: 4,// 主题,对应主题库 JS 需要提前引入theme: "eclipse",// 显示行号lineNumbers: true,line: true,foldGutter: true,lineWrapping: true,gutters: ["CodeMirror-linenumbers","CodeMirror-foldgutter","CodeMirror-lint-markers",],matchTags: { bothTags: true },extraKeys: { Ctrl: "autocomplete" },
});
const modes = ref([// {// value: 'css',// label: 'CSS'// }, {// value: 'javascript',// label: 'Javascript'// }, {// value: 'html',// label: 'XML/HTML'// }, {// value: 'x-java',// label: 'Java'// }, {// value: 'x-csrc',// label: 'C'// }, {// value: 'x-c++src',// label: 'C++'// },{value: "x-csharp",label: "C#",},{value: "x-sql",label: "SQL",},{value: "javascript",label: "Javascript",},// {// value: 'x-python',// label: 'Python'// }, {// value: 'x-rsrc',// label: 'R'// }, {// value: 'x-sh',// label: 'Shell'// }, {// value: 'x-sql',// label: 'SQL'// }, {// value: 'x-swift',// label: 'Swift'// }, {// value: 'x-vue',// label: 'Vue'// }, {// value: 'markdown',// label: 'Markdown'// }
]);
onMounted(() => {_initialize();//
});
defineExpose({_initialize,CodeMirror,coder,language,
});
const textarea = ref();
// 初始化
function _initialize() {CodeMirror.value = window.CodeMirror || _CodeMirror;// 初始化编辑器实例,传入需要被实例化的文本域对象和默认配置coder.value = CodeMirror.value.fromTextArea(textarea.value, options.value);// 编辑器赋值if (props.value || code.value) {coder.value.setValue(props.value || code.value);} else {coder.value.setValue("");}code.value = props.value;// 支持双向绑定coder.value.on("change", (coder) => {code.value = coder.getValue();// if (this.$emit) {// this.$emit('input', this.code)// }});// 尝试从父容器获取语法类型if (JSON.stringify(props.languageSingle) !== "{}") {if (props.languageSingle.val) {language.value = props.languageSingle.val;}// language.value = props.languageSingle.val? props.languageSingle.val:''languageType.value = props.languageSingle.label;coder.value.setOption("mode", `text/` + language.value);}coder.value.setOption("readOnly", props.readOnly);
}
// 获取当前语法类型
function _getLanguage(language) {// 在支持的语法类型列表中寻找传入的语法类型return modes.value.find((mode) => {// 所有的值都忽略大小写,方便比较const currentLanguage = language.toLowerCase();const currentLabel = mode.label.toLowerCase();const currentValue = mode.value.toLowerCase();// 由于真实值可能不规范,例如 java 的真实值是 x-java ,所以讲 value 和 label 同时和传入语法进行比较return currentLabel === currentLanguage || currentValue === currentLanguage;});
}
const emits = defineEmits(["submitCode", "language-change"]);
// 更改模式
function changeMode(val) {language.value = val;// 修改编辑器的语法配置coder.value.setOption("mode", `text/${val}`);// 获取修改后的语法const label = _getLanguage(val).label.toLowerCase();// 允许父容器通过以下函数监听当前的语法值// emits('language-change',label)languageType.value = label;
}
function saveCode() {if (!languageType.value) {message.warning("请选择语言!");return;}if (!code.value) {message.warning("请输入函数!");return;}emits("submitCode", languageType.value, language.value, code.value);
}
watch(() => props.readOnly,(val, oldVal) => {coder.value.setOption("readOnly", val);}// { deep: true, immediate: true }
);
watch(() => props.value,(newVal, oldVal) => {console.log("fff");if (newVal) {console.log("nrr", newVal);props.value = newVal;CodeMirror.value = null;if (props.value || code.value) {coder.value.setValue(props.value || code.value);}code.value = props.value;if (JSON.stringify(props.languageSingle) !== "{}") {if (props.languageSingle.val) {language.value = props.languageSingle.val;}// language.value = props.languageSingle.val? props.languageSingle.val:''languageType.value = props.languageSingle.label;coder.value.setOption("mode", `text/` + language.value);}// _initialize ()} else {console.log("实现");// if(CodeMirror.value){// coder.value.setValue('')// CodeMirror.value=null// coder.value=null// code.value=''// languageType.value=''// }}},{ deep: true, immediate: true }
);
</script>
<style lang="less" scoped>
.in-coder-panel {position: relative;height: 660px;:deep(.CodeMirror) {flex-grow: 1;z-index: 1;height: calc(100% - 52px);border-top: 1px solid #dddddd;.CodeMirror-code {line-height: 19px;}}.CodeMirror-sizer {padding-top: 10px;}.select-box {padding-left: 15px;.code-mode-select {width: 200px;margin: 10px 0 10px;}}.run_btn {float: right;margin: 15px 20px 0;font-size: 24px;cursor: pointer;i {margin-left: 10px;&:hover {color: #357ad4;}}}.saveBtn {font-size: 16px;padding: 3px 20px;border-radius: 2px;background-color: #2d77e8;color: #fff;position: absolute;right: 20px;top: 18px;}
}
.in-coder-panel {:deep(.CodeMirror):nth-child(1) {display: none !important;}
}
</style>