Files

329 lines
9.2 KiB
React
Raw Normal View History

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";
// import Editor from "@/components/Editor";
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,
// editor: Editor,
};
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}
// </>
// );
// },
});