同步操作将从 anye931123/react-visual-editor 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
import each from 'lodash/each';import update from 'lodash/update';import get from 'lodash/get';import cloneDeep from 'lodash/cloneDeep';import filter from 'lodash/filter';import isEmpty from 'lodash/isEmpty';import keys from 'lodash/keys';import merge from 'lodash/merge';import { message } from 'antd';import uuid from 'uuid';import {copyConfig, flattenDeepArray,generateNewKey,getFieldInPropsPath,getNewSortChildNodes,getPath, handleRequiredHasChild,} from '@/utils';import configs from '@/configs';import { generatePageCode } from '@/modules/previewAndCode/utils';import { addTemplates, deleteTemplate, getTemplates, searchTemplate } from '@/service';import {ModelType,PropsNodeType,PropsSettingType,SelectedComponentInfoType,VirtualDOMType,} from '@/types/ModelType';import defaultData from '../../data'const handleComponentInfo=(payload:any)=> {const { propName, componentConfig } = payload;const { parentName, childNodes } = componentConfig;let { componentName} = componentConfig;componentName = parentName || componentName;const isContainer = !!childNodeslet { nodePropsConfig} = get(configs.AllComponentConfigs, componentName),childNodesRule,isOnlyNode;if(nodePropsConfig){if(propName){({childNodesRule,isOnlyNode} = get(nodePropsConfig, propName))}else {each(nodePropsConfig,(config)=>{({childNodesRule,isOnlyNode}=config)})}}return {isContainer,isOnlyNode,childNodesRule,componentName}}/*** 初始默认组件* @type {{childNodes: Array, componentName: string, key: string, props: {style: {height: string}}}}*/const DEFAULT_LAYOUT :VirtualDOMType = {key: `n${Date.now()}`,componentName: 'Layout',props: { style: {height:'100%'} },childNodes: [],};const ALL_CONTAINER_COMPONENT_NAMES=flattenDeepArray(configs.CONTAINER_CATEGORY)/*** 命名空间* @type {string}*/export const namespace='BLOCK_NAME_CAMEL_CASE'/*** actions*/export const ACTION_TYPES={submitConfigs:`${namespace}/submitConfigs`,searchTemplate:`${namespace}/searchTemplate`,getTemplateList:`${namespace}/getTemplateList`,outputFiles:`${namespace}/outputFiles`,addTemplateInfo:`${namespace}/addTemplateInfo`,deleteTemplate:`${namespace}/deleteTemplate`,saveTemplateInfos:`${namespace}/saveTemplateInfos`,addComponent:`${namespace}/addComponent`,copyComponent:`${namespace}/copyComponent`,onLayoutSortChange:`${namespace}/onLayoutSortChange`,clearSelectedStatus:`${namespace}/clearSelectedStatus`,selectComponent:`${namespace}/selectComponent`,clearChildNodes:`${namespace}/clearChildNodes`,deleteComponent:`${namespace}/deleteComponent`,addPropsConfig:`${namespace}/addPropsConfig`,deletePropsConfig:`${namespace}/deletePropsConfig`,changeStyles:`${namespace}/changeStyles`,submitProps:`${namespace}/submitProps`,overTarget:`${namespace}/overTarget`,clearHovered:`${namespace}/clearHovered`,undo:`${namespace}/undo`,redo:`${namespace}/redo`,getDragData:`${namespace}/getDragData`,getDropTargetInfo:`${namespace}/getDropTargetInfo`,changePlatform:`${namespace}/changePlatform`}const Model:ModelType= {namespace,state: {componentConfigs: defaultData, // 所有组件信息selectedComponentInfo: {}, // 选中组件的信息propsSetting: {}, // 属性设置暂存属性数据styleSetting: {},undo: [],redo: [],templateInfos: [], // 复合组件hoverKey: null,dragData:null,dropTargetInfo:null,isMobile:true},effects: {* submitConfigs({ payload }, { select }) {const componentConfigs = yield select(state => get(state, `${namespace}.componentConfigs`));const { pageCodes, styleSheetCodes } = generatePageCode(componentConfigs);// if(res&&res.id){// message.success('页面配置更新成功!!');// } else {// message.error('配置信息更新失败!')// }},* searchTemplate({payload},{put}){const templateInfo=yield new Promise(function(resolve) {searchTemplate(payload.searchValue,resolve)})yield put({type: 'saveTemplateInfos',templateInfos:templateInfo?[templateInfo]:[],})},* getTemplateList(_, { put }) {const templateInfos = yield new Promise(function(resolve) {getTemplates(resolve);});yield put({type: 'saveTemplateInfos',payload:{templateInfos}});},* addTemplateInfo({ payload }, { put }) {yield new Promise(function(resolve) {addTemplates(payload, resolve);});yield put({type: 'getTemplateList',});},* deleteTemplate({ payload }, { put }) {const { id } = payload;yield new Promise(function(resolve) {deleteTemplate(id, resolve);});yield put({type: 'getTemplateList',});},},reducers: {saveTemplateInfos(state, {payload}) {return {...state,...payload,};},/*** 往画板或者容器组件添加组件* @param state* @returns {{componentConfigs: *}}*/addComponent(state) {const {undo, redo,componentConfigs: prevComponentConfigs,selectedComponentInfo,dragData,dropTargetInfo} = state;const { defaultProps = {}, componentName, templateData,dragPath,dragParentPath }=dragData!const { propPath, path, isOnlyNode,isContainer, childNodesRule, componentName: selectedComponentName, propName }=dropTargetInfo!||selectedComponentInfo;// 找到新添加组件所要放置的路径位置const parentPath = getPath({ path: propPath || path, isContainer: true });/*** 如果在有跟节点的情况下选中组件为非容器组件,* 或者拖拽组件的父节点路径与当前选中组件的子节点路径相同表明拖拽组件没有拖出它所在的容器,* 或者拖拽组件的路径与当前选中组件的路径相同表明为它自己*/if(!isContainer&&!isEmpty(prevComponentConfigs)||dragParentPath&&parentPath===dragParentPath ||dragPath&&dragPath===path){return state}const componentConfigs = cloneDeep(prevComponentConfigs);const isTemplate = !isEmpty(templateData);let info:VirtualDOMType;if(dragParentPath){info=templateData!}else if(isTemplate){info= generateNewKey(templateData!)}else {info = {key: uuid(),componentName:componentName!,props: defaultProps, // 最终输出当前组件的属性树};}/*** 获取当前拖拽组件的父组件规则,以及属性节点配置信息*/const { nodePropsConfig, parentNodesRule } = get(configs.AllComponentConfigs, info.componentName);/*** 父组件规则限制,减少不必要的组件错误嵌套*/if (parentNodesRule && !parentNodesRule.includes(propName ? `${selectedComponentName}.${propName}` : selectedComponentName)) {message.warning(`${info.componentName}:只允许放入${parentNodesRule.toString()}组件或者属性中`);return state;}/*** 子组件规则限制,减少不必要的组件错误嵌套*/if (childNodesRule && !childNodesRule.includes(info.componentName)) {message.warning(`${propName || selectedComponentName}:只允许拖拽${childNodesRule.toString()}组件`);return state;}if (!isTemplate) {const isContainer = ALL_CONTAINER_COMPONENT_NAMES.includes(componentName!);if (isContainer) {const childNodes:VirtualDOMType[]|PropsNodeType={};// 获取该组件节点属性映射字段信息const isMultiPropsNode= keys(nodePropsConfig).length > 1each(nodePropsConfig, (nodePropConfig, propName) => {isMultiPropsNode&&(childNodes[propName] = { childNodes: []});});// 更改新添加组件的key为最后一个属性节点key此key目的为默认选中最后一个属性节点info.childNodes = isEmpty(childNodes) ? [] : childNodes;}}if (parentPath) {update(componentConfigs, parentPath, childNodes => {if (isOnlyNode) return [info];return [...childNodes, info];});if(dragParentPath){update(componentConfigs,dragParentPath,(childNodes)=>childNodes.filter((node:VirtualDOMType)=>node.key!==info.key))}} else {componentConfigs.push(info);}undo.push({ componentConfigs: prevComponentConfigs });redo.length = 0;return {...state,componentConfigs,dragData:null,dropTargetInfo:null,undo,redo,};},/*** 复制组件* @param state* @returns {{componentConfigs: *}}*/copyComponent(state) {const { undo, redo, componentConfigs: prevComponentConfigs, selectedComponentInfo } = state;const { selectedKey,parentPath }=selectedComponentInfo as SelectedComponentInfoType;const componentConfigs = cloneDeep(prevComponentConfigs);if (parentPath) {update(componentConfigs, parentPath, childNodes => copyConfig(childNodes, selectedKey));} else {message.warning('禁止复制根节点或者OnlyNode节点');return state;}undo.push({ componentConfigs: prevComponentConfigs });redo.length = 0;return {...state,componentConfigs,undo,redo,};},/*** 当domTree中拖拽节点调整顺序时触发* @param state* @param action* @returns {{componentConfigs: *}}*/onLayoutSortChange(state, {payload}) {const { sortKeys, path, dragNode } = payload;const { undo, redo, componentConfigs: prevComponentConfigs } = state;let componentConfigs = cloneDeep(prevComponentConfigs);update(componentConfigs, path, childNodes => getNewSortChildNodes(sortKeys, childNodes, dragNode),);undo.push({ componentConfigs: prevComponentConfigs });redo.length = 0;return {...state,componentConfigs,undo,redo,};},/*** 清除选中状态* @param state* @returns {{undo: *, propsSetting: {}, redo: *, selectedComponentInfo: {}}}*/clearSelectedStatus(state) {const { selectedComponentInfo, propsSetting, undo, redo, styleSetting,componentConfigs } = state;if(handleRequiredHasChild(selectedComponentInfo as SelectedComponentInfoType,componentConfigs)){return state}undo.push({ selectedComponentInfo, propsSetting, styleSetting });redo.length = 0;return {...state,selectedComponentInfo: {},propsSetting: {},styleSetting: {},undo,redo,};},/*** 选中组件* @param state* @param action* @returns {{ undo: *, propsSetting: {propsConfig, mergePropsConfig, addPropsConfig: *, props: *}, redo: *, selectedComponentInfo: {selectedKey: *, path: *, domTreeKeys: *[], parentPath: *, isContainer: boolean, style: *, componentName: *, nodePropsConfig}}}*/selectComponent(state, {payload}) {const { undo, redo, selectedComponentInfo, propsSetting,componentConfigs } = state;if(handleRequiredHasChild(selectedComponentInfo as SelectedComponentInfoType,componentConfigs)){return state}const {propPath, path, propName, componentConfig, parentPath, domTreeKeys,isRequiredHasChild } = payload;const { props, addPropsConfig={},key } = componentConfig;const {isContainer, isOnlyNode, childNodesRule, componentName}=handleComponentInfo(payload)let { propsConfig} = get(configs.AllComponentConfigs, componentName);const mergePropsConfig = merge({}, propsConfig, addPropsConfig);undo.push({ selectedComponentInfo, propsSetting });let selectedKey = key;if (propName && !key.includes(propName)) {selectedKey = `${key}${propName}`;domTreeKeys.push(selectedKey);}redo.length = 0;return {...state,dropTargetInfo:null,selectedComponentInfo: {selectedKey,style: props.style||{},parentPath,componentName,propName,propPath,path,isContainer,isOnlyNode,childNodesRule,domTreeKeys,isRequiredHasChild},propsSetting: { propsConfig, mergePropsConfig, addPropsConfig, props },undo,redo,styleSetting: props.style,};},/*** 清除所有子节点* @param state* @returns {{undo: *, componentConfigs, redo: *}}*/clearChildNodes(state) {const { componentConfigs: prevComponentConfigs, selectedComponentInfo, undo, redo } = state;const componentConfigs = cloneDeep(prevComponentConfigs);const { path,propPath} = selectedComponentInfo as SelectedComponentInfoType;const updatePath=getPath({ path:propPath||path, isContainer: true })update(componentConfigs,updatePath!, () => []);undo.push({ componentConfigs: prevComponentConfigs });redo.length = 0;return {...state,componentConfigs,undo,redo,};},/*** 删除组件* @param state* @returns {{propsSetting: *, componentConfigs: *, selectedComponentInfo: *}}*/deleteComponent(state) {const { undo, redo, componentConfigs: prevComponentConfigs, selectedComponentInfo, propsSetting } = state;let componentConfigs = cloneDeep(prevComponentConfigs);const { selectedKey, parentPath } = selectedComponentInfo as SelectedComponentInfoType;if (parentPath) {update(componentConfigs, parentPath, childNodes =>filter(childNodes, componentConfig => !selectedKey.includes(componentConfig.key)),);} else {componentConfigs = [];}undo.push({ componentConfigs: prevComponentConfigs, propsSetting, selectedComponentInfo });redo.length = 0;return {...state,componentConfigs,propsSetting: {},selectedComponentInfo: {},undo,redo,};},/*** 添加属性配置* @param state* @param action* @returns {{propsSetting: *}}*/addPropsConfig(state, {payload}) {const { newPropField, parentFieldPath, childPropsConfig, propType } = payload;const { propsSetting: prevPropsSetting, undo, redo } = state;const propsSetting = cloneDeep(prevPropsSetting);const { addPropsConfig, propsConfig } = propsSetting as PropsSettingType;let isAdd = true;update(addPropsConfig, parentFieldPath, (propsContent:any) => {// 对象数组 添加一个对象时的逻辑if (childPropsConfig) return childPropsConfig;if (!propsContent) propsContent = {};if (propsContent[newPropField]) {isAdd = false;message.warning(`${newPropField}属性已存在`);} else {propsContent[newPropField] = {label: newPropField,type: propType,isAdd: true};}return propsContent;});if (!isAdd) return state;const mergePropsConfig = (merge({}, propsConfig, addPropsConfig));undo.push({ propsSetting: prevPropsSetting });redo.length = 0;return {...state,propsSetting:{...propsSetting,mergePropsConfig},undo,redo,};},/*** 删除属性配置* @param state* @param action* @returns {{propsSetting: *}}*/deletePropsConfig(state, {payload}) {const { propsSetting: prevPropsSetting, undo, redo } = state;const propsSetting = cloneDeep(prevPropsSetting);const { parentFieldPath, field } = payload;const { addPropsConfig, propsConfig,props } = propsSetting as PropsSettingType;const fieldInPropsPath= getFieldInPropsPath(parentFieldPath)update(addPropsConfig, parentFieldPath, prevPropsConfig => {delete prevPropsConfig[field];return prevPropsConfig;});update(props,fieldInPropsPath,prevProps=>{if(typeof prevProps ==='object'){delete prevProps[field]}return prevProps})const mergePropsConfig = merge({}, propsConfig, addPropsConfig);undo.push({ propsSetting: prevPropsSetting });redo.length = 0;return {...state,propsSetting:{...propsSetting,mergePropsConfig},undo,redo,};},/*** 样式改变时调用* @param state* @param action* @returns {{propsSetting: *, componentConfigs: *}|*}*/changeStyles(state, {payload}) {const { style } = payload;const { undo, redo, selectedComponentInfo, componentConfigs: prevComponentConfigs, styleSetting: prevStyleSetting } = state;const { path } = selectedComponentInfo as SelectedComponentInfoType;if (isEmpty(selectedComponentInfo)) return state;const componentConfigs = cloneDeep(prevComponentConfigs);let styleSetting = style;update(componentConfigs, path, componentConfig => {componentConfig.props.style = style;return componentConfig;});undo.push({ componentConfigs: prevComponentConfigs, styleSetting: prevStyleSetting });redo.length = 0;return {...state,componentConfigs,styleSetting,undo,redo,};},/*** 提交属性* @param state* @param action* @returns {{propsSetting: *, componentConfigs: *}}*/submitProps(state, {payload}) {const { props } = payload;const { propsSetting: prevPropsSetting, componentConfigs: prevComponentConfigs, selectedComponentInfo, undo, redo } = state;const propsSetting = cloneDeep(prevPropsSetting);const componentConfigs = cloneDeep(prevComponentConfigs);const { path } = selectedComponentInfo as SelectedComponentInfoType;update(componentConfigs, path, (componentConfig) => {const { addPropsConfig } = propsSetting as PropsSettingType;const { props: { style } } = componentConfig;return ({...componentConfig,props: { ...props, style },...(isEmpty(addPropsConfig)?{}:{addPropsConfig}),});});undo.push({ componentConfigs: prevComponentConfigs, propsSetting: prevPropsSetting });redo.length = 0;message.success('属性配置提交成功!!');return {...state,propsSetting:{...propsSetting,props},componentConfigs,undo,redo,};},/*** hover 目标组件* @param state* @param action* @returns {{hoverKey: *}}*/overTarget(state, {payload}) {const { hoverKey } = payload;return {...state,hoverKey,};},/*** 清除hover状态* @param state* @returns {{hoverKey: null}}*/clearHovered(state) {return {...state,hoverKey: null,};},/*** 获取拖拽组件数据* @param state* @param action* @returns {{dragData: *}}*/getDragData(state,{payload}){const {dragData}=payloadreturn{...state,dragData}},/*** 获取放置组件的容器组件信息* @param state* @param payload*/getDropTargetInfo(state,{payload}){/*** 如果path为undefined说明当前组件不是容器组件*/if(!payload.path) return {...state,dropTargetInfo:null,hoverKey:null}const {path, propName, propPath,componentConfig:{key}}=payloadconst {isOnlyNode,isContainer, childNodesRule, componentName}=handleComponentInfo(payload)return{...state,dropTargetInfo:{isContainer,propPath,path,isOnlyNode,childNodesRule,componentName,propName},hoverKey:key}},/*** 更改平台* @param state*/changePlatform(state){const {isMobile}=statereturn {...state,isMobile:!isMobile,redo:[],undo:[]}},/*** 撤销* @param state* @returns {(*&void&{undo: *, redo: *})|(*&T&{undo: *, redo: *})}*/undo(state) {const { undo, redo } = state;const nextState = undo.pop();const prevState:any = {};each(nextState, (_, key) => prevState[key] = get(state,key));redo.push(prevState);return {...state,...nextState,undo,redo,};},/*** 重做* @param state* @returns {(*&void&{undo: *, redo: *})|(*&T&{undo: *, redo: *})}*/redo(state) {const { undo, redo } = state;const nextState = redo.pop();const prevState:any = {};each(nextState, (_, key) => prevState[key] = get(state,key));undo.push(prevState);return {...state,...nextState,undo,redo,};},},};export default Model;
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。