import { message } from 'antd' import * as service from '../services/index' import URLS from '../constants/url' import CHART_TYPE from './chartType.json' export default { namespace: 'chart', state: { originData: { 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}); }, reset(state, action) { let newState = Object.assign({}, state, state.originData); return Object.assign({}, newState); }, }, effects: { *fetchList(action, { select, call, put }) { const { pageNum, pageSize } = action; const body = { pageNum: pageNum || 1, pageSize: pageSize || 999 } 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, method: 'GET', body }); if(!res.err && res.data.code > 0) { let list = res.data.data.list.map(d => { let chartOption = d.chartOption ? JSON.parse(d.chartOption) : {}; return { code: d.chartId+'', name: d.chartName, dataSourceCode: d.dataId + '', dataSourceName: d.dataName, dataConnectCode: d.dataConnectionId, dataConnectName: d.dataConnectionName, access: d.authority === '1', // 权限 database: d.dbStatus === '0', // 数据源是否还存在 type: CHART_TYPE[d.chartType], creatorCode: d.createId + '', creatorName: d.createBy, createTime: d.createDate, description: d.describes || '', groupCode: d.chartsGroup + '', chartOption: chartOption, demo: d.demo } }) yield put({ type: 'list', list: list }); }else { message.error('请求图表列表失败: ' + (res.err || res.data.msg)); } }catch(e) { message.error('请求图表列表失败: ' + e); } }, *remoteDetail(action, { select, call, put }) { const code = action.code; if(!code){ return } try { const res = yield call(service.fetch, { url: URLS.CHART_DETAIL, method: 'GET', body: { id: code } }); if(!res.err && res.data.code > 0) { let resData = res.data.data; let chartConfig = JSON.parse(resData.chartConfig || '{ "xAxis": { "column": {}, "granularity": {} }, "yAxis": { "column": {}, "gauge": {} } }'); let styleConfig = JSON.parse(resData.style || '{}'); let otherConfig = JSON.parse(resData.otherConfig || '{}'); let viewType = CHART_TYPE[resData.chartType]; let filters = JSON.parse(resData.filters || '[]'); let chartOption = JSON.parse(resData.chartOption || '{}'); let data = { code: resData.chartId + '', creatorCode: resData.createId+'', creatorName: resData.createBy, dataSourceCode: resData.dataId + '', dataSourceName: resData.dataName, dataConnectCode: resData.dataConnectionId, dataConnectName: resData.dataConnectionName, header: { label: resData.chartName }, baseConfig: { dataSource: { code: resData.dataId + '', name: resData.dataName, }, viewType: viewType }, styleConfig: styleConfig, otherConfig: otherConfig, description: resData.describes, group: resData.chartsGroup+'', filters: filters, chartOption: chartOption, demo: resData.demo } if(viewType === 'bar') { data.barConfig = chartConfig; }else if(viewType === 'pie') { data.pieConfig = chartConfig; }else if(viewType === 'line') { data.lineConfig = chartConfig; }else if(viewType === 'scatter') { data.scatterConfig = chartConfig; }else if(viewType === 'aggregateTable') { data.aggregateTableConfig = chartConfig; }else if(viewType === 'dataView') { data.dataViewConfig = chartConfig; } let fields = []; for(let key in data) { fields.push({ name: key, value: data[key] }) } yield put({ type: 'chartDesigner/defaultChangeFields', fields: fields }); yield put({ type: 'chartDesigner/changeDataSource', dataSource: data.baseConfig.dataSource }); }else { message.error('解析图表错误: ' + (res.err || res.data.msg)); } }catch(e) { message.error('解析图表错误: ' + e); } }, *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.code, 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); }else if(baseConfig.viewType === 'pie') { body.chartType = 'Pie'; body.chartConfig = JSON.stringify(pieConfig); }else if(baseConfig.viewType === 'line') { body.chartType = 'Line'; body.chartConfig = JSON.stringify(lineConfig); }else if(baseConfig.viewType === 'scatter') { body.chartType = 'scatter'; body.chartConfig = JSON.stringify(scatterConfig); }else if(baseConfig.viewType === 'aggregateTable') { body.chartType = 'population'; body.chartConfig = JSON.stringify(aggregateTableConfig); }else if(baseConfig.viewType === 'dataView') { body.chartType = 'individual'; body.chartConfig = JSON.stringify(dataViewConfig); }else { body.chartType = ''; body.chartConfig = JSON.stringify({}); } const res = yield call(service.fetch, { url: URLS.CHART_ADD, body: body }) 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('新增失败: ' + e); } }, *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, fetchConfig, styleConfig } = chartDesigner; let body = { chartId: code, filters: JSON.stringify(filters), chartName: header.label, dataId: baseConfig.dataSource.code, describes: description || '', style: JSON.stringify(styleConfig), otherConfig: JSON.stringify(otherConfig), chartsGroup: group+'' ? group : '-1', chartOption: JSON.stringify(chartOption), fetchConfig: JSON.stringify(fetchConfig), }; // 基本属性 if(baseConfig.viewType === 'bar') { body.chartType = 'Histogram'; body.chartConfig = JSON.stringify(barConfig); }else if(baseConfig.viewType === 'pie') { body.chartType = 'Pie'; body.chartConfig = JSON.stringify(pieConfig); }else if(baseConfig.viewType === 'line') { body.chartType = 'Line'; body.chartConfig = JSON.stringify(lineConfig); }else if(baseConfig.viewType === 'scatter') { body.chartType = 'scatter'; body.chartConfig = JSON.stringify(scatterConfig); }else if(baseConfig.viewType === 'aggregateTable') { body.chartType = 'population'; body.chartConfig = JSON.stringify(aggregateTableConfig); }else if(baseConfig.viewType === 'dataView') { body.chartType = 'individual'; body.chartConfig = JSON.stringify(dataViewConfig); } 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('修改失败: ' + e); } }, *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('删除失败: ' + e); } }, *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('读取图表分组列表错误: ' + e); } }, /** * 新增分组/子分组,需要传入父节点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, } }else { body = { fatherId: '-1', groupName: '新分组', groupIndex: pgroups.length, } } console.log('新增图表分组', body); 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('添加分组失败: ' + e); } }, /** * 修改单个分组信息(因为不涉及顺序号的修改,所以一般只用于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, } 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('修改分组失败: ' + 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, } }); 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('修改分组失败: ' + e); } }, *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 }); if(!res.err && res.data.code > 0) { yield put({ type: 'deleteGroup', group}); }else { message.error('删除分组失败: ' + (res.err || res.data.msg)); } }catch(e) { message.error('删除分组失败: ' + e); } }, *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('位置调整失败: ' + e); } }, /** * 设置图表所属分组 */ *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('设置分组失败: ' + e); } }, *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('移交失败: ' + (res.err || res.data.msg)); } }catch(e) { console.log(body, e); message.error('移交失败: ' + e); } }, }, subscriptions: { setup({ dispatch, history }) { dispatch({ type: 'reset' }); } } }