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 ; // }, // }); 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 () => ( // // {children} // // ); // }, 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 ? ( {children} ) : ( )} // ); }, // render() { // return ( // <> // {tag == "el-input" ? ( // // {children} // // ) : tag == "el-input-number" ? ( // // {children} // // ) : tag == "el-slider" ? ( // // {children} // // ) : tag == "el-time-picker" ? ( // // ) : tag === "el-switch" ? ( // // ) : tag === "el-color-picker" ? ( // // ) : tag === "el-button" ? ( // // {children[1]} // // ) : tag === "el-select" ? ( // // {children} // // ) : tag === "el-date-picker" ? ( // // {children} // // ) : null} // // ); // }, });