index.jsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import React, { Component } from "react";
  2. import { Button, message, Modal, Spin, Table, Checkbox, Collapse, } from "antd";
  3. import $ from "jquery/src/ajax";
  4. import "./index.less";
  5. //选择部门组件 2022-07-12
  6. class Cascaders extends Component {
  7. constructor(props) {
  8. super(props);
  9. this.state = {
  10. visible: false,//弹窗开关
  11. authTree: [],//列表显示数据
  12. checkedList: [],//选中数据
  13. };
  14. this.itemHandle = this.itemHandle.bind(this);
  15. this.onSelect = this.onSelect.bind(this);
  16. this.onOks = this.onOks.bind(this);
  17. this.onCancel = this.onCancel.bind(this);
  18. }
  19. componentDidMount() {
  20. // 后端返回的数据,转成前端要用的数据保存页面使用
  21. // const authTree = [...params.authTree];
  22. // this.setState({
  23. // authTree
  24. // })
  25. }
  26. // 转成前端要用的数据
  27. authTreeFun() {
  28. const checkedList = this.state.checkedList;
  29. checkedList.forEach((item) => {
  30. this.itemHandle(item);
  31. });
  32. }
  33. // 获取部门数据
  34. selectSuperId() {
  35. $.ajax({
  36. method: "get",
  37. dataType: "json",
  38. url: globalConfig.context + "/api/admin/organization/selectSuperId",
  39. data: {},
  40. success: function (data) {
  41. let theArr = [];
  42. if (data.error && data.error.length === 0) {
  43. localStorage.setItem("departmentData", JSON.stringify(data.data));
  44. this.setState({
  45. visible: true,
  46. authTree: data.data || []
  47. }, () => {
  48. this.authTreeFun();
  49. })
  50. } else {
  51. // message.warning(data.error[0].message);
  52. }
  53. }.bind(this),
  54. }).always(
  55. );
  56. }
  57. // 点击选择部门
  58. onSelect() {
  59. // 缓存的后端返回数据,转成前端要用的数据保存页面使用
  60. const list = JSON.parse(localStorage.getItem("departmentData")) || []
  61. const authTree = list
  62. if (authTree.length > 0) {
  63. this.setState({
  64. visible: true,
  65. authTree: authTree,
  66. }, () => {
  67. this.authTreeFun();
  68. })
  69. } else {
  70. //若缓存清理则重新请求接口拿
  71. this.selectSuperId()
  72. }
  73. }
  74. // 确定
  75. onOks() {
  76. const { authTree } = this.state
  77. const { id = "id", children = "children", onSel } = this.props
  78. let list = []
  79. authTree.forEach((its) => {
  80. if (its.checked) {
  81. list.push(its[id])
  82. }
  83. if (its[children]) {
  84. its[children].forEach((itl) => {
  85. if (itl.checked) {
  86. list.push(itl[id])
  87. }
  88. });
  89. }
  90. })
  91. this.setState({
  92. checkedList: list,
  93. visible: false,
  94. })
  95. onSel(list)
  96. }
  97. // 取消
  98. onCancel() {
  99. this.setState({
  100. visible: false,
  101. })
  102. }
  103. // 代码二级联动
  104. itemHandle(iD, checked = true) {
  105. const { id = "id", children = "children" } = this.props
  106. const { authTree } = this.state
  107. authTree.forEach((item1) => {
  108. if (item1[id] == iD) {
  109. item1.checked = checked;
  110. if (item1[children]) {
  111. item1[children].forEach((item2) => {
  112. item2.checked = checked;
  113. });
  114. }
  115. } else {
  116. if (!!item1[children]) {
  117. // 反向思路: 保存子选项框的个数, 子选项选中就-1, 等于0说明都选中了, 父选项就勾上
  118. let temp1 = item1[children].length;
  119. item1[children].forEach((item2) => {
  120. if (item2[id] == iD) {
  121. item2.checked = checked;
  122. }
  123. // 选中-1, 未选中不动
  124. item2.checked ? temp1 -= 1 : temp1;
  125. });
  126. // 长度是0, 父选项框就勾选
  127. temp1 === 0 ? item1.checked = true : item1.checked = false;
  128. } else {
  129. }
  130. }
  131. });
  132. this.setState({
  133. authTree,
  134. });
  135. }
  136. // 清空 现用于重置
  137. empty() {
  138. this.setState({
  139. visible: false,
  140. checkedList: []
  141. })
  142. }
  143. render() {
  144. const { Panel } = Collapse;
  145. const { visible, authTree, checkedList } = this.state
  146. const {
  147. placeholder = "选择部门",
  148. width = 200,
  149. height = 32,
  150. id = "id",//接口需要的字段名
  151. name = "name",//显示内容字段名
  152. children = "children",//二级列表字段名
  153. } = this.props
  154. const authTreeMap = authTree.map((item1) => (
  155. // Panel是手风琴
  156. <Panel
  157. key={item1[id]}
  158. header={(
  159. <div className="item">
  160. {/* 一级复选框(向下操控二级三级) */}
  161. <Checkbox
  162. name={item1[id]}
  163. checked={item1.checked}
  164. onClick={(e) => {
  165. e.stopPropagation();
  166. this.itemHandle(e.target.name, e.target.checked);
  167. }}
  168. >
  169. </Checkbox>
  170. <div className="iname">{item1[name]}</div>
  171. </div>
  172. )}
  173. >
  174. {/* 二级复选框(向下操控三级,向上联动一级) */}
  175. {!!item1[children] && item1[children].map((item2) => (
  176. <div key={item2[id]} className="item">
  177. <Checkbox
  178. name={item2[id]}
  179. checked={item2.checked}
  180. onClick={(e) => {
  181. this.itemHandle(e.target.name, e.target.checked);
  182. }}
  183. >
  184. </Checkbox>
  185. <div className="iname" style={{ width: "90%" }}>{item2[name]}</div>
  186. </div>
  187. ))}
  188. </Panel>
  189. ));
  190. return (
  191. <div className="cascaders">
  192. <div
  193. className="cinput"
  194. style={{
  195. height: height,
  196. width: width,
  197. color: checkedList.length > 0 ? "rgba(0, 0, 0, 0.65)" : "rgba(191, 191, 191, 1)"
  198. }}
  199. onClick={this.onSelect}
  200. >
  201. <div className="ctext">{checkedList.length > 0 ? `已选择${checkedList.length}项` : placeholder}</div>
  202. </div>
  203. <div data-reactroot>
  204. {
  205. visible &&
  206. <div className="cpop" style={{ width: width, }}>
  207. <div className="clist">
  208. <Collapse expandIconPosition="right">
  209. {authTreeMap}
  210. </Collapse>
  211. </div>
  212. <div className="cboot">
  213. <Button type="primary" style={{ marginLeft: 10 }} onClick={this.onOks}>确定</Button>
  214. <Button onClick={this.onCancel}>取消</Button>
  215. </div>
  216. </div>
  217. }
  218. </div>
  219. </div>
  220. );
  221. }
  222. }
  223. export default Cascaders;