scatterConfigForm.jsx 7.1 KB

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