代码:
<template>
<CodeMirror
ref="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-select
class="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>