amis 1.5.2 → 1.5.6-beta.0

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 (171) hide show
  1. package/README.md +5 -0
  2. package/lib/RootRenderer.d.ts +1 -1
  3. package/lib/RootRenderer.js +4 -3
  4. package/lib/RootRenderer.js.map +2 -2
  5. package/lib/components/Card.d.ts +96 -0
  6. package/lib/components/Card.js +85 -0
  7. package/lib/components/Card.js.map +13 -0
  8. package/lib/components/Collapse.js +1 -1
  9. package/lib/components/Collapse.js.map +2 -2
  10. package/lib/components/DatePicker.d.ts +179 -84
  11. package/lib/components/DatePicker.js +25 -4
  12. package/lib/components/DatePicker.js.map +2 -2
  13. package/lib/components/DateRangePicker.d.ts +84 -84
  14. package/lib/components/MonthRangePicker.d.ts +84 -84
  15. package/lib/components/Picker.d.ts +503 -0
  16. package/lib/components/Picker.js +65 -0
  17. package/lib/components/Picker.js.map +13 -0
  18. package/lib/components/PickerColumn.d.ts +29 -459
  19. package/lib/components/PickerColumn.js +35 -44
  20. package/lib/components/PickerColumn.js.map +2 -2
  21. package/lib/components/Progress.js +1 -1
  22. package/lib/components/Progress.js.map +2 -2
  23. package/lib/components/Select.d.ts +238 -238
  24. package/lib/components/Select.js +9 -2
  25. package/lib/components/Select.js.map +2 -2
  26. package/lib/components/Selection.js +1 -4
  27. package/lib/components/Selection.js.map +2 -2
  28. package/lib/components/Switch.d.ts +6 -6
  29. package/lib/components/Switch.js.map +2 -2
  30. package/lib/components/calendar/Calendar.d.ts +8 -0
  31. package/lib/components/calendar/Calendar.js +19 -1
  32. package/lib/components/calendar/Calendar.js.map +2 -2
  33. package/lib/components/calendar/DaysView.d.ts +8 -0
  34. package/lib/components/calendar/DaysView.js +71 -0
  35. package/lib/components/calendar/DaysView.js.map +2 -2
  36. package/lib/components/calendar/TimeView.d.ts +10 -0
  37. package/lib/components/calendar/TimeView.js +55 -2
  38. package/lib/components/calendar/TimeView.js.map +2 -2
  39. package/lib/components/calendar/YearsView.d.ts +9 -0
  40. package/lib/components/calendar/YearsView.js +19 -0
  41. package/lib/components/calendar/YearsView.js.map +2 -2
  42. package/lib/index.js +1 -1
  43. package/lib/renderers/CRUD.d.ts +1 -1
  44. package/lib/renderers/CRUD.js +4 -3
  45. package/lib/renderers/CRUD.js.map +2 -2
  46. package/lib/renderers/Card.d.ts +81 -13
  47. package/lib/renderers/Card.js +178 -81
  48. package/lib/renderers/Card.js.map +2 -2
  49. package/lib/renderers/Dialog.d.ts +2 -2
  50. package/lib/renderers/Dialog.js +7 -7
  51. package/lib/renderers/Dialog.js.map +2 -2
  52. package/lib/renderers/Drawer.js +2 -2
  53. package/lib/renderers/Drawer.js.map +2 -2
  54. package/lib/renderers/Form/DiffEditor.d.ts +145 -37
  55. package/lib/renderers/Form/Editor.d.ts +144 -36
  56. package/lib/renderers/Form/Formula.js +5 -5
  57. package/lib/renderers/Form/Formula.js.map +2 -2
  58. package/lib/renderers/Form/InputCity.d.ts +84 -84
  59. package/lib/renderers/Form/InputDate.d.ts +25 -0
  60. package/lib/renderers/Form/InputDate.js +48 -3
  61. package/lib/renderers/Form/InputDate.js.map +2 -2
  62. package/lib/renderers/Form/InputFile.js +3 -3
  63. package/lib/renderers/Form/InputFile.js.map +2 -2
  64. package/lib/renderers/Form/InputImage.js +1 -1
  65. package/lib/renderers/Form/InputImage.js.map +2 -2
  66. package/lib/renderers/Form/Item.d.ts +1 -1
  67. package/lib/renderers/Form/Item.js +4 -3
  68. package/lib/renderers/Form/Item.js.map +2 -2
  69. package/lib/renderers/Form/index.d.ts +1 -1
  70. package/lib/renderers/Form/index.js +13 -2
  71. package/lib/renderers/Form/index.js.map +2 -2
  72. package/lib/renderers/Form/wrapControl.js +3 -2
  73. package/lib/renderers/Form/wrapControl.js.map +2 -2
  74. package/lib/renderers/Page.d.ts +3 -3
  75. package/lib/renderers/Page.js +4 -3
  76. package/lib/renderers/Page.js.map +2 -2
  77. package/lib/renderers/Status.js +1 -1
  78. package/lib/renderers/Status.js.map +2 -2
  79. package/lib/renderers/Wizard.d.ts +1 -1
  80. package/lib/renderers/Wizard.js +93 -36
  81. package/lib/renderers/Wizard.js.map +2 -2
  82. package/lib/store/combo.d.ts +160 -40
  83. package/lib/store/form.d.ts +64 -16
  84. package/lib/store/formItem.d.ts +4 -2
  85. package/lib/store/formItem.js +11 -6
  86. package/lib/store/formItem.js.map +2 -2
  87. package/lib/store/table.d.ts +128 -32
  88. package/lib/themes/ang-ie11.css +255 -31
  89. package/lib/themes/ang.css +255 -31
  90. package/lib/themes/ang.css.map +1 -1
  91. package/lib/themes/antd-ie11.css +255 -32
  92. package/lib/themes/antd.css +255 -32
  93. package/lib/themes/antd.css.map +1 -1
  94. package/lib/themes/cxd-ie11.css +263 -31
  95. package/lib/themes/cxd.css +263 -31
  96. package/lib/themes/cxd.css.map +1 -1
  97. package/lib/themes/dark-ie11.css +255 -31
  98. package/lib/themes/dark.css +255 -31
  99. package/lib/themes/dark.css.map +1 -1
  100. package/lib/themes/default.css +263 -31
  101. package/lib/themes/default.css.map +1 -1
  102. package/lib/utils/helper.d.ts +7 -0
  103. package/lib/utils/helper.js +33 -1
  104. package/lib/utils/helper.js.map +2 -2
  105. package/package.json +2 -2
  106. package/schema.json +209 -20
  107. package/scss/_properties.scss +14 -3
  108. package/scss/components/_calendar.scss +81 -0
  109. package/scss/components/_card.scss +155 -15
  110. package/scss/components/_nav.scss +1 -1
  111. package/scss/components/_picker-columns.scss +20 -14
  112. package/scss/components/_toast.scss +3 -0
  113. package/scss/components/form/_file.scss +2 -2
  114. package/scss/components/form/_selection.scss +4 -0
  115. package/scss/components/form/_switch.scss +6 -0
  116. package/scss/themes/_antd-variables.scss +0 -2
  117. package/scss/themes/_common.scss +1 -0
  118. package/scss/themes/_cxd-variables.scss +9 -0
  119. package/sdk/ang-ie11.css +296 -33
  120. package/sdk/ang.css +306 -33
  121. package/sdk/antd-ie11.css +295 -32
  122. package/sdk/antd.css +306 -34
  123. package/sdk/charts.js +13 -13
  124. package/sdk/color-picker.js +65 -65
  125. package/sdk/cropperjs.js +2 -2
  126. package/sdk/cxd-ie11.css +296 -33
  127. package/sdk/cxd.css +314 -33
  128. package/sdk/dark-ie11.css +296 -33
  129. package/sdk/dark.css +306 -33
  130. package/sdk/exceljs.js +1 -1
  131. package/sdk/markdown.js +69 -69
  132. package/sdk/papaparse.js +1 -1
  133. package/sdk/renderers/Form/CityDB.js +1 -1
  134. package/sdk/rest.js +18 -18
  135. package/sdk/rich-text.js +62 -62
  136. package/sdk/sdk-ie11.css +296 -33
  137. package/sdk/sdk.css +314 -33
  138. package/sdk/sdk.js +1190 -1186
  139. package/sdk/thirds/hls.js/hls.js +1 -1
  140. package/sdk/thirds/mpegts.js/mpegts.js +1 -1
  141. package/sdk/tinymce.js +57 -57
  142. package/src/RootRenderer.tsx +3 -3
  143. package/src/components/Card.tsx +203 -0
  144. package/src/components/Collapse.tsx +1 -1
  145. package/src/components/DatePicker.tsx +44 -3
  146. package/src/components/Picker.tsx +145 -0
  147. package/src/components/PickerColumn.tsx +58 -95
  148. package/src/components/Progress.tsx +1 -1
  149. package/src/components/Select.tsx +17 -12
  150. package/src/components/Selection.tsx +1 -4
  151. package/src/components/Switch.tsx +7 -7
  152. package/src/components/calendar/Calendar.tsx +30 -1
  153. package/src/components/calendar/DaysView.tsx +91 -0
  154. package/src/components/calendar/TimeView.tsx +80 -5
  155. package/src/components/calendar/YearsView.tsx +44 -1
  156. package/src/renderers/CRUD.tsx +3 -3
  157. package/src/renderers/Card.tsx +299 -191
  158. package/src/renderers/Dialog.tsx +8 -8
  159. package/src/renderers/Drawer.tsx +2 -2
  160. package/src/renderers/Form/Formula.tsx +7 -5
  161. package/src/renderers/Form/InputDate.tsx +83 -2
  162. package/src/renderers/Form/InputFile.tsx +7 -3
  163. package/src/renderers/Form/InputImage.tsx +1 -1
  164. package/src/renderers/Form/Item.tsx +2 -2
  165. package/src/renderers/Form/index.tsx +14 -2
  166. package/src/renderers/Form/wrapControl.tsx +5 -2
  167. package/src/renderers/Page.tsx +11 -10
  168. package/src/renderers/Status.tsx +3 -1
  169. package/src/renderers/Wizard.tsx +52 -12
  170. package/src/store/formItem.ts +12 -6
  171. package/src/utils/helper.ts +34 -0
