2022-12-16 17:26:54 +08:00
|
|
|
|
import { deepClone } from "@/utils/index";
|
|
|
|
|
import {
|
|
|
|
|
ElRow,
|
|
|
|
|
ElRate,
|
|
|
|
|
ElInput,
|
|
|
|
|
ElSlider,
|
|
|
|
|
ElSelect,
|
|
|
|
|
ElButton,
|
|
|
|
|
ElSwitch,
|
|
|
|
|
ElUpload,
|
|
|
|
|
ElCascader,
|
|
|
|
|
ElDatePicker,
|
|
|
|
|
ElTimePicker,
|
|
|
|
|
ElRadioGroup,
|
|
|
|
|
ElColorPicker,
|
|
|
|
|
ElInputNumber,
|
|
|
|
|
ElCheckboxGroup,
|
|
|
|
|
} from "element-plus";
|
2022-12-21 15:23:17 +08:00
|
|
|
|
import Editor from "@/components/Editor";
|
2022-12-16 17:26:54 +08:00
|
|
|
|
import { h, defineComponent } from "vue";
|
|
|
|
|
|
|
|
|
|
const formComponentsMap = {
|
|
|
|
|
"el-row": ElRow,
|
|
|
|
|
"el-rate": ElRate,
|
|
|
|
|
"el-input": ElInput,
|
|
|
|
|
"el-switch": ElSwitch,
|
|
|
|
|
"el-select": ElSelect,
|
|
|
|
|
"el-upload": ElUpload,
|
|
|
|
|
"el-button": ElButton,
|
|
|
|
|
"el-slider": ElSlider,
|
|
|
|
|
"el-cascader": ElCascader,
|
|
|
|
|
"el-time-picker": ElTimePicker,
|
|
|
|
|
"el-radio-group": ElRadioGroup,
|
|
|
|
|
"el-date-picker": ElDatePicker,
|
|
|
|
|
"el-input-number": ElInputNumber,
|
|
|
|
|
"el-color-picker": ElColorPicker,
|
|
|
|
|
"el-checkbox-group": ElCheckboxGroup,
|
2022-12-21 15:23:17 +08:00
|
|
|
|
editor: Editor,
|
2022-12-16 17:26:54 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const componentChild = {};
|
|
|
|
|
/**
|
|
|
|
|
* 将./slots中的文件挂载到对象componentChild上
|
|
|
|
|
* 文件名为key,对应JSON配置中的__config__.tag
|
|
|
|
|
* 文件内容为value,解析JSON配置中的__slot__
|
|
|
|
|
*/
|
|
|
|
|
const slotsFiles = import.meta.glob("./slots/*.jsx", { eager: true });
|
|
|
|
|
// const slotsFiles = require.context("./slots", false, /\.js$/);
|
|
|
|
|
const keys = Object.keys(slotsFiles) || [];
|
|
|
|
|
keys.forEach((key) => {
|
|
|
|
|
const tag = key.replace(/^\.\/slots\/(.*)\.\w+$/, "$1");
|
|
|
|
|
componentChild[tag] = slotsFiles[key].default;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function vModel(dataObject, defaultValue) {
|
|
|
|
|
dataObject.props.value = defaultValue;
|
|
|
|
|
dataObject.on.input = (val) => {
|
|
|
|
|
this.$emit("input", val);
|
|
|
|
|
};
|
|
|
|
|
dataObject.on.change = (val) => {
|
|
|
|
|
this.$emit("input", val);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function mountSlotFiles(confClone, children) {
|
|
|
|
|
const childObjs = componentChild[confClone.__config__.tag];
|
|
|
|
|
if (childObjs) {
|
|
|
|
|
Object.keys(childObjs).forEach((key) => {
|
|
|
|
|
const childFunc = childObjs[key];
|
|
|
|
|
if (confClone.__slot__ && confClone.__slot__[key]) {
|
|
|
|
|
children.push(childFunc(confClone, key));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function emitEvents(confClone) {
|
|
|
|
|
["on", "nativeOn"].forEach((attr) => {
|
|
|
|
|
const eventKeyList = Object.keys(confClone[attr] || {});
|
|
|
|
|
eventKeyList.forEach((key) => {
|
|
|
|
|
const val = confClone[attr][key];
|
|
|
|
|
if (typeof val === "string") {
|
|
|
|
|
confClone[attr][key] = (event) => this.$emit(val, event);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function buildDataObject(confClone, dataObject) {
|
|
|
|
|
Object.keys(confClone).forEach((key) => {
|
|
|
|
|
const val = confClone[key];
|
|
|
|
|
if (key === "__vModel__") {
|
|
|
|
|
vModel.call(this, dataObject, confClone.__config__.defaultValue);
|
|
|
|
|
} else if (dataObject[key] !== undefined) {
|
|
|
|
|
if (
|
|
|
|
|
dataObject[key] === null ||
|
|
|
|
|
dataObject[key] instanceof RegExp ||
|
|
|
|
|
["boolean", "string", "number", "function"].includes(
|
|
|
|
|
typeof dataObject[key]
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
dataObject[key] = val;
|
|
|
|
|
} else if (Array.isArray(dataObject[key])) {
|
|
|
|
|
dataObject[key] = [...dataObject[key], ...val];
|
|
|
|
|
} else {
|
|
|
|
|
dataObject[key] = { ...dataObject[key], ...val };
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
dataObject.attrs[key] = val;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 清理属性
|
|
|
|
|
clearAttrs(dataObject);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearAttrs(dataObject) {
|
|
|
|
|
delete dataObject.attrs.__config__;
|
|
|
|
|
delete dataObject.attrs.__slot__;
|
|
|
|
|
delete dataObject.attrs.__methods__;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function makeDataObject() {
|
|
|
|
|
// 深入数据对象:
|
|
|
|
|
// https://cn.vuejs.org/v2/guide/render-function.html#%E6%B7%B1%E5%85%A5%E6%95%B0%E6%8D%AE%E5%AF%B9%E8%B1%A1
|
|
|
|
|
return {
|
|
|
|
|
class: {},
|
|
|
|
|
attrs: {},
|
|
|
|
|
props: {},
|
|
|
|
|
domProps: {},
|
|
|
|
|
nativeOn: {},
|
|
|
|
|
on: {},
|
|
|
|
|
style: {},
|
|
|
|
|
directives: [],
|
|
|
|
|
scopedSlots: {},
|
|
|
|
|
slot: null,
|
|
|
|
|
key: null,
|
|
|
|
|
ref: null,
|
|
|
|
|
refInFor: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// export default defineComponent({
|
|
|
|
|
// name: "render",
|
|
|
|
|
// props: {
|
|
|
|
|
// conf: {
|
|
|
|
|
// type: Object,
|
|
|
|
|
// required: true,
|
|
|
|
|
// },
|
|
|
|
|
// },
|
|
|
|
|
// setup(props, ctx) {
|
|
|
|
|
// console.log(props);
|
|
|
|
|
// console.log(ctx);
|
|
|
|
|
// const dataObject = makeDataObject();
|
|
|
|
|
// const confClone = deepClone(props.conf);
|
|
|
|
|
// const children = [ctx.slots.default] || [];
|
|
|
|
|
// // 如果slots文件夹存在与当前tag同名的文件,则执行文件中的代码
|
|
|
|
|
// mountSlotFiles.call(this, h, confClone, children);
|
|
|
|
|
|
|
|
|
|
// // 将字符串类型的事件,发送为消息
|
|
|
|
|
// emitEvents.call(this, confClone);
|
|
|
|
|
|
|
|
|
|
// // 将json表单配置转化为vue render可以识别的 “数据对象(dataObject)”
|
|
|
|
|
// buildDataObject.call(this, confClone, dataObject);
|
|
|
|
|
// const Tag = props.conf.__config__.tag;
|
|
|
|
|
// return <Tag></Tag>;
|
|
|
|
|
// },
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
|
name: "render",
|
|
|
|
|
props: {
|
|
|
|
|
conf: {
|
|
|
|
|
type: Object,
|
|
|
|
|
required: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
arr: [],
|
|
|
|
|
tempTime: "",
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
emits: ["input"],
|
|
|
|
|
// setup(props, { slots, emit }) {
|
|
|
|
|
// const dataObject = makeDataObject();
|
|
|
|
|
// const confClone = deepClone(props.conf);
|
|
|
|
|
// // const children = [this.$slots.default] || [];
|
|
|
|
|
// console.log(slots, "slots");
|
|
|
|
|
// const children = [];
|
|
|
|
|
// // 如果slots文件夹存在与当前tag同名的文件,则执行文件中的代码
|
|
|
|
|
// mountSlotFiles(h, confClone, children);
|
|
|
|
|
|
|
|
|
|
// // 将字符串类型的事件,发送为消息
|
|
|
|
|
// emitEvents(emit, confClone);
|
|
|
|
|
// setTimeout(() => {
|
|
|
|
|
// emit("input", "4ww3243");
|
|
|
|
|
// }, 3000);
|
|
|
|
|
// // 将json表单配置转化为vue render可以识别的 “数据对象(dataObject)”
|
|
|
|
|
// const update = (val) => {
|
|
|
|
|
// console.log(val, "update");
|
|
|
|
|
// emit("input", val);
|
|
|
|
|
// };
|
|
|
|
|
// buildDataObject(update, confClone, dataObject);
|
|
|
|
|
|
|
|
|
|
// const Tag = formComponentsMap[props.conf.__config__.tag];
|
|
|
|
|
|
|
|
|
|
// return () => (
|
|
|
|
|
// <Tag
|
|
|
|
|
// {...dataObject.attrs}
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// >
|
|
|
|
|
// {children}
|
|
|
|
|
// </Tag>
|
|
|
|
|
// );
|
|
|
|
|
// },
|
|
|
|
|
render() {
|
|
|
|
|
const dataObject = makeDataObject();
|
|
|
|
|
const confClone = deepClone(this.$props.conf);
|
|
|
|
|
const children = [];
|
|
|
|
|
// 如果slots文件夹存在与当前tag同名的文件,则执行文件中的代码
|
|
|
|
|
mountSlotFiles(confClone, children);
|
|
|
|
|
// 将字符串类型的事件,发送为消息
|
|
|
|
|
emitEvents.call(this, confClone);
|
|
|
|
|
|
|
|
|
|
// 将json表单配置转化为vue render可以识别的 “数据对象(dataObject)”
|
|
|
|
|
buildDataObject.call(this, confClone, dataObject);
|
|
|
|
|
const Tag = formComponentsMap[this.$props.conf.__config__.tag];
|
|
|
|
|
|
|
|
|
|
// return h(Tag, dataObject.attrs, children);
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{children.length > 0 ? (
|
|
|
|
|
<Tag
|
|
|
|
|
{...dataObject.attrs}
|
|
|
|
|
on={dataObject.on}
|
|
|
|
|
v-model={this.$props.conf.__config__.defaultValue}
|
|
|
|
|
>
|
|
|
|
|
{children}
|
|
|
|
|
</Tag>
|
|
|
|
|
) : (
|
|
|
|
|
<Tag
|
|
|
|
|
{...dataObject.attrs}
|
|
|
|
|
on={dataObject.on}
|
|
|
|
|
v-model={this.$props.conf.__config__.defaultValue}
|
|
|
|
|
></Tag>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
|
|
|
|
|
|
|
|
|
// <Tag options={dataObject.attrs.options} />
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
// render() {
|
|
|
|
|
|
|
|
|
|
// return (
|
|
|
|
|
// <>
|
|
|
|
|
// {tag == "el-input" ? (
|
|
|
|
|
// <el-input
|
|
|
|
|
// {...dataObject.attrs}
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// >
|
|
|
|
|
// {children}
|
|
|
|
|
// </el-input>
|
|
|
|
|
// ) : tag == "el-input-number" ? (
|
|
|
|
|
// <el-input-number
|
|
|
|
|
// {...dataObject.attrs}
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// >
|
|
|
|
|
// {children}
|
|
|
|
|
// </el-input-number>
|
|
|
|
|
// ) : tag == "el-slider" ? (
|
|
|
|
|
// <el-slider
|
|
|
|
|
// {...dataObject.attrs}
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// >
|
|
|
|
|
// {children}
|
|
|
|
|
// </el-slider>
|
|
|
|
|
// ) : tag == "el-time-picker" ? (
|
|
|
|
|
// <el-date-picker
|
|
|
|
|
// type="datetimerange"
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// />
|
|
|
|
|
// ) : tag === "el-switch" ? (
|
|
|
|
|
// <el-switch
|
|
|
|
|
// {...dataObject.attrs}
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// ></el-switch>
|
|
|
|
|
// ) : tag === "el-color-picker" ? (
|
|
|
|
|
// <el-color-picker
|
|
|
|
|
// {...dataObject.attrs}
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// ></el-color-picker>
|
|
|
|
|
// ) : tag === "el-button" ? (
|
|
|
|
|
// <el-button
|
|
|
|
|
// {...dataObject.attrs}
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// >
|
|
|
|
|
// {children[1]}
|
|
|
|
|
// </el-button>
|
|
|
|
|
// ) : tag === "el-select" ? (
|
|
|
|
|
// <el-select
|
|
|
|
|
// {...dataObject.attrs}
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// >
|
|
|
|
|
// {children}
|
|
|
|
|
// </el-select>
|
|
|
|
|
// ) : tag === "el-date-picker" ? (
|
|
|
|
|
// <el-date-picker
|
|
|
|
|
// {...dataObject.attrs}
|
|
|
|
|
// on={dataObject.on}
|
|
|
|
|
// modelValue={confClone.__config__.defaultValue}
|
|
|
|
|
// >
|
|
|
|
|
// {children}
|
|
|
|
|
// </el-date-picker>
|
|
|
|
|
// ) : null}
|
|
|
|
|
// </>
|
|
|
|
|
// );
|
|
|
|
|
// },
|
|
|
|
|
});
|