基于 JSON Schema 构建 Element 表单,表单页面开发从未如此高效!
Element Schema Form:
https://vueblocks.github.io/element-schema-form/
textarea不能展示显示行号,也没有代码高亮,可以使用vue-codemirror替代
vue-codemirror:
https://www.npmjs.com/package/vue-codemirror
CodeMirror:
Extensible Code Editor
CodeMirror 6 is a rewrite of the CodeMirror code editor. It greatly improves the library's accessibility and touchscreen support, provides better content analysis and a modern programming interface. The new system matches the existing code in features and performance. It is not API-compatible with the old code.
The project is in the beta phase—there's a stable interface, but small breaking changes might still happen. It is being used in production in a few mid-size systems, but is not as battle-tested as the old version.
<template>
<div class="m-schema-wrap">
<div class="m-schema-toolbar">
<el-button type="primary" size="small" v-if="permission.func_config_center_history" @click="handleHistoryDialogVisible"
>历史记录</el-button
>
<el-button
type="primary"
size="small"
@click="handleFormatJsonData"
class="m-schema-space-left"
>格式化文档</el-button
>
<el-select v-model="viewType" size="small" placeholder="请选择" class="m-schema-space-left">
<el-option label="显示全部" :value="3"> </el-option>
<el-option label="只显示JSON schema 数据" :value="1"> </el-option>
<el-option label="只显示预览" :value="2"> </el-option>
</el-select>
</div>
<div class="m-schema-content">
<div class="m-schema-left" v-if="viewType === 1 || viewType === 3">
<div class="m-schema-title">JSON schema 数据:</div>
<!-- <el-input
type="textarea"
placeholder="请输入内容"
:value="schemaData"
@input="handleSchemaDataInput"
resize="none"
:class="[`m-schema-textarea ${isJsonData ? '' : 'error'}`]"
>
</el-input> -->
<codemirror
:value="schemaData"
@input="handleSchemaDataInput"
:options="cmOptions"
:class="[`m-schema-textarea ${isJsonData ? '' : 'error'}`]"
></codemirror>
<div :class="[`m-schema-error-msg ${isJsonData ? '' : 'active'}`]">
<div>请输入JSON格式的数据,错误信息:{{isJsonDataErrorMsg}}</div>
</div>
</div>
<div class="m-schema-right" v-if="viewType === 2 || viewType === 3">
<div class="m-schema-title">预览:</div>
<div class="m-schema-preview">
<el-form
size="small"
label-width="200px"
:model="model"
:rules="rules"
ref="ruleForm"
v-if="isSchemaFormVisible"
>
<schema-form
:model="model"
:layout="layout"
:schema="schema"
:options="options"
>
<div class="line" slot="line"></div>
<el-form-item slot="submit">
<el-button type="primary" @click="submitForm('ruleForm')"
>确定</el-button
>
<el-button @click="resetForm('ruleForm')">重置</el-button>
<el-button>取消</el-button>
</el-form-item>
</schema-form>
</el-form>
</div>
</div>
</div>
</div>
</template>
<script>
import { codemirror } from "vue-codemirror";
import "codemirror/lib/codemirror.css";
//https://codemirror.net/demo/theme.html#default
import "codemirror/theme/base16-dark.css";
import "codemirror/theme/blackboard.css";
import "codemirror/theme/ambiance.css";
import "codemirror/theme/ayu-dark.css";
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";
import "codemirror/mode/javascript/javascript.js";
import "./design.css";
export default {
props: ["schemaData", "onHistoryDialogVisible", "onFormatJsonData", "permission"],
data() {
return {
layout: {},
model: {},
schema: [],
options: {},
rules: {},
isSchemaFormVisible: true,
isJsonData: true,
isJsonDataErrorMsg: '',
cmOptions: {
tabSize: 2,
mode: {
name: "javascript",
json: true,
},
lineNumbers: true,
line: true,
lineWrapping: true,
theme: "base16-dark", //default, base16-dark blackboard ayu-dark
tabSize: 4,
styleActiveLine: true,
foldGutter: true,
lineWrapping: true,
gutters: [
"CodeMirror-linenumbers",
"CodeMirror-foldgutter",
"CodeMirror-lint-markers",
],
},
viewType: 3,
};
},
components: {
codemirror,
},
watch: {
schemaData() {
this.handleSchemaData(this.schemaData);
},
},
methods: {
handleHistoryDialogVisible() {
this.$emit("onHistoryDialogVisible");
},
handleSchemaData(schemaData) {
let schemaDataObj = {};
try {
schemaDataObj = JSON.parse(schemaData);
this.isJsonData = true;
} catch (error) {
this.isJsonData = false;
this.isJsonDataErrorMsg = error.message
}
const { layout, model, schema, options, rules } = schemaDataObj;
if (JSON.stringify(layout) !== JSON.stringify(this.layout)) {
this.layout = layout;
}
let isNeedRefresh = false;
if (JSON.stringify(model) !== JSON.stringify(this.model)) {
this.model = model;
isNeedRefresh = true;
}
if (JSON.stringify(schema) !== JSON.stringify(this.schema)) {
this.schema = schema;
}
if (JSON.stringify(options) !== JSON.stringify(this.options)) {
this.options = options;
}
if (JSON.stringify(rules) !== JSON.stringify(this.rules)) {
this.rules = rules;
isNeedRefresh = true;
}
if (isNeedRefresh) {
this.isSchemaFormVisible = false;
setTimeout(() => {
this.isSchemaFormVisible = true;
}, 200);
}
},
handleSchemaDataInput(value) {
this.$emit("onSchemaDataInput", value);
},
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
console.log("成功:", this.model);
} else {
console.log("验证失败:", this.model);
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
handleFormatJsonData() {
this.$emit("onFormatJsonData");
},
},
};
</script>