index.jsx 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /* eslint-disable max-lines-per-function */
  2. import { Table, Checkbox, Button, SideSheet } from '@douyinfe/semi-ui';
  3. import React, { useMemo, useState, useCallback, useEffect } from 'react';
  4. import * as _ from 'lodash';
  5. import { IconEdit } from '@douyinfe/semi-icons';
  6. import testJson from '../data/big2.json';
  7. const getKey = (record, rowKey) => (typeof rowKey === 'function' ? rowKey(rowKey) : _.get(record, rowKey));
  8. const storeKeys = (parent = null, dataSource = [], map = {}, rowKey = 'key', childrenRecordName = 'children') => {
  9. if (Array.isArray(dataSource) && dataSource.length) {
  10. dataSource.forEach(record => {
  11. const key = getKey(record, rowKey);
  12. const children = _.get(record, childrenRecordName);
  13. if (Array.isArray(children) && children.length) {
  14. storeKeys(record, children, map, rowKey, childrenRecordName);
  15. }
  16. if (parent) {
  17. if (Array.isArray(map[key])) {
  18. map[key].push(parent);
  19. } else {
  20. map[key] = [parent];
  21. }
  22. }
  23. });
  24. }
  25. return map;
  26. };
  27. function ChildrenDataSelectedDemo(props = {}) {
  28. const childrenRecordName = 'children';
  29. const rowKey = 'key';
  30. const authPoint = 'auth_point_list';
  31. const checkName = 'role_perm';
  32. const isZh = true;
  33. const [expandedRowKeys, setExpandedRowKeys] = useState(['0', '1']);
  34. const [selectedRowKeys, setSelectedRowKeys] = useState([]);
  35. const [allKeys, setAllKeys] = useState([]);
  36. const [visible, setVisible] = useState(false);
  37. const getRecordKey = useCallback(record => getKey(record, rowKey), [rowKey]);
  38. const [data, setData] = useState([]);
  39. const getTableData = () => {
  40. const tableData = _.cloneDeep(testJson.data);
  41. const allKeys = [];
  42. for (let i = 0, len = tableData.length; i < len; ++i) {
  43. const key = `${i}`;
  44. tableData[i][rowKey] = key;
  45. allKeys.push(key);
  46. }
  47. const queue = [...tableData];
  48. while (queue.length) {
  49. const curNode = queue.shift();
  50. const someSelected = curNode[authPoint].some(item => item[checkName]);
  51. const everySelected = curNode[authPoint].every(item => item[checkName]);
  52. curNode.checkAll = {
  53. checked: curNode[authPoint] && curNode[authPoint].length && everySelected,
  54. indeterminate: someSelected,
  55. };
  56. const parentKey = curNode[rowKey];
  57. if (curNode.children.length) {
  58. for (let i = 0, len = curNode.children.length; i < len; ++i) {
  59. const key = `${parentKey}.${childrenRecordName}.${i}`;
  60. curNode.children[i][rowKey] = key;
  61. allKeys.push(key);
  62. }
  63. queue.push(...curNode.children);
  64. }
  65. }
  66. setData(tableData);
  67. setAllKeys(allKeys);
  68. setExpandedRowKeys([...allKeys]);
  69. };
  70. const getCheckboxProps = useCallback(record => {
  71. const children = _.get(record, childrenRecordName);
  72. const recordKey = getRecordKey(record);
  73. const checkboxProps = {};
  74. if (Array.isArray(children) && children.length) {
  75. const allChildrenKeys = children.map(getRecordKey);
  76. const someSelected = allChildrenKeys.some(key => selectedRowKeys.includes(key));
  77. if (someSelected && !selectedRowKeys.includes(recordKey)) {
  78. checkboxProps.indeterminate = true;
  79. }
  80. }
  81. return checkboxProps;
  82. }, [getRecordKey, selectedRowKeys]);
  83. const onChangeOne = useCallback((recordKey, text, e) => {
  84. const tableData = _.cloneDeep(data);
  85. // const tableData = data;
  86. const findRecord = _.get(tableData, recordKey);
  87. const findCheckBox = _.find(findRecord[authPoint], item => item.code === text);
  88. findCheckBox[checkName] = e.target.checked;
  89. const someSelected = findRecord[authPoint].some(item => item[checkName]);
  90. const everySelected = findRecord[authPoint].every(item => item[checkName]);
  91. findRecord.checkAll = {
  92. checked: everySelected,
  93. indeterminate: someSelected,
  94. };
  95. setData(tableData);
  96. // setData(_.cloneDeep(tableData));
  97. }, [data]);
  98. const onChangeAll = useCallback((recordKey, e) => {
  99. const tableData = _.cloneDeep(data);
  100. const findRecord = _.get(tableData, recordKey);
  101. findRecord.checkAll = {
  102. checked: findRecord[authPoint] && findRecord[authPoint].length && e.target.checked,
  103. };
  104. for (const item of findRecord[authPoint]) {
  105. item[checkName] = e.target.checked;
  106. }
  107. setData(tableData);
  108. }, [data]);
  109. const getSet = useCallback((record, set, selected) => {
  110. const queue = [record];
  111. while (queue.length) {
  112. const curNode = queue.shift();
  113. const key = getRecordKey(curNode);
  114. onChangeAll(key, {
  115. target: {
  116. checked: selected,
  117. },
  118. });
  119. if (selected) {
  120. set.add(key);
  121. } else {
  122. set.delete(key);
  123. }
  124. if (curNode.children.length) {
  125. queue.push(...curNode.children);
  126. }
  127. }
  128. }, [onChangeAll, getRecordKey]);
  129. const doSelect = useCallback((record, selected) => {
  130. const set = new Set([...selectedRowKeys]);
  131. getSet(record, set, selected);
  132. setSelectedRowKeys(Array.from(set));
  133. setExpandedRowKeys(Array.from(new Set([...expandedRowKeys, ...set])));
  134. }, [getSet, setSelectedRowKeys, setExpandedRowKeys, expandedRowKeys, selectedRowKeys]);
  135. const doSelectAll = useCallback((selected, selectedRows) => {
  136. setSelectedRowKeys(selected ? [...allKeys] : []);
  137. setExpandedRowKeys([...allKeys]);
  138. // for (const key of allKeys) {
  139. // onChangeAll(key, {
  140. // target: {
  141. // checked: selected,
  142. // },
  143. // });
  144. // }
  145. }, [allKeys]);
  146. const rowSelection = useMemo(
  147. () => ({
  148. // fixed: true,
  149. getCheckboxProps,
  150. selectedRowKeys,
  151. onSelect: doSelect,
  152. onSelectAll: doSelectAll,
  153. }),
  154. [selectedRowKeys, getCheckboxProps, doSelect, doSelectAll]
  155. );
  156. const columns = useMemo(() => [
  157. {
  158. title: 'authSideSheetTitle',
  159. dataIndex: 'name',
  160. key: 'name',
  161. width: 300,
  162. // fixed: true,
  163. render: (text, record) => (isZh ? record.name : record.en_name),
  164. },
  165. {
  166. title: 'authSideSheetCheckAll',
  167. dataIndex: 'checkAll',
  168. key: 'checkAll',
  169. width: 100,
  170. // fixed: true,
  171. render: (text, record) => <Checkbox {...text} onChange={(...args) => onChangeAll(record.key, ...args)} />,
  172. },
  173. {
  174. title: 'authSideSheetAuthPoint',
  175. dataIndex: authPoint,
  176. key: authPoint,
  177. render: (text, record) => record[authPoint].map(item => (
  178. <Checkbox
  179. style={{ display: 'inline-flex', marginRight: 20 }}
  180. key={item.code}
  181. checked={item.role_perm}
  182. onChange={(...args) => onChangeOne(record.key, item.code, ...args)}
  183. >
  184. {isZh ? item.name : item.en_name}
  185. </Checkbox>
  186. )),
  187. },
  188. {
  189. title: 'Operations',
  190. width: 120,
  191. key: 'Operations',
  192. render: () => <Button icon={<IconEdit />} />,
  193. // fixed: 'right',
  194. },
  195. ], [isZh, onChangeAll, onChangeOne]);
  196. const scroll = useMemo(() => ({ y: 600, x: 900 }), []);
  197. const virtualized = useMemo(() => ({ itemSize: () => 54 }), []);
  198. const onExpandedRowsChange = useCallback(rows => setExpandedRowKeys(rows.map(item => item[rowKey])), []);
  199. useEffect(() => {
  200. getTableData();
  201. }, []);
  202. return (
  203. <div>
  204. <Button onClick={() => setVisible(true)}>切换显示侧边栏</Button>
  205. <SideSheet visible={visible} onCancel={() => setVisible(false)} width={900}>
  206. <div>
  207. <Table
  208. scroll={scroll}
  209. columns={columns}
  210. rowKey={rowKey}
  211. childrenRecordName={childrenRecordName}
  212. // defaultExpandAllRows
  213. expandedRowKeys={expandedRowKeys}
  214. onExpandedRowsChange={onExpandedRowsChange}
  215. rowSelection={rowSelection}
  216. dataSource={data}
  217. pagination={false}
  218. virtualized={virtualized}
  219. />
  220. </div>
  221. </SideSheet>
  222. </div>
  223. );
  224. }
  225. export default ChildrenDataSelectedDemo;