amis 1.9.1-beta.0 → 1.9.1-beta.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (278) hide show
  1. package/lib/RootRenderer.js +10 -2
  2. package/lib/RootRenderer.js.map +2 -2
  3. package/lib/Schema.d.ts +3 -2
  4. package/lib/Schema.js.map +1 -1
  5. package/lib/SchemaRenderer.js +6 -9
  6. package/lib/SchemaRenderer.js.map +2 -2
  7. package/lib/actions/CmptAction.js +4 -4
  8. package/lib/actions/CmptAction.js.map +2 -2
  9. package/lib/components/Button.d.ts +11 -10
  10. package/lib/components/Button.js +2 -2
  11. package/lib/components/Button.js.map +2 -2
  12. package/lib/components/CalendarMobile.d.ts +40 -40
  13. package/lib/components/Checkbox.js +1 -1
  14. package/lib/components/Checkbox.js.map +2 -2
  15. package/lib/components/ContextMenu.d.ts +4 -0
  16. package/lib/components/ContextMenu.js +23 -7
  17. package/lib/components/ContextMenu.js.map +2 -2
  18. package/lib/components/DatePicker.d.ts +40 -40
  19. package/lib/components/DateRangePicker.d.ts +40 -40
  20. package/lib/components/Form.d.ts +22 -0
  21. package/lib/components/Form.js +44 -0
  22. package/lib/components/Form.js.map +13 -0
  23. package/lib/components/FormField.d.ts +65 -0
  24. package/lib/components/FormField.js +48 -0
  25. package/lib/components/FormField.js.map +13 -0
  26. package/lib/components/InputBox.d.ts +10 -10
  27. package/lib/components/InputBox.js +4 -3
  28. package/lib/components/InputBox.js.map +2 -2
  29. package/lib/components/InputBoxWithSuggestion.d.ts +280 -0
  30. package/lib/components/InputBoxWithSuggestion.js +65 -0
  31. package/lib/components/InputBoxWithSuggestion.js.map +13 -0
  32. package/lib/components/ListGroup.d.ts +10 -10
  33. package/lib/components/PickerContainer.d.ts +4 -2
  34. package/lib/components/PickerContainer.js +28 -5
  35. package/lib/components/PickerContainer.js.map +2 -2
  36. package/lib/components/Radios.d.ts +10 -10
  37. package/lib/components/ResultBox.d.ts +40 -40
  38. package/lib/components/Select.d.ts +195 -202
  39. package/lib/components/Select.js +7 -3
  40. package/lib/components/Select.js.map +2 -2
  41. package/lib/components/Textarea.d.ts +568 -2
  42. package/lib/components/Textarea.js +129 -1
  43. package/lib/components/Textarea.js.map +2 -2
  44. package/lib/components/Toast.js +11 -9
  45. package/lib/components/Toast.js.map +2 -2
  46. package/lib/components/UserSelect.d.ts +500 -0
  47. package/lib/components/UserSelect.js +559 -0
  48. package/lib/components/UserSelect.js.map +13 -0
  49. package/lib/components/UserTabSelect.d.ts +320 -0
  50. package/lib/components/UserTabSelect.js +163 -0
  51. package/lib/components/UserTabSelect.js.map +13 -0
  52. package/lib/components/WithRemoteConfig.d.ts +7 -0
  53. package/lib/components/WithRemoteConfig.js +22 -13
  54. package/lib/components/WithRemoteConfig.js.map +2 -2
  55. package/lib/components/calendar/DaysView.d.ts +26 -1
  56. package/lib/components/calendar/DaysView.js +60 -19
  57. package/lib/components/calendar/DaysView.js.map +2 -2
  58. package/lib/components/calendar/TimeView.d.ts +1 -1
  59. package/lib/components/calendar/TimeView.js +10 -3
  60. package/lib/components/calendar/TimeView.js.map +2 -2
  61. package/lib/components/formula/Picker.js +4 -4
  62. package/lib/components/formula/Picker.js.map +2 -2
  63. package/lib/components/icons.d.ts +7 -1
  64. package/lib/components/icons.js +17 -1
  65. package/lib/components/icons.js.map +2 -2
  66. package/lib/components/index.d.ts +2 -1
  67. package/lib/components/index.js +3 -1
  68. package/lib/components/index.js.map +2 -2
  69. package/lib/components/json-schema/Array.d.ts +3 -0
  70. package/lib/components/json-schema/Array.js +125 -0
  71. package/lib/components/json-schema/Array.js.map +13 -0
  72. package/lib/components/json-schema/Item.d.ts +3 -0
  73. package/lib/components/json-schema/Item.js +34 -0
  74. package/lib/components/json-schema/Item.js.map +13 -0
  75. package/lib/components/json-schema/Object.d.ts +3 -0
  76. package/lib/components/json-schema/Object.js +178 -0
  77. package/lib/components/json-schema/Object.js.map +13 -0
  78. package/lib/components/json-schema/index.d.ts +279 -0
  79. package/lib/components/json-schema/index.js +16 -0
  80. package/lib/components/json-schema/index.js.map +13 -0
  81. package/lib/components/schema-editor/Array.js +2 -2
  82. package/lib/components/schema-editor/Array.js.map +2 -2
  83. package/lib/components/schema-editor/Common.d.ts +2 -0
  84. package/lib/components/schema-editor/Common.js +39 -3
  85. package/lib/components/schema-editor/Common.js.map +2 -2
  86. package/lib/components/schema-editor/Object.js +2 -2
  87. package/lib/components/schema-editor/Object.js.map +2 -2
  88. package/lib/components/schema-editor/index.d.ts +45 -41
  89. package/lib/components/schema-editor/index.js +5 -5
  90. package/lib/components/schema-editor/index.js.map +2 -2
  91. package/lib/components/table/ItemActionsWrapper.d.ts +10 -0
  92. package/lib/components/table/ItemActionsWrapper.js +25 -0
  93. package/lib/components/table/ItemActionsWrapper.js.map +13 -0
  94. package/lib/components/table/index.d.ts +48 -41
  95. package/lib/components/table/index.js +46 -18
  96. package/lib/components/table/index.js.map +2 -2
  97. package/lib/helper.css +125 -124
  98. package/lib/helper.css.map +1 -1
  99. package/lib/hooks/use-validation-resolver.d.ts +1 -0
  100. package/lib/hooks/use-validation-resolver.js +49 -0
  101. package/lib/hooks/use-validation-resolver.js.map +13 -0
  102. package/lib/icons/department.js +17 -0
  103. package/lib/icons/menu.js +9 -0
  104. package/lib/icons/post.js +15 -0
  105. package/lib/icons/role.js +14 -0
  106. package/lib/icons/user-remove.js +12 -0
  107. package/lib/index.d.ts +2 -0
  108. package/lib/index.js +3 -1
  109. package/lib/index.js.map +2 -2
  110. package/lib/locale/de-DE.js +11 -1
  111. package/lib/locale/de-DE.js.map +2 -2
  112. package/lib/locale/en-US.js +12 -1
  113. package/lib/locale/en-US.js.map +2 -2
  114. package/lib/locale/zh-CN.js +14 -3
  115. package/lib/locale/zh-CN.js.map +2 -2
  116. package/lib/renderers/Action.js +25 -11
  117. package/lib/renderers/Action.js.map +2 -2
  118. package/lib/renderers/CRUD.js +5 -1
  119. package/lib/renderers/CRUD.js.map +2 -2
  120. package/lib/renderers/Dialog.js +9 -3
  121. package/lib/renderers/Dialog.js.map +2 -2
  122. package/lib/renderers/Drawer.js +5 -1
  123. package/lib/renderers/Drawer.js.map +2 -2
  124. package/lib/renderers/Form/InputDate.d.ts +2 -2
  125. package/lib/renderers/Form/InputDate.js.map +2 -2
  126. package/lib/renderers/Form/JSONSchema.d.ts +23 -0
  127. package/lib/renderers/Form/JSONSchema.js +44 -0
  128. package/lib/renderers/Form/JSONSchema.js.map +13 -0
  129. package/lib/renderers/Form/JSONSchemaEditor.d.ts +2 -3
  130. package/lib/renderers/Form/JSONSchemaEditor.js +9 -24
  131. package/lib/renderers/Form/JSONSchemaEditor.js.map +2 -2
  132. package/lib/renderers/Form/Options.js +11 -5
  133. package/lib/renderers/Form/Options.js.map +2 -2
  134. package/lib/renderers/Form/Textarea.d.ts +1 -8
  135. package/lib/renderers/Form/Textarea.js +11 -75
  136. package/lib/renderers/Form/Textarea.js.map +2 -2
  137. package/lib/renderers/Form/UserSelect.d.ts +54 -0
  138. package/lib/renderers/Form/UserSelect.js +197 -0
  139. package/lib/renderers/Form/UserSelect.js.map +13 -0
  140. package/lib/renderers/Form/index.d.ts +1 -1
  141. package/lib/renderers/Form/index.js +88 -42
  142. package/lib/renderers/Form/index.js.map +2 -2
  143. package/lib/renderers/Form/wrapControl.js.map +2 -2
  144. package/lib/renderers/Log.d.ts +28 -0
  145. package/lib/renderers/Log.js +110 -20
  146. package/lib/renderers/Log.js.map +2 -2
  147. package/lib/renderers/Page.js +5 -1
  148. package/lib/renderers/Page.js.map +2 -2
  149. package/lib/renderers/Service.js +5 -1
  150. package/lib/renderers/Service.js.map +2 -2
  151. package/lib/renderers/Table-v2/index.d.ts +14 -2
  152. package/lib/renderers/Table-v2/index.js +33 -3
  153. package/lib/renderers/Table-v2/index.js.map +2 -2
  154. package/lib/renderers/Wizard.js +37 -14
  155. package/lib/renderers/Wizard.js.map +2 -2
  156. package/lib/store/form.js +65 -45
  157. package/lib/store/form.js.map +2 -2
  158. package/lib/themes/ang-ie11.css +576 -24
  159. package/lib/themes/ang.css +553 -12
  160. package/lib/themes/ang.css.map +1 -1
  161. package/lib/themes/antd-ie11.css +576 -24
  162. package/lib/themes/antd.css +553 -12
  163. package/lib/themes/antd.css.map +1 -1
  164. package/lib/themes/cxd-ie11.css +576 -24
  165. package/lib/themes/cxd.css +553 -12
  166. package/lib/themes/cxd.css.map +1 -1
  167. package/lib/themes/dark-ie11.css +576 -24
  168. package/lib/themes/dark.css +553 -12
  169. package/lib/themes/dark.css.map +1 -1
  170. package/lib/themes/default-ie11.css +576 -24
  171. package/lib/themes/default.css +553 -12
  172. package/lib/themes/default.css.map +1 -1
  173. package/lib/utils/api.js +1 -1
  174. package/lib/utils/api.js.map +2 -2
  175. package/lib/utils/renderer-event.js.map +2 -2
  176. package/package.json +2 -1
  177. package/schema.json +552 -5
  178. package/scss/_properties.scss +20 -8
  179. package/scss/components/_input-box.scss +22 -1
  180. package/scss/components/_json-schema.scss +124 -0
  181. package/scss/components/_log.scss +37 -5
  182. package/scss/components/form/_date-range.scss +1 -0
  183. package/scss/components/form/_select.scss +9 -0
  184. package/scss/components/form/_transfer.scss +19 -3
  185. package/scss/components/form/_user-select.scss +422 -0
  186. package/scss/helper/background/_background-color.scss +125 -124
  187. package/scss/themes/_common.scss +2 -0
  188. package/sdk/ang-ie11.css +670 -24
  189. package/sdk/ang.css +647 -12
  190. package/sdk/antd-ie11.css +670 -24
  191. package/sdk/antd.css +647 -12
  192. package/sdk/barcode.js +51 -51
  193. package/sdk/charts.js +14 -14
  194. package/sdk/codemirror.js +7 -7
  195. package/sdk/color-picker.js +65 -65
  196. package/sdk/cropperjs.js +2 -2
  197. package/sdk/cxd-ie11.css +670 -24
  198. package/sdk/cxd.css +647 -12
  199. package/sdk/dark-ie11.css +670 -24
  200. package/sdk/dark.css +647 -12
  201. package/sdk/exceljs.js +1 -1
  202. package/sdk/helper.css +125 -124
  203. package/sdk/helper.css.map +1 -1
  204. package/sdk/locale/de-DE.js +11 -1
  205. package/sdk/markdown.js +69 -69
  206. package/sdk/papaparse.js +1 -1
  207. package/sdk/renderers/Form/CityDB.js +1 -1
  208. package/sdk/rest.js +16 -16
  209. package/sdk/rich-text.js +62 -62
  210. package/sdk/sdk-ie11.css +670 -24
  211. package/sdk/sdk.css +647 -12
  212. package/sdk/sdk.js +1653 -1637
  213. package/sdk/thirds/hls.js/hls.js +1 -1
  214. package/sdk/thirds/mpegts.js/mpegts.js +1 -1
  215. package/sdk/tinymce.js +57 -57
  216. package/src/RootRenderer.tsx +27 -15
  217. package/src/Schema.ts +5 -1
  218. package/src/SchemaRenderer.tsx +1 -4
  219. package/src/actions/CmptAction.ts +4 -4
  220. package/src/components/Button.tsx +3 -0
  221. package/src/components/Checkbox.tsx +2 -1
  222. package/src/components/ContextMenu.tsx +25 -7
  223. package/src/components/Form.tsx +70 -0
  224. package/src/components/FormField.tsx +127 -0
  225. package/src/components/InputBox.tsx +4 -1
  226. package/src/components/InputBoxWithSuggestion.tsx +113 -0
  227. package/src/components/PickerContainer.tsx +20 -5
  228. package/src/components/Select.tsx +18 -10
  229. package/src/components/Textarea.tsx +234 -2
  230. package/src/components/Toast.tsx +19 -18
  231. package/src/components/UserSelect.tsx +850 -0
  232. package/src/components/UserTabSelect.tsx +261 -0
  233. package/src/components/WithRemoteConfig.tsx +35 -11
  234. package/src/components/calendar/DaysView.tsx +117 -49
  235. package/src/components/calendar/TimeView.tsx +11 -6
  236. package/src/components/formula/Picker.tsx +2 -1
  237. package/src/components/icons.tsx +17 -1
  238. package/src/components/index.tsx +3 -1
  239. package/src/components/json-schema/Array.tsx +216 -0
  240. package/src/components/json-schema/Item.tsx +47 -0
  241. package/src/components/json-schema/Object.tsx +339 -0
  242. package/src/components/json-schema/index.tsx +44 -0
  243. package/src/components/schema-editor/Array.tsx +3 -1
  244. package/src/components/schema-editor/Common.tsx +61 -4
  245. package/src/components/schema-editor/Object.tsx +3 -1
  246. package/src/components/schema-editor/index.tsx +12 -5
  247. package/src/components/table/ItemActionsWrapper.tsx +32 -0
  248. package/src/components/table/index.tsx +115 -58
  249. package/src/hooks/use-validation-resolver.ts +45 -0
  250. package/src/icons/department.svg +17 -0
  251. package/src/icons/menu.svg +2 -0
  252. package/src/icons/post.svg +15 -0
  253. package/src/icons/role.svg +14 -0
  254. package/src/icons/user-remove.svg +12 -0
  255. package/src/index.tsx +2 -0
  256. package/src/locale/de-DE.ts +11 -1
  257. package/src/locale/en-US.ts +12 -1
  258. package/src/locale/zh-CN.ts +14 -3
  259. package/src/renderers/Action.tsx +10 -9
  260. package/src/renderers/CRUD.tsx +5 -1
  261. package/src/renderers/Dialog.tsx +9 -3
  262. package/src/renderers/Drawer.tsx +5 -1
  263. package/src/renderers/Form/InputDate.tsx +9 -4
  264. package/src/renderers/Form/JSONSchema.tsx +56 -0
  265. package/src/renderers/Form/JSONSchemaEditor.tsx +8 -27
  266. package/src/renderers/Form/Options.tsx +17 -7
  267. package/src/renderers/Form/Textarea.tsx +7 -117
  268. package/src/renderers/Form/UserSelect.tsx +263 -0
  269. package/src/renderers/Form/index.tsx +28 -18
  270. package/src/renderers/Form/wrapControl.tsx +0 -1
  271. package/src/renderers/Log.tsx +213 -19
  272. package/src/renderers/Page.tsx +6 -1
  273. package/src/renderers/Service.tsx +5 -1
  274. package/src/renderers/Table-v2/index.tsx +65 -2
  275. package/src/renderers/Wizard.tsx +24 -10
  276. package/src/store/form.ts +24 -17
  277. package/src/utils/api.ts +1 -1
  278. package/src/utils/renderer-event.ts +0 -2
