import { message } from 'antd' import * as service from '../services/index' import URLS from '../constants/url' import DEFAULT_COLUMN_TYPE from './defaultColumnType.json' export default { namespace: 'dataSource', state: { newOne: {}, list: [], filterLabel: '', invalidSQL: false, groupList: [], currentGroup: [{ code: 'all', label: '全部分组' }], groupDirty: false }, reducers: { list(state, action) { const { list } = action; return { ...state, list }; }, modify(state, action) { const { newOne } = state; let list = state.list; for(let i = 0; i < list.length; i++) { if(list[i].code === newOne.code) { list[i] = Object.assign({}, newOne); break; } } return Object.assign({}, 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}); }, setNewModelFields(state, action) { const { fields } = action; let newOne = state.newOne; for(let i = 0; i < fields.length; i++) { newOne[fields[i]['name']] = fields[i]['value']; } let obj = Object.assign({}, state, {newOne}); return obj; }, setNewModelField(state, action) { const { name, value } = action; let newOne = state.newOne; newOne[name] = value; let obj = Object.assign({}, state, {newOne}); return obj; }, setNewModel(state, action) { const { model } = action; let newOne = Object.assign({}, model); return Object.assign({}, state, {newOne}); }, resetNewModel(state, action) { return Object.assign({}, state, {newOne: {}}); }, setFilterLabel(state, action) { const { label } = action; return Object.assign({}, state, {filterLabel: label}); }, setNewModelInvalidSQL(state, action) { const { value } = action; let newOne = state.newOne; newOne.invalidSQL = value; return Object.assign({}, state, {newOne}); }, 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}); }, 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) { l.groupCode = groupCode; break; } } return Object.assign({}, state, {list: list}); } }, effects: { *fetchList(action, { select, call, put, takeEvery, takeLatest }) { const { pageNum, pageSize } = action; const body = { pageNum: pageNum || 1, pageSize: pageSize || 999 } try { const dataSource = yield select(state => state.present.dataSource); if(!action.mandatory && dataSource.list.length > 0) { return; } const res = yield call(service.fetch, { url: URLS.DATASOURCE_LIST, body }); console.log('请求数据源列表', body, res); if(!res.err && res.data.code > 0) { let list = res.data.data.list.map((r, i) => { let dbConfig = JSON.parse(r.dbConfig); let tags = JSON.parse(r.dataTag); return { key: r.dataId + '', code: r.dataId + '', name: r.dataName, type: r.type || 'database', dbType: dbConfig.databaseType, creatorName: r.createBy, creatorCode: r.createId+'', createTime: new Date(r.createDate), tags: tags, description: r.note, groupCode: r.connectorGroup+'' } }); yield put({ type: 'list', list }); }else { message.error('读取数据源列表错误: ' + (res.err || res.data.msg)); } }catch(e) { console.error(body, e); message.error('读取数据源列表错误: ' + e); } }, *remoteAdd(action, { select, call, put }) { const dataSource = yield select(state => state.present.dataSource); const model = dataSource.newOne; try { const data = { dataName: model.name, note: model.description, loadObject: model.target, dataTag: model.tags, type: model.type, createBy: 'admin', dbConfig: { id: model.connectCode, addrass: model.address, port: model.port, databaseType: model.dbType, dataName: model.dbName, userName: model.userName, passWord: model.password }, columnConfig: model.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: model.group ? model.group : '-1' }; const res = yield call(service.fetch, { url: URLS.DATASOURCE_ADD, body: data }); console.log('新增数据源', data, res); if(!res.err && res.data.code > 0) { yield put({ type: 'fetchList', mandatory: true }); yield put({ type: 'main/redirect', path: { pathname: '/datasource' } }); message.success('新增成功'); }else { message.error('新增失败: ' + (res.err || res.data.msg)); } }catch(e) { message.error('新增失败: ' + e); } }, *remoteDetail(action, { select, call, put }) { try { const code = action.code; const dataSource = yield select(state => state.present.dataSource); const model = dataSource.newOne; if((code + '') === (model.code + '')) { return; } const res = yield call(service.fetch, { url: URLS.DATASOURCE_DETAIL, body: code }); console.log('解析数据源', code, res); if(!res.err && res.data.code > 0) { let resData = res.data.data; let columnConfig = JSON.parse(resData.columnConfig); let dbConfig = JSON.parse(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 } }) } yield put({ type: 'setNewModel', model: data }); }else { message.error('数据源解析错误: ' + (res.err || res.data.msg)); } }catch(e) { console.log(e); message.error('数据源解析错误: ' + e); yield put({ type: 'list', list: [] }); } }, *importNewModelColumns(action, { select, call, put }) { const dataSource = yield select(state => state.present.dataSource); const sqlStr = dataSource.newOne.target; const oldColumns = dataSource.newOne.columns; const { cover } = action; let body = { id: dataSource.newOne.connectCode, strSql: sqlStr }; try{ const res = yield call(service.fetch, { url: URLS.DATASOURCE_QUERY_SQLCOLUMNS, body: body, timeout: 120000 }); const getColumnType = (dataType) => { return DEFAULT_COLUMN_TYPE[dataType] || 'categorical'; } console.log('请求列数据', body, res); if(!res.err && res.data.code > 0) { // let columns = res.data.data.map((d, i) => { // return { // key: i, // using: true, // name: d, // alias: d.remarks ? d.remarks.substring(0, 10) : (d), // dataType: d.columnType, // columnType: getColumnType(d.columnType), // // groupable: d.columnType === 'VARCHAR2', // groupable: true, // filterable: true, // bucketizable: d.columnType === 'NUMBER', // description: d.remarks // } // }); let columns = res.data.data.map((d, i) => { return { key: i, using: true, name: d.columnName, alias: d.columnName, dataType: d.columnType, columnType: getColumnType(d.columnType), groupable: d.columnType === 'String', filterable: true, // bucketizable: d.columnType === 'BigDecimal', } }); yield put({ type: 'setNewModelInvalidSQL', value: columns.length === 0 }); // yield put({ type: 'setNewModelField', name: 'columns', value: columns }); if(cover) { yield put({ type: 'setNewModelField', name: 'columns', value: columns }); }else { let mergeColumns = []; columns.forEach(c => { let tc = oldColumns.find(o => o.name === c.name ); if(tc) { mergeColumns.push(tc); }else { mergeColumns.push(c); } }); yield put({ type: 'setNewModelField', name: 'columns', value: mergeColumns }); } }else { yield put({ type: 'setNewModelInvalidSQL', value: true }); yield put({ type: 'setNewModelField', name: 'columns', value: [] }); } }catch(e) { console.log(body) yield put({ type: 'setNewModelInvalidSQL', value: true }); yield put({ type: 'setNewModelField', name: 'columns', value: [] }); message.error('请求列数据错误: ' + e); } }, *remoteDelete(action, { select, call, put }) { const dataSource = yield select(state => state.present.dataSource); const code = action.code; let list = dataSource.list; try { const res = yield call(service.fetch, { url: URLS.DATASOURCE_DELETE, body: [code] }); 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 }); message.success('删除成功'); }else { message.error('删除失败: ' + (res.err || res.data.msg)); } }catch(e) { console.log(e); message.error('删除失败: ' + e); } }, *remoteModify(action, { select, call, put }) { try{ const dataSource = yield select(state => state.present.dataSource); let model = action.model || dataSource.newOne; const code = model.code; let data = { dataId: code, dataName: model.name, note: model.description, loadObject: model.target, dataTag: model.tags, type: model.type, createBy: 'admin', connectorGroup: model.group ? model.group : '-1', dbConfig: model.address ? { addrass: model.address, port: model.port, databaseType: model.dbType, dataName: model.dbName, userName: model.userName, passWord: model.password } : '', columnConfig: model.columns ? model.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 }); console.log('修改数据源', data, res); if(!res.err && res.data.code > 0) { yield put({ type: 'fetchList', mandatory: true }); message.success('修改成功'); }else { message.error('修改失败: ' + (res.err || res.data.msg)); } }catch(e) { console.log(e); message.error('修改失败: ' + e); } }, *remoteGroupList(action, { select, call, put }) { try { const dataSource = yield select(state => state.present.dataSource); if(!action.mandatory && dataSource.groupList.length > 0) { return; } const res = yield call(service.fetch, { url: URLS.GROUP_DATASOURCE_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('请求数据源列表错误: ' + e); } }, /** * 新增分组/子分组,需要传入父节点code */ *remoteAddGroup(action, { select, call, put }) { try { const dataSource = yield select((state) => state.present.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 }); 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('新增分组失败: ' + e); } }, /** * 修改单个分组信息(因为不涉及顺序号的修改,所以一般只用于label的修改) */ *remoteModifyGroup(action, { select, call, put }) { try { const dataSource = yield select((state) => state.present.dataSource); const groupDirty = dataSource.groupDirty; const group = action.group; if(!groupDirty) { // 如果属性无改动则取消修改请求 return; } let body = { id: group.code, fatherId: group.pcode, groupName: group.label, groupIndex: group.index, } console.log('修改数据源分组', body); const res = yield call(service.fetch, { url: URLS.GROUP_DATASOURCE_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('修改分组失败: ' + e); } }, /** * 批量修改多个分组信息(在移动位置时用) */ *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, } }); console.log('批量修改数据源分组', body); const res = yield call(service.fetch, { url: URLS.GROUP_DATASOURCE_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('修改分组失败: ' + e); } }, *remoteDeleteGroup(action, { select, call, put }) { try { const dataSource = yield select((state) => state.present.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] }); 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('删除分组失败: ' + e); } }, *remoteMoveGroup(action, { select, call, put }) { try { const { dragCode, dropCode, dropPosition } = action; const dataSource = yield select((state) => state.present.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)) { // 跨级 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('位置调整失败: ' + e); } }, /** * 为数据源设置所属分组 */ *remoteSetDataSourceGroup(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 }); console.log('设置数据源所属分组', body, res); if(!res.err && res.data.code > 0) { yield put({ type: 'setDataSourceGroup', dataSourceCode, groupCode }); }else { message.error('设置分组失败: ' + (res.err || res.data.msg)); } } catch(e) { console.log(e); message.error('设置分组失败: ' + e); } }, *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 }); console.log('数据源移交', body, res); if(!res.err && res.data.code > 0) { const dataSource = yield select(state => state.present.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 { console.log(body, (res.err || res.data.msg)); message.error('移交失败'); } }catch(e) { console.log(body, e); message.error('移交失败: ' + e); } } }, subscriptions: { setup({ dispatch, history }) { return history.listen(({ pathname, query }) => { }) } } };