@@ -97,7 +97,7 @@ export type DialogSchemaBase = Omit<DialogSchema, 'type'>;
97
97
  export interface DialogProps
98
98
  extends RendererProps,
99
99
  Omit<DialogSchema, 'className'> {
100
- onClose: () => void;
100
+ onClose: (confirmed?: boolean) => void;
101
101
  onConfirm: (
102
102
  values: Array<object>,
103
103
  action: Action,
@@ -214,12 +214,12 @@ export default class Dialog extends React.Component<DialogProps> {
214
214
  return ret;
215
215
  }
216
216
 
217
- handleSelfClose() {
217
+ handleSelfClose(e?: any, confirmed?: boolean) {
218
218
  const {onClose, store} = this.props;
219
219
 
220
220
  // clear error
221
221
  store.updateMessage();
222
- onClose();
222
+ onClose(confirmed);
223
223
  }
224
224
 
225
225
  handleAction(e: React.UIEvent<any>, action: Action, data: object) {
@@ -251,7 +251,7 @@ export default class Dialog extends React.Component<DialogProps> {
251
251
  return;
252
252
  }
253
253
 
254
- store.closeDialog();
254
+ store.closeDialog(true);
255
255
  }
256
256
 
257
257
  handleDialogClose(...args: Array<any>) {
@@ -264,7 +264,7 @@ export default class Dialog extends React.Component<DialogProps> {
264
264
  return;
265
265
  }
266
266
 
267
- store.closeDialog();
267
+ store.closeDialog(args[1]);
268
268
  }
269
269
 
270
270
  handleDrawerConfirm(values: object[], action: Action, ...args: Array<any>) {
@@ -743,7 +743,7 @@ export class DialogRenderer extends Dialog {
743
743
  },
744
744
  data,
745
745
  action
746
- ) || this.handleSelfClose();
746
+ ) || this.handleSelfClose(undefined, true);
747
747
  } else if (action.actionType === 'next' || action.actionType === 'prev') {
748
748
  store.setCurrentAction(action);
749
749
  if (action.type === 'submit') {
@@ -755,7 +755,7 @@ export class DialogRenderer extends Dialog {
755
755
  },
756
756
  data,
757
757
  action
758
- ) || this.handleSelfClose();
758
+ ) || this.handleSelfClose(undefined, true);
759
759
  } else {
760
760
  onConfirm([data], action, data, []);
761
761
  }
