diff --git a/package.json b/package.json index cf8a4d6..dd0fcff 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "react-draggable": "^4.4.3", "react-grid-layout": "^1.0.0", "react-text-loop": "^2.3.0", + "redux-undo": "^1.0.1", "sass-loader": "^9.0.3", "socket.io-client": "^2.3.0", "umi": "^3.2.19", @@ -80,6 +81,7 @@ "devDependencies": { "@types/classnames": "^2.2.10", "@types/react-color": "^3.0.4", + "@types/redux-logger": "^3.0.8", "@typescript-eslint/eslint-plugin": "2.x", "@typescript-eslint/parser": "2.x", "babel-eslint": "10.x", @@ -89,6 +91,7 @@ "eslint-plugin-import": "2.x", "eslint-plugin-jsx-a11y": "6.x", "eslint-plugin-react": "7.x", - "eslint-plugin-react-hooks": "2.x" + "eslint-plugin-react-hooks": "2.x", + "redux-logger": "^3.0.6" } } diff --git a/src/app.tsx b/src/app.tsx new file mode 100644 index 0000000..4e3e2c9 --- /dev/null +++ b/src/app.tsx @@ -0,0 +1,21 @@ +import { createLogger } from 'redux-logger'; +import { message } from 'antd'; +import undoable, { StateWithHistory } from 'redux-undo'; +import { Reducer, AnyAction } from 'redux'; + +export const dva = { + config: { + onAction: createLogger(), + onError(e: Error) { + message.error(e.message, 3); + }, + onReducer: (reducer: Reducer) => { + let undoReducer = undoable(reducer); + return function(state: StateWithHistory, action: AnyAction) { + let newState = undoReducer(state, action); + let router = newState.present.router ? newState.present.router : newState.present.routing; + return { ...newState, router: router }; + }; + }, + }, +}; diff --git a/src/components/Carousel/index.tsx b/src/components/Carousel/index.tsx index bfd6eb8..7140293 100644 --- a/src/components/Carousel/index.tsx +++ b/src/components/Carousel/index.tsx @@ -13,7 +13,7 @@ const XCarousel = memo((props: PropsWithChildren) => { return imgList.map((item, i) => { return (
- + 0 ? item.imgUrl[0].url : ''} alt="" />
); }); diff --git a/src/pages/editor/Container.js b/src/pages/editor/Container.js index 5a1cd6f..581bbee 100644 --- a/src/pages/editor/Container.js +++ b/src/pages/editor/Container.js @@ -18,15 +18,19 @@ 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 { ActionCreators } from 'redux-undo'; import styles from './index.less'; const { TabPane } = Tabs; -const Container = memo(props => { +const Container = props => { const [scaleNum, setScale] = useState(1); - const { pointData, curPoint, dispatch } = props; + const { pstate, dispatch } = props; + + const pointData = pstate ? pstate.pointData : {}; + const curPoint = pstate ? pstate.curPoint : {}; // 指定画布的id let canvasId = 'js_canvas'; @@ -67,9 +71,9 @@ const Container = memo(props => { }); }; - const clearData = useCallback(() => { + const clearData = () => { dispatch({ type: 'editorModal/clearAll' }); - }, []); + }; const handleDel = id => { dispatch({ @@ -77,7 +81,12 @@ const Container = memo(props => { payload: { id }, }); }; - + const redohandler = () => { + dispatch(ActionCreators.redo()); + }; + const undohandler = () => { + dispatch(ActionCreators.undo()); + }; useEffect(() => { if (window.innerWidth < 1024) { props.history.push('/mobileTip'); @@ -100,7 +109,13 @@ const Container = memo(props => { return (
- +
@@ -196,9 +211,8 @@ const Container = memo(props => {
); -}); +}; -export default connect(({ editorModal: { pointData, curPoint } }) => ({ - pointData, - curPoint, -}))(Container); +export default connect(state => { + return { pstate: state.present.editorModal }; +})(Container); diff --git a/src/pages/editor/SourceBox.js b/src/pages/editor/SourceBox.js index be25e02..26b4295 100644 --- a/src/pages/editor/SourceBox.js +++ b/src/pages/editor/SourceBox.js @@ -8,7 +8,9 @@ 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 { pstate, scaleNum, canvasId, allType, dispatch } = props; + + const pointData = pstate ? pstate.pointData : {}; const [canvasRect, setCanvasRect] = useState([]); const [isShowTip, setIsShowTip] = useState(true); const [{ isOver }, drop] = useDrop({ @@ -142,6 +144,4 @@ const SourceBox = memo(props => { ); }); -export default connect(({ editorModal: { pointData } }) => ({ - pointData, -}))(SourceBox); +export default connect(state => ({ pstate: state.present.editorModal }))(SourceBox); diff --git a/src/pages/editor/TargetBox.js b/src/pages/editor/TargetBox.js index 876766d..74c2ab0 100644 --- a/src/pages/editor/TargetBox.js +++ b/src/pages/editor/TargetBox.js @@ -1,13 +1,12 @@ import React, { useMemo, memo } from 'react'; import { useDrag } from 'react-dnd'; -import { connect } from 'dva'; import schema from 'components/DynamicEngine/schema'; import styles from './index.less'; const TargetBox = memo(props => { - const { item, dispatch, pointData } = props; - const [{ isDragging }, drag, preview] = useDrag({ + const { item } = props; + const [{ isDragging }, drag] = useDrag({ item: { type: item.type, config: schema[item.type].config, @@ -34,6 +33,4 @@ const TargetBox = memo(props => { ); }); -export default connect(({ editorModal: { pointData } }) => ({ - pointData, -}))(TargetBox); +export default TargetBox; diff --git a/src/pages/editor/components/Header/index.js b/src/pages/editor/components/Header/index.js index 4291361..788c194 100644 --- a/src/pages/editor/components/Header/index.js +++ b/src/pages/editor/components/Header/index.js @@ -6,13 +6,14 @@ import { DownloadOutlined, CopyOutlined, DeleteOutlined, + UndoOutlined, + RedoOutlined, } from '@ant-design/icons'; import QRCode from 'qrcode.react'; import { saveAs } from 'file-saver'; import Zan from 'components/Zan'; import req from '@/utils/req'; import Code from '@/assets/code.png'; - import styles from './index.less'; const { confirm } = Modal; @@ -20,7 +21,7 @@ const { confirm } = Modal; const isDev = process.env.NODE_ENV === 'development'; const HeaderComponent = memo(props => { - const { pointData, location, clearData } = props; + const { pointData, location, clearData, undohandler, redohandler } = props; const iptRef = useRef(null); const toPreview = () => { @@ -100,7 +101,6 @@ const HeaderComponent = memo(props => { const { tid } = props.location.query || ''; req.post('/visible/preview', { tid, tpl: pointData }); }; - const handleSaveCode = () => {}; return ( @@ -159,6 +159,12 @@ const HeaderComponent = memo(props => { > + + diff --git a/yarn.lock b/yarn.lock index 3df331d..f49f17b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2204,6 +2204,13 @@ dependencies: "@types/react" "*" +"@types/redux-logger@^3.0.8": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/redux-logger/-/redux-logger-3.0.8.tgz#1fb6d26917bb198792bb1cf57feb31cae1532c5d" + integrity sha512-zM+cxiSw6nZtRbxpVp9SE3x/X77Z7e7YAfHD1NkxJyJbAGSXJGF0E9aqajZfPOa/sTYnuwutmlCldveExuCeLw== + dependencies: + redux "^4.0.0" + "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.npm.taobao.org/@types/resolve/download/@types/resolve-1.17.1.tgz?cache=0&sync_timestamp=1596840738717&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fresolve%2Fdownload%2F%40types%2Fresolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -5301,6 +5308,11 @@ dedent@^0.7.0: resolved "https://registry.npm.taobao.org/dedent/download/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= +deep-diff@^0.3.5: + version "0.3.8" + resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84" + integrity sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ= + deep-is@~0.1.3: version "0.1.3" resolved "https://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -12021,11 +12033,23 @@ redeyed@~2.1.0: dependencies: esprima "~4.0.0" +redux-logger@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf" + integrity sha1-91VZZvMJjzyIYExEnPC69XeCdL8= + dependencies: + deep-diff "^0.3.5" + redux-saga@^0.16.0: version "0.16.2" resolved "https://registry.npm.taobao.org/redux-saga/download/redux-saga-0.16.2.tgz#993662e86bc945d8509ac2b8daba3a8c615cc971" integrity sha1-mTZi6GvJRdhQmsK42ro6jGFcyXE= +redux-undo@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/redux-undo/-/redux-undo-1.0.1.tgz#8d989d6c326e6718f4471042e90a5b8b6f3317eb" + integrity sha512-0yFPT+FUgwxCEiS0Mg5T1S4tkgjR8h6sJRY9CW4EMsbJOf1SxO289TbJmlzhRouCHacdDF+powPjrjLHoJYxWQ== + redux@^4.0.0, redux@^4.0.1, redux@^4.0.4: version "4.0.5" resolved "https://registry.npm.taobao.org/redux/download/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"