输入json数据,自动生成表单,且json数据语法高亮

基于 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.

https://codemirror.net/6/

<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>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐同保

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值