| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 | import React, { Component } from "react";import { Button, message, Checkbox, Collapse, } from "antd";import $ from "jquery/src/ajax";import "./index.less";/** * 部门多选组件  2022-07-12 * <Cascaders *   ref={ref => this.Cascaders = ref} *   placeholder="请选择公出部门" *   id="id" *   name="name" *   children="list" *   height={28} *   onSel={(e) => {}} * /> */class Cascaders extends Component {  constructor(props) {    super(props);    this.state = {      visible: false, // 弹窗开关      authTree: [], // 列表显示数据      checkedList: [], // 选中数据      isFous: true, // 是否在组件外    };    this.itemHandle = this.itemHandle.bind(this);    this.onSelect = this.onSelect.bind(this);    this.onOks = this.onOks.bind(this);    this.onCancel = this.onCancel.bind(this);  }  componentDidMount() {    // 后端返回的数据,转成前端要用的数据保存页面使用    // const authTree = [...params.authTree];    // this.setState({    //   authTree    // })  }  // 转成前端要用的数据  authTreeFun() {    const checkedList = this.state.checkedList;    checkedList.forEach((item) => {      this.itemHandle(item);    });  }  // 获取部门数据  selectSuperId() {    $.ajax({      method: "get",      dataType: "json",      url: globalConfig.context + "/api/admin/organization/getAllDep",      data: {},      success: function (data) {        if (data.error && data.error.length === 0) {          localStorage.setItem("departmentData", JSON.stringify(data.data));          this.setState({            visible: true,            authTree: data.data || []          }, () => {            this.authTreeFun();          })        } else {          // message.warning(data.error[0].message);        }      }.bind(this),    }).always(    );  }  // 点击选择部门  onSelect() {    // 缓存的后端返回数据,转成前端要用的数据保存页面使用     const list = JSON.parse(localStorage.getItem("departmentData")) || []    const authTree = list    if (authTree.length > 0) {      this.setState({        visible: !this.state.visible,        authTree: authTree,      }, () => {        this.authTreeFun();      })    } else {      //若缓存清理则重新请求接口拿      this.selectSuperId()    }  }  // 确定  onOks() {    const { authTree } = this.state    const { id = "id", children = "list", onSel } = this.props    let list = []    authTree.forEach((its) => {      if (its.checked) {        list.push(its[id])      }      if (!!its[children] && its[children].length > 0) {        its[children].forEach((itl) => {          if (itl.checked) {            list.push(itl[id])          }        });      }    })    if (list.length === 0) {      message.warn("还没有选择的部门")      return    }    this.setState({      checkedList: list,      visible: false,      isFous: true,    })    onSel(list)  }  // 取消  onCancel() {    this.setState({      visible: false,      isFous: true,    })  }  // 代码二级联动  itemHandle(iD, checked = true) {    const { id = "id", children = "list" } = this.props    const { authTree } = this.state    authTree.forEach((item1) => {      if (item1[id] == iD) {        item1.checked = checked;        if (!!item1[children] && item1[children].length > 0) {          item1[children].forEach((item2) => {            item2.checked = checked;          });        }      } else {        if (!!item1[children] && item1[children].length > 0) {          // 反向思路: 保存子选项框的个数, 子选项选中就-1, 等于0说明都选中了, 父选项就勾上          let temp1 = item1[children].length;          item1[children].forEach((item2) => {            if (item2[id] == iD) {              item2.checked = checked;            }            //  选中-1, 未选中不动            item2.checked ? temp1 -= 1 : temp1;          });          //  长度是0, 父选项框就勾选          temp1 === 0 ? item1.checked = true : item1.checked = false;        } else {        }      }    });    this.setState({      authTree,    });  }  // 清空  现用于父级重置  empty() {    this.setState({      visible: false,      isFous: true,      checkedList: []    })  }  // checked组件样式  inde(item) {    const { children = "list" } = this.props    if (item.checked) {      return false    } else {      if (!!item[children] && item[children].length > 0) {        let clist = []        for (var i = 0; i < item[children].length; i++) {          if (item[children][i].checked == true) {            clist.push(item[children][i])          }        }        if (!!clist.length && (clist.length < item[children].length)) {          return true        } else {          return false        }      } else {        return false      }    }  }  render() {    const { Panel } = Collapse;    const { visible, isFous, authTree, checkedList } = this.state    const {      placeholder = "选择部门",      width = 200,      height = 32,      id = "id",//接口需要的字段名      name = "name",//显示内容字段名      children = "list",//二级列表字段名    } = this.props    const authTreeMap = authTree.map((item1) => (      // Panel是手风琴      <Panel        key={item1[id]}        header={(          <div className="item">            {/* 一级复选框(向下操控二级) */}            <Checkbox              indeterminate={this.inde(item1)}              name={item1[id]}              checked={item1.checked}              onClick={(e) => {                e.stopPropagation();                this.itemHandle(e.target.name, e.target.checked);              }}            >            </Checkbox>            <div className="iname">{item1[name]}</div>          </div>        )}      >        {/* 二级复选框(向上联动一级) */}        {!!item1[children] && item1[children].map((item2) => (          <div key={item2[id]} className="item">            <Checkbox              name={item2[id]}              checked={item2.checked}              onClick={(e) => {                this.itemHandle(e.target.name, e.target.checked);              }}            >            </Checkbox>            <div className="iname" style={{ width: "90%" }}>{item2[name]}</div>          </div>        ))}      </Panel>    ));    return (      <div        className="cascaders"        tabIndex={0}        onBlur={(e) => {          isFous && this.setState({            visible: false          })        }}      >        <div          className="cinput"          style={{            height: height,            width: width,            borderColor: visible && "#80b9ff",            color: checkedList.length > 0              ? "rgba(0, 0, 0, 0.65)"              : "rgba(191, 191, 191, 1)"          }}          onClick={this.onSelect}        >          <div className="ctext">            {checkedList.length > 0 ? `已选择${checkedList.length}项` : placeholder}          </div>        </div>        <div          data-reactroot          onMouseLeave={() => {            this.setState({              isFous: true            })          }}          onMouseEnter={() => {            this.setState({              isFous: false            })          }}        >          {            visible &&            <div className="cpop" style={{ width: 260, }}>              <div className="clist">                <Collapse expandIconPosition="right">                  {authTreeMap}                </Collapse>              </div>              <div className="cboot">                <Button type="primary" style={{ marginLeft: 10 }} onClick={this.onOks}>确定</Button>                <Button onClick={this.onCancel}>取消</Button>              </div>            </div>          }        </div>      </div>    );  }}export default Cascaders;
 |