mirror of
https://github.com/MrXujiang/h5-Dooring.git
synced 2026-03-17 11:13:38 +00:00
🔨 代码部分重构,渲染层和数据层分离,核心组件放在core文件夹
This commit is contained in:
parent
a1516cfffa
commit
5a8d62d98a
@ -1,36 +0,0 @@
|
|||||||
import { memo } from 'react';
|
|
||||||
import { BackToTop, Icon } from 'zarm';
|
|
||||||
import React from 'react';
|
|
||||||
const themeObj = {
|
|
||||||
simple: { bgColor: '#fff', color: '#999' },
|
|
||||||
black: { bgColor: '#000', color: '#fff' },
|
|
||||||
danger: { bgColor: '#ff5050', color: '#fff' },
|
|
||||||
primary: { bgColor: '#00bc71', color: '#fff' },
|
|
||||||
blue: { bgColor: '#06c', color: '#fff' },
|
|
||||||
};
|
|
||||||
const BackTop = memo((props: { theme: keyof typeof themeObj }) => {
|
|
||||||
const { theme = 'simple' } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<BackToTop>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
lineHeight: '48px',
|
|
||||||
textAlign: 'center',
|
|
||||||
backgroundColor: themeObj[theme].bgColor,
|
|
||||||
color: themeObj[theme].color,
|
|
||||||
fontSize: 20,
|
|
||||||
borderRadius: 30,
|
|
||||||
boxShadow: '0 2px 10px 0 rgba(0, 0, 0, 0.2)',
|
|
||||||
cursor: 'pointer',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon type="arrow-top" />
|
|
||||||
</div>
|
|
||||||
</BackToTop>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default BackTop;
|
|
||||||
@ -7,7 +7,7 @@ import {
|
|||||||
TDataListDefaultType,
|
TDataListDefaultType,
|
||||||
TNumberDefaultType,
|
TNumberDefaultType,
|
||||||
TSelectDefaultType,
|
TSelectDefaultType,
|
||||||
} from '@/components/PanelComponents/FormEditor/types';
|
} from '@/core/FormComponents/types';
|
||||||
import { baseConfig, baseDefault, ICommonBaseType } from '../../common';
|
import { baseConfig, baseDefault, ICommonBaseType } from '../../common';
|
||||||
export type TListSelectKeyType = '60' | '80' | '100' | '120' | '150';
|
export type TListSelectKeyType = '60' | '80' | '100' | '120' | '150';
|
||||||
export type TListEditData = Array<
|
export type TListEditData = Array<
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
TNumberDefaultType,
|
TNumberDefaultType,
|
||||||
TSelectDefaultType,
|
TSelectDefaultType,
|
||||||
TTextAreaDefaultType,
|
TTextAreaDefaultType,
|
||||||
} from '@/components/PanelComponents/FormEditor/types';
|
} from '@/core/FormComponents/types';
|
||||||
export type TLongTextSelectKeyType = 'left' | 'center' | 'right';
|
export type TLongTextSelectKeyType = 'left' | 'center' | 'right';
|
||||||
|
|
||||||
export type TLongTextEditData = Array<
|
export type TLongTextEditData = Array<
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
TNumberDefaultType,
|
TNumberDefaultType,
|
||||||
TSelectDefaultType,
|
TSelectDefaultType,
|
||||||
TTextDefaultType,
|
TTextDefaultType,
|
||||||
} from '@/components/PanelComponents/FormEditor/types';
|
} from '@/core/FormComponents/types';
|
||||||
|
|
||||||
export type TTextSelectKeyType = 'left' | 'right' | 'center';
|
export type TTextSelectKeyType = 'left' | 'right' | 'center';
|
||||||
export type TTextEditData = Array<
|
export type TTextEditData = Array<
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
import { NoticeBar } from 'zarm';
|
|
||||||
import React, { memo } from 'react';
|
|
||||||
import { INoticeConfig } from './schema';
|
|
||||||
const Notice = memo((props: INoticeConfig) => {
|
|
||||||
const { text, speed, theme, isClose = false } = props;
|
|
||||||
return (
|
|
||||||
<NoticeBar theme={theme === 'default' ? undefined : theme} closable={isClose} speed={speed}>
|
|
||||||
<span style={{ color: 'inherit' }}>{text}</span>
|
|
||||||
</NoticeBar>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default Notice;
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
import {
|
|
||||||
INumberConfigType,
|
|
||||||
ISelectConfigType,
|
|
||||||
ISwitchConfigType,
|
|
||||||
ITextConfigType,
|
|
||||||
TNumberDefaultType,
|
|
||||||
TSelectDefaultType,
|
|
||||||
TSwitchDefaultType,
|
|
||||||
TTextDefaultType,
|
|
||||||
} from '@/components/PanelComponents/FormEditor/types';
|
|
||||||
|
|
||||||
export type TNoticeSelectKeyType = 'default' | 'warning' | 'primary' | 'success' | 'danger';
|
|
||||||
export type TNoticeEditData = Array<
|
|
||||||
ITextConfigType | INumberConfigType | ISelectConfigType<TNoticeSelectKeyType> | ISwitchConfigType
|
|
||||||
>;
|
|
||||||
export interface INoticeConfig {
|
|
||||||
text: TTextDefaultType;
|
|
||||||
speed: TNumberDefaultType;
|
|
||||||
theme: TSelectDefaultType<TNoticeSelectKeyType>;
|
|
||||||
isClose: TSwitchDefaultType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface INoticeSchema {
|
|
||||||
editData: TNoticeEditData;
|
|
||||||
config: INoticeConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Notice: INoticeSchema = {
|
|
||||||
editData: [
|
|
||||||
{
|
|
||||||
key: 'text',
|
|
||||||
name: '文本',
|
|
||||||
type: 'Text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'speed',
|
|
||||||
name: '滚动速度',
|
|
||||||
type: 'Number',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'theme',
|
|
||||||
name: '主题',
|
|
||||||
type: 'Select',
|
|
||||||
range: [
|
|
||||||
{
|
|
||||||
key: 'default',
|
|
||||||
text: '默认',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'warning',
|
|
||||||
text: '警告',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'primary',
|
|
||||||
text: '主要',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'success',
|
|
||||||
text: '成功',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'danger',
|
|
||||||
text: '危险',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'isClose',
|
|
||||||
name: '是否可关闭',
|
|
||||||
type: 'Switch',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
config: {
|
|
||||||
text: '通知栏: 趣谈前端上线啦',
|
|
||||||
speed: 50,
|
|
||||||
theme: 'warning',
|
|
||||||
isClose: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Notice;
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
const template = {
|
|
||||||
type: 'Notice',
|
|
||||||
h: 20,
|
|
||||||
};
|
|
||||||
export default template;
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
.tabWrap {
|
|
||||||
padding-top: 16px;
|
|
||||||
padding-bottom: 16px;
|
|
||||||
.content {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
.item {
|
|
||||||
padding: 20px 20px 0;
|
|
||||||
width: 50%;
|
|
||||||
text-align: center;
|
|
||||||
justify-content: center;
|
|
||||||
.imgWrap {
|
|
||||||
display: inline-block;
|
|
||||||
width: 80%;
|
|
||||||
img {
|
|
||||||
border-radius: 6px;
|
|
||||||
width: 120px;
|
|
||||||
height: 120px;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
.title {
|
|
||||||
line-height: 2.4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
|
||||||
import { Tabs } from 'zarm';
|
|
||||||
import styles from './index.less';
|
|
||||||
import { ITabConfig } from './schema';
|
|
||||||
|
|
||||||
const { Panel } = Tabs;
|
|
||||||
|
|
||||||
const XTab = (props: ITabConfig) => {
|
|
||||||
const { tabs = ['分类一', '分类二'], activeColor, color, fontSize, sourceData } = props;
|
|
||||||
|
|
||||||
const tabWrapRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (tabWrapRef.current) {
|
|
||||||
let res = tabWrapRef.current.querySelector('.za-tabs__line') as HTMLElement;
|
|
||||||
if (res) {
|
|
||||||
res.style.backgroundColor = activeColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [activeColor]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.tabWrap} ref={tabWrapRef}>
|
|
||||||
<Tabs scrollThreshold={3}>
|
|
||||||
{tabs.map((item, i) => {
|
|
||||||
return (
|
|
||||||
<Panel title={item} key={i}>
|
|
||||||
<div className={styles.content}>
|
|
||||||
{sourceData
|
|
||||||
.filter(item => item.type === i)
|
|
||||||
.map((item, i) => {
|
|
||||||
return (
|
|
||||||
<div className={styles.item} key={i}>
|
|
||||||
<a className={styles.imgWrap} href={item.link} title={item.desc}>
|
|
||||||
<img
|
|
||||||
src={
|
|
||||||
item.imgUrl[0]
|
|
||||||
? item.imgUrl[0].url
|
|
||||||
: 'http://io.nainor.com/uploads/01_173e15d3493.png'
|
|
||||||
}
|
|
||||||
alt={item.title}
|
|
||||||
/>
|
|
||||||
<div className={styles.title} style={{ fontSize, color }}>
|
|
||||||
{item.title}
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</Panel>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default XTab;
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
import {
|
|
||||||
IColorConfigType,
|
|
||||||
IDataListConfigType,
|
|
||||||
IMutiTextConfigType,
|
|
||||||
INumberConfigType,
|
|
||||||
TColorDefaultType,
|
|
||||||
TDataListDefaultType,
|
|
||||||
TMutiTextDefaultType,
|
|
||||||
TNumberDefaultType,
|
|
||||||
} from '@/components/PanelComponents/FormEditor/types';
|
|
||||||
|
|
||||||
export type TTabEditData = Array<
|
|
||||||
IMutiTextConfigType | IColorConfigType | INumberConfigType | IDataListConfigType
|
|
||||||
>;
|
|
||||||
export interface ITabConfig {
|
|
||||||
tabs: TMutiTextDefaultType;
|
|
||||||
color: TColorDefaultType;
|
|
||||||
activeColor: TColorDefaultType;
|
|
||||||
fontSize: TNumberDefaultType;
|
|
||||||
imgSize: TNumberDefaultType;
|
|
||||||
sourceData: TDataListDefaultType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ITabSchema {
|
|
||||||
editData: TTabEditData;
|
|
||||||
config: ITabConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Tab: ITabSchema = {
|
|
||||||
editData: [
|
|
||||||
{
|
|
||||||
key: 'tabs',
|
|
||||||
name: '项目类别',
|
|
||||||
type: 'MutiText',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'activeColor',
|
|
||||||
name: '激活颜色',
|
|
||||||
type: 'Color',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'color',
|
|
||||||
name: '文字颜色',
|
|
||||||
type: 'Color',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fontSize',
|
|
||||||
name: '文字大小',
|
|
||||||
type: 'Number',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'imgSize',
|
|
||||||
name: '图片大小',
|
|
||||||
type: 'Number',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'sourceData',
|
|
||||||
name: '数据源',
|
|
||||||
type: 'DataList',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
config: {
|
|
||||||
tabs: ['类别一', '类别二'],
|
|
||||||
color: 'rgba(153,153,153,1)',
|
|
||||||
activeColor: 'rgba(0,102,204,1)',
|
|
||||||
fontSize: 16,
|
|
||||||
imgSize: 100,
|
|
||||||
sourceData: [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
title: '趣谈小课1',
|
|
||||||
desc: '致力于打造优质小课程',
|
|
||||||
link: 'xxxxx',
|
|
||||||
type: 0,
|
|
||||||
imgUrl: [
|
|
||||||
{
|
|
||||||
uid: '001',
|
|
||||||
name: 'image.png',
|
|
||||||
status: 'done',
|
|
||||||
url: 'http://io.nainor.com/uploads/1_1740c6fbcd9.png',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
title: '趣谈小课2',
|
|
||||||
desc: '致力于打造优质小课程',
|
|
||||||
link: 'xxxxx',
|
|
||||||
type: 0,
|
|
||||||
imgUrl: [
|
|
||||||
{
|
|
||||||
uid: '001',
|
|
||||||
name: 'image.png',
|
|
||||||
status: 'done',
|
|
||||||
url: 'http://io.nainor.com/uploads/2_1740c7033a9.png',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3',
|
|
||||||
title: '趣谈小课3',
|
|
||||||
desc: '致力于打造优质小课程',
|
|
||||||
link: 'xxxxx',
|
|
||||||
type: 1,
|
|
||||||
imgUrl: [
|
|
||||||
{
|
|
||||||
uid: '001',
|
|
||||||
name: 'image.png',
|
|
||||||
status: 'done',
|
|
||||||
url: 'http://io.nainor.com/uploads/1_1740c6fbcd9.png',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Tab;
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
const template = {
|
|
||||||
type: 'Tab',
|
|
||||||
h: 130,
|
|
||||||
};
|
|
||||||
export default template;
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import Carousel from './Carousel/schema';
|
|
||||||
import Footer from './Footer/schema';
|
|
||||||
import Form from './Form/schema';
|
|
||||||
import Header from './Header/schema';
|
|
||||||
import Icon from './Icon/schema';
|
|
||||||
import Image from './Image/schema';
|
|
||||||
import List from './List/schema';
|
|
||||||
import LongText from './LongText/schema';
|
|
||||||
import Notice from './Notice/schema';
|
|
||||||
import Qrcode from './Qrcode/schema';
|
|
||||||
import Tab from './Tab/schema';
|
|
||||||
import Text from './Text/schema';
|
|
||||||
|
|
||||||
const basicSchema = {
|
|
||||||
Carousel,
|
|
||||||
Footer,
|
|
||||||
Form,
|
|
||||||
Header,
|
|
||||||
Icon,
|
|
||||||
Image,
|
|
||||||
List,
|
|
||||||
LongText,
|
|
||||||
Notice,
|
|
||||||
Qrcode,
|
|
||||||
Tab,
|
|
||||||
Text,
|
|
||||||
};
|
|
||||||
export default basicSchema;
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
import Carousel from './Carousel/template';
|
|
||||||
import Footer from './Footer/template';
|
|
||||||
import Form from './Form/template';
|
|
||||||
import Header from './Header/template';
|
|
||||||
import Icon from './Icon/template';
|
|
||||||
import Image from './Image/template';
|
|
||||||
import List from './List/template';
|
|
||||||
import LongText from './LongText/template';
|
|
||||||
import Notice from './Notice/template';
|
|
||||||
import Qrcode from './Qrcode/template';
|
|
||||||
import Tab from './Tab/template';
|
|
||||||
import Text from './Text/template';
|
|
||||||
|
|
||||||
const basicTemplate = [
|
|
||||||
Carousel,
|
|
||||||
Footer,
|
|
||||||
Form,
|
|
||||||
Header,
|
|
||||||
Icon,
|
|
||||||
Image,
|
|
||||||
List,
|
|
||||||
LongText,
|
|
||||||
Notice,
|
|
||||||
Qrcode,
|
|
||||||
Tab,
|
|
||||||
Text,
|
|
||||||
];
|
|
||||||
const BasicTemplate = basicTemplate.map(v => {
|
|
||||||
return { ...v, category: 'base' };
|
|
||||||
});
|
|
||||||
|
|
||||||
export default BasicTemplate;
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
.carousel__item__pic {
|
|
||||||
display: inline-block;
|
|
||||||
width: 100%;
|
|
||||||
max-height: 220px;
|
|
||||||
overflow: hidden;
|
|
||||||
vertical-align: top;
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
import React, { memo, PropsWithChildren } from 'react';
|
|
||||||
import { Carousel } from 'zarm';
|
|
||||||
import styles from './index.less';
|
|
||||||
import { ICarouselConfig } from './schema';
|
|
||||||
|
|
||||||
interface CarouselTypes extends ICarouselConfig {
|
|
||||||
isTpl: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const XCarousel = memo((props: PropsWithChildren<CarouselTypes>) => {
|
|
||||||
const { direction, swipeable, autoPlay, isTpl, imgList, tplImg } = props;
|
|
||||||
const contentRender = () => {
|
|
||||||
return imgList.map((item, i) => {
|
|
||||||
return (
|
|
||||||
<div className={styles.carousel__item__pic} key={+i}>
|
|
||||||
<img src={item.imgUrl.length > 0 ? item.imgUrl[0].url : ''} alt="" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div style={{ width: '100%', overflow: 'hidden' }}>
|
|
||||||
{isTpl ? (
|
|
||||||
<div className={styles.carousel__item__pic}>
|
|
||||||
<img src={tplImg} alt="" />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Carousel
|
|
||||||
onChange={index => {
|
|
||||||
// console.log(`onChange: ${index}`);
|
|
||||||
}}
|
|
||||||
direction={direction}
|
|
||||||
swipeable={swipeable}
|
|
||||||
autoPlay={autoPlay}
|
|
||||||
loop
|
|
||||||
>
|
|
||||||
{contentRender()}
|
|
||||||
</Carousel>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default XCarousel;
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
import {
|
|
||||||
IDataListConfigType,
|
|
||||||
IRadioConfigType,
|
|
||||||
ISwitchConfigType,
|
|
||||||
TDataListDefaultType,
|
|
||||||
TRadioDefaultType,
|
|
||||||
TSwitchDefaultType,
|
|
||||||
} from '@/components/PanelComponents/FormEditor/types';
|
|
||||||
|
|
||||||
export type CarouselDirectionKeyType = 'down' | 'left';
|
|
||||||
|
|
||||||
export type TCarouselEditData = Array<
|
|
||||||
IRadioConfigType<CarouselDirectionKeyType> | ISwitchConfigType | IDataListConfigType
|
|
||||||
>;
|
|
||||||
export interface ICarouselConfig {
|
|
||||||
direction: TRadioDefaultType<CarouselDirectionKeyType>;
|
|
||||||
swipeable: TSwitchDefaultType;
|
|
||||||
autoPlay: TSwitchDefaultType;
|
|
||||||
imgList: TDataListDefaultType;
|
|
||||||
tplImg: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ICarouselSchema {
|
|
||||||
editData: TCarouselEditData;
|
|
||||||
config: ICarouselConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Carousel: ICarouselSchema = {
|
|
||||||
editData: [
|
|
||||||
{
|
|
||||||
key: 'direction',
|
|
||||||
name: '方向',
|
|
||||||
type: 'Radio',
|
|
||||||
range: [
|
|
||||||
{
|
|
||||||
key: 'down',
|
|
||||||
text: '从上到下',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'left',
|
|
||||||
text: '从左到右',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'swipeable',
|
|
||||||
name: '是否可拖拽',
|
|
||||||
type: 'Switch',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'autoPlay',
|
|
||||||
name: '是否自动播放',
|
|
||||||
type: 'Switch',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'imgList',
|
|
||||||
name: '图片列表',
|
|
||||||
type: 'DataList',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
config: {
|
|
||||||
direction: 'left',
|
|
||||||
swipeable: false,
|
|
||||||
autoPlay: false,
|
|
||||||
imgList: [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
title: '趣谈小课1',
|
|
||||||
desc: '致力于打造优质小课程',
|
|
||||||
link: 'xxxxx',
|
|
||||||
imgUrl: [
|
|
||||||
{
|
|
||||||
uid: '001',
|
|
||||||
name: 'image.png',
|
|
||||||
status: 'done',
|
|
||||||
url: 'http://io.nainor.com/uploads/1_1740bd7c3dc.png',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
title: '趣谈小课1',
|
|
||||||
desc: '致力于打造优质小课程',
|
|
||||||
link: 'xxxxx',
|
|
||||||
imgUrl: [
|
|
||||||
{
|
|
||||||
uid: '001',
|
|
||||||
name: 'image.png',
|
|
||||||
status: 'done',
|
|
||||||
url: 'http://io.nainor.com/uploads/2_1740bd8d525.png',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
tplImg: 'http://io.nainor.com/uploads/carousal_17442e1420f.png',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
export default Carousel;
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
const template = {
|
|
||||||
type: 'Carousel',
|
|
||||||
h: 82,
|
|
||||||
};
|
|
||||||
export default template;
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
import { Input, Cell, DateSelect, Radio, Select } from 'zarm';
|
|
||||||
import styles from './baseForm.less';
|
|
||||||
import React from 'react';
|
|
||||||
import {
|
|
||||||
baseFormDateTpl,
|
|
||||||
baseFormMyRadioTpl,
|
|
||||||
baseFormMySelectTpl,
|
|
||||||
baseFormNumberTpl,
|
|
||||||
baseFormTextAreaTpl,
|
|
||||||
baseFormTextTpl,
|
|
||||||
baseFormUnionType,
|
|
||||||
} from '@/components/PanelComponents/FormEditor/types';
|
|
||||||
// 维护表单控件, 提高form渲染性能
|
|
||||||
|
|
||||||
type TBaseForm = {
|
|
||||||
[key in baseFormUnionType]: any;
|
|
||||||
};
|
|
||||||
|
|
||||||
const BaseForm: TBaseForm = {
|
|
||||||
Text: (props: baseFormTextTpl & { onChange: (v: string | undefined) => void }) => {
|
|
||||||
const { label, placeholder, onChange } = props;
|
|
||||||
return (
|
|
||||||
<Cell title={label}>
|
|
||||||
<Input clearable type="text" placeholder={placeholder} onChange={onChange} />
|
|
||||||
</Cell>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Textarea: (props: baseFormTextAreaTpl & { onChange: (v: string | undefined) => void }) => {
|
|
||||||
const { label, placeholder, onChange } = props;
|
|
||||||
return (
|
|
||||||
<Cell title={label}>
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
rows={3}
|
|
||||||
autoHeight
|
|
||||||
showLength
|
|
||||||
placeholder={placeholder}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
</Cell>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Number: (props: baseFormNumberTpl & { onChange: (v: string | undefined | number) => void }) => {
|
|
||||||
const { label, placeholder, onChange } = props;
|
|
||||||
return (
|
|
||||||
<Cell title={label}>
|
|
||||||
<Input type="number" placeholder={placeholder} onChange={onChange} />
|
|
||||||
</Cell>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
MyRadio: (props: baseFormMyRadioTpl & { onChange: (v: string | undefined | number) => void }) => {
|
|
||||||
const { label, options, onChange } = props;
|
|
||||||
return (
|
|
||||||
<div className={styles.radioWrap}>
|
|
||||||
<div className={styles.radioTitle}>{label}</div>
|
|
||||||
<Cell>
|
|
||||||
<Radio.Group onChange={onChange}>
|
|
||||||
{options.map((item, i) => {
|
|
||||||
return (
|
|
||||||
<Radio value={item.value} key={i} className={styles.radioItem}>
|
|
||||||
{item.label}
|
|
||||||
</Radio>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Radio.Group>
|
|
||||||
</Cell>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Date: (props: baseFormDateTpl & { onChange: (v: Date) => void }) => {
|
|
||||||
const { label, placeholder, onChange } = props;
|
|
||||||
return (
|
|
||||||
<Cell title={label}>
|
|
||||||
<DateSelect
|
|
||||||
placeholder={placeholder}
|
|
||||||
mode="date"
|
|
||||||
min="1949-05-15"
|
|
||||||
max="2100-05-15"
|
|
||||||
onOk={onChange}
|
|
||||||
/>
|
|
||||||
</Cell>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
MySelect: (
|
|
||||||
props: baseFormMySelectTpl & { onChange: ((v: Record<string, any>) => void) | undefined },
|
|
||||||
) => {
|
|
||||||
const { label, options, onChange } = props;
|
|
||||||
return (
|
|
||||||
<Cell title={label}>
|
|
||||||
<Select dataSource={options} onOk={onChange} />
|
|
||||||
</Cell>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BaseForm;
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
.radioWrap {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
.radioTitle {
|
|
||||||
padding: 19px 14px;
|
|
||||||
// font-size: 15px;
|
|
||||||
}
|
|
||||||
.radioItem {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
.formWrap {
|
|
||||||
margin: 10px;
|
|
||||||
padding: 20px 16px;
|
|
||||||
border-radius: 6px;
|
|
||||||
background-color: #fff;
|
|
||||||
box-shadow: 0 2px 6px #f0f0f0;
|
|
||||||
.title {
|
|
||||||
padding-bottom: 20px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
.formContent {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
import React, { memo, useCallback } from 'react';
|
|
||||||
import { Button } from 'zarm';
|
|
||||||
import BaseForm from './BaseForm';
|
|
||||||
import styles from './index.less';
|
|
||||||
import { IFormConfig } from './schema';
|
|
||||||
|
|
||||||
const FormComponent = (props: IFormConfig) => {
|
|
||||||
const { title, bgColor, fontSize, titColor, btnColor, btnTextColor, api, formControls } = props;
|
|
||||||
const formData: Record<string, any> = {};
|
|
||||||
const handleChange = useCallback(
|
|
||||||
(item, v) => {
|
|
||||||
if (item.options) {
|
|
||||||
formData[item.label] = v[0].label;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
formData[item.label] = v;
|
|
||||||
},
|
|
||||||
[formData],
|
|
||||||
);
|
|
||||||
const handleSubmit = () => {
|
|
||||||
if (api) {
|
|
||||||
fetch(api, {
|
|
||||||
body: JSON.stringify(formData),
|
|
||||||
cache: 'no-cache',
|
|
||||||
headers: {
|
|
||||||
'content-type': 'application/json',
|
|
||||||
},
|
|
||||||
method: 'POST',
|
|
||||||
mode: 'cors',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div className={styles.formWrap} style={{ backgroundColor: bgColor }}>
|
|
||||||
{title && (
|
|
||||||
<div className={styles.title} style={{ fontSize, color: titColor }}>
|
|
||||||
{title}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className={styles.formContent}>
|
|
||||||
{formControls.map(item => {
|
|
||||||
const FormItem = BaseForm[item.type];
|
|
||||||
return <FormItem onChange={handleChange.bind(this, item)} {...item} key={item.id} />;
|
|
||||||
})}
|
|
||||||
<div style={{ textAlign: 'center', padding: '16px 0' }}>
|
|
||||||
<Button
|
|
||||||
theme="primary"
|
|
||||||
size="sm"
|
|
||||||
block
|
|
||||||
onClick={handleSubmit}
|
|
||||||
style={{ backgroundColor: btnColor, borderColor: btnColor, color: btnTextColor }}
|
|
||||||
>
|
|
||||||
提交
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(FormComponent);
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
import {
|
|
||||||
IColorConfigType,
|
|
||||||
IFormItemsConfigType,
|
|
||||||
INumberConfigType,
|
|
||||||
ITextConfigType,
|
|
||||||
TColorDefaultType,
|
|
||||||
TFormItemsDefaultType,
|
|
||||||
TNumberDefaultType,
|
|
||||||
TTextDefaultType,
|
|
||||||
} from '@/components/PanelComponents/FormEditor/types';
|
|
||||||
|
|
||||||
export type TFormEditData = Array<
|
|
||||||
ITextConfigType | INumberConfigType | IColorConfigType | ITextConfigType | IFormItemsConfigType
|
|
||||||
>;
|
|
||||||
export interface IFormConfig {
|
|
||||||
title: TTextDefaultType;
|
|
||||||
fontSize: TNumberDefaultType;
|
|
||||||
titColor: TColorDefaultType;
|
|
||||||
bgColor: TColorDefaultType;
|
|
||||||
btnColor: TColorDefaultType;
|
|
||||||
btnTextColor: TColorDefaultType;
|
|
||||||
api: TTextDefaultType;
|
|
||||||
formControls: TFormItemsDefaultType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IFormSchema {
|
|
||||||
editData: TFormEditData;
|
|
||||||
config: IFormConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Form: IFormSchema = {
|
|
||||||
editData: [
|
|
||||||
{
|
|
||||||
key: 'title',
|
|
||||||
name: '标题',
|
|
||||||
type: 'Text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fontSize',
|
|
||||||
name: '标题大小',
|
|
||||||
type: 'Number',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'titColor',
|
|
||||||
name: '标题颜色',
|
|
||||||
type: 'Color',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'bgColor',
|
|
||||||
name: '背景色',
|
|
||||||
type: 'Color',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'btnColor',
|
|
||||||
name: '按钮颜色',
|
|
||||||
type: 'Color',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'btnTextColor',
|
|
||||||
name: '按钮文本颜色',
|
|
||||||
type: 'Color',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'api',
|
|
||||||
name: '表单Api地址',
|
|
||||||
type: 'Text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'formControls',
|
|
||||||
name: '表单控件',
|
|
||||||
type: 'FormItems',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
config: {
|
|
||||||
title: '表单定制组件',
|
|
||||||
fontSize: 18,
|
|
||||||
titColor: 'rgba(60,60,60,1)',
|
|
||||||
bgColor: 'rgba(255,255,255,1)',
|
|
||||||
btnColor: 'rgba(129,173,173,1)',
|
|
||||||
btnTextColor: 'rgba(255,255,255,1)',
|
|
||||||
api: '',
|
|
||||||
formControls: [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
type: 'Text',
|
|
||||||
label: '姓名',
|
|
||||||
placeholder: '请输入姓名',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
type: 'Number',
|
|
||||||
label: '年龄',
|
|
||||||
placeholder: ' 请输入年龄',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4',
|
|
||||||
type: 'MySelect',
|
|
||||||
label: '爱好',
|
|
||||||
options: [
|
|
||||||
{ label: '篮球', value: '1' },
|
|
||||||
{ label: '乒乓球', value: '2' },
|
|
||||||
{ label: '健身', value: '3' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
export default Form;
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
const template = {
|
|
||||||
type: 'Form',
|
|
||||||
h: 172,
|
|
||||||
};
|
|
||||||
export default template;
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
import React, { memo } from 'react';
|
|
||||||
import { Progress } from 'zarm';
|
|
||||||
import styles from './index.less';
|
|
||||||
import { IXProgressConfig } from './schema';
|
|
||||||
|
|
||||||
const XProgress = memo((props: IXProgressConfig) => {
|
|
||||||
const { theme, size, shape, percent, strokeWidth } = props;
|
|
||||||
return (
|
|
||||||
<div className={styles.textWrap} style={{ textAlign: 'center' }}>
|
|
||||||
<Progress
|
|
||||||
shape={shape}
|
|
||||||
size={size}
|
|
||||||
percent={percent}
|
|
||||||
theme={theme}
|
|
||||||
strokeWidth={strokeWidth}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default XProgress;
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
import {
|
|
||||||
INumberConfigType,
|
|
||||||
IRadioConfigType,
|
|
||||||
ISelectConfigType,
|
|
||||||
TNumberDefaultType,
|
|
||||||
TRadioDefaultType,
|
|
||||||
TSelectDefaultType,
|
|
||||||
} from '@/components/PanelComponents/FormEditor/types';
|
|
||||||
export type TXProgressSelectKeyType = 'success' | 'warning' | 'danger';
|
|
||||||
export type TXProgressRadiotKeyType = 'circle' | 'line' | 'semi-circle';
|
|
||||||
export type TXProgressEditData = Array<
|
|
||||||
| ISelectConfigType<TXProgressSelectKeyType>
|
|
||||||
| IRadioConfigType<TXProgressRadiotKeyType>
|
|
||||||
| INumberConfigType
|
|
||||||
>;
|
|
||||||
export interface IXProgressConfig {
|
|
||||||
theme: TSelectDefaultType<TXProgressSelectKeyType>;
|
|
||||||
shape: TRadioDefaultType<TXProgressRadiotKeyType>;
|
|
||||||
size: TNumberDefaultType;
|
|
||||||
percent: TNumberDefaultType;
|
|
||||||
strokeWidth: TNumberDefaultType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IXProgressSchema {
|
|
||||||
editData: TXProgressEditData;
|
|
||||||
config: IXProgressConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
const XProgress: IXProgressSchema = {
|
|
||||||
editData: [
|
|
||||||
{
|
|
||||||
key: 'theme',
|
|
||||||
name: '主题',
|
|
||||||
type: 'Select',
|
|
||||||
range: [
|
|
||||||
{
|
|
||||||
key: 'success',
|
|
||||||
text: '成功',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'warning',
|
|
||||||
text: '警告',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'danger',
|
|
||||||
text: '危险',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'shape',
|
|
||||||
name: '形状',
|
|
||||||
type: 'Radio',
|
|
||||||
range: [
|
|
||||||
{
|
|
||||||
key: 'circle',
|
|
||||||
text: '圆形',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'line',
|
|
||||||
text: '线形',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'semi-circle',
|
|
||||||
text: '半圆形',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'size',
|
|
||||||
name: '大小',
|
|
||||||
type: 'Number',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'percent',
|
|
||||||
name: '进度值',
|
|
||||||
type: 'Number',
|
|
||||||
range: [0, 100],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'strokeWidth',
|
|
||||||
name: '线条粗细',
|
|
||||||
type: 'Number',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
config: {
|
|
||||||
theme: 'success',
|
|
||||||
shape: 'circle',
|
|
||||||
size: 200,
|
|
||||||
percent: 30,
|
|
||||||
strokeWidth: 10,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default XProgress;
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
const template = {
|
|
||||||
type: 'XProgress',
|
|
||||||
h: 102,
|
|
||||||
};
|
|
||||||
export default template;
|
|
||||||
BIN
src/components/DynamicEngine/.DS_Store
vendored
BIN
src/components/DynamicEngine/.DS_Store
vendored
Binary file not shown.
@ -1,9 +1,8 @@
|
|||||||
import { dynamic } from 'umi';
|
import { dynamic } from 'umi';
|
||||||
import Loading from '../LoadingCp';
|
import Loading from '../components/LoadingCp';
|
||||||
import { useMemo, memo, FC, useContext } from 'react';
|
import { useMemo, memo, FC, useContext } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { dooringContext, dooringContextType } from '@/layouts';
|
import { dooringContext, dooringContextType } from '@/layouts';
|
||||||
// import { AllTemplateType } from './schema';
|
|
||||||
|
|
||||||
export type componentsType = 'media' | 'base' | 'visible';
|
export type componentsType = 'media' | 'base' | 'visible';
|
||||||
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { useState, useEffect, memo } from 'react';
|
import { useState, useEffect, memo } from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import Icon from '../../BasicShop/BasicComponents/Icon';
|
import Icon from '@/components/BasicShop/BasicComponents/Icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IconTypes } from '@/components/BasicShop/BasicComponents/Icon/schema';
|
import { IconTypes } from '@/components/BasicShop/BasicComponents/Icon/schema';
|
||||||
import { ICardPickerConfigType } from '../FormEditor/types';
|
import { ICardPickerConfigType } from '../types';
|
||||||
|
|
||||||
interface CardPickerType extends Omit<ICardPickerConfigType<IconTypes>, 'type' | 'key' | 'name'> {
|
interface CardPickerType extends Omit<ICardPickerConfigType<IconTypes>, 'type' | 'key' | 'name'> {
|
||||||
onChange?: (v: string) => void;
|
onChange?: (v: string) => void;
|
||||||
@ -18,7 +18,7 @@ import { HTML5Backend } from 'react-dnd-html5-backend';
|
|||||||
import EditorModal from './editorModal';
|
import EditorModal from './editorModal';
|
||||||
import { uuid } from '@/utils/tool';
|
import { uuid } from '@/utils/tool';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import { TDataListDefaultType, TDataListDefaultTypeItem } from '../FormEditor/types';
|
import { TDataListDefaultType, TDataListDefaultTypeItem } from '../types';
|
||||||
|
|
||||||
type ListItemProps = DndItemProps & {
|
type ListItemProps = DndItemProps & {
|
||||||
isDragging: boolean;
|
isDragging: boolean;
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import React, { FC, memo, useEffect } from 'react';
|
import React, { FC, memo, useEffect } from 'react';
|
||||||
import { Form, Select, Input, Modal, Button, InputNumber } from 'antd';
|
import { Form, Select, Input, Modal, Button, InputNumber } from 'antd';
|
||||||
import { baseFormOptionsType } from '../FormEditor/types';
|
import { baseFormOptionsType } from '../types';
|
||||||
import Color from '../Color';
|
import Color from '../Color';
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import React, { memo, RefObject, useCallback, useEffect, useState } from 'react';
|
import React, { memo, RefObject, useCallback, useEffect, useState } from 'react';
|
||||||
import BaseForm from '../../BasicShop/BasicComponents/Form/BaseForm';
|
import BaseForm from '@/components/BasicShop/BasicComponents/Form/BaseForm';
|
||||||
import BasePopoverForm from '../../BasicShop/BasicComponents/Form/BasePopoverForm';
|
import BasePopoverForm from '@/components/BasicShop/BasicComponents/Form/BasePopoverForm';
|
||||||
import EditorModal from './EditorModal';
|
import EditorModal from './EditorModal';
|
||||||
import { MinusCircleFilled, EditFilled, PlusOutlined } from '@ant-design/icons';
|
import { MinusCircleFilled, EditFilled, PlusOutlined } from '@ant-design/icons';
|
||||||
import styles from './formItems.less';
|
import styles from './formItems.less';
|
||||||
import { baseFormUnion, TFormItemsDefaultType } from '../FormEditor/types';
|
import { baseFormUnion, TFormItemsDefaultType } from '../types';
|
||||||
import { uuid } from '@/utils/tool';
|
import { uuid } from '@/utils/tool';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import MyPopover from 'yh-react-popover';
|
import MyPopover from 'yh-react-popover';
|
||||||
@ -2,7 +2,7 @@ import React, { memo, useEffect } from 'react';
|
|||||||
import { Input, Button, Popconfirm } from 'antd';
|
import { Input, Button, Popconfirm } from 'antd';
|
||||||
import { MinusCircleFilled } from '@ant-design/icons';
|
import { MinusCircleFilled } from '@ant-design/icons';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import { TMutiTextDefaultType } from '../FormEditor/types';
|
import { TMutiTextDefaultType } from '../types';
|
||||||
|
|
||||||
type MultiTextProps = {
|
type MultiTextProps = {
|
||||||
onChange?: (v: TMutiTextDefaultType) => void;
|
onChange?: (v: TMutiTextDefaultType) => void;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import React, { memo, useState, useEffect } from 'react';
|
import React, { memo, useState, useEffect } from 'react';
|
||||||
import { InputNumber } from 'antd';
|
import { InputNumber } from 'antd';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import { TPosDefaultType, TPosItem } from '../FormEditor/types';
|
import { TPosDefaultType, TPosItem } from '../types';
|
||||||
|
|
||||||
type PosProps = {
|
type PosProps = {
|
||||||
value?: TPosDefaultType;
|
value?: TPosDefaultType;
|
||||||
@ -27,11 +27,10 @@ const controls = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export default memo(function XEditor(props: any) {
|
export default memo(function XEditor(props: any) {
|
||||||
const [editorState, setEditorState] = useState(BraftEditor.createEditorState());
|
|
||||||
|
|
||||||
const { value, onChange } = props;
|
const { value, onChange } = props;
|
||||||
|
const [editorState, setEditorState] = useState(BraftEditor.createEditorState(value));
|
||||||
|
|
||||||
const myUploadFn = param => {
|
const myUploadFn = (param: any) => {
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append('file', param.file);
|
fd.append('file', param.file);
|
||||||
|
|
||||||
@ -46,8 +45,7 @@ export default memo(function XEditor(props: any) {
|
|||||||
param.progress((event.loaded / event.total) * 100);
|
param.progress((event.loaded / event.total) * 100);
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then((res: any) => {
|
||||||
console.log(res);
|
|
||||||
// 上传成功后调用param.success并传入上传后的文件地址
|
// 上传成功后调用param.success并传入上传后的文件地址
|
||||||
param.success({
|
param.success({
|
||||||
url: res.url,
|
url: res.url,
|
||||||
@ -1,16 +1,15 @@
|
|||||||
import React, { memo, RefObject, useEffect } from 'react';
|
import React, { memo, RefObject, useEffect } from 'react';
|
||||||
import { Form, Select, InputNumber, Input, Switch, Radio, Button } from 'antd';
|
import { Form, Select, InputNumber, Input, Switch, Radio } from 'antd';
|
||||||
import Upload from '../Upload';
|
import Upload from './FormComponents/Upload';
|
||||||
import DataList from '../DataList';
|
import DataList from './FormComponents/DataList';
|
||||||
import MutiText from '../MutiText';
|
import MutiText from './FormComponents/MutiText';
|
||||||
import Color from '../Color';
|
import Color from './FormComponents/Color';
|
||||||
import CardPicker from '../CardPicker';
|
import CardPicker from './FormComponents/CardPicker';
|
||||||
import Table from '../Table';
|
import Table from './FormComponents/Table';
|
||||||
import Pos from '../Pos';
|
import Pos from './FormComponents/Pos';
|
||||||
import { Store } from 'antd/lib/form/interface';
|
import { Store } from 'antd/lib/form/interface';
|
||||||
import RichText from '../XEditor';
|
import RichText from './FormComponents/XEditor';
|
||||||
import FormItems from '../FormItems';
|
import FormItems from './FormComponents/FormItems';
|
||||||
// import styles from './index.less';
|
|
||||||
const normFile = (e: any) => {
|
const normFile = (e: any) => {
|
||||||
console.log('Upload event:', e);
|
console.log('Upload event:', e);
|
||||||
if (Array.isArray(e)) {
|
if (Array.isArray(e)) {
|
||||||
50
src/core/ViewRender.tsx
Normal file
50
src/core/ViewRender.tsx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import React, { memo } from 'react';
|
||||||
|
import GridLayout, { ItemCallback } from 'react-grid-layout';
|
||||||
|
import DynamicEngine from '@/core/DynamicEngine';
|
||||||
|
import styles from './viewRender.less';
|
||||||
|
|
||||||
|
interface PointDataItem {
|
||||||
|
id: string;
|
||||||
|
item: Record<string, any>;
|
||||||
|
point: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ViewProps {
|
||||||
|
pointData: Array<PointDataItem>;
|
||||||
|
pageData?: any;
|
||||||
|
width?: number;
|
||||||
|
dragStop?: ItemCallback;
|
||||||
|
onDragStart?: ItemCallback;
|
||||||
|
onResizeStop?: ItemCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ViewRender = memo((props: ViewProps) => {
|
||||||
|
const { pointData, pageData, width, dragStop, onDragStart, onResizeStop } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GridLayout
|
||||||
|
cols={24}
|
||||||
|
rowHeight={2}
|
||||||
|
width={width}
|
||||||
|
margin={[0, 0]}
|
||||||
|
onDragStop={dragStop}
|
||||||
|
onDragStart={onDragStart}
|
||||||
|
onResizeStop={onResizeStop}
|
||||||
|
style={{
|
||||||
|
backgroundColor: pageData && pageData.bgColor,
|
||||||
|
backgroundImage:
|
||||||
|
pageData && pageData.bgImage ? `url(${pageData.bgImage[0].url})` : 'initial',
|
||||||
|
backgroundSize: 'contain',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{pointData.map((value: PointDataItem) => (
|
||||||
|
<div key={value.id} data-grid={value.point} className={styles.dragItem}>
|
||||||
|
<DynamicEngine {...(value.item as any)} isTpl={false} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</GridLayout>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ViewRender;
|
||||||
14
src/core/viewRender.less
Normal file
14
src/core/viewRender.less
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
.dragItem {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
cursor: move;
|
||||||
|
&:hover {
|
||||||
|
border: 2px solid #06c;
|
||||||
|
}
|
||||||
|
:global(a) {
|
||||||
|
display: block;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect, useMemo, useCallback, useContext, useRef } from 'react';
|
import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react';
|
||||||
import { Result, Tabs, Button } from 'antd';
|
import { Result, Tabs } from 'antd';
|
||||||
import {
|
import {
|
||||||
PieChartOutlined,
|
PieChartOutlined,
|
||||||
PlayCircleOutlined,
|
PlayCircleOutlined,
|
||||||
@ -13,8 +13,8 @@ import CanvasControl from './components/CanvasControl';
|
|||||||
import SourceBox from './SourceBox';
|
import SourceBox from './SourceBox';
|
||||||
import TargetBox from './TargetBox';
|
import TargetBox from './TargetBox';
|
||||||
import Calibration from 'components/Calibration';
|
import Calibration from 'components/Calibration';
|
||||||
import DynamicEngine, { componentsType } from 'components/DynamicEngine';
|
import DynamicEngine, { componentsType } from '@/core/DynamicEngine';
|
||||||
import FormEditor from 'components/PanelComponents/FormEditor';
|
import FormRender from '@/core/FormRender';
|
||||||
|
|
||||||
import template from 'components/BasicShop/BasicComponents/template';
|
import template from 'components/BasicShop/BasicComponents/template';
|
||||||
import mediaTpl from 'components/BasicShop/MediaComponents/template';
|
import mediaTpl from 'components/BasicShop/MediaComponents/template';
|
||||||
@ -22,7 +22,6 @@ import graphTpl from 'components/BasicShop/VisualComponents/template';
|
|||||||
|
|
||||||
import schemaH5 from 'components/BasicShop/schema';
|
import schemaH5 from 'components/BasicShop/schema';
|
||||||
import { ActionCreators, StateWithHistory } from 'redux-undo';
|
import { ActionCreators, StateWithHistory } from 'redux-undo';
|
||||||
import { dooringContext } from '@/layouts';
|
|
||||||
import { throttle } from '@/utils/tool';
|
import { throttle } from '@/utils/tool';
|
||||||
|
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
@ -53,7 +52,6 @@ const Container = (props: {
|
|||||||
setRightColla(c);
|
setRightColla(c);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
const context = useContext(dooringContext);
|
|
||||||
const curPoint = pstate ? pstate.curPoint : {};
|
const curPoint = pstate ? pstate.curPoint : {};
|
||||||
|
|
||||||
// 指定画布的id
|
// 指定画布的id
|
||||||
@ -91,48 +89,26 @@ const Container = (props: {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleFormSave = useMemo(() => {
|
const handleFormSave = useMemo(() => {
|
||||||
if (context.theme === 'h5') {
|
|
||||||
return (data: any) => {
|
return (data: any) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'editorModal/modPointData',
|
type: 'editorModal/modPointData',
|
||||||
payload: { ...curPoint, item: { ...curPoint.item, config: data } },
|
payload: { ...curPoint, item: { ...curPoint.item, config: data } },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
} else {
|
}, [curPoint, dispatch]);
|
||||||
return (data: any) => {
|
|
||||||
dispatch({
|
|
||||||
type: 'editorPcModal/modPointData',
|
|
||||||
payload: { ...curPoint, item: { ...curPoint.item, config: data } },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [context.theme, curPoint, dispatch]);
|
|
||||||
|
|
||||||
const clearData = useCallback(() => {
|
const clearData = useCallback(() => {
|
||||||
if (context.theme === 'h5') {
|
|
||||||
dispatch({ type: 'editorModal/clearAll' });
|
dispatch({ type: 'editorModal/clearAll' });
|
||||||
} else {
|
}, [dispatch]);
|
||||||
dispatch({ type: 'editorPcModal/clearAll' });
|
|
||||||
}
|
|
||||||
}, [context.theme, dispatch]);
|
|
||||||
|
|
||||||
const handleDel = useMemo(() => {
|
const handleDel = useMemo(() => {
|
||||||
if (context.theme === 'h5') {
|
|
||||||
return (id: any) => {
|
return (id: any) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'editorModal/delPointData',
|
type: 'editorModal/delPointData',
|
||||||
payload: { id },
|
payload: { id },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
} else {
|
}, [dispatch]);
|
||||||
return (id: any) => {
|
|
||||||
dispatch({
|
|
||||||
type: 'editorPcModal/delPointData',
|
|
||||||
payload: { id },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [context.theme, dispatch]);
|
|
||||||
|
|
||||||
const redohandler = useMemo(() => {
|
const redohandler = useMemo(() => {
|
||||||
return () => {
|
return () => {
|
||||||
@ -184,7 +160,6 @@ const Container = (props: {
|
|||||||
|
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const renderRight = useMemo(() => {
|
const renderRight = useMemo(() => {
|
||||||
if (context.theme === 'h5') {
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@ -197,7 +172,7 @@ const Container = (props: {
|
|||||||
{pointData.length && curPoint ? (
|
{pointData.length && curPoint ? (
|
||||||
<>
|
<>
|
||||||
<div className={styles.tit}>属性设置</div>
|
<div className={styles.tit}>属性设置</div>
|
||||||
<FormEditor
|
<FormRender
|
||||||
config={curPoint.item.editableEl}
|
config={curPoint.item.editableEl}
|
||||||
uid={curPoint.id}
|
uid={curPoint.id}
|
||||||
defaultValue={curPoint.item.config}
|
defaultValue={curPoint.item.config}
|
||||||
@ -208,57 +183,12 @@ const Container = (props: {
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ paddingTop: '100px' }}>
|
<div style={{ paddingTop: '100px' }}>
|
||||||
<Result
|
<Result status="404" title="还没有数据哦" subTitle="赶快拖拽组件来生成你的H5页面吧~" />
|
||||||
status="404"
|
|
||||||
title="还没有数据哦"
|
|
||||||
subTitle="赶快拖拽组件来生成你的H5页面吧~"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
}, [cpointData.length, curPoint, handleDel, handleFormSave, pointData.length, rightColla]);
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={styles.attrSetting}
|
|
||||||
style={{
|
|
||||||
transition: 'all ease-in-out 0.5s',
|
|
||||||
transform: rightColla ? 'translate(100%,0)' : 'translate(0,0)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{cpointData.length && curPoint ? (
|
|
||||||
<>
|
|
||||||
<div className={styles.tit}>属性设置</div>
|
|
||||||
<FormEditor
|
|
||||||
config={curPoint.item.editableEl}
|
|
||||||
uid={curPoint.id}
|
|
||||||
defaultValue={curPoint.item.config}
|
|
||||||
onSave={handleFormSave}
|
|
||||||
onDel={handleDel}
|
|
||||||
rightPannelRef={ref}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div style={{ paddingTop: '100px' }}>
|
|
||||||
<Result
|
|
||||||
status="404"
|
|
||||||
title="还没有数据哦"
|
|
||||||
subTitle="赶快拖拽组件来生成你的H5页面吧~"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
context.theme,
|
|
||||||
cpointData.length,
|
|
||||||
curPoint,
|
|
||||||
handleDel,
|
|
||||||
handleFormSave,
|
|
||||||
pointData.length,
|
|
||||||
rightColla,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const tabRender = useMemo(() => {
|
const tabRender = useMemo(() => {
|
||||||
if (collapsed) {
|
if (collapsed) {
|
||||||
|
|||||||
@ -1,16 +1,15 @@
|
|||||||
import React, { memo, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
import React, { memo, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { useDrop } from 'react-dnd';
|
import { useDrop } from 'react-dnd';
|
||||||
import Draggable, { DraggableData, DraggableEvent } from 'react-draggable';
|
import Draggable, { DraggableData, DraggableEvent } from 'react-draggable';
|
||||||
import GridLayout, { ItemCallback } from 'react-grid-layout';
|
import { ItemCallback } from 'react-grid-layout';
|
||||||
import { connect } from 'dva';
|
import { connect } from 'dva';
|
||||||
import DynamicEngine from 'components/DynamicEngine';
|
import ViewRender from '@/core/ViewRender';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import { uuid } from '@/utils/tool';
|
import { uuid } from '@/utils/tool';
|
||||||
import { Dispatch } from 'umi';
|
import { Dispatch } from 'umi';
|
||||||
import { StateWithHistory } from 'redux-undo';
|
import { StateWithHistory } from 'redux-undo';
|
||||||
import { Menu, Item, MenuProvider } from 'react-contexify';
|
import { Menu, Item, MenuProvider } from 'react-contexify';
|
||||||
import 'react-contexify/dist/ReactContexify.min.css';
|
import 'react-contexify/dist/ReactContexify.min.css';
|
||||||
import { dooringContext } from '@/layouts';
|
|
||||||
interface SourceBoxProps {
|
interface SourceBoxProps {
|
||||||
pstate: { pointData: { id: string; item: any; point: any; isMenu?: any }[]; curPoint: any };
|
pstate: { pointData: { id: string; item: any; point: any; isMenu?: any }[]; curPoint: any };
|
||||||
cstate: { pointData: { id: string; item: any; point: any }[]; curPoint: any };
|
cstate: { pointData: { id: string; item: any; point: any }[]; curPoint: any };
|
||||||
@ -29,15 +28,12 @@ interface SourceBoxProps {
|
|||||||
|
|
||||||
const SourceBox = memo((props: SourceBoxProps) => {
|
const SourceBox = memo((props: SourceBoxProps) => {
|
||||||
const { pstate, scaleNum, canvasId, allType, dispatch, dragState, setDragState, cstate } = props;
|
const { pstate, scaleNum, canvasId, allType, dispatch, dragState, setDragState, cstate } = props;
|
||||||
const context = useContext(dooringContext);
|
|
||||||
|
|
||||||
let pointData = pstate ? pstate.pointData : [];
|
let pointData = pstate ? pstate.pointData : [];
|
||||||
const cpointData = cstate ? cstate.pointData : [];
|
const cpointData = cstate ? cstate.pointData : [];
|
||||||
|
|
||||||
const [canvasRect, setCanvasRect] = useState<number[]>([]);
|
const [canvasRect, setCanvasRect] = useState<number[]>([]);
|
||||||
const [isShowTip, setIsShowTip] = useState(true);
|
const [isShowTip, setIsShowTip] = useState(true);
|
||||||
// const [clonePointData, setPointData] = useState(pointData);
|
|
||||||
// const [isMenu, setIsMenu] = useState(false);
|
|
||||||
const [{ isOver }, drop] = useDrop({
|
const [{ isOver }, drop] = useDrop({
|
||||||
accept: allType,
|
accept: allType,
|
||||||
drop: (item: { h: number; type: string; x: number }, monitor) => {
|
drop: (item: { h: number; type: string; x: number }, monitor) => {
|
||||||
@ -51,7 +47,6 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
w = item.type === 'Icon' ? 3 : col;
|
w = item.type === 'Icon' ? 3 : col;
|
||||||
// 转换成网格规则的坐标和大小
|
// 转换成网格规则的坐标和大小
|
||||||
let gridY = Math.ceil(y / cellHeight);
|
let gridY = Math.ceil(y / cellHeight);
|
||||||
if (context.theme === 'h5') {
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'editorModal/addPointData',
|
type: 'editorModal/addPointData',
|
||||||
payload: {
|
payload: {
|
||||||
@ -61,24 +56,6 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
status: 'inToCanvas',
|
status: 'inToCanvas',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
dispatch({
|
|
||||||
type: 'editorPcModal/addPointData',
|
|
||||||
payload: {
|
|
||||||
id: uuid(6, 10),
|
|
||||||
item,
|
|
||||||
point: {
|
|
||||||
i: `x-${cpointData.length}`,
|
|
||||||
x: item.x || 0,
|
|
||||||
y: gridY,
|
|
||||||
w,
|
|
||||||
h: item.h,
|
|
||||||
isBounded: true,
|
|
||||||
},
|
|
||||||
status: 'inToCanvas',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
collect: monitor => ({
|
collect: monitor => ({
|
||||||
isOver: monitor.isOver(),
|
isOver: monitor.isOver(),
|
||||||
@ -94,21 +71,8 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
type: 'editorModal/modPointData',
|
type: 'editorModal/modPointData',
|
||||||
payload: { ...curPointData, point: newItem, status: 'inToCanvas' },
|
payload: { ...curPointData, point: newItem, status: 'inToCanvas' },
|
||||||
});
|
});
|
||||||
// if (context.theme === 'h5') {
|
|
||||||
// const curPointData = pointData.filter(item => item.id === newItem.i)[0];
|
|
||||||
// dispatch({
|
|
||||||
// type: 'editorModal/modPointData',
|
|
||||||
// payload: { ...curPointData, point: newItem, status: 'inToCanvas' },
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// const curPointData = cpointData.filter(item => item.id === newItem.i)[0];
|
|
||||||
// dispatch({
|
|
||||||
// type: 'editorPcModal/modPointData',
|
|
||||||
// payload: { ...curPointData, point: newItem, status: 'inToCanvas' },
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
}, [context.theme, cpointData, dispatch, pointData]);
|
}, [cpointData, dispatch, pointData]);
|
||||||
|
|
||||||
const onDragStart: ItemCallback = useMemo(() => {
|
const onDragStart: ItemCallback = useMemo(() => {
|
||||||
return (layout, oldItem, newItem, placeholder, e, element) => {
|
return (layout, oldItem, newItem, placeholder, e, element) => {
|
||||||
@ -117,19 +81,6 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
type: 'editorModal/modPointData',
|
type: 'editorModal/modPointData',
|
||||||
payload: { ...curPointData, status: 'inToCanvas' },
|
payload: { ...curPointData, status: 'inToCanvas' },
|
||||||
});
|
});
|
||||||
// if (context.theme === 'h5') {
|
|
||||||
// const curPointData = pointData.filter(item => item.id === newItem.i)[0];
|
|
||||||
// dispatch({
|
|
||||||
// type: 'editorModal/modPointData',
|
|
||||||
// payload: { ...curPointData, status: 'inToCanvas' },
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// const curPointData = cpointData.filter(item => item.id === newItem.i)[0];
|
|
||||||
// dispatch({
|
|
||||||
// type: 'editorPcModal/modPointData',
|
|
||||||
// payload: { ...curPointData, status: 'inToCanvas' },
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
}, [dispatch, pointData]);
|
}, [dispatch, pointData]);
|
||||||
|
|
||||||
@ -140,32 +91,9 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
type: 'editorModal/modPointData',
|
type: 'editorModal/modPointData',
|
||||||
payload: { ...curPointData, point: newItem, status: 'inToCanvas' },
|
payload: { ...curPointData, point: newItem, status: 'inToCanvas' },
|
||||||
});
|
});
|
||||||
// if (context.theme === 'h5') {
|
|
||||||
// const curPointData = pointData.filter(item => item.id === newItem.i)[0];
|
|
||||||
// dispatch({
|
|
||||||
// type: 'editorModal/modPointData',
|
|
||||||
// payload: { ...curPointData, point: newItem, status: 'inToCanvas' },
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// const curPointData = cpointData.filter(item => item.id === newItem.i)[0];
|
|
||||||
// dispatch({
|
|
||||||
// type: 'editorPcModal/modPointData',
|
|
||||||
// payload: { ...curPointData, point: newItem, status: 'inToCanvas' },
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
}, [dispatch, pointData]);
|
}, [dispatch, pointData]);
|
||||||
|
|
||||||
const initSelect: any = (data: any = []) => {
|
|
||||||
return (
|
|
||||||
data &&
|
|
||||||
data.map((itemData: any) => ({
|
|
||||||
...itemData,
|
|
||||||
isMenu: false,
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleContextMenuDel = () => {
|
const handleContextMenuDel = () => {
|
||||||
if (pstate.curPoint) {
|
if (pstate.curPoint) {
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -245,26 +173,13 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
ref={drop}
|
ref={drop}
|
||||||
>
|
>
|
||||||
{pointData.length > 0 ? (
|
{pointData.length > 0 ? (
|
||||||
<GridLayout
|
<ViewRender
|
||||||
className={styles.layout}
|
pointData={pointData}
|
||||||
cols={24}
|
|
||||||
rowHeight={2}
|
|
||||||
width={canvasRect[0] || 0}
|
width={canvasRect[0] || 0}
|
||||||
margin={[0, 0]}
|
dragStop={dragStop}
|
||||||
onDragStop={dragStop}
|
|
||||||
onDragStart={onDragStart}
|
onDragStart={onDragStart}
|
||||||
onResizeStop={onResizeStop}
|
onResizeStop={onResizeStop}
|
||||||
>
|
/>
|
||||||
{pointData.map(value => (
|
|
||||||
<div
|
|
||||||
className={value.isMenu ? styles.selected : styles.dragItem}
|
|
||||||
key={value.id}
|
|
||||||
data-grid={value.point}
|
|
||||||
>
|
|
||||||
<DynamicEngine {...value.item} isTpl={false} />
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</GridLayout>
|
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -132,7 +132,6 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
border: 2px solid transparent;
|
|
||||||
cursor: move;
|
cursor: move;
|
||||||
:global(a) {
|
:global(a) {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import React, { CSSProperties, memo, useEffect, useMemo, useRef, useState } from 'react';
|
import React, { CSSProperties, memo, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import GridLayout from 'react-grid-layout';
|
import ViewRender from '@/core/ViewRender';
|
||||||
import DynamicEngine from 'components/DynamicEngine';
|
|
||||||
import domtoimage from 'dom-to-image';
|
import domtoimage from 'dom-to-image';
|
||||||
import req from '@/utils/req';
|
import req from '@/utils/req';
|
||||||
import styles from './index.less';
|
|
||||||
import { useGetScrollBarWidth } from '@/utils/tool';
|
import { useGetScrollBarWidth } from '@/utils/tool';
|
||||||
import { LocationDescriptorObject } from 'history-with-query';
|
import { LocationDescriptorObject } from 'history-with-query';
|
||||||
|
|
||||||
@ -123,25 +121,7 @@ const PreviewPage = memo((props: PreviewPageProps) => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div ref={refImgDom}>
|
<div ref={refImgDom}>
|
||||||
<GridLayout
|
<ViewRender pageData={pageData} pointData={pointData} width={vw > 800 ? 375 : vw} />
|
||||||
className={styles.layout}
|
|
||||||
cols={24}
|
|
||||||
rowHeight={2}
|
|
||||||
width={vw > 800 ? 375 : vw}
|
|
||||||
margin={[0, 0]}
|
|
||||||
style={{
|
|
||||||
backgroundColor: pageData.bgColor,
|
|
||||||
backgroundImage: pageData.bgImage ? `url(${pageData.bgImage[0].url})` : 'initial',
|
|
||||||
backgroundSize: 'contain',
|
|
||||||
backgroundRepeat: 'no-repeat',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{pointData.map((value: PointDataItem) => (
|
|
||||||
<div className={styles.dragItem} key={value.id} data-grid={value.point}>
|
|
||||||
<DynamicEngine {...(value.item as any)} />
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</GridLayout>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user