@@ -0,0 +1,850 @@
1
+ /**
2
+ * @file 移动端人员、部门、角色、岗位选择
3
+ * @author fex
4
+ */
5
+
6
+ import React from 'react';
7
+ import {themeable, ThemeProps} from '../theme';
8
+ import {LocaleProps, localeable} from '../locale';
9
+ import {ResultBox} from '../components';
10
+ import {Option} from '../renderers/Form/Options';
11
+ import Sortable from 'sortablejs';
12
+ import PopUp from '../components/PopUp';
13
+ import InputBox from '../components/InputBox';
14
+ import {Icon} from '../components/icons';
15
+ import debounce from 'lodash/debounce';
16
+ import {autobind, findTree} from '../utils/helper';
17
+ import Checkbox from '../components/Checkbox';
18
+ import {optionValueCompare, value2array} from './Select';
19
+ import Spinner from '../components/Spinner';
20
+ import flatten from 'lodash/flatten';
21
+ import {findDOMNode} from 'react-dom';
22
+ import {Api, PlainObject} from '../types';
23
+ import {Payload} from 'echarts';
24
+
25
+ export interface UserSelectProps extends ThemeProps, LocaleProps {
26
+ showNav?: boolean;
27
+ navTitle?: string;
28
+ options: Array<any>;
29
+ value?: Array<Option> | Option | string;
30
+ selection?: Array<Option>;
31
+ valueField?: string;
32
+ labelField?: string;
33
+ multi?: boolean;
34
+ multiple?: boolean;
35
+ isDep?: boolean;
36
+ isRef?: boolean;
37
+ searchable?: boolean;
38
+ // 选项卡模式开关
39
+ showResultBox?: boolean;
40
+ placeholder?: string;
41
+ searchPlaceholder?: string;
42
+ controlled?: boolean;
43
+ fetcher?: (
44
+ api: Api,
45
+ data?: any,
46
+ options?: PlainObject | undefined
47
+ ) => Promise<Payload>;
48
+ onSearch?: (
49
+ term: string,
50
+ cancelExecutor: Function
51
+ ) => Promise<any[]> | undefined;
52
+ deferLoad: (
53
+ data?: PlainObject,
54
+ isRef?: boolean,
55
+ param?: PlainObject
56
+ ) => Promise<Option[]>;
57
+ onChange: (value: Array<Option> | Option, isReplace?: boolean) => void;
58
+ }
59
+
60
+ export interface UserSelectState {
61
+ isOpened: boolean;
62
+ isSearch: boolean;
63
+ isSelectOpened: boolean;
64
+ inputValue: string;
65
+ breadList: Array<any>;
66
+ options: Array<Option>;
67
+ tempSelection: Array<Option>;
68
+ selection: Array<Option>;
69
+ searchList: Array<Option>;
70
+ searchLoading: boolean;
71
+ isEdit: boolean;
72
+ }
73
+
74
+ export class UserSelect extends React.Component<
75
+ UserSelectProps,
76
+ UserSelectState
77
+ > {
78
+ cancelSearch?: Function;
79
+ sortable?: Sortable;
80
+ unmounted = false;
81
+
82
+ constructor(props: UserSelectProps) {
83
+ super(props);
84
+ this.state = {
85
+ isOpened: false,
86
+ isSelectOpened: false,
87
+ inputValue: '',
88
+ options: this.props.options || [],
89
+ breadList: [],
90
+ searchList: [],
91
+ tempSelection: [],
92
+ selection: props.selection || [],
93
+ isSearch: false,
94
+ searchLoading: false,
95
+ isEdit: false
96
+ };
97
+ }
98
+
99
+ static defaultProps = {
100
+ showResultBox: true,
101
+ labelField: 'label',
102
+ valueField: 'value'
103
+ };
104
+
105
+ componentDidMount() {}
106
+
107
+ componentDidUpdate(prevProps: UserSelectProps) {
108
+ let {options, value} = this.props;
109
+ if (prevProps.options !== options) {
110
+ if (
111
+ options &&
112
+ options.length === 1 &&
113
+ options[0].leftOptions &&
114
+ Array.isArray(options[0].children)
115
+ ) {
116
+ let leftOptions = options[0].leftOptions as Option[];
117
+ this.setState({
118
+ options: leftOptions
119
+ });
120
+ } else {
121
+ // 部门选择
122
+ this.setState({
123
+ options: options
124
+ });
125
+ }
126
+ }
127
+ if (
128
+ JSON.stringify(value) !== JSON.stringify(prevProps.value) ||
129
+ JSON.stringify(options) !== JSON.stringify(prevProps.options)
130
+ ) {
131
+ const selection: Array<Option> = value2array(value, this.props);
132
+ this.setState({
133
+ selection
134
+ });
135
+ }
136
+ }
137
+
138
+ componentWillUnmount() {
139
+ this.unmounted = true;
140
+ }
141
+
142
+ @autobind
143
+ onClose() {
144
+ this.setState({
145
+ isOpened: false,
146
+ isSearch: false,
147
+ inputValue: '',
148
+ searchList: [],
149
+ searchLoading: false
150
+ });
151
+ }
152
+
153
+ @autobind
154
+ handleSearch(text: string) {
155
+ if (text) {
156
+ this.setState(
157
+ {
158
+ isSearch: true,
159
+ searchLoading: true,
160
+ inputValue: text
161
+ },
162
+ () => {
163
+ // 如果有取消搜索,先取消掉。
164
+ this.cancelSearch && this.cancelSearch();
165
+ this.lazySearch(text);
166
+ }
167
+ );
168
+ } else {
169
+ this.handleSeachCancel();
170
+ }
171
+ }
172
+
173
+ @autobind
174
+ handleSeachCancel() {
175
+ this.setState({
176
+ isSearch: false,
177
+ searchLoading: false,
178
+ inputValue: ''
179
+ });
180
+ }
181
+
182
+ lazySearch = debounce(
183
+ (text: string) => {
184
+ (async (text: string) => {
185
+ const onSearch = this.props.onSearch!;
186
+ let result = await onSearch(
187
+ text,
188
+ (cancelExecutor: () => void) => (this.cancelSearch = cancelExecutor)
189
+ );
190
+ if (this.unmounted) {
191
+ return;
192
+ }
193
+
194
+ if (!Array.isArray(result)) {
195
+ throw new Error('onSearch 需要返回数组');
196
+ }
197
+
198
+ this.setState({
199
+ searchList: result,
200
+ searchLoading: false
201
+ });
202
+ })(text).catch(e => {
203
+ this.setState({searchLoading: false});
204
+ console.error(e);
205
+ });
206
+ },
207
+ 250,
208
+ {
209
+ trailing: true,
210
+ leading: false
211
+ }
212
+ );
213
+
214
+ swapSelectPosition(oldIndex: number, newIndex: number) {
215
+ const tempSelection = this.state.tempSelection;
216
+ tempSelection.splice(newIndex, 0, tempSelection.splice(oldIndex, 1)[0]);
217
+ this.setState({tempSelection});
218
+ }
219
+
220
+ @autobind
221
+ dragRef(ref: any) {
222
+ if (ref) {
223
+ this.initDragging();
224
+ }
225
+ }
226
+
227
+ initDragging() {
228
+ const ns = this.props.classPrefix;
229
+ this.sortable = new Sortable(
230
+ document.querySelector(`.${ns}UserSelect-checkContent`) as HTMLElement,
231
+ {
232
+ group: `UserSelect-checkContent`,
233
+ animation: 150,
234
+ handle: `.${ns}UserSelect-dragBar`,
235
+ ghostClass: `${ns}UserSelect--dragging`,
236
+ onEnd: (e: any) => {
237
+ if (!this.state.isEdit || e.newIndex === e.oldIndex) {
238
+ return;
239
+ }
240
+ const parent = e.to as HTMLElement;
241
+ if (e.oldIndex < parent.childNodes.length - 1) {
242
+ parent.insertBefore(e.item, parent.childNodes[e.oldIndex]);
243
+ } else {
244
+ parent.appendChild(e.item);
245
+ }
246
+ this.swapSelectPosition(e.oldIndex, e.newIndex);
247
+ }
248
+ }
249
+ );
250
+ }
251
+
252
+ destroyDragging() {
253
+ this.sortable && this.sortable.destroy();
254
+ }
255
+
256
+ @autobind
257
+ onOpen() {
258
+ const {selection} = this.state;
259
+ this.setState({
260
+ isOpened: true,
261
+ tempSelection: selection.slice()
262
+ });
263
+ }
264
+
265
+ @autobind
266
+ handleBack() {
267
+ this.setState({
268
+ isOpened: false,
269
+ inputValue: '',
270
+ isSearch: false,
271
+ searchList: [],
272
+ breadList: []
273
+ });
274
+ }
275
+
276
+ @autobind
277
+ async handleExpand(option: Option) {
278
+ const {deferLoad, isRef, isDep} = this.props;
279
+ if (!option.isLoaded || (!isRef && isDep && !option.children?.length)) {
280
+ option.isLoaded = true;
281
+ let deferParam = option.deferApi ? {deferApi: option.deferApi} : {};
282
+ if (isRef) {
283
+ // 部门、人员一起加载
284
+ const res = await Promise.all([
285
+ deferLoad(option, false, deferParam),
286
+ deferLoad({...option, ref: option.value}, true, deferParam)
287
+ ]);
288
+ option.children = flatten(res);
289
+ } else {
290
+ // 只加载部门
291
+ const res = await deferLoad(option, false, deferParam);
292
+ option.children = res || [];
293
+ }
294
+ }
295
+
296
+ const breadList = this.state.breadList;
297
+ breadList.push(option);
298
+ this.setState({
299
+ breadList
300
+ });
301
+ }
302
+
303
+ @autobind
304
+ handleSelectChange(option: Option, isReplace?: boolean) {
305
+ const {multiple, onChange, valueField = 'value', controlled} = this.props;
306
+ if (controlled) {
307
+ onChange(option);
308
+ return;
309
+ }
310
+ let selection = this.state.selection.slice();
311
+ // 直接替换的option 肯定是数组
312
+ if (isReplace) {
313
+ selection = option as Option[];
314
+ } else {
315
+ let selectionVals = selection.map((option: Option) => option[valueField]);
316
+ let pos = selectionVals.indexOf(option[valueField]);
317
+ if (pos !== -1) {
318
+ selection.splice(selection.indexOf(option), 1);
319
+ } else {
320
+ if (multiple) {
321
+ selection.push(option);
322
+ } else {
323
+ selection = [option];
324
+ }
325
+ }
326
+ }
327
+
328
+ onChange(multiple ? selection : selection?.[0]);
329
+ this.setState({
330
+ selection
331
+ });
332
+ return false;
333
+ }
334
+
335
+ @autobind
336
+ onDelete(option: Option, isTemp: boolean = false) {
337
+ const {valueField = 'value'} = this.props;
338
+ const {tempSelection, selection} = this.state;
339
+ let _selection = isTemp ? tempSelection : selection;
340
+ _selection = _selection.filter(
341
+ (item: Option) => item[valueField] !== option[valueField]
342
+ );
343
+ if (isTemp) {
344
+ this.setState({tempSelection: _selection});
345
+ } else {
346
+ this.setState({selection: _selection});
347
+ }
348
+ }
349
+
350
+ @autobind
351
+ handleBreadChange(option: Option, index: number) {
352
+ const breadList = this.state.breadList.slice(0, index);
353
+ this.setState({
354
+ breadList
355
+ });
356
+ }
357
+
358
+ @autobind
359
+ handleEdit() {
360
+ const {multiple, onChange, controlled} = this.props;
361
+ const {isEdit, tempSelection} = this.state;
362
+ if (isEdit) {
363
+ if (controlled) {
364
+ onChange(multiple ? tempSelection : tempSelection?.[0], true);
365
+ this.setState({
366
+ isSelectOpened: false,
367
+ isEdit: false
368
+ });
369
+ return;
370
+ } else {
371
+ this.setState({
372
+ isSelectOpened: false,
373
+ isEdit: false,
374
+ selection: tempSelection
375
+ });
376
+ }
377
+ } else {
378
+ this.setState({
379
+ isEdit: true
380
+ });
381
+ }
382
+ }
383
+
384
+ renderIcon(option: Option, isSelect?: boolean) {
385
+ const {labelField = 'label', classnames: cx, isRef} = this.props;
386
+ const {isSearch} = this.state;
387
+
388
+ if (!option.icon) {
389
+ if (option.isRef || ((isSearch || isSelect) && isRef)) {
390
+ return (
391
+ <span className={cx('UserSelect-text-userPic')}>
392
+ {option[labelField].slice(0, 1)}
393
+ </span>
394
+ );
395
+ } else {
396
+ // 没有icon默认返回部门图标
397
+ return (
398
+ <span className={cx('icon', 'UserSelect-icon-box', 'department')}>
399
+ <Icon icon="department" className="icon" />
400
+ </span>
401
+ );
402
+ }
403
+ }
404
+ // 支持角色、岗位等图标配置
405
+ let IconHtml;
406
+ switch (option.icon) {
407
+ case 'user-default-department':
408
+ IconHtml = (
409
+ <span className={cx('icon', 'UserSelect-icon-box', 'department')}>
410
+ <Icon icon="department" className="icon" />
411
+ </span>
412
+ );
413
+ break;
414
+ case 'user-default-role':
415
+ IconHtml = (
416
+ <span className={cx('icon', 'UserSelect-icon-box', 'role')}>
417
+ <Icon icon="role" className="icon" />
418
+ </span>
419
+ );
420
+ break;
421
+ case 'user-default-post':
422
+ IconHtml = (
423
+ <span className={cx('icon', 'UserSelect-icon-box', 'post')}>
424
+ <Icon icon="post" className="icon" />
425
+ </span>
426
+ );
427
+ break;
428
+ case '':
429
+ IconHtml = (
430
+ <span className={cx('UserSelect-text-userPic')}>
431
+ {option[labelField].slice(0, 1)}
432
+ </span>
433
+ );
434
+ break;
435
+ default:
436
+ IconHtml = (
437
+ <img src={option.icon} className={cx('UserSelect-userPic')} />
438
+ );
439
+ }
440
+ return IconHtml;
441
+ }
442
+
443
+ renderList(
444
+ options: Array<object> = [],
445
+ key?: number | string,
446
+ isSearch?: boolean
447
+ ) {
448
+ const {
449
+ classnames: cx,
450
+ valueField = 'value',
451
+ labelField = 'label',
452
+ isDep,
453
+ isRef,
454
+ translate: __,
455
+ controlled
456
+ } = this.props;
457
+
458
+ let selection = controlled
459
+ ? this.props.selection || []
460
+ : this.state.selection;
461
+ const checkValues = selection.map((item: Option) => item[valueField]);
462
+
463
+ return options.length ? (
464
+ <div className={cx('UserSelect-memberList-box')} key={key}>
465
+ <ul className={cx(`UserSelect-memberList`)} key={key}>
466
+ {options.map((option: Option, index: number) => {
467
+ const hasChildren =
468
+ (isRef && !option.isRef) ||
469
+ (isDep && (option.defer || option.children?.length));
470
+ const checkVisible =
471
+ (isDep && isRef) ||
472
+ (isRef && option.isRef) ||
473
+ (isDep && !isRef) ||
474
+ isSearch;
475
+
476
+ const userIcon = this.renderIcon(option);
477
+
478
+ return (
479
+ <li key={index}>
480
+ {checkVisible ? (
481
+ <Checkbox
482
+ size="sm"
483
+ checked={checkValues.includes(option[valueField])}
484
+ label={''}
485
+ onChange={() => this.handleSelectChange(option)}
486
+ />
487
+ ) : null}
488
+ <span
489
+ className={cx('UserSelect-memberName')}
490
+ onClick={() =>
491
+ checkVisible
492
+ ? this.handleSelectChange(option)
493
+ : hasChildren && this.handleExpand(option)
494
+ }
495
+ >
496
+ {userIcon ? (
497
+ <span className={cx('UserSelect-userPic-box')}>
498
+ {userIcon}
499
+ </span>
500
+ ) : null}
501
+
502
+ <span className={cx('UserSelect-label')}>
503
+ {option[labelField]}
504
+ </span>
505
+ </span>
506
+
507
+ {!isSearch && hasChildren ? (
508
+ <span
509
+ className={cx(`UserSelect-more`)}
510
+ onClick={() => this.handleExpand(option)}
511
+ >
512
+ <Icon icon="caret" className="icon" />
513
+ </span>
514
+ ) : null}
515
+ </li>
516
+ );
517
+ })}
518
+ </ul>
519
+ </div>
520
+ ) : (
521
+ <div className={cx(`UserSelect-noRecord`)}>
522
+ {__('placeholder.noOption')}~
523
+ </div>
524
+ );
525
+ }
526
+
527
+ renderselectList(options: Array<object> = []) {
528
+ const {
529
+ classnames: cx,
530
+ labelField = 'label',
531
+ valueField = 'value',
532
+ translate: __
533
+ } = this.props;
534
+ const {isEdit} = this.state;
535
+
536
+ return options.length ? (
537
+ <div className={cx('UserSelect-selection-wrap')}>
538
+ <ul
539
+ className={cx(`UserSelect-selection`, `UserSelect-checkContent`)}
540
+ ref={this.dragRef}
541
+ >
542
+ {options.map((option: Option, index: number) => {
543
+ const userIcon = this.renderIcon(option, true);
544
+ const options = this.state.options;
545
+ const originOption = findTree(
546
+ options,
547
+ (item: Option) => item[valueField] === option[valueField]
548
+ );
549
+ return (
550
+ <li key={index}>
551
+ {isEdit ? (
552
+ <span
553
+ className={cx(`UserSelect-del`)}
554
+ onClick={() => this.onDelete(option, true)}
555
+ >
556
+ <Icon icon="user-remove" className="icon" />
557
+ </span>
558
+ ) : null}
559
+
560
+ <span className={cx(`UserSelect-memberName`)}>
561
+ {userIcon ? (
562
+ <span className={cx('UserSelect-userPic-box')}>
563
+ {userIcon}
564
+ </span>
565
+ ) : null}
566
+
567
+ <span className={cx('UserSelect-label')}>
568
+ {originOption
569
+ ? originOption[labelField]
570
+ : option[labelField]}
571
+ </span>
572
+ </span>
573
+ {isEdit ? (
574
+ <a className={cx('UserSelect-dragBar')}>
575
+ <Icon icon="drag-bar" className={cx('icon')} />
576
+ </a>
577
+ ) : null}
578
+ </li>
579
+ );
580
+ })}
581
+ </ul>
582
+ </div>
583
+ ) : (
584
+ <div className={cx(`UserSelect-noRecord`)}>
585
+ {__('placeholder.noOption')}~
586
+ </div>
587
+ );
588
+ }
589
+
590
+ renderContent() {
591
+ let {
592
+ navTitle,
593
+ showNav,
594
+ searchable,
595
+ searchPlaceholder,
596
+ controlled,
597
+ labelField = 'label',
598
+ valueField = 'value',
599
+ classnames: cx,
600
+ translate: __
601
+ } = this.props;
602
+
603
+ const {breadList, options, isSearch, searchList, searchLoading} =
604
+ this.state;
605
+ let selection = controlled
606
+ ? this.props.selection || []
607
+ : this.state.selection;
608
+
609
+ return (
610
+ <div className={cx(`UserSelect-wrap`)}>
611
+ {showNav ? (
612
+ <div className={cx('UserSelect-navbar')}>
613
+ <span className="left-arrow-box" onClick={this.handleBack}>
614
+ <Icon icon="left-arrow" className="icon" />
615
+ </span>
616
+ <div className={cx('UserSelect-navbar-title')}>{navTitle}</div>
617
+ </div>
618
+ ) : null}
619
+
620
+ {/* 搜索 */}
621
+ {searchable ? (
622
+ <div className={cx('UserSelect-searchBox')}>
623
+ <InputBox
624
+ className={cx(`UserSelect-search`)}
625
+ value={this.state.inputValue}
626
+ onChange={this.handleSearch}
627
+ placeholder={searchPlaceholder}
628
+ clearable={false}
629
+ >
630
+ {this.state.isSearch ? (
631
+ <a onClick={this.handleSeachCancel}>
632
+ <Icon icon="close" className="icon" />
633
+ </a>
634
+ ) : (
635
+ <Icon icon="search" className="icon" />
636
+ )}
637
+ </InputBox>
638
+ </div>
639
+ ) : null}
640
+
641
+ {/* 面包屑 */}
642
+ {breadList.length ? (
643
+ <div className={cx('UserSelect-breadcrumb')}>
644
+ {breadList
645
+ .map<React.ReactNode>((item, index) => (
646
+ <span
647
+ className={cx('UserSelect-breadcrumb-item')}
648
+ key={index}
649
+ onClick={() => this.handleBreadChange(item, index)}
650
+ >
651
+ {item[labelField]}
652
+ </span>
653
+ ))
654
+ .reduce((prev, curr, index) => [
655
+ prev,
656
+ <Icon
657
+ icon="caret"
658
+ className={cx('UserSelect-breadcrumb-separator', 'icon')}
659
+ key={`separator-${index}`}
660
+ />,
661
+ curr
662
+ ])}
663
+ </div>
664
+ ) : null}
665
+
666
+ {selection?.length ? (
667
+ <div className={cx(`UserSelect-resultBox`)}>
668
+ <ul className={cx(`UserSelect-selectList`)}>
669
+ {selection.map((item: Option, index) => {
670
+ const originOption = findTree(
671
+ options,
672
+ (op: Option) => op[valueField] === item[valueField]
673
+ );
674
+ return (
675
+ <li key={index} className={cx('UserSelect-selectList-item')}>
676
+ <span>
677
+ {originOption
678
+ ? originOption[labelField]
679
+ : item[labelField]}
680
+ </span>
681
+ <span
682
+ className={cx('UserSelect-selectList-item-closeBox')}
683
+ onClick={() => this.onDelete(item)}
684
+ >
685
+ <Icon icon="close" className="icon" />
686
+ </span>
687
+ </li>
688
+ );
689
+ })}
690
+ </ul>
691
+ <span
692
+ className={cx('UserSelect-selectSort-box')}
693
+ onClick={() =>
694
+ this.setState({
695
+ isSelectOpened: true,
696
+ tempSelection: selection.slice()
697
+ })
698
+ }
699
+ >
700
+ <Icon
701
+ icon="menu"
702
+ className={cx('UserSelect-selectSort', 'icon')}
703
+ />
704
+ </span>
705
+ </div>
706
+ ) : null}
707
+
708
+ {isSearch ? (
709
+ searchLoading ? (
710
+ <div className={cx(`UserSelect-searchLoadingBox`)}>
711
+ <Spinner />
712
+ </div>
713
+ ) : (
714
+ <div className={cx('UserSelect-searchResult')}>
715
+ {this.renderList(searchList, -1, true)}
716
+ </div>
717
+ )
718
+ ) : (
719
+ <div className={cx(`UserSelect-contentBox`)}>
720
+ <div
721
+ className={cx(`UserSelect-scroll`)}
722
+ style={{
723
+ width: 100 * (breadList.length + 1) + 'vw',
724
+ left: -breadList.length * 100 + 'vw'
725
+ }}
726
+ >
727
+ {this.renderList(options)}
728
+
729
+ {breadList.map((option: Option, index: number) => {
730
+ const treeOption = findTree(
731
+ options,
732
+ optionValueCompare(option[valueField], valueField || 'value')
733
+ ) as Option;
734
+ const children = treeOption.children;
735
+ const hasChildren = Array.isArray(children) && children;
736
+
737
+ return hasChildren ? (
738
+ this.renderList(children, option[valueField])
739
+ ) : (
740
+ <div className={cx(`UserSelect-spinnerBox`)} key={index}>
741
+ <Spinner />
742
+ </div>
743
+ );
744
+ })}
745
+ </div>
746
+ </div>
747
+ )}
748
+ </div>
749
+ );
750
+ }
751
+
752
+ render() {
753
+ let {
754
+ classnames: cx,
755
+ translate: __,
756
+ placeholder = '请选择',
757
+ showResultBox,
758
+ controlled,
759
+ onChange
760
+ } = this.props;
761
+
762
+ const {isOpened, tempSelection, isSelectOpened, isEdit} = this.state;
763
+ let selection = controlled ? this.props.selection : this.state.selection;
764
+
765
+ return (
766
+ <div className={cx('UserSelect')}>
767
+ {showResultBox ? (
768
+ <ResultBox
769
+ className={cx('UserSelect-input', isOpened ? 'is-active' : '')}
770
+ allowInput={false}
771
+ result={selection}
772
+ onResultChange={value => this.handleSelectChange(value, true)}
773
+ onResultClick={this.onOpen}
774
+ placeholder={placeholder}
775
+ useMobileUI
776
+ />
777
+ ) : null}
778
+
779
+ {showResultBox ? (
780
+ <PopUp
781
+ isShow={isOpened}
782
+ className={cx(`UserSelect-popup`)}
783
+ onHide={this.onClose}
784
+ showClose={false}
785
+ >
786
+ {this.renderContent()}
787
+ </PopUp>
788
+ ) : (
789
+ this.renderContent()
790
+ )}
791
+
792
+ <PopUp
793
+ isShow={isSelectOpened}
794
+ className={cx(`UserSelect-selectPopup`)}
795
+ onHide={() =>
796
+ this.setState({
797
+ isSelectOpened: false,
798
+ isEdit: false
799
+ })
800
+ }
801
+ showClose={false}
802
+ >
803
+ <div className={cx('UserSelect-selectBody')}>
804
+ <div className={cx('UserSelect-navbar')}>
805
+ <span
806
+ className="left-arrow-box"
807
+ onClick={() =>
808
+ this.setState({
809
+ isSelectOpened: false,
810
+ isEdit: false
811
+ })
812
+ }
813
+ >
814
+ <Icon icon="left-arrow" className="icon" />
815
+ </span>
816
+ <div className={cx('UserSelect-navbar-title')}>
817
+ {__('UserSelect.resultSort')}
818
+ </div>
819
+ <span
820
+ className={cx('UserSelect-navbar-btnEdit')}
821
+ onClick={this.handleEdit}
822
+ >
823
+ {isEdit ? __('UserSelect.save') : __('UserSelect.edit')}
824
+ </span>
825
+ </div>
826
+
827
+ <div className={cx('UserSelect-selectList-box')}>
828
+ <div className={cx('UserSelect-select-head')}>
829
+ <span className={cx('UserSelect-select-head-text')}>
830
+ {__('UserSelect.selected')}
831
+ </span>
832
+ {isEdit ? (
833
+ <span
834
+ className={cx('UserSelect-select-head-btnClear')}
835
+ onClick={() => this.setState({tempSelection: []})}
836
+ >
837
+ {__('UserSelect.clear')}
838
+ </span>
839
+ ) : null}
840
+ </div>
841
+ {this.renderselectList(tempSelection)}
842
+ </div>
843
+ </div>
844
+ </PopUp>
845
+ </div>
846
+ );
847
+ }
848
+ }
849
+
850
+ export default themeable(localeable(UserSelect));