GaugeSection.tsx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  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 from 'react'
  21. import { Row, Col, Input, Checkbox, Select, InputNumber } from 'antd'
  22. const Option = Select.Option
  23. import ColorPicker from 'app/components/ColorPicker'
  24. import {
  25. PIVOT_CHART_FONT_FAMILIES,
  26. PIVOT_CHART_LINE_STYLES,
  27. PIVOT_CHART_FONT_SIZES,
  28. CHART_LABEL_POSITIONS,
  29. CHART_PIE_LABEL_POSITIONS,
  30. CHART_FUNNEL_LABEL_POSITIONS
  31. } from 'app/globalConstants'
  32. const styles = require('../Workbench.less')
  33. export interface IGaugeConfig {
  34. radius: number
  35. splitNumber: number
  36. startAngle: number
  37. endAngle: number
  38. clockwise: boolean
  39. max: number
  40. prefix: string
  41. suffix: string
  42. showTitle: boolean
  43. titleFontFamily: string
  44. titleFontSize: string
  45. titleColor: string
  46. titleOffsetLeft: number
  47. titleOffsetTop: number
  48. showDetail: boolean
  49. detailFontFamily: string
  50. detailFontSize: string
  51. detailColor: string
  52. detailOffsetLeft: number
  53. detailOffsetTop: number
  54. showPointer: boolean
  55. pointerLength: number
  56. pointerWidth: number
  57. customPointerColor: boolean
  58. pointerColor: string
  59. pointerBorderStyle: string
  60. pointerBorderWidth: number
  61. pointerBorderColor: string
  62. axisLineSize: number
  63. axisLineColor: string
  64. showAxisTick: boolean
  65. showAxisLabel: boolean
  66. axisLabelDistance: number
  67. axisLabelFontFamily: string
  68. axisLabelFontSize: string
  69. axisLabelColor: string
  70. showSplitLine: boolean
  71. splitLineLength: number
  72. splitLineSize: string
  73. splitLineStyle: string
  74. splitLineColor: string
  75. }
  76. interface IGaugeSectionProps {
  77. title: string
  78. config: IGaugeConfig
  79. onChange: (prop: string, value: any) => void
  80. }
  81. export class GaugeSection extends React.PureComponent<IGaugeSectionProps, {}> {
  82. private inputChange = (prop) => (e: React.ChangeEvent<HTMLInputElement>) => {
  83. this.props.onChange(prop, e.target.value)
  84. }
  85. private checkboxChange = (prop) => (e) => {
  86. this.props.onChange(prop, e.target.checked)
  87. }
  88. private selectChange = (prop) => (value) => {
  89. this.props.onChange(prop, value)
  90. }
  91. private colorChange = (prop) => (color) => {
  92. this.props.onChange(prop, color)
  93. }
  94. private inputNumberChange = (prop) => (value) => {
  95. this.props.onChange(prop, value)
  96. }
  97. private percentFormatter = (value) => `${value}%`
  98. private percentParser = (value) => value.replace('%', '')
  99. private pixelFormatter = (value) => `${value}px`
  100. private pixelParser = (value) => value.replace(/[p|x]+/, '')
  101. private lineStyles = PIVOT_CHART_LINE_STYLES.map((l) => (
  102. <Option key={l.value} value={l.value}>
  103. {l.name}
  104. </Option>
  105. ))
  106. public render () {
  107. const { title, config } = this.props
  108. const {
  109. radius,
  110. splitNumber,
  111. startAngle,
  112. endAngle,
  113. clockwise,
  114. max,
  115. prefix,
  116. suffix,
  117. showTitle,
  118. titleFontFamily,
  119. titleFontSize,
  120. titleColor,
  121. titleOffsetLeft,
  122. titleOffsetTop,
  123. showDetail,
  124. detailFontFamily,
  125. detailFontSize,
  126. detailColor,
  127. detailOffsetLeft,
  128. detailOffsetTop,
  129. showPointer,
  130. pointerLength,
  131. pointerWidth,
  132. customPointerColor,
  133. pointerColor,
  134. pointerBorderStyle,
  135. pointerBorderWidth,
  136. pointerBorderColor,
  137. axisLineSize,
  138. axisLineColor,
  139. showAxisTick,
  140. showAxisLabel,
  141. axisLabelDistance,
  142. axisLabelFontFamily,
  143. axisLabelFontSize,
  144. axisLabelColor,
  145. showSplitLine,
  146. splitLineLength,
  147. splitLineSize,
  148. splitLineStyle,
  149. splitLineColor
  150. } = config
  151. const fontFamilies = PIVOT_CHART_FONT_FAMILIES.map((f) => (
  152. <Option key={f.value} value={f.value}>{f.name}</Option>
  153. ))
  154. const fontSizes = PIVOT_CHART_FONT_SIZES.map((f) => (
  155. <Option key={`${f}`} value={`${f}`}>{f}</Option>
  156. ))
  157. return (
  158. <>
  159. <div className={styles.paneBlock}>
  160. <h4>{title}</h4>
  161. <div className={styles.blockBody}>
  162. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  163. <Col span={6}>目标值</Col>
  164. <Col span={10}>
  165. <InputNumber
  166. className={styles.blockElm}
  167. value={max}
  168. onChange={this.inputNumberChange('max')}
  169. />
  170. </Col>
  171. </Row>
  172. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  173. <Col span={6}>前缀</Col>
  174. <Col span={6}>
  175. <Input
  176. className={styles.blockElm}
  177. value={prefix}
  178. onChange={this.inputChange('prefix')}
  179. />
  180. </Col>
  181. <Col span={6}>后缀</Col>
  182. <Col span={6}>
  183. <Input
  184. className={styles.blockElm}
  185. value={suffix}
  186. onChange={this.inputChange('suffix')}
  187. />
  188. </Col>
  189. </Row>
  190. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  191. <Col span={6}>半径</Col>
  192. <Col span={6}>
  193. <InputNumber
  194. className={styles.blockElm}
  195. value={radius}
  196. onChange={this.inputNumberChange('radius')}
  197. formatter={this.percentFormatter}
  198. parser={this.percentParser}
  199. />
  200. </Col>
  201. <Col span={6}>分隔段数</Col>
  202. <Col span={6}>
  203. <InputNumber
  204. className={styles.blockElm}
  205. value={splitNumber}
  206. min={1}
  207. onChange={this.inputNumberChange('splitNumber')}
  208. />
  209. </Col>
  210. </Row>
  211. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  212. <Col span={6}>起始角度</Col>
  213. <Col span={6}>
  214. <InputNumber
  215. className={styles.blockElm}
  216. value={startAngle}
  217. onChange={this.inputNumberChange('startAngle')}
  218. />
  219. </Col>
  220. <Col span={6}>结束角度</Col>
  221. <Col span={6}>
  222. <InputNumber
  223. className={styles.blockElm}
  224. value={endAngle}
  225. onChange={this.inputNumberChange('endAngle')}
  226. />
  227. </Col>
  228. </Row>
  229. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  230. <Col span={10}>
  231. <Checkbox
  232. checked={clockwise}
  233. onChange={this.checkboxChange('clockwise')}
  234. >
  235. 顺时针
  236. </Checkbox>
  237. </Col>
  238. </Row>
  239. </div>
  240. </div>
  241. <div className={styles.paneBlock}>
  242. <h4>标题</h4>
  243. <div className={styles.blockBody}>
  244. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  245. <Col span={10}>
  246. <Checkbox
  247. checked={showTitle}
  248. onChange={this.checkboxChange('showTitle')}
  249. >
  250. 显示标题
  251. </Checkbox>
  252. </Col>
  253. </Row>
  254. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  255. <Col span={10}>
  256. <Select
  257. placeholder="字体"
  258. className={styles.blockElm}
  259. value={titleFontFamily}
  260. onChange={this.selectChange('titleFontFamily')}
  261. >
  262. {fontFamilies}
  263. </Select>
  264. </Col>
  265. <Col span={10}>
  266. <Select
  267. placeholder="文字大小"
  268. className={styles.blockElm}
  269. value={titleFontSize}
  270. onChange={this.selectChange('titleFontSize')}
  271. >
  272. {fontSizes}
  273. </Select>
  274. </Col>
  275. <Col span={4}>
  276. <ColorPicker
  277. value={titleColor}
  278. onChange={this.colorChange('titleColor')}
  279. />
  280. </Col>
  281. </Row>
  282. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  283. <Col span={6}>距离左侧</Col>
  284. <Col span={12}>
  285. <InputNumber
  286. className={styles.blockElm}
  287. value={titleOffsetLeft}
  288. onChange={this.inputNumberChange('titleOffsetLeft')}
  289. formatter={this.percentFormatter}
  290. parser={this.percentParser}
  291. />
  292. </Col>
  293. </Row>
  294. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  295. <Col span={6}>距离顶部</Col>
  296. <Col span={12}>
  297. <InputNumber
  298. className={styles.blockElm}
  299. value={titleOffsetTop}
  300. onChange={this.inputNumberChange('titleOffsetTop')}
  301. formatter={this.percentFormatter}
  302. parser={this.percentParser}
  303. />
  304. </Col>
  305. </Row>
  306. </div>
  307. </div>
  308. <div className={styles.paneBlock}>
  309. <h4>数据</h4>
  310. <div className={styles.blockBody}>
  311. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  312. <Col span={10}>
  313. <Checkbox
  314. checked={showDetail}
  315. onChange={this.checkboxChange('showDetail')}
  316. >
  317. 显示数据
  318. </Checkbox>
  319. </Col>
  320. </Row>
  321. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  322. <Col span={10}>
  323. <Select
  324. placeholder="字体"
  325. className={styles.blockElm}
  326. value={detailFontFamily}
  327. onChange={this.selectChange('detailFontFamily')}
  328. >
  329. {fontFamilies}
  330. </Select>
  331. </Col>
  332. <Col span={10}>
  333. <Select
  334. placeholder="文字大小"
  335. className={styles.blockElm}
  336. value={detailFontSize}
  337. onChange={this.selectChange('detailFontSize')}
  338. >
  339. {fontSizes}
  340. </Select>
  341. </Col>
  342. <Col span={4}>
  343. <ColorPicker
  344. value={detailColor}
  345. onChange={this.colorChange('detailColor')}
  346. />
  347. </Col>
  348. </Row>
  349. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  350. <Col span={6}>距离左侧</Col>
  351. <Col span={12}>
  352. <InputNumber
  353. className={styles.blockElm}
  354. value={detailOffsetLeft}
  355. onChange={this.inputNumberChange('detailOffsetLeft')}
  356. formatter={this.percentFormatter}
  357. parser={this.percentParser}
  358. />
  359. </Col>
  360. </Row>
  361. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  362. <Col span={6}>距离顶部</Col>
  363. <Col span={12}>
  364. <InputNumber
  365. className={styles.blockElm}
  366. value={detailOffsetTop}
  367. onChange={this.inputNumberChange('detailOffsetTop')}
  368. formatter={this.percentFormatter}
  369. parser={this.percentParser}
  370. />
  371. </Col>
  372. </Row>
  373. </div>
  374. </div>
  375. <div className={styles.paneBlock}>
  376. <h4>指针</h4>
  377. <div className={styles.blockBody}>
  378. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  379. <Col span={10}>
  380. <Checkbox
  381. checked={showPointer}
  382. onChange={this.checkboxChange('showPointer')}
  383. >
  384. 显示指针
  385. </Checkbox>
  386. </Col>
  387. <Col span={10}>
  388. <Checkbox
  389. checked={customPointerColor}
  390. onChange={this.checkboxChange('customPointerColor')}
  391. >
  392. 自定颜色
  393. </Checkbox>
  394. </Col>
  395. {
  396. customPointerColor && (
  397. <Col span={4}>
  398. <ColorPicker
  399. value={pointerColor}
  400. onChange={this.colorChange('pointerColor')}
  401. />
  402. </Col>
  403. )
  404. }
  405. </Row>
  406. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  407. <Col span={4}>长度</Col>
  408. <Col span={8}>
  409. <InputNumber
  410. className={styles.blockElm}
  411. value={pointerLength}
  412. onChange={this.inputNumberChange('pointerLength')}
  413. formatter={this.percentFormatter}
  414. parser={this.percentParser}
  415. />
  416. </Col>
  417. <Col span={4}>粗细</Col>
  418. <Col span={8}>
  419. <InputNumber
  420. className={styles.blockElm}
  421. value={pointerWidth}
  422. onChange={this.inputNumberChange('pointerWidth')}
  423. formatter={this.pixelFormatter}
  424. parser={this.pixelParser}
  425. />
  426. </Col>
  427. </Row>
  428. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  429. <Col span={4}>边框</Col>
  430. <Col span={8}>
  431. <Select
  432. placeholder="样式"
  433. className={styles.blockElm}
  434. value={pointerBorderStyle}
  435. onChange={this.selectChange('pointerBorderStyle')}
  436. >
  437. {this.lineStyles}
  438. </Select>
  439. </Col>
  440. <Col span={8}>
  441. <InputNumber
  442. placeholder="粗细"
  443. className={styles.blockElm}
  444. value={pointerBorderWidth}
  445. min={0}
  446. onChange={this.selectChange('pointerBorderWidth')}
  447. />
  448. </Col>
  449. <Col span={4}>
  450. <ColorPicker
  451. value={pointerBorderColor}
  452. onChange={this.selectChange('pointerBorderColor')}
  453. />
  454. </Col>
  455. </Row>
  456. </div>
  457. </div>
  458. <div className={styles.paneBlock}>
  459. <h4>轴</h4>
  460. <div className={styles.blockBody}>
  461. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  462. <Col span={4}>粗细</Col>
  463. <Col span={8}>
  464. <InputNumber
  465. className={styles.blockElm}
  466. value={axisLineSize}
  467. onChange={this.selectChange('axisLineSize')}
  468. formatter={this.pixelFormatter}
  469. parser={this.pixelParser}
  470. />
  471. </Col>
  472. <Col span={4}>颜色</Col>
  473. <Col span={4}>
  474. <ColorPicker
  475. value={axisLineColor}
  476. onChange={this.colorChange('axisLineColor')}
  477. />
  478. </Col>
  479. </Row>
  480. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  481. <Col span={12}>
  482. <Checkbox
  483. checked={showAxisTick}
  484. onChange={this.checkboxChange('showAxisTick')}
  485. >
  486. 显示刻度
  487. </Checkbox>
  488. </Col>
  489. </Row>
  490. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  491. <Col span={12}>
  492. <Checkbox
  493. checked={showAxisLabel}
  494. onChange={this.checkboxChange('showAxisLabel')}
  495. >
  496. 显示标签
  497. </Checkbox>
  498. </Col>
  499. </Row>
  500. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  501. <Col span={10}>
  502. <Select
  503. placeholder="标签字体"
  504. className={styles.blockElm}
  505. value={axisLabelFontFamily}
  506. onChange={this.selectChange('axisLabelFontFamily')}
  507. >
  508. {fontFamilies}
  509. </Select>
  510. </Col>
  511. <Col span={10}>
  512. <Select
  513. placeholder="标签文字大小"
  514. className={styles.blockElm}
  515. value={axisLabelFontSize}
  516. onChange={this.selectChange('axisLabelFontSize')}
  517. >
  518. {fontSizes}
  519. </Select>
  520. </Col>
  521. <Col span={4}>
  522. <ColorPicker
  523. value={axisLabelColor}
  524. onChange={this.colorChange('axisLabelColor')}
  525. />
  526. </Col>
  527. </Row>
  528. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  529. <Col span={6}>距离轴线</Col>
  530. <Col span={12}>
  531. <InputNumber
  532. className={styles.blockElm}
  533. value={axisLabelDistance}
  534. onChange={this.inputNumberChange('axisLabelDistance')}
  535. />
  536. </Col>
  537. </Row>
  538. </div>
  539. </div>
  540. <div className={styles.paneBlock}>
  541. <h4>分隔线</h4>
  542. <div className={styles.blockBody}>
  543. <Row gutter={8} type="flex" align="middle" className={styles.blockRow}>
  544. <Col span={16}>
  545. <Checkbox
  546. checked={showSplitLine}
  547. onChange={this.checkboxChange('showSplitLine')}
  548. >
  549. 显示分隔线
  550. </Checkbox>
  551. </Col>
  552. </Row>
  553. </div>
  554. </div>
  555. </>
  556. )
  557. }
  558. }
  559. export default GaugeSection