From d426f93080057d31ec8be6ec6908329daaf65796 Mon Sep 17 00:00:00 2001 From: fanxb Date: Thu, 18 Jul 2019 17:07:11 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Feat:=20[=E5=89=8D=E5=8F=B0]:?= =?UTF-8?q?=E4=B9=A6=E7=AD=BE=E7=AE=A1=E7=90=86=E9=A1=B5=E9=9D=A2,?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E7=BC=96=E8=BE=91,=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E6=8B=96=E6=8B=BD=E5=8A=9F=E8=83=BD=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/pages/manage/OverView/AddModal.jsx | 64 +++++++--- front/src/pages/manage/OverView/function.js | 117 +++++++++---------- front/src/pages/manage/OverView/index.jsx | 116 +++++++----------- 3 files changed, 148 insertions(+), 149 deletions(-) diff --git a/front/src/pages/manage/OverView/AddModal.jsx b/front/src/pages/manage/OverView/AddModal.jsx index e98b061..ee5fc30 100644 --- a/front/src/pages/manage/OverView/AddModal.jsx +++ b/front/src/pages/manage/OverView/AddModal.jsx @@ -2,7 +2,24 @@ import React from "react"; import { Modal, Form, Upload, Button, Radio, Input, Icon, message } from "antd"; import httpUtil from "../../../util/httpUtil"; -export default class AddModal extends React.Component { +import * as action from "../../../redux/action/BookmarkTreeOverview"; +import { connect } from "react-redux"; + +function mapStateToProps(state) { + return state[action.DATA_NAME]; +} + +function mapDispatchToProps(dispatch) { + return { + updateTreeData: treeData => dispatch(action.updateTreeData(treeData)), + setIsEdit: isEdit => dispatch(action.setIsEdit(isEdit)), + addNode: (item, e) => dispatch(action.addNode(item, e)), + editNode: (item, e) => dispatch(action.editNode(item, e)), + closeModal: () => dispatch(action.closeModal()) + }; +} + +class AddModal extends React.Component { constructor(props) { super(props); this.state = { @@ -13,6 +30,17 @@ export default class AddModal extends React.Component { }; } + componentWillReceiveProps(nextProps) { + const { currentEditNode } = nextProps; + if (currentEditNode != null) { + this.type = "edit"; + this.setState({ addType: currentEditNode.type, addName: currentEditNode.name, addValue: currentEditNode.url }); + } else { + this.type = "add"; + this.setState({ addType: 0, addName: "", addValue: "", file: null }); + } + } + submit = () => { const { currentEditNode } = this.props; if (currentEditNode == null) { @@ -36,7 +64,7 @@ export default class AddModal extends React.Component { message.success("编辑成功"); node.name = addName; node.url = addValue; - this.close(); + this.props.closeModal(); }); } @@ -44,7 +72,7 @@ export default class AddModal extends React.Component { * 新增一个节点 */ addOne() { - const { currentAddFolder, addToTree, closeModal } = this.props; + const { currentAddFolder, updateTreeData, closeModal, treeData } = this.props; const path = currentAddFolder == null ? "" : currentAddFolder.path + "." + currentAddFolder.bookmarkId; if (this.state.addType === 2) { const form = new FormData(); @@ -65,21 +93,24 @@ export default class AddModal extends React.Component { url: this.state.addValue }; httpUtil.put("/bookmark", body).then(res => { - addToTree(res); + // addToTree(res); message.success("加入成功"); + if (currentAddFolder === null) { + treeData.push(res); + } else { + //存在children说明该子节点的孩子数据已经加载,需要重新将新的子书签加入进去 + if (currentAddFolder.children) { + currentAddFolder.children.push(res); + } + } + updateTreeData(treeData); closeModal(); }); } } - close = () => { - const { closeModal } = this.props; - this.setState({ file: null, addType: 0, addValue: "", addName: "" }); - closeModal(); - }; - render() { - const { isShowModal, currentEditNode } = this.props; + const { isShowModal, currentEditNode, closeModal } = this.props; const { addType, addName, addValue } = this.state; const type = currentEditNode == null ? "add" : "edit"; const formItemLayout = { @@ -103,7 +134,7 @@ export default class AddModal extends React.Component { fileList: [] }; return ( - +
{type === "add" ? ( @@ -114,12 +145,12 @@ export default class AddModal extends React.Component { ) : null} - {addType < 2 || type === "edit" ? ( + {addType < 2 ? ( this.setState({ addName: e.target.value })} value={addName} /> ) : null} - {(addType === 0 && type === "add") || (type === "edit" && currentEditNode.type === 0) ? ( + {addType === 0 ? ( this.setState({ addValue: e.target.value })} /> @@ -142,3 +173,8 @@ export default class AddModal extends React.Component { ); } } + +export default connect( + mapStateToProps, + mapDispatchToProps +)(AddModal); diff --git a/front/src/pages/manage/OverView/function.js b/front/src/pages/manage/OverView/function.js index b3a1b15..3099092 100644 --- a/front/src/pages/manage/OverView/function.js +++ b/front/src/pages/manage/OverView/function.js @@ -5,61 +5,12 @@ import styles from "./index.module.less"; import IconFont from "../../../components/IconFont"; const { TreeNode } = Tree; -/** - * 选中的文件夹id列表 - */ -let folderIdList = []; -/** - * 选中的书签id列表 - */ -let bookmarkIdList = []; - -/** - * 展开/关闭 - * @param {*} keys - */ -export function onExpand(keys) { - this.setState({ expandKeys: keys }); -} - -/** - * 关闭全部节点 - */ -export function closeAll() { - this.setState({ expandKeys: [] }); -} - -/** - * 选中节点 - * @param {*} keys - * @param {*} data - */ -export function onCheck(keys, data) { - this.setState({ checkedKeys: keys }); - bookmarkIdList = []; - folderIdList = []; - data.checkedNodes.forEach(item => { - const bookmark = item.props.dataRef; - bookmark.type === 0 ? bookmarkIdList.push(bookmark.bookmarkId) : folderIdList.push(bookmark.bookmarkId); - }); -} - -/** - * 编辑一个节点 - * @param {*} node 节点对象 - * @param {*} e - */ -function editNode(node, e) { - e.stopPropagation(); - this.setState({ isShowModal: true, currentEditNode: node }); -} - /** * 渲染树节点中节点内容 * @param {*} item */ export function renderNodeContent(item) { - const { isEdit } = this.state; + const { isEdit, addNode, editNode } = this.props; // 节点内容后面的操作按钮 const btns = (
@@ -75,7 +26,7 @@ export function renderNodeContent(item) { title="点击复制url" /> ) : null} - {item.type === 1 ?
@@ -142,6 +93,13 @@ export function deleteOne(item, e) { * 批量删除 */ export function batchDelete() { + const { checkedNodes } = this.props; + const folderIdList = [], + bookmarkIdList = []; + checkedNodes.forEach(item => { + const data = item.props.dataRef; + data.type === 0 ? bookmarkIdList.push(data.bookmarkId) : folderIdList.push(data.bookmarkId); + }); deleteBookmark.call(this, folderIdList, bookmarkIdList); } @@ -151,7 +109,7 @@ export function batchDelete() { * @param {*} bookmarkIdList */ function deleteBookmark(folderIdList, bookmarkIdList) { - const _this = this; + const { updateTreeData, treeData, changeCheckedKeys } = this.props; Modal.confirm({ title: "确认删除?", content: "删除后,无法找回", @@ -164,8 +122,9 @@ function deleteBookmark(folderIdList, bookmarkIdList) { const set = new Set(); folderIdList.forEach(item => set.add(parseInt(item))); bookmarkIdList.forEach(item => set.add(parseInt(item))); - deleteTreeData(_this.state.treeData, set); - _this.setState({ treeData: [..._this.state.treeData], checkedKeys: [] }); + deleteTreeData(treeData, set); + changeCheckedKeys([], null); + updateTreeData([...treeData]); resolve(); }) .catch(() => reject()); @@ -191,19 +150,15 @@ function deleteTreeData(treeData, set) { } } -export function onDragEnter(info) { - // console.log(info); -} - /** * 节点拖拽 * @param {*} info */ export function onDrop(info) { - const { treeData } = this.state; + const { treeData, updateTreeData } = this.props; const target = info.node.props.dataRef; - if (!info.dropToGap && target.type === "0") { - message.error("只能移动到文件夹中"); + if (!info.dropToGap && target.type === 0) { + message.error("无法移动到书签内部"); return; } const current = info.dragNode.props.dataRef; @@ -227,14 +182,29 @@ export function onDrop(info) { body.sort = target.sort; insertToArray(current, index, targetBelowList); } - current.sort = body.sort; } else { + //移动该一个文件夹内,该文件夹可能还未加载 body.targetPath = target.path + "." + target.bookmarkId; + //存在children说明已经加载 if (target.children) { + const length = target.children.length; + body.sort = length > 0 ? target.children[length - 1].sort + 1 : 1; target.children.push(current); } } - this.setState({ treeData: [...treeData] }); + if (body.sort !== -1) { + //说明目标位置已经加载,需要更新当前节点信息 + current.path = body.targetPath; + current.sort = body.sort; + } + //如果移动的目标和当前位置不在同一个层级需要更新子节点path信息 + if (body.sourcePath !== body.targetPath) { + updateChildrenPath(current.children, body.sourcePath + "." + body.bookmarkId, body.targetPath + "." + body.bookmarkId); + } + httpUtil.post("/bookmark/moveNode", body).then(res => { + message.success("移动完成"); + }); + updateTreeData({ treeData: [...treeData] }); } /** @@ -255,6 +225,12 @@ function getBelowList(treeList, node) { } } +/** + * 往数组中插入一个节点,并让后面节点的sort+1 + * @param {*} item 节点 + * @param {*} index 插入位置 + * @param {*} arr 目标数组 + */ function insertToArray(item, index, arr) { const length = arr.length; let i = length; @@ -264,3 +240,18 @@ function insertToArray(item, index, arr) { } arr[i] = item; } + +/** + * 更新节点的path信息 + * @param {*} children 孩子数组 + * @param {*} oldPath 旧path + * @param {*} newPath 新path + */ +function updateChildrenPath(children, oldPath, newPath) { + if (children && children.length > 0) { + children.forEach(item => { + item.path = item.path.replace(oldPath, newPath); + updateChildrenPath(item.children, oldPath, newPath); + }); + } +} diff --git a/front/src/pages/manage/OverView/index.jsx b/front/src/pages/manage/OverView/index.jsx index d35df65..1d1171d 100644 --- a/front/src/pages/manage/OverView/index.jsx +++ b/front/src/pages/manage/OverView/index.jsx @@ -3,25 +3,29 @@ import { Tree, Empty, Button } from "antd"; import MainLayout from "../../../layout/MainLayout"; import httpUtil from "../../../util/httpUtil"; import styles from "./index.module.less"; -import { batchDelete, renderTreeNodes, onExpand, closeAll, onCheck, onDragEnter, onDrop } from "./function.js"; +import { batchDelete, renderTreeNodes, onDrop } from "./function.js"; import AddModal from "./AddModal"; -export default class OverView extends React.Component { - constructor(props) { - super(props); - this.state = { - treeData: [], - isEdit: false, - isLoading: true, - checkedKeys: [], - expandKeys: [], - //是否显示新增/编辑书签弹窗 - isShowModal: false, - currentAddFolder: null, - currentEditNode: null - }; - } +import * as action from "../../../redux/action/BookmarkTreeOverview"; +import { connect } from "react-redux"; +function mapStateToProps(state) { + return state[action.DATA_NAME]; +} + +function mapDispatchToProps(dispatch) { + return { + updateTreeData: treeData => dispatch(action.updateTreeData(treeData)), + setIsEdit: isEdit => dispatch(action.setIsEdit(isEdit)), + addNode: (item, e) => dispatch(action.addNode(item, e)), + editNode: (item, e) => dispatch(action.editNode(item, e)), + changeIsInit: value => dispatch(action.changeIsInit(value)), + changeCheckedKeys: (keys, nodes) => dispatch(action.changeCheckedKeys(keys, nodes)), + changeExpandedKeys: keys => dispatch(action.changeExpandedKeys(keys)) + }; +} + +class OverView extends React.Component { /** * 初始化第一级书签 */ @@ -29,9 +33,10 @@ export default class OverView extends React.Component { httpUtil .get("/bookmark/currentUser/path?path=") .then(res => { - this.setState({ treeData: res, isLoading: false }); + this.props.updateTreeData(res); + this.props.changeIsInit(true); }) - .catch(() => this.setState({ isLoading: false })); + .catch(() => this.props.changeIsInit(true)); } /** @@ -43,7 +48,7 @@ export default class OverView extends React.Component { const newPath = item.path + "." + item.bookmarkId; httpUtil.get("/bookmark/currentUser/path?path=" + newPath).then(res => { item.children = res; - this.setState({ treeData: [...this.state.treeData] }); + this.props.updateTreeData([...this.props.treeData]); resolve(); }); }); @@ -57,61 +62,30 @@ export default class OverView extends React.Component { if (e.nativeEvent.delegateTarget && e.nativeEvent.delegateTarget.name === "copy") { return; } - const { expandKeys } = this.state; + const { expandedKeys, changeExpandedKeys } = this.props; const item = e.node.props.dataRef; if (item.type === 0) { window.open(item.url); } else { const id = item.bookmarkId.toString(); - const index = expandKeys.indexOf(id); - index === -1 ? expandKeys.push(id) : expandKeys.splice(index, 1); - this.setState({ expandKeys: [...expandKeys] }); + const index = expandedKeys.indexOf(id); + index === -1 ? expandedKeys.push(id) : expandedKeys.splice(index, 1); + changeExpandedKeys([...expandedKeys]); } } - /** - * 将新增的数据加入到state中 - */ - addToTree = node => { - const { currentAddFolder, treeData } = this.state; - if (currentAddFolder === null) { - treeData.push(node); - } else { - //存在children说明该子节点的孩子数据已经加载,需要重新将新的子书签加入进去 - if (currentAddFolder.children) { - currentAddFolder.children.push(node); - this.setState({ treeData: [...treeData] }); - } - this.setState({ currentAddFolder: null }); - } - }; - - /** - * 关闭新增书签弹窗 - */ - closeAddModal = () => { - this.setState({ isShowModal: false, currentAddFolder: null, currentEditNode: null }); - }; - - /** - * 新增书签 - */ - addOne = (item, e) => { - e.stopPropagation(); - this.setState({ currentAddFolder: item, isShowModal: true }); - }; - render() { - const { isLoading, isEdit, treeData, expandKeys, checkedKeys, isShowModal, currentAddFolder, currentEditNode } = this.state; + const { isEdit, setIsEdit, treeData, addNode, isInit, expandedKeys, checkedKeys } = this.props; + const { changeExpandedKeys } = this.props; return (
我的书签树 - {isEdit ? ) : null} @@ -124,7 +98,7 @@ export default class OverView extends React.Component { ) : null} -
@@ -132,29 +106,27 @@ export default class OverView extends React.Component { {renderTreeNodes.call(this, treeData)} - {isLoading === false && treeData.length === 0 ? : null} - + {isInit && treeData.length === 0 ? : null} +
); } } + +export default connect( + mapStateToProps, + mapDispatchToProps +)(OverView);