import { message } from 'antd'
import * as service from '../services/index'
import URLS from '../constants/url'
import parseChartOption from './parseChartOption'
import moment from 'moment'

function getBodyFilters(filters) {
    let bodyFilters = [];
    filters.filter(f => f.using).forEach(f => {
        let { name, operator, type, value1, value2 } = f;
        if(((type === 'index' || type === 'string') && !!value1) || // 因为数字类型会生成数字字符串，所以为0也是可以正常传入条件的
        ((type === 'scale' || type === 'time' || type === 'ordinal') && (operator === 'between' ? (!!value1 && !!value2) : (!!value1))) ||
        (type === 'categorical' &&
            (operator === 'contain' || operator === 'notContain' ?
                (value1 && value1.length > 0) : (!!value1)
            )
        )) {
            let bodyFilter = {
                columnName: name,
                columnType: type,
                symbol: operator,
                value: value1
            };
            if(type === 'scale' && operator === 'between') {
                bodyFilter['value'] = value1 + ',' + value2;
            }else if(type === 'time') {
                let v1 = value1.dynamic ? value1.name : moment(value1).format('YYYY-MM-DD');
                let v2 = value2.dynamic ? value2.name : moment(value2).format('YYYY-MM-DD');
    
                if(operator === 'between') {
                    bodyFilter['value'] = v1 + ',' + v2;
                }else {
                    bodyFilter['value'] = v1;
                }
            }else if(type === 'categorical' && (operator === 'contain' || operator === 'notContain')) {
                bodyFilter['value'] = JSON.stringify(value1);
            }
            bodyFilters.push(bodyFilter);
        }
    });
    return bodyFilters;
}

