amis 1.9.0-beta.12 → 1.9.0-beta.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/lib/Schema.d.ts +4 -2
  2. package/lib/Schema.js.map +1 -1
  3. package/lib/SchemaRenderer.d.ts +2 -2
  4. package/lib/SchemaRenderer.js +3 -3
  5. package/lib/SchemaRenderer.js.map +2 -2
  6. package/lib/actions/Action.d.ts +8 -6
  7. package/lib/actions/Action.js.map +2 -2
  8. package/lib/actions/AjaxAction.d.ts +10 -7
  9. package/lib/actions/AjaxAction.js +27 -21
  10. package/lib/actions/AjaxAction.js.map +2 -2
  11. package/lib/actions/BreakAction.d.ts +2 -2
  12. package/lib/actions/BreakAction.js.map +1 -1
  13. package/lib/actions/BroadcastAction.d.ts +3 -3
  14. package/lib/actions/BroadcastAction.js +3 -2
  15. package/lib/actions/BroadcastAction.js.map +2 -2
  16. package/lib/actions/CmptAction.d.ts +2 -2
  17. package/lib/actions/CmptAction.js +7 -9
  18. package/lib/actions/CmptAction.js.map +2 -2
  19. package/lib/actions/ContinueAction.d.ts +2 -2
  20. package/lib/actions/ContinueAction.js.map +1 -1
  21. package/lib/actions/CopyAction.d.ts +7 -4
  22. package/lib/actions/CopyAction.js +8 -6
  23. package/lib/actions/CopyAction.js.map +2 -2
  24. package/lib/actions/CustomAction.d.ts +2 -2
  25. package/lib/actions/CustomAction.js.map +1 -1
  26. package/lib/actions/DialogAction.d.ts +14 -8
  27. package/lib/actions/DialogAction.js +6 -6
  28. package/lib/actions/DialogAction.js.map +2 -2
  29. package/lib/actions/DrawerAction.d.ts +3 -3
  30. package/lib/actions/DrawerAction.js.map +1 -1
  31. package/lib/actions/EmailAction.d.ts +10 -7
  32. package/lib/actions/EmailAction.js +4 -5
  33. package/lib/actions/EmailAction.js.map +2 -2
  34. package/lib/actions/LinkAction.d.ts +19 -11
  35. package/lib/actions/LinkAction.js +6 -5
  36. package/lib/actions/LinkAction.js.map +2 -2
  37. package/lib/actions/LoopAction.d.ts +6 -3
  38. package/lib/actions/LoopAction.js +22 -20
  39. package/lib/actions/LoopAction.js.map +2 -2
  40. package/lib/actions/PageAction.d.ts +8 -5
  41. package/lib/actions/PageAction.js +3 -2
  42. package/lib/actions/PageAction.js.map +2 -2
  43. package/lib/actions/ParallelAction.d.ts +2 -2
  44. package/lib/actions/ParallelAction.js.map +1 -1
  45. package/lib/actions/SwitchAction.d.ts +2 -2
  46. package/lib/actions/SwitchAction.js.map +1 -1
  47. package/lib/actions/ToastAction.d.ts +2 -2
  48. package/lib/actions/ToastAction.js +6 -4
  49. package/lib/actions/ToastAction.js.map +2 -2
  50. package/lib/components/Editor.d.ts +84 -84
  51. package/lib/components/InputBox.js +1 -1
  52. package/lib/components/InputBox.js.map +2 -2
  53. package/lib/components/Pagination.d.ts +1175 -0
  54. package/lib/components/Pagination.js +274 -0
  55. package/lib/components/Pagination.js.map +13 -0
  56. package/lib/components/PickerContainer.d.ts +1 -0
  57. package/lib/components/PickerContainer.js +3 -2
  58. package/lib/components/PickerContainer.js.map +2 -2
  59. package/lib/components/Rating.js +11 -9
  60. package/lib/components/Rating.js.map +2 -2
  61. package/lib/components/Select.js +3 -3
  62. package/lib/components/Select.js.map +2 -2
  63. package/lib/components/Tag.d.ts +148 -0
  64. package/lib/components/Tag.js +96 -0
  65. package/lib/components/Tag.js.map +13 -0
  66. package/lib/components/TooltipWrapper.d.ts +25 -21
  67. package/lib/components/TooltipWrapper.js +11 -1
  68. package/lib/components/TooltipWrapper.js.map +2 -2
  69. package/lib/components/TransferDropDown.d.ts +85 -84
  70. package/lib/components/TransferDropDown.js +2 -2
  71. package/lib/components/TransferDropDown.js.map +2 -2
  72. package/lib/components/Tree.d.ts +84 -84
  73. package/lib/components/formula/VariableList.d.ts +1 -0
  74. package/lib/components/formula/VariableList.js.map +2 -2
  75. package/lib/components/icons.js +2 -0
  76. package/lib/components/icons.js.map +2 -2
  77. package/lib/components/index.d.ts +4 -1
  78. package/lib/components/index.js +7 -1
  79. package/lib/components/index.js.map +2 -2
  80. package/lib/components/schema-editor/Array.d.ts +11 -0
  81. package/lib/components/schema-editor/Array.js +66 -0
  82. package/lib/components/schema-editor/Array.js.map +13 -0
  83. package/lib/components/schema-editor/Common.d.ts +29 -0
  84. package/lib/components/schema-editor/Common.js +69 -0
  85. package/lib/components/schema-editor/Common.js.map +13 -0
  86. package/lib/components/schema-editor/Item.d.ts +9 -0
  87. package/lib/components/schema-editor/Item.js +31 -0
  88. package/lib/components/schema-editor/Item.js.map +13 -0
  89. package/lib/components/schema-editor/Object.d.ts +44 -0
  90. package/lib/components/schema-editor/Object.js +191 -0
  91. package/lib/components/schema-editor/Object.js.map +13 -0
  92. package/lib/components/schema-editor/SchemaVariableList.d.ts +316 -0
  93. package/lib/components/schema-editor/SchemaVariableList.js +74 -0
  94. package/lib/components/schema-editor/SchemaVariableList.js.map +13 -0
  95. package/lib/components/schema-editor/SchemaVariableListPicker.d.ts +305 -0
  96. package/lib/components/schema-editor/SchemaVariableListPicker.js +32 -0
  97. package/lib/components/schema-editor/SchemaVariableListPicker.js.map +13 -0
  98. package/lib/components/schema-editor/index.d.ts +520 -0
  99. package/lib/components/schema-editor/index.js +118 -0
  100. package/lib/components/schema-editor/index.js.map +13 -0
  101. package/lib/components/table/Cell.d.ts +930 -0
  102. package/lib/components/table/Cell.js +36 -0
  103. package/lib/components/table/Cell.js.map +13 -0
  104. package/lib/components/table/HeadCellDropDown.d.ts +514 -0
  105. package/lib/components/table/HeadCellDropDown.js +52 -0
  106. package/lib/components/table/HeadCellDropDown.js.map +13 -0
  107. package/lib/components/table/HeadCellFilter.d.ts +771 -0
  108. package/lib/components/table/HeadCellFilter.js +106 -0
  109. package/lib/components/table/HeadCellFilter.js.map +13 -0
  110. package/lib/components/table/HeadCellSelect.d.ts +672 -0
  111. package/lib/components/table/HeadCellSelect.js +46 -0
  112. package/lib/components/table/HeadCellSelect.js.map +13 -0
  113. package/lib/components/table/HeadCellSort.d.ts +498 -0
  114. package/lib/components/table/HeadCellSort.js +67 -0
  115. package/lib/components/table/HeadCellSort.js.map +13 -0
  116. package/lib/components/table/index.d.ts +1355 -0
  117. package/lib/components/table/index.js +1095 -0
  118. package/lib/components/table/index.js.map +13 -0
  119. package/lib/env.d.ts +2 -4
  120. package/lib/env.js.map +2 -2
  121. package/lib/factory.js +0 -95
  122. package/lib/factory.js.map +2 -2
  123. package/lib/icons/dot.js +11 -0
  124. package/lib/index.d.ts +6 -1
  125. package/lib/index.js +9 -2
  126. package/lib/index.js.map +2 -2
  127. package/lib/locale/de-DE.js +18 -1
  128. package/lib/locale/de-DE.js.map +2 -2
  129. package/lib/locale/en-US.js +18 -1
  130. package/lib/locale/en-US.js.map +2 -2
  131. package/lib/locale/zh-CN.js +20 -1
  132. package/lib/locale/zh-CN.js.map +2 -2
  133. package/lib/renderers/Action.js +0 -2
  134. package/lib/renderers/Action.js.map +2 -2
  135. package/lib/renderers/Carousel.d.ts +5 -1
  136. package/lib/renderers/Carousel.js +18 -5
  137. package/lib/renderers/Carousel.js.map +2 -2
  138. package/lib/renderers/Form/ButtonGroupSelect.d.ts +2 -0
  139. package/lib/renderers/Form/ButtonGroupSelect.js +7 -0
  140. package/lib/renderers/Form/ButtonGroupSelect.js.map +2 -2
  141. package/lib/renderers/Form/Checkbox.js +3 -4
  142. package/lib/renderers/Form/Checkbox.js.map +2 -2
  143. package/lib/renderers/Form/Checkboxes.d.ts +2 -1
  144. package/lib/renderers/Form/Checkboxes.js +19 -14
  145. package/lib/renderers/Form/Checkboxes.js.map +2 -2
  146. package/lib/renderers/Form/Combo.js +23 -4
  147. package/lib/renderers/Form/Combo.js.map +2 -2
  148. package/lib/renderers/Form/DiffEditor.d.ts +126 -18
  149. package/lib/renderers/Form/Editor.d.ts +412 -112
  150. package/lib/renderers/Form/Editor.js +10 -1
  151. package/lib/renderers/Form/Editor.js.map +2 -2
  152. package/lib/renderers/Form/InputExcel.js +6 -1
  153. package/lib/renderers/Form/InputExcel.js.map +2 -2
  154. package/lib/renderers/Form/InputFile.js +1 -2
  155. package/lib/renderers/Form/InputFile.js.map +2 -2
  156. package/lib/renderers/Form/InputTree.js +1 -1
  157. package/lib/renderers/Form/InputTree.js.map +2 -2
  158. package/lib/renderers/Form/Item.d.ts +0 -6
  159. package/lib/renderers/Form/JSONSchemaEditor.d.ts +41 -0
  160. package/lib/renderers/Form/JSONSchemaEditor.js +33 -0
  161. package/lib/renderers/Form/JSONSchemaEditor.js.map +13 -0
  162. package/lib/renderers/Form/ListSelect.d.ts +2 -0
  163. package/lib/renderers/Form/ListSelect.js +7 -0
  164. package/lib/renderers/Form/ListSelect.js.map +2 -2
  165. package/lib/renderers/Form/Options.js +1 -0
  166. package/lib/renderers/Form/Options.js.map +2 -2
  167. package/lib/renderers/Form/Select.js +12 -1
  168. package/lib/renderers/Form/Select.js.map +2 -2
  169. package/lib/renderers/Form/TabsTransfer.d.ts +1 -1
  170. package/lib/renderers/Form/TabsTransfer.js +2 -2
  171. package/lib/renderers/Form/TabsTransfer.js.map +2 -2
  172. package/lib/renderers/Form/TreeSelect.d.ts +4 -0
  173. package/lib/renderers/Form/TreeSelect.js +2 -2
  174. package/lib/renderers/Form/TreeSelect.js.map +2 -2
  175. package/lib/renderers/Form/wrapControl.js +10 -5
  176. package/lib/renderers/Form/wrapControl.js.map +2 -2
  177. package/lib/renderers/Pagination.d.ts +49 -30
  178. package/lib/renderers/Pagination.js +3 -132
  179. package/lib/renderers/Pagination.js.map +2 -2
  180. package/lib/renderers/Table/HeadCellSearchDropdown.js +0 -1
  181. package/lib/renderers/Table/HeadCellSearchDropdown.js.map +2 -2
  182. package/lib/renderers/Table-v2/HeadCellSearchDropdown.d.ts +29 -0
  183. package/lib/renderers/Table-v2/HeadCellSearchDropdown.js +158 -0
  184. package/lib/renderers/Table-v2/HeadCellSearchDropdown.js.map +13 -0
  185. package/lib/renderers/Table-v2/TableCell.d.ts +6 -0
  186. package/lib/renderers/Table-v2/TableCell.js +28 -0
  187. package/lib/renderers/Table-v2/TableCell.js.map +13 -0
  188. package/lib/renderers/Table-v2/index.d.ts +256 -0
  189. package/lib/renderers/Table-v2/index.js +548 -0
  190. package/lib/renderers/Table-v2/index.js.map +13 -0
  191. package/lib/renderers/Tabs.js +1 -1
  192. package/lib/renderers/Tabs.js.map +2 -2
  193. package/lib/renderers/Tag.d.ts +66 -0
  194. package/lib/renderers/Tag.js +53 -0
  195. package/lib/renderers/Tag.js.map +13 -0
  196. package/lib/renderers/Wizard.js +3 -3
  197. package/lib/renderers/Wizard.js.map +2 -2
  198. package/lib/schemaExtend.js +24 -30
  199. package/lib/schemaExtend.js.map +2 -2
  200. package/lib/store/combo.d.ts +140 -20
  201. package/lib/store/form.d.ts +56 -8
  202. package/lib/store/formItem.d.ts +3 -1
  203. package/lib/store/formItem.js +3 -1
  204. package/lib/store/formItem.js.map +2 -2
  205. package/lib/store/index.js +2 -0
  206. package/lib/store/index.js.map +2 -2
  207. package/lib/store/table-v2.d.ts +308 -0
  208. package/lib/store/table-v2.js +452 -0
  209. package/lib/store/table-v2.js.map +13 -0
  210. package/lib/store/table.d.ts +112 -16
  211. package/lib/store/table.js +1 -1
  212. package/lib/store/table.js.map +2 -2
  213. package/lib/themes/ang-ie11.css +1686 -120
  214. package/lib/themes/ang.css +1807 -208
  215. package/lib/themes/ang.css.map +1 -1
  216. package/lib/themes/antd-ie11.css +1667 -101
  217. package/lib/themes/antd.css +1789 -201
  218. package/lib/themes/antd.css.map +1 -1
  219. package/lib/themes/cxd-ie11.css +1662 -97
  220. package/lib/themes/cxd.css +1983 -394
  221. package/lib/themes/cxd.css.map +1 -1
  222. package/lib/themes/dark-ie11.css +1667 -101
  223. package/lib/themes/dark.css +1789 -201
  224. package/lib/themes/dark.css.map +1 -1
  225. package/lib/themes/default-ie11.css +1662 -97
  226. package/lib/themes/default.css +1983 -394
  227. package/lib/themes/default.css.map +1 -1
  228. package/lib/utils/DataSchema.d.ts +25 -0
  229. package/lib/utils/DataSchema.js +104 -0
  230. package/lib/utils/DataSchema.js.map +13 -0
  231. package/lib/utils/DataScope.d.ts +23 -0
  232. package/lib/utils/DataScope.js +140 -0
  233. package/lib/utils/DataScope.js.map +13 -0
  234. package/lib/utils/handleAction.js +1 -1
  235. package/lib/utils/handleAction.js.map +2 -2
  236. package/lib/utils/renderer-event.d.ts +8 -2
  237. package/lib/utils/renderer-event.js +102 -1
  238. package/lib/utils/renderer-event.js.map +2 -2
  239. package/package.json +3 -2
  240. package/schema.json +1476 -469
  241. package/scss/_properties.scss +69 -0
  242. package/scss/components/_button.scss +37 -39
  243. package/scss/components/_context-menu.scss +3 -18
  244. package/scss/components/_json-schema-editor.scss +126 -0
  245. package/scss/components/_pagination.scss +104 -23
  246. package/scss/components/_result-box.scss +2 -2
  247. package/scss/components/_table-v2.scss +912 -0
  248. package/scss/components/_tag.scss +177 -0
  249. package/scss/components/form/_selection.scss +1 -14
  250. package/scss/components/form/_text.scss +1 -1
  251. package/scss/themes/_antd-variables.scss +0 -13
  252. package/scss/themes/_common.scss +3 -0
  253. package/scss/themes/_cxd-variables.scss +7 -17
  254. package/scss/themes/_dark-variables.scss +0 -13
  255. package/scss/themes/cxd.scss +1 -1
  256. package/sdk/ang-ie11.css +2240 -227
  257. package/sdk/ang.css +2905 -859
  258. package/sdk/antd-ie11.css +2233 -220
  259. package/sdk/antd.css +2905 -870
  260. package/sdk/barcode.js +51 -51
  261. package/sdk/charts.js +14 -14
  262. package/sdk/codemirror.js +7 -7
  263. package/sdk/color-picker.js +65 -65
  264. package/sdk/cropperjs.js +2 -2
  265. package/sdk/cxd-ie11.css +2223 -211
  266. package/sdk/cxd.css +2911 -875
  267. package/sdk/dark-ie11.css +2233 -220
  268. package/sdk/dark.css +2905 -870
  269. package/sdk/exceljs.js +1 -1
  270. package/sdk/locale/de-DE.js +18 -1
  271. package/sdk/markdown.js +69 -69
  272. package/sdk/papaparse.js +1 -1
  273. package/sdk/renderers/Form/CityDB.js +1 -1
  274. package/sdk/rest.js +16 -16
  275. package/sdk/rich-text.js +62 -62
  276. package/sdk/sdk-ie11.css +2223 -211
  277. package/sdk/sdk.css +2911 -875
  278. package/sdk/sdk.js +1326 -1270
  279. package/sdk/thirds/hls.js/hls.js +1 -1
  280. package/sdk/thirds/mpegts.js/mpegts.js +1 -1
  281. package/sdk/tinymce.js +57 -57
  282. package/src/Schema.ts +7 -0
  283. package/src/SchemaRenderer.tsx +4 -5
  284. package/src/actions/Action.ts +7 -6
  285. package/src/actions/AjaxAction.ts +33 -24
  286. package/src/actions/BreakAction.ts +2 -2
  287. package/src/actions/BroadcastAction.ts +6 -5
  288. package/src/actions/CmptAction.ts +5 -6
  289. package/src/actions/ContinueAction.ts +2 -2
  290. package/src/actions/CopyAction.ts +14 -8
  291. package/src/actions/CustomAction.ts +2 -2
  292. package/src/actions/DialogAction.ts +16 -10
  293. package/src/actions/DrawerAction.ts +3 -3
  294. package/src/actions/EmailAction.ts +12 -12
  295. package/src/actions/LinkAction.ts +34 -14
  296. package/src/actions/LoopAction.ts +13 -8
  297. package/src/actions/PageAction.ts +9 -6
  298. package/src/actions/ParallelAction.ts +2 -2
  299. package/src/actions/SwitchAction.ts +2 -2
  300. package/src/actions/ToastAction.ts +9 -5
  301. package/src/components/InputBox.tsx +1 -0
  302. package/src/components/Pagination.tsx +446 -0
  303. package/src/components/PickerContainer.tsx +8 -5
  304. package/src/components/Rating.tsx +16 -9
  305. package/src/components/Select.tsx +3 -3
  306. package/src/components/Tag.tsx +179 -0
  307. package/src/components/TooltipWrapper.tsx +14 -1
  308. package/src/components/TransferDropDown.tsx +3 -0
  309. package/src/components/formula/VariableList.tsx +1 -0
  310. package/src/components/icons.tsx +2 -0
  311. package/src/components/index.tsx +7 -1
  312. package/src/components/schema-editor/Array.tsx +95 -0
  313. package/src/components/schema-editor/Common.tsx +138 -0
  314. package/src/components/schema-editor/Item.tsx +36 -0
  315. package/src/components/schema-editor/Object.tsx +299 -0
  316. package/src/components/schema-editor/SchemaVariableList.tsx +97 -0
  317. package/src/components/schema-editor/SchemaVariableListPicker.tsx +66 -0
  318. package/src/components/schema-editor/index.tsx +211 -0
  319. package/src/components/table/Cell.tsx +70 -0
  320. package/src/components/table/HeadCellDropDown.tsx +115 -0
  321. package/src/components/table/HeadCellFilter.tsx +193 -0
  322. package/src/components/table/HeadCellSelect.tsx +86 -0
  323. package/src/components/table/HeadCellSort.tsx +102 -0
  324. package/src/components/table/index.tsx +1681 -0
  325. package/src/env.tsx +7 -14
  326. package/src/factory.tsx +3 -106
  327. package/src/icons/dot.svg +11 -0
  328. package/src/index.tsx +8 -1
  329. package/src/locale/de-DE.ts +18 -1
  330. package/src/locale/en-US.ts +18 -1
  331. package/src/locale/zh-CN.ts +20 -1
  332. package/src/renderers/Action.tsx +1 -1
  333. package/src/renderers/Carousel.tsx +21 -6
  334. package/src/renderers/Form/ButtonGroupSelect.tsx +10 -1
  335. package/src/renderers/Form/Checkbox.tsx +4 -4
  336. package/src/renderers/Form/Checkboxes.tsx +31 -25
  337. package/src/renderers/Form/Combo.tsx +20 -4
  338. package/src/renderers/Form/Editor.tsx +15 -1
  339. package/src/renderers/Form/InputExcel.tsx +6 -1
  340. package/src/renderers/Form/InputFile.tsx +1 -2
  341. package/src/renderers/Form/InputTree.tsx +1 -1
  342. package/src/renderers/Form/JSONSchemaEditor.tsx +67 -0
  343. package/src/renderers/Form/ListSelect.tsx +9 -1
  344. package/src/renderers/Form/Options.tsx +1 -1
  345. package/src/renderers/Form/Select.tsx +7 -0
  346. package/src/renderers/Form/TabsTransfer.tsx +2 -2
  347. package/src/renderers/Form/TreeSelect.tsx +8 -1
  348. package/src/renderers/Form/wrapControl.tsx +11 -5
  349. package/src/renderers/Pagination.tsx +65 -253
  350. package/src/renderers/Table/HeadCellSearchDropdown.tsx +0 -1
  351. package/src/renderers/Table-v2/HeadCellSearchDropdown.tsx +244 -0
  352. package/src/renderers/Table-v2/TableCell.tsx +19 -0
  353. package/src/renderers/Table-v2/index.tsx +1140 -0
  354. package/src/renderers/Tabs.tsx +1 -1
  355. package/src/renderers/Tag.tsx +128 -0
  356. package/src/renderers/Wizard.tsx +3 -3
  357. package/src/schemaExtend.ts +24 -28
  358. package/src/store/formItem.ts +5 -1
  359. package/src/store/index.ts +2 -0
  360. package/src/store/table-v2.ts +646 -0
  361. package/src/store/table.ts +1 -1
  362. package/src/utils/DataSchema.ts +131 -0
  363. package/src/utils/DataScope.ts +190 -0
  364. package/src/utils/handleAction.ts +1 -1
  365. package/src/utils/renderer-event.ts +113 -2
