mirror of
https://github.com/MrXujiang/h5-Dooring.git
synced 2025-12-15 04:12:49 +00:00
commit
b9219c9ebc
@ -1,5 +1,6 @@
|
|||||||
const template = {
|
const template = {
|
||||||
type: 'Footer',
|
type: 'Footer',
|
||||||
h: 24,
|
h: 24,
|
||||||
|
x: 12,
|
||||||
};
|
};
|
||||||
export default template;
|
export default template;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
const template = {
|
const template = {
|
||||||
type: 'Header',
|
type: 'Header',
|
||||||
h: 28,
|
h: 28,
|
||||||
|
x: 12,
|
||||||
};
|
};
|
||||||
export default template;
|
export default template;
|
||||||
|
|||||||
@ -1,23 +1,32 @@
|
|||||||
import { dynamic } from 'umi';
|
import { dynamic } from 'umi';
|
||||||
import Loading from '../LoadingCp';
|
import Loading from '../LoadingCp';
|
||||||
import { useMemo, memo, FC } from 'react';
|
import { useMemo, memo, FC, useContext } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { dooringContext, dooringContextType } from '@/layouts';
|
||||||
// import { AllTemplateType } from './schema';
|
// import { AllTemplateType } from './schema';
|
||||||
|
|
||||||
export type componentsType = 'media' | 'base' | 'visible';
|
export type componentsType = 'media' | 'base' | 'visible';
|
||||||
|
|
||||||
const DynamicFunc = (type: string, componentsType: string) =>
|
const DynamicFunc = (type: string, componentsType: string, context: dooringContextType) => {
|
||||||
dynamic({
|
const prefix = context === 'pc' ? 'Pc' : '';
|
||||||
|
return dynamic({
|
||||||
loader: async function() {
|
loader: async function() {
|
||||||
let Component: FC<{ isTpl: boolean }>;
|
let Component: FC<{ isTpl: boolean }>;
|
||||||
|
|
||||||
if (componentsType === 'base') {
|
if (componentsType === 'base') {
|
||||||
const { default: Graph } = await import(`@/components/BasicShop/BasicComponents/${type}`);
|
const { default: Graph } = await import(
|
||||||
|
`@/components/Basic${prefix}Shop/BasicComponents/${type}`
|
||||||
|
);
|
||||||
Component = Graph;
|
Component = Graph;
|
||||||
} else if (componentsType === 'media') {
|
} else if (componentsType === 'media') {
|
||||||
const { default: Graph } = await import(`@/components/BasicShop/MediaComponents/${type}`);
|
const { default: Graph } = await import(
|
||||||
|
`@/components/Basic${prefix}Shop/MediaComponents/${type}`
|
||||||
|
);
|
||||||
Component = Graph;
|
Component = Graph;
|
||||||
} else {
|
} else {
|
||||||
const { default: Graph } = await import(`@/components/BasicShop/VisualComponents/${type}`);
|
const { default: Graph } = await import(
|
||||||
|
`@/components/Basic${prefix}Shop/VisualComponents/${type}`
|
||||||
|
);
|
||||||
Component = Graph;
|
Component = Graph;
|
||||||
}
|
}
|
||||||
return (props: DynamicType) => {
|
return (props: DynamicType) => {
|
||||||
@ -31,6 +40,7 @@ const DynamicFunc = (type: string, componentsType: string) =>
|
|||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
type DynamicType = {
|
type DynamicType = {
|
||||||
isTpl: boolean;
|
isTpl: boolean;
|
||||||
@ -41,10 +51,11 @@ type DynamicType = {
|
|||||||
};
|
};
|
||||||
const DynamicEngine = memo((props: DynamicType) => {
|
const DynamicEngine = memo((props: DynamicType) => {
|
||||||
const { type, config, category } = props;
|
const { type, config, category } = props;
|
||||||
|
const context = useContext(dooringContext);
|
||||||
const Dynamic = useMemo(() => {
|
const Dynamic = useMemo(() => {
|
||||||
return (DynamicFunc(type, category) as unknown) as FC<DynamicType>;
|
return (DynamicFunc(type, category, context.theme) as unknown) as FC<DynamicType>;
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [config]);
|
}, [config, context.theme]);
|
||||||
|
|
||||||
return <Dynamic {...props} />;
|
return <Dynamic {...props} />;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import React, { useCallback, useState } from 'react';
|
import React, { createContext, useCallback, useState } from 'react';
|
||||||
import { library, generateRespones, RenderList, useRegister } from 'chatbot-antd';
|
import { library, generateRespones, RenderList, useRegister } from 'chatbot-antd';
|
||||||
import { IRouteComponentProps } from 'umi';
|
import { IRouteComponentProps } from 'umi';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import { CustomerServiceOutlined } from '@ant-design/icons';
|
import { CustomerServiceOutlined } from '@ant-design/icons';
|
||||||
|
import { stat } from 'fs/promises';
|
||||||
|
|
||||||
library.push(
|
library.push(
|
||||||
//语料库,push进去,也可以不用
|
//语料库,push进去,也可以不用
|
||||||
@ -21,6 +22,17 @@ library.push(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export type dooringContextType = 'h5' | 'pc';
|
||||||
|
|
||||||
|
export interface IdooringContextType {
|
||||||
|
theme: dooringContextType;
|
||||||
|
setTheme: Function;
|
||||||
|
}
|
||||||
|
export const dooringContext = createContext<IdooringContextType>({
|
||||||
|
theme: 'h5',
|
||||||
|
setTheme: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
export default function Layout({ children }: IRouteComponentProps) {
|
export default function Layout({ children }: IRouteComponentProps) {
|
||||||
const [modalOpen, setModalOpen] = useState(false);
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
const callb = useCallback((v: RenderList) => {
|
const callb = useCallback((v: RenderList) => {
|
||||||
@ -46,7 +58,16 @@ export default function Layout({ children }: IRouteComponentProps) {
|
|||||||
{},
|
{},
|
||||||
<div>welcome!欢迎使用h5-Dooring,你有任何问题,都可以咨询我哦~</div>,
|
<div>welcome!欢迎使用h5-Dooring,你有任何问题,都可以咨询我哦~</div>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [state, setState] = useState<dooringContextType>('h5');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<dooringContext.Provider
|
||||||
|
value={{
|
||||||
|
theme: state,
|
||||||
|
setTheme: setState,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div style={{ height: '100%', width: '100%' }}>
|
<div style={{ height: '100%', width: '100%' }}>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@ -64,5 +85,6 @@ export default function Layout({ children }: IRouteComponentProps) {
|
|||||||
{render}
|
{render}
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
</dooringContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect, useMemo } from 'react';
|
import React, { useState, useEffect, useMemo, useContext } from 'react';
|
||||||
import { Slider, Result, Tabs, Alert } from 'antd';
|
import { Slider, Result, Tabs, Alert } from 'antd';
|
||||||
import {
|
import {
|
||||||
PieChartOutlined,
|
PieChartOutlined,
|
||||||
@ -15,24 +15,82 @@ import TargetBox from './TargetBox';
|
|||||||
import Calibration from 'components/Calibration';
|
import Calibration from 'components/Calibration';
|
||||||
import DynamicEngine, { componentsType } from 'components/DynamicEngine';
|
import DynamicEngine, { componentsType } from 'components/DynamicEngine';
|
||||||
import FormEditor from 'components/PanelComponents/FormEditor';
|
import FormEditor from 'components/PanelComponents/FormEditor';
|
||||||
import template from 'components/BasicShop/BasicComponents/template';
|
|
||||||
import mediaTpl from 'components/BasicShop/MediaComponents/template';
|
import template1 from 'components/BasicShop/BasicComponents/template';
|
||||||
import graphTpl from 'components/BasicShop/VisualComponents/template';
|
import template2 from 'components/BasicPcShop/BasicComponents/template';
|
||||||
import schema from 'components/BasicShop/schema';
|
import mediaTpl1 from 'components/BasicShop/MediaComponents/template';
|
||||||
|
import mediaTpl2 from 'components/BasicPcShop/MediaComponents/template';
|
||||||
|
import graphTpl1 from 'components/BasicShop/VisualComponents/template';
|
||||||
|
import graphTpl2 from 'components/BasicPcShop/VisualComponents/template';
|
||||||
|
|
||||||
|
import schema1 from 'components/BasicShop/schema';
|
||||||
|
import schema2 from 'components/BasicPcShop/schema';
|
||||||
|
|
||||||
import { ActionCreators } from 'redux-undo';
|
import { ActionCreators } from 'redux-undo';
|
||||||
import { StateWithHistory } from 'redux-undo';
|
import { StateWithHistory } from 'redux-undo';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import { useGetBall } from 'react-draggable-ball';
|
import { useGetBall } from 'react-draggable-ball';
|
||||||
|
import { useAnimation } from '@/utils/tool';
|
||||||
|
import { dooringContext } from '@/layouts';
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
|
|
||||||
const Container = (props: { history?: any; location?: any; pstate?: any; dispatch?: any }) => {
|
const Container = (props: {
|
||||||
|
history?: any;
|
||||||
|
location?: any;
|
||||||
|
pstate?: any;
|
||||||
|
cstate?: any;
|
||||||
|
dispatch?: any;
|
||||||
|
}) => {
|
||||||
const [scaleNum, setScale] = useState(1);
|
const [scaleNum, setScale] = useState(1);
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(true);
|
||||||
|
|
||||||
|
const { pstate, cstate, dispatch } = props;
|
||||||
|
const pointData = pstate ? pstate.pointData : [];
|
||||||
|
const cpointData = cstate ? cstate.pointData : [];
|
||||||
|
|
||||||
|
const context = useContext(dooringContext);
|
||||||
|
const curPoint = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
|
return pstate ? pstate.curPoint : {};
|
||||||
|
} else {
|
||||||
|
return cstate ? cstate.curPoint : {};
|
||||||
|
}
|
||||||
|
}, [context.theme, cstate, pstate]);
|
||||||
|
|
||||||
|
const schema = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
|
return schema1;
|
||||||
|
} else {
|
||||||
|
console.log(schema2);
|
||||||
|
return schema2;
|
||||||
|
}
|
||||||
|
}, [context.theme]);
|
||||||
|
|
||||||
|
const template = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
|
return template1;
|
||||||
|
} else {
|
||||||
|
return template2;
|
||||||
|
}
|
||||||
|
}, [context.theme]);
|
||||||
|
|
||||||
|
const mediaTpl = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
|
return mediaTpl1;
|
||||||
|
} else {
|
||||||
|
return mediaTpl2;
|
||||||
|
}
|
||||||
|
}, [context.theme]);
|
||||||
|
|
||||||
|
const graphTpl = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
|
return graphTpl1;
|
||||||
|
} else {
|
||||||
|
return graphTpl2;
|
||||||
|
}
|
||||||
|
}, [context.theme]);
|
||||||
|
|
||||||
const { pstate, dispatch } = props;
|
|
||||||
const pointData = pstate ? pstate.pointData : {};
|
|
||||||
const curPoint = pstate ? pstate.curPoint : {};
|
|
||||||
// 指定画布的id
|
// 指定画布的id
|
||||||
let canvasId = 'js_canvas';
|
let canvasId = 'js_canvas';
|
||||||
|
|
||||||
@ -41,6 +99,7 @@ const Container = (props: { history?: any; location?: any; pstate?: any; dispatc
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleCollapsed = (checked: boolean) => {
|
const toggleCollapsed = (checked: boolean) => {
|
||||||
|
console.log(checked);
|
||||||
setCollapsed(checked);
|
setCollapsed(checked);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,23 +128,51 @@ const Container = (props: { history?: any; location?: any; pstate?: any; dispatc
|
|||||||
setScale(prev => (prev <= 0.5 ? 0.5 : prev - 0.1));
|
setScale(prev => (prev <= 0.5 ? 0.5 : prev - 0.1));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleFormSave = (data: any) => {
|
|
||||||
|
const handleFormSave = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
|
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 {
|
||||||
const clearData = () => {
|
return (data: any) => {
|
||||||
dispatch({ type: 'editorModal/clearAll' });
|
dispatch({
|
||||||
|
type: 'editorPcModal/modPointData',
|
||||||
|
payload: { ...curPoint, item: { ...curPoint.item, config: data } },
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
}, [context.theme, curPoint, dispatch]);
|
||||||
|
|
||||||
const handleDel = (id: any) => {
|
const clearData = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
|
dispatch({ type: 'editorModal/clearAll' });
|
||||||
|
} else {
|
||||||
|
dispatch({ type: 'editorPcModal/clearAll' });
|
||||||
|
}
|
||||||
|
}, [context.theme, dispatch]);
|
||||||
|
|
||||||
|
const handleDel = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
|
return (id: any) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'editorModal/delPointData',
|
type: 'editorModal/delPointData',
|
||||||
payload: { id },
|
payload: { id },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
return (id: any) => {
|
||||||
|
dispatch({
|
||||||
|
type: 'editorPcModal/delPointData',
|
||||||
|
payload: { id },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, [context.theme, dispatch]);
|
||||||
|
|
||||||
const redohandler = () => {
|
const redohandler = () => {
|
||||||
dispatch(ActionCreators.redo());
|
dispatch(ActionCreators.redo());
|
||||||
};
|
};
|
||||||
@ -120,18 +207,81 @@ const Container = (props: { history?: any; location?: any; pstate?: any; dispatc
|
|||||||
intervalDelay: 5,
|
intervalDelay: 5,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [display] = useAnimation(collapsed, 500);
|
||||||
|
|
||||||
|
const renderRight = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
|
return (
|
||||||
|
<div className={styles.attrSetting}>
|
||||||
|
{pointData.length && curPoint ? (
|
||||||
|
<>
|
||||||
|
<div className={styles.tit}>属性设置</div>
|
||||||
|
<FormEditor
|
||||||
|
config={curPoint.item.editableEl}
|
||||||
|
uid={curPoint.id}
|
||||||
|
defaultValue={curPoint.item.config}
|
||||||
|
onSave={handleFormSave}
|
||||||
|
onDel={handleDel}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div style={{ paddingTop: '100px' }}>
|
||||||
|
<Result
|
||||||
|
status="404"
|
||||||
|
title="还没有数据哦"
|
||||||
|
subTitle="赶快拖拽组件来生成你的H5页面吧~"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div className={styles.attrSetting}>
|
||||||
|
{cpointData.length && curPoint ? (
|
||||||
|
<>
|
||||||
|
<div className={styles.tit}>属性设置</div>
|
||||||
|
<FormEditor
|
||||||
|
config={curPoint.item.editableEl}
|
||||||
|
uid={curPoint.id}
|
||||||
|
defaultValue={curPoint.item.config}
|
||||||
|
onSave={handleFormSave}
|
||||||
|
onDel={handleDel}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div style={{ paddingTop: '100px' }}>
|
||||||
|
<Result
|
||||||
|
status="404"
|
||||||
|
title="还没有数据哦"
|
||||||
|
subTitle="赶快拖拽组件来生成你的H5页面吧~"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [context.theme, cpointData.length, curPoint, handleDel, handleFormSave, pointData.length]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.editorWrap}>
|
<div className={styles.editorWrap}>
|
||||||
<HeaderComponent
|
<HeaderComponent
|
||||||
redohandler={redohandler}
|
redohandler={redohandler}
|
||||||
undohandler={undohandler}
|
undohandler={undohandler}
|
||||||
pointData={pointData}
|
pointData={context.theme === 'h5' ? pointData : cpointData}
|
||||||
clearData={clearData}
|
clearData={clearData}
|
||||||
location={props.location}
|
location={props.location}
|
||||||
toggleCollapsed={toggleCollapsed}
|
toggleCollapsed={toggleCollapsed}
|
||||||
/>
|
/>
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className={!collapsed ? styles.list : styles.collapsed}>
|
<div
|
||||||
|
className={styles.list}
|
||||||
|
style={{
|
||||||
|
transform: collapsed ? 'translate(0,0)' : 'translate(-100%,0)',
|
||||||
|
transition: 'all ease-in-out 0.5s',
|
||||||
|
display: display ? 'none' : 'block',
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className={styles.searchBar}>
|
<div className={styles.searchBar}>
|
||||||
<Alert
|
<Alert
|
||||||
banner
|
banner
|
||||||
@ -228,33 +378,12 @@ const Container = (props: { history?: any; location?: any; pstate?: any; dispatc
|
|||||||
<ExpandOutlined onClick={backSize} />
|
<ExpandOutlined onClick={backSize} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.attrSetting}>
|
{renderRight}
|
||||||
{pointData.length && curPoint ? (
|
|
||||||
<>
|
|
||||||
<div className={styles.tit}>属性设置</div>
|
|
||||||
<FormEditor
|
|
||||||
config={curPoint.item.editableEl}
|
|
||||||
uid={curPoint.id}
|
|
||||||
defaultValue={curPoint.item.config}
|
|
||||||
onSave={handleFormSave}
|
|
||||||
onDel={handleDel}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div style={{ paddingTop: '100px' }}>
|
|
||||||
<Result
|
|
||||||
status="404"
|
|
||||||
title="还没有数据哦"
|
|
||||||
subTitle="赶快拖拽组件来生成你的H5页面吧~"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect((state: StateWithHistory<any>) => {
|
export default connect((state: StateWithHistory<any>) => {
|
||||||
return { pstate: state.present.editorModal };
|
return { pstate: state.present.editorModal, cstate: state.present.editorPcModal };
|
||||||
})(Container);
|
})(Container);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { memo, useEffect, useState } from 'react';
|
import React, { memo, 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 GridLayout, { ItemCallback } from 'react-grid-layout';
|
||||||
@ -9,8 +9,10 @@ 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 { dooringContext } from '@/layouts';
|
||||||
interface SourceBoxProps {
|
interface SourceBoxProps {
|
||||||
pstate: { pointData: { id: string; item: any; point: any }[] };
|
pstate: { pointData: { id: string; item: any; point: any }[]; curPoint: any };
|
||||||
|
cstate: { pointData: { id: string; item: any; point: any }[]; curPoint: any };
|
||||||
scaleNum: number;
|
scaleNum: number;
|
||||||
canvasId: string;
|
canvasId: string;
|
||||||
allType: string[];
|
allType: string[];
|
||||||
@ -25,14 +27,17 @@ interface SourceBoxProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SourceBox = memo((props: SourceBoxProps) => {
|
const SourceBox = memo((props: SourceBoxProps) => {
|
||||||
const { pstate, scaleNum, canvasId, allType, dispatch, dragState, setDragState } = props;
|
const { pstate, scaleNum, canvasId, allType, dispatch, dragState, setDragState, cstate } = props;
|
||||||
|
const context = useContext(dooringContext);
|
||||||
|
|
||||||
const pointData = pstate ? pstate.pointData : [];
|
const pointData = pstate ? pstate.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 [{ isOver }, drop] = useDrop({
|
const [{ isOver }, drop] = useDrop({
|
||||||
accept: allType,
|
accept: allType,
|
||||||
drop: (item: { h: number; type: string }, monitor) => {
|
drop: (item: { h: number; type: string; x: number }, monitor) => {
|
||||||
let parentDiv = document.getElementById(canvasId),
|
let parentDiv = document.getElementById(canvasId),
|
||||||
pointRect = parentDiv!.getBoundingClientRect(),
|
pointRect = parentDiv!.getBoundingClientRect(),
|
||||||
top = pointRect.top,
|
top = pointRect.top,
|
||||||
@ -43,6 +48,7 @@ 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: {
|
||||||
@ -51,6 +57,24 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
point: { i: `x-${pointData.length}`, x: 0, y: gridY, w, h: item.h, isBounded: true },
|
point: { i: `x-${pointData.length}`, x: 0, y: gridY, w, h: item.h, isBounded: true },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
console.log(item.x);
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
collect: monitor => ({
|
collect: monitor => ({
|
||||||
isOver: monitor.isOver(),
|
isOver: monitor.isOver(),
|
||||||
@ -59,34 +83,65 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const dragStop: ItemCallback = (layout, oldItem, newItem, placeholder, e, element) => {
|
const dragStop: ItemCallback = useMemo(() => {
|
||||||
|
return (layout, oldItem, newItem, placeholder, e, element) => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
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 },
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const curPointData = cpointData.filter(item => item.id === newItem.i)[0];
|
||||||
|
dispatch({
|
||||||
|
type: 'editorPcModal/modPointData',
|
||||||
|
payload: { ...curPointData, point: newItem },
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
}, [context.theme, cpointData, dispatch, pointData]);
|
||||||
|
|
||||||
const onDragStart: ItemCallback = (layout, oldItem, newItem, placeholder, e, element) => {
|
const onDragStart: ItemCallback = useMemo(() => {
|
||||||
|
return (layout, oldItem, newItem, placeholder, e, element) => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
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 },
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const curPointData = cpointData.filter(item => item.id === newItem.i)[0];
|
||||||
|
dispatch({
|
||||||
|
type: 'editorPcModal/modPointData',
|
||||||
|
payload: { ...curPointData },
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
}, [context.theme, cpointData, dispatch, pointData]);
|
||||||
|
|
||||||
const onResizeStop: ItemCallback = (layout, oldItem, newItem, placeholder, e, element) => {
|
const onResizeStop: ItemCallback = useMemo(() => {
|
||||||
|
return (layout, oldItem, newItem, placeholder, e, element) => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
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 },
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const curPointData = cpointData.filter(item => item.id === newItem.i)[0];
|
||||||
|
dispatch({
|
||||||
|
type: 'editorPcModal/modPointData',
|
||||||
|
payload: { ...curPointData, point: newItem },
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
}, [context.theme, cpointData, dispatch, pointData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let { width, height } = document.getElementById(canvasId)!.getBoundingClientRect();
|
let { width, height } = document.getElementById(canvasId)!.getBoundingClientRect();
|
||||||
|
console.log(width, height);
|
||||||
setCanvasRect([width, height]);
|
setCanvasRect([width, height]);
|
||||||
}, [canvasId]);
|
}, [canvasId, context.theme]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let timer = window.setTimeout(() => {
|
let timer = window.setTimeout(() => {
|
||||||
@ -99,6 +154,8 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
const opacity = isOver ? 0.7 : 1;
|
const opacity = isOver ? 0.7 : 1;
|
||||||
// const backgroundColor = isOver ? 1 : 0.7;
|
// const backgroundColor = isOver ? 1 : 0.7;
|
||||||
|
|
||||||
|
const render = useMemo(() => {
|
||||||
|
if (context.theme === 'h5') {
|
||||||
return (
|
return (
|
||||||
<Draggable
|
<Draggable
|
||||||
position={dragState}
|
position={dragState}
|
||||||
@ -164,8 +221,95 @@ const SourceBox = memo((props: SourceBoxProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</Draggable>
|
</Draggable>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
//pc可能要传递宽度
|
||||||
|
return (
|
||||||
|
<Draggable
|
||||||
|
position={dragState}
|
||||||
|
handle=".js_box"
|
||||||
|
onStop={(e: DraggableEvent, data: DraggableData) => {
|
||||||
|
setDragState({ x: data.x, y: data.y });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className={styles.canvasBox2}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
transform: `scale(${scaleNum - 0.2})`,
|
||||||
|
position: 'relative',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
id={canvasId}
|
||||||
|
className={styles.canvas2}
|
||||||
|
style={{
|
||||||
|
opacity,
|
||||||
|
}}
|
||||||
|
ref={drop}
|
||||||
|
>
|
||||||
|
<Tooltip placement="right" title="鼠标按住此处拖拽画布" visible={isShowTip}>
|
||||||
|
<div
|
||||||
|
className="js_box"
|
||||||
|
style={{
|
||||||
|
width: '10px',
|
||||||
|
height: '100%',
|
||||||
|
position: 'absolute',
|
||||||
|
borderRadius: '0 6px 6px 0',
|
||||||
|
backgroundColor: '#2f54eb',
|
||||||
|
right: '-10px',
|
||||||
|
top: '0',
|
||||||
|
color: '#fff',
|
||||||
|
cursor: 'move',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
{cpointData.length > 0 ? (
|
||||||
|
<GridLayout
|
||||||
|
className={styles.layout}
|
||||||
|
cols={24}
|
||||||
|
rowHeight={2}
|
||||||
|
width={canvasRect[0] || 0}
|
||||||
|
margin={[0, 0]}
|
||||||
|
onDragStop={dragStop}
|
||||||
|
onDragStart={onDragStart}
|
||||||
|
onResizeStop={onResizeStop}
|
||||||
|
>
|
||||||
|
{cpointData.map(value => (
|
||||||
|
<div className={styles.dragItem} key={value.id} data-grid={value.point}>
|
||||||
|
<DynamicEngine {...value.item} isTpl={false} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</GridLayout>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
canvasId,
|
||||||
|
canvasRect,
|
||||||
|
context.theme,
|
||||||
|
cpointData,
|
||||||
|
dragState,
|
||||||
|
dragStop,
|
||||||
|
drop,
|
||||||
|
isShowTip,
|
||||||
|
onDragStart,
|
||||||
|
onResizeStop,
|
||||||
|
opacity,
|
||||||
|
pointData,
|
||||||
|
scaleNum,
|
||||||
|
setDragState,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return <>{render}</>;
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect((state: StateWithHistory<any>) => ({ pstate: state.present.editorModal }))(
|
export default connect((state: StateWithHistory<any>) => ({
|
||||||
SourceBox,
|
pstate: state.present.editorModal,
|
||||||
);
|
cstate: state.present.editorPcModal,
|
||||||
|
}))(SourceBox);
|
||||||
|
|||||||
@ -18,6 +18,7 @@ const TargetBox = memo((props: TargetBoxProps) => {
|
|||||||
h: item.h,
|
h: item.h,
|
||||||
editableEl: schema[item.type as keyof typeof schema].editData,
|
editableEl: schema[item.type as keyof typeof schema].editData,
|
||||||
category: item.category,
|
category: item.category,
|
||||||
|
x: item.x || 0,
|
||||||
},
|
},
|
||||||
collect: monitor => ({
|
collect: monitor => ({
|
||||||
isDragging: monitor.isDragging(),
|
isDragging: monitor.isDragging(),
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React, { useRef, memo } from 'react';
|
import React, { useRef, memo, useContext } from 'react';
|
||||||
import { Button, Input, Popover, Modal, Switch } from 'antd';
|
import { Button, Input, Popover, Modal, Switch, Select } from 'antd';
|
||||||
import {
|
import {
|
||||||
ArrowLeftOutlined,
|
ArrowLeftOutlined,
|
||||||
MobileOutlined,
|
MobileOutlined,
|
||||||
@ -17,6 +17,7 @@ import Zan from 'components/Zan';
|
|||||||
import req from '@/utils/req';
|
import req from '@/utils/req';
|
||||||
import Code from '@/assets/code.png';
|
import Code from '@/assets/code.png';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
import { dooringContext } from '@/layouts';
|
||||||
|
|
||||||
const { confirm } = Modal;
|
const { confirm } = Modal;
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ const HeaderComponent = memo((props: HeaderComponentProps) => {
|
|||||||
req.post('/visible/preview', { tid, tpl: pointData });
|
req.post('/visible/preview', { tid, tpl: pointData });
|
||||||
};
|
};
|
||||||
const handleSaveCode = () => {};
|
const handleSaveCode = () => {};
|
||||||
|
const { setTheme } = useContext(dooringContext);
|
||||||
return (
|
return (
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<div className={styles.logoArea}>
|
<div className={styles.logoArea}>
|
||||||
@ -136,7 +137,7 @@ const HeaderComponent = memo((props: HeaderComponentProps) => {
|
|||||||
<ArrowLeftOutlined />
|
<ArrowLeftOutlined />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.logo}>Dooring</div>
|
<div className={styles.logo}>Dooring</div>
|
||||||
{/* <Switch onChange={toggleCollapsed} style={{ marginLeft: '100px' }} />暂时隐藏 TODO */}
|
<Switch defaultChecked onChange={toggleCollapsed} style={{ marginLeft: '100px' }} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.controlArea}>
|
<div className={styles.controlArea}>
|
||||||
<Button type="primary" style={{ marginRight: '9px' }} onClick={useTemplate}>
|
<Button type="primary" style={{ marginRight: '9px' }} onClick={useTemplate}>
|
||||||
@ -211,6 +212,16 @@ const HeaderComponent = memo((props: HeaderComponentProps) => {
|
|||||||
预览
|
预览
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
<Select
|
||||||
|
defaultValue="h5"
|
||||||
|
style={{ width: 120 }}
|
||||||
|
onChange={e => {
|
||||||
|
setTheme(e);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Select.Option value="h5">h5模式</Select.Option>
|
||||||
|
<Select.Option value="pc">pc模式</Select.Option>
|
||||||
|
</Select>
|
||||||
<div className={styles.btnArea}>
|
<div className={styles.btnArea}>
|
||||||
<Zan />
|
<Zan />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -18,10 +18,10 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.container {
|
.container {
|
||||||
width: 100%; //写vw产生滚动条会出现横向滚动条
|
|
||||||
// height: 100vh;
|
// height: 100vh;
|
||||||
height: calc(100% - 56px);
|
height: calc(100% - 56px);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -56,10 +56,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tickMark {
|
.tickMark {
|
||||||
width: calc(100% - 750px);
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
.tickMarkTop {
|
.tickMarkTop {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
@ -108,6 +108,40 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.canvasBox2 {
|
||||||
|
width: 1200px;
|
||||||
|
min-height: 800px;
|
||||||
|
height: 800px;
|
||||||
|
left: 15%;
|
||||||
|
position: relative;
|
||||||
|
margin-left: -200px;
|
||||||
|
top: 20px;
|
||||||
|
.canvas2 {
|
||||||
|
position: relative;
|
||||||
|
width: 1200px;
|
||||||
|
min-height: 800px;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 2px 0px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
transition: transform 300ms ease-out;
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.resetBall {
|
.resetBall {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 24px;
|
right: 24px;
|
||||||
@ -152,6 +186,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
box-shadow: -2px 0px 4px 0px rgba(0, 0, 0, 0.1);
|
box-shadow: -2px 0px 4px 0px rgba(0, 0, 0, 0.1);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
.tit {
|
.tit {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
@ -205,10 +240,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.collapsed {
|
|
||||||
.list;
|
|
||||||
height: calc(56px);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
58
src/pages/editor/models/editorPcModel.ts
Normal file
58
src/pages/editor/models/editorPcModel.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
const pointData = localStorage.getItem('userPcData') || '[]';
|
||||||
|
|
||||||
|
function overSave(name: string, data: any) {
|
||||||
|
localStorage.setItem(name, JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
namespace: 'editorPcModal',
|
||||||
|
state: {
|
||||||
|
pointData: JSON.parse(pointData),
|
||||||
|
curPoint: null,
|
||||||
|
},
|
||||||
|
reducers: {
|
||||||
|
addPointData(state: any, { payload }: any) {
|
||||||
|
let pointData = [...state.pointData, payload];
|
||||||
|
overSave('userPcData', pointData);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pointData,
|
||||||
|
curPoint: payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
modPointData(state: any, { payload }: any) {
|
||||||
|
const { id } = payload;
|
||||||
|
const pointData = state.pointData.map((item: any) => {
|
||||||
|
if (item.id === id) {
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
return { ...item };
|
||||||
|
});
|
||||||
|
overSave('userPcData', pointData);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pointData,
|
||||||
|
curPoint: payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
delPointData(state: any, { payload }: any) {
|
||||||
|
const { id } = payload;
|
||||||
|
const pointData = state.pointData.filter((item: any) => item.id !== id);
|
||||||
|
overSave('userPcData', pointData);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pointData,
|
||||||
|
curPoint: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
clearAll(state: any) {
|
||||||
|
overSave('userPcData', []);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pointData: [],
|
||||||
|
curPoint: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
effects: {},
|
||||||
|
};
|
||||||
@ -63,3 +63,21 @@ export function useGetScrollBarWidth(ref: RefObject<HTMLElement>) {
|
|||||||
}, [ref]);
|
}, [ref]);
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useAnimation(state: boolean, delay: number) {
|
||||||
|
const [display, setDisplay] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
let timer: number;
|
||||||
|
if (state && display === true) {
|
||||||
|
setDisplay(false);
|
||||||
|
} else if (!state && display === false) {
|
||||||
|
timer = window.setTimeout(() => {
|
||||||
|
setDisplay(true);
|
||||||
|
}, delay);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
window.clearTimeout(timer);
|
||||||
|
};
|
||||||
|
}, [delay, display, state]);
|
||||||
|
return [display, setDisplay];
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user