Commit 3c37394e authored by Bill's avatar Bill

feat: 营销装修页

parent 8f9736c8
import { PROPS_SETTING_TYPES } from '@lingxi-disign/core';
const mallLayoutConfig = {
key: "0",
"0": {
"componentName": "MallLayout",
"props": {
"style": {
"width": "100%",
"minHeight": "100%",
"background": "#F7F8FA",
"overflowX": "hidden",
"paddingBottom": "50px",
}
},
"childNodes": ["1", "5"]
},
};
const divWrap = {
key: "1",
"1": {
"componentName": "div",
"props": {
"style": {
"width": "100%",
"background": "#FFF",
}
},
"childNodes": ["2", "3"]
}
};
const mobileHeaderNav = {
key: "2",
"2": {
"componentName": "CustomizeTag",
"componentType": PROPS_SETTING_TYPES.mobileHeaderNav,
"title": "顶部导航",
"canEdit": true,
"canHide": false,
"props": {
type: 'primary'
},
}
};
const bannerWrap = {
key: "3",
"3": {
"componentName": "div",
"props": {
"style": {
"marginTop": "-50px",
}
},
"childNodes": ["4"]
}
};
const mobileBanner = {
key: "4",
"4": {
"componentName": "MobileBanner",
"componentType": PROPS_SETTING_TYPES.mobileBanner,
"title": "轮播广告",
"canEdit": true,
"canHide": true,
"props": {
visible: true,
dataList: []
}
}
};
const mobileQuickNav = {
key: "5",
"5": {
childNodes: ["6"],
"componentName": "MobileQuickNav",
"componentType": PROPS_SETTING_TYPES.mobileQuickNav,
"title": "功能入口",
"canEdit": true,
"canHide": true,
"props": {
dataList: [
{
"icon": "https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/85de453a73a44983ba9c441c54bdc2261619070264426.png",
"name": "找现货",
"type": 1,
"url": "",
},
{
"icon": "https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/646cba64f3984e8887b8cda29e561f471619070308310.png",
"name": "找供应",
"type": 2,
"url": "",
},
{
"icon": "https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/c2d16fe4c2104859a5ffc4ddd2b3bebe1619070341564.png",
"name": "找店铺",
"type": 6,
"url": "",
},
{
"icon": "https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/d6818a5f4c044e0b9fcc28e243b7ddcc1619070365026.png",
"name": "看资讯",
"type": 7,
"url": "",
},
{
"icon": "https://shushangyun-lingxi.oss-cn-shenzhen.aliyuncs.com/bbb358d8b1c64eb5ab0bfb9f5396297c1619070388474.png",
"name": "人气店铺",
"type": 9,
"url": "",
},
]
}
}
};
const mobileBanner1 = {
key: "6",
"6": {
"componentName": "div",
"props": {
"style": {
"width": "100%",
"background": "red",
marginTop: '600px',
}
},
"title": "嘻嘻",
"canEdit": true,
"canHide": true,
childNodes: ["7"]
}
};
const mobileBanner2 = {
key: "7",
"7": {
"componentName": "div",
"props": {
"style": {
"width": "100%",
"background": "red",
marginTop: '600px',
}
},
"title": "哈哈哈",
"canEdit": true,
"canHide": true,
}
};
const configs = {
...mallLayoutConfig,
...divWrap,
...mobileHeaderNav,
...bannerWrap,
...mobileBanner,
...mobileQuickNav,
...mobileBanner1,
...mobileBanner2
};
export default configs;
import React from 'react';
import { Switch } from 'antd';
const ComponentModule = () => {
return (
<div style={{ height: '160px', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
<img style={{width: '24px', height: '24px'}} />
<div style={{margin: '8px 0'}}>特价促销</div>
<div>
<Switch size="small" />
</div>
</div>
);
};
export default ComponentModule;
.tab {
width: 320px;
background-color: #fff;
:global {
.ant-tabs-nav-wrap {
width: 100%;
.ant-tabs-nav-list {
width: 100%;
.ant-tabs-tab {
height: 48px;
flex: 1;
border: none;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
font-size: 16px;
color: #8E959D;
& + .ant-tabs-tab {
margin-left: 0px;
}
}
}
}
.ant-collapse {
background-color: #fff;
border: none;
.ant-collapse-content {
border: none;
}
.ant-collapse-item {
border-bottom: none;
.ant-collapse-header {
border: 1px solid #EDEEEF;
padding: 8px;
display: flex;
flex-direction: row;
align-items: center;
padding: 0px;
}
.ant-collapse-content-box {
padding: 8px 0px;
&:last-of-type {
padding-bottom: 0px;
}
}
}
}
}
.noChildPanel {
background-color: #fff;
border-radius: 4px;
border: 1px solid #EDEEEF;
padding: 8px;
margin-bottom: 4px;
}
.active {
background: rgba(0,169,143,0.08);
border: 1px solid #00A98F;
}
.pannel {
flex: 1;
padding: 8px;
}
.add {
border: 1px solid #E3E4E5;
padding: 8px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-top: 8px;
}
.module {
display: flex;
flex-direction: row;
flex-wrap: wrap;
.moduleItem {
flex-basis: 50%,
}
}
}
import React, { useMemo, useState } from 'react';
import map from 'lodash/map';
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
import cx from 'classnames';
import { cloneDeep } from 'lodash';
import { selectComponent, PageConfigType, PropsType, ChildNodesType, SelectedInfoBaseType, SelectedInfoType, clearSelectedStatus, STATE_PROPS } from '@lingxi-disign/core';
import { useSelector } from '@lingxi-disign/react';
import { Collapse, Tabs } from 'antd';
import styles from './index.less';
import ComponentModule from './ComponentModule';
const { Panel } = Collapse;
const { TabPane } = Tabs;
export interface VirtualDOMType {
key?: string;
componentName: string;
props?: PropsType;
childNodes?: ChildNodesType;
condition?: string;
isStateDomain?: boolean;
propFields?: string[];
methods?: {
[key: string]: string;
};
loop?: string | any[];
fileName?: string;
[custom: string]: any;
}
type SettingPanelType = {
selectedInfo: SelectedInfoType,
pageConfig: PageConfigType
}
const getData = (pageConfig: PageConfigType, result: any[], keys: string[], dataIndex: string, parentKey: string, prefix: string) => {
// if (keys.includes())
if (keys.includes(dataIndex.toString())) {
return;
}
keys.push(dataIndex.toString());
const itemData = pageConfig[dataIndex];
itemData.key = dataIndex;
itemData.parentKey = parentKey;
itemData.uniqueKey = prefix + dataIndex;
if(!itemData.canEdit) {
return;
}
const childNodes = itemData.childNodes || [];
itemData.children = [];
(childNodes as string[]).forEach((_row) => {
const childrenRes = getData(pageConfig, result, keys, _row.toString(), dataIndex, itemData.uniqueKey + "_");
itemData.children.push(childrenRes);
});
if (parentKey === '0') {
result.push(itemData);
}
return itemData;
};
const ComponentTree = () => {
const [allComponents, setAllComponents] = useState<VirtualDOMType[]>([]);
const { selectedInfo, pageConfig } = useSelector<SettingPanelType, STATE_PROPS>(['selectedInfo', 'pageConfig']);
const depth = selectedInfo?.domTreeKeys?.length || 1;
const treeData = useMemo(() => {
const keys = [];
const res = [];
const cloneTemp = JSON.parse(JSON.stringify(pageConfig));
Object.keys(cloneTemp).map((_item, index) => {
if (_item === 'key') {
return;
}
if(cloneTemp[_item].canEdit) {
getData(cloneTemp, res, keys, _item.toString(), '0', "");
}
});
return res;
}, [pageConfig]);
const onSelect = (_row) => {
if(!selectedInfo || selectedInfo.selectedKey !== _row.key) {
const specialProps: SelectedInfoBaseType & { uniqueKey: string } = {
parentKey: _row?.parentKey,
key: _row.key,
domTreeKeys: _row.uniqueKey.split("_"),
uniqueKey: _row.uniqueKey,
};
selectComponent(specialProps);
}
};
const renderCollapse = (treeData, floor: number) => {
const offset = floor === 1 ? 8 : 16;
return (
<Collapse>
{
treeData.map((_item, index) => {
const { children } = _item;
if (children.length > 0) {
return (
<Panel showArrow={false} header={
<div
onClick={() => onSelect(_item)}
className={cx(
styles.pannel,
{
[styles.active]: selectedInfo?.selectedKey === _item.key
}
)}
style={{paddingLeft: offset * floor }}
>
{_item.title}
</div>
} key={_item.key}>
{ renderCollapse(children, floor+1)}
</Panel>
);
}
return (
<div
onClick={() => onSelect(_item)}
className={cx(styles.noChildPanel, {
[styles.active]: selectedInfo?.selectedKey === _item.key
})}
style={{paddingLeft: offset * floor }}
key={_item.key}
>
{_item.title}
</div>
);
})
}
{
depth === floor && (
<div className={styles.add}>添加分支</div>
) || null
}
</Collapse>
);
};
return (
<div className={styles.tab}>
<Tabs type="card">
<TabPane tab="已添加" key="1">
<div style={{padding: '0 16px'}}>
{renderCollapse(treeData, 1)}
</div>
</TabPane>
<TabPane tab="全部模块" key="2">
<div className={styles.module}>
{
[1,2,3].map((_item) => {
return (
<div className={styles.moduleItem} key={_item}>
<ComponentModule />
</div>
);
})
}
</div>
</TabPane>
</Tabs>
</div>
);
};
export default ComponentTree;
.toolbar {
display: flex;
flex-direction: row;
background-color: #fff;
align-items: center;
border-bottom: 1px solid #5C626A;
padding-right: 16px;
.back {
width: 48px;
height: 48px;
background-color: #5C626A;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.title {
margin-left: 16px;
font-size: 18px;
color: #1F2C3D;
}
.extra {
margin-left: auto;
}
}
......@@ -2,11 +2,9 @@ import React from 'react';
import { ArrowLeftOutlined } from '@ant-design/icons';
import { history } from 'umi';
import styles from './index.less';
interface Iprops {
extra: React.ReactNode,
title: string,
extra?: React.ReactNode,
title: string | React.ReactNode,
}
const Toolbar: React.FC<Iprops> = (props: Iprops) => {
......@@ -18,12 +16,12 @@ const Toolbar: React.FC<Iprops> = (props: Iprops) => {
return (
<div className={styles.toolbar}>
<div className={styles.back} onClick={goback}>
<ArrowLeftOutlined />
<ArrowLeftOutlined style={{color: '#fff', fontSize: '24px'}} />
</div>
<div className={styles.title}>
{title}
</div>
<div>{extra}</div>
<div className={styles.extra}>{extra}</div>
</div>
);
};
......
const mallLayoutConfig = {
key: "0",
"0": {
"componentName": "MallLayout",
"props": {
"style": {
"width": "100%",
"minHeight": "100%",
"background": "#F7F8FA",
"overflowX": "hidden",
"paddingBottom": "50px",
}
},
"childNodes": ["1"],
componentsMap: {},
componentSchemasMap: {},
},
};
const divWrap = {
key: "1",
"1": {
"componentName": "div",
componentsMap: {},
"props": {
"style": {
"width": "100%",
"background": "#FFF",
}
},
componentSchemasMap: {},
// "childNodes": []
}
};
const configs = {
...mallLayoutConfig,
...divWrap
};
export default configs;
@content-height: calc(100vh - 120px);
.wrapper {
background: white;
display: flex;
flex-direction: column;
box-shadow: 2px 0 4px 0 rgba(174, 174, 174, 0.50);
transition: all .3s;
}
.content {
display: flex;
flex: 1;
flex-direction: row;
justify-content: center;
background-color: #F2F3F5;
height: calc(100vh - 64px);
}
.app-wrapper {
display: flex;
flex: 1;
justify-content: center;
}
.app-canvas-container {
display: flex;
width: 381px;
margin-top: 40px;
margin-bottom: 52px;
justify-content: center;
background-color: #F4F5F7;
// height: calc(@content-height + 50px);
overflow: hidden;
}
import React from 'react';
import { Spin, message } from 'antd';
import { BrickProvider } from '@lingxi-disign/react';
import configs from './config';
import config from '@/pages/pageCustomized/configs';
import MobileDesignPanel from '@/pages/pageCustomized/components/MobileDesignPanel';
import ComponentTree from './components/ComponentTree';
import componentConfigs from './common/configs';
import Toolbar from './components/Toolbar';
import styles from './index.less';
interface Iprops {
location: {
......@@ -18,13 +23,26 @@ interface Iprops {
const Fixtures: React.FC<Iprops> = (props: Iprops) => {
return (
<Spin spinning={false}>
<div>123</div>
<BrickProvider
config={configs}
config={config}
warn={(msg: string) => {
message.warning(msg);
}}
>
<div className={styles['wrapper']}>
<Toolbar title="正在编辑:平台营销活动页" />
<div className={styles['content']}>
{/* <AllComponents /> */}
<ComponentTree />
<div className={styles['app-wrapper']}>
<div className={styles['app-canvas-container']}>
<MobileDesignPanel theme={'theme-mall-science'} onlyEidt pageConfig={componentConfigs} />
</div>
</div>
</div>
</div>
</BrickProvider>
</Spin>
);
......
import { ComponentSchemaType, PROPS_TYPES } from '@lingxi-disign/core';
const CustomizeTag: ComponentSchemaType = {
propsConfig: {
children: {
label: '文本内容',
type: PROPS_TYPES.string,
},
},
};
export default CustomizeTag;
......@@ -39,6 +39,7 @@ import PlatformInformation from './PlatformInformation';
import PlatformAddGoodsItem from './PlatformAddGoodsItem';
import PlatformIndex from './PlatformIndex';
import View from './View';
import CustomizeTag from './CustomizeTag';
export default {
View,
......@@ -82,4 +83,5 @@ export default {
PlatformService,
PlatformAddGoodsItem,
...PlatformIndex,
CustomizeTag
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment