lineConfigForm.jsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import React from 'react'
  2. import { Form, Select, Tag, Cascader, Dropdown, Menu } from 'antd'
  3. import { connect } from 'dva'
  4. import '../../../models/chartDesigner'
  5. import GAUGE from './gauge.json'
  6. import GRANULARITY from './granularity.json'
  7. const FormItem = Form.Item
  8. const { Option } = Select
  9. const formItemLayout = {
  10. labelCol: { span: 8 },
  11. wrapperCol: { span: 16 },
  12. };
  13. const LineConfigForm = ({ autoRefresh, chartDesigner, dispatch }) => {
  14. const columns = chartDesigner.columns;
  15. return (
  16. <Form hideRequiredMark={true}>
  17. <FormItem label='横轴' {...formItemLayout}>
  18. <Cascader
  19. value={[chartDesigner.lineConfig.xAxis.column.value, chartDesigner.lineConfig.xAxis.granularity.value]}
  20. allowClear={true}
  21. showSearch={{
  22. filter: (inputValue, path) => {
  23. let p0 = path[0].label.toLowerCase();
  24. let v = inputValue.toLowerCase();
  25. return p0.indexOf(v) !== -1;
  26. },
  27. sort: (a, b, inputValue) => {
  28. return a[0].label.localeCompare(b[0].label,"zh");
  29. },
  30. render: (inputValue, path) => {
  31. const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
  32. let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
  33. let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
  34. return (
  35. fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
  36. <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
  37. fragment
  38. )
  39. }))
  40. return <div>{label0}</div>
  41. }
  42. }}
  43. options={columns.filter(c =>['time'].indexOf(c.type) !== -1).map((c, i)=>{
  44. return {
  45. type: c.type,
  46. value: c.name,
  47. label: c.label,
  48. children: GRANULARITY[c.type]
  49. }
  50. })}
  51. onChange={(value, items) => {
  52. let column = {};
  53. let granularity = {};
  54. if(items.length > 0) {
  55. column = { type: items[0].type, value: items[0].value, label: items[0].label };
  56. }
  57. if(items.length > 1) {
  58. granularity = { value: items[1].value, label: items[1].label };
  59. }
  60. dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, xAxis: { column, granularity } }, autoRefresh });
  61. }}
  62. displayRender={(label, selectedOptions) => {
  63. let text = '';
  64. let className = 'cascader-label';
  65. if(label.length > 0) {
  66. className += ' full-label';
  67. text += label[0];
  68. if(label.length > 1) {
  69. text += '(' + label[1] + ')';
  70. }
  71. }else {
  72. className += ' empty-label';
  73. text = '请选择...';
  74. }
  75. return <div className={className}>{text}</div>;
  76. }}
  77. >
  78. </Cascader>
  79. </FormItem>
  80. <FormItem label='纵轴' {...formItemLayout}>
  81. <Cascader
  82. className='gauge-item'
  83. value={[chartDesigner.lineConfig.yAxis.column.value, chartDesigner.lineConfig.yAxis.gauge.value]}
  84. allowClear={true}
  85. showSearch={{
  86. filter: (inputValue, path) => {
  87. let p0 = path[0].label.toLowerCase();
  88. let v = inputValue.toLowerCase();
  89. return p0.indexOf(v) !== -1;
  90. },
  91. sort: (a, b, inputValue) => {
  92. return a[0].label.localeCompare(b[0].label,"zh");
  93. },
  94. render: (inputValue, path) => {
  95. const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
  96. let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
  97. let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
  98. return (
  99. fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
  100. <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
  101. fragment
  102. )
  103. }))
  104. return <div>{label0}>{path[1].label}</div>
  105. }
  106. }}
  107. options={columns.map((c, i)=>{
  108. return {
  109. type: c.type,
  110. value: c.name,
  111. label: c.label,
  112. children: GAUGE[chartDesigner.baseConfig.viewType].map(g => {
  113. if(g.columnType.indexOf(c.type) !== -1) {
  114. return g;
  115. }else {
  116. return null;
  117. }
  118. }).filter( g => g!==null)
  119. }
  120. })}
  121. onChange={(value, items) => {
  122. let column = {};
  123. let gauge = {};
  124. if(value.length > 0) {
  125. column = { type: items[0].type, value: items[0].value, label: items[0].label };
  126. gauge = { value: items[1].value, label: items[1].label };
  127. }
  128. dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, yAxis: { column, gauge } }, autoRefresh });
  129. }}
  130. displayRender={(label, selectedOptions) => {
  131. let menu = selectedOptions.length > 0 ? <Menu
  132. selectedKeys={[chartDesigner.lineConfig.yAxis.gauge.value]}
  133. selectable={true}
  134. >
  135. {selectedOptions[0].children.map((c, i) => {
  136. return <Menu.Item data-value={c.value} data-label={c.label} key={c.value} onClick={(e) => {
  137. let value = e.domEvent.target.getAttribute('data-value');
  138. let label = e.domEvent.target.getAttribute('data-label');
  139. dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: {
  140. ...chartDesigner.lineConfig,
  141. yAxis: {
  142. column: chartDesigner.lineConfig.yAxis.column,
  143. gauge: { value, label }
  144. }
  145. }, autoRefresh });
  146. e.domEvent.stopPropagation();
  147. }}>{c.label}</Menu.Item>
  148. })}
  149. </Menu>: [];
  150. let tag = selectedOptions.length > 0 ? <Dropdown
  151. trigger={['click']}
  152. overlay={menu}
  153. >
  154. <Tag size='small' onClick={(e) => {e.stopPropagation()}}>{label[1]}</Tag>
  155. </Dropdown>
  156. : null;
  157. return <div className={`cascader-label ${tag?'full' : 'empty'}-label`}>
  158. {tag}
  159. <span>{label[0] || '请选择...'}</span>
  160. </div>
  161. }}
  162. >
  163. </Cascader>
  164. </FormItem>
  165. <FormItem label='分组' {...formItemLayout}>
  166. <Select
  167. maxTagCount={1}
  168. labelInValue={true}
  169. allowClear={true}
  170. showSearch
  171. filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
  172. placeholder='请选择...'
  173. onChange={(value) => {
  174. const column = value ? columns.find(c => c.name === value.key) : null;
  175. const groupBy = column ? { ...value, type: column.type } : undefined;
  176. dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, groupBy }, autoRefresh });
  177. }}
  178. value={chartDesigner.lineConfig.groupBy}
  179. >
  180. {columns.filter(c => c.groupable).map((c, i)=>{
  181. return (<Option key={i} value={c.name}>{c.label}</Option>)
  182. })}
  183. </Select>
  184. </FormItem>
  185. </Form>
  186. );
  187. }
  188. function mapStateToProps({ present: { chartDesigner } }) {
  189. return { chartDesigner: chartDesigner }
  190. }
  191. export default connect(mapStateToProps)(LineConfigForm);