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

const getViewType = function(type) {
    if(type === 'Histogram') {
        return 'bar';
    }else if(type === 'Line') {
        return 'line';
    }else if(type === 'Pie') {
        return 'pie';
    }else if(type === 'scatter') {
        return 'scatter';
    }else if(type === 'population') {
        return 'aggregateTable';
    }else if(type === 'individual') {
        return 'dataView';
    }else {
        return '';
    }
}

export default {
    namespace: 'chart',
    state: {
        list: [],
        filterLabel: '',
        groupList: [],
        currentGroup: [{
            code: 'all',
            label: '全部分组'
        }],
        groupDirty: false
    },
    reducers: {
        add(state, action) {
            const { data } = action;
            let list = state.list;
            list.push(data);
            return Object.assign({}, state, {list});
        },
        list(state, action) {
            let list = action.list;
            return Object.assign({}, state, {list: list});
        },
        setFilterLabel(state, action) {
            const { label } = action;
            return Object.assign({}, state, {filterLabel: label});
        },
        groupList(state, action) {
            let data = action.data;
            return Object.assign({}, state, {groupList: data});
        },
        /**
         * 设置数据源过滤用分组
         */
        setCurrentGroup(state, action) {
            const { group1, group2 } = action;
            let g = [group1];
            group2 && g.push(group2);
            return Object.assign({}, state, {currentGroup: g});
        },
        addGroup(state, action) {
            const { group } = action;
            let list = state.groupList;
            list.push(group);
            return Object.assign({}, state, {groupList: list});
        },
        modifyGroup(state, action) {
            const { group } = action;
            let list = state.groupList;
            let dirty = false;
            for(let i = 0; i < list.length; i++) {
                let l = list[i];
                if(l.code === group.code) {
                    for(let k in l) {
                        if(group[k] !== undefined && l[k] !== group[k]) {
                            l[k] = group[k];
                            dirty = true;
                        }
                    }
                    break;
                }
            }
            return Object.assign({}, state, {groupDirty: dirty, groupList: list});
        },
        modifyGroups(state, action) {
            const { groups } = action;
            let list = state.groupList;
            const modifyGroupCodes = groups.map(g => g.code);

            list = list.filter(l => modifyGroupCodes.indexOf(l.code) === -1);
            list = list.concat(groups);

            return Object.assign({}, state, {groupList: list});
        },
        deleteGroup(state, action) {
            const { group } = action;
            let list = state.groupList;
            for(let i = 0; i < list.length; i++) {
                let l = list[i];
                if(l.code === group.code) {
                    list.splice(i, 1);
                    break;
                }
            }
            return Object.assign({}, state, {groupList: list});
        },
        setGroupDirty(state, action) {
            let dirty = action.dirty;
            return Object.assign({}, state, {groupDirty: dirty});
        },
        /** 
         * 设置图表所属分组
         */
        setChartGroup(state, action) {
            const { chartCode, groupCode } = action;
            let list = state.list;
            for(let i = 0; i < list.length; i++) {
                let l = list[i];
                if(l.code === chartCode) {
                    l.groupCode = groupCode;
                    break;
                }
            }
            return Object.assign({}, state, {list: list});
        }
    },
    effects: {
        *fetchList(action, { select, call, put }) {
            try{
                const chart = yield select(state => state.present.chart);
                if(!action.mandatory && chart.list.length > 0) {
                    return;
                }
                const res = yield call(service.fetch, {
                    url: URLS.CHART_LIST
                });
                console.log('请求图表列表', res);
                if(!res.err && res.data.code > 0) {
                    let list = res.data.data.map(d => {
                        let chartOption = d.chartOption ? JSON.parse(d.chartOption) : {};
                        return {
                            code:  d.chartId+'',
                            name: d.chartName,
                            type: getViewType(d.chartType),
                            creator: d.createBy,
                            createTime: d.createDate,
                            description: d.describes || '',
                            groupCode: d.chartsGroup + '',
                            chartOption: chartOption
                        }
                    })
                    console.log('请求图表列表', list);
                    yield put({ type: 'list', list: list });
                }else {
                    message.error('请求图表列表失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.log(e);
                message.error('请求图表列表失败');
            }
        },
        *remoteDetail(action, { select, call, put }) {
            const code = action.code;
            if(!code){
                return
            }
            try {
                const res = yield call(service.fetch, {
                    url: URLS.CHART_DETAIL,
                    body: code
                });
                console.log('解析图表数据', code, res);
                if(!res.err && res.data.code > 0) {
                    let resData = res.data.data;
                    let groupBy = JSON.parse(resData.groupBy) || [];
                    let chartConfig = JSON.parse(resData.chartConfig || '{ "xAxis": { "column": {}, "granularity": {} }, "yAxis": { "column": {}, "gauge": {} } }');
                    let otherConfig = JSON.parse(resData.otherConfig || '{}');
                    let viewType = getViewType(resData.chartType);
                    let filters = JSON.parse(resData.filters || '[]');
                    let chartOption = JSON.parse(resData.chartOption || '{}');

                    let data = {
                        code: resData.chartId,
                        header: {
                            label: resData.chartName
                        },
                        baseConfig: {
                            dataSource: resData.dataId,
                            viewType: viewType
                        },
                        otherConfig: otherConfig,
                        description: resData.describes,
                        group: resData.chartsGroup+'',
                        filters: filters,
                        chartOption: chartOption
                    }

                    if(viewType === 'bar') {
                        data.barConfig = { ...chartConfig, groupBy: groupBy.map(g => {
                            return {
                                key: g.columnName.toLowerCase(),
                                label: g.columnRename
                            }
                        })[0] };
                    }else if(viewType === 'pie') {
                        data.pieConfig = chartConfig;
                    }else if(viewType === 'line') {
                        data.lineConfig = { ...chartConfig, groupBy: groupBy.map(g => {
                            return {
                                key: g.columnName.toLowerCase(),
                                label: g.columnRename
                            }
                        })[0] };
                    }else if(viewType === 'scatter') {
                        data.scatterConfig = { ...chartConfig, groupBy: groupBy.map(g => {
                            return {
                                key: g.columnName.toLowerCase(),
                                label: g.columnRename
                            }
                        })[0] };
                    }else if(viewType === 'aggregateTable') {
                        data.aggregateTableConfig = { ...chartConfig, groupBy: groupBy.map(g => {
                            return {
                                key: g.columnName.toLowerCase(),
                                label: g.columnRename
                            }
                        }) };
                    }else if(viewType === 'dataView') {
                        data.dataViewConfig = chartConfig;
                    }

                    let fields = [];
                    for(let key in data) {
                        fields.push({
                            name: key,
                            value: data[key]
                        })
                    }
                    console.log(fields);
                    yield put({ type: 'chartDesigner/defaultChangeFields', fields: fields });
                    
                    yield put({ type: 'chartDesigner/changeDataSource', value: {
                        dataSource: data.baseConfig.dataSource,
                        viewType: data.baseConfig.viewType
                    } });
                }else {
                    message.error('解析图表错误: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.log(e);
                message.error('解析图表错误');
            }
        },
        *remoteAdd(action, { select, call, put }) {
            try{
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { header, baseConfig, pieConfig, lineConfig, aggregateTableConfig, dataViewConfig,
                    barConfig, scatterConfig, otherConfig, description, group, filters, chartOption } = chartDesigner;
                let body = {
                    chartName: header.label,
                    dataId: baseConfig.dataSource,
                    createBy: 'zhuth',
                    describes: description,
                    style: '',
                    otherConfig: JSON.stringify(otherConfig),
                    chartsGroup: group ? group : '-1',
                    filters: JSON.stringify(filters),
                    chartOption: JSON.stringify(chartOption),
                }; // 基本属性
                if(baseConfig.viewType === 'bar') {
                    body.chartType = 'Histogram';
                    body.chartConfig = JSON.stringify(barConfig);
                    body.groupBy = barConfig.groupBy.key ? [{
                        columnName: barConfig.groupBy.key,
                        columnRename: barConfig.groupBy.label
                    }] : []
                }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);
                    body.groupBy = lineConfig.groupBy.key ? [{
                        columnName: lineConfig.groupBy.key,
                        columnRename: lineConfig.groupBy.label
                    }] : []
                }else if(baseConfig.viewType === 'scatter') {
                    body.chartType = 'scatter';
                    body.chartConfig = JSON.stringify(scatterConfig);
                    body.groupBy = scatterConfig.groupBy.key ? [{
                        columnName: scatterConfig.groupBy.key,
                        columnRename: scatterConfig.groupBy.label
                    }] : []
                }else if(baseConfig.viewType === 'aggregateTable') {
                    body.chartType = 'population';
                    body.chartConfig = JSON.stringify(aggregateTableConfig);
                    body.groupBy = aggregateTableConfig.groupBy && aggregateTableConfig.groupBy.length > 0 ? aggregateTableConfig.groupBy.map(g => {
                        return {
                            columnName: g.key,
                            columnRename: g.label
                        }
                    }) : []
                }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
                })
                console.log('新增图表', body, res);
                if(!res.err && res.data.code > 0) {
                    message.success('新增成功');
                    yield put({ type: 'fetchList', mandatory: true });
                }else {
                    message.error('新增失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.error(e);
                message.error('新增失败');
            }
        },
        *remoteModify(action, { select, call, put }) {
            try{
                const chartDesigner = yield select(state => state.present.chartDesigner);
                const { filters, code, header, baseConfig, pieConfig, lineConfig, aggregateTableConfig, dataViewConfig,
                    barConfig, scatterConfig, otherConfig, description, group, chartOption } = chartDesigner;
                let body = {
                    chartId: code,
                    filters: JSON.stringify(filters),
                    chartName: header.label,
                    dataId: baseConfig.dataSource,
                    createBy: 'zhuth',
                    describes: description || '',
                    style: '',
                    otherConfig: JSON.stringify(otherConfig),
                    chartsGroup: group+'' ? group : '-1',
                    chartOption: JSON.stringify(chartOption)
                }; // 基本属性
                if(baseConfig.viewType === 'bar') {
                    body.chartType = 'Histogram';
                    body.chartConfig = JSON.stringify(barConfig);
                    body.groupBy = barConfig.groupBy && barConfig.groupBy.key ? [{
                        columnName: barConfig.groupBy.key,
                        columnRename: barConfig.groupBy.label
                    }] : []
                }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);
                    body.groupBy = lineConfig.groupBy && lineConfig.groupBy.key ? [{
                        columnName: lineConfig.groupBy.key,
                        columnRename: lineConfig.groupBy.label
                    }] : []
                }else if(baseConfig.viewType === 'scatter') {
                    body.chartType = 'scatter';
                    body.chartConfig = JSON.stringify(scatterConfig);
                    body.groupBy = scatterConfig.groupBy && scatterConfig.groupBy.key ? [{
                        columnName: scatterConfig.groupBy.key,
                        columnRename: scatterConfig.groupBy.label
                    }] : []
                }else if(baseConfig.viewType === 'aggregateTable') {
                    body.chartType = 'population';
                    body.chartConfig = JSON.stringify(aggregateTableConfig);
                    body.groupBy = aggregateTableConfig.groupBy && aggregateTableConfig.groupBy.length > 0 ? aggregateTableConfig.groupBy.map(g => {
                        return {
                            columnName: g.key,
                            columnRename: g.label
                        }
                    }) : []
                }else if(baseConfig.viewType === 'dataView') {
                    body.chartType = 'individual';
                    body.chartConfig = JSON.stringify(dataViewConfig);
                }
                console.log('body', body)
                const res = yield call(service.fetch, {
                    url: URLS.CHART_UPDATE,
                    body: body
                })
                console.log('修改图表', body, res);
                if(!res.err && res.data.code > 0) {
                    message.success('修改成功');
                    yield put({ type: 'fetchList', mandatory: true });
                }else {
                    message.error('修改失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.error(e);
                message.error('修改失败');
            }
        },
        *remoteDelete(action, { select, call, put, takeEvery, takeLatest }) {
            const chart = yield select(state => state.present.chart);
            const code = action.code;
            let list = chart.list;
            try {
                const res = yield call(service.fetch, {
                    url: URLS.CHART_DELETE,
                    body: [code]
                });
                console.log('删除图表', code, res);
                if(!res.err && res.data.code > 0) {
                    for(let i = 0; i < list.length; i++) {
                        if(list[i].code === code) {
                            list.splice(i, 1);
                            break;
                        }
                    }
                    yield put({ type: 'list', list: list });
                    message.success('删除成功');
                }else {
                    message.error('删除失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.log(e);
                message.error('删除失败');
            }
        },
        
        *remoteGroupList(action, { select, call, put }) {
            try {
                const chart = yield select(state => state.present.chart);
                if(!action.mandatory && chart.groupList.length > 0) {
                    return;
                }
                const res = yield call(service.fetch, {
                    url: URLS.GROUP_CHART_LIST,
                });
                
                console.log('请求图表分组列表', res);
                if(!res.err && res.data.code > 0) {
                    const resData = res.data.data;
                    let data = resData.map(d => {
                        return {
                            code: d.id+'',
                            pcode: d.fatherId+'',
                            index: +d.groupIndex,
                            label: d.groupName+'',
                        }
                    });
                    yield put({ type: 'groupList', data });
                }else {
                    message.error('读取图表分组列表错误: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.log(e);
                message.error('读取图表分组列表错误');
            }
        },
        /**
         * 新增分组/子分组，需要传入父节点code
         */
        *remoteAddGroup(action, { select, call, put }) {
            try {
                const chart = yield select((state) => state.present.chart);
                const group = chart.groupList;
                const pgroups = group.filter(g => g.pcode === '-1');
                const cgroups = group.filter(g => g.pcode !== '-1');
                const { pgroup } = action;

                let body = {};
                if(pgroup) {
                    body = {
                        fatherId: pgroup.code,
                        groupName: '新子分组',
                        groupIndex: cgroups.filter(c => c.pcode === pgroup.code).length,
                        createBy: 'zhuth'
                    }
                }else {
                    body = {
                        fatherId: '-1',
                        groupName: '新分组',
                        groupIndex: pgroups.length,
                        createBy: 'zhuth'
                    }
                }
                const res = yield call(service.fetch, {
                    url: URLS.GROUP_CHART_ADD,
                    body: body
                });
                console.log('新增图表分组', body, res);
                if(!res.err && res.data.code > 0) {
                    let group = {
                        code: res.data.data + '',
                        pcode: body.fatherId + '',
                        index: body.groupIndex,
                        label: body.groupName+'',
                    }
                    yield put({ type: 'addGroup', group });
                }else {
                    message.error('添加分组失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.log(e);
                message.error('添加分组失败');
            }
        },
        /**
         * 修改单个分组信息（因为不涉及顺序号的修改，所以一般只用于label的修改）
         */
        *remoteModifyGroup(action, { select, call, put }) {
            try {
                const chart = yield select((state) => state.present.chart);
                const groupDirty = chart.groupDirty;
                const group = action.group;

                if(!groupDirty) { // 如果属性无改动则取消修改请求
                    return;
                }
                let body = {
                    id: group.code,
                    fatherId: group.pcode,
                    groupName: group.label,
                    groupIndex: group.index,
                    createBy: 'zhuth'
                }
                const res = yield call(service.fetch, {
                    url: URLS.GROUP_CHART_UPDATE,
                    body: body
                });
                console.log('修改图表分组', body, res);
                if(!res.err && res.data.code > 0) {
                    yield put({ type: 'setGroupDirty', dirty: false });
                }else {
                    message.error('修改分组失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.log(e);
                message.error('修改分组失败');
            }
        },
        /**
         * 批量修改多个分组信息(在移动位置时用)
         */
        *remoteModifyGroups(action, { select, call, put }) {
            try {
                const groups = action.groups;

                let body = groups.map(g => {
                    return {
                        id: g.code,
                        groupName: g.label,
                        groupIndex: g.index,
                        fatherId: g.pcode,
                        createBy: 'zhuth'
                    }
                });
                const res = yield call(service.fetch, {
                    url: URLS.GROUP_CHART_LIST_UPDATE,
                    body: body
                });
                console.log('批量修改图表分组', body, res);
                if(!res.err && res.data.code > 0) {
                    yield put({ type: 'modifyGroups', groups: groups });
                }else {
                    message.error('修改分组失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.log(e);
                message.error('修改分组失败');
            }
        },
        *remoteDeleteGroup(action, { select, call, put }) {
            try {
                const chart = yield select((state) => state.present.chart);
                const groupList = chart.groupList;
                const { group } = action;

                let bgroups = groupList.filter(l => l.pcode === group.pcode);
                bgroups.splice(group.index, 1);
                bgroups = bgroups.map((b, i) => {
                    return { ...b, index: i }
                });

                yield put({ type: 'remoteModifyGroups', groups: bgroups });

                const res = yield call(service.fetch, {
                    url: URLS.GROUP_CHART_DELETE,
                    body: [group.code]
                });
                
                console.log('删除图表分组', group.code, res);
                if(!res.err && res.data.code > 0) {
                    yield put({ type: 'deleteGroup', group});
                }else {
                    message.error('删除分组失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                console.log(e);
                message.error('删除分组失败');
            }
        },
        *remoteMoveGroup(action, { select, call, put }) {
            try {
                const { dragCode, dropCode, dropPosition } = action;
                const chart = yield select((state) => state.present.chart);
                let group = chart.groupList;

                const dragGroup = group.filter(g => g.code === dragCode)[0];
                const dropGroup = group.filter(g => g.code === dropCode)[0];

                let modifyGroups = [];
                if((dragGroup.pcode === '-1' || dropGroup.pcode === '-1') && (dragGroup.pcode !== dropGroup.pcode)) { // 跨级
                    console.log('跨级');
                    if(dropGroup.pcode !== '-1') { // 从父级到子级
                        console.log('error');
                        return; // 不允许
                    }else { // 从子级到父级
                        if(dragGroup.pcode === dropGroup.code) { // 不跨组
                            if(dropPosition === -1) { // 目标前
                                console.log('before');
                                let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                                let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                                dragGroups.splice(dragGroup.index, 1);
                                dragGroups = dragGroups.map((g, i) => {
                                    return { ...g, index: i }
                                });
                                dropGroups.splice(dropGroup.index, 0, dragGroup);
                                dropGroups = dropGroups.map((g, i) => {
                                    return { ...g, index: i, pcode: dropGroup.pcode }
                                });
                                modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                            }else if(dropPosition === 0) { // 目标内
                                console.log('nothing');
                                return; // 无变化
                            }else if(dropPosition === 1) { // 目标后
                                console.log('after');
                                let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                                let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                                dragGroups.splice(dragGroup.index, 1);
                                dragGroups = dragGroups.map((g, i) => {
                                    return { ...g, index: i }
                                });
                                dropGroups.splice(dropGroup.index + 1, 0, dragGroup);
                                dropGroups = dropGroups.map((g, i) => {
                                    return { ...g, index: i, pcode: dropGroup.pcode }
                                });
                                modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                            }
                        }else { // 跨组
                            let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                            let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                            let dropChildrenGroups = group.filter(g => g.pcode === dropGroup.code).sort((a, b) => a.index - b.index);
                            
                            dragGroups.splice(dragGroup.index, 1);
                            dragGroups = dragGroups.map((g, i) => {
                                return { ...g, index: i }
                            });
                            if(dropPosition === -1) { // 目标前
                                console.log('before');
                                dropGroups.splice(dropGroup.index, 0, dragGroup);
                                dropGroups = dropGroups.map((g, i) => {
                                    return { ...g, index: i, pcode: dropGroup.pcode }
                                });
                                modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                            }else if(dropPosition === 0) { // 目标内
                                console.log('in');
                                dropChildrenGroups.push({
                                    ...dragGroup,
                                    index: dropChildrenGroups.length,
                                    pcode: dropGroup.code
                                });
                                modifyGroups = modifyGroups.concat(dragGroups, dropChildrenGroups);
                            }else if(dropPosition === 1) { // 目标后
                                console.log('after');
                                dropGroups.splice(dropGroup.index + 1, 0, dragGroup);
                                dropGroups = dropGroups.map((g, i) => {
                                    return { ...g, index: i, pcode: dropGroup.pcode }
                                });
                                modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                            }
                        }
                    }
                }else { // 不跨级
                    console.log('不跨级');
                    if(dragGroup.pcode === dropGroup.pcode) { // 不跨组
                        console.log('不跨组');
                        let dGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                        dGroups.splice(dragGroup.index, 1, {code: 'temp', index: dragGroup.index});
                        if(dropPosition === -1) { // 目标前
                            console.log('before');
                            dGroups.splice(dropGroup.index, 0, dragGroup);
                            dGroups = dGroups.filter(g => g.code !== 'temp').map((g, i) => {
                                return { ...g, index: i }
                            });
                            modifyGroups = modifyGroups.concat(dGroups);
                        }else if(dropPosition === 0) { // 目标内
                            console.log('in');
                            return;
                        }else if(dropPosition === 1) { // 目标后
                            console.log('after');
                            dGroups.splice(dropGroup.index + 1, 0, dragGroup);
                            dGroups = dGroups.filter(g => g.code !== 'temp').map((g, i) => {
                                return { ...g, index: i }
                            });
                            modifyGroups = modifyGroups.concat(dGroups);
                        }
                    }else { // 跨组
                        console.log('跨组');
                        let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                        let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                        
                        dragGroups.splice(dragGroup.index, 1);
                        dragGroups = dragGroups.map((g, i) => {
                            return { ...g, index: i }
                        });
                        for(let i = 0; i < dropGroups.length; i++) {
                            if(dropGroups[i].code === dropGroup.code) {
                                if(dropPosition === -1) { // 目标前
                                    console.log('before');
                                    dropGroups.splice(i, 0, dragGroup);
                                    dropGroups = dropGroups.map((g, i) => {
                                        return { ...g, index: i, pcode: dropGroup.pcode }
                                    });
                                    modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                                }else if(dropPosition === 0) { // 目标内
                                    console.log('in');
                                    return; // 不允许
                                }else if(dropPosition === 1) { // 目标后
                                    console.log('after');
                                    dropGroups.splice(i + 1, 0, dragGroup);
                                    dropGroups = dropGroups.map((g, i) => {
                                        return { ...g, index: i, pcode: dropGroup.pcode }
                                    });
                                    modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                                }
                                break;
                            }
                        }
                    }
                }
                console.log(dragGroup, dropGroup, modifyGroups);
                yield put({ type: 'remoteModifyGroups', groups: modifyGroups });
            }catch(e) {
                console.log(e);
                message.error('位置调整失败');
            }
        },
        /**
         * 设置图表所属分组
         */
        *remoteSetChartGroup(action, { select, call, put }) {
            const { chart, group } = action;
            const chartCode = chart.code;
            const groupCode = group.code;
            try {
                let body = { 
                    id: chartCode,
                    groupId: groupCode
                }
                let res = yield call(service.fetch, {
                    url: URLS.GROUP_CHART_SET_GROUP,
                    body: body
                });
                console.log('设置图表所属分组', body, res);
                if(!res.err && res.data.code > 0) {
                    yield put({ type: 'setChartGroup', chartCode, groupCode });
                }else {
                    message.error('设置分组失败: ' + (res.err || res.data.msg));
                }
            } catch(e) {
                console.log(e);
                message.error('设置分组失败');
            }
        },
        *transfer(action, { put, call, select }) {
            const { userCode, chartCode } = action;
            const body = {
                userId: userCode,
                id: chartCode
            };
            try {
                const res = yield call(service.fetch, {
                    url: URLS.CHART_TRANSFER,
                    body
                });
                console.log('图表移交', body, res);
                if(!res.err && res.data.code > 0) {
                    const chart = yield select(state => state.present.chart);
                    const list = chart.list;
                    for(let i = 0; i < list.length; i++) {
                        if(list[i].code === chartCode) {
                            list.splice(i, 1);
                            break;
                        }
                    }
                    yield put({ type: 'list', list });
                    message.success('移交成功');
                }else {
                    console.log(body, res.err || res.data.msg);
                    message.error('移交失败');
                }
            }catch(e) {
                console.log(body, e);
                message.error('移交失败');
            }
        }
    },
    subscriptions: {
        setup({ dispatch, history }) {
            return history.listen(({ pathname, query }) => {}
        )}
    }
}