index.jsx 7.5 KB

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