BaseForm.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. * <<
  3. * Davinci
  4. * ==
  5. * Copyright (C) 2016 - 2017 EDP
  6. * ==
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * >>
  19. */
  20. import React, { FC, useCallback, memo } from 'react'
  21. import {
  22. Form,
  23. Row,
  24. Col,
  25. Input,
  26. InputNumber,
  27. Radio,
  28. Select,
  29. Divider
  30. } from 'antd'
  31. import { WrappedFormUtils } from 'antd/lib/form/Form'
  32. import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox'
  33. import { RadioChangeEvent } from 'antd/lib/radio'
  34. import Condition from './Condition'
  35. import {
  36. ControlTypesLocale,
  37. ControlTypes,
  38. DatePickerFormatsLocale,
  39. ControlVisibilityTypes,
  40. SHOULD_LOAD_OPTIONS
  41. } from '../../constants'
  42. import { IControl } from '../../types'
  43. import { getDatePickerFormatOptions } from '../../util'
  44. import utilStyles from 'assets/less/util.less'
  45. const FormItem = Form.Item
  46. const Option = Select.Option
  47. const RadioGroup = Radio.Group
  48. const RadioButton = Radio.Button
  49. interface IBaseFormProps {
  50. form: WrappedFormUtils
  51. controls: IControl[]
  52. controlBase: Omit<IControl, 'relatedItems' | 'relatedViews'>
  53. onControlTypeChange: (value) => void
  54. onMultipleSettingChange: (e: CheckboxChangeEvent) => void
  55. onSliderPropChange: (min: number, max: number, step: number) => void
  56. onCommonPropChange: (propName: string, value) => void
  57. }
  58. const BaseForm: FC<IBaseFormProps> = ({
  59. form,
  60. controls,
  61. controlBase,
  62. onControlTypeChange,
  63. onMultipleSettingChange,
  64. onSliderPropChange,
  65. onCommonPropChange
  66. }) => {
  67. const { getFieldDecorator } = form
  68. const { key, type, multiple, visibility } = controlBase
  69. const datePickerFormatOptions = getDatePickerFormatOptions(type, multiple)
  70. const colSpan = { xxl: 12, xl: 18 }
  71. const itemCols = {
  72. labelCol: { span: 8 },
  73. wrapperCol: { span: 12 }
  74. }
  75. const radioTypeChange = useCallback(
  76. (e: RadioChangeEvent) => {
  77. onCommonPropChange('radioType', e.target.value)
  78. },
  79. [onCommonPropChange]
  80. )
  81. const visibilityChange = useCallback(
  82. (e: RadioChangeEvent) => {
  83. onCommonPropChange('visibility', e.target.value)
  84. },
  85. [onCommonPropChange]
  86. )
  87. const minChange = useCallback(
  88. (value) => {
  89. const { max, step } = form.getFieldsValue()
  90. onSliderPropChange(value, max, step)
  91. },
  92. [form, onSliderPropChange]
  93. )
  94. const maxChange = useCallback(
  95. (value) => {
  96. const { min, step } = form.getFieldsValue()
  97. onSliderPropChange(min, value, step)
  98. },
  99. [form, onSliderPropChange]
  100. )
  101. const stepChange = useCallback(
  102. (value) => {
  103. const { min, max } = form.getFieldsValue()
  104. onSliderPropChange(min, max, value)
  105. },
  106. [form, onSliderPropChange]
  107. )
  108. const labelChange = useCallback(
  109. (e: CheckboxChangeEvent) => {
  110. onCommonPropChange('label', e.target.checked)
  111. },
  112. [onCommonPropChange]
  113. )
  114. const minValidator = useCallback(
  115. (rule, value, callback) => {
  116. if (typeof value === 'number') {
  117. const max = form.getFieldValue('max')
  118. if (typeof max === 'number' && value > max) {
  119. callback('最小值不能大于最大值')
  120. } else {
  121. callback()
  122. }
  123. } else {
  124. callback()
  125. }
  126. },
  127. [form]
  128. )
  129. const maxValidator = useCallback(
  130. (rule, value, callback) => {
  131. form.validateFields(['min'], { force: true }, () => void 0)
  132. callback()
  133. },
  134. [form]
  135. )
  136. const getDateFormatComponent = useCallback(
  137. () => (
  138. <Row key="dateFormat">
  139. <Col {...colSpan}>
  140. <FormItem label="日期格式" {...itemCols}>
  141. {getFieldDecorator(
  142. 'dateFormat',
  143. {}
  144. )(
  145. <Select>
  146. {datePickerFormatOptions.map((format) => {
  147. const title = DatePickerFormatsLocale[format]
  148. return (
  149. <Option key={title} value={format}>
  150. {title}
  151. </Option>
  152. )
  153. })}
  154. </Select>
  155. )}
  156. </FormItem>
  157. </Col>
  158. </Row>
  159. ),
  160. [datePickerFormatOptions]
  161. )
  162. const getMultipleComponent = useCallback(
  163. () => (
  164. <Row key="multiple">
  165. <Col {...colSpan}>
  166. <FormItem label="多选" {...itemCols}>
  167. {getFieldDecorator('multiple', { valuePropName: 'checked' })(
  168. <Checkbox onChange={onMultipleSettingChange} />
  169. )}
  170. </FormItem>
  171. </Col>
  172. </Row>
  173. ),
  174. [onMultipleSettingChange]
  175. )
  176. let controlPropComponents
  177. switch (type) {
  178. case ControlTypes.Date:
  179. controlPropComponents = [getDateFormatComponent(), getMultipleComponent()]
  180. break
  181. case ControlTypes.DateRange:
  182. controlPropComponents = [getDateFormatComponent()]
  183. break
  184. case ControlTypes.Select:
  185. case ControlTypes.TreeSelect:
  186. controlPropComponents = [getMultipleComponent()]
  187. break
  188. case ControlTypes.Radio:
  189. controlPropComponents = (
  190. <Row key="radioType">
  191. <Col {...colSpan}>
  192. <FormItem label="按钮样式" {...itemCols}>
  193. {getFieldDecorator(
  194. 'radioType',
  195. {}
  196. )(
  197. <RadioGroup onChange={radioTypeChange}>
  198. <RadioButton value="normal">常规</RadioButton>
  199. <RadioButton value="button">按钮</RadioButton>
  200. </RadioGroup>
  201. )}
  202. </FormItem>
  203. </Col>
  204. </Row>
  205. )
  206. break
  207. case ControlTypes.Slider:
  208. controlPropComponents = (
  209. <>
  210. <Row key="min">
  211. <Col {...colSpan}>
  212. <FormItem label="最小值" {...itemCols}>
  213. {getFieldDecorator('min', {
  214. rules: [
  215. { required: true, message: '最小值不能为空' },
  216. { validator: minValidator }
  217. ]
  218. })(<InputNumber onChange={minChange} />)}
  219. </FormItem>
  220. </Col>
  221. </Row>
  222. <Row key="max">
  223. <Col {...colSpan}>
  224. <FormItem label="最大值" {...itemCols}>
  225. {getFieldDecorator('max', {
  226. rules: [
  227. { required: true, message: '最大值不能为空' },
  228. { validator: maxValidator }
  229. ]
  230. })(<InputNumber onChange={maxChange} />)}
  231. </FormItem>
  232. </Col>
  233. </Row>
  234. <Row key="step">
  235. <Col {...colSpan}>
  236. <FormItem label="步长" {...itemCols}>
  237. {getFieldDecorator('step', { initialValue: 1 })(
  238. <InputNumber min={1} onChange={stepChange} />
  239. )}
  240. </FormItem>
  241. </Col>
  242. </Row>
  243. <Row key="label">
  244. <Col {...colSpan}>
  245. <FormItem label="显示标签" {...itemCols}>
  246. {getFieldDecorator('label', { valuePropName: 'checked' })(
  247. <Checkbox onChange={labelChange} />
  248. )}
  249. </FormItem>
  250. </Col>
  251. </Row>
  252. </>
  253. )
  254. break
  255. }
  256. const selectTypeControls = controls.filter(
  257. (c) => c.type === ControlTypes.Select && c.key !== key
  258. )
  259. return (
  260. <>
  261. <Divider orientation="left">控制器配置</Divider>
  262. <Row>
  263. <Col {...colSpan}>
  264. <FormItem className={utilStyles.hide}>
  265. {getFieldDecorator('key', {})(<Input />)}
  266. </FormItem>
  267. <FormItem label="类型" {...itemCols}>
  268. {getFieldDecorator(
  269. 'type',
  270. {}
  271. )(
  272. <Select onChange={onControlTypeChange}>
  273. {Object.values(ControlTypes).map((controlType) => (
  274. <Option key={controlType} value={controlType}>
  275. {ControlTypesLocale[controlType]}
  276. </Option>
  277. ))}
  278. </Select>
  279. )}
  280. </FormItem>
  281. </Col>
  282. </Row>
  283. {controlPropComponents}
  284. {SHOULD_LOAD_OPTIONS[type] && (
  285. <>
  286. <Row key="cache">
  287. <Col {...colSpan}>
  288. <FormItem label="缓存" {...itemCols}>
  289. {getFieldDecorator(
  290. 'cache',
  291. {}
  292. )(
  293. <RadioGroup>
  294. <RadioButton value={true}>开启</RadioButton>
  295. <RadioButton value={false}>关闭</RadioButton>
  296. </RadioGroup>
  297. )}
  298. </FormItem>
  299. </Col>
  300. </Row>
  301. <Row key="expired">
  302. <Col {...colSpan}>
  303. <FormItem label="有效期(秒)" {...itemCols}>
  304. {getFieldDecorator('expired', {})(<InputNumber />)}
  305. </FormItem>
  306. </Col>
  307. </Row>
  308. </>
  309. )}
  310. <Row>
  311. <Col {...colSpan}>
  312. <FormItem label="宽度" {...itemCols}>
  313. {getFieldDecorator(
  314. 'width',
  315. {}
  316. )(
  317. <Select>
  318. <Option value={0}>自动适应</Option>
  319. <Option value={24}>100%</Option>
  320. <Option value={12}>50%</Option>
  321. <Option value={8}>33.33% (1/3)</Option>
  322. <Option value={6}>25% (1/4)</Option>
  323. <Option value={4}>16.67% (1/6)</Option>
  324. <Option value={3}>12.5% (1/8)</Option>
  325. <Option value={2}>8.33% (1/12)</Option>
  326. </Select>
  327. )}
  328. </FormItem>
  329. </Col>
  330. </Row>
  331. <Row>
  332. <Col {...colSpan}>
  333. <FormItem label="是否可见" {...itemCols}>
  334. {getFieldDecorator(
  335. 'visibility',
  336. {}
  337. )(
  338. <RadioGroup onChange={visibilityChange}>
  339. <RadioButton value={ControlVisibilityTypes.Visible}>
  340. 显示
  341. </RadioButton>
  342. <RadioButton value={ControlVisibilityTypes.Hidden}>
  343. 隐藏
  344. </RadioButton>
  345. <RadioButton value={ControlVisibilityTypes.Conditional}>
  346. 条件
  347. </RadioButton>
  348. </RadioGroup>
  349. )}
  350. </FormItem>
  351. </Col>
  352. </Row>
  353. {visibility === ControlVisibilityTypes.Conditional && (
  354. <Row>
  355. <Col {...colSpan}>
  356. <FormItem label="显示条件" {...itemCols}>
  357. {getFieldDecorator(
  358. 'conditions[0]',
  359. {}
  360. )(<Condition controls={selectTypeControls} />)}
  361. </FormItem>
  362. </Col>
  363. </Row>
  364. )}
  365. </>
  366. )
  367. }
  368. export default memo(BaseForm)