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

export default {
    namespace: 'dataSource',
    state: {
        originData: {
            listLoading: false,
            list: [],
            filterLabel: '',
            invalidSQL: false,
            groupList: [],
            currentGroup: null,
            noGroup: false,
            filterItems: [ // 可选过滤字段
                { name: 'name', label: '名称', type: 'string' },
                { name: 'creatorName', label: '创建人', type: 'string' },
                { name: 'createTime', label: '创建时间', type: 'date' },
                { name: 'dbConfig.code', label: '数据链接', type: 'enum', options: () => {
                    return service.fetch({
                        url: URLS.DATACONNECT_LIST,
                        method: 'GET',
                        body: {
                            pageNum: 1,
                            pageSize: 999999999
                        }
                    }).then(res => {
                        if(res.code > 0) {
                            return res.data.list.map(l => ({
                                name: l.id,
                                label: l.name,
                            }));
                        }else {
                            message.error('获取数据源下拉列表失败: ' + res.msg);
                        }
                    }).catch(e => {
                        message.error('获取数据源下拉列表失败: ' + e.message);
                    });
                } },
            ],
            filterItem: { name: 'name', label: '名称', type: 'string' }, // 已选过滤字段
            listScrollTop: 0, // 记录列表界面滚动条位置
        }
    },
    reducers: {
        setField(state, action) {
            const { name, value } = action;
            let obj = {};
            obj[name] = value;
            return Object.assign({}, state, obj);
        },
        setFields(state, action) {
            const { fields } = action;
            let obj = {};
            fields.map(f => (obj[f.name] = f.value));
            return Object.assign({}, state, obj);
        },
        list(state, action) {
            const { list } = action;
            return { ...state, list };
        },
        delete(state, action) {
            const { model } = action;
            let { list } = state;
            for(let i = 0; i < list.length; i++) {
                if(list[i].code === model.code) {
                    list.splice(i, 1);
                }
            }
            return Object.assign({}, state, {list});

        },
        setFilterItem(state, action) {
            const { item } = action;
            return Object.assign({}, state, {filterItem: item, filterLabel: ''});
        },
        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 { group } = action;
            return Object.assign({}, state, {currentGroup: group});
        },
        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});
        },
        setDataSourceGroup(state, action) {
            const { dataSourceCode, groupCode } = action;
            let list = state.list;
            for(let i = 0; i < list.length; i++) {
                let l = list[i];
                if(l.code === dataSourceCode) {
                    list[i] = { ...l, groupCode }
                    break;
                }
            }
            return Object.assign({}, state, {list: list});
        },
        reset(state, action) {
            let newState = Object.assign({}, state, state.originData);
            return Object.assign({}, newState);
        },
    },
    effects: {
        *fetchList(action, { select, call, put, takeEvery, takeLatest }) {
            const { pageNum, pageSize } = action;
            const body = {
                pageNum: pageNum || 1,
                pageSize: pageSize || 999999999
            }
            try {
                const dataSource = yield select(state => state.dataSource);
                if(!action.mandatory && dataSource.list.length > 0) {
                    return;
                }
                if(!action.silent) {
                    yield put({ type: 'setField', name: 'listLoading', value: true });
                }
                const res = yield call(service.fetch, {
                    url: URLS.DATASOURCE_LIST,
                    method: 'GET',
                    body
                });
                
                if(res.code > 0) {
                    let list = res.data.list.map((r, i) => {
                        let dbConfig = {
                            code: r.dbConfig.id + '',
                            name: r.dbConfig.name,
                            dbName: r.dbConfig.dataName,
                            dbType: r.dbConfig.databaseType,
                            address: r.dbConfig.addrass,
                            port: r.dbConfig.port,
                            userName: r.dbConfig.userName,
                            password: r.dbConfig.passWord,
                            description: r.dbConfig.note,
                            demo: r.dbConfig.demo
                        };
                        let tags = JSON.parse(r.dataTag);
                        return {
                            key: r.dataId + '',
                            code: r.dataId + '',
                            name: r.dataName,
                            type: r.type || 'database',
                            dbConfig: dbConfig,
                            creatorName: r.createBy,
                            creatorCode: r.createId+'',
                            createTime: new Date(r.createDate),
                            tags: tags,
                            description: r.note,
                            groupCode: r.connectorGroup+'',
                            demo: r.demo
                        }
                    });
                    yield put({ type: 'list', list });
                }else {
                    message.error('读取数据源列表错误: ' + res.msg);
                }
            }catch(e) {
                message.error('读取数据源列表错误: ' + e.message);
            }finally {
                yield put({ type: 'setField', name: 'listLoading', value: false });
            }
            
        },
        *remoteAdd(action, { select, call, put }) {
            const dataSourceDetail = yield select(state => state.dataSourceDetail);
            const currentUserName = yield select(state => state.main.currentUser.name)
            const { name, description, target, tags, type, connectCode, columns, group } = dataSourceDetail;
            try {
                const data = {
                    dataName: name,
                    note: description,
                    loadObject: target,
                    dataTag: tags,
                    type: type,
                    createBy: currentUserName,
                    dbConId: connectCode,
                    columnConfig: columns.map((c, i) => {
                        return {
                            columnName: c.name,
                            columnLable: c.alias || c.description || c.name,
                            dataType: c.dataType,
                            columnType: c.columnType,
                            isGroup: c.groupable?'1':'0',
                            isFilter: c.filterable?'1':'0',
                            isSubsection: c.bucketizable?'1':'0',
                            isOpen: c.using?'1':'0',
                            remarks: c.description
                        }
                    }),
                    connectorGroup: group ? group : '-1'
                };
                const res = yield call(service.fetch, {
                    url: URLS.DATASOURCE_ADD,
                    body: data
                });
                if(res.code > 0) {
                    yield put({ type: 'fetchList', mandatory: true });
                    yield put({ type: 'main/redirect', path: { pathname: '/workshop/datasource' } });
                    message.success('新增成功');
                }else {
                    message.error('新增失败: ' + res.msg);
                }
            }catch(e) {
                message.error('新增失败: ' + e.message);

            }
        },
        *remoteDetail(action, { select, call, put }) {
            try {
                const code = action.code;

                const res = yield call(service.fetch, {
                    url: URLS.DATASOURCE_DETAIL,
                    method: 'GET',
                    body: {
                        id: code
                    }
                });
                if(res.code > 0) {
                    let resData = res.data;
                    let columnConfig = JSON.parse(resData.columnConfig) || [];
                    let dbConfig = resData.dbConfig;
                    let tags = JSON.parse(resData.dataTag);
                    let data = {
                        code: resData.dataId + '',
                        name: resData.dataName,
                        type: resData.type,
                        connectCode: dbConfig.id + '',
                        dbType: dbConfig.databaseType,
                        dbName: dbConfig.dataName,
                        address: dbConfig.addrass,
                        port: dbConfig.port,
                        target: resData.loadObject,
                        creatorName: resData.createBy,
                        creatorCode: resData.createId+'',
                        createTime: new Date(resData.createDate),
                        userName: dbConfig.userName,
                        password: dbConfig.passWord,
                        tags: tags,
                        description: resData.note,
                        group: resData.connectorGroup+'',
                        columns: columnConfig.map((c, i) => {
                            return {
                                key: i,
                                using: c.isOpen==='1'?true:false,
                                name: c.columnName,
                                alias: c.columnLable,
                                dataType: c.dataType,
                                columnType: c.columnType,
                                groupable: c.isGroup==='1'?true:false,
                                filterable: c.isFilter==='1'?true:false,
                                bucketizable: c.isSubsection==='1'?true:false,
                                description: c.remarks
                            }
                        }),
                        demo: resData.demo
                    }
                    let fields = [];
                    for(let key in data) {
                        fields.push({
                            name: key,
                            value: data[key]
                        })
                    }
                    yield put({ type: 'dataSourceDetail/silentSetFields', fields: fields });
                }else {
                    message.error('数据源解析错误: ' + res.msg);
                }
            }catch(e) {
                message.error('数据源解析错误: ' + e.message);
                yield put({ type: 'list', list: [] });
            }
        },
        *remoteDelete(action, { select, call, put }) {
            const dataSource = yield select(state => state.dataSource);
            const code = action.code;
            let list = dataSource.list;
            try {
                const res = yield call(service.fetch, {
                    url: URLS.DATASOURCE_DELETE,
                    body: code
                });
                if(res.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 });
                    message.success('删除成功');
                }else {
                    message.error('删除失败: ' + res.msg);
                }
            }catch(e) {
                message.error('删除失败: ' + e.message);
            }
        },
        *remoteModify(action, { select, call, put }) {
            try{
                const dataSourceDetail = yield select(state => state.dataSourceDetail);
                const currentUserName = yield select(state => state.main.currentUser.name)
                const { code, name, description, target, type, group, connectCode, columns } = dataSourceDetail;
    
                let data = {
                    dataId: code,
                    dataName: name,
                    note: description,
                    loadObject: target,
                    dataTag: null,
                    type: type,
                    createBy: currentUserName,
                    connectorGroup: group ? group : '-1',
                    dbConId: connectCode,
                    columnConfig: columns ? columns.map((c, i) => {
                        return {
                            columnName: c.name,
                            columnLable: c.alias || c.description || c.name,
                            dataType: c.dataType,
                            columnType: c.columnType,
                            isGroup: c.groupable?'1':'0',
                            isFilter: c.filterable?'1':'0',
                            isSubsection: c.bucketizable?'1':'0',
                            isOpen: c.using?'1':'0',
                            remarks: c.description
                        }
                    }) : '',
                };
                const res = yield call(service.fetch, {
                    url: URLS.DATASOURCE_UPDATE,
                    body: data
                });
                if(res.code > 0) {
                    yield put({ type: 'fetchList', mandatory: true });
                    yield put({ type: 'dataSourceDetail/setDirty', dirty: false });
                    message.success('保存成功');
                }else {
                    message.error('保存失败: ' + res.msg);
    
                }
            }catch(e) {
                message.error('保存失败: ' + e.message);
            }
        },

        *remoteGroupList(action, { select, call, put }) {
            try {
                const dataSource = yield select(state => state.dataSource);
                if(!action.mandatory && dataSource.groupList.length > 0) {
                    return;
                }
                const res = yield call(service.fetch, {
                    url: URLS.GROUP_DATASOURCE_LIST,
                });
                
                if(res.code > 0) {
                    const resData = res.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.msg);
                }
            }catch(e) {
                message.error('请求数据源列表错误: ' + e.message);
            }
        },

        *remoteSetGroups(action, { select, call, put }) {
            const { aGroups, mGroups, dGroups } = action;
            const body = aGroups.concat(mGroups).concat(dGroups).map(g => ({
                id: g.operate === 'add' ? null : g.code,
                fatherId: g.pcode,
                groupIndex: g.index,
                operate: g.operate,
                groupName: g.label
            }))
            try{
                const res = yield call(service.fetch, {
                    url: URLS.GROUP_DATASOURCE_BATCH_SET,
                    body
                });
                if(res.code > 0) {
                    message.success('修改分组信息成功');
                    yield put({ type: 'remoteGroupList', mandatory: true });
                    return true;
                }else {
                    message.error('修改分组信息失败: ' + res.msg);
                    return false;
                }
            }catch(e) {
                message.error('修改分组信息失败: ' + e.message);
            }
        },
        /**
         * 新增分组/子分组，需要传入父节点code
         */
        *remoteAddGroup(action, { select, call, put }) {
            try {
                const dataSource = yield select((state) => state.dataSource);
                const group = dataSource.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,
                    }
                }else {
                    body = {
                        fatherId: '-1',
                        groupName: '新分组',
                        groupIndex: pgroups.length,
                    }
                }
                const res = yield call(service.fetch, {
                    url: URLS.GROUP_DATASOURCE_ADD,
                    body: body
                });
                if(res.code > 0) {
                    let group = {
                        code: res.data + '',
                        pcode: body.fatherId + '',
                        index: body.groupIndex,
                        label: body.groupName+'',
                    }
                    yield put({ type: 'addGroup', group });
                }else {
                    message.error('新增分组失败: ' + res.msg);
                }
            }catch(e) {
                message.error('新增分组失败: ' + e.message);
            }
        },
        /**
         * 修改单个分组信息（因为不涉及顺序号的修改，所以一般只用于label的修改）
         */
        *remoteModifyGroup(action, { select, call, put }) {
            try {
                const group = action.group;

                let body = {
                    id: group.code,
                    fatherId: group.pcode,
                    groupName: group.label,
                    groupIndex: group.index,
                }
                const res = yield call(service.fetch, {
                    url: URLS.GROUP_DATASOURCE_UPDATE,
                    body: body
                });
                if(res.code > 0) {
                    yield put({ type: 'setGroupDirty', dirty: false });
                }else {
                    message.error('修改分组失败: ' + res.msg);
                }
            }catch(e) {
                message.error('修改分组失败: ' + e.message);
            }
        },
        /**
         * 批量修改多个分组信息(在移动位置时用)
         */
        *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,
                    }
                });
                const res = yield call(service.fetch, {
                    url: URLS.GROUP_DATASOURCE_LIST_UPDATE,
                    body: body
                });
                
                if(res.code > 0) {
                    yield put({ type: 'modifyGroups', groups: groups });
                }else {
                    message.error('修改分组失败: ' + res.msg);
                }
            }catch(e) {
                message.error('修改分组失败: ' + e.message);
            }
        },
        *remoteDeleteGroup(action, { select, call, put }) {
            try {
                const dataSource = yield select((state) => state.dataSource);
                const groupList = dataSource.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_DATASOURCE_DELETE,
                    body: group.code
                });
                
                if(res.code > 0) {
                    yield put({ type: 'deleteGroup', group});
                }else {
                    message.error('删除分组失败: ' + res.msg);
                }
            }catch(e) {
                message.error('删除分组失败: ' + e.message);
            }
        },
        *remoteMoveGroup(action, { select, call, put }) {
            try {
                const { dragCode, dropCode, dropPosition } = action;
                const dataSource = yield select((state) => state.dataSource);
                let group = dataSource.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)) { // 跨级
                    if(dropGroup.pcode !== '-1') { // 从父级到子级
                        return; // 不允许
                    }else { // 从子级到父级
                        if(dragGroup.pcode === dropGroup.code) { // 不跨组
                            if(dropPosition === -1) { // 目标前
                                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) { // 目标内
                                return; // 无变化
                            }else if(dropPosition === 1) { // 目标后
                                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) { // 目标前
                                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) { // 目标内
                                dropChildrenGroups.push({
                                    ...dragGroup,
                                    index: dropChildrenGroups.length,
                                    pcode: dropGroup.code
                                });
                                modifyGroups = modifyGroups.concat(dragGroups, dropChildrenGroups);
                            }else if(dropPosition === 1) { // 目标后
                                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 { // 不跨级
                    if(dragGroup.pcode === dropGroup.pcode) { // 不跨组
                        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) { // 目标前
                            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) { // 目标内
                            return;
                        }else if(dropPosition === 1) { // 目标后
                            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 { // 跨组
                        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) { // 目标前
                                    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) { // 目标内
                                    return; // 不允许
                                }else if(dropPosition === 1) { // 目标后
                                    dropGroups.splice(i + 1, 0, dragGroup);
                                    dropGroups = dropGroups.map((g, i) => {
                                        return { ...g, index: i, pcode: dropGroup.pcode }
                                    });
                                    modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                                }
                                break;
                            }
                        }
                    }
                }
                yield put({ type: 'remoteModifyGroups', groups: modifyGroups });
            }catch(e) {
                message.error('位置调整失败: ' + e.message);
            }
        },
        /**
         * 为数据源设置所属分组
         */
        *remoteSetGroup(action, { select, call, put }) {

            const { dataSource, group } = action;
            const dataSourceCode = dataSource.code;
            const groupCode = group.code;
            try {
                let body = { 
                    id: dataSourceCode,
                    groupId: groupCode
                }
                let res = yield call(service.fetch, {
                    url: URLS.GROUP_DATASOURCE_SET_GROUP,
                    body: body
                });
                if(res.code > 0) {
                    yield put({ type: 'setDataSourceGroup', dataSourceCode, groupCode });
                }else {
                    message.error('设置分组失败: ' + res.msg);
                }
            } catch(e) {
                message.error('设置分组失败: ' + e.message);
            }
        },
        *transfer(action, { put, call, select }) {
            const { userCode, dataSourceCode } = action;
            const body = {
                userId: userCode,
                id: dataSourceCode
            };
            try {
                const res = yield call(service.fetch, {
                    url: URLS.DATASOURCE_TRANSFER,
                    body
                });
                if(res.code > 0) {
                    const dataSource = yield select(state => state.dataSource);
                    const list = dataSource.list;
                    for(let i = 0; i < list.length; i++) {
                        if(list[i].code === dataSourceCode) {
                            list.splice(i, 1);
                            break;
                        }
                    }
                    yield put({ type: 'list', list });
                    yield put({ type: 'chart/fetchList', mandatory: true });
                    message.success('移交成功');
                }else {
                    message.error('移交失败');
                }
            }catch(e) {
                message.error('移交失败: ' + e.message);
            }
        },
        /**
         * 预览数据
         */
        *remoteDataList(action, { put, call, select }) {
            const { code, page, pageSize } = action;
            const body = {
                id: code,
                testPage: {
                    pageNum: page || 1,
                    pageSize: pageSize || 25,
                }
            };

            try {
                yield put({ type: 'dataList/setField', name: 'loading', value: true });
                const res = yield call(service.fetch, {
                    url: URLS.DATASOURCE_DATA_LIST,
                    body
                });
                if(res.code > 0) {
                    const { columnConfig, values } = res.data;
                    const columns = JSON.parse(columnConfig).filter(c => c.isOpen === '1').map(c => ({
                        label: c.columnLable,
                        name: c.columnName,
                        type: c.columnType,
                    }));
                    const { list: dataSource, pageSize, total } = values;

                    yield put({ type: 'dataList/setFields', fields: [
                        { name: 'columns', value: columns },
                        { name: 'dataSource', value: dataSource },
                        { name: 'pageSize', value: pageSize },
                        { name: 'total', value: total }
                    ] });
                    // 主动触发一次window的resize事件
                    yield window.setTimeout(() => {
                        var e = document.createEvent("Event");
                        e.initEvent("resize", true, true);
                        window.dispatchEvent(e);
                    }, 20);
                    return {
                        columns,
                        dataSource,
                        pageSize,
                        total
                    }
                }else {
                    message.error('请求数据列表失败: ' + res.msg);
                    return false;
                }
            }catch(e) {
                message.error('请求数据列表失败: ' + e.message);
            }finally {
                yield put({ type: 'dataList/setField', name: 'loading', value: false });
            }
        },
        *copy(action, { select, call, put }) {
            const { dataSourceCode, dataConnectCode } = action;

            const res = yield call(service.fetch, {
                url: URLS.DATASOURCE_COPY,
                body: {
                    dataSourceId: dataSourceCode,
                    dataConnectionId: dataConnectCode
                }
            });
            if(res.code > 0) {
                message.success('复制成功');
                yield put({ type: 'fetchList', mandatory: true });
                return true;
            }else {
                message.error('复制失败: ' + res.msg);
                return false;
            }
        }
    },
    subscriptions: {
        setup({ dispatch, history }) {
            dispatch({ type: 'reset' });
        }
    }
};