@@ -769,7 +769,7 @@ export class DialogRenderer extends Dialog {
769
769
  store.setCurrentAction(action);
770
770
  action.target && scoped.reload(action.target, data);
771
771
  if (action.close || action.type === 'submit') {
772
- this.handleSelfClose();
772
+ this.handleSelfClose(undefined, action.type === 'submit');
773
773
  this.closeTarget(action.close);
774
774
  }
775
775
  } else if (this.tryChildrenToHandle(action, data)) {
@@ -304,7 +304,7 @@ export default class Drawer extends React.Component<DrawerProps> {
304
304
  return;
305
305
  }
306
306
 
307
- store.closeDialog();
307
+ store.closeDialog(true);
308
308
  }
309
309
 
310
310
  handleDialogClose(...args: Array<any>) {
@@ -317,7 +317,7 @@ export default class Drawer extends React.Component<DrawerProps> {
317
317
  return;
318
318
  }
319
319
 
320
- store.closeDialog();
320
+ store.closeDialog(args[1]);
321
321
  }
322
322
 
323
323
  handleChildFinished(value: any, action: Action) {
@@ -65,10 +65,7 @@ export default class FormulaControl extends React.Component<
65
65
  componentDidMount() {
66
66
  const {formInited, initSet, addHook} = this.props;
67
67
 
68
- this.unHook =
69
- initSet !== false && addHook
70
- ? addHook(this.handleFormInit, 'init')
71
- : undefined;
68
+ this.unHook = addHook ? addHook(this.handleFormInit, 'init') : undefined;
72
69
 
73
70
  // 如果在表单中,还是等初始化数据过来才算
74
71
  if (formInited === false) {
@@ -97,7 +94,12 @@ export default class FormulaControl extends React.Component<
97
94
  @autobind
98
95
  handleFormInit(data: any) {
99
96
  this.inited = true;
100
- const {name} = this.props;
97
+ const {name, initSet} = this.props;
98
+
99
+ if (initSet === false) {
100
+ return;
101
+ }
102
+
101
103
  const result = this.initSet();
102
104
 
103
105
  if (typeof name === 'string' && typeof result !== 'undefined') {
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
2
  import {FormItem, FormControlProps, FormBaseControl} from './Item';
3
3
  import cx from 'classnames';
4
- import {filterDate} from '../../utils/tpl-builtin';
4
+ import {filterDate, isPureVariable, resolveVariableAndFilter} from '../../utils/tpl-builtin';
5
5
  import moment from 'moment';
6
6
  import 'moment/locale/zh-cn';
7
7
  import DatePicker from '../../components/DatePicker';
8
+ import {SchemaObject} from '../../Schema';
9
+ import {createObject, anyChanged} from '../../utils/helper';
8
10
 
9
11
  export interface InputDateBaseControlSchema extends FormBaseControl {
10
12
  /**
@@ -85,6 +87,24 @@ export interface DateControlSchema extends InputDateBaseControlSchema {
85
87
  * 限制最大日期
86
88
  */
87
89
  maxDate?: string;
90
+
91
+ /**
92
+ * 日程
93
+ */
94
+ schedules?: Array<{
95
+ startTime: Date,
96
+ endTime: Date,
97
+ content: any,
98
+ className?: string
99
+ }> | string;
100
+ /**
101
+ * 日程显示颜色自定义
102
+ */
103
+ scheduleClassNames?: Array<string>;
104
+ /**
105
+ * 日程点击展示
106
+ */
107
+ scheduleAction?: SchemaObject;
88
108
  }
89
109
 
90
110
  /**
@@ -267,6 +287,12 @@ export interface DateProps extends FormControlProps {
267
287
  interface DateControlState {
268
288
  minDate?: moment.Moment;
269
289
  maxDate?: moment.Moment;
290
+ schedules?: Array<{
291
+ startTime: Date,
292
+ endTime: Date,
293
+ content: any,
294
+ className?: string
295
+ }>;
270
296
  }
271
297
 
272
298
  export default class DateControl extends React.PureComponent<
@@ -304,9 +330,18 @@ export default class DateControl extends React.PureComponent<
304
330
  setPrinstineValue((utc ? moment.utc(date) : date).format(format));
305
331
  }
306
332
 
333
+ let schedulesData = props.schedules;
334
+ if (typeof schedulesData === 'string') {
335
+ const resolved = resolveVariableAndFilter(schedulesData, data, '| raw');
336
+ if (Array.isArray(resolved)) {
337
+ schedulesData = resolved;
338
+ }
339
+ }
340
+
307
341
  this.state = {
308
342
  minDate: minDate ? filterDate(minDate, data, format) : undefined,
309
- maxDate: maxDate ? filterDate(maxDate, data, format) : undefined
343
+ maxDate: maxDate ? filterDate(maxDate, data, format) : undefined,
344
+ schedules: schedulesData
310
345
  };
311
346
  }
312
347
 
@@ -334,6 +369,47 @@ export default class DateControl extends React.PureComponent<
334
369
  : undefined
335
370
  });
336
371
  }
372
+
373
+ if (anyChanged(['schedules', 'data'], prevProps, props)
374
+ && (typeof props.schedules === 'string' && isPureVariable(props.schedules))
375
+ ) {
376
+ const schedulesData = resolveVariableAndFilter(props.schedules, props.data, '| raw');
377
+ const preSchedulesData = resolveVariableAndFilter(prevProps.schedules, prevProps.data, '| raw');
378
+ if (Array.isArray(schedulesData) && preSchedulesData !== schedulesData) {
379
+ this.setState({
380
+ schedules: schedulesData
381
+ })
382
+ }
383
+ }
384
+ }
385
+
386
+ // 日程点击事件
387
+ onScheduleClick(scheduleData: any) {
388
+ const {scheduleAction, onAction, data, translate: __} = this.props;
389
+ const defaultscheduleAction = {
390
+ actionType: 'dialog',
391
+ dialog: {
392
+ title: __('Schedule'),
393
+ actions: [],
394
+ body: {
395
+ type: 'table',
396
+ columns: [
397
+ {
398
+ name: 'time',
399
+ label: __('Time')
400
+ },
401
+ {
402
+ name: 'content',
403
+ label: __('Content')
404
+ }
405
+ ],
406
+ data: '${scheduleData}'
407
+ }
408
+ }
409
+ };
410
+
411
+ onAction && onAction(null, scheduleAction || defaultscheduleAction, createObject(data, scheduleData));
412
+
337
413
  }
338
414
 
339
415
  render() {
@@ -348,6 +424,8 @@ export default class DateControl extends React.PureComponent<
348
424
  format,
349
425
  timeFormat,
350
426
  valueFormat,
427
+ largeMode,
428
+ render,
351
429
  ...rest
352
430
  } = this.props;
353
431
 
@@ -363,6 +441,9 @@ export default class DateControl extends React.PureComponent<
363
441
  format={valueFormat || format}
364
442
  {...this.state}
365
443
  classnames={cx}
444
+ schedules={this.state.schedules}
445
+ largeMode={largeMode}
446
+ onScheduleClick={this.onScheduleClick.bind(this)}
366
447
  />
367
448
  </div>
368
449
  );
@@ -790,7 +790,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
790
790
  onProgress
791
791
  )
792
792
  .then(ret => {
793
- if (ret.status || !ret.data) {
793
+ if ((ret.status && (ret as any).status !== '0') || !ret.data) {
794
794
  throw new Error(ret.msg || __('File.errorRetry'));
795
795
  }
796
796
 
@@ -1185,6 +1185,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
1185
1185
  multiple,
1186
1186
  autoUpload,
1187
1187
  description,
1188
+ descriptionClassName,
1188
1189
  hideUploadButton,
1189
1190
  className,
1190
1191
  btnClassName,
@@ -1224,7 +1225,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
1224
1225
  <Icon icon="download" className="icon" />
1225
1226
  <span>{__('File.downloadTpl')}</span>
1226
1227
  </a>
1227
- ) : null}
1228
+ ) : null}
1228
1229
 
1229
1230
  <DropZone
1230
1231
  disabled={disabled}
@@ -1277,7 +1278,10 @@ export default class FileControl extends React.Component<FileProps, FileState> {
1277
1278
 
1278
1279
  {description
1279
1280
  ? render('desc', description!, {
1280
- className: cx('FileControl-description')
1281
+ className: cx(
1282
+ 'FileControl-description',
1283
+ descriptionClassName
1284
+ )
1281
1285
  })
1282
1286
  : null}
1283
1287
 
@@ -1035,7 +1035,7 @@ export default class ImageControl extends React.Component<
1035
1035
  const __ = this.props.translate;
1036
1036
  this._send(file, this.props.receiver as string, {}, onProgress)
1037
1037
  .then((ret: Payload) => {
1038
- if (ret.status) {
1038
+ if (ret.status && (ret as any).status !== '0') {
1039
1039
  throw new Error(ret.msg || __('File.errorRetry'));
1040
1040
  }
1041
1041
 
@@ -436,12 +436,12 @@ export class FormItemWrap extends React.Component<FormItemProps> {
436
436
  }
437
437
 
438
438
  @autobind
439
- handleDialogClose() {
439
+ handleDialogClose(confirmed = false) {
440
440
  const {formItem: model} = this.props;
441
441
  if (!model) {
442
442
  return;
443
443
  }
444
- model.closeDialog();
444
+ model.closeDialog(confirmed);
445
445
  }
446
446
 
447
447
  renderControl(): JSX.Element | null {
@@ -866,6 +866,18 @@ export default class Form extends React.Component<FormProps, object> {
866
866
 
867
867
  store.updateData(values);
868
868
 
869
+ store.items.forEach(formItem => {
870
+ const updatedValue = getVariable(values, formItem.name, false);
871
+
872
+ if (updatedValue !== undefined) {
873
+ // 更新验证状态但保留错误信息
874
+ formItem.reset(true);
875
+ // 这里需要更新value,否则提交时不会使用新的字段值校验
876
+ formItem.changeTmpValue(updatedValue);
877
+ formItem.validateOnChange && formItem.validate(values);
878
+ }
879
+ });
880
+
869
881
  (formLazyChange === false ? this.emitChange : this.lazyEmitChange)(submit);
870
882
  }
871
883
 
@@ -1155,9 +1167,9 @@ export default class Form extends React.Component<FormProps, object> {
1155
1167
  store.closeDialog(true);
1156
1168
  }
1157
1169
 
1158
- handleDialogClose() {
1170
+ handleDialogClose(confirmed = false) {
1159
1171
  const {store} = this.props;
1160
- store.closeDialog(false);
1172
+ store.closeDialog(confirmed);
1161
1173
  }
1162
1174
 
1163
1175
  handleDrawerConfirm(
@@ -129,7 +129,8 @@ export function wrapControl<
129
129
  clearValueOnHidden,
130
130
  validateApi,
131
131
  minLength,
132
- maxLength
132
+ maxLength,
133
+ validateOnChange
133
134
  }
134
135
  } = this.props;
135
136
 
@@ -174,7 +175,8 @@ export function wrapControl<
174
175
  clearValueOnHidden,
175
176
  validateApi,
176
177
  minLength,
177
- maxLength
178
+ maxLength,
179
+ validateOnChange
178
180
  });
179
181
 
180
182
  // issue 这个逻辑应该在 combo 里面自己实现。
@@ -465,6 +467,7 @@ export function wrapControl<
465
467
  }
466
468
 
467
469
  this.model.changeTmpValue(value);
470
+
468
471
  if (changeImmediately || conrolChangeImmediately || !formInited) {
469
472
  this.emitChange(submitOnChange);
470
473
  } else {
@@ -95,7 +95,7 @@ export interface PageSchema extends BaseSchema {
95
95
  */
96
96
  asideMinWidth?: number;
97
97
 
98
- /**
98
+ /**
99
99
  * 边栏最小宽度
100
100
  */
101
101
  asideMaxWidth?: number;
@@ -471,12 +471,12 @@ export default class Page extends React.Component<PageProps> {
471
471
  return;
472
472
  }
473
473
 
474
- store.closeDialog();
474
+ store.closeDialog(true);
475
475
  }
476
476
 
477
- handleDialogClose() {
477
+ handleDialogClose(confirmed = false) {
478
478
  const {store} = this.props;
479
- store.closeDialog();
479
+ store.closeDialog(confirmed);
480
480
  }
481
481
 
482
482
  handleDrawerConfirm(values: object[], action: Action, ...args: Array<any>) {
@@ -734,11 +734,13 @@ export default class Page extends React.Component<PageProps> {
734
734
  style={styleVar}
735
735
  >
736
736
  {hasAside ? (
737
- <div className={cx(
738
- `Page-aside`,
739
- asideResizor ? 'relative' : 'Page-aside--withWidth',
740
- asideClassName
741
- )}>
737
+ <div
738
+ className={cx(
739
+ `Page-aside`,
740
+ asideResizor ? 'relative' : 'Page-aside--withWidth',
741
+ asideClassName
742
+ )}
743
+ >
742
744
  {render('aside', aside || '', {
743
745
  ...subProps,
744
746
  ...(typeof aside === 'string'
@@ -754,7 +756,6 @@ export default class Page extends React.Component<PageProps> {
754
756
  className={cx(`Page-asideResizor`)}
755
757
  ></div>
756
758
  ) : null}
757
-
758
759
  </div>
759
760
  ) : null}
760
761
 
@@ -92,7 +92,9 @@ export class StatusField extends React.Component<StatusProps, object> {
92
92
  } = this.props;
93
93
  let value = getPropValue(this.props);
94
94
  let viewValue: React.ReactNode = (
95
- <span className="text-muted">{placeholder}</span>
95
+ <span className="text-muted" key="status-value">
96
+ {placeholder}
97
+ </span>
96
98
  );
97
99
  let wrapClassName: string = '';
98
100
 
@@ -9,7 +9,8 @@ import {
9
9
  until,
10
10
  isVisible,
11
11
  getScrollParent,
12
- autobind
12
+ autobind,
13
+ SkipOperation
13
14
  } from '../utils/helper';
14
15
  import {isApiOutdated, isEffectiveApi} from '../utils/api';
15
16
  import {IFormStore} from '../store/form';
@@ -546,8 +547,16 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
546
547
  .then(async () => {
547
548
  this.form && this.form.isValidated() && this.form.validate(true);
548
549
 
549
- if (action.feedback && isVisible(action.feedback, store.data)) {
550
- await this.openFeedback(action.feedback, store.data);
550
+ const feedback = action.feedback;
551
+ if (feedback && isVisible(feedback, store.data)) {
552
+ const confirmed = await this.openFeedback(feedback, store.data);
553
+
554
+ // 如果 feedback 配置了,取消就跳过原有逻辑。
555
+ if (feedback.skipRestOnCancel && !confirmed) {
556
+ throw new SkipOperation();
557
+ } else if (feedback.skipRestOnConfirm && confirmed) {
558
+ throw new SkipOperation();
559
+ }
551
560
  }
552
561
 
553
562
  const reidrect =
@@ -556,7 +565,11 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
556
565
 
557
566
  action.reload && this.reloadTarget(action.reload, store.data);
558
567
  })
559
- .catch(() => {});
568
+ .catch(reason => {
569
+ if (reason instanceof SkipOperation) {
570
+ return;
571
+ }
572
+ });
560
573
  } else if (action.actionType === 'reload') {
561
574
  action.target && this.reloadTarget(action.target, data);
562
575
  } else if (onAction) {
@@ -667,14 +680,29 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
667
680
  }
668
681
  }
669
682
  })
670
- .then((value: any) =>
683
+ .then(async (value: any) => {
684
+ const feedback = action.feedback;
685
+ if (feedback && isVisible(feedback, value)) {
686
+ const confirmed = await this.openFeedback(feedback, value);
687
+
688
+ // 如果 feedback 配置了,取消就跳过原有逻辑。
689
+ if (feedback.skipRestOnCancel && !confirmed) {
690
+ throw new SkipOperation();
691
+ } else if (feedback.skipRestOnConfirm && confirmed) {
692
+ throw new SkipOperation();
693
+ }
694
+ }
695
+
671
696
  this.gotoStep(
672
697
  value && typeof value.step === 'number'
673
698
  ? value.step
674
699
  : this.state.currentStep + 1
675
- )
676
- )
677
- .catch(() => {
700
+ );
701
+ })
702
+ .catch(reason => {
703
+ if (reason instanceof SkipOperation) {
704
+ return;
705
+ }
678
706
  // do nothing
679
707
  });
680
708
  } else {
@@ -715,7 +743,19 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
715
743
  );
716
744
  }
717
745
  })
718
- .then(value => {
746
+ .then(async value => {
747
+ const feedback = action.feedback;
748
+ if (feedback && isVisible(feedback, value)) {
749
+ const confirmed = await this.openFeedback(feedback, value);
750
+
751
+ // 如果 feedback 配置了,取消就跳过原有逻辑。
752
+ if (feedback.skipRestOnCancel && !confirmed) {
753
+ throw new SkipOperation();
754
+ } else if (feedback.skipRestOnConfirm && confirmed) {
755
+ throw new SkipOperation();
756
+ }
757
+ }
758
+
719
759
  this.setState({completeStep: steps.length});
720
760
  store.updateData({
721
761
  ...store.data,
@@ -771,13 +811,13 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
771
811
  store.updateData(values[0]);
772
812
  }
773
813
 
774
- store.closeDialog();
814
+ store.closeDialog(true);
775
815
  }
776
816
 
777
817
  @autobind
778
- handleDialogClose() {
818
+ handleDialogClose(confirmed = false) {
779
819
  const {store} = this.props;
780
- store.closeDialog();
820
+ store.closeDialog(confirmed);
781
821
  }
782
822
 
783
823
  renderSteps() {
@@ -14,6 +14,7 @@ import {str2rules, validate as doValidate} from '../utils/validations';
14
14
  import {Api, Payload, fetchOptions} from '../types';
15
15
  import {ComboStore, IComboStore, IUniqueGroup} from './combo';
16
16
  import {evalExpression} from '../utils/tpl';
17
+ import {isEffectiveApi} from '../utils/api';
17
18
  import findIndex from 'lodash/findIndex';
18
19
  import {
19
20
  isArrayChildrenModified,
@@ -88,7 +89,8 @@ export const FormItemStore = StoreNode.named('FormItemStore')
88
89
  dialogSchema: types.frozen(),
89
90
  dialogOpen: false,
90
91
  dialogData: types.frozen(),
91
- resetValue: types.optional(types.frozen(), '')
92
+ resetValue: types.optional(types.frozen(), ''),
93
+ validateOnChange: false
92
94
  })
93
95
  .views(self => {
94
96
  function getForm(): any {
@@ -233,7 +235,8 @@ export const FormItemStore = StoreNode.named('FormItemStore')
233
235
  clearValueOnHidden,
234
236
  validateApi,
235
237
  maxLength,
236
- minLength
238
+ minLength,
239
+ validateOnChange
237
240
  }: {
238
241
  required?: boolean;
239
242
  unique?: boolean;
@@ -254,6 +257,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
254
257
  validateApi?: boolean;
255
258
  minLength?: number;
256
259
  maxLength?: number;
260
+ validateOnChange?: boolean;
257
261
  }) {
258
262
  if (typeof rules === 'string') {
259
263
  rules = str2rules(rules);
@@ -279,6 +283,8 @@ export const FormItemStore = StoreNode.named('FormItemStore')
279
283
  typeof clearValueOnHidden !== 'undefined' &&
280
284
  (self.clearValueOnHidden = !!clearValueOnHidden);
281
285
  typeof validateApi !== 'undefined' && (self.validateApi = validateApi);
286
+ typeof validateOnChange !== 'undefined' &&
287
+ (self.validateOnChange = !!validateOnChange);
282
288
 
283
289
  rules = {
284
290
  ...rules,
@@ -315,7 +321,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
315
321
  let validateCancel: Function | null = null;
316
322
  const validate: (data: Object, hook?: any) => Promise<boolean> = flow(
317
323
  function* validate(data: Object, hook?: any) {
318
- if (self.validating && !self.validateApi) {
324
+ if (self.validating && !isEffectiveApi(self.validateApi, data)) {
319
325
  return self.valid;
320
326
  }
321
327
 
@@ -329,7 +335,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
329
335
  doValidate(self.tmpValue, data, self.rules, self.messages, self.__)
330
336
  );
331
337
 
332
- if (!self.errors.length && self.validateApi) {
338
+ if (!self.errors.length && isEffectiveApi(self.validateApi, data)) {
333
339
  if (validateCancel) {
334
340
  validateCancel();
335
341
  validateCancel = null;
@@ -1029,7 +1035,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
1029
1035
  subStore = store;
1030
1036
  }
1031
1037
 
1032
- function reset() {
1038
+ function reset(keepErrors: boolean = false) {
1033
1039
  self.validated = false;
1034
1040
 
1035
1041
  if (subStore && subStore.storeType === 'ComboStore') {
@@ -1037,7 +1043,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
1037
1043
  combo.forms.forEach(form => form.reset());
1038
1044
  }
1039
1045
 
1040
- clearError();
1046
+ !keepErrors && clearError();
1041
1047
  }
1042
1048
 
1043
1049
  function openDialog(
@@ -1592,3 +1592,37 @@ export function JSONTraverse(
1592
1592
  }
1593
1593
  });
1594
1594
  }
1595
+
1596
+
1597
+ export function convertDateArrayToDate(
1598
+ value: number[],
1599
+ types: string[],
1600
+ date: moment.Moment
1601
+ ): moment.Moment | null {
1602
+ if (value.length === 0) return date
1603
+ for (let i = 0; i < types.length; i++) {
1604
+ const type = types[i];
1605
+ // @ts-ignore
1606
+ date[type](value[i]);
1607
+ }
1608
+ return date;
1609
+ }
1610
+
1611
+ export function convertDateToObject(value: moment.Moment) {
1612
+ if (value) {
1613
+ return {
1614
+ year: value.year(),
1615
+ month: parseInt(value.format('MM'), 10),
1616
+ day: parseInt(value.format('DD'), 10)
1617
+ };
1618
+ }
1619
+ return null;
1620
+ }
1621
+
1622
+ export function getRange(min: number, max: number, step: number = 1) {
1623
+ const arr = [];
1624
+ for (let i = min; i <= max; i += step) {
1625
+ arr.push(i);
1626
+ }
1627
+ return arr;
1628
+ };