mirror of
https://github.com/MrXujiang/h5-Dooring.git
synced 2025-12-11 17:32:50 +00:00
fix drag bug
add ignore
This commit is contained in:
parent
15d8e8e6e6
commit
eee468a1c3
2
.gitignore
vendored
2
.gitignore
vendored
@ -102,3 +102,5 @@ dist
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
/**/*.umi
|
||||
@ -1,165 +1,190 @@
|
||||
import React, { useState, useEffect, memo } from 'react'
|
||||
import { Input, Slider, Result, Tabs } from 'antd'
|
||||
import React, { useState, useEffect, memo, useMemo } from 'react';
|
||||
import { Input, Slider, Result, Tabs } from 'antd';
|
||||
import {
|
||||
PieChartOutlined,
|
||||
ExpandOutlined,
|
||||
PlayCircleOutlined,
|
||||
HighlightOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { connect } from 'dva'
|
||||
import HeaderComponent from './components/Header'
|
||||
import SourceBox from './SourceBox'
|
||||
import TargetBox from './TargetBox'
|
||||
import Calibration from 'components/Calibration'
|
||||
import DynamicEngine from 'components/DynamicEngine'
|
||||
import FormEditor from 'components/FormEditor'
|
||||
import template from 'components/DynamicEngine/template'
|
||||
import mediaTpl from 'components/DynamicEngine/mediaTpl'
|
||||
import graphTpl from 'components/DynamicEngine/graphTpl'
|
||||
import schema from 'components/DynamicEngine/schema'
|
||||
HighlightOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { connect } from 'dva';
|
||||
import HeaderComponent from './components/Header';
|
||||
import SourceBox from './SourceBox';
|
||||
import TargetBox from './TargetBox';
|
||||
import Calibration from 'components/Calibration';
|
||||
import DynamicEngine from 'components/DynamicEngine';
|
||||
import FormEditor from 'components/FormEditor';
|
||||
import template from 'components/DynamicEngine/template';
|
||||
import mediaTpl from 'components/DynamicEngine/mediaTpl';
|
||||
import graphTpl from 'components/DynamicEngine/graphTpl';
|
||||
import schema from 'components/DynamicEngine/schema';
|
||||
|
||||
import styles from './index.less'
|
||||
import styles from './index.less';
|
||||
|
||||
const { Search } = Input;
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
const Container = memo((props) => {
|
||||
const [ scaleNum , setScale ] = useState(1)
|
||||
const Container = memo(props => {
|
||||
const [scaleNum, setScale] = useState(1);
|
||||
|
||||
const { pointData, curPoint, dispatch } = props
|
||||
const { pointData, curPoint, dispatch } = props;
|
||||
|
||||
// 指定画布的id
|
||||
let canvasId = 'js_canvas'
|
||||
let canvasId = 'js_canvas';
|
||||
|
||||
const backSize = () => {
|
||||
setScale(1)
|
||||
}
|
||||
setScale(1);
|
||||
};
|
||||
|
||||
const CpIcon = {
|
||||
base: <HighlightOutlined />,
|
||||
media: <PlayCircleOutlined />,
|
||||
visible: <PieChartOutlined />
|
||||
}
|
||||
visible: <PieChartOutlined />,
|
||||
};
|
||||
|
||||
const generateHeader = (type, text) => {
|
||||
return <div>{ CpIcon[type] } { text }</div>
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{CpIcon[type]} {text}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const handleSliderChange = (v) => {
|
||||
setScale(prev => v >= 150 ? 1.5 : (v / 100))
|
||||
}
|
||||
const handleSliderChange = v => {
|
||||
setScale(prev => (v >= 150 ? 1.5 : v / 100));
|
||||
};
|
||||
|
||||
const handleSlider = (type) => {
|
||||
if(type) {
|
||||
setScale(prev => prev >= 1.5 ? 1.5 : (prev + 0.1))
|
||||
}else {
|
||||
setScale(prev => prev <= 0.5 ? 0.5 : (prev - 0.1))
|
||||
const handleSlider = type => {
|
||||
if (type) {
|
||||
setScale(prev => (prev >= 1.5 ? 1.5 : prev + 0.1));
|
||||
} else {
|
||||
setScale(prev => (prev <= 0.5 ? 0.5 : prev - 0.1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleFormSave = (data) => {
|
||||
const handleFormSave = data => {
|
||||
dispatch({
|
||||
type: 'editorModal/modPointData',
|
||||
payload: { ...curPoint, item: {...curPoint.item, config: data} }
|
||||
})
|
||||
}
|
||||
payload: { ...curPoint, item: { ...curPoint.item, config: data } },
|
||||
});
|
||||
};
|
||||
|
||||
const handleDel = (id) => {
|
||||
const handleDel = id => {
|
||||
dispatch({
|
||||
type: 'editorModal/delPointData',
|
||||
payload: { id }
|
||||
})
|
||||
}
|
||||
payload: { id },
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if(window.innerWidth < 1024) {
|
||||
props.history.push('/mobileTip')
|
||||
if (window.innerWidth < 1024) {
|
||||
props.history.push('/mobileTip');
|
||||
}
|
||||
}, [])
|
||||
}, []);
|
||||
|
||||
const allType = useMemo(() => {
|
||||
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;
|
||||
}, []);
|
||||
return (
|
||||
<div className={styles.editorWrap}>
|
||||
<HeaderComponent pointData={pointData} location={props.location} />
|
||||
<div className={styles.container}>
|
||||
<div className={styles.list} >
|
||||
<div className={styles.list}>
|
||||
<div className={styles.searchBar}>
|
||||
<Search placeholder="搜索组件" onSearch={value => console.log(value)} enterButton />
|
||||
</div>
|
||||
<div className={styles.componentList}>
|
||||
<Tabs defaultActiveKey="1">
|
||||
<TabPane tab={generateHeader("base","基础组件")} key="1">
|
||||
{
|
||||
template.map((value,i) =>
|
||||
<TargetBox item={value} key={i} canvasId={canvasId}>
|
||||
<DynamicEngine {...value} config={schema[value.type].config} />
|
||||
</TargetBox>
|
||||
)
|
||||
}
|
||||
<TabPane tab={generateHeader('base', '基础组件')} key="1">
|
||||
{template.map((value, i) => (
|
||||
<TargetBox item={value} key={i} canvasId={canvasId}>
|
||||
<DynamicEngine {...value} config={schema[value.type].config} />
|
||||
</TargetBox>
|
||||
))}
|
||||
</TabPane>
|
||||
<TabPane tab={generateHeader("media","媒体组件")} key="2">
|
||||
{
|
||||
mediaTpl.map((value,i) =>
|
||||
<TargetBox item={value} key={i} canvasId={canvasId}>
|
||||
<DynamicEngine {...value} config={schema[value.type].config} />
|
||||
</TargetBox>
|
||||
)
|
||||
}
|
||||
<TabPane tab={generateHeader('media', '媒体组件')} key="2">
|
||||
{mediaTpl.map((value, i) => (
|
||||
<TargetBox item={value} key={i} canvasId={canvasId}>
|
||||
<DynamicEngine {...value} config={schema[value.type].config} />
|
||||
</TargetBox>
|
||||
))}
|
||||
</TabPane>
|
||||
<TabPane tab={generateHeader("visible","可视化组件")} key="3">
|
||||
{
|
||||
graphTpl.map((value,i) =>
|
||||
<TargetBox item={value} key={i} canvasId={canvasId}>
|
||||
<DynamicEngine {...value} config={schema[value.type].config} />
|
||||
</TargetBox>
|
||||
)
|
||||
}
|
||||
<TabPane tab={generateHeader('visible', '可视化组件')} key="3">
|
||||
{graphTpl.map((value, i) => (
|
||||
<TargetBox item={value} key={i} canvasId={canvasId}>
|
||||
<DynamicEngine {...value} config={schema[value.type].config} />
|
||||
</TargetBox>
|
||||
))}
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.tickMark} id='calibration'>
|
||||
<div className={styles.tickMark} id="calibration">
|
||||
<div className={styles.tickMarkTop}>
|
||||
<Calibration direction='up' id='calibrationUp' multiple={scaleNum} />
|
||||
</div>
|
||||
<Calibration direction="up" id="calibrationUp" multiple={scaleNum} />
|
||||
</div>
|
||||
<div className={styles.tickMarkLeft}>
|
||||
<Calibration direction='right' id='calibrationRight' multiple={scaleNum} />
|
||||
<Calibration direction="right" id="calibrationRight" multiple={scaleNum} />
|
||||
</div>
|
||||
<SourceBox scaleNum={scaleNum} canvasId={canvasId} />
|
||||
<SourceBox scaleNum={scaleNum} canvasId={canvasId} allType={allType} />
|
||||
<div className={styles.sliderWrap}>
|
||||
<span className={styles.sliderBtn} onClick={handleSlider.bind(this, 1)}>+</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>
|
||||
<span className={styles.sliderBtn} onClick={handleSlider.bind(this, 1)}>
|
||||
+
|
||||
</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 className={styles.backSize}><ExpandOutlined onClick={backSize} /></div>
|
||||
</div>
|
||||
<div className={styles.attrSetting}>
|
||||
{
|
||||
pointData.length && curPoint ?
|
||||
{pointData.length && curPoint ? (
|
||||
<>
|
||||
<div className={styles.tit}>属性设置</div>
|
||||
<FormEditor
|
||||
<FormEditor
|
||||
config={curPoint.item.editableEl}
|
||||
uid={curPoint.id}
|
||||
defaultValue={curPoint.item.config}
|
||||
uid={curPoint.id}
|
||||
defaultValue={curPoint.item.config}
|
||||
onSave={handleFormSave}
|
||||
onDel={handleDel}
|
||||
/>
|
||||
</> :
|
||||
<div style={{paddingTop: '100px'}}>
|
||||
</>
|
||||
) : (
|
||||
<div style={{ paddingTop: '100px' }}>
|
||||
<Result
|
||||
status="404"
|
||||
title="还没有数据哦"
|
||||
subTitle="赶快拖拽组件来生成你的H5页面吧~"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export default connect(({ editorModal: { pointData, curPoint } }) => ({
|
||||
pointData, curPoint
|
||||
}))(Container)
|
||||
pointData,
|
||||
curPoint,
|
||||
}))(Container);
|
||||
|
||||
@ -1,79 +1,105 @@
|
||||
import React, { memo, useEffect, useState } from 'react'
|
||||
import { useDrop } from 'react-dnd'
|
||||
import Draggable from 'react-draggable'
|
||||
import GridLayout from 'react-grid-layout'
|
||||
import { Tooltip } from 'antd'
|
||||
import { connect } from 'dva'
|
||||
import DynamicEngine from 'components/DynamicEngine'
|
||||
import styles from './index.less'
|
||||
|
||||
const SourceBox = memo((props) => {
|
||||
const { pointData, scaleNum, canvasId, dispatch } = props
|
||||
const [canvasRect, setCanvasRect] = useState([])
|
||||
const [isShowTip, setIsShowTip] = useState(true)
|
||||
import React, { memo, useEffect, useState } from 'react';
|
||||
import { useDrop } from 'react-dnd';
|
||||
import Draggable from 'react-draggable';
|
||||
import GridLayout from 'react-grid-layout';
|
||||
import { Tooltip } from 'antd';
|
||||
import { connect } from 'dva';
|
||||
import DynamicEngine from 'components/DynamicEngine';
|
||||
import styles from './index.less';
|
||||
import { uuid } from '@/utils/tool';
|
||||
const SourceBox = memo(props => {
|
||||
const { pointData, scaleNum, canvasId, allType, dispatch } = props;
|
||||
const [canvasRect, setCanvasRect] = useState([]);
|
||||
const [isShowTip, setIsShowTip] = useState(true);
|
||||
const [{ isOver }, drop] = useDrop({
|
||||
accept: [],
|
||||
collect: (monitor) => ({
|
||||
accept: allType,
|
||||
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(),
|
||||
canDrop: monitor.canDrop(),
|
||||
item: monitor.getItem()
|
||||
})
|
||||
})
|
||||
item: monitor.getItem(),
|
||||
}),
|
||||
});
|
||||
|
||||
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({
|
||||
type: 'editorModal/modPointData',
|
||||
payload: { ...curPointData, point: newItem }
|
||||
})
|
||||
}
|
||||
payload: { ...curPointData, point: newItem },
|
||||
});
|
||||
};
|
||||
|
||||
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({
|
||||
type: 'editorModal/modPointData',
|
||||
payload: { ...curPointData }
|
||||
})
|
||||
}
|
||||
payload: { ...curPointData },
|
||||
});
|
||||
};
|
||||
|
||||
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({
|
||||
type: 'editorModal/modPointData',
|
||||
payload: { ...curPointData, point: newItem }
|
||||
})
|
||||
}
|
||||
payload: { ...curPointData, point: newItem },
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let { width, height } = document.getElementById(canvasId).getBoundingClientRect()
|
||||
setCanvasRect([width, height])
|
||||
}, [canvasId])
|
||||
let { width, height } = document.getElementById(canvasId).getBoundingClientRect();
|
||||
setCanvasRect([width, height]);
|
||||
}, [canvasId]);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setIsShowTip(false)
|
||||
}, 3000)
|
||||
}, [])
|
||||
setIsShowTip(false);
|
||||
}, 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 (
|
||||
<Draggable handle=".js_box">
|
||||
<div className={styles.canvasBox}>
|
||||
<div style={{transform: `scale(${scaleNum})`, position: 'relative', width: '100%', height: '100%'}}>
|
||||
|
||||
<div
|
||||
<div
|
||||
style={{
|
||||
transform: `scale(${scaleNum})`,
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
id={canvasId}
|
||||
className={styles.canvas}
|
||||
style={{
|
||||
opacity, backgroundColor
|
||||
}}
|
||||
ref={drop}
|
||||
className={styles.canvas}
|
||||
style={{
|
||||
opacity,
|
||||
backgroundColor,
|
||||
}}
|
||||
ref={drop}
|
||||
>
|
||||
<Tooltip placement="right" title="鼠标按住此处拖拽画布" visible={isShowTip}>
|
||||
<div
|
||||
className="js_box"
|
||||
<div
|
||||
className="js_box"
|
||||
style={{
|
||||
width: '12px',
|
||||
height: '100%',
|
||||
@ -83,39 +109,36 @@ const SourceBox = memo((props) => {
|
||||
right: '-12px',
|
||||
top: '0',
|
||||
color: '#fff',
|
||||
cursor: 'move'
|
||||
cursor: 'move',
|
||||
}}
|
||||
/>
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
{
|
||||
pointData.length > 0 ?
|
||||
<GridLayout
|
||||
className={styles.layout}
|
||||
cols={24}
|
||||
rowHeight={2}
|
||||
width={canvasRect[0]}
|
||||
margin={[0,0]}
|
||||
|
||||
{pointData.length > 0 ? (
|
||||
<GridLayout
|
||||
className={styles.layout}
|
||||
cols={24}
|
||||
rowHeight={2}
|
||||
width={canvasRect[0]}
|
||||
margin={[0, 0]}
|
||||
onDragStop={dragStop}
|
||||
onDragStart={onDragStart}
|
||||
onResizeStop={onResizeStop}
|
||||
>
|
||||
{
|
||||
pointData.map(value =>
|
||||
<div className={styles.dragItem} key={value.id} data-grid={value.point}>
|
||||
<DynamicEngine {...value.item} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</GridLayout> : null
|
||||
}
|
||||
{pointData.map(value => (
|
||||
<div className={styles.dragItem} key={value.id} data-grid={value.point}>
|
||||
<DynamicEngine {...value.item} />
|
||||
</div>
|
||||
))}
|
||||
</GridLayout>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Draggable>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export default connect(({ editorModal: { pointData } }) => ({
|
||||
pointData
|
||||
}))(SourceBox)
|
||||
pointData,
|
||||
}))(SourceBox);
|
||||
|
||||
@ -1,61 +1,45 @@
|
||||
import React, { useMemo, memo } from 'react'
|
||||
import { useDrag } from 'react-dnd'
|
||||
import { connect } from 'dva'
|
||||
import schema from 'components/DynamicEngine/schema'
|
||||
import { uuid } from '@/utils/tool';
|
||||
import styles from './index.less'
|
||||
import React, { useMemo, memo } from 'react';
|
||||
import { useDrag, DragPreviewImage } from 'react-dnd';
|
||||
import { connect } from 'dva';
|
||||
import schema from 'components/DynamicEngine/schema';
|
||||
|
||||
const TargetBox = memo((props) => {
|
||||
const { item, dispatch, canvasId, pointData } = props
|
||||
const [{ isDragging }, drag] = useDrag({
|
||||
item: { type: item.type, config: schema[item.type].config, h: item.h, editableEl: schema[item.type].editData },
|
||||
collect: (monitor) => ({
|
||||
import styles from './index.less';
|
||||
|
||||
const TargetBox = memo(props => {
|
||||
const { item, dispatch, canvasId, pointData } = props;
|
||||
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(),
|
||||
}),
|
||||
// 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(
|
||||
() => ({
|
||||
opacity: isDragging ? 0.4 : 1,
|
||||
cursor: 'move'
|
||||
cursor: 'move',
|
||||
}),
|
||||
[isDragging],
|
||||
)
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.module}
|
||||
style={{ ...containerStyle}}
|
||||
ref={drag}
|
||||
>
|
||||
{ props.children }
|
||||
<div className={styles.module} style={{ ...containerStyle }} ref={drag}>
|
||||
{props.children}
|
||||
{item.type === 'Carousel' && (
|
||||
<DragPreviewImage
|
||||
connect={preview}
|
||||
src={'https://www.easyicon.net/api/resizeApi.php?id=1200841&size=32'}
|
||||
></DragPreviewImage>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export default connect(({ editorModal: { pointData } }) => ({
|
||||
pointData
|
||||
}))(TargetBox)
|
||||
pointData,
|
||||
}))(TargetBox);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user