export default {
    namespace: 'chartDesigner',
    state: {
        originData: {
            code: null,
            creatorCode: null,
            creatorName: null,
            header: { label: '无标题' },
            columns: [],
            baseConfig: { dataSource: { code: '' }, viewType: '' },
            aggregateTableConfig: { targetColumn: {}, statistics: [], groupBy: [] },
            dataViewConfig: { viewColumns: [], sortColumn: {key: ''}, sortType: 'asc' },
            barConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''}, threshold: 20 },
            lineConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''}, threshold: 1000 },
            pieConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, threshold: 20 },
            scatterConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''}, threshold: 1000 },
            theme: 'default',
            styleConfig: {
                aggregateTable: {},
                pie: {},
            },
            otherConfig:{},
            description: '',
            filters: [],
            chartOption: {},
            dirty: false,
            fetchConfig: {},
            demo: false
        },
    },
    reducers: {
        /**
         * 更新model字段值
         * 1. 改变dirty
         */
        setField(state, action) {
            const { name, value } = action;
            let obj = {};
            obj[name] = value;
            return Object.assign({}, state, obj, { dirty: true });
        },
        /**
         * 批量更新model字段值
         * 1. 改变dirty
         */
        setFields(state, action) {
            const { fields } = action;
            let obj = {};
            fields.map(f => (obj[f.name] = f.value));
            return Object.assign({}, state, obj, { dirty: true });
        },
        /**
         * 更新model字段值
         * 1. 不改变dirty
         */
        silentSetField(state, action) {
            const { name, value } = action;
            let obj = {};
            obj[name] = value;
            let newState = Object.assign({}, state, obj);
            return newState;
        },
        /**
         * 批量更新model字段值
         * 1. 不改变dirty
         */
        silentSetFields(state, action) {
            const { fields } = action;
            let obj = {};
            fields.map(f => (obj[f.name] = f.value));
            let newState = Object.assign({}, state, obj);
            return newState;
        },
        reset(state, action) {
            let newState = Object.assign({}, state, state.originData);
            return Object.assign({}, newState);
        },
        setDirty(state, action) {
            const { dirty } = action;
            return Object.assign({}, state, { dirty });
        }
    },
    effects: {
        *changeField(action, { select, call, put }) {
            const { name, value } = action;
            yield put({ type: 'setField', name, value });

            const { autoRefresh } = action;
            if(autoRefresh === undefined ? true : autoRefresh) {
                yield put({ type: 'fetchChartData' });
            }
        },
        *silentChangeField(action, { select, call, put }) {
            const { name, value } = action;
            yield put({ type: 'silentSetField', name, value });
        },
        *changeFields(action, { select, call, put }) {
            const { fields } = action;
            yield put({ type: 'setFields', fields });

            const { autoRefresh } = action;
            if(autoRefresh === undefined ? true : autoRefresh) {
                yield put({ type: 'fetchChartData' });
            }
        },
        *silentChangeFields(action, { select, call, put }) {
            const { fields } = action;
            yield put({ type: 'silentSetFields', fields });
        },
        *changeDataSource(action, { select, call, put }) {
            const { dataSource } = action;
            const chartDesigner = yield select(state => state.present.chartDesigner);
            const { baseConfig } = chartDesigner;
            yield put({ type: 'changeField', name: 'baseConfig', value: { ...baseConfig, dataSource } });
            yield put({ type: 'remoteDataColumn', code: dataSource.code });
        },
        *silentChangeDataSource(action, { select, call, put }) {
            const { dataSource } = action;
            const chartDesigner = yield select(state => state.present.chartDesigner);
            const { baseConfig } = chartDesigner;
            yield put({ type: 'silentChangeField', name: 'baseConfig', value: { ...baseConfig, dataSource } });
            yield put({ type: 'remoteDataColumn', code: dataSource.code });
        },
        *remoteQucikAdd(action, { select, call, put }) {
            try{
                const { dataSource } = action;

                yield put({ type: 'silentSetFields', fields: [
                    { name: 'baseConfig', value: { dataSource: dataSource.code, viewType: '' } }
                ] });
                let body = {
                    chartName: dataSource.name + '_未命名',
                    dataId: dataSource.code,
                    describes: '',
                    chartConfig: '{}',
                    chartType: '',
                };
                const res = yield call(service.fetch, {
                    url: URLS.CHART_ADD,
                    body: body
                })
                if(!res.err && res.data.data > 0) {
                    yield put({ type: 'chart/fetchList', mandatory: true });
                    yield put({ type: 'main/redirect', path: '/chart/' + res.data.data });
                    // yield put({ type: 'chart/remoteDetail', code: res.data.data });
                }else {
                    message.error('新增失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                message.error('新增失败: ' + e.message);
            }
        },
        /**
         * 复制新增
         */
        *remoteCopyAdd(action, { select, call, put }) {
            try{
                yield put({ type: 'chart/remoteModify' });
                const { newHeaderLabel } = action;
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { filters, baseConfig, pieConfig, lineConfig, aggregateTableConfig, dataViewConfig,
                    barConfig, scatterConfig, otherConfig, description, group, chartOption, fetchConfig, styleConfig } = chartDesigner;
                let body = {
                    filters: JSON.stringify(filters),
                    chartName: newHeaderLabel,
                    dataId: baseConfig.dataSource.code,
                    describes: description || '',
                    style: JSON.stringify(styleConfig),
                    otherConfig: JSON.stringify(otherConfig),
                    chartsGroup: group+'' ? group : '-1',
                    chartOption: JSON.stringify(chartOption),
                    fetchConfig: JSON.stringify(fetchConfig),
                }; // 基本属性
                if(baseConfig.viewType === 'bar') {
                    body.chartType = 'Histogram';
                    body.chartConfig = JSON.stringify(barConfig);
                }else if(baseConfig.viewType === 'pie') {
                    body.chartType = 'Pie';
                    body.chartConfig = JSON.stringify(pieConfig);
                }else if(baseConfig.viewType === 'line') {
                    body.chartType = 'Line';
                    body.chartConfig = JSON.stringify(lineConfig);
                }else if(baseConfig.viewType === 'scatter') {
                    body.chartType = 'scatter';
                    body.chartConfig = JSON.stringify(scatterConfig);
                }else if(baseConfig.viewType === 'aggregateTable') {
                    body.chartType = 'population';
                    body.chartConfig = JSON.stringify(aggregateTableConfig);
                }else if(baseConfig.viewType === 'dataView') {
                    body.chartType = 'individual';
                    body.chartConfig = JSON.stringify(dataViewConfig);;
                }else {
                    body.chartType = '';
                    body.chartConfig = JSON.stringify({});
                }
                const res = yield call(service.fetch, {
                    url: URLS.CHART_ADD,
                    body: body
                })
                if(!res.err && res.data.code > 0) {
                    yield put({ type: 'chart/fetchList', mandatory: true });
                    yield put({ type: 'main/redirect', path: '/chart/' + res.data.data , reload: true});
                }else {
                    message.error('创建副本失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                message.error('创建副本失败: ' + e.message);
            }
        },
        *remoteDataColumn(action, { select, call, put }) {
            const code = action.code;
            try {
                const res = yield call(service.fetch, {
                    url: URLS.DATASOURCE_QUERY_DATACOLUMNS,
                    body: code
                });
                if(!res.err && res.data.code > 0) {
                    let resData = res.data.data;

                    let columns = resData.map((c, i) => {
                        return {
                            key: i,
                            name: c.columnName,
                            label: c.columnRaname,
                            type: c.columnType,
                            groupable: c.isGroup==='1'?true:false,
                            filterable: c.isFilter==='1'?true:false,
                            bucketizable: c.isSubsection==='1'?true:false,
                            selection: []
                        }
                    })
                    yield put({ type: 'silentSetField', name: 'columns', value: columns });
                }else {
                    message.error('请求列数据失败:' + (res.err || res.data.msg));
                    yield put({ type: 'silentSetField', name: 'columns', value: [] });
                }
            }catch(e) {
                message.error('请求列数据失败: ' + e.message);
                yield put({ type: 'silentSetField', name: 'columns', value: [] });
            }
        },
        *fetchChartData(action, { select, call, put }) {
            const chartDesigner = yield select(state => state.present.chartDesigner);
            const { baseConfig } = chartDesigner;
            const { viewType } = baseConfig;
            const { page, pageSize } = action;

            try{
                yield put({ type: 'silentSetField', name: 'fetchConfig', value: {} });
                if(viewType === 'bar') {
                    const { barConfig } = chartDesigner;
                    if(barConfig.xAxis.column.value && barConfig.yAxis.column.value) {
                        yield put({ type: 'fetchBarData' });
                    }else {
                        yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                    }
                }else if(viewType === 'pie') {
                    const { pieConfig } = chartDesigner;
                    if(pieConfig.xAxis.column.value && pieConfig.yAxis.column.value) {
                        yield put({ type: 'fetchPieData' });
                    }else {
                        yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                    }
                }else if(viewType === 'line') {
                    const { lineConfig } = chartDesigner;
                    if(lineConfig.xAxis.column.value && lineConfig.yAxis.column.value) {
                        yield put({ type: 'fetchLineData' });
                    }else {
                        yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                    }
                }else if(viewType === 'scatter') {
                    const { scatterConfig } = chartDesigner;
                    if(scatterConfig.xAxis.column.value && scatterConfig.yAxis.column.value) {
                        yield put({ type: 'fetchScatterData' });
                    }else {
                        yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                    }
                }else if(viewType === 'dataView') {
                    const { dataViewConfig } = chartDesigner;
                    if(dataViewConfig.viewColumns.length > 0) {
                        yield put({ type: 'fetchDataViewData', page, pageSize });
                        // yield put({ type: 'fetchDataViewData' }); // dataView不需要在这里触发数据请求，组件在计算完pageSize后会自动发起数据请求
                    }else {
                        yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                    }
                }else if(viewType === 'aggregateTable') {
                    const { aggregateTableConfig } = chartDesigner;
                    if(aggregateTableConfig.targetColumn.name && aggregateTableConfig.statistics.length > 0) {
                        yield put({ type: 'fetchAggregateTableData' });
                    }else {
                        yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                    }
                }else {
                    console.log('no viewType......')
                }
            }catch(e) {
                message.error('加载数据错误: ' + e.message);
            }
        },
        *fetchBarData(action, { select, call, put }) {
            try {
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { code, barConfig, filters, theme, styleConfig } = chartDesigner;
                const body = {
                    id: code,
                    groups: barConfig.groupBy && barConfig.groupBy.key ? [barConfig.groupBy.key] : [],
                    xAxis: {
                        columnRename: barConfig.xAxis.column.value,
                        columnType: barConfig.xAxis.column.type,
                        showDataType: barConfig.xAxis.granularity.value
                    },
                    yAxis: {
                        columnRename: barConfig.yAxis.column.value,
                        showDataType: barConfig.yAxis.gauge.value
                    },
                    filters: getBodyFilters(filters),
                    maxCount: barConfig.threshold
                };
                
                let res = yield call(service.fetch, {
                    url: URLS.CHART_BAR_OPTION,
                    body: body,
                    timeout: 30000
                });
                if(!res.err && res.data.code > 0) {
                    let option = parseChartOption('bar', res.data.data, barConfig, theme, styleConfig.bar);
                    yield put({ type: 'silentSetField', name: 'chartOption', value: option });
                }else {
                    message.error('请求柱状图数据失败: ' + (res.err || res.data.msg));
                    yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                }
                yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
            }catch(e) {
                yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                message.error('请求柱状图数据失败: ' + e.message);
            }
        },
        *fetchPieData(action, { select, call, put }) {
            try {
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { code, pieConfig, filters, theme, styleConfig } = chartDesigner;
                const body = {
                    id: code,
                    legendData: {
                        columnRename: pieConfig.xAxis.column.value,
                        columnType: pieConfig.xAxis.column.type,
                        showDataType: pieConfig.xAxis.granularity.value
                    },
                    series: {
                        columnRename: pieConfig.yAxis.column.value,
                        columnName: pieConfig.yAxis.column.label,
                        showDataType: pieConfig.yAxis.gauge.value
                    },
                    filters: getBodyFilters(filters),
                    maxCount: pieConfig.threshold
                };

                let res = yield call(service.fetch, {
                    url: URLS.CHART_PIE_OPTION,
                    body: body,
                    timeout: 30000
                });
                if(!res.err && res.data.code > 0) {
                    let option = parseChartOption('pie', res.data.data, pieConfig, theme, styleConfig.pie || {});
                    yield put({ type: 'silentSetField', name: 'chartOption', value: option });
                }else {
                    message.error('请求饼图数据失败: ' + (res.err || res.data.msg));
                    yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                }
                yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
            }catch(e) {
                yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                message.error('请求饼图数据失败: ' + e.message);
            }
        },
        *fetchLineData(action, { select, call, put }) {
            try {
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { code, lineConfig, filters, theme, styleConfig } = chartDesigner;
                const body = {
                    id: code,
                    xAxis: {
                        columnRename: lineConfig.xAxis.column.value,
                        columnType: lineConfig.xAxis.column.type
                    },
                    yAxis: {
                        columnRename: lineConfig.yAxis.column.value,
                        showDataType: lineConfig.yAxis.gauge.value
                    },
                    groups: lineConfig.groupBy && lineConfig.groupBy.key ? [lineConfig.groupBy.key] : [],
                    filters: getBodyFilters(filters),
                    maxCount: lineConfig.threshold
                };

                let res = yield call(service.fetch, {
                    url: URLS.CHART_LINE_OPTION,
                    body: body,
                    timeout: 30000
                });
                if(!res.err && res.data.code > 0) {
                    let option = parseChartOption('line', res.data.data, lineConfig, theme, styleConfig.line);
                    yield put({ type: 'silentSetField', name: 'chartOption', value: option });
                }else {
                    message.error('请求折线图数据失败: ' + (res.err || res.data.msg));
                    yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                }
                yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
            }catch(e) {
                yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                message.error('请求折线图数据失败: ' + e.message);
            }
        },
        *fetchScatterData(action, { select, call, put }) {
            try {
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { code, scatterConfig, filters, theme, styleConfig } = chartDesigner;
                const body = {
                    id: code,
                    xAxis: {
                        columnRename: scatterConfig.xAxis.column.value,
                        columnType: scatterConfig.xAxis.column.type
                    },
                    yAxis: {
                        columnRename: scatterConfig.yAxis.column.value,
                        showDataType: scatterConfig.yAxis.gauge.value
                    },
                    groups: scatterConfig.groupBy && scatterConfig.groupBy.key ? [scatterConfig.groupBy.key] : [],
                    filters: getBodyFilters(filters),
                    maxCount: scatterConfig.threshold
                };

                let res = yield call(service.fetch, {
                    url: URLS.CHART_SCATTER_OPTION,
                    body: body,
                    timeout: 30000
                });
                if(!res.err && res.data.code > 0) {
                    let option = parseChartOption('scatter', res.data.data, scatterConfig, theme, styleConfig.scatter);
                    yield put({ type: 'silentSetField', name: 'chartOption', value: option });
                }else {
                    message.error('请求散点图数据失败: ' + (res.err || res.data.msg));
                    yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                }
                yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
            }catch(e) {
                yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                message.error('请求散点图数据失败: ' + e.message);
            }
        },
        *fetchDataViewData(action, { select, call, put }) {
            try {
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { code, dataViewConfig, filters, theme, styleConfig } = chartDesigner;
                const { page, pageSize } = action;
                const body = {
                    id: code,
                    columnListName: dataViewConfig.viewColumns.map(c => c.name),
                    sortColumn: dataViewConfig.sortColumn ? dataViewConfig.sortColumn.key : dataViewConfig.viewColumns[0].name,
                    sort: dataViewConfig.sortType || 'asc',
                    filters: getBodyFilters(filters),
                    testPage: {
                        pageNum: page || 1,
                        pageSize: pageSize || 25,
                    }
                };

                let res = yield call(service.fetch, {
                    url: URLS.CHART_DATAVIEW_OPTION,
                    body: body,
                    timeout: 30000
                });
                if(!res.err && res.data.code > 0) {
                    let option = parseChartOption('dataView', res.data.data, dataViewConfig, theme, styleConfig.dataView);
                    yield put({ type: 'silentSetField', name: 'chartOption', value: option });
                }else {
                    message.error('请求列表数据失败: ' + (res.err || res.data.msg));
                    yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                }
                yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
            }catch(e) {
                yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                message.error('请求列表数据失败: ' + e.message);
            }
        },
        *fetchAggregateTableData(action, { select, call, put }) {
            try {
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { originData, code, aggregateTableConfig, filters, theme, styleConfig } = chartDesigner;
                const { targetColumn, statistics } = aggregateTableConfig;

                const body = {
                    id: code,
                    columnName: targetColumn.name,
                    operatorList: statistics,
                    groupByList: aggregateTableConfig.groupBy && aggregateTableConfig.groupBy.length > 0 ? aggregateTableConfig.groupBy.map(g => g.key) : [],
                    filters: getBodyFilters(filters),
                    testPage: {
                        pageNum: 1,
                        pageSize: 99,
                    }
                };

                let res = yield call(service.fetch, {
                    url: URLS.CHART_AGGREGATETABLE_OPTION,
                    body: body,
                    timeout: 30000
                });
                if(!res.err && res.data.code > 0) {
                    let option = parseChartOption('aggregateTable', res.data.data, aggregateTableConfig, theme, styleConfig.aggregateTable || originData.styleConfig.aggregateTable);
                    yield put({ type: 'silentSetField', name: 'chartOption', value: option });
                }else {
                    message.error('请求统计数据失败: ' + (res.err || res.data.msg));
                    yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                }
                yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
            }catch(e) {
                yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                message.error('请求统计数据失败: ' + e.message);
            }
        },
        /**
         * 将图表数据以表格的方式作为预览
         */
        *remoteChartDataList(action, { select, call, put }) {
            try {
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { code, baseConfig, aggregateTableConfig, lineConfig, barConfig, pieConfig, scatterConfig, dataViewConfig, filters } = chartDesigner;
                const { viewType } = baseConfig;
                const { page, pageSize } = action;

                let columns = [];
                let columnListName = [];
                let sortColumn = null;

                if(viewType === 'aggregateTable') {
                    const { groupBy, targetColumn } = aggregateTableConfig;
                    groupBy.map(g => ({
                        label: g.label,
                        name: g.key,
                    })).concat([targetColumn]).filter(x => !!x.name).forEach(x => {
                        if(!columns.find(c => c.name === x.name)) {
                            columns.push(x);
                        }
                    });;
                    sortColumn = targetColumn.name;
                }else if(viewType === 'line') {
                    const { groupBy, xAxis, yAxis } = lineConfig;
                    [{
                        label: groupBy ? groupBy.label : '',
                        name: groupBy ? groupBy.key : '',
                        type: groupBy ? groupBy.type : '',
                    }, {
                        label: xAxis.column.label,
                        name: xAxis.column.value,
                        type: xAxis.column.type,
                    }, {
                        label: yAxis.column.label,
                        name: yAxis.column.value,
                        type: yAxis.column.type,
                    }].filter(x => !!x.name).forEach(x => {
                        if(!columns.find(c => c.name === x.name)) {
                            columns.push(x);
                        }
                    });;
                    sortColumn = xAxis.column.value;
                }else if(viewType === 'bar') {
                    const { groupBy, xAxis, yAxis } = barConfig;
                    [{
                        label: groupBy ? groupBy.label : '',
                        name: groupBy ? groupBy.key : '',
                        type: groupBy ? groupBy.type : '',
                    }, {
                        label: xAxis.column.label,
                        name: xAxis.column.value,
                        type: xAxis.column.type,
                    }, {
                        label: yAxis.column.label,
                        name: yAxis.column.value,
                        type: yAxis.column.type,
                    }].filter(x => !!x.name).forEach(x => {
                        if(!columns.find(c => c.name === x.name)) {
                            columns.push(x);
                        }
                    });;
                    sortColumn = xAxis.column.value;
                }else if(viewType === 'pie') {
                    const { xAxis, yAxis } = pieConfig;
                    [{
                        label: xAxis.column.label,
                        name: xAxis.column.value,
                        type: xAxis.column.type,
                    }, {
                        label: yAxis.column.label,
                        name: yAxis.column.value,
                        type: yAxis.column.type,
                    }].filter(x => !!x.name).forEach(x => {
                        if(!columns.find(c => c.name === x.name)) {
                            columns.push(x);
                        }
                    });;
                    sortColumn = xAxis.column.value;
                }else if(viewType === 'scatter') {
                    const { groupBy, xAxis, yAxis } = scatterConfig;
                    [{
                        label: groupBy ? groupBy.label : '',
                        name: groupBy ? groupBy.key : '',
                        type: groupBy ? groupBy.type : '',
                    }, {
                        label: xAxis.column.label,
                        name: xAxis.column.value,
                        type: xAxis.column.type,
                    }, {
                        label: yAxis.column.label,
                        name: yAxis.column.value,
                        type: yAxis.column.type,
                    }].filter(x => !!x.name).forEach(x => {
                        if(!columns.find(c => c.name === x.name)) {
                            columns.push(x);
                        }
                    });;
                    sortColumn = xAxis.column.value;
                }else if(viewType === 'dataView') {
                    columns = dataViewConfig.viewColumns;
                    sortColumn = dataViewConfig.sortColumn.key;
                }

                if(columns.length === 0) {
                    // message.error('');
                    return false;
                }
                columnListName = columns.map(c => c.name);

                const body = {
                    id: code,
                    columnListName: columnListName,
                    sortColumn: sortColumn,
                    sort: 'asc',
                    filters: getBodyFilters(filters),
                    testPage: {
                        pageNum: page || 1,
                        pageSize: pageSize || 25,
                    }
                };

                yield put({ type: 'dataList/setField', name: 'loading', value: true });
                let res = yield call(service.fetch, {
                    url: URLS.CHART_DATAVIEW_OPTION,
                    body: body,
                    timeout: 30000
                });
                if(!res.err && res.data.code > 0) {

                    const { valueList } = res.data.data;
                    const { list: dataSource, pageSize, total } = valueList;

                    yield put({ type: 'dataList/setFields', fields: [
                        { name: 'columns', value: columns },
                        { name: 'dataSource', value: dataSource },
                        { name: 'pageSize', value: pageSize },
                        { name: 'total', value: total }
                    ] });
                }else {
                    message.error('请求列表数据失败: ' + (res.err || res.data.msg));
                    // yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
                }
            }catch(e) {
                message.error('请求数据列表失败: ' + e.message);
            }finally {
                yield put({ type: 'dataList/setField', name: 'loading', value: false });
            }
        },
    },
    subscriptions: {
        setup({ dispatch, history }) {
            dispatch({ type: 'reset' });  
        },
    },
};