amis 1.3.4 → 1.4.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 (270) hide show
  1. package/README.md +2 -1
  2. package/lib/RootRenderer.js +4 -1
  3. package/lib/RootRenderer.js.map +2 -2
  4. package/lib/components/Badge.d.ts +13 -1
  5. package/lib/components/Badge.js +16 -2
  6. package/lib/components/Badge.js.map +2 -2
  7. package/lib/components/Checkbox.d.ts +1 -1
  8. package/lib/components/Checkbox.js +1 -1
  9. package/lib/components/Checkbox.js.map +2 -2
  10. package/lib/components/Drawer.js +1 -1
  11. package/lib/components/Drawer.js.map +2 -2
  12. package/lib/components/Modal.js +1 -1
  13. package/lib/components/Modal.js.map +2 -2
  14. package/lib/components/RichText.d.ts +0 -3
  15. package/lib/components/RichText.js +1 -22
  16. package/lib/components/RichText.js.map +2 -2
  17. package/lib/components/Select.d.ts +7 -0
  18. package/lib/components/Select.js.map +2 -2
  19. package/lib/components/Steps.d.ts +3 -3
  20. package/lib/components/Steps.js.map +1 -1
  21. package/lib/components/WithRemoteConfig.d.ts +8 -0
  22. package/lib/components/WithRemoteConfig.js +28 -2
  23. package/lib/components/WithRemoteConfig.js.map +2 -2
  24. package/lib/components/condition-builder/Field.js +0 -1
  25. package/lib/components/condition-builder/Field.js.map +2 -2
  26. package/lib/components/condition-builder/Value.js +2 -1
  27. package/lib/components/condition-builder/Value.js.map +2 -2
  28. package/lib/components/condition-builder/types.d.ts +5 -0
  29. package/lib/components/condition-builder/types.js.map +1 -1
  30. package/lib/env.d.ts +1 -1
  31. package/lib/env.js.map +1 -1
  32. package/lib/factory.d.ts +6 -2
  33. package/lib/factory.js +9 -4
  34. package/lib/factory.js.map +2 -2
  35. package/lib/index.d.ts +1 -0
  36. package/lib/index.js +2 -1
  37. package/lib/index.js.map +2 -2
  38. package/lib/locale/de-DE.js +1 -0
  39. package/lib/locale/de-DE.js.map +2 -2
  40. package/lib/locale/en-US.js +2 -1
  41. package/lib/locale/en-US.js.map +2 -2
  42. package/lib/locale/zh-CN.js +2 -1
  43. package/lib/locale/zh-CN.js.map +2 -2
  44. package/lib/renderers/Action.d.ts +6 -0
  45. package/lib/renderers/Action.js +9 -1
  46. package/lib/renderers/Action.js.map +2 -2
  47. package/lib/renderers/CRUD.d.ts +2 -2
  48. package/lib/renderers/CRUD.js +13 -21
  49. package/lib/renderers/CRUD.js.map +2 -2
  50. package/lib/renderers/Card.js +11 -11
  51. package/lib/renderers/Card.js.map +2 -2
  52. package/lib/renderers/Collapse.d.ts +1 -1
  53. package/lib/renderers/Collapse.js +5 -1
  54. package/lib/renderers/Collapse.js.map +2 -2
  55. package/lib/renderers/Copyable.js +30 -28
  56. package/lib/renderers/Copyable.js.map +2 -2
  57. package/lib/renderers/Dialog.d.ts +0 -252
  58. package/lib/renderers/Dialog.js +3 -2
  59. package/lib/renderers/Dialog.js.map +2 -2
  60. package/lib/renderers/Drawer.js +2 -1
  61. package/lib/renderers/Drawer.js.map +2 -2
  62. package/lib/renderers/DropDownButton.d.ts +4 -0
  63. package/lib/renderers/DropDownButton.js +2 -2
  64. package/lib/renderers/DropDownButton.js.map +2 -2
  65. package/lib/renderers/Form/ButtonGroupSelect.js +3 -0
  66. package/lib/renderers/Form/ButtonGroupSelect.js.map +2 -2
  67. package/lib/renderers/Form/Combo.d.ts +2 -0
  68. package/lib/renderers/Form/Combo.js +16 -1
  69. package/lib/renderers/Form/Combo.js.map +2 -2
  70. package/lib/renderers/Form/DiffEditor.d.ts +0 -2
  71. package/lib/renderers/Form/Editor.d.ts +0 -2
  72. package/lib/renderers/Form/Editor.js +1 -1
  73. package/lib/renderers/Form/Editor.js.map +2 -2
  74. package/lib/renderers/Form/InputExcel.d.ts +5 -0
  75. package/lib/renderers/Form/InputExcel.js +24 -3
  76. package/lib/renderers/Form/InputExcel.js.map +2 -2
  77. package/lib/renderers/Form/InputImage.d.ts +8 -0
  78. package/lib/renderers/Form/InputImage.js +2 -1
  79. package/lib/renderers/Form/InputImage.js.map +2 -2
  80. package/lib/renderers/Form/InputNumber.d.ts +19 -5
  81. package/lib/renderers/Form/InputNumber.js +69 -7
  82. package/lib/renderers/Form/InputNumber.js.map +2 -2
  83. package/lib/renderers/Form/InputRange.js +7 -2
  84. package/lib/renderers/Form/InputRange.js.map +2 -2
  85. package/lib/renderers/Form/InputTable.d.ts +23 -5
  86. package/lib/renderers/Form/InputTable.js +32 -3
  87. package/lib/renderers/Form/InputTable.js.map +2 -2
  88. package/lib/renderers/Form/NestedSelect.js +2 -3
  89. package/lib/renderers/Form/NestedSelect.js.map +2 -2
  90. package/lib/renderers/Form/Options.js +3 -1
  91. package/lib/renderers/Form/Options.js.map +2 -2
  92. package/lib/renderers/Form/index.js +0 -10
  93. package/lib/renderers/Form/index.js.map +2 -2
  94. package/lib/renderers/Form/wrapControl.js +3 -3
  95. package/lib/renderers/Form/wrapControl.js.map +2 -2
  96. package/lib/renderers/Json.js +5 -1
  97. package/lib/renderers/Json.js.map +2 -2
  98. package/lib/renderers/List.d.ts +5 -0
  99. package/lib/renderers/List.js +20 -14
  100. package/lib/renderers/List.js.map +2 -2
  101. package/lib/renderers/Page.d.ts +6 -0
  102. package/lib/renderers/Page.js +10 -2
  103. package/lib/renderers/Page.js.map +2 -2
  104. package/lib/renderers/Service.d.ts +10 -1
  105. package/lib/renderers/Service.js +85 -3
  106. package/lib/renderers/Service.js.map +2 -2
  107. package/lib/renderers/Steps.d.ts +4 -4
  108. package/lib/renderers/Steps.js +5 -2
  109. package/lib/renderers/Steps.js.map +2 -2
  110. package/lib/renderers/Table/TableBody.d.ts +5 -3
  111. package/lib/renderers/Table/TableBody.js +17 -11
  112. package/lib/renderers/Table/TableBody.js.map +2 -2
  113. package/lib/renderers/Table/TableCell.js +6 -2
  114. package/lib/renderers/Table/TableCell.js.map +2 -2
  115. package/lib/renderers/Table/TableContent.d.ts +3 -1
  116. package/lib/renderers/Table/TableContent.js +6 -2
  117. package/lib/renderers/Table/TableContent.js.map +2 -2
  118. package/lib/renderers/Table/TableRow.d.ts +1 -1
  119. package/lib/renderers/Table/TableRow.js +14 -13
  120. package/lib/renderers/Table/TableRow.js.map +2 -2
  121. package/lib/renderers/Table/index.d.ts +28 -3
  122. package/lib/renderers/Table/index.js +97 -54
  123. package/lib/renderers/Table/index.js.map +2 -2
  124. package/lib/schemaExtend.d.ts +1 -0
  125. package/lib/schemaExtend.js +59 -0
  126. package/lib/schemaExtend.js.map +13 -0
  127. package/lib/store/app.d.ts +0 -1
  128. package/lib/store/combo.d.ts +0 -2
  129. package/lib/store/crud.d.ts +3 -3
  130. package/lib/store/crud.js +41 -36
  131. package/lib/store/crud.js.map +2 -2
  132. package/lib/store/form.d.ts +0 -1
  133. package/lib/store/formItem.js +10 -6
  134. package/lib/store/formItem.js.map +2 -2
  135. package/lib/store/modal.d.ts +1 -1
  136. package/lib/store/modal.js +4 -0
  137. package/lib/store/modal.js.map +2 -2
  138. package/lib/store/root.d.ts +0 -1
  139. package/lib/store/service.d.ts +0 -1
  140. package/lib/store/service.js +0 -13
  141. package/lib/store/service.js.map +2 -2
  142. package/lib/store/table.d.ts +1 -2
  143. package/lib/store/table.js +44 -3
  144. package/lib/store/table.js.map +2 -2
  145. package/lib/themes/ang-ie11.css +278 -17
  146. package/lib/themes/ang.css +278 -17
  147. package/lib/themes/ang.css.map +1 -1
  148. package/lib/themes/antd-ie11.css +278 -17
  149. package/lib/themes/antd.css +278 -17
  150. package/lib/themes/antd.css.map +1 -1
  151. package/lib/themes/cxd-ie11.css +278 -17
  152. package/lib/themes/cxd.css +278 -17
  153. package/lib/themes/cxd.css.map +1 -1
  154. package/lib/themes/dark-ie11.css +278 -17
  155. package/lib/themes/dark.css +278 -17
  156. package/lib/themes/dark.css.map +1 -1
  157. package/lib/themes/default.css +278 -17
  158. package/lib/themes/default.css.map +1 -1
  159. package/lib/utils/api.js +12 -0
  160. package/lib/utils/api.js.map +2 -2
  161. package/lib/utils/attachmentAdpator.d.ts +7 -0
  162. package/lib/utils/attachmentAdpator.js +82 -0
  163. package/lib/utils/attachmentAdpator.js.map +13 -0
  164. package/lib/utils/helper.d.ts +2 -0
  165. package/lib/utils/helper.js +14 -1
  166. package/lib/utils/helper.js.map +2 -2
  167. package/lib/utils/resize-sensor.js +6 -0
  168. package/lib/utils/resize-sensor.js.map +2 -2
  169. package/lib/utils/tpl-builtin.d.ts +1 -0
  170. package/lib/utils/tpl-builtin.js +24 -8
  171. package/lib/utils/tpl-builtin.js.map +2 -2
  172. package/lib/utils/validations.js +62 -5
  173. package/lib/utils/validations.js.map +2 -2
  174. package/package.json +1 -1
  175. package/schema.json +369 -164
  176. package/scss/_properties.scss +6 -0
  177. package/scss/components/_badge.scss +15 -1
  178. package/scss/components/_list.scss +8 -0
  179. package/scss/components/_markdown.scss +266 -0
  180. package/scss/components/_spinner.scss +6 -2
  181. package/scss/components/_table.scss +4 -0
  182. package/scss/components/form/_form.scss +3 -17
  183. package/scss/components/form/_group.scss +4 -0
  184. package/scss/components/form/_nested-select.scss +4 -0
  185. package/scss/components/form/_number.scss +12 -1
  186. package/scss/themes/_common.scss +1 -0
  187. package/sdk/ang-ie11.css +324 -20
  188. package/sdk/ang.css +330 -20
  189. package/sdk/antd-ie11.css +324 -20
  190. package/sdk/antd.css +330 -20
  191. package/sdk/charts.js +15 -15
  192. package/sdk/color-picker.js +65 -69
  193. package/sdk/cropperjs.js +2 -2
  194. package/sdk/cxd-ie11.css +324 -20
  195. package/sdk/cxd.css +330 -20
  196. package/sdk/dark-ie11.css +324 -20
  197. package/sdk/dark.css +330 -20
  198. package/sdk/exceljs.js +1 -1
  199. package/sdk/locale/de-DE.js +1 -0
  200. package/sdk/markdown.js +69 -69
  201. package/sdk/papaparse.js +1 -1
  202. package/sdk/renderers/Form/CityDB.js +1 -1
  203. package/sdk/rest.js +27 -23
  204. package/sdk/rich-text.js +63 -63
  205. package/sdk/sdk-ie11.css +324 -20
  206. package/sdk/sdk.css +330 -20
  207. package/sdk/sdk.js +1146 -1138
  208. package/sdk/thirds/hls.js/hls.js +1 -1
  209. package/sdk/thirds/mpegts.js/mpegts.js +1 -1
  210. package/sdk/tinymce.js +57 -57
  211. package/src/RootRenderer.tsx +8 -3
  212. package/src/components/Badge.tsx +41 -6
  213. package/src/components/Checkbox.tsx +5 -2
  214. package/src/components/Drawer.tsx +3 -2
  215. package/src/components/Modal.tsx +3 -2
  216. package/src/components/RichText.tsx +2 -27
  217. package/src/components/Select.tsx +1 -0
  218. package/src/components/Steps.tsx +3 -3
  219. package/src/components/WithRemoteConfig.tsx +37 -2
  220. package/src/components/condition-builder/Field.tsx +1 -2
  221. package/src/components/condition-builder/Value.tsx +3 -0
  222. package/src/components/condition-builder/types.ts +6 -0
  223. package/src/env.tsx +1 -1
  224. package/src/factory.tsx +14 -4
  225. package/src/index.tsx +2 -0
  226. package/src/locale/de-DE.ts +1 -0
  227. package/src/locale/en-US.ts +2 -1
  228. package/src/locale/zh-CN.ts +2 -1
  229. package/src/renderers/Action.tsx +19 -1
  230. package/src/renderers/CRUD.tsx +15 -34
  231. package/src/renderers/Card.tsx +21 -15
  232. package/src/renderers/Collapse.tsx +5 -1
  233. package/src/renderers/Copyable.tsx +46 -44
  234. package/src/renderers/Dialog.tsx +3 -2
  235. package/src/renderers/Drawer.tsx +2 -1
  236. package/src/renderers/DropDownButton.tsx +8 -0
  237. package/src/renderers/Form/ButtonGroupSelect.tsx +3 -0
  238. package/src/renderers/Form/Combo.tsx +7 -0
  239. package/src/renderers/Form/Editor.tsx +19 -20
  240. package/src/renderers/Form/InputExcel.tsx +28 -3
  241. package/src/renderers/Form/InputImage.tsx +23 -8
  242. package/src/renderers/Form/InputNumber.tsx +113 -18
  243. package/src/renderers/Form/InputRange.tsx +5 -2
  244. package/src/renderers/Form/InputTable.tsx +88 -9
  245. package/src/renderers/Form/NestedSelect.tsx +1 -1
  246. package/src/renderers/Form/Options.tsx +3 -1
  247. package/src/renderers/Form/index.tsx +0 -15
  248. package/src/renderers/Form/wrapControl.tsx +2 -2
  249. package/src/renderers/Json.tsx +10 -1
  250. package/src/renderers/List.tsx +32 -19
  251. package/src/renderers/Page.tsx +19 -0
  252. package/src/renderers/Service.tsx +101 -3
  253. package/src/renderers/Steps.tsx +12 -9
  254. package/src/renderers/Table/TableBody.tsx +29 -10
  255. package/src/renderers/Table/TableCell.tsx +15 -1
  256. package/src/renderers/Table/TableContent.tsx +7 -1
  257. package/src/renderers/Table/TableRow.tsx +18 -17
  258. package/src/renderers/Table/index.tsx +117 -28
  259. package/src/schemaExtend.ts +66 -0
  260. package/src/store/crud.ts +34 -38
  261. package/src/store/formItem.ts +10 -6
  262. package/src/store/modal.ts +4 -0
  263. package/src/store/service.ts +0 -19
  264. package/src/store/table.ts +48 -0
  265. package/src/utils/api.ts +11 -0
  266. package/src/utils/attachmentAdpator.ts +90 -0
  267. package/src/utils/helper.ts +15 -0
  268. package/src/utils/resize-sensor.ts +7 -0
  269. package/src/utils/tpl-builtin.ts +36 -17
  270. package/src/utils/validations.ts +80 -12
