UNPKG

magic-page-designer

Version:

magic-page-designer 是一个基于 vue 的在线页面快速开发平台,主要把所有的 vue 代码都改为在线配置,最终获得一个 json 格式的页面,你可以把它存放到服务器的任何地方:数据库、静态文件、redis 等。最方便的是可以在线修改页面,再也不用担心生产出问题了,还得打开 IDE,修改测试打包,直接在线编码,所见即所得。还可以配合 [magic-api](https://gitee.com/ssssssss-team/magic-api) 使用,完全抛弃 IDE,随时随地 code w

285 lines (283 loc) 10.3 kB
import { isArray, uuid } from './utils' import { isCssVariableName } from './regexUtil' import Vue from 'vue' import library from '../library' import { PageDom, ComponentItemExt, MpdConfig, ConfigDetailType } from '../library/page-object' import { mpdMessage } from './messageUtil' import _ from 'lodash' /** * 一维数组转对象 * @param arr 需要转换的数组对象 * @param keyField 作为key的字段名 * @param valueField 作为value的字段名 * @returns */ export const arrayToObj = function ( arr: Array<{ [key: string]: any }>, keyField: string = 'key', valueField: string = 'value' ): { [key: string]: any } { if (!isArray(arr)) { return {} } const obj: { [key: string]: any } = {} arr.forEach((item) => { if (isCssVariableName(item[keyField]) && item[valueField]) { obj[item[keyField]] = item[valueField] } }) return obj } /** * 初始化dom对象的默认值 * @param {PageDom} domItem */ export const initDomValue = function (domItem: PageDom) { // 节点名称 Vue.set(domItem, 'title', domItem.title || '') // 组件配置:页面dom配置 if (domItem.mpdConfig) { // 组件配置:使用的组件名 Vue.set(domItem.mpdConfig, 'component', domItem.mpdConfig.component || domItem.id) // 组件配置:双向绑定属性 Vue.set(domItem.mpdConfig, 'model', domItem.mpdConfig.model || {}) // 组件配置:传递的属性 Vue.set(domItem.mpdConfig, 'attr', domItem.mpdConfig.attr || {}) // 组件配置:class Vue.set(domItem.mpdConfig, 'class', domItem.mpdConfig.class || '') // 组件配置:style Vue.set(domItem.mpdConfig, 'style', domItem.mpdConfig.style || []) // 组件配置:v-on绑定的事件 Vue.set(domItem.mpdConfig, 'event', domItem.mpdConfig.event || {}) // 组件配置:text内容 Vue.set(domItem.mpdConfig, 'text', domItem.mpdConfig.text || '') // 组件配置:slot内容 if (!domItem.mpdConfig.slot) { const comConfig: PageDom = <PageDom>library.getLibraryDataMap(domItem.mpdConfig.component) if (comConfig && comConfig.mpdConfig && comConfig.mpdConfig.slot) { Vue.set(domItem.mpdConfig, 'slot', _.cloneDeep(comConfig.mpdConfig.slot)) } } else if (domItem.mpdConfig.slot.length > 0) { domItem.mpdConfig.slot.forEach((item) => { initDomValue(item) }) } // 组件配置:记录一些属性用的配置,用于设计器配置 Vue.set(domItem.mpdConfig, 'configTmp', domItem.mpdConfig.configTmp || {}) } else { const mpdConfig: MpdConfig = { component: domItem.id, model: {}, attr: {}, class: '', style: [], event: {}, configTmp: {} } Vue.set(domItem, 'mpdConfig', mpdConfig) } // 子节点 Vue.set(domItem, 'children', domItem.children || []) // id唯一标识,由uuid生成 if (!domItem.id || domItem.id.length !== 36) { Vue.set(domItem, 'id', uuid()) } // 将componentConfig的配置转换一下 transformComponentConfig(domItem) // 移除扩展参数 delete domItem.ext // 继续初始化子节点 initArrayDomValue(domItem.children) } /** * 初始化数组dom对象的默认值 * @param {Array} arrayDomItem */ export const initArrayDomValue = function (arrayDomItem?: Array<PageDom>): void { if (arrayDomItem && isArray(arrayDomItem) && arrayDomItem.length > 0) { arrayDomItem.forEach((item) => { initDomValue(item) }) } } /** * 转换组件配置 * @param {PageDom} domItem */ export const transformComponentConfig = function (domItem: PageDom): void { if (domItem.ext && domItem.ext.componentConfig) { domItem.ext.componentConfig.forEach((item) => { if (domItem.mpdConfig && item.defaultValue !== undefined) { Vue.set(domItem.mpdConfig[item.type] as object, item.name, item.defaultValue) } }) } } /** * 是否含有对应的配置属性 * @param domItem * @returns boolean */ export const hasConfigAttr = function (domItem: PageDom, attr: string): boolean { if (domItem.mpdConfig) { return domItem.mpdConfig.hasOwnProperty(attr) } return false } /** * 是否可以添加到子列表 * @param {PageDom} parent 父元素 * @param {PageDom} item 要判断的元素 * @returns {Boolean} */ export const isCanPushChildren = function (parent: PageDom, item: PageDom): Boolean { const parentMpdConfig: MpdConfig = parent.mpdConfig || {} const foundParentData: PageDom = <PageDom>library.getLibraryDataMap(parentMpdConfig.component || parent.id) const foundItemData: PageDom = <PageDom>( library.getLibraryDataMap(item.mpdConfig ? item.mpdConfig.component || item.id : item.id) ) let msg: string = '' const itemMpdConfig: MpdConfig = item.mpdConfig || {} if (!foundParentData) { msg = `没有在组件库中找到【${parent.title}(${parentMpdConfig.component})】的配置` } else if (!foundItemData) { msg = `没有在组件库中找到【${item.title}(${itemMpdConfig.component})】的配置` } else if (foundParentData.ext && foundParentData.ext.hasOwnProperty('childrenComponent')) { // 判断子元素配置 const extData: ComponentItemExt = foundParentData.ext if ( extData.childrenComponent && extData.childrenComponent.length > 0 && !extData.childrenComponent.includes(item.id) && !(itemMpdConfig.component && extData.childrenComponent.includes(itemMpdConfig.component)) ) { msg = `只能放入以下组件【${extData.childrenComponent.join(',')}】` } } else { msg = `没有配置属性【mpdConfig.childrenComponent】` } // 判断父元素配置 if ( !msg && foundItemData.ext && foundItemData.ext.hasOwnProperty('parentComponent') && (foundItemData.ext.parentComponent as string[]).length > 0 ) { const extData: ComponentItemExt = foundItemData.ext if ( extData.parentComponent && !extData.parentComponent.includes(parent.id) && !extData.parentComponent.includes(<string>parentMpdConfig.component) ) { msg = `子元素只能放入到以下组件【${extData.parentComponent.join(',')}】` } } if (msg) { const msgPrefix = `目标元素【${parent.title}(${parentMpdConfig.component})】不能拖入子元素【${item.title}】,原因:` mpdMessage.error(msgPrefix + msg) } return !msg } /** * 删除单个配置对象 * @param item 需要删除的对象 * @param configArray 需要删除的数组元素 * @param field 比较的字段 * @returns */ export const deleteItem = function (item: any, configArray: Array<any> = [], field: string = 'id'): boolean { for (const index in configArray) { if (configArray[index][field] === item[field]) { configArray.splice(index as unknown as number, 1) return true } if (configArray[index].mpdConfig.slot && configArray[index].mpdConfig.slot.length > 0) { if (deleteItem(item, configArray[index].mpdConfig.slot, field)) { return true } } if (configArray[index].children && configArray[index].children.length > 0) { if (deleteItem(item, configArray[index].children, field)) { return true } } } return false } /** * 选中item,如果不传则是取消选中 * @param selectPageNodeDom 选中的缓存对象 * @param item 选中节点的item * @param slotItem 选中节点的slotItem */ export const selectItem = function (selectPageNodeDom: any, item: PageDom, slotItem: PageDom) { if (item) { selectPageNodeDom.item = item selectPageNodeDom.slotItem = slotItem || {} } else { selectPageNodeDom.item = {} selectPageNodeDom.slotItem = {} } } /** * 优化mpdPageConfig json结构,主要删除无用的属性,让保存的json体积更小 * @param mpdPageConfig 页面配置 * @returns */ export const optimizeMpdPageConfig = function (mpdPageConfig: PageDom): PageDom { if (mpdPageConfig.mpdConfig) { if (!mpdPageConfig.mpdConfig.model || Object.keys(mpdPageConfig.mpdConfig.model).length === 0) { delete mpdPageConfig.mpdConfig.model } if (!mpdPageConfig.mpdConfig.attr || Object.keys(mpdPageConfig.mpdConfig.attr).length === 0) { delete mpdPageConfig.mpdConfig.attr } if (!mpdPageConfig.mpdConfig.class) { delete mpdPageConfig.mpdConfig.class } if (!mpdPageConfig.mpdConfig.style || mpdPageConfig.mpdConfig.style.length === 0) { delete mpdPageConfig.mpdConfig.style } if (!mpdPageConfig.mpdConfig.event || Object.keys(mpdPageConfig.mpdConfig.event).length === 0) { delete mpdPageConfig.mpdConfig.event } if (!mpdPageConfig.mpdConfig.text) { delete mpdPageConfig.mpdConfig.text } if (!mpdPageConfig.mpdConfig.slot || mpdPageConfig.mpdConfig.slot.length === 0) { delete mpdPageConfig.mpdConfig.slot } else { mpdPageConfig.mpdConfig.slot.forEach((item) => { optimizeMpdPageConfig(item) }) } // 整理slot配置 const comConfig: PageDom = <PageDom>library.getLibraryDataMap(mpdPageConfig.mpdConfig.component) if (comConfig.ext && comConfig.ext.componentConfig && comConfig.ext.componentConfig.length > 0) { comConfig.ext.componentConfig.forEach((item) => { if (mpdPageConfig.mpdConfig && mpdPageConfig.mpdConfig.configTmp) { const key = `${item.type}.${item.name}` if ( !item.inputList || item.inputList.length === 0 || item.inputList[0].component === mpdPageConfig.mpdConfig.configTmp[key] ) { delete mpdPageConfig.mpdConfig.configTmp[key] } } }) } if (!mpdPageConfig.mpdConfig.configTmp || Object.keys(mpdPageConfig.mpdConfig.configTmp).length === 0) { delete mpdPageConfig.mpdConfig.configTmp } } if (mpdPageConfig.children && mpdPageConfig.children.length > 0) { mpdPageConfig.children.forEach((item) => { optimizeMpdPageConfig(item) }) } else { delete mpdPageConfig.children } delete mpdPageConfig.ext return mpdPageConfig }