@@ -0,0 +1,1681 @@
1
+ /**
2
+ * @file Table
3
+ * @author fex
4
+ */
5
+
6
+ import React from 'react';
7
+ import {findDOMNode} from 'react-dom';
8
+ import findLastIndex from 'lodash/findLastIndex';
9
+ import find from 'lodash/find';
10
+ import isEqual from 'lodash/isEqual';
11
+ import filter from 'lodash/filter';
12
+ import intersection from 'lodash/intersection';
13
+ import cloneDeep from 'lodash/cloneDeep';
14
+ import Sortable from 'sortablejs';
15
+
16
+ import {themeable, ClassNamesFn, ThemeProps} from '../../theme';
17
+ import {localeable, LocaleProps} from '../../locale';
18
+ import {isObject, isBreakpoint, guid} from '../../utils/helper';
19
+ import {Icon} from '../icons';
20
+ import CheckBox from '../Checkbox';
21
+ import Spinner from '../Spinner';
22
+
23
+ import HeadCellSort from './HeadCellSort';
24
+ import HeadCellFilter from './HeadCellFilter';
25
+ import HeadCellSelect from './HeadCellSelect';
26
+ import Cell from './Cell';
27
+
28
+ export interface ColumnProps {
29
+ title: string | React.ReactNode | Function;
30
+ key: string;
31
+ className?: string;
32
+ children?: Array<ColumnProps>;
33
+ render: Function;
34
+ fixed?: boolean | string;
35
+ width?: number | string;
36
+ sorter?: (a: any, b: any) => number | boolean; // 设置为true时,执行onSort,否则执行前端排序
37
+ sortOrder?: string; // 升序ascend、降序descend
38
+ filters?: Array<any>; // 筛选数据源,配置了数据源才展示
39
+ filterMode?: string; // menu/tree 默认menu 先只支持menu
40
+ filterMultiple?: boolean; // 是否支持多选
41
+ filteredValue?: Array<string>;
42
+ filtered?: boolean;
43
+ filterDropdown?: Function | React.ReactNode; // 列筛选 filterDropdown的优先级更高 和filters两者不能并存
44
+ align?: string; // left/right/center
45
+ breakpoint?: '*' | 'xs' | 'sm' | 'md' | 'lg';
46
+ }
47
+
48
+ export interface ThProps extends ColumnProps {
49
+ rowSpan: number;
50
+ colSpan: number;
51
+ groupId: string; // 随机生成表头分组的id
52
+ depth: number; // 表头分组层级
53
+ }
54
+
55
+ export interface TdProps extends ColumnProps {
56
+ rowSpan: number;
57
+ colSpan: number;
58
+ groupId: string; // 随机生成表头分组的id
59
+ }
60
+
61
+ export interface RowSelectionOptionProps {
62
+ key: string;
63
+ text: string;
64
+ onSelect: Function;
65
+ }
66
+
67
+ export interface RowSelectionProps {
68
+ type: string;
69
+ rowClick: boolean; // 点击复选框选中还是点击整行选中
70
+ fixed: boolean; // 只能固定在左边
71
+ selectedRowKeys: Array<string | number>;
72
+ keyField?: string; // 默认是key,可自定义
73
+ columnWidth?: number;
74
+ selections?: Array<RowSelectionOptionProps>;
75
+ onChange?: Function;
76
+ onSelect?: Function;
77
+ onSelectAll?: Function;
78
+ getCheckboxProps: Function;
79
+ }
80
+
81
+ export interface ExpandableProps {
82
+ expandedRowKeys?: Array<string | number>;
83
+ keyField: string; // 默认是key,可自定义
84
+ columnWidth?: number;
85
+ rowExpandable: Function;
86
+ defaultExpandedRowKeys?: Array<string | number>;
87
+ onExpand?: Function;
88
+ onExpandedRowsChange?: Function;
89
+ expandedRowRender?: Function;
90
+ expandedRowClassName?: Function;
91
+ expandIcon?: Function;
92
+ fixed?: boolean;
93
+ }
94
+
95
+ export interface SummaryProps {
96
+ colSpan: number; // 手动控制列合并 先不支持列合并
97
+ fixed: string | boolean; // 手动设置左固定还是右固定
98
+ render: Function | React.ReactNode;
99
+ }
100
+
101
+ export interface OnRowProps {
102
+ onRowMouseEnter?: Function;
103
+ onRowMouseLeave?: Function;
104
+ onRowClick?: Function
105
+ }
106
+
107
+ export interface TableProps extends ThemeProps, LocaleProps {
108
+ title: string | React.ReactNode | Function;
109
+ footer: string | React.ReactNode | Function;
110
+ className?: string;
111
+ dataSource: Array<any>;
112
+ classnames: ClassNamesFn
113
+ columns: Array<ColumnProps>;
114
+ scroll?: ScrollProps;
115
+ rowSelection?: RowSelectionProps,
116
+ onSort?: Function;
117
+ expandable?: ExpandableProps;
118
+ bordered?: boolean;
119
+ size?: string; // large | default | small
120
+ headSummary?: Function | React.ReactNode | Array<SummaryProps | Array<SummaryProps>>;
121
+ footSummary?: Function | React.ReactNode | Array<SummaryProps | Array<SummaryProps>>;
122
+ draggable?: boolean;
123
+ onDrag?: Function;
124
+ resizable?: boolean; // 列宽调整
125
+ placeholder?: string | React.ReactNode | Function; // 数据为空展示
126
+ loading?: boolean | string | React.ReactNode; // 数据加载中
127
+ sticky?: boolean; // 粘性头部
128
+ onFilter?: Function; // 筛选/过滤函数
129
+ childrenColumnName?: string; // 控制数据源哪一列作为嵌套数据,不想支持,就随便设置一个不存在的值,默认是children
130
+ keyField?: string; // 展开嵌套数据的时候,用哪个字段做唯一标识
131
+ indentSize: number; // 树形展示时 设置缩进值
132
+ onRow?: OnRowProps; // 行操作事件
133
+ rowClassName?: Function;
134
+ lineHeight?: string; // 可设置large、middle固定高度,不设置则跟随内容
135
+ showHeader?: boolean; // 是否展示表头
136
+ }
137
+
138
+ export interface ScrollProps {
139
+ x: number | string | true;
140
+ y: number | string;
141
+ }
142
+
143
+ export interface TableState {
144
+ selectedRowKeys: Array<string | number>;
145
+ dataSource: Array<any>;
146
+ expandedRowKeys: Array<string | number>;
147
+ colWidths: Array<number>;
148
+ }
149
+
150
+ function getMaxLevelThRowSpan(columns: Array<ColumnProps>) {
151
+ let maxLevel = 0;
152
+
153
+ Array.isArray(columns) && columns.forEach(c => {
154
+ const level = getThRowSpan(c);
155
+ if (maxLevel < level) {
156
+ maxLevel = level;
157
+ }
158
+ });
159
+
160
+ return maxLevel;
161
+ }
162
+
163
+ function getThRowSpan(column: ColumnProps) {
164
+ if (!column.children || (column.children && !column.children.length)) {
165
+ return 1;
166
+ }
167
+
168
+ return 1 + getMaxLevelThRowSpan(column.children);
169
+ }
170
+
171
+ function getThColSpan(column: ColumnProps) {
172
+ if (!column.children || (column.children && !column.children.length)) {
173
+ return 1;
174
+ }
175
+
176
+ let childrenLength = 0;
177
+ column.children.forEach(item => childrenLength += getThColSpan(item));
178
+
179
+ return childrenLength;
180
+ }
181
+
182
+ function buildColumns(
183
+ columns: Array<ColumnProps> = [],
184
+ thColumns: Array<Array<any>>,
185
+ tdColumns: Array<ColumnProps> = [],
186
+ depth: number = 0,
187
+ id?: string,
188
+ fixed?: boolean | string) {
189
+ const maxLevel = getMaxLevelThRowSpan(columns);
190
+ // 在处理表头时,如果父级column设置了fixed属性,那么所有children保持一致
191
+ Array.isArray(columns) && columns.forEach(column => {
192
+ const groupId = id || guid();
193
+ let childMaxLevel = 0;
194
+ if (column.children) {
195
+ childMaxLevel = getMaxLevelThRowSpan(column.children);
196
+ }
197
+ const newColumn = {
198
+ ...column,
199
+ rowSpan: childMaxLevel ? 1 : maxLevel - childMaxLevel + depth,
200
+ colSpan: getThColSpan(column),
201
+ groupId,
202
+ depth
203
+ };
204
+ const tdColumn = {
205
+ ...column,
206
+ groupId
207
+ };
208
+ if (fixed) {
209
+ newColumn.fixed = fixed;
210
+ tdColumn.fixed = fixed;
211
+ }
212
+
213
+ if (!thColumns[depth]) {
214
+ thColumns[depth] = []
215
+ }
216
+ thColumns[depth].push(newColumn);
217
+ if (column.children && column.children.length > 0) {
218
+ buildColumns(column.children, thColumns, tdColumns, depth + 1, groupId, column.fixed);
219
+ }
220
+ else {
221
+ const {children, ...rest} = tdColumn;
222
+ tdColumns.push(rest);
223
+ }
224
+ });
225
+ }
226
+
227
+ function isFixedLeftColumn(fixed: boolean | string | undefined) {
228
+ return fixed === true || fixed === 'left';
229
+ }
230
+
231
+ function isFixedRightColumn(fixed: boolean | string | undefined) {
232
+ return fixed === 'right';
233
+ }
234
+
235
+ function getPreviousLeftWidth(
236
+ doms: HTMLCollection,
237
+ index: number,
238
+ columns: Array<ColumnProps>
239
+ ) {
240
+ let width = 0;
241
+ for (let i = 0; i < index; i++) {
242
+ if (columns && columns[i] && isFixedLeftColumn(columns[i].fixed)) {
243
+ const dom = doms[i] as HTMLElement;
244
+ width += dom.offsetWidth;
245
+ }
246
+ }
247
+ return width;
248
+ }
249
+
250
+ function getAfterRightWidth(
251
+ doms: HTMLCollection,
252
+ index: number,
253
+ columns: Array<ColumnProps>
254
+ ) {
255
+ let width = 0;
256
+ for (let i = doms.length - 0; i > index; i--) {
257
+ if (columns && columns[i] && isFixedRightColumn(columns[i].fixed)) {
258
+ const dom = doms[i] as HTMLElement;
259
+ width += dom.offsetWidth;
260
+ }
261
+ }
262
+ return width;
263
+ }
264
+
265
+ function hasFixedColumn(columns: Array<ColumnProps>) {
266
+ return find(columns, column => column.fixed);
267
+ }
268
+
269
+ function getSummaryColumns(summary: Array<SummaryProps>) {
270
+ if (!summary) {
271
+ return [];
272
+ }
273
+ const last: Array<SummaryProps> = [];
274
+ const first: Array<SummaryProps> = [];
275
+ summary.forEach(item => {
276
+ if (isObject(item)) {
277
+ first.push(item);
278
+ } else if (Array.isArray(item)) {
279
+ last.push(item);
280
+ }
281
+ });
282
+ return [first, ...last];
283
+ }
284
+
285
+ const DefaultCellWidth = 40;
286
+
287
+ export class Table extends React.PureComponent<TableProps, TableState> {
288
+ static defaultProps = {
289
+ title: '',
290
+ className: '',
291
+ dataSource: [],
292
+ columns: [],
293
+ indentSize: 15,
294
+ placeholder: '暂无数据',
295
+ showHeader: true
296
+ };
297
+
298
+ constructor(props: TableProps) {
299
+ super(props);
300
+
301
+ this.selectedRows = props.rowSelection
302
+ ? this.getSelectedRows(props.dataSource, props.rowSelection?.selectedRowKeys)
303
+ : [];
304
+
305
+ this.state = {
306
+ selectedRowKeys: props.rowSelection
307
+ ? (props.rowSelection.selectedRowKeys.map(key => key) || []) : [],
308
+ dataSource: props.dataSource || [], // 为了支持前端搜索
309
+ expandedRowKeys: [
310
+ ...(props.expandable ? (props.expandable.expandedRowKeys || []) : []),
311
+ ...props.expandable ? (props.expandable.defaultExpandedRowKeys || []) : []
312
+ ],
313
+ colWidths: []
314
+ };
315
+
316
+ this.onTableContentScroll = this.onTableContentScroll.bind(this);
317
+ this.getPopOverContainer = this.getPopOverContainer.bind(this);
318
+ }
319
+
320
+ getPopOverContainer() {
321
+ return findDOMNode(this);
322
+ }
323
+
324
+ // 表头配置
325
+ thColumns: Array<Array<ThProps>>;
326
+ // 表格配置
327
+ tdColumns: Array<TdProps>;
328
+ // 表格当前选中行
329
+ selectedRows: Array<any>;
330
+ // 拖拽排序
331
+ sortable: Sortable;
332
+ // 记录点击起始横坐标
333
+ resizeStart: number;
334
+ resizeKey: string;
335
+
336
+ tableDom: React.RefObject<HTMLDivElement> = React.createRef();
337
+ theadDom: React.RefObject<HTMLTableSectionElement> = React.createRef();
338
+ tbodyDom: React.RefObject<HTMLTableSectionElement> = React.createRef();
339
+ contentDom: React.RefObject<HTMLDivElement> = React.createRef();
340
+ headerDom: React.RefObject<HTMLDivElement> = React.createRef();
341
+ bodyDom: React.RefObject<HTMLDivElement> = React.createRef();
342
+ tfootDom: React.RefObject<HTMLTableSectionElement> = React.createRef();
343
+ footDom: React.RefObject<HTMLDivElement> = React.createRef();
344
+
345
+ getColWidths() {
346
+ const childrens = this.tbodyDom.current?.children[0]?.children || [];
347
+ const colWidths: Array<any> = new Array(childrens ? childrens.length : 0);
348
+
349
+ for (let i = 0; i < childrens.length; i++) {
350
+ const child: any = childrens[i];
351
+ colWidths[i] = child ? child.offsetWidth : null
352
+ };
353
+
354
+ return colWidths;
355
+ }
356
+
357
+ getSelectedRows(dataSource: Array<any>, selectedRowKeys: Array<string | number>) {
358
+ const selectedRows: Array<any> = [];
359
+ dataSource.forEach(data => {
360
+ if (find(selectedRowKeys,
361
+ key => key === data[this.getRowSelectionKeyField()])) {
362
+ selectedRows.push(data);
363
+ }
364
+ });
365
+
366
+ return selectedRows;
367
+ }
368
+
369
+ updateTableBodyFixed() {
370
+ const tbodyDom = this.tbodyDom && (this.tbodyDom.current as HTMLElement);
371
+ const tdColumns = [...this.tdColumns];
372
+ this.updateTbodyFixedRow(tbodyDom, tdColumns);
373
+ this.updateHeadSummaryFixedRow(tbodyDom);
374
+ }
375
+
376
+ updateColWidths() {
377
+ this.setState({colWidths: this.getColWidths()}, () => {
378
+ if (hasFixedColumn(this.props.columns)) {
379
+ const theadDom = this.theadDom && (this.theadDom.current as HTMLElement);
380
+ const thColumns = this.thColumns;
381
+ this.updateTheadFixedRow(theadDom, thColumns);
382
+ this.updateTableBodyFixed();
383
+ }
384
+ });
385
+ }
386
+
387
+ componentDidMount() {
388
+ if (this.props.loading) {
389
+ return;
390
+ }
391
+
392
+ if (hasFixedColumn(this.props.columns)) {
393
+ const headerDom = this.headerDom && (this.headerDom.current as HTMLElement);
394
+ if (headerDom) {
395
+ const headerBody = headerDom.getElementsByTagName('tbody');
396
+ headerBody && headerBody[0] && this.updateHeadSummaryFixedRow(headerBody[0]);
397
+ }
398
+
399
+ const tfootDom = this.tfootDom && (this.tfootDom.current as HTMLElement);
400
+ tfootDom && this.updateFootSummaryFixedRow(tfootDom);
401
+ }
402
+
403
+ let current = null;
404
+ if (this.contentDom && this.contentDom.current) {
405
+ current = this.contentDom.current;
406
+ current.addEventListener('scroll', this.onTableContentScroll.bind(this));
407
+ } else {
408
+ current = this.headerDom?.current;
409
+
410
+ // overflow设置为hidden的情况
411
+ const hiddenDomRefs = [this.headerDom, this.footDom];
412
+ hiddenDomRefs.forEach(ref =>
413
+ ref && ref.current
414
+ && ref.current.addEventListener('wheel', this.onWheel.bind(this)));
415
+ // 横向同步滚动
416
+ const scrollDomRefs = [this.bodyDom];
417
+ scrollDomRefs.forEach(ref =>
418
+ ref && ref.current
419
+ && ref.current.addEventListener('scroll', this.onTableScroll.bind(this)));
420
+ }
421
+ current && this.updateTableDom(current);
422
+
423
+ if (this.props.draggable) {
424
+ this.initDragging();
425
+ }
426
+
427
+ if (this.props.resizable) {
428
+ this.theadDom.current?.addEventListener('mouseup', this.onResizeMouseUp.bind(this));
429
+ }
430
+
431
+ this.updateStickyHeader();
432
+
433
+ this.updateColWidths();
434
+ }
435
+
436
+ componentDidUpdate(prevProps: TableProps, prevState: TableState) {
437
+ // 数据源发生了变化
438
+ if (!isEqual(prevProps.dataSource, this.props.dataSource)) {
439
+ this.setState({dataSource: [...this.props.dataSource]}, () => this.updateColWidths()); // 异步加载数据需求再更新一次
440
+ }
441
+
442
+ // 选择项发生了变化触发
443
+ if (!isEqual(prevState.selectedRowKeys, this.state.selectedRowKeys)) {
444
+ // 更新保存的已选择行数据
445
+ this.selectedRows = this.getSelectedRows(this.state.dataSource, this.state.selectedRowKeys);
446
+
447
+ const {rowSelection} = this.props;
448
+ rowSelection && rowSelection.onChange
449
+ && rowSelection.onChange(this.state.selectedRowKeys, this.selectedRows);
450
+
451
+ this.setState({selectedRowKeys: this.state.selectedRowKeys.filter((key, i, a) => a.indexOf(key) === i)});
452
+ }
453
+
454
+ // 外部传入的选择项发生了变化
455
+ if (!isEqual(prevProps.rowSelection?.selectedRowKeys, this.props.rowSelection?.selectedRowKeys)) {
456
+ if (this.props.rowSelection) {
457
+ this.setState({selectedRowKeys: this.props.rowSelection.selectedRowKeys});
458
+ this.selectedRows = this.getSelectedRows(this.state.dataSource, this.state.selectedRowKeys);
459
+ }
460
+ }
461
+
462
+ // 外部传入的展开项发生了变化
463
+ if (!isEqual(prevProps?.expandable?.expandedRowKeys, this.props.expandable?.expandedRowKeys)) {
464
+ if (this.props.expandable) {
465
+ this.setState({expandedRowKeys: this.props.expandable.expandedRowKeys || []});
466
+ }
467
+ }
468
+
469
+ // 展开行变化时触发
470
+ if (!isEqual(prevState.expandedRowKeys, this.state.expandedRowKeys)) {
471
+ if (this.props.expandable) {
472
+ const {onExpandedRowsChange, keyField} = this.props.expandable;
473
+ const expandedRows: Array<any> = [];
474
+ this.state.dataSource.forEach(item => {
475
+ if (find(this.state.expandedRowKeys, key => key == item[keyField || 'key'])) {
476
+ expandedRows.push(item);
477
+ }
478
+ });
479
+ onExpandedRowsChange && onExpandedRowsChange(expandedRows);
480
+ }
481
+ }
482
+
483
+ // sticky属性发生了变化
484
+ if (prevProps.sticky !== this.props.sticky) {
485
+ this.updateStickyHeader();
486
+ }
487
+ }
488
+
489
+ componentWillUnmount() {
490
+ this.contentDom && this.contentDom.current
491
+ && this.contentDom.current.removeEventListener('scroll', this.onTableContentScroll.bind(this));
492
+
493
+ const hiddenDomRefs = [this.headerDom, this.footDom];
494
+ hiddenDomRefs.forEach(ref =>
495
+ ref && ref.current
496
+ && ref.current.removeEventListener('wheel', this.onWheel.bind(this)));
497
+
498
+ const scrollDomRefs = [this.bodyDom];
499
+ scrollDomRefs.forEach(ref =>
500
+ ref && ref.current
501
+ && ref.current.removeEventListener('scroll', this.onTableScroll.bind(this)));
502
+
503
+ this.destroyDragging();
504
+ }
505
+
506
+ exchange(fromIndex: number, toIndex: number, item: any) {
507
+ const {scroll, headSummary, onDrag} = this.props;
508
+ // 如果有头部总结行 fromIndex就会+1
509
+ if ((!scroll || scroll && !scroll.y) && headSummary) {
510
+ fromIndex = fromIndex - 1;
511
+ }
512
+
513
+ const index = toIndex - fromIndex;
514
+
515
+ const levels = item.getAttribute('row-levels');
516
+ const rowIndex = +item.getAttribute('row-index');
517
+
518
+ const dataSource = cloneDeep(this.state.dataSource);
519
+ const levelsArray = levels ? levels.split(',') : [];
520
+ const childrenColumnName = this.getChildrenColumnName();
521
+ let data: Array<any> = dataSource;
522
+ let i = 0;
523
+ while (i < levelsArray.length) {
524
+ data = data[levelsArray[i]][childrenColumnName];
525
+ i++;
526
+ }
527
+
528
+ if (data && data.length > 0) {
529
+ const row = cloneDeep(data[rowIndex]);
530
+ data.splice(rowIndex, 1);
531
+ data.splice(rowIndex + index, 0, row);
532
+ }
533
+
534
+ // 先通过事件把最新的排序数据提供出去
535
+ // Sortable修改了dom 数据排序后再通过state更新 会有问题
536
+ onDrag && onDrag(dataSource);
537
+ }
538
+
539
+ initDragging() {
540
+ const {classnames: cx} = this.props;
541
+
542
+ this.sortable = new Sortable(
543
+ this.tbodyDom.current as HTMLElement,
544
+ {
545
+ group: 'table',
546
+ animation: 150,
547
+ handle: `.${cx('Table-dragCell')}`,
548
+ ghostClass: 'is-dragging',
549
+ onMove: (e: any) => {
550
+ const dragged = e.dragged;
551
+ const related = e.related;
552
+
553
+ if (related && related.classList.contains(`${cx('Table-summary-row')}`)) {
554
+ return false;
555
+ }
556
+
557
+ const draggedLevels = dragged.getAttribute('row-levels');
558
+ const relatedLevels = related.getAttribute('row-levels');
559
+
560
+ // 嵌套展示 不属于同一层的 不允许拖动
561
+ // 否则涉及到试图的更新,比如子元素都被拖完了
562
+ if (draggedLevels !== relatedLevels) {
563
+ return false;
564
+ }
565
+
566
+ return true;
567
+ },
568
+ onEnd: (e: any) => {
569
+ // 没有移动
570
+ if (e.newIndex === e.oldIndex) {
571
+ return;
572
+ }
573
+
574
+ this.exchange(e.oldIndex, e.newIndex, e.item);
575
+ }
576
+ }
577
+ );
578
+ }
579
+
580
+ destroyDragging() {
581
+ this.sortable && this.sortable.destroy();
582
+ }
583
+
584
+ updateStickyHeader() {
585
+ if (this.props.sticky) {
586
+ // 如果设置了sticky 如果父元素设置了overflow: auto top值还需要考虑padding值
587
+ let parent = this.headerDom?.current?.parentElement;
588
+ setTimeout(() => {
589
+ while (parent && window.getComputedStyle(parent, null).getPropertyValue('overflow') !== 'auto') {
590
+ parent = parent.parentElement;
591
+ }
592
+ if (parent && window.getComputedStyle(parent, null).getPropertyValue('overflow') === 'auto') {
593
+ const paddingTop = window.getComputedStyle(parent, null).getPropertyValue('padding-top');
594
+ if (paddingTop && this.headerDom && this.headerDom.current) {
595
+ this.headerDom.current.style.top = '-' + paddingTop;
596
+ }
597
+ }
598
+ });
599
+ }
600
+ }
601
+
602
+ // 更新一个tr下的td的left和class
603
+ updateFixedRow(row: HTMLElement, columns: Array<ColumnProps>) {
604
+ const {classnames: cx} = this.props;
605
+
606
+ const children = row.children;
607
+ for (let i = 0; i < children.length; i++) {
608
+ const dom = children[i] as HTMLElement;
609
+ const fixed = columns[i] ? (columns[i].fixed || '') : '';
610
+ if (isFixedLeftColumn(fixed)) {
611
+ dom.style.left = i > 0 ? getPreviousLeftWidth(children, i, columns) + 'px' : '0';
612
+ } else if (isFixedRightColumn(fixed)) {
613
+ dom.style.right = i < children.length - 1
614
+ ? getAfterRightWidth(children, i, columns) + 'px' : '0';
615
+ }
616
+ }
617
+ // 最后一个左fixed的添加样式
618
+ let leftIndex = findLastIndex(columns, column => isFixedLeftColumn(column.fixed));
619
+ if (leftIndex > -1) {
620
+ children[leftIndex]?.classList.add(cx('Table-cell-fix-left-last'));
621
+ }
622
+ // 第一个右fixed的添加样式
623
+ let rightIndex = columns.findIndex(column => isFixedRightColumn(column.fixed));
624
+ if (rightIndex > -1) {
625
+ children[rightIndex]?.classList.add(cx('Table-cell-fix-right-first'));
626
+ if (rightIndex > 0) {
627
+ children[rightIndex - 1]?.classList.add(cx('Table-cell-fix-right-first-prev'));
628
+ }
629
+ }
630
+ }
631
+
632
+ // 在可选、可展开、可拖拽的情况下,补充column,方便fix处理
633
+ prependColumns(columns: Array<any>) {
634
+ const {rowSelection, expandable, draggable} = this.props;
635
+ if (draggable) {
636
+ columns.unshift({});
637
+ } else {
638
+ if (expandable) {
639
+ columns.unshift(expandable);
640
+ }
641
+ if (rowSelection) {
642
+ columns.unshift(rowSelection);
643
+ }
644
+ }
645
+ }
646
+
647
+ updateTheadFixedRow(thead: HTMLElement, columns: Array<any>) {
648
+ const children = thead.children;
649
+ for (let i = 0; i < children.length; i++) {
650
+ const cols = [...columns[i]];
651
+ if (i === 0) {
652
+ this.prependColumns(cols);
653
+ }
654
+
655
+ this.updateFixedRow(children[i] as HTMLElement, cols);
656
+ }
657
+ }
658
+
659
+ updateTbodyFixedRow(tbody: HTMLElement, columns: Array<any>) {
660
+ const {classnames: cx} = this.props;
661
+ const children = filter(tbody.children,
662
+ child => !child.classList.contains(cx('Table-summary-row'))
663
+ && !child.classList.contains(cx('Table-empty-row')));
664
+ this.prependColumns(columns);
665
+ for (let i = 0; i < children.length; i++) {
666
+ this.updateFixedRow(children[i] as HTMLElement, columns);
667
+ }
668
+ }
669
+
670
+ updateSummaryFixedRow(children: HTMLCollection | Array<Element>, columns: Array<any>) {
671
+ for (let i = 0; i < children.length; i++) {
672
+ this.updateFixedRow(children[i] as HTMLElement, columns[i]);
673
+ }
674
+ }
675
+
676
+ updateFootSummaryFixedRow(tfoot: HTMLElement) {
677
+ const {footSummary} = this.props;
678
+ if (Array.isArray(footSummary)) {
679
+ const columns = getSummaryColumns(footSummary as Array<SummaryProps>);
680
+ this.updateSummaryFixedRow(tfoot.children, columns);
681
+ }
682
+ }
683
+
684
+ updateHeadSummaryFixedRow(tbody: HTMLElement) {
685
+ const {headSummary, classnames: cx} = this.props;
686
+ if (Array.isArray(headSummary)) {
687
+ const columns = getSummaryColumns(headSummary as Array<SummaryProps>);
688
+ const children = filter(tbody.children,
689
+ child => child.classList.contains(cx('Table-summary-row')));
690
+ this.updateSummaryFixedRow(children, columns);
691
+ }
692
+ }
693
+
694
+ renderColGroup(colWidths?: Array<number>) {
695
+ const {rowSelection, classnames: cx, expandable, draggable} = this.props;
696
+
697
+ const tdColumns = this.tdColumns;
698
+ const isExpandable = this.isExpandableTable();
699
+ const extraCount = this.getExtraColumnCount();
700
+
701
+ return (
702
+ <colgroup>
703
+ {draggable
704
+ ? <col
705
+ className={cx('Table-drag-col')}
706
+ style={{width: DefaultCellWidth + 'px'}}></col> : null}
707
+ {!draggable && rowSelection
708
+ ? <col className={cx('Table-selection-col')}
709
+ style={{width: (rowSelection.columnWidth || DefaultCellWidth) + 'px'}}></col> : null}
710
+ {
711
+ !draggable && isExpandable ? <col
712
+ className={cx('Table-expand-col')}
713
+ style={{width: (expandable?.columnWidth || DefaultCellWidth) + 'px'}}
714
+ ></col> : null
715
+ }
716
+ {tdColumns.map((data, index) => {
717
+ const width = colWidths ? colWidths[index + extraCount] : data.width;
718
+ return <col
719
+ key={index}
720
+ style={{width: typeof width === 'number' ? width + 'px' : width}}
721
+ className={data.className ? cx(`Table-colgroup-${data.className}`) : ''}>
722
+ </col>;
723
+ })}
724
+ </colgroup>
725
+ );
726
+ }
727
+
728
+ onResizeMouseDown(event: React.MouseEvent<any>, key: string) {
729
+ // 点击记录起始坐标
730
+ this.resizeStart = event.clientX;
731
+ // 记录点击的列名
732
+ this.resizeKey = key;
733
+ event && event.stopPropagation();
734
+ }
735
+
736
+ onResizeMouseUp(event: React.MouseEvent<any>) {
737
+ // 点击了调整列宽
738
+ if (this.resizeStart && this.resizeKey) {
739
+ // 计算横向移动距离
740
+ const distance = event.clientX - this.resizeStart;
741
+ const tdColumns = [...this.tdColumns];
742
+ let index = tdColumns.findIndex(c => c.key === this.resizeKey)
743
+ + this.getExtraColumnCount();
744
+
745
+ const colGroup = this.tableDom.current?.getElementsByTagName('colgroup')[0];
746
+ let currentWidth = 0;
747
+ if (colGroup && colGroup.children[index]) {
748
+ const child = colGroup.children[index] as HTMLElement;
749
+ currentWidth = child.offsetWidth;
750
+ }
751
+
752
+ let newWidth = 0;
753
+ if (colGroup) {
754
+ let maxDistance = 0; // 最多可以移动的距离
755
+ // 调宽列
756
+ if (distance > 0) {
757
+ for (let i = 0; i < colGroup.children.length; i++) {
758
+ const child = colGroup.children[i] as HTMLElement;
759
+ // 自适应列 保证有一个最小宽度
760
+ // 如果都设置了固定宽度 那一个都拖不动
761
+ if (!this.tdColumns[i].width) {
762
+ maxDistance += child.offsetWidth - DefaultCellWidth;
763
+ }
764
+ }
765
+ if (colGroup.children[index]) {
766
+ const child = colGroup.children[index] as HTMLElement;
767
+ newWidth = currentWidth + Math.min(distance, maxDistance);
768
+ child.style.width = newWidth + 'px';
769
+ }
770
+ } else { // 缩短列
771
+ const autoColumns = [];
772
+ for (let i = 0; i < colGroup.children.length; i++) {
773
+ const child = colGroup.children[i] as HTMLElement;
774
+ // 自适应列 保证有一个最小宽度
775
+ // 如果都设置了固定宽度 那一个都拖不动
776
+ if (!this.tdColumns[i].width) {
777
+ autoColumns.push(child);
778
+ }
779
+ }
780
+ maxDistance = DefaultCellWidth - currentWidth;
781
+ if (colGroup.children[index]) {
782
+ const child = colGroup.children[index] as HTMLElement;
783
+ newWidth = currentWidth + Math.max(distance, maxDistance);
784
+ child.style.width = newWidth + 'px';
785
+ }
786
+ const gap = Math.abs(Math.max(distance, maxDistance)) / autoColumns.length;
787
+ autoColumns.forEach(c => {
788
+ c.style.width = c.offsetWidth + gap + 'px';
789
+ });
790
+ }
791
+ }
792
+
793
+ const column = find(tdColumns, c => c.key === this.resizeKey);
794
+ // 只有通过配置设置过的宽度保存到tdColumns
795
+ // 自动分配的不保存
796
+ // 这样可以一直调整了
797
+ if (column && column.width && newWidth) {
798
+ column.width = newWidth;
799
+ }
800
+
801
+ this.tdColumns = tdColumns;
802
+
803
+ this.resizeStart = 0;
804
+ this.resizeKey = '';
805
+ }
806
+ event && event.stopPropagation();
807
+ }
808
+
809
+ renderTHead() {
810
+ const {
811
+ rowSelection,
812
+ dataSource,
813
+ classnames: cx,
814
+ onSort,
815
+ expandable,
816
+ draggable,
817
+ resizable
818
+ } = this.props;
819
+
820
+ const thColumns = this.thColumns;
821
+ // 获取一行最多th个数
822
+ let maxCount = 0;
823
+ thColumns.forEach(columns => {
824
+ if (columns.length > maxCount) {
825
+ maxCount = columns.length;
826
+ }
827
+ });
828
+ const keyField = this.getRowSelectionKeyField();
829
+ const dataList = rowSelection && rowSelection.getCheckboxProps
830
+ ? this.state.dataSource.filter((data, index) => {
831
+ const props = rowSelection.getCheckboxProps(data, index);
832
+ return !props.disabled;
833
+ }) : this.state.dataSource;
834
+
835
+ const isExpandable = this.isExpandableTable();
836
+
837
+ let allRowKeys: Array<string> = [];
838
+ let allRows: Array<any> = [];
839
+ dataList.forEach(data => {
840
+ allRowKeys.push(data[keyField]);
841
+ allRows.push(data);
842
+ if (!expandable && this.hasChildrenRow(data)) {
843
+ allRowKeys = [...allRowKeys, ...this.getDataChildrenKeys(data)];
844
+ data[this.getChildrenColumnName()].forEach((item: any) => allRows.push(item));
845
+ }
846
+ });
847
+
848
+ return (
849
+ <thead ref={this.theadDom} className={cx('Table-thead')}>
850
+ {thColumns.map((data, index) => {
851
+ return <tr key={'th-cell-' + index}>
852
+ {
853
+ draggable && index === 0 ? <Cell
854
+ wrapperComponent="th"
855
+ rowSpan={thColumns.length}
856
+ className={cx('Table-dragCell')}></Cell> : null
857
+ }
858
+ {!draggable && rowSelection && index === 0
859
+ ? <Cell
860
+ wrapperComponent="th"
861
+ rowSpan={thColumns.length}
862
+ fixed={rowSelection.fixed ? 'left': ''}
863
+ className={cx('Table-checkCell')}>
864
+ {rowSelection.type !== 'radio'
865
+ ? [<CheckBox
866
+ key="checkAll"
867
+ partial={this.state.selectedRowKeys.length > 0
868
+ && this.state.selectedRowKeys.length < allRowKeys.length}
869
+ checked={this.state.selectedRowKeys.length > 0}
870
+ onChange={value => {
871
+ let changeRows;
872
+ if (value) {
873
+ changeRows = dataList.filter(data => !this.hasCheckedRows(data));
874
+ } else {
875
+ changeRows = this.selectedRows;
876
+ }
877
+ const selectedRows = value ? allRows : [];
878
+ this.setState({
879
+ selectedRowKeys: value ? allRowKeys : []
880
+ });
881
+
882
+ rowSelection.onSelectAll
883
+ && rowSelection.onSelectAll(value, selectedRows, changeRows);
884
+ }}></CheckBox>,
885
+ rowSelection.selections && rowSelection.selections.length > 0
886
+ ? <HeadCellSelect
887
+ key="checkSelection"
888
+ keys={allRowKeys}
889
+ selections={rowSelection.selections}
890
+ popOverContainer={this.getPopOverContainer}>
891
+ </HeadCellSelect> : null] : null
892
+ }</Cell> : null}
893
+ {
894
+ !draggable && isExpandable && index === 0
895
+ ? <Cell
896
+ wrapperComponent="th"
897
+ rowSpan={thColumns.length}
898
+ fixed={expandable && expandable.fixed ? 'left': ''}
899
+ className={cx('Table-row-expand-icon-cell')}></Cell> : null
900
+ }
901
+ {data.map((item, i) => {
902
+ let sort = null;
903
+ if (item.sorter) {
904
+ sort = (
905
+ <HeadCellSort
906
+ column={item}
907
+ onSort={onSort ? onSort : (payload: any) => {
908
+ if (typeof item.sorter === 'function') {
909
+ if (payload.orderBy) {
910
+ const sortList = [...this.state.dataSource];
911
+ this.setState({dataSource: sortList.sort(item.sorter as (a: any, b: any) => number)});
912
+ } else {
913
+ this.setState({dataSource: [...dataSource]});
914
+ }
915
+ }
916
+ }}
917
+ ></HeadCellSort>
918
+ );
919
+ }
920
+
921
+ let filter = null;
922
+ if (item.filterDropdown) {
923
+ filter = item.filterDropdown;
924
+ } else if (item.filters && item.filters.length > 0) {
925
+ filter = (
926
+ <HeadCellFilter
927
+ column={item}
928
+ popOverContainer={this.getPopOverContainer}>
929
+ </HeadCellFilter>
930
+ );
931
+ }
932
+
933
+ const children = <span>
934
+ {sort}
935
+ {filter}
936
+ {resizable ? <i
937
+ className={cx('Table-thead-resizable')}
938
+ onMouseDown={e => this.onResizeMouseDown(e, item.key)}></i> : null}
939
+ </span>;
940
+
941
+ return <Cell
942
+ wrapperComponent="th"
943
+ rowSpan={item.rowSpan}
944
+ colSpan={item.colSpan}
945
+ key={'cell' + (item.key || i)}
946
+ fixed={item.fixed === true ? 'left' : item.fixed}
947
+ className={cx({
948
+ 'Table-cell-last': i === maxCount - 1 && i === data.length - 1
949
+ })}
950
+ groupId={item.groupId}
951
+ depth={item.depth}>
952
+ {typeof item.title === 'function' ? item.title(children) : item.title}
953
+ </Cell>;
954
+ })
955
+ }</tr>;
956
+ })}
957
+ </thead>
958
+ );
959
+ }
960
+
961
+ onRowClick(event: React.ChangeEvent<any>, record?: any, rowIndex?: number) {
962
+ const {rowSelection, onRow} = this.props;
963
+
964
+ if (rowSelection && rowSelection.type && rowSelection.rowClick) {
965
+ const defaultKey = this.getRowSelectionKeyField();
966
+
967
+ const isSelected = !!find(this.state.selectedRowKeys, key => key === record[defaultKey]);
968
+
969
+ this.selectedSingleRow(!isSelected, record);
970
+ }
971
+
972
+ if (record && onRow) {
973
+ onRow.onRowClick && onRow.onRowClick(event, record, rowIndex);
974
+ }
975
+ }
976
+
977
+ onRowMouseEnter(event: React.ChangeEvent<any>, record?: any, rowIndex?: number) {
978
+ const {classnames: cx, onRow} = this.props;
979
+
980
+ let parent = event.target;
981
+ while (parent && parent.tagName !== 'TR') {
982
+ parent = parent.parentElement;
983
+ }
984
+
985
+ if (parent && !parent.classList.contains(cx('Table-row-disabled'))) {
986
+ for (let i = 0; i < parent.children.length; i++) {
987
+ const td = parent.children[i];
988
+ td.classList.add(cx('Table-cell-row-hover')); // 保证有列fixed的时候样式一致
989
+ }
990
+ }
991
+
992
+ if (record && onRow) {
993
+ onRow.onRowMouseEnter && onRow.onRowMouseEnter(event, record, rowIndex);
994
+ }
995
+ }
996
+
997
+ onRowMouseLeave(event: React.ChangeEvent<any>, record?: any, rowIndex?: number) {
998
+ const {classnames: cx, onRow} = this.props;
999
+
1000
+ let parent = event.target;
1001
+ while (parent && parent.tagName !== 'TR') {
1002
+ parent = parent.parentElement;
1003
+ }
1004
+
1005
+ if (parent) {
1006
+ for (let i = 0; i < parent.children.length; i++) {
1007
+ const td = parent.children[i];
1008
+ td.classList.remove(cx('Table-cell-row-hover'));
1009
+ }
1010
+ }
1011
+
1012
+ if (record && onRow) {
1013
+ onRow.onRowMouseLeave && onRow.onRowMouseLeave(event, record, rowIndex);
1014
+ }
1015
+ }
1016
+
1017
+ onExpandRow(data: any) {
1018
+ const {expandedRowKeys} = this.state;
1019
+ const {expandable} = this.props;
1020
+ const key = data[this.getExpandableKeyField()];
1021
+ this.setState({expandedRowKeys: [...expandedRowKeys, key]});
1022
+ expandable?.onExpand && expandable?.onExpand(true, data);
1023
+ }
1024
+
1025
+ onCollapseRow(data: any) {
1026
+ const {expandedRowKeys} = this.state;
1027
+ const {expandable} = this.props;
1028
+ const key = data[this.getExpandableKeyField()];
1029
+ // 还是得模糊匹配 否则'3'、3匹配不上
1030
+ this.setState({expandedRowKeys: expandedRowKeys.filter(k => k != key)});
1031
+ expandable?.onExpand && expandable?.onExpand(false, data);
1032
+ }
1033
+
1034
+ getChildrenColumnName() {
1035
+ const {childrenColumnName} = this.props;
1036
+
1037
+ return childrenColumnName || 'children';
1038
+ }
1039
+
1040
+ getRowSelectionKeyField() {
1041
+ const {rowSelection} = this.props;
1042
+
1043
+ return rowSelection ? (rowSelection.keyField || 'key') : '';
1044
+ }
1045
+
1046
+ getExpandableKeyField() {
1047
+ const {expandable, keyField} = this.props;
1048
+
1049
+ return expandable?.keyField || keyField || 'key';
1050
+ }
1051
+
1052
+ hasChildrenRow(data: any) {
1053
+ const key = this.getChildrenColumnName();
1054
+ return data[key]
1055
+ && Array.isArray(data[key]) && data[key].length > 0;
1056
+ }
1057
+
1058
+ // 展开和嵌套不能共存
1059
+ isExpandableRow(data: any, rowIndex: number) {
1060
+ const {expandable} = this.props;
1061
+
1062
+ return expandable && expandable.rowExpandable
1063
+ && expandable.rowExpandable(data, rowIndex);
1064
+ }
1065
+
1066
+ // 获取当前行数据所有子行的key值
1067
+ getDataChildrenKeys(data: any) {
1068
+ let keys: Array<string> = [];
1069
+
1070
+ if (this.hasChildrenRow(data)) {
1071
+ const key = this.getChildrenColumnName();
1072
+ data[key].forEach((item: any) =>
1073
+ keys = [
1074
+ ...keys,
1075
+ ...this.getDataChildrenKeys(item),
1076
+ item[this.getRowSelectionKeyField()]
1077
+ ]);
1078
+ }
1079
+
1080
+ return keys;
1081
+ }
1082
+
1083
+ hasCheckedRows(data: any) {
1084
+ const selectedRowKeys = this.state.selectedRowKeys;
1085
+ const childrenKeys = this.getDataChildrenKeys(data);
1086
+
1087
+ return intersection(selectedRowKeys, [
1088
+ ...childrenKeys,
1089
+ data[this.getRowSelectionKeyField()]
1090
+ ]).length > 0;
1091
+ }
1092
+
1093
+ hasCheckedChildrenRows(data: any) {
1094
+ const selectedRowKeys = this.state.selectedRowKeys;
1095
+ const childrenKeys = this.getDataChildrenKeys(data);
1096
+ const length = intersection(selectedRowKeys, childrenKeys).length;
1097
+
1098
+ return length > 0;
1099
+ }
1100
+
1101
+ getExpandedIcons(isExpanded: boolean, record: any) {
1102
+ const {classnames: cx} = this.props;
1103
+
1104
+ return isExpanded
1105
+ ? <i
1106
+ className={cx(
1107
+ 'Table-expandBtn',
1108
+ 'is-active'
1109
+ )}
1110
+ onClick={this.onCollapseRow.bind(this, record)}>
1111
+ <Icon icon="right-arrow-bold" className="icon" />
1112
+ </i>
1113
+ : <i
1114
+ className={cx(
1115
+ 'Table-expandBtn'
1116
+ )}
1117
+ onClick={this.onExpandRow.bind(this, record)}>
1118
+ <Icon icon="right-arrow-bold" className="icon" />
1119
+ </i>;
1120
+ }
1121
+
1122
+ selectedSingleRow(value: boolean, data: any) {
1123
+ const {rowSelection} = this.props;
1124
+
1125
+ const defaultKey = this.getRowSelectionKeyField();
1126
+ const isRadio = rowSelection && rowSelection.type === 'radio';
1127
+
1128
+ const callback = () => {
1129
+ rowSelection && rowSelection.onSelect
1130
+ && rowSelection.onSelect(
1131
+ data,
1132
+ value,
1133
+ this.selectedRows,
1134
+ this.state.selectedRowKeys
1135
+ );
1136
+ };
1137
+
1138
+ if (value) {
1139
+ if (isRadio) {
1140
+ this.setState({
1141
+ selectedRowKeys: [data[defaultKey]]
1142
+ }, callback);
1143
+ } else {
1144
+ this.setState(prevState => (
1145
+ {
1146
+ selectedRowKeys: [
1147
+ ...prevState.selectedRowKeys,
1148
+ data[defaultKey],
1149
+ ...this.getDataChildrenKeys(data)
1150
+ ].filter((key, i, a) => a.indexOf(key) === i)
1151
+ }
1152
+ ), callback);
1153
+ }
1154
+ } else {
1155
+ if (!isRadio) {
1156
+ this.setState({
1157
+ selectedRowKeys: this.state.selectedRowKeys.filter(key =>
1158
+ ![data[defaultKey], ...this.getDataChildrenKeys(data)].includes(key))
1159
+ }, callback);
1160
+ }
1161
+ }
1162
+ }
1163
+
1164
+ renderRow(data: any, rowIndex: number, levels: Array<number>) {
1165
+ const {
1166
+ classnames: cx,
1167
+ rowSelection,
1168
+ expandable,
1169
+ draggable,
1170
+ indentSize,
1171
+ rowClassName,
1172
+ lineHeight // 是否设置了固定行高
1173
+ } = this.props;
1174
+
1175
+ const tdColumns = this.tdColumns;
1176
+ const isExpandable = this.isExpandableTable();
1177
+ const defaultKey = this.getRowSelectionKeyField();
1178
+ const colCount = this.getExtraColumnCount();
1179
+
1180
+ // 当前行是否可展开
1181
+ const isExpandableRow = this.isExpandableRow(data, rowIndex);
1182
+ // 当前行是否有children
1183
+ const hasChildrenRow = this.hasChildrenRow(data);
1184
+
1185
+ const isExpanded = !!find(this.state.expandedRowKeys,
1186
+ key => key == data[this.getExpandableKeyField()]); // == 匹配 否则'3'、3匹配不上
1187
+
1188
+ // 设置缩进效果
1189
+ const indentDom = levels.length > 0 ? <span
1190
+ className={cx('Table-row-indent', `indent-level-${levels.length}`)}
1191
+ style={{paddingLeft: (indentSize * levels.length) + 'px'}}></span> : null;
1192
+
1193
+ const cells = tdColumns.map((item, i) => {
1194
+ const render = item.render && typeof item.render === 'function'
1195
+ ? item.render(data[item.key], data, rowIndex, i) : null;
1196
+ let props = {rowSpan: 1, colSpan: 1};
1197
+ let children = render;
1198
+ if (render && isObject(render)) {
1199
+ props = render.props;
1200
+ children = render.children;
1201
+ // 如果合并行 且有展开行,那么合并行不生效
1202
+ if (props.rowSpan > 1 && isExpandableRow && hasChildrenRow) {
1203
+ props.rowSpan === 1;
1204
+ }
1205
+ }
1206
+ return props.rowSpan === 0 || props.colSpan === 0 ? null : <Cell
1207
+ key={i}
1208
+ {...props}
1209
+ fixed={item.fixed === true ? 'left' : item.fixed}
1210
+ column={item}
1211
+ groupId={item.groupId}>
1212
+ <div className={cx('Table-cell-wrapper', {
1213
+ [cx('Table-cell-wrapper-prefix')]: i === 0
1214
+ && (!!indentDom || levels.length === 0 && hasChildrenRow),
1215
+ [cx(`Table-cell-height-${lineHeight}`)]: !!lineHeight
1216
+ })}>
1217
+ {i === 0 && levels.length > 0 ? indentDom : null}
1218
+ {i === 0 && hasChildrenRow
1219
+ ? this.getExpandedIcons(isExpanded, data) : null}
1220
+ {render
1221
+ ? children
1222
+ : data[item.key]}
1223
+ </div>
1224
+ </Cell>;
1225
+ });
1226
+
1227
+ const rowClassNameClass = rowClassName && typeof rowClassName === 'function'
1228
+ ? rowClassName(data, rowIndex) : '';
1229
+
1230
+ // 可展开和嵌套不能同时支持
1231
+ // 设置了expandable 数据源里有children也就不生效了
1232
+ // 拖拽排序 可选、可展开都先不支持了,可以支持嵌套展示
1233
+ const checkboxProps = rowSelection && rowSelection.getCheckboxProps
1234
+ ? rowSelection.getCheckboxProps(data, rowIndex) : {};
1235
+
1236
+ const expandedRowClassName = expandable && expandable.expandedRowClassName
1237
+ && typeof expandable.expandedRowClassName === 'function'
1238
+ ? expandable.expandedRowClassName(data, rowIndex) : '';
1239
+ const dataKey = this.getChildrenColumnName();
1240
+
1241
+ const children = !draggable && isExpandableRow && isExpanded
1242
+ ? <tr
1243
+ key="expanded"
1244
+ className={cx('Table-expanded-row', expandedRowClassName)}>
1245
+ <Cell colSpan={tdColumns.length + colCount}>
1246
+ {expandable && expandable.expandedRowRender
1247
+ && typeof expandable.expandedRowRender === 'function'
1248
+ ? expandable.expandedRowRender(data, rowIndex) : null}
1249
+ </Cell>
1250
+ </tr> : (this.hasChildrenRow(data) && isExpanded ? data[dataKey].map((item: any, index: number) => {
1251
+ return this.renderRow(item, index, [...levels, rowIndex]);
1252
+ }) : null);
1253
+
1254
+ const isChecked = !!find(this.state.selectedRowKeys, key => key === data[defaultKey]);
1255
+ const hasChildrenChecked = this.hasCheckedChildrenRows(data);
1256
+
1257
+ return [<tr
1258
+ key={rowIndex}
1259
+ row-index={rowIndex}
1260
+ row-levels={levels.join(',')}
1261
+ className={cx(
1262
+ 'Table-row',
1263
+ `Table-row-level-${levels.length}`,
1264
+ rowClassNameClass, {
1265
+ 'Table-row-disabled': !!checkboxProps.disabled
1266
+ })}
1267
+ onMouseEnter={e => this.onRowMouseEnter(e, data, rowIndex)}
1268
+ onMouseLeave={e => this.onRowMouseLeave(e, data, rowIndex)}
1269
+ onClick={e => this.onRowClick(e, data, rowIndex)}>
1270
+ {
1271
+ draggable ? <Cell
1272
+ className={cx('Table-dragCell')}>
1273
+ <Icon icon="drag-bar" className="icon"></Icon>
1274
+ </Cell> : null
1275
+ }
1276
+ {!draggable && rowSelection
1277
+ ? (<Cell
1278
+ fixed={rowSelection.fixed ? 'left' : ''}
1279
+ className={cx('Table-checkCell')}>
1280
+ <CheckBox
1281
+ name={'Table-checkbox'}
1282
+ type={rowSelection.type || 'checkbox'}
1283
+ partial={hasChildrenChecked && !isChecked}
1284
+ checked={hasChildrenChecked || isChecked}
1285
+ onChange={
1286
+ (value, shift) => {
1287
+ if (!(rowSelection && rowSelection.rowClick)) {
1288
+ this.selectedSingleRow(value, data);
1289
+ }
1290
+
1291
+ event && event.stopPropagation();
1292
+ }
1293
+ }
1294
+ {...checkboxProps}></CheckBox></Cell>) : null}
1295
+ {
1296
+ !draggable && isExpandable ? <Cell
1297
+ fixed={expandable && expandable.fixed ? 'left' : ''}
1298
+ className={cx('Table-cell-expand-icon-cell')}>
1299
+ {isExpandableRow || hasChildrenRow
1300
+ ? this.getExpandedIcons(isExpanded, data) : null}
1301
+ </Cell> : null
1302
+ }
1303
+ {cells}</tr>, children];
1304
+ }
1305
+
1306
+ renderTBody() {
1307
+ const {
1308
+ classnames: cx,
1309
+ headSummary,
1310
+ scroll,
1311
+ placeholder,
1312
+ sticky
1313
+ } = this.props;
1314
+
1315
+ const tdColumns = this.tdColumns;
1316
+ const hasScrollY = scroll && scroll.y;
1317
+ const colCount = this.getExtraColumnCount();
1318
+ return (
1319
+ <tbody ref={this.tbodyDom} className={cx('Table-tbody')}>
1320
+ {!hasScrollY && !sticky && headSummary
1321
+ ? this.renderSummaryRow(headSummary) : null}
1322
+ {
1323
+ !this.state.dataSource.length
1324
+ ? <tr className={cx('Table-row', 'Table-empty-row')}>
1325
+ <Cell colSpan={tdColumns.length + colCount}>
1326
+ <div className={cx('Table-empty')}>
1327
+ {typeof placeholder === 'function' ? placeholder() : placeholder}
1328
+ </div>
1329
+ </Cell>
1330
+ </tr>
1331
+ : this.state.dataSource.map((data, index) => {
1332
+ return this.renderRow(data, index, []);
1333
+ })
1334
+ }
1335
+ </tbody>
1336
+ );
1337
+ }
1338
+
1339
+ isExpandableTable() {
1340
+ const {expandable} = this.props;
1341
+
1342
+ // 设置了expandable 优先级更高
1343
+ // 就不支持默认嵌套了
1344
+ return !!expandable;
1345
+ }
1346
+
1347
+ isNestedTable() {
1348
+ const {dataSource} = this.props;
1349
+ return !!find(dataSource, item => this.hasChildrenRow(item));
1350
+ }
1351
+
1352
+ getExtraColumnCount() {
1353
+ const {
1354
+ draggable,
1355
+ rowSelection
1356
+ } = this.props;
1357
+
1358
+ let count = 0;
1359
+ if (draggable) {
1360
+ count++;
1361
+ } else {
1362
+ if (this.isExpandableTable()) {
1363
+ count++;
1364
+ }
1365
+ if (rowSelection) {
1366
+ count++;
1367
+ }
1368
+ }
1369
+
1370
+ return count;
1371
+ }
1372
+
1373
+ renderSummaryRow(summary: any) {
1374
+ const {classnames: cx, dataSource} = this.props;
1375
+ const cells: Array<React.ReactNode> = [];
1376
+ const trs: Array<React.ReactNode> = [];
1377
+ let colCount = this.getExtraColumnCount();
1378
+
1379
+ (Array.isArray(summary) ? summary.forEach((s, index) => {
1380
+ Array.isArray(s) ? trs.push(<tr
1381
+ onMouseEnter={e => this.onRowMouseEnter(e)}
1382
+ onMouseLeave={e => this.onRowMouseLeave(e)}
1383
+ key={'summary-tr-' + index}
1384
+ className={cx('Table-summary-row')}>
1385
+ {s.map((d, i) => {
1386
+ // 将操作列自动添加到第一列,用户的colSpan只需要关心实际的列数
1387
+ const colSpan = i === 0 ? (d.colSpan || 1) + colCount : d.colSpan;
1388
+ return <Cell
1389
+ key={'summary-tr-cell-' + i}
1390
+ fixed={d.fixed}
1391
+ colSpan={colSpan}
1392
+ >
1393
+ {typeof d.render === 'function' ? d.render(dataSource) : d.render}
1394
+ </Cell>;
1395
+ })}</tr>) : cells.push(
1396
+ <Cell
1397
+ key={'summary-cell-' + index}
1398
+ fixed={s.fixed}
1399
+ colSpan={cells.length === 0 ? ((s.colSpan || 1) + colCount) : s.colSpan}>
1400
+ {typeof s.render === 'function' ? s.render(dataSource) : s.render}
1401
+ </Cell>);
1402
+ }) : null)
1403
+
1404
+ return (
1405
+ summary ? (typeof summary === 'function'
1406
+ ? summary(dataSource) : [cells.length > 0 ? <tr
1407
+ onMouseEnter={e => this.onRowMouseEnter(e)}
1408
+ onMouseLeave={e => this.onRowMouseLeave(e)}
1409
+ key="summary-row"
1410
+ className={cx('Table-summary-row')}>{cells}</tr> : null, ...trs]) : null
1411
+ );
1412
+ }
1413
+
1414
+ renderTFoot() {
1415
+ const {classnames: cx, footSummary} = this.props;
1416
+ return (<tfoot ref={this.tfootDom} className={cx('Table-summary')}>
1417
+ {this.renderSummaryRow(footSummary)}
1418
+ </tfoot>);
1419
+ }
1420
+
1421
+ updateTableDom(dom: HTMLElement) {
1422
+ const {classnames: cx} = this.props;
1423
+ const {scrollLeft, scrollWidth, offsetWidth} = dom;
1424
+ const table = this.tableDom.current;
1425
+
1426
+ const leftCalss = cx('Table-ping-left');
1427
+ if (scrollLeft > 0) {
1428
+ table?.classList.add(leftCalss);
1429
+ } else {
1430
+ table?.classList.remove(leftCalss);
1431
+ }
1432
+
1433
+ const rightClass = cx('Table-ping-right');
1434
+ if (scrollLeft + offsetWidth < scrollWidth) {
1435
+ table?.classList.add(rightClass);
1436
+ } else {
1437
+ table?.classList.remove(rightClass);
1438
+ }
1439
+ }
1440
+
1441
+ onTableContentScroll(event: React.ChangeEvent<any>) {
1442
+ this.updateTableDom(event.target);
1443
+ }
1444
+
1445
+ onWheel(event: WheelEvent) {
1446
+ const {currentTarget, deltaX} = event as unknown as React.WheelEvent<HTMLDivElement>;
1447
+ if (deltaX) {
1448
+ this.onTableScroll({
1449
+ target: currentTarget,
1450
+ scrollLeft: currentTarget.scrollLeft + deltaX
1451
+ });
1452
+
1453
+ event.preventDefault();
1454
+ }
1455
+ }
1456
+
1457
+ onTableScroll(event: {target: HTMLDivElement, scrollLeft?: number}) {
1458
+ const scrollDomRefs = [
1459
+ this.headerDom,
1460
+ this.bodyDom,
1461
+ this.footDom
1462
+ ];
1463
+
1464
+ const {target, scrollLeft} = event;
1465
+
1466
+ scrollDomRefs.forEach(ref => {
1467
+ const current = ref && ref.current
1468
+ if (current && current !== target) {
1469
+ current.scrollLeft = (scrollLeft || target.scrollLeft);
1470
+ }
1471
+ });
1472
+
1473
+ this.updateTableDom(target);
1474
+ }
1475
+
1476
+ renderLoading() {
1477
+ const {classnames: cx, loading} = this.props;
1478
+ return <div className={cx('Table-loading')}>{
1479
+ typeof loading === 'boolean' ? <Spinner></Spinner> : loading
1480
+ }</div>;
1481
+ }
1482
+
1483
+ renderTable() {
1484
+ const {
1485
+ scroll,
1486
+ footSummary,
1487
+ loading,
1488
+ showHeader,
1489
+ classnames: cx
1490
+ } = this.props;
1491
+
1492
+ // 设置了横向滚动轴 则table的table-layout为fixed
1493
+ const hasScrollX = scroll && scroll.x;
1494
+
1495
+ return (
1496
+ <div
1497
+ ref={this.contentDom}
1498
+ className={cx('Table-content')}
1499
+ style={hasScrollX ? {overflow: 'auto hidden'} : {}}>
1500
+ <table
1501
+ style={hasScrollX
1502
+ ? {width: scroll.x + 'px', tableLayout: 'fixed'}
1503
+ : {tableLayout: 'auto'}}
1504
+ className={cx('Table-table')}>
1505
+ {this.renderColGroup()}
1506
+ {showHeader ? this.renderTHead() : null}
1507
+ {!loading ? this.renderTBody() : null}
1508
+ {!loading && footSummary ? this.renderTFoot() : null}
1509
+ </table>
1510
+ {loading ? this.renderLoading() : null}
1511
+ </div>
1512
+ );
1513
+ }
1514
+
1515
+ renderScrollTableHeader() {
1516
+ const {
1517
+ scroll,
1518
+ headSummary,
1519
+ sticky,
1520
+ showHeader,
1521
+ classnames: cx
1522
+ } = this.props;
1523
+
1524
+ const style = {overflow: 'hidden'};
1525
+ if (!!sticky) {
1526
+ Object.assign(style, {top: 0});
1527
+ }
1528
+
1529
+ const tableStyle = {};
1530
+ if (scroll && (scroll.y || scroll.x)) {
1531
+ Object.assign(tableStyle, {
1532
+ width: (scroll && scroll.x ? (scroll.x + 'px') : '100%'),
1533
+ tableLayout: 'fixed'
1534
+ });
1535
+ }
1536
+
1537
+ return (
1538
+ <div
1539
+ ref={this.headerDom}
1540
+ className={cx('Table-header', {
1541
+ [cx('Table-sticky-holder')]: !!sticky
1542
+ })}
1543
+ style={style}>
1544
+ <table
1545
+ className={cx('Table-table')}
1546
+ style={tableStyle}>
1547
+ {this.renderColGroup(this.state.colWidths)}
1548
+ {showHeader ? this.renderTHead() : null}
1549
+ {headSummary ? <tbody>{this.renderSummaryRow(headSummary)}</tbody> : null}
1550
+ </table>
1551
+ </div>
1552
+ );
1553
+ }
1554
+
1555
+ renderScrollTableBody() {
1556
+ const {
1557
+ scroll,
1558
+ classnames: cx
1559
+ } = this.props;
1560
+
1561
+ const style = {};
1562
+ const tableStyle = {};
1563
+ if (scroll && (scroll.y || scroll.x)) {
1564
+ Object.assign(style, {
1565
+ overflow: 'auto scroll',
1566
+ maxHeight: scroll.y
1567
+ });
1568
+
1569
+ Object.assign(tableStyle, {
1570
+ width: scroll && scroll.x ? (scroll.x + 'px') : '100%',
1571
+ tableLayout: 'fixed'
1572
+ });
1573
+ }
1574
+
1575
+ return (
1576
+ <div
1577
+ ref={this.bodyDom}
1578
+ className={cx('Table-body')}
1579
+ style={style}>
1580
+ <table
1581
+ className={cx('Table-table')}
1582
+ style={tableStyle}>
1583
+ {this.renderColGroup()}
1584
+ {this.renderTBody()}
1585
+ </table>
1586
+ </div>
1587
+ )
1588
+ }
1589
+
1590
+ renderScrollTableFoot() {
1591
+ const {
1592
+ scroll,
1593
+ classnames: cx
1594
+ } = this.props;
1595
+
1596
+ return (
1597
+ <div
1598
+ ref={this.footDom}
1599
+ className={cx('Table-summary')}
1600
+ style={{overflow: 'hidden'}}>
1601
+ <table
1602
+ className={cx('Table-table')}
1603
+ style={{width: (scroll?.x + 'px') || '100%', tableLayout: 'fixed'}}>
1604
+ {this.renderTFoot()}
1605
+ </table>
1606
+ </div>
1607
+ );
1608
+ }
1609
+
1610
+ renderScrollTable() {
1611
+ const {
1612
+ footSummary,
1613
+ loading,
1614
+ classnames: cx
1615
+ } = this.props;
1616
+
1617
+ return (
1618
+ <div
1619
+ className={cx('Table-container')}>
1620
+ {this.renderScrollTableHeader()}
1621
+ {!loading ? this.renderScrollTableBody() : null}
1622
+ {!loading && footSummary ? this.renderScrollTableFoot() : null}
1623
+ {loading ? this.renderLoading() : null}
1624
+ </div>
1625
+ );
1626
+ }
1627
+
1628
+ render() {
1629
+ const {
1630
+ title,
1631
+ footer,
1632
+ className,
1633
+ scroll,
1634
+ size,
1635
+ bordered,
1636
+ resizable,
1637
+ columns,
1638
+ sticky,
1639
+ classnames: cx
1640
+ } = this.props;
1641
+
1642
+ // 过滤掉设置了breakpoint属性的列
1643
+ const filterColumns = columns.filter(item => !item.breakpoint ||
1644
+ !isBreakpoint(item.breakpoint));
1645
+
1646
+ this.thColumns = [];
1647
+ this.tdColumns = [];
1648
+ buildColumns(filterColumns, this.thColumns, this.tdColumns);
1649
+
1650
+ // 是否设置了纵向滚动
1651
+ const hasScrollY = scroll && scroll.y;
1652
+ // 是否设置了横向滚动
1653
+ const hasScrollX = scroll && scroll.x;
1654
+
1655
+ return (
1656
+ <div
1657
+ ref={this.tableDom}
1658
+ className={cx('Table-v2', className, {
1659
+ [cx('Table-scroll-horizontal')]: hasScrollX,
1660
+ [cx(`Table-${size}`)]: size,
1661
+ [cx('Table-bordered')]: bordered,
1662
+ [cx('Table-resizable')]: resizable
1663
+ })}>
1664
+ {title ? <div className={cx('Table-title')}>{
1665
+ typeof title === 'function' ? title() : title
1666
+ }</div> : null}
1667
+
1668
+ {hasScrollY || sticky ? this.renderScrollTable()
1669
+ : <div className={cx('Table-container')}>{this.renderTable()}</div>}
1670
+
1671
+ {footer ? <div className={cx('Table-footer')}>{
1672
+ typeof footer === 'function' ? footer() : footer
1673
+ }</div> : null}
1674
+ </div>
1675
+ );
1676
+ }
1677
+ }
1678
+
1679
+ export default themeable(
1680
+ localeable(Table)
1681
+ );