@@ -4,7 +4,8 @@ import cx from 'classnames';
4
4
  import {filter} from '../../utils/tpl';
5
5
  import NumberInput from '../../components/NumberInput';
6
6
  import {FormOptionsControl} from './Options';
7
-
7
+ import Select, {normalizeOptions, Option} from '../../components/Select';
8
+ import {PlainObject} from '../../types';
8
9
  /**
9
10
  * 数字输入框
10
11
  * 文档:https://baidu.gitee.io/amis/docs/components/form/number
@@ -48,14 +49,20 @@ export interface NumberControlSchema extends FormBaseControl {
48
49
  * 后缀
49
50
  */
50
51
  suffix?: string;
52
+
53
+ /**
54
+ * 单位列表
55
+ */
56
+ unitOptions?: string | Array<Option> | string[] | PlainObject;
57
+
51
58
  /**
52
59
  * 是否千分分隔
53
60
  */
54
61
  kilobitSeparator?: boolean;
55
62
  /**
56
- * 只读
57
- */
58
- readOnly?: boolean
63
+ * 只读
64
+ */
65
+ readOnly?: boolean;
59
66
  }
60
67
 
61
68
  export interface NumberProps extends FormControlProps {
@@ -67,8 +74,8 @@ export interface NumberProps extends FormControlProps {
67
74
  /**
68
75
  * 边框模式,全边框,还是半边框,或者没边框。
69
76
  */
70
- borderMode?: 'full' | 'half' | 'none';
71
- /**
77
+ borderMode?: 'full' | 'half' | 'none';
78
+ /**
72
79
  * 前缀
73
80
  */
74
81
  prefix?: string;
@@ -83,10 +90,19 @@ export interface NumberProps extends FormControlProps {
83
90
  /**
84
91
  * 只读
85
92
  */
86
- readOnly?: boolean
93
+ readOnly?: boolean;
94
+ }
95
+
96
+ interface NumberState {
97
+ // 数字单位,将会影响输出
98
+ unit?: string;
99
+ unitOptions?: Option[];
87
100
  }
88
101
 
89
- export default class NumberControl extends React.Component<NumberProps, any> {
102
+ export default class NumberControl extends React.Component<
103
+ NumberProps,
104
+ NumberState
105
+ > {
90
106
  static defaultProps: Partial<NumberProps> = {
91
107
  step: 1,
92
108
  resetValue: ''
@@ -94,17 +110,51 @@ export default class NumberControl extends React.Component<NumberProps, any> {
94
110
 
95
111
  constructor(props: NumberProps) {
96
112
  super(props);
97
-
98
113
  this.handleChange = this.handleChange.bind(this);
114
+ this.handleChangeUnit = this.handleChangeUnit.bind(this);
115
+ const unit = this.getUnit();
116
+ const unitOptions = normalizeOptions(props.unitOptions);
117
+ this.state = {unit, unitOptions};
118
+ }
119
+
120
+ // 解析出单位
121
+ getUnit() {
122
+ const props = this.props;
123
+ if (props.unitOptions && props.unitOptions.length) {
124
+ const optionValues = normalizeOptions(props.unitOptions).map(
125
+ option => option.value
126
+ );
127
+ // 如果有值就解析出来作为单位
128
+ if (props.value && typeof props.value === 'string') {
129
+ let unit = optionValues[0];
130
+ // 先找长的字符,这样如果有 ab 和 b 两种后缀相同的也能识别
131
+ optionValues.sort((a, b) => b.length - a.length);
132
+ for (const optionValue of optionValues) {
133
+ if (props.value.endsWith(optionValue)) {
134
+ unit = optionValue;
135
+ break;
136
+ }
137
+ }
138
+ return unit;
139
+ } else {
140
+ // 没有值就使用第一个单位
141
+ return optionValues[0];
142
+ }
143
+ }
144
+ return undefined;
99
145
  }
100
146
 
101
147
  handleChange(inputValue: any) {
102
- const {classPrefix: ns, onChange, resetValue} = this.props;
148
+ const {classPrefix: ns, onChange, resetValue, unitOptions} = this.props;
103
149
 
104
150
  if (inputValue && typeof inputValue !== 'number') {
105
151
  return;
106
152
  }
107
153
 
154
+ if (inputValue !== null && unitOptions && this.state.unit) {
155
+ inputValue = inputValue + this.state.unit;
156
+ }
157
+
108
158
  onChange(inputValue === null ? resetValue ?? null : inputValue);
109
159
  }
110
160
 
@@ -116,6 +166,28 @@ export default class NumberControl extends React.Component<NumberProps, any> {
116
166
  return value;
117
167
  }
118
168
 
169
+ // 单位选项的变更
170
+ handleChangeUnit(option: Option) {
171
+ let value = this.props.value;
172
+ const prevUnitValue = this.state.unit;
173
+ this.setState({unit: option.value}, () => {
174
+ if (value) {
175
+ value = value.replace(prevUnitValue, '');
176
+ this.props.onChange(value + this.state.unit);
177
+ }
178
+ });
179
+ }
180
+
181
+ componentDidUpdate(prevProps: NumberProps) {
182
+ if (this.props.value !== prevProps.value) {
183
+ const unit = this.getUnit();
184
+ this.setState({unit: unit});
185
+ }
186
+ if (this.props.unitOptions !== prevProps.unitOptions) {
187
+ this.setState({unitOptions: normalizeOptions(this.props.unitOptions)});
188
+ }
189
+ }
190
+
119
191
  render(): JSX.Element {
120
192
  const {
121
193
  className,
@@ -132,6 +204,7 @@ export default class NumberControl extends React.Component<NumberProps, any> {
132
204
  suffix,
133
205
  prefix,
134
206
  kilobitSeparator,
207
+ unitOptions,
135
208
  readOnly
136
209
  } = this.props;
137
210
 
@@ -141,29 +214,43 @@ export default class NumberControl extends React.Component<NumberProps, any> {
141
214
  if (typeof finalPrecision === 'number') {
142
215
  precisionProps.precision = finalPrecision;
143
216
  }
217
+
218
+ const unit = this.state?.unit;
144
219
  // 数据格式化
145
220
  const formatter = (value: string | number) => {
146
221
  // 增加千分分隔
147
222
  if (kilobitSeparator && value) {
148
223
  value = (value + '').replace(/\B(?=(\d{3})+(?!\d))/g, ',');
149
224
  }
150
- return (prefix ? prefix : '')
151
- + value
152
- + (suffix ? suffix : '');
153
- }
225
+ return (prefix ? prefix : '') + value + (suffix ? suffix : '');
226
+ };
154
227
  // 将数字还原
155
228
  const parser = (value: string) => {
156
229
  if (value) {
157
230
  prefix && (value = value.replace(prefix, ''));
158
231
  suffix && (value = value.replace(suffix, ''));
159
- kilobitSeparator && (value = value.replace(/,/g, ''));
232
+ kilobitSeparator && (value = value.replace(/,/g, ''));
160
233
  }
161
234
  return value;
162
- }
235
+ };
236
+
237
+ const finalValue =
238
+ unit && value && typeof value === 'string'
239
+ ? value.replace(unit, '')
240
+ : value;
241
+
163
242
  return (
164
- <div className={cx(`${ns}NumberControl`, className)}>
243
+ <div
244
+ className={cx(
245
+ `${ns}NumberControl`,
246
+ {
247
+ [`${ns}NumberControl--withUnit`]: unitOptions
248
+ },
249
+ className
250
+ )}
251
+ >
165
252
  <NumberInput
166
- value={value}
253
+ value={finalValue}
167
254
  step={step}
168
255
  max={this.filterNum(max)}
169
256
  min={this.filterNum(min)}
@@ -177,6 +264,14 @@ export default class NumberControl extends React.Component<NumberProps, any> {
177
264
  borderMode={borderMode}
178
265
  readOnly={readOnly}
179
266
  />
267
+ {unitOptions ? (
268
+ <Select
269
+ value={unit}
270
+ clearable={false}
271
+ options={this.state.unitOptions || []}
272
+ onChange={this.handleChangeUnit}
273
+ />
274
+ ) : null}
180
275
  </div>
181
276
  );
182
277
  }
@@ -7,6 +7,7 @@ import {FormItem, FormControlProps, FormBaseControl} from './Item';
7
7
  import InputRange from '../../components/Range';
8
8
  import {Icon} from '../../components/icons';
9
9
  import {FormOptionsControl} from './Options';
10
+ import {stripNumber} from '../../utils/tpl-builtin';
10
11
 
11
12
  /**
12
13
  * Range
@@ -205,7 +206,7 @@ export default class RangeControl extends React.PureComponent<
205
206
 
206
207
  handleChange(value: any) {
207
208
  this.setState({
208
- value: value,
209
+ value: stripNumber(value),
209
210
  minValue: value.min,
210
211
  maxValue: value.max
211
212
  });
@@ -253,6 +254,8 @@ export default class RangeControl extends React.PureComponent<
253
254
  min: value.min,
254
255
  max: value.max
255
256
  };
257
+ } else {
258
+ endValue = stripNumber(value);
256
259
  }
257
260
  const {onChange} = this.props;
258
261
  this.setState(
@@ -268,7 +271,7 @@ export default class RangeControl extends React.PureComponent<
268
271
 
269
272
  return typeof step !== 'number' || step >= 1 || step < 0
270
273
  ? 0
271
- : step.toString().split('.')[1].length;
274
+ : step.toString().split('.')[1]?.length;
272
275
  }
273
276
 
274
277
  getValue(value: any, type?: string) {
@@ -30,6 +30,26 @@ export interface TableControlSchema
30
30
  */
31
31
  addable?: boolean;
32
32
 
33
+ /**
34
+ * 可复制新增
35
+ */
36
+ copyable?: boolean;
37
+
38
+ /**
39
+ * 复制按钮文字
40
+ */
41
+ copyBtnLabel?: string;
42
+
43
+ /**
44
+ * 复制按钮图标
45
+ */
46
+ copyBtnIcon?: string;
47
+
48
+ /**
49
+ * 是否显示复制按钮
50
+ */
51
+ copyAddBtn?: boolean;
52
+
33
53
  /**
34
54
  * 是否可以拖拽排序
35
55
  */
@@ -41,12 +61,12 @@ export interface TableControlSchema
41
61
  addApi?: SchemaApi;
42
62
 
43
63
  /**
44
- * 新增按钮
64
+ * 新增按钮文字
45
65
  */
46
66
  addBtnLabel?: string;
47
67
 
48
68
  /**
49
- * 新增图标
69
+ * 新增按钮图标
50
70
  */
51
71
  addBtnIcon?: string;
52
72
 
@@ -73,12 +93,12 @@ export interface TableControlSchema
73
93
  /**
74
94
  * 更新按钮名称
75
95
  */
76
- updateBtnLabel?: string;
96
+ editBtnLabel?: string;
77
97
 
78
98
  /**
79
99
  * 更新按钮图标
80
100
  */
81
- updateBtnIcon?: string;
101
+ editBtnIcon?: string;
82
102
 
83
103
  /**
84
104
  * 确认按钮文字
@@ -172,7 +192,8 @@ export default class FormTable extends React.Component<TableProps, TableState> {
172
192
  placeholder: '空',
173
193
  scaffold: {},
174
194
  addBtnIcon: 'plus',
175
- updateBtnIcon: 'pencil',
195
+ copyBtnIcon: 'copy',
196
+ editBtnIcon: 'pencil',
176
197
  deleteBtnIcon: 'minus',
177
198
  confirmBtnIcon: 'check',
178
199
  cancelBtnIcon: 'close',
@@ -188,6 +209,7 @@ export default class FormTable extends React.Component<TableProps, TableState> {
188
209
  'showAddBtn',
189
210
  'addable',
190
211
  'removable',
212
+ 'copyable',
191
213
  'editable',
192
214
  'addApi',
193
215
  'updateApi',
@@ -423,6 +445,26 @@ export default class FormTable extends React.Component<TableProps, TableState> {
423
445
  return onAction && onAction(action, ctx, ...rest);
424
446
  }
425
447
 
448
+ copyItem(index: number) {
449
+ const {needConfirm} = this.props;
450
+ const items = this.state.items.concat();
451
+
452
+ items.splice(index + 1, 0, items[index]);
453
+ index = Math.min(index + 1, items.length - 1);
454
+ this.setState(
455
+ {
456
+ items
457
+ },
458
+ () => {
459
+ if (needConfirm === false) {
460
+ this.emitValue();
461
+ } else {
462
+ this.startEdit(index, true);
463
+ }
464
+ }
465
+ );
466
+ }
467
+
426
468
  addItem(index: number) {
427
469
  const {needConfirm, scaffold, columns} = this.props;
428
470
  const items = this.state.items.concat();
@@ -653,6 +695,38 @@ export default class FormTable extends React.Component<TableProps, TableState> {
653
695
  });
654
696
  }
655
697
 
698
+ if (props.copyable && props.showCopyBtn !== false) {
699
+ btns.push({
700
+ children: ({
701
+ key,
702
+ rowIndex,
703
+ offset
704
+ }: {
705
+ key: any;
706
+ rowIndex: number;
707
+ offset: number;
708
+ }) =>
709
+ ~this.state.editIndex && needConfirm !== false ? null : (
710
+ <Button
711
+ classPrefix={ns}
712
+ size="sm"
713
+ key={key}
714
+ level="link"
715
+ tooltip={__('Table.copyRow')}
716
+ tooltipContainer={
717
+ env && env.getModalContainer ? env.getModalContainer : undefined
718
+ }
719
+ onClick={this.copyItem.bind(this, rowIndex + offset, undefined)}
720
+ >
721
+ {props.copyBtnLabel ? <span>{props.copyBtnLabel}</span> : null}
722
+ {props.copyBtnIcon ? (
723
+ <Icon icon={props.copyBtnIcon} className="icon" />
724
+ ) : null}
725
+ </Button>
726
+ )
727
+ });
728
+ }
729
+
656
730
  if (props.needConfirm === false) {
657
731
  columns = columns.map(column => {
658
732
  const quickEdit = column.quickEdit;
@@ -716,11 +790,16 @@ export default class FormTable extends React.Component<TableProps, TableState> {
716
790
  }
717
791
  onClick={() => this.startEdit(rowIndex + offset)}
718
792
  >
719
- {props.updateBtnLabel ? (
720
- <span>{props.updateBtnLabel}</span>
793
+ {props.updateBtnLabel || props.editBtnLabel ? (
794
+ <span>{props.updateBtnLabel || props.editBtnLabel}</span>
721
795
  ) : null}
722
- {props.updateBtnIcon ? (
723
- <Icon icon={props.updateBtnIcon} className="icon" />
796
+ {/* 兼容之前的写法 */}
797
+ {typeof props.updateBtnIcon !== 'undefined' ? (
798
+ props.updateBtnIcon ? (
799
+ <Icon icon={props.updateBtnIcon} className="icon" />
800
+ ) : null
801
+ ) : props.editBtnIcon ? (
802
+ <Icon icon={props.editBtnIcon} className="icon" />
724
803
  ) : null}
725
804
  </Button>
726
805
  )
@@ -602,7 +602,7 @@ export default class NestedSelectControl extends React.Component<
602
602
  return (
603
603
  <Overlay
604
604
  target={this.getTarget}
605
- container={popOverContainer || findDOMNode(this)?.parentElement}
605
+ container={popOverContainer || (() => findDOMNode(this))}
606
606
  placement={'auto'}
607
607
  show
608
608
  >
@@ -272,6 +272,7 @@ export function registerOptionsControl(config: OptionsConfig) {
272
272
 
273
273
  reaction?: () => void;
274
274
  input: any;
275
+ mounted = false;
275
276
 
276
277
  constructor(props: OptionsProps) {
277
278
  super(props);
@@ -303,7 +304,7 @@ export function registerOptionsControl(config: OptionsConfig) {
303
304
 
304
305
  this.reaction = reaction(
305
306
  () => JSON.stringify([formItem.loading, formItem.filteredOptions]),
306
- () => this.forceUpdate()
307
+ () => this.mounted && this.forceUpdate()
307
308
  );
308
309
  // 默认全选。这里会和默认值\回填值逻辑冲突,所以如果有配置source则不执行默认全选
309
310
  if (
@@ -340,6 +341,7 @@ export function registerOptionsControl(config: OptionsConfig) {
340
341
  }
341
342
 
342
343
  componentDidMount() {
344
+ this.mounted = true;
343
345
  this.normalizeValue();
344
346
 
345
347
  if (this.props.value) {
@@ -1514,23 +1514,8 @@ export default class Form extends React.Component<FormProps, object> {
1514
1514
  formStore
1515
1515
  } = this.props;
1516
1516
 
1517
- // trace(true);
1518
- // console.log('Form');
1519
-
1520
1517
  let body: JSX.Element = this.renderBody();
1521
1518
 
1522
- // props有formStore 说明是嵌套表单 || 不允许在表单的按钮组中再直接套表单
1523
- if (formStore) {
1524
- body = (
1525
- <>
1526
- <Alert level="warning" showCloseButton>
1527
- <p>{__('Form.nestedError')}</p>
1528
- </Alert>
1529
- {body}
1530
- </>
1531
- );
1532
- }
1533
-
1534
1519
  if (wrapWithPanel) {
1535
1520
  body = render(
1536
1521
  'body',
@@ -506,8 +506,8 @@ export function wrapControl<
506
506
 
507
507
  if (
508
508
  // 如果配置了 minLength 或者 maxLength 就切成及时验证
509
- // (typeof maxLength && maxLength) ||
510
- // (typeof minLength && minLength) ||
509
+ (typeof maxLength && maxLength) ||
510
+ (typeof minLength && minLength) ||
511
511
  validateOnChange === true ||
512
512
  (validateOnChange !== false && (formSubmited || validated))
513
513
  ) {
@@ -97,6 +97,15 @@ export class JSONField extends React.Component<JSONProps, object> {
97
97
  }
98
98
  }
99
99
 
100
+ let jsonThemeValue = jsonTheme;
101
+ if (isPureVariable(jsonTheme)) {
102
+ jsonThemeValue = resolveVariableAndFilter(
103
+ jsonTheme,
104
+ this.props.data,
105
+ '| raw'
106
+ );
107
+ }
108
+
100
109
  // JsonView 只支持对象,所以不是对象格式需要转成对象格式。
101
110
  if (data && ~['string', 'number'].indexOf(typeof data)) {
102
111
  data = {
@@ -112,7 +121,7 @@ export class JSONField extends React.Component<JSONProps, object> {
112
121
  <JsonView
113
122
  name={false}
114
123
  src={data}
115
- theme={(jsonTheme as any) ?? 'rjv-default'}
124
+ theme={(jsonThemeValue as any) ?? 'rjv-default'}
116
125
  shouldCollapse={this.shouldExpandNode}
117
126
  enableClipboard={false}
118
127
  iconStyle="square"
@@ -15,7 +15,8 @@ import {
15
15
  difference,
16
16
  isVisible,
17
17
  isDisabled,
18
- noop
18
+ noop,
19
+ isClickOnInput
19
20
  } from '../utils/helper';
20
21
  import {
21
22
  isPureVariable,
@@ -215,6 +216,11 @@ export interface ListSchema extends BaseSchema {
215
216
  * 大小
216
217
  */
217
218
  size?: 'sm' | 'base';
219
+
220
+ /**
221
+ * 点击列表项的行为
222
+ */
223
+ itemAction?: ActionSchema;
218
224
  }
219
225
 
220
226
  export interface Column {
@@ -919,6 +925,7 @@ export default class List extends React.Component<ListProps, object> {
919
925
  onAction,
920
926
  hideCheckToggler,
921
927
  checkOnItemClick,
928
+ itemAction,
922
929
  affixHeader,
923
930
  classnames: cx,
924
931
  size,
@@ -969,6 +976,7 @@ export default class List extends React.Component<ListProps, object> {
969
976
  itemIndex: item.index,
970
977
  hideCheckToggler,
971
978
  checkOnItemClick,
979
+ itemAction,
972
980
  selected: item.checked,
973
981
  onCheck: this.handleCheck,
974
982
  dragging: store.dragging,
@@ -1018,6 +1026,7 @@ export interface ListItemProps
1018
1026
  itemIndex?: number;
1019
1027
  checkable?: boolean;
1020
1028
  checkOnItemClick?: boolean;
1029
+ itemAction?: ActionSchema;
1021
1030
  }
1022
1031
  export class ListItem extends React.Component<ListItemProps> {
1023
1032
  static defaultProps: Partial<ListItemProps> = {
@@ -1025,7 +1034,11 @@ export class ListItem extends React.Component<ListItemProps> {
1025
1034
  titleClassName: 'h5'
1026
1035
  };
1027
1036
 
1028
- static propsList: Array<string> = ['avatarClassName', 'titleClassName'];
1037
+ static propsList: Array<string> = [
1038
+ 'avatarClassName',
1039
+ 'titleClassName',
1040
+ 'itemAction'
1041
+ ];
1029
1042
 
1030
1043
  constructor(props: ListItemProps) {
1031
1044
  super(props);
@@ -1037,20 +1050,15 @@ export class ListItem extends React.Component<ListItemProps> {
1037
1050
  }
1038
1051
 
1039
1052
  handleClick(e: React.MouseEvent<HTMLDivElement>) {
1040
- const target: HTMLElement = e.target as HTMLElement;
1041
- const ns = this.props.classPrefix;
1042
- let formItem;
1043
-
1044
- if (
1045
- !e.currentTarget.contains(target) ||
1046
- ~['INPUT', 'TEXTAREA'].indexOf(target.tagName) ||
1047
- ((formItem = target.closest(`button, a, .${ns}Form-item`)) &&
1048
- e.currentTarget.contains(formItem))
1049
- ) {
1053
+ if (isClickOnInput(e)) {
1054
+ return;
1055
+ }
1056
+ const {itemAction, onAction, item} = this.props;
1057
+ if (itemAction) {
1058
+ onAction && onAction(e, itemAction, item?.data);
1050
1059
  return;
1051
1060
  }
1052
1061
 
1053
- const item = this.props.item;
1054
1062
  this.props.onCheck && this.props.onCheck(item);
1055
1063
  }
1056
1064
 
@@ -1160,10 +1168,7 @@ export class ListItem extends React.Component<ListItemProps> {
1160
1168
  ))}
1161
1169
  </div>
1162
1170
  );
1163
- } else */ if (
1164
- typeof node === 'string' ||
1165
- typeof node === 'number'
1166
- ) {
1171
+ } else */ if (typeof node === 'string' || typeof node === 'number') {
1167
1172
  return render(region, node, {key}) as JSX.Element;
1168
1173
  }
1169
1174
 
@@ -1261,7 +1266,8 @@ export class ListItem extends React.Component<ListItemProps> {
1261
1266
  render,
1262
1267
  checkable,
1263
1268
  classnames: cx,
1264
- actionsPosition
1269
+ actionsPosition,
1270
+ itemAction
1265
1271
  } = this.props;
1266
1272
 
1267
1273
  const avatar = filter(avatarTpl, data);
@@ -1271,9 +1277,16 @@ export class ListItem extends React.Component<ListItemProps> {
1271
1277
 
1272
1278
  return (
1273
1279
  <div
1274
- onClick={checkOnItemClick && checkable ? this.handleClick : undefined}
1280
+ onClick={
1281
+ (checkOnItemClick && checkable) || itemAction
1282
+ ? this.handleClick
1283
+ : undefined
1284
+ }
1275
1285
  className={cx(
1276
1286
  `ListItem ListItem--actions-at-${actionsPosition || 'right'}`,
1287
+ {
1288
+ 'ListItem--hasItemAction': itemAction
1289
+ },
1277
1290
  className
1278
1291
  )}
1279
1292
  >
@@ -29,6 +29,8 @@ import {
29
29
  } from '../Schema';
30
30
  import {SchemaRemark} from './Remark';
31
31
  import {onAction} from 'mobx-state-tree';
32
+ import mapValues from 'lodash/mapValues';
33
+ import {resolveVariable} from '../utils/tpl-builtin';
32
34
 
33
35
  /**
34
36
  * 样式属性名及值
@@ -175,6 +177,13 @@ export interface PageSchema extends BaseSchema {
175
177
  * 如果配置了,以配置为主。
176
178
  */
177
179
  regions?: Array<'aside' | 'body' | 'toolbar' | 'header'>;
180
+
181
+ /**
182
+ * 自定义样式
183
+ */
184
+ style?: {
185
+ [propName: string]: any;
186
+ };
178
187
  }
179
188
 
180
189
  export interface PageProps
@@ -362,6 +371,8 @@ export default class Page extends React.Component<PageProps> {
362
371
  JSON.stringify(props.cssVars) !== JSON.stringify(prevProps.cssVars)
363
372
  ) {
364
373
  this.updateVarStyle();
374
+ } else if (props.defaultData !== prevProps.defaultData) {
375
+ store.reInitData(props.defaultData);
365
376
  }
366
377
  }
367
378
 
@@ -645,6 +656,8 @@ export default class Page extends React.Component<PageProps> {
645
656
  showErrorMsg,
646
657
  initApi,
647
658
  regions,
659
+ style,
660
+ data,
648
661
  translate: __
649
662
  } = this.props;
650
663
 
@@ -659,10 +672,16 @@ export default class Page extends React.Component<PageProps> {
659
672
  ? ~regions.indexOf('aside')
660
673
  : aside && (!Array.isArray(aside) || aside.length);
661
674
 
675
+ let styleVar =
676
+ typeof style === 'string'
677
+ ? resolveVariable(style, data) || {}
678
+ : mapValues(style, s => resolveVariable(s, data) || s);
679
+
662
680
  return (
663
681
  <div
664
682
  className={cx(`Page`, hasAside ? `Page--withSidebar` : '', className)}
665
683
  onClick={this.handleClick}
684
+ style={styleVar}
666
685
  >
667
686
  {hasAside ? (
668
687
  <div className={cx(`Page-aside`, asideClassName)}>