菜单拖拽排序

846 阅读2分钟
import React, {Component} from 'react';
import {Tree, Icon,Input,Form,Modal,message,Select } from 'antd';
import { menuTree } from "@/services/menu-tree";
import './EditmenuTree.less';
import notification from '@/services/notification';
const { TreeNode } = Tree;
const { Option } = Select;
const { confirm } = Modal;
class EditmenuTree extends Component {
  expandedKeys = ['0'];
  root = [{
    name: 'Root',
    id: 0,
    type:"",
    parentKey:'0',
    children:[],
  }];
  state = {
    expandedKeys: [],
    data:[],
    editModuleDetail:{},
    dashBoards:[],
    users:[],
    dragData:{module_id:0,parent_id:0,sequence:0},//拖拽参数
    icon:["overview","content","city","im","e_commerce","my_board","user_relationship","online_event","basic","sales","car_control","energy","car","customer_service","lto","otd","user_operation","apollo_tools"]
  };
  componentWillMount() {
    this.reSetData();
}
  reSetData = () => {
    menuTree.getModules().then((res) => {
        this.root[0].children=res;
        this.setState({
          data: this.root,
        });
        this.getExpandId(res);
        this.onExpand(this.expandedKeys);// 手动触发,否则会遇到第一次添加子节点不展开的Bug
        //获取dashboard列表-初始化数据
          menuTree.allDashboards().then((data) =>{
            this.setState({
              dashBoards: data.results
            })
          })
          //获取用户列表
          menuTree.allUsers().then((data) =>{
            this.setState({
              users: data.results
            })
          })
    }).catch((err) => {
      message.error('数据有误稍后再试');
    });
  }
  getExpandId = (data) => data.map((item) => {
    item.type != "dashboard" && this.expandedKeys.push(item.id.toString());
    if (item.children && item.children.length>0) {
      this.getExpandId(item.children);
    }
    return item.id;
  });
  onExpand = (expandedKeys) => {
    this.expandedKeys = expandedKeys;
    this.setState({ expandedKeys: expandedKeys })
  };
  showModal =(e)=>{
    menuTree.getModules_one({module_id:e}).then((res) =>{
      this.setState({
        editModuleDetail: res,
        visible: true
      })
    });
  };
  //form表单修改
  onSelectChange = value => {
    this.state.editModuleDetail.dashboard_id = value?value:'';
    this.setState({
      editModuleDetail:this.state.editModuleDetail
    })
  };
  onChangeUsers = value => {
    this.state.editModuleDetail.approver_id = value?value:"";
    this.setState({
      editModuleDetail:this.state.editModuleDetail
    })
  };
  onChangeName = e =>{
    const value = e.target.value.trim();
    this.state.editModuleDetail.name = value;
    this.setState({
      editModuleDetail:this.state.editModuleDetail
    })
  };
  onChangeOrder = e =>{
    const value = e.target.value.trim();
    this.state.editModuleDetail.sequence = value;
    this.setState({
      editModuleDetail:this.state.editModuleDetail
    })
  }
  onChangeIcon = e =>{
    this.state.editModuleDetail.icon = e?e:'';
    this.setState({
      editModuleDetail:this.state.editModuleDetail
    })
  }
  onChangeDescription = e =>{
    const value = e.target.value.trim();
    this.state.editModuleDetail.description = value;
    this.setState({
      editModuleDetail:this.state.editModuleDetail
    })
  }
  //form表单修改 end
  editNodeTreeMenu = () =>{
    const layout = {
      labelCol: { span: 6 },
      wrapperCol: { span: 16 },
    };
    return (
      <div className="show-form">
         <Modal
          title={this.state.editModuleDetail.id?"编辑模块信息":"添加"}
          visible={this.state.visible}
          onOk={this.editSubmit}
          onCancel={this.handleCancel}
        >
          <Form {...layout} name="nest-messages">
            <Form.Item name="user" label="展示名称" rules={[{ required: true }]}>
              <Input value={this.state.editModuleDetail.name} onChange={this.onChangeName}/>
            </Form.Item>
            <Form.Item name={['user', 'website']} label="对应看板">
              <Select
                allowClear
                showSearch
                style={{ width: 200 }}
                placeholder="选择dashboard"
                optionFilterProp="children"
                onChange={this.onSelectChange}
                value={this.state.editModuleDetail.dashboard_id}
                filterOption={(input, option) =>
                  option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                }
              >
                {this.state.dashBoards.map((item) => {
                  return <Option key={item.id} value={item.id}>{item.name}</Option>
                })}
              </Select>
            </Form.Item>
            {/* <Form.Item name="order" label="顺序">
              <Input  value={this.state.editModuleDetail.sequence} placeholder="输入数字" onChange={this.onChangeOrder}/>
            </Form.Item> */}
            <Form.Item name={['user', 'owner']} label="审批人">
              <Select
                allowClear
                showSearch
                style={{ width: 200 }}
                placeholder="审批人"
                optionFilterProp="children"
                onChange={this.onChangeUsers}
                value={this.state.editModuleDetail.approver_id}
                filterOption={(input, option) =>
                  option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                }
              >
                {this.state.users.map((item) => {
                  return <Option key={item.id} value={item.id}>{item.account}</Option>
                })}
              </Select>
            </Form.Item>
            <Form.Item name={['user', 'icon']} label="Icon">
              <Select
                allowClear
                style={{ width: 200 }}
                placeholder="icon"
                optionFilterProp="children"
                onChange={this.onChangeIcon}
                value={this.state.editModuleDetail.icon}
              >
                {this.state.icon.map((item) => {
                  return <Option key={item} value={item}><img alt="" src={require(`@/assets/images/sidebar-icons/${item}.png`)} width="16"/>&nbsp;{item}</Option>
                })}
              </Select>
            </Form.Item>
            <Form.Item name={['user', 'introduction']} label="描述">
              <Input.TextArea value={this.state.editModuleDetail.description} onChange={this.onChangeDescription}/>
            </Form.Item>
          </Form>
        </Modal>
      </div>
    );
  }
  editSubmit = () => {
    const editJson = this.state.editModuleDetail;
    if(editJson.id){
      const str = {module_id:editJson.id,name:editJson.name,description:editJson.description,sequence:editJson.sequence,icon:editJson.icon,approver_id:editJson.approver_id,dashboard_id:editJson.dashboard_id}
      menuTree.editModule(str).then((res)=>{
        message.success('编辑操作成功!');
        this.onChange(editJson.name, editJson.id)
        this.setState({
          visible: false,
          editModuleDetail:{}
        });
         // 重新请求数据
        this.reloadMenuData();
      }).catch((err) => {
        message.error('数据有误稍后再试');
      });
    }else{
      const str = {parent_id:editJson.parent_id,name:editJson.name,description:editJson.description,sequence:editJson.sequence,icon:editJson.icon,approver_id:editJson.approver_id,dashboard_id:editJson.dashboard_id}
      menuTree.addModule(str).then((res)=>{
        message.success('添加成功!');
        // const strJson={id:res.id,parent_id:str.parent_id,name:str.name,sequence:str.sequence}
        // this.addNode(strJson, this.state.data);
        this.setState({
            visible:false,
            // data: this.state.data
        });
        this.reloadMenuData();
      });
    }
  };
  // 重新请求数据
  reloadMenuData = () => {
    menuTree.getModules().then((res) => {
      this.root[0].children=res;
      this.setState({
        data: this.root,
      });
      this.getExpandId(res);
      this.onExpand(this.expandedKeys);
    });
  }
  handleCancel = e => {
    this.setState({
      visible: false
    });
  };
  renderTreeNodes = data => data.map((item) => {
        item.title = (
            <div className={`titleContainer ${item.name}`}>
               {item.level == 2 && item.icon && <img className="sidebar-icon" alt={item.name} src={`/static/images/sidebar-icons/${item.icon}.png`}></img>}
                <span className="item-name">
                  {item.name}{item.dashboard_is_draft && item.children.length == 0 &&  <span className="unpublished">Unpublished</span>}
                </span>
                <span className="icon-block">
                  <Icon type='plus-circle-o' onClick={() => this.onAdd(item.id)} />
                  {item.parentKey === '0' ? null : (<Icon style={{ marginLeft: 10 }} type='minus-circle-o' onClick={() => this.onDelete(item.id)} />)}
                  {item.parentKey === '0' ? null : (<Icon style={{ marginLeft: 10 }} type='edit' onClick={() => this.showModal(item.id)} />)}
                </span>
            </div>
        )
        if (item.children) {
            return (
                <TreeNode title={item.title} key={item.id} dataRef={item}>
                    {this.renderTreeNodes(item.children)}
                </TreeNode>
            );
        }
        return <TreeNode {...item} key={item.id}/>;
    })


  onAdd = (e) => {
    this.setState({
      editModuleDetail: {parent_id:e},
      visible: true
    })
  }

  addNode = (strJson, data) => data.map((item) => {
    if (item.id === strJson.parent_id) {
      if (item.children) {
        item
          .children
          .push({
            name: strJson.name,
            id: strJson.id,
            parent_id: strJson.parent_id,
          });
      } else {
        item.children = [];
        item
          .children
          .push({
            name: strJson.name,
            id: strJson.id,
            parent_id: strJson.parent_id,
          });
      }

    }
    if (item.children) {
      this.addNode(strJson, item.children)
    }
    return '';
  })

  onDelete = (key) => {
    const that = this;
    confirm({
      title: '你确定要删除此条节点吗?',
      content: '慎重操作',
      okText: '确定',
      okType: 'danger',
      cancelText: '取消',
      onOk() {
        menuTree.deleteModules_one({module_id:key}).then(()=>{
          message.success("删除成功!");
          that.deleteNode(key, that.state.data);
          that.setState({
            data: that.state.data
          });
        });
      },
      onCancel() {
        console.log(key);
      },
    });
  }

  deleteNode = (key, data) => data.forEach((item, index) => {
    if (item.id === key) {
      data.splice(index, 1);
    } else {
      if (item.children) {
        this.deleteNode(key, item.children)
      }
    }
  })

  onChange = (e, key) => {
    this.changeNode(key, e, this.state.data);
    this.setState({
      data: this.state.data
    });
  }
  changeNode = (key, value, data) => data.forEach((item) => {
    if (item.id === key) {
      item.name = value;
    }
    if (item.children) {
      this.changeNode(key, value, item.children)
    }
  });
  onDrop = info => {
    const dropTo = info.node.props;
    const dropKey = dropTo.eventKey;
    const dragKey = info.dragNode.props.eventKey;//正拖动节点
    const dropPos = dropTo.pos.split('-');
    const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
    // console.log(info,dropKey,dragKey);
    const dragData = {};
    dragData.module_id = dragKey;
    dragData.cancelable=true;
     
    if (!info.dropToGap) {
      if(dropTo.dataRef.level == '3'){
        dragData.cancelable=false;
        notification.error("暂时无法操作");
        this.setState({
          dragData:dragData
        })
        return false;
      }
      // 加到尾部
      dragData.parent_id = dropKey;
      const leg = dropTo.dataRef.children.length;
      const sequence = leg>0? dropTo.dataRef.children[leg-1].sequence+1 :'1';
      dragData.sequence = sequence;
      // console.log("加到尾部");
    } else if ((dropTo.children || []).length > 0 && dropTo.expanded && dropPosition === 1){
      // 有child,添加到头部,可以是随意位置
      dragData.parent_id = dropKey;
      const sequence = dropTo.dataRef.children[0].sequence;
      dragData.sequence = sequence;
      // console.log("有child,添加到头部,可以是随意位置");
    } else {
      dragData.parent_id = dropTo.dataRef.parent_id;
      if (dropPosition === -1) {
        dragData.sequence = dropTo.dataRef.sequence;
        // console.log("插入上"+dropPosition);
      } else {
        dragData.sequence = dropTo.dataRef.sequence+1;
        // console.log("插入下"+dropPosition);
      }
    }
    this.setState({
      dragData:dragData
    })
  }
  onDragEnd = () => {
    const dData = this.state.dragData;
    if(dData.module_id && dData.cancelable){
      menuTree.editOrdersModule(parseInt(dData.module_id),{parent_id:parseInt(dData.parent_id),sequence:parseInt(dData.sequence)}).then(()=>{
        this.setState({
          dragData:{}
        })
        this.reloadMenuData();
      });
    }
   
  }
  render() {
    return (
      <div>
        <Tree draggable blockNode showLine expandedKeys={this.state.expandedKeys} onDrop={this.onDrop} onDragEnd ={this.onDragEnd} selectedKeys={[]} onExpand={this.onExpand}>
          {this.renderTreeNodes(this.state.data)}
        </Tree>
        {this.editNodeTreeMenu()}
      </div>
    )
  }
}

export default EditmenuTree;