|
|
@@ -0,0 +1,192 @@
|
|
|
+import React from 'react'
|
|
|
+import { Form, Select, Tag, Cascader, Dropdown, Menu } from 'antd'
|
|
|
+import { connect } from 'dva'
|
|
|
+import GAUGE from './gauge.json'
|
|
|
+const FormItem = Form.Item
|
|
|
+const { Option } = Select
|
|
|
+
|
|
|
+const ScatterConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }) => {
|
|
|
+
|
|
|
+ const columns = chartDesigner.columns;
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Form hideRequiredMark={true}>
|
|
|
+ <FormItem label='横轴' {...formItemLayout}>
|
|
|
+ <Cascader
|
|
|
+ value={[chartDesigner.scatterConfig.xAxis.column.value, chartDesigner.scatterConfig.xAxis.granularity.value]}
|
|
|
+ allowClear={true}
|
|
|
+ showSearch={{
|
|
|
+ filter: (inputValue, path) => {
|
|
|
+ let p0 = path[0].label.toLowerCase();
|
|
|
+ let v = inputValue.toLowerCase();
|
|
|
+ return p0.indexOf(v) !== -1;
|
|
|
+ },
|
|
|
+ sort: (a, b, inputValue) => {
|
|
|
+ return a[0].label.localeCompare(b[0].label,"zh");
|
|
|
+ },
|
|
|
+ render: (inputValue, path) => {
|
|
|
+ const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
|
|
|
+ let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
|
|
|
+ let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
|
|
|
+ return (
|
|
|
+ fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
|
|
|
+ <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
|
|
|
+ fragment
|
|
|
+ )
|
|
|
+ }))
|
|
|
+ return <div>{label0}>{path[1].label}</div>
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ options={columns.filter(c =>['scale', 'ordinal'].indexOf(c.type) !== -1).map((c, i)=>{
|
|
|
+ return {
|
|
|
+ type: c.type,
|
|
|
+ value: c.name,
|
|
|
+ label: c.label
|
|
|
+ }
|
|
|
+ })}
|
|
|
+ onChange={(value, items) => {
|
|
|
+ let column = {};
|
|
|
+ let granularity = {};
|
|
|
+ console.log('items', items)
|
|
|
+ console.log('value', value)
|
|
|
+ if(items.length > 0) {
|
|
|
+ column = { type: items[0].type, value: items[0].value, label: items[0].label };
|
|
|
+ }
|
|
|
+ if(items.length > 1) {
|
|
|
+ granularity = { value: items[1].value, label: items[1].label };
|
|
|
+ }
|
|
|
+ dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, xAxis: { column, granularity } }, autoRefresh });
|
|
|
+ }}
|
|
|
+ displayRender={(label, selectedOptions) => {
|
|
|
+ let text = '';
|
|
|
+ let className = 'cascader-label';
|
|
|
+ if(label.length > 0) {
|
|
|
+ className += ' full-label';
|
|
|
+ text += label[0];
|
|
|
+ if(label.length > 1) {
|
|
|
+ text += '(' + label[1] + ')';
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ className += ' empty-label';
|
|
|
+ text = '请选择...';
|
|
|
+ }
|
|
|
+ return <div className={className}>{text}</div>;
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ </Cascader>
|
|
|
+ </FormItem>
|
|
|
+ <FormItem label='纵轴' {...formItemLayout}>
|
|
|
+ <Cascader
|
|
|
+ className='gauge-item'
|
|
|
+ value={[chartDesigner.scatterConfig.yAxis.column.value, chartDesigner.scatterConfig.yAxis.gauge.value]}
|
|
|
+ allowClear={true}
|
|
|
+ showSearch={{
|
|
|
+ filter: (inputValue, path) => {
|
|
|
+ let p0 = path[0].label.toLowerCase();
|
|
|
+ let v = inputValue.toLowerCase();
|
|
|
+ return p0.indexOf(v) !== -1;
|
|
|
+ },
|
|
|
+ sort: (a, b, inputValue) => {
|
|
|
+ return a[0].label.localeCompare(b[0].label,"zh");
|
|
|
+ },
|
|
|
+ render: (inputValue, path) => {
|
|
|
+ const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
|
|
|
+ let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
|
|
|
+ let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
|
|
|
+ return (
|
|
|
+ fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
|
|
|
+ <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
|
|
|
+ fragment
|
|
|
+ )
|
|
|
+ }))
|
|
|
+ return <div>{label0}>{path[1].label}</div>
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ options={columns.map((c, i)=>{
|
|
|
+ return {
|
|
|
+ type: c.type,
|
|
|
+ value: c.name,
|
|
|
+ label: c.label,
|
|
|
+ children: GAUGE[chartDesigner.baseConfig.viewType].map(g => {
|
|
|
+ if(g.columnType.indexOf(c.type) !== -1) {
|
|
|
+ return g;
|
|
|
+ }else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }).filter( g => g!==null)
|
|
|
+ }
|
|
|
+ })}
|
|
|
+ onChange={(value, items) => {
|
|
|
+ let column = {};
|
|
|
+ let gauge = {};
|
|
|
+ if(value.length > 0) {
|
|
|
+ column = { type: items[0].type, value: items[0].value, label: items[0].label };
|
|
|
+ gauge = { value: items[1].value, label: items[1].label };
|
|
|
+ }
|
|
|
+ dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, yAxis: { column, gauge } }, autoRefresh });
|
|
|
+ }}
|
|
|
+ displayRender={(label, selectedOptions) => {
|
|
|
+ let menu = selectedOptions.length > 0 ? <Menu
|
|
|
+ selectedKeys={[chartDesigner.scatterConfig.yAxis.gauge.value]}
|
|
|
+ selectable={true}
|
|
|
+ >
|
|
|
+ {selectedOptions[0].children.map((c, i) => {
|
|
|
+ return <Menu.Item data-value={c.value} data-label={c.label} key={c.value} onClick={(e) => {
|
|
|
+ let value = e.domEvent.target.getAttribute('data-value');
|
|
|
+ let label = e.domEvent.target.getAttribute('data-label');
|
|
|
+ dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: {
|
|
|
+ ...chartDesigner.scatterConfig,
|
|
|
+ yAxis: {
|
|
|
+ column: chartDesigner.scatterConfig.yAxis.column,
|
|
|
+ gauge: { value, label }
|
|
|
+ }
|
|
|
+ }, autoRefresh });
|
|
|
+ e.domEvent.stopPropagation();
|
|
|
+ }}>{c.label}</Menu.Item>
|
|
|
+ })}
|
|
|
+ </Menu>: [];
|
|
|
+ let tag = selectedOptions.length > 0 ? <Dropdown
|
|
|
+ trigger={['click']}
|
|
|
+ overlay={menu}
|
|
|
+ >
|
|
|
+ <Tag size='small' onClick={(e) => {e.stopPropagation()}}>{label[1]}</Tag>
|
|
|
+ </Dropdown>
|
|
|
+ : null;
|
|
|
+
|
|
|
+ return <div className={`cascader-label ${tag?'full' : 'empty'}-label`}>
|
|
|
+ {tag}
|
|
|
+ <span>{label[0] || '请选择...'}</span>
|
|
|
+ </div>
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ </Cascader>
|
|
|
+ </FormItem>
|
|
|
+ <FormItem label='分组' {...formItemLayout}>
|
|
|
+ <Select
|
|
|
+ maxTagCount={1}
|
|
|
+ labelInValue={true}
|
|
|
+ allowClear={true}
|
|
|
+ showSearch
|
|
|
+ filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
|
|
|
+ placeholder='请选择...'
|
|
|
+ onChange={(value) => {
|
|
|
+ const column = value ? columns.find(c => c.name === value.key) : null;
|
|
|
+ const groupBy = column ? { ...value, type: column.type } : undefined;
|
|
|
+ dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, groupBy }, autoRefresh });
|
|
|
+ }}
|
|
|
+ value={chartDesigner.scatterConfig.groupBy}
|
|
|
+ >
|
|
|
+ {columns.filter(c => c.groupable).map((c, i)=>{
|
|
|
+ return (<Option key={i} value={c.name}>{c.label}</Option>)
|
|
|
+ })}
|
|
|
+ </Select>
|
|
|
+ </FormItem>
|
|
|
+ </Form>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+function mapStateToProps({ present: { chartDesigner } }) {
|
|
|
+ return { chartDesigner: chartDesigner }
|
|
|
+}
|
|
|
+
|
|
|
+export default connect(mapStateToProps)(ScatterConfigForm);
|