mirror of
https://github.com/MrXujiang/h5-Dooring.git
synced 2025-12-11 17:32:50 +00:00
🆕 添加右键菜单,支持删除和复制组件 🆕 添加帮助引导
This commit is contained in:
parent
a7132c2c99
commit
68eedbd245
@ -34,6 +34,10 @@ export default defineConfig({
|
||||
path: '/ide',
|
||||
component: '../pages/ide',
|
||||
},
|
||||
{
|
||||
path: '/help',
|
||||
component: '../pages/help',
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
component: '../pages/login',
|
||||
|
||||
@ -70,6 +70,7 @@
|
||||
"react": "^16.12.0",
|
||||
"react-codemirror2": "^7.2.1",
|
||||
"react-color": "^2.18.1",
|
||||
"react-contexify": "^4.1.1",
|
||||
"react-dnd": "^11.1.3",
|
||||
"react-dnd-html5-backend": "^11.1.3",
|
||||
"react-dom": "^16.12.0",
|
||||
|
||||
BIN
src/assets/1.png
Executable file
BIN
src/assets/1.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
src/assets/2.png
Executable file
BIN
src/assets/2.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
BIN
src/assets/3.png
Executable file
BIN
src/assets/3.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 144 KiB |
BIN
src/assets/4.png
Executable file
BIN
src/assets/4.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
src/assets/5.png
Executable file
BIN
src/assets/5.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
BIN
src/assets/6.png
Executable file
BIN
src/assets/6.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
@ -2,13 +2,14 @@ import React, { memo, useCallback, useContext, useEffect, useMemo, useState } fr
|
||||
import { useDrop } from 'react-dnd';
|
||||
import Draggable, { DraggableData, DraggableEvent } from 'react-draggable';
|
||||
import GridLayout, { ItemCallback } 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';
|
||||
import { Dispatch } from 'umi';
|
||||
import { StateWithHistory } from 'redux-undo';
|
||||
import { Menu, Item, MenuProvider } from 'react-contexify';
|
||||
import 'react-contexify/dist/ReactContexify.min.css';
|
||||
import { dooringContext } from '@/layouts';
|
||||
interface SourceBoxProps {
|
||||
pstate: { pointData: { id: string; item: any; point: any; isMenu?: any }[]; curPoint: any };
|
||||
@ -148,6 +149,43 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
||||
}))
|
||||
);
|
||||
};
|
||||
|
||||
const handleContextMenuDel = () => {
|
||||
if (pstate.curPoint) {
|
||||
dispatch({
|
||||
type: 'editorModal/delPointData',
|
||||
payload: { id: pstate.curPoint.id },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleContextMenuCopy = () => {
|
||||
if (pstate.curPoint) {
|
||||
dispatch({
|
||||
type: 'editorModal/copyPointData',
|
||||
payload: { id: pstate.curPoint.id },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onConTextClick = (type: string) => {
|
||||
if (type === 'del') {
|
||||
handleContextMenuDel();
|
||||
} else if (type === 'copy') {
|
||||
handleContextMenuCopy();
|
||||
}
|
||||
};
|
||||
|
||||
const MyAwesomeMenu = useCallback(
|
||||
() => (
|
||||
<Menu id="menu_id">
|
||||
<Item onClick={() => onConTextClick('copy')}>复制</Item>
|
||||
<Item onClick={() => onConTextClick('del')}>删除</Item>
|
||||
</Menu>
|
||||
),
|
||||
[onConTextClick],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
let { width, height } = document.getElementById(canvasId)!.getBoundingClientRect();
|
||||
console.log(width, height);
|
||||
@ -176,57 +214,59 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
||||
}}
|
||||
>
|
||||
<div className={styles.canvasBox}>
|
||||
<div
|
||||
style={{
|
||||
transform: `scale(${scaleNum})`,
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<MenuProvider id="menu_id">
|
||||
<div
|
||||
id={canvasId}
|
||||
className={styles.canvas}
|
||||
style={{
|
||||
opacity,
|
||||
transform: `scale(${scaleNum})`,
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
ref={drop}
|
||||
>
|
||||
{pointData.length > 0 ? (
|
||||
<GridLayout
|
||||
className={styles.layout}
|
||||
cols={24}
|
||||
rowHeight={2}
|
||||
width={canvasRect[0] || 0}
|
||||
margin={[0, 0]}
|
||||
onDragStop={dragStop}
|
||||
onDragStart={onDragStart}
|
||||
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
|
||||
className={styles.tooltip}
|
||||
style={{ display: value.isMenu ? 'block' : 'none' }}
|
||||
<div
|
||||
id={canvasId}
|
||||
className={styles.canvas}
|
||||
style={{
|
||||
opacity,
|
||||
}}
|
||||
ref={drop}
|
||||
>
|
||||
{pointData.length > 0 ? (
|
||||
<GridLayout
|
||||
className={styles.layout}
|
||||
cols={24}
|
||||
rowHeight={2}
|
||||
width={canvasRect[0] || 0}
|
||||
margin={[0, 0]}
|
||||
onDragStop={dragStop}
|
||||
onDragStart={onDragStart}
|
||||
onResizeStop={onResizeStop}
|
||||
>
|
||||
{pointData.map(value => (
|
||||
<div
|
||||
className={value.isMenu ? styles.selected : styles.dragItem}
|
||||
key={value.id}
|
||||
data-grid={value.point}
|
||||
>
|
||||
<div className="tooltipRow1">
|
||||
<a>恢复</a>
|
||||
</div>
|
||||
<div className="tooltipRow2">
|
||||
<a>删除</a>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
))}
|
||||
</GridLayout>
|
||||
) : null}
|
||||
<DynamicEngine {...value.item} isTpl={false} />
|
||||
{/* <div
|
||||
className={styles.tooltip}
|
||||
style={{ display: value.isMenu ? 'block' : 'none' }}
|
||||
>
|
||||
<div className="tooltipRow1">
|
||||
<a>恢复</a>
|
||||
</div>
|
||||
<div className="tooltipRow2">
|
||||
<a>删除</a>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
))}
|
||||
</GridLayout>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MenuProvider>
|
||||
</div>
|
||||
</Draggable>
|
||||
);
|
||||
@ -356,7 +396,12 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
||||
clonePointData,
|
||||
]);
|
||||
|
||||
return <>{render}</>;
|
||||
return (
|
||||
<>
|
||||
{render}
|
||||
<MyAwesomeMenu />
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export default connect((state: StateWithHistory<any>) => ({
|
||||
|
||||
@ -142,6 +142,10 @@ const HeaderComponent = memo((props: HeaderComponentProps) => {
|
||||
});
|
||||
};
|
||||
|
||||
const toHelp = () => {
|
||||
window.open('/help');
|
||||
};
|
||||
|
||||
const toBack = () => {
|
||||
history.push('/');
|
||||
};
|
||||
@ -262,6 +266,15 @@ const HeaderComponent = memo((props: HeaderComponentProps) => {
|
||||
<Button type="link" onClick={toPreview} disabled={!pointData.length}>
|
||||
预览
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
style={{ marginRight: '9px' }}
|
||||
onClick={toHelp}
|
||||
disabled={!pointData.length}
|
||||
title="使用帮助"
|
||||
>
|
||||
帮助
|
||||
</Button>
|
||||
</div>
|
||||
<div className={styles.btnArea}>
|
||||
<Select
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
* @LastEditors: dragon
|
||||
* @LastEditTime: 2020-10-08 16:12:26
|
||||
*/
|
||||
import { uuid } from '@/utils/tool';
|
||||
const pointData = localStorage.getItem('userData') || '[]';
|
||||
|
||||
function overSave(name, data) {
|
||||
@ -43,6 +44,22 @@ export default {
|
||||
curPoint: payload,
|
||||
};
|
||||
},
|
||||
copyPointData(state, { payload }) {
|
||||
const { id } = payload;
|
||||
const pointData = [];
|
||||
state.pointData.forEach(item => {
|
||||
pointData.push({ ...item });
|
||||
if (item.id === id) {
|
||||
pointData.push({ ...item, id: uuid(6, 10) });
|
||||
}
|
||||
});
|
||||
overSave('userData', pointData);
|
||||
|
||||
return {
|
||||
...state,
|
||||
pointData,
|
||||
};
|
||||
},
|
||||
delPointData(state, { payload }) {
|
||||
const { id } = payload;
|
||||
const pointData = state.pointData.filter(item => item.id !== id);
|
||||
|
||||
23
src/pages/help/index.less
Normal file
23
src/pages/help/index.less
Normal file
@ -0,0 +1,23 @@
|
||||
.helpWrap {
|
||||
width: 880px;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
margin: 0 auto;
|
||||
padding-top: 20px;
|
||||
background-color: #fff;
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
.helpItem {
|
||||
border-bottom: 1px dashed #ccc;
|
||||
margin-bottom: 20px;
|
||||
h3 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.imgWrap {
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/pages/help/index.tsx
Normal file
54
src/pages/help/index.tsx
Normal file
@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import A from '@/assets/1.png';
|
||||
import B from '@/assets/2.png';
|
||||
import C from '@/assets/3.png';
|
||||
import D from '@/assets/4.png';
|
||||
import E from '@/assets/5.png';
|
||||
import F from '@/assets/6.png';
|
||||
import styles from './index.less';
|
||||
|
||||
const Help = () => {
|
||||
return (
|
||||
<div className={styles.helpWrap}>
|
||||
<h2>H5-Dooring使用指南</h2>
|
||||
<div className={styles.helpItem}>
|
||||
<h3>1. 首页功能介绍</h3>
|
||||
<div className={styles.imgWrap}>
|
||||
<img src={A} alt="H5编辑器, H5制作, H5设计" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.helpItem}>
|
||||
<h3>2. 客服机器人</h3>
|
||||
<div className={styles.imgWrap}>
|
||||
<img src={B} alt="H5编辑器, H5制作, H5设计" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.helpItem}>
|
||||
<h3>3. 编辑器页面使用说明</h3>
|
||||
<div className={styles.imgWrap}>
|
||||
<img src={C} alt="H5编辑器, H5制作, H5设计" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.helpItem}>
|
||||
<h3>4. 管理后台入口</h3>
|
||||
<div className={styles.imgWrap}>
|
||||
<img src={D} alt="H5编辑器, H5制作, H5设计" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.helpItem}>
|
||||
<h3>5. 页面管理系统使用</h3>
|
||||
<div className={styles.imgWrap}>
|
||||
<img src={E} alt="H5编辑器, H5制作, H5设计" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.helpItem}>
|
||||
<h3>6. 页面数据分析, 数据收集</h3>
|
||||
<div className={styles.imgWrap}>
|
||||
<img src={F} alt="H5编辑器, H5制作, H5设计" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Help;
|
||||
@ -11791,6 +11791,14 @@ react-color@^2.18.1:
|
||||
reactcss "^1.2.0"
|
||||
tinycolor2 "^1.4.1"
|
||||
|
||||
react-contexify@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-contexify/-/react-contexify-4.1.1.tgz#f5eba1ad82a923c033c91d0abcea1da0a71ebaa1"
|
||||
integrity sha512-WJeRI4ohHEOmNiH0xb62a/eV+5ae168FB7H6pfbeEVJkf0UN7D5H99l6b89poc2LHKN1gOimFjREyY8quGVsXA==
|
||||
dependencies:
|
||||
classnames "^2.2.6"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
react-dnd-html5-backend@^11.1.3:
|
||||
version "11.1.3"
|
||||
resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-11.1.3.tgz#2749f04f416ec230ea193f5c1fbea2de7dffb8f7"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user