Skip to content

JSON生成表单

表单基础组件集合
<template>
  <div class="container">
    <div class="form-section">
      <div class="form-container">
        <XForm
          v-if="show"
          :config="config"
          v-model:api="api"
          v-model:formData="formData"
          :option="option"
        />
        <div>
          {{ validateState }}
        </div>
      </div>
    </div>
    <div class="data-section">
      <CodeView :code="formData" />
    </div>
  </div>
</template>

<script lang="ts" setup>
import type { formConfigTypes, formOptionsTypes } from "sc-business-ui";
import { ref, nextTick } from "vue";
import CodeView from "./CodeView/index.vue";
// 表单数据
const formData = ref({
  name: "s",
  autoComplete: "",
  activeKey: "0",
  testSwitch: false,
  cascader: ["1", "1-1"],
  transfer: ["1"],
  subItem: { name: "123" },
  filesId:'123'
});

const validateState = ref("");
const api = ref(null);
const option = ref<formOptionsTypes>({
  onSubmit(validate, formData) {
    console.log(validate);
    validateState.value = validate ? "提交中" : "验证失败";
    if (validate) {
      api.value.btn.loading(true);
      setTimeout(() => {
        api.value.btn.loading(false);
        validateState.value = "验证成功";
      }, 2000);
    }
  },
  created() {
    console.log("开始渲染 JSONVIEW");
  },
  mounted() {
    console.log("结束渲染 JSONVIEW");
  },

  wrap: {
    required: false,
    colon: true,
  },
  submitBtn: {
    loading: false,
    show: true,
    click: () => console.log("点击了提交按钮"),
    innerText: "sss",
  },
  resetBtn: { click: () => console.log("点击了重置按钮") },
});

let config: formConfigTypes[] = [
  {
    field: "name",
    type: "formItem",
    key: "input",
    col: {
      span: 12,
    },
    props: {
      self: { placeholder: "名字" },
      formItem: {
        label: "名字",
        rules: [{ required: true, message: "请输入名字", trigger: "blur" }],
      },
    },
  },
  {
    field: "age",
    type: "formItem",
    key: "input",
    col: {
      span: 12,
    },
    props: {
      self: { placeholder: "年龄", type: "number" },
      formItem: { label: "年龄", required: false },
    },
  },
  {
    field: "area",
    type: "formItem",
    key: "textarea",
    props: {
      self: { placeholder: "请输入签名", type: "number" },
      formItem: { label: "签名", required: false },
    },
  },
  {
    field: "password",
    type: "formItem",
    key: "password",
    props: {
      self: { placeholder: "请输入密码", visibilityToggle: true },
      formItem: { label: "密码", required: false },
    },
  },
  {
    field: "search",
    type: "formItem",
    key: "search",
    props: {
      self: { placeholder: "" },
      formItem: { label: "搜索", required: false },
    },
  },
  {
    key: "radio",
    type: "formItem",
    field: "radio",
    options: [
      { label: "北京", value: 1 },
      { label: "重庆", value: 2 },
    ],
    props: {
      self: {},
      formItem: {
        label: "选择城市",
        rules: [{ required: true, message: "请选择城市", trigger: "change" }],
      },
    },
  },
  {
    key: "checkbox",
    type: "formItem",
    field: "like",
    options: [
      { label: "足球", value: "1" },
      { label: "乒乓球", value: "2" },
      { label: "篮球", value: "3" },
    ],
    props: {
      self: {
        showCheckAll: true,
      },
      formItem: { label: "喜好" },
    },
  },
  {
    key: "rate",
    type: "formItem",
    field: "rate",
    props: { formItem: { label: "评分" } },
  },
  {
    key: "slider",
    type: "formItem",
    field: "slider",
    props: {
      formItem: { label: "滑块" },
      self: {
        step: 10,
        max: 100,
        marks: {
          0: "0°C",
          26: "26°C",
          47: "47°C",
          100: { style: { color: "#f50" }, label: "100°C" },
        },
      },
    },
  },
  {
    key: "inputNumber",
    type: "formItem",
    field: "inputNumber",
    props: {
      formItem: {
        label: "输入内容",
        rules: [{ required: true, message: "请输入数字", trigger: "blur" }],
      },
      self: { prefix: "$" },
    },
  },
  {
    key: "select",
    type: "formItem",
    field: "food",
    optionsTo: "options",
    options: [
      { value: 1, label: "苹果" },
      { value: 4, label: "香蕉" },
    ],
    props: {
      formItem: {
        label: "食物",
        rules: [{ required: true, message: "请选择食物", trigger: "change" }],
      },
      self: {},
    },
  },
  {
    key: "timePicker",
    type: "formItem",
    field: "timeList",
    props: {
      formItem: { label: "选择区间时间" },
      self: { type: "range" },
    },
  },
  {
    key: "switch",
    type: "formItem",
    field: "testSwitch",
    props: {
      formItem: { label: "测试 switch" },
      self: {
        checkedChildren: "开",
        unCheckedChildren: "关",
        size: "large",
      },
    },
  },
  {
    key: "autoComplete",
    type: "formItem",
    field: "autoComplete",
    options: [
      { label: "苹果", value: "苹果" },
      { value: "香蕉", label: "香蕉" },
    ],
    props: {
      formItem: {
        label: "食物",
        rules: [{ required: true, message: "请选择食物", trigger: "change" }],
      },
      self: {},
    },
  },
  {
    key: "cascader",
    type: "formItem",
    field: "cascader",
    options: [
      {
        label: "苹果",
        value: "1",
        children: [
          { label: "红富士", value: "1-1" },
          { label: "青苹果", value: "1-2", disabled: true },
        ],
      },
      { label: "香蕉", value: "2" },
    ],
    props: {
      formItem: {
        label: "水果",
        rules: [{ required: true, message: "请选择水果", trigger: "change" }],
      },
      self: {},
    },
  },
  {
    key: "transfer",
    type: "formItem",
    field: "transfer",
    options: [
      { key: "1", title: "香蕉", description: "1", disabled: false },
      { key: "2", title: "葡萄", description: "2", disabled: false },
      { key: "3", title: "梨", description: "3", disabled: false },
    ],
    props: {
      formItem: { label: "水果" },
      self: {},
    },
  },
  {
    key:"upload",
    type:"formItem",
    field:"filesId",
    props:{
      formItem:{label:"上传文件"},
      self:{}
    }
  
  }
];

const show = ref(true);

const updateConfig = (e) => {
  config = e;
  show.value = false;
  nextTick(() => {
    show.value = true;
  });
};

defineExpose({ config, updateConfig });
</script>

<style scoped>
.container {
  display: flex;
  padding: 0 20px;
  box-sizing: border-box;
  min-width: 600px;
}

.form-section {
  flex: 1;
  margin-right: 20px;
}

.form-container {
  padding: 20px;
  border-radius: 10px;
  height: 600px;
  overflow: auto;
  background-color: #f9f9f9;
}

.data-section {
  flex: 1;
}

h2 {
  font-weight: 700;
  margin-bottom: 10px;
}

.input-wrapper {
  display: flex;
  align-items: center;
  margin-top: 10px;
}

.input-wrapper span {
  white-space: nowrap;
  margin-right: 10px;
}

a-input {
  flex: 1;
}
</style>