mirror of
https://github.com/MrXujiang/h5-Dooring.git
synced 2026-01-26 01:19:42 +00:00
commit
79a23953dd
4
.gitignore
vendored
4
.gitignore
vendored
@ -103,4 +103,8 @@ dist
|
|||||||
# TernJS port file
|
# TernJS port file
|
||||||
.tern-port
|
.tern-port
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
/**/*.umi
|
||||||
|
=======
|
||||||
.umi/
|
.umi/
|
||||||
|
>>>>>>> upstream/master
|
||||||
|
|||||||
@ -3,44 +3,39 @@ import { Carousel } from 'zarm';
|
|||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
const XCarousel = memo(props => {
|
const XCarousel = memo(props => {
|
||||||
const {
|
const { direction, swipeable, autoPlay, isTpl, imgList, tplImg } = props;
|
||||||
direction,
|
|
||||||
swipeable,
|
|
||||||
autoPlay,
|
|
||||||
isTpl,
|
|
||||||
imgList,
|
|
||||||
tplImg
|
|
||||||
} = props
|
|
||||||
|
|
||||||
const contentRender = () => {
|
const contentRender = () => {
|
||||||
return imgList.map((item, i) => {
|
return imgList.map((item, i) => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.carousel__item__pic} key={+i}>
|
<div className={styles.carousel__item__pic} key={+i}>
|
||||||
<img src={item.imgUrl[0].url} alt="" />
|
<img src={item.imgUrl[0].url} alt="" />
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
return <div style={{width: '100%', overflow: 'hidden'}}>
|
return (
|
||||||
{
|
<div style={{ width: '100%', overflow: 'hidden' }}>
|
||||||
isTpl ? <div className={styles.carousel__item__pic}>
|
{isTpl ? (
|
||||||
<img src={tplImg} alt="" />
|
<div className={styles.carousel__item__pic}>
|
||||||
</div>
|
<img src={tplImg} alt="" />
|
||||||
:
|
|
||||||
<Carousel
|
|
||||||
onChange={(index) => {
|
|
||||||
// console.log(`onChange: ${index}`);
|
|
||||||
}}
|
|
||||||
direction={direction}
|
|
||||||
swipeable={swipeable}
|
|
||||||
autoPlay={autoPlay}
|
|
||||||
loop
|
|
||||||
>
|
|
||||||
{contentRender()}
|
|
||||||
</Carousel>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
})
|
) : (
|
||||||
|
<Carousel
|
||||||
|
onChange={index => {
|
||||||
|
// console.log(`onChange: ${index}`);
|
||||||
|
}}
|
||||||
|
direction={direction}
|
||||||
|
swipeable={swipeable}
|
||||||
|
autoPlay={autoPlay}
|
||||||
|
loop
|
||||||
|
>
|
||||||
|
{contentRender()}
|
||||||
|
</Carousel>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
export default XCarousel;
|
export default XCarousel;
|
||||||
|
|||||||
@ -2,35 +2,38 @@ import { dynamic } from 'umi';
|
|||||||
import Loading from '../LoadingCp';
|
import Loading from '../LoadingCp';
|
||||||
import { useMemo, memo } from 'react';
|
import { useMemo, memo } from 'react';
|
||||||
|
|
||||||
const needList = ['Tab', 'Carousel', 'Upload', 'Video']
|
const needList = ['Tab', 'Carousel', 'Upload', 'Video'];
|
||||||
|
|
||||||
const DynamicFunc = (type) => dynamic({
|
const DynamicFunc = type =>
|
||||||
loader: async function() {
|
dynamic({
|
||||||
let Component;
|
loader: async function() {
|
||||||
if(needList.includes(type)) {
|
let Component;
|
||||||
const { default: Graph } = await import(`@/components/${type}`)
|
if (needList.includes(type)) {
|
||||||
Component = Graph
|
const { default: Graph } = await import(`@/components/${type}`);
|
||||||
}else {
|
Component = Graph;
|
||||||
const Components = await import(`@/components/DynamicEngine/components`)
|
} else {
|
||||||
Component = Components[type]
|
const Components = await import(`@/components/DynamicEngine/components`);
|
||||||
}
|
Component = Components[type];
|
||||||
|
}
|
||||||
|
|
||||||
return (props) => {
|
return props => {
|
||||||
const { config } = props
|
const { config } = props;
|
||||||
return <Component {...config} />
|
return <Component {...config} />;
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
loading: () => <div style={{ paddingTop: 10, textAlign: 'center' }}>
|
loading: () => (
|
||||||
<Loading />
|
<div style={{ paddingTop: 10, textAlign: 'center' }}>
|
||||||
</div>
|
<Loading />
|
||||||
})
|
</div>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
const DynamicEngine = memo((props) => {
|
const DynamicEngine = memo(props => {
|
||||||
const { type, config } = props
|
const { type, config } = props;
|
||||||
const Dynamic = useMemo(() => {
|
const Dynamic = useMemo(() => {
|
||||||
return DynamicFunc(type)
|
return DynamicFunc(type);
|
||||||
}, [type])
|
}, [type, config]);
|
||||||
return <Dynamic type={type} config={config} />
|
return <Dynamic type={type} config={config} />;
|
||||||
})
|
});
|
||||||
|
|
||||||
export default DynamicEngine
|
export default DynamicEngine;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,185 +1,211 @@
|
|||||||
import React, { useState, useEffect, useCallback, memo } from 'react'
|
import React, { useState, useEffect, useCallback, memo, useMemo } from 'react';
|
||||||
import { Slider, Result, Tabs, Alert } from 'antd'
|
import { Slider, Result, Tabs, Alert } from 'antd';
|
||||||
import {
|
import {
|
||||||
PieChartOutlined,
|
PieChartOutlined,
|
||||||
ExpandOutlined,
|
ExpandOutlined,
|
||||||
PlayCircleOutlined,
|
PlayCircleOutlined,
|
||||||
HighlightOutlined
|
HighlightOutlined,
|
||||||
} from '@ant-design/icons'
|
} from '@ant-design/icons';
|
||||||
import TextLoop from 'react-text-loop'
|
import TextLoop from 'react-text-loop';
|
||||||
import { connect } from 'dva'
|
import { connect } from 'dva';
|
||||||
import HeaderComponent from './components/Header'
|
import HeaderComponent from './components/Header';
|
||||||
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 from 'components/DynamicEngine'
|
import DynamicEngine from 'components/DynamicEngine';
|
||||||
import FormEditor from 'components/FormEditor'
|
import FormEditor from 'components/FormEditor';
|
||||||
import template from 'components/DynamicEngine/template'
|
import template from 'components/DynamicEngine/template';
|
||||||
import mediaTpl from 'components/DynamicEngine/mediaTpl'
|
import mediaTpl from 'components/DynamicEngine/mediaTpl';
|
||||||
import graphTpl from 'components/DynamicEngine/graphTpl'
|
import graphTpl from 'components/DynamicEngine/graphTpl';
|
||||||
import schema from 'components/DynamicEngine/schema'
|
import schema from 'components/DynamicEngine/schema';
|
||||||
import { uuid } from 'utils/tool'
|
import { uuid } from 'utils/tool';
|
||||||
|
|
||||||
import styles from './index.less'
|
import styles from './index.less';
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
|
|
||||||
const Container = memo((props) => {
|
const Container = memo(props => {
|
||||||
const [ scaleNum , setScale ] = useState(1)
|
const [scaleNum, setScale] = useState(1);
|
||||||
|
|
||||||
const { pointData, curPoint, dispatch } = props
|
const { pointData, curPoint, dispatch } = props;
|
||||||
|
|
||||||
// 指定画布的id
|
// 指定画布的id
|
||||||
let canvasId = 'js_canvas'
|
let canvasId = 'js_canvas';
|
||||||
|
|
||||||
const backSize = () => {
|
const backSize = () => {
|
||||||
setScale(1)
|
setScale(1);
|
||||||
}
|
};
|
||||||
|
|
||||||
const CpIcon = {
|
const CpIcon = {
|
||||||
base: <HighlightOutlined />,
|
base: <HighlightOutlined />,
|
||||||
media: <PlayCircleOutlined />,
|
media: <PlayCircleOutlined />,
|
||||||
visible: <PieChartOutlined />
|
visible: <PieChartOutlined />,
|
||||||
}
|
};
|
||||||
|
|
||||||
const generateHeader = (type, text) => {
|
const generateHeader = (type, text) => {
|
||||||
return <div>{ CpIcon[type] } { text }</div>
|
return (
|
||||||
}
|
<div>
|
||||||
|
{CpIcon[type]} {text}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const handleSliderChange = (v) => {
|
const handleSliderChange = v => {
|
||||||
setScale(prev => v >= 150 ? 1.5 : (v / 100))
|
setScale(prev => (v >= 150 ? 1.5 : v / 100));
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleSlider = (type) => {
|
const handleSlider = type => {
|
||||||
if(type) {
|
if (type) {
|
||||||
setScale(prev => prev >= 1.5 ? 1.5 : (prev + 0.1))
|
setScale(prev => (prev >= 1.5 ? 1.5 : prev + 0.1));
|
||||||
}else {
|
} else {
|
||||||
setScale(prev => prev <= 0.5 ? 0.5 : (prev - 0.1))
|
setScale(prev => (prev <= 0.5 ? 0.5 : prev - 0.1));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleFormSave = (data) => {
|
const handleFormSave = data => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'editorModal/modPointData',
|
type: 'editorModal/modPointData',
|
||||||
payload: { ...curPoint, item: {...curPoint.item, config: data} }
|
payload: { ...curPoint, item: { ...curPoint.item, config: data } },
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
const clearData = useCallback(() => {
|
const clearData = useCallback(() => {
|
||||||
dispatch({ type: 'editorModal/clearAll' })
|
dispatch({ type: 'editorModal/clearAll' });
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const handleDel = (id) => {
|
const handleDel = id => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'editorModal/delPointData',
|
type: 'editorModal/delPointData',
|
||||||
payload: { id }
|
payload: { id },
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(window.innerWidth < 1024) {
|
if (window.innerWidth < 1024) {
|
||||||
props.history.push('/mobileTip')
|
props.history.push('/mobileTip');
|
||||||
}
|
}
|
||||||
// 存储用户唯一信息
|
}, []);
|
||||||
if(!localStorage.getItem('uid') || !sessionStorage.getItem('sid')) {
|
|
||||||
localStorage.setItem('uid', uuid(8, 10))
|
const allType = useMemo(() => {
|
||||||
sessionStorage.setItem('sid', uuid(5, 10))
|
let arr = [];
|
||||||
}
|
template.forEach(v => {
|
||||||
}, [])
|
arr.push(v.type);
|
||||||
|
});
|
||||||
|
mediaTpl.forEach(v => {
|
||||||
|
arr.push(v.type);
|
||||||
|
});
|
||||||
|
graphTpl.forEach(v => {
|
||||||
|
arr.push(v.type);
|
||||||
|
});
|
||||||
|
return arr;
|
||||||
|
}, []);
|
||||||
|
// 存储用户唯一信息
|
||||||
|
if (!localStorage.getItem('uid') || !sessionStorage.getItem('sid')) {
|
||||||
|
localStorage.setItem('uid', uuid(8, 10));
|
||||||
|
sessionStorage.setItem('sid', uuid(5, 10));
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.editorWrap}>
|
<div className={styles.editorWrap}>
|
||||||
<HeaderComponent pointData={pointData} clearData={clearData} location={props.location} />
|
<HeaderComponent pointData={pointData} clearData={clearData} location={props.location} />
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className={styles.list} >
|
<div className={styles.list}>
|
||||||
<div className={styles.searchBar}>
|
<div className={styles.searchBar}>
|
||||||
<Alert
|
<Alert
|
||||||
banner
|
banner
|
||||||
message={
|
message={
|
||||||
<TextLoop mask>
|
<TextLoop mask>
|
||||||
<div>Dooring升级啦!</div>
|
<div>Dooring升级啦!</div>
|
||||||
<div>Dooring添加自动保存功能</div>
|
<div>Dooring添加自动保存功能</div>
|
||||||
<div>已有500+人使用</div>
|
<div>已有500+人使用</div>
|
||||||
<div>持续迭代中...</div>
|
<div>持续迭代中...</div>
|
||||||
</TextLoop>
|
</TextLoop>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.componentList}>
|
<div className={styles.componentList}>
|
||||||
<Tabs defaultActiveKey="1">
|
<Tabs defaultActiveKey="1">
|
||||||
<TabPane tab={generateHeader("base","基础组件")} key="1">
|
<TabPane tab={generateHeader('base', '基础组件')} key="1">
|
||||||
{
|
{template.map((value, i) => (
|
||||||
template.map((value,i) =>
|
<TargetBox item={value} key={i} canvasId={canvasId}>
|
||||||
<TargetBox item={value} key={i} canvasId={canvasId}>
|
<DynamicEngine {...value} config={schema[value.type].config} isTpl={true} />
|
||||||
<DynamicEngine {...value} config={schema[value.type].config} isTpl={true} />
|
</TargetBox>
|
||||||
</TargetBox>
|
))}
|
||||||
)
|
|
||||||
}
|
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<TabPane tab={generateHeader("media","媒体组件")} key="2">
|
<TabPane tab={generateHeader('media', '媒体组件')} key="2">
|
||||||
{
|
{mediaTpl.map((value, i) => (
|
||||||
mediaTpl.map((value,i) =>
|
<TargetBox item={value} key={i} canvasId={canvasId}>
|
||||||
<TargetBox item={value} key={i} canvasId={canvasId}>
|
<DynamicEngine {...value} config={schema[value.type].config} isTpl={true} />
|
||||||
<DynamicEngine {...value} config={schema[value.type].config} isTpl={true} />
|
</TargetBox>
|
||||||
</TargetBox>
|
))}
|
||||||
)
|
|
||||||
}
|
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<TabPane tab={generateHeader("visible","可视化组件")} key="3">
|
<TabPane tab={generateHeader('visible', '可视化组件')} key="3">
|
||||||
{
|
{graphTpl.map((value, i) => (
|
||||||
graphTpl.map((value,i) =>
|
<TargetBox item={value} key={i} canvasId={canvasId}>
|
||||||
<TargetBox item={value} key={i} canvasId={canvasId}>
|
<DynamicEngine {...value} config={schema[value.type].config} isTpl={true} />
|
||||||
<DynamicEngine {...value} config={schema[value.type].config} isTpl={true} />
|
</TargetBox>
|
||||||
</TargetBox>
|
))}
|
||||||
)
|
|
||||||
}
|
|
||||||
</TabPane>
|
</TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.tickMark} id='calibration'>
|
<div className={styles.tickMark} id="calibration">
|
||||||
<div className={styles.tickMarkTop}>
|
<div className={styles.tickMarkTop}>
|
||||||
<Calibration direction='up' id='calibrationUp' multiple={scaleNum} />
|
<Calibration direction="up" id="calibrationUp" multiple={scaleNum} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.tickMarkLeft}>
|
<div className={styles.tickMarkLeft}>
|
||||||
<Calibration direction='right' id='calibrationRight' multiple={scaleNum} />
|
<Calibration direction="right" id="calibrationRight" multiple={scaleNum} />
|
||||||
</div>
|
</div>
|
||||||
<SourceBox scaleNum={scaleNum} canvasId={canvasId} />
|
<SourceBox scaleNum={scaleNum} canvasId={canvasId} allType={allType} />
|
||||||
<div className={styles.sliderWrap}>
|
<div className={styles.sliderWrap}>
|
||||||
<span className={styles.sliderBtn} onClick={handleSlider.bind(this, 1)}>+</span>
|
<span className={styles.sliderBtn} onClick={handleSlider.bind(this, 1)}>
|
||||||
<Slider vertical defaultValue={100} className={styles.slider} onChange={handleSliderChange} min={50} max={150} value={scaleNum * 100} />
|
+
|
||||||
<span className={styles.sliderBtn} onClick={handleSlider.bind(this, 0)}>-</span>
|
</span>
|
||||||
|
<Slider
|
||||||
|
vertical
|
||||||
|
defaultValue={100}
|
||||||
|
className={styles.slider}
|
||||||
|
onChange={handleSliderChange}
|
||||||
|
min={50}
|
||||||
|
max={150}
|
||||||
|
value={scaleNum * 100}
|
||||||
|
/>
|
||||||
|
<span className={styles.sliderBtn} onClick={handleSlider.bind(this, 0)}>
|
||||||
|
-
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.backSize}>
|
||||||
|
<ExpandOutlined onClick={backSize} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.backSize}><ExpandOutlined onClick={backSize} /></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.attrSetting}>
|
<div className={styles.attrSetting}>
|
||||||
{
|
{pointData.length && curPoint ? (
|
||||||
pointData.length && curPoint ?
|
|
||||||
<>
|
<>
|
||||||
<div className={styles.tit}>属性设置</div>
|
<div className={styles.tit}>属性设置</div>
|
||||||
<FormEditor
|
<FormEditor
|
||||||
config={curPoint.item.editableEl}
|
config={curPoint.item.editableEl}
|
||||||
uid={curPoint.id}
|
uid={curPoint.id}
|
||||||
defaultValue={curPoint.item.config}
|
defaultValue={curPoint.item.config}
|
||||||
onSave={handleFormSave}
|
onSave={handleFormSave}
|
||||||
onDel={handleDel}
|
onDel={handleDel}
|
||||||
/>
|
/>
|
||||||
</> :
|
</>
|
||||||
<div style={{paddingTop: '100px'}}>
|
) : (
|
||||||
|
<div style={{ paddingTop: '100px' }}>
|
||||||
<Result
|
<Result
|
||||||
status="404"
|
status="404"
|
||||||
title="还没有数据哦"
|
title="还没有数据哦"
|
||||||
subTitle="赶快拖拽组件来生成你的H5页面吧~"
|
subTitle="赶快拖拽组件来生成你的H5页面吧~"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
|
|
||||||
export default connect(({ editorModal: { pointData, curPoint } }) => ({
|
export default connect(({ editorModal: { pointData, curPoint } }) => ({
|
||||||
pointData, curPoint
|
pointData,
|
||||||
}))(Container)
|
curPoint,
|
||||||
|
}))(Container);
|
||||||
|
|||||||
@ -1,79 +1,104 @@
|
|||||||
import React, { memo, useEffect, useState } from 'react'
|
import React, { memo, useEffect, useState } from 'react';
|
||||||
import { useDrop } from 'react-dnd'
|
import { useDrop } from 'react-dnd';
|
||||||
import Draggable from 'react-draggable'
|
import Draggable from 'react-draggable';
|
||||||
import GridLayout from 'react-grid-layout'
|
import GridLayout from 'react-grid-layout';
|
||||||
import { Tooltip } from 'antd'
|
import { Tooltip } from 'antd';
|
||||||
import { connect } from 'dva'
|
import { connect } from 'dva';
|
||||||
import DynamicEngine from 'components/DynamicEngine'
|
import DynamicEngine from 'components/DynamicEngine';
|
||||||
import styles from './index.less'
|
import styles from './index.less';
|
||||||
|
import { uuid } from '@/utils/tool';
|
||||||
const SourceBox = memo((props) => {
|
const SourceBox = memo(props => {
|
||||||
const { pointData, scaleNum, canvasId, dispatch } = props
|
const { pointData, scaleNum, canvasId, allType, dispatch } = props;
|
||||||
const [canvasRect, setCanvasRect] = useState([])
|
const [canvasRect, setCanvasRect] = useState([]);
|
||||||
const [isShowTip, setIsShowTip] = useState(true)
|
const [isShowTip, setIsShowTip] = useState(true);
|
||||||
const [{ isOver }, drop] = useDrop({
|
const [{ isOver }, drop] = useDrop({
|
||||||
accept: [],
|
accept: allType,
|
||||||
collect: (monitor) => ({
|
drop: (item, monitor) => {
|
||||||
|
let parentDiv = document.getElementById(canvasId),
|
||||||
|
pointRect = parentDiv.getBoundingClientRect(),
|
||||||
|
top = pointRect.top,
|
||||||
|
pointEnd = monitor.getSourceClientOffset(),
|
||||||
|
y = pointEnd.y - top,
|
||||||
|
col = 24, // 网格列数
|
||||||
|
cellHeight = 2;
|
||||||
|
// 转换成网格规则的坐标和大小
|
||||||
|
let gridY = Math.ceil(y / cellHeight);
|
||||||
|
dispatch({
|
||||||
|
type: 'editorModal/addPointData',
|
||||||
|
payload: {
|
||||||
|
id: uuid(6, 10),
|
||||||
|
item,
|
||||||
|
point: { i: `x-${pointData.length}`, x: 0, y: gridY, w: col, h: item.h, isBounded: true },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
collect: monitor => ({
|
||||||
isOver: monitor.isOver(),
|
isOver: monitor.isOver(),
|
||||||
canDrop: monitor.canDrop(),
|
canDrop: monitor.canDrop(),
|
||||||
item: monitor.getItem()
|
item: monitor.getItem(),
|
||||||
})
|
}),
|
||||||
})
|
});
|
||||||
|
|
||||||
const dragStop = (layout, oldItem, newItem, placeholder, e, element) => {
|
const dragStop = (layout, oldItem, newItem, placeholder, e, element) => {
|
||||||
const curPointData = pointData.filter(item => item.id === newItem.i)[0]
|
const curPointData = pointData.filter(item => item.id === newItem.i)[0];
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'editorModal/modPointData',
|
type: 'editorModal/modPointData',
|
||||||
payload: { ...curPointData, point: newItem }
|
payload: { ...curPointData, point: newItem },
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
const onDragStart = (layout, oldItem, newItem, placeholder, e, element) => {
|
const onDragStart = (layout, oldItem, newItem, placeholder, e, element) => {
|
||||||
const curPointData = pointData.filter(item => item.id === newItem.i)[0]
|
const curPointData = pointData.filter(item => item.id === newItem.i)[0];
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'editorModal/modPointData',
|
type: 'editorModal/modPointData',
|
||||||
payload: { ...curPointData }
|
payload: { ...curPointData },
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
const onResizeStop = (layout, oldItem, newItem, placeholder, e, element) => {
|
const onResizeStop = (layout, oldItem, newItem, placeholder, e, element) => {
|
||||||
const curPointData = pointData.filter(item => item.id === newItem.i)[0]
|
const curPointData = pointData.filter(item => item.id === newItem.i)[0];
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'editorModal/modPointData',
|
type: 'editorModal/modPointData',
|
||||||
payload: { ...curPointData, point: newItem }
|
payload: { ...curPointData, point: newItem },
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let { width, height } = document.getElementById(canvasId).getBoundingClientRect()
|
let { width, height } = document.getElementById(canvasId).getBoundingClientRect();
|
||||||
setCanvasRect([width, height])
|
setCanvasRect([width, height]);
|
||||||
}, [canvasId])
|
}, [canvasId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsShowTip(false)
|
setIsShowTip(false);
|
||||||
}, 3000)
|
}, 3000);
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const opacity = isOver ? 0.7 : 1
|
|
||||||
const backgroundColor = isOver ? 1 : 0.7
|
|
||||||
|
|
||||||
|
const opacity = isOver ? 0.7 : 1;
|
||||||
|
const backgroundColor = isOver ? 1 : 0.7;
|
||||||
return (
|
return (
|
||||||
<Draggable handle=".js_box">
|
<Draggable handle=".js_box">
|
||||||
<div className={styles.canvasBox}>
|
<div className={styles.canvasBox}>
|
||||||
<div style={{transform: `scale(${scaleNum})`, position: 'relative', width: '100%', height: '100%'}}>
|
<div
|
||||||
|
style={{
|
||||||
<div
|
transform: `scale(${scaleNum})`,
|
||||||
|
position: 'relative',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
id={canvasId}
|
id={canvasId}
|
||||||
className={styles.canvas}
|
className={styles.canvas}
|
||||||
style={{
|
style={{
|
||||||
opacity, backgroundColor
|
opacity,
|
||||||
}}
|
backgroundColor,
|
||||||
ref={drop}
|
}}
|
||||||
|
ref={drop}
|
||||||
>
|
>
|
||||||
<Tooltip placement="right" title="鼠标按住此处拖拽画布" visible={isShowTip}>
|
<Tooltip placement="right" title="鼠标按住此处拖拽画布" visible={isShowTip}>
|
||||||
<div
|
<div
|
||||||
className="js_box"
|
className="js_box"
|
||||||
style={{
|
style={{
|
||||||
width: '10px',
|
width: '10px',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
@ -83,39 +108,36 @@ const SourceBox = memo((props) => {
|
|||||||
right: '-10px',
|
right: '-10px',
|
||||||
top: '0',
|
top: '0',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
cursor: 'move'
|
cursor: 'move',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
{
|
{pointData.length > 0 ? (
|
||||||
pointData.length > 0 ?
|
<GridLayout
|
||||||
<GridLayout
|
className={styles.layout}
|
||||||
className={styles.layout}
|
cols={24}
|
||||||
cols={24}
|
rowHeight={2}
|
||||||
rowHeight={2}
|
width={canvasRect[0]}
|
||||||
width={canvasRect[0]}
|
margin={[0, 0]}
|
||||||
margin={[0,0]}
|
|
||||||
onDragStop={dragStop}
|
onDragStop={dragStop}
|
||||||
onDragStart={onDragStart}
|
onDragStart={onDragStart}
|
||||||
onResizeStop={onResizeStop}
|
onResizeStop={onResizeStop}
|
||||||
>
|
>
|
||||||
{
|
{pointData.map(value => (
|
||||||
pointData.map(value =>
|
<div className={styles.dragItem} key={value.id} data-grid={value.point}>
|
||||||
<div className={styles.dragItem} key={value.id} data-grid={value.point}>
|
<DynamicEngine {...value.item} isTpl={false} />
|
||||||
<DynamicEngine {...value.item} isTpl={false} />
|
</div>
|
||||||
</div>
|
))}
|
||||||
)
|
</GridLayout>
|
||||||
}
|
) : null}
|
||||||
</GridLayout> : null
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Draggable>
|
</Draggable>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
|
|
||||||
export default connect(({ editorModal: { pointData } }) => ({
|
export default connect(({ editorModal: { pointData } }) => ({
|
||||||
pointData
|
pointData,
|
||||||
}))(SourceBox)
|
}))(SourceBox);
|
||||||
|
|||||||
@ -1,61 +1,39 @@
|
|||||||
import React, { useMemo, memo } from 'react'
|
import React, { useMemo, memo } from 'react';
|
||||||
import { useDrag } from 'react-dnd'
|
import { useDrag } from 'react-dnd';
|
||||||
import { connect } from 'dva'
|
import { connect } from 'dva';
|
||||||
import schema from 'components/DynamicEngine/schema'
|
import schema from 'components/DynamicEngine/schema';
|
||||||
import { uuid } from '@/utils/tool';
|
|
||||||
import styles from './index.less'
|
|
||||||
|
|
||||||
const TargetBox = memo((props) => {
|
import styles from './index.less';
|
||||||
const { item, dispatch, canvasId, pointData } = props
|
|
||||||
const [{ isDragging }, drag] = useDrag({
|
const TargetBox = memo(props => {
|
||||||
item: { type: item.type, config: schema[item.type].config, h: item.h, editableEl: schema[item.type].editData },
|
const { item, dispatch, canvasId, pointData } = props;
|
||||||
collect: (monitor) => ({
|
const [{ isDragging }, drag, preview] = useDrag({
|
||||||
|
item: {
|
||||||
|
type: item.type,
|
||||||
|
config: schema[item.type].config,
|
||||||
|
h: item.h,
|
||||||
|
editableEl: schema[item.type].editData,
|
||||||
|
},
|
||||||
|
collect: monitor => ({
|
||||||
isDragging: monitor.isDragging(),
|
isDragging: monitor.isDragging(),
|
||||||
}),
|
}),
|
||||||
// begin(monitor) {
|
});
|
||||||
// getStartPoint(monitor.getSourceClientOffset())
|
|
||||||
// },
|
|
||||||
end(item, monitor) {
|
|
||||||
let parentDiv = document.getElementById(canvasId),
|
|
||||||
pointRect = parentDiv.getBoundingClientRect(),
|
|
||||||
top = pointRect.top,
|
|
||||||
pointEnd = monitor.getSourceClientOffset(),
|
|
||||||
y = pointEnd.y - top,
|
|
||||||
col = 24, // 网格列数
|
|
||||||
cellHeight = 2
|
|
||||||
// 转换成网格规则的坐标和大小
|
|
||||||
let gridY = Math.ceil(y / cellHeight)
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: 'editorModal/addPointData',
|
|
||||||
payload: {
|
|
||||||
id: uuid(6, 10),
|
|
||||||
item,
|
|
||||||
point: { i: `x-${pointData.length}`, x: 0, y: gridY, w: col, h: item.h, isBounded: true }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const containerStyle = useMemo(
|
const containerStyle = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
opacity: isDragging ? 0.4 : 1,
|
opacity: isDragging ? 0.4 : 1,
|
||||||
cursor: 'move'
|
cursor: 'move',
|
||||||
}),
|
}),
|
||||||
[isDragging],
|
[isDragging],
|
||||||
)
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={styles.module} style={{ ...containerStyle }} ref={drag}>
|
||||||
className={styles.module}
|
{props.children}
|
||||||
style={{ ...containerStyle}}
|
|
||||||
ref={drag}
|
|
||||||
>
|
|
||||||
{ props.children }
|
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
|
|
||||||
export default connect(({ editorModal: { pointData } }) => ({
|
export default connect(({ editorModal: { pointData } }) => ({
|
||||||
pointData
|
pointData,
|
||||||
}))(TargetBox)
|
}))(TargetBox);
|
||||||
|
|||||||
@ -1,73 +1,82 @@
|
|||||||
import React, { memo, useEffect, useState } from 'react'
|
import React, { memo, useEffect, useState } from 'react';
|
||||||
import GridLayout from 'react-grid-layout'
|
import GridLayout from 'react-grid-layout';
|
||||||
import DynamicEngine from 'components/DynamicEngine'
|
import DynamicEngine from 'components/DynamicEngine';
|
||||||
import req from '@/utils/req'
|
import req from '@/utils/req';
|
||||||
import styles from './index.less'
|
import styles from './index.less';
|
||||||
|
|
||||||
// 可视化组件类型
|
// 可视化组件类型
|
||||||
// const componentTypes = ['Column', 'Pie']
|
// const componentTypes = ['Column', 'Pie']
|
||||||
|
|
||||||
const isMac = navigator.platform.indexOf('Mac') === 0
|
const isMac = navigator.platform.indexOf('Mac') === 0;
|
||||||
|
|
||||||
const pcStyle = {
|
const pcStyle = {
|
||||||
width: isMac ? 395 : 412,
|
width: isMac ? 395 : 412,
|
||||||
margin: '20px auto',
|
margin: '20px auto',
|
||||||
border: '10px solid #000',
|
border: '10px solid #000',
|
||||||
borderRadius: '20px',
|
borderRadius: '20px',
|
||||||
height: '684px',
|
height: '684px',
|
||||||
overflow: 'auto'
|
overflow: 'auto',
|
||||||
}
|
};
|
||||||
|
|
||||||
const PreviewPage = memo((props) => {
|
const PreviewPage = memo(props => {
|
||||||
const [pointData, setPointData] = useState(() => {
|
const [pointData, setPointData] = useState(() => {
|
||||||
let pointDataStr = localStorage.getItem('pointData')
|
let pointDataStr = localStorage.getItem('pointData');
|
||||||
let points
|
let points;
|
||||||
|
|
||||||
try{
|
|
||||||
points = JSON.parse(pointDataStr) || []
|
|
||||||
}catch(err) {
|
|
||||||
points = []
|
|
||||||
}
|
|
||||||
return points.map(item => ({...item, point: {...item.point, isDraggable: false, isResizable: false } }))
|
|
||||||
})
|
|
||||||
|
|
||||||
const vw = window.innerWidth
|
try {
|
||||||
|
points = JSON.parse(pointDataStr) || [];
|
||||||
|
} catch (err) {
|
||||||
|
points = [];
|
||||||
|
}
|
||||||
|
return points.map(item => ({
|
||||||
|
...item,
|
||||||
|
point: { ...item.point, isDraggable: false, isResizable: false },
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
const vw = window.innerWidth;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { tid } = props.location.query
|
const { tid } = props.location.query;
|
||||||
const timer = null
|
const timer = null;
|
||||||
req.get('/visible/preview/get', { params: { tid } }).then(res => {
|
req
|
||||||
setPointData(res.map(item => ({...item, point: {...item.point, isDraggable: false, isResizable: false } })))
|
.get('/visible/preview/get', { params: { tid } })
|
||||||
}).catch(err => {
|
.then(res => {
|
||||||
timer = setTimeout(() => {
|
setPointData(
|
||||||
window.close()
|
res.map(item => ({
|
||||||
}, 3000)
|
...item,
|
||||||
})
|
point: { ...item.point, isDraggable: false, isResizable: false },
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
window.close();
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(timer)
|
clearTimeout(timer);
|
||||||
}
|
};
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={vw > 800 ? pcStyle : {}}>
|
<div style={vw > 800 ? pcStyle : {}}>
|
||||||
<GridLayout
|
<GridLayout
|
||||||
className={styles.layout}
|
className={styles.layout}
|
||||||
cols={24}
|
cols={24}
|
||||||
rowHeight={2}
|
rowHeight={2}
|
||||||
width={vw > 800 ? 375 :vw }
|
width={vw > 800 ? 375 : vw}
|
||||||
margin={[0,0]}
|
margin={[0, 0]}
|
||||||
id="xx"
|
id="xx"
|
||||||
>
|
>
|
||||||
{
|
{pointData.map(value => (
|
||||||
pointData.map(value =>
|
<div className={styles.dragItem} key={value.id} data-grid={value.point}>
|
||||||
<div className={styles.dragItem} key={value.id} data-grid={value.point}>
|
<DynamicEngine {...value.item} />
|
||||||
<DynamicEngine {...value.item} />
|
</div>
|
||||||
</div>
|
))}
|
||||||
)
|
|
||||||
}
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
|
|
||||||
export default PreviewPage
|
export default PreviewPage;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user