import html2canvas from 'html2canvas'
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: 'dashboardDesigner',
state: {
originData: {
code: null,
name: '标题',
items: [],
description: '',
thumbnail: '',
dirty: false,
editMode: true,
filterColumns: [],
filters: [],
dataSources: [],
relationColumns: [],
columnFetching: false,
},
name: '标题',
defaultLayout: { x: 0, y: 50, w: 12, h: 6, minW: 2, maxW: 12, minH: 1 },
items: [],
description: '',
thumbnail: '',
dirty: false,
editMode: true,
filterColumns: [],
filters: [],
dataSources: [], // 图表关联的所有数据源
relationColumns: [], // 自定义的列
columnFetching: false,
},
reducers: {
silentSetField(state, action) {
const { name, value } = action;
let obj = {};
obj[name] = value;
let newState = Object.assign({}, state, obj);
return newState;
},
setField(state, action) {
const { name, value } = action;
let obj = {};
obj[name] = value;
let newState = Object.assign({}, state, obj);
return Object.assign({}, newState, {dirty: true});
},
silentSetFields(state, action) {
const { fields } = action;
let obj = {};
fields.map(f => (obj[f.name] = f.value));
let newState = Object.assign({}, state, obj);
return newState;
},
setFields(state, action) {
const { fields } = action;
let obj = {};
fields.map(f => (obj[f.name] = f.value));
let newState = Object.assign({}, state, obj);
return Object.assign({}, newState, {dirty: true});
},
addChart(state, action) {
let { items, defaultLayout } = state;
const { chart } = action;
items = items.concat([{
code: chart.code,
chartCode: chart.code,
name: chart.name,
dataSourceCode: chart.dataSourceCode+'',
dataSourceName: chart.dataSourceName,
viewType: 'chart',
layout: defaultLayout,
}]);
return Object.assign({}, state, {items, dirty: true});
},
addCharts(state, action) {
let { items, defaultLayout } = state;
const { charts } = action;
items = items.concat(charts.map(c => ({
code: c.code,
chartCode: c.code,
name: c.name,
viewType: 'chart',
dataSourceCode: c.dataSourceCode+'',
dataSourceName: c.dataSourceName,
layout: defaultLayout,
})));
return Object.assign({}, state, {items, dirty: true});
},
deleteItem(state, action) {
let { items, dataSources, relationColumns, dirty } = state;
const { item } = action;
let count = 0;
let targetIndex = -1;
for(let i = 0; i < items.length; i++) {
let tempItem = items[i];
if(tempItem.dataSourceCode === item.dataSourceCode) {
count++;
}
if(tempItem.code === item.code) {
targetIndex = i;
}
}
if(count === 1) {
// 找到只有被删除的item使用的数据源并删除
let idx = dataSources.findIndex(d => d.code === item.dataSourceCode);
dataSources.splice(idx, 1);
// 同时删除已定义的关联字段
relationColumns.forEach(rc => {
rc.relations.forEach((r, x) => {
if(r.dataSourceCode === item.dataSourceCode) {
rc.relations.splice(x, 1);
}
})
});
}
if(targetIndex !== -1) {
items.splice(targetIndex, 1);
}
return { ...state, dirty: dirty, items, dataSources };
},
addRichText(state, action) {
let { items, defaultLayout } = state;
items.push({
code: Math.random(),
viewType: 'richText',
name: '',
layout: defaultLayout
});
return Object.assign({}, state, {items, dirty: true});
},
changeLayout(state, action) {
const { layout } = action;
let { items, dirty } = state;
const ly = ['x', 'y', 'w', 'h'];
for(let i = 0; i < items.length; i++) {
if(layout[i]) { // 非删除引起
for(let j = 0; j < ly.length; j ++) {
if(items[i].layout[ly[j]] !== layout[i][ly[j]]) {
dirty = true;
items[i].layout[ly[j]] = layout[i][ly[j]];
}
}
}else { // 删除引起
dirty = true;
}
}
return Object.assign({}, state, {items, dirty});
},
modifyItem(state, action) {
let { fields, dirty } = action;
let { items } = state;
for(let i = 0; i < items.length; i++) {
if(items[i].code === fields.code) {
for(let k in fields) {
items[i][k] = fields[k];
dirty = true;
}
}
}
return Object.assign({}, state, {items, dirty});
},
reset(state, action) {
let newState = Object.assign({}, state, state.originData);
return Object.assign({}, newState);
},
setEditMode(state, action) {
const { checked } = action;
return { ...state, editMode: checked };
},
addRelationColumn(state, action) {
const { relationColumns } = state;
relationColumns.push({
code: Math.random()+'',
name: '新字段',
relations: []
});
return { ...state, relationColumns, dirty: true };
},
deleteRelationColumn(state, action) {
const { code } = action;
const { relationColumns } = state;
let index = relationColumns.findIndex(r => r.code === code);
relationColumns.splice(index, 1);
console.log(relationColumns);
return { ...state, relationColumns, dirty: true };
},
setRelationColumn(state, action) {
const { code, relationColumn } = action
const { relationColumns } = state;
let index = relationColumns.findIndex(r => r.code === code);
relationColumns[index] = relationColumn;
return { ...state, relationColumns, dirty: true };
},
setChartFilters(state, action) {
let { items } = state;
const { chartCode, filters } = action;
let idx = items.findIndex(i => i.chartCode === chartCode);
if(idx !== -1) {
items[idx] = { ...items[idx], filters }
}
return { ...state, items };
},
addDataSource(state, action) {
let { dataSources } = state;
const { dataSource } = action;
dataSources.findIndex(d => d.code === dataSource.code) === -1 && dataSources.push(dataSource);
console.log(dataSources);
return { ...state, dataSources };
}
},
effects: {
*remoteGetColumns(action, { call, put, select }) {
const { dataSourceCode, mandatory } = action;
const dashboardDesigner = yield select(state => state.present.dashboardDesigner);
const { dataSources } = dashboardDesigner;
const body = dataSourceCode;
let idx = dataSources.findIndex(d => d.code === dataSourceCode);
if(!mandatory && dataSources[idx].columns && dataSources[idx].columns.length > 0) {
return;
}
try {
yield put({ type: 'silentSetField', field: 'columnFetching', value: true });
const res = yield call(service.fetch, {
url: URLS.DATASOURCE_QUERY_DATACOLUMNS,
body: body
});
yield put({ type: 'silentSetField', field: 'columnFetching', value: false });
console.log('获得列数据', body, res);
if(!res.err && res.data.code > 0) {
let resData = res.data.data;
let columns = resData.map((c, i) => {
return {
key: i,
name: c.columnName,
label: c.columnRaname,
type: c.columnType,
groupable: c.isGroup==='1'?true:false,
filterable: c.isFilter==='1'?true:false,
bucketizable: c.isSubsection==='1'?true:false,
selection: []
}
})
dataSources[idx] = { ...dataSources[idx], columns }
yield put({ type: 'silentSetField', name: 'dataSources', value: dataSources });
}else {
message.error('请求列数据失败:' + (res.err || res.data.msg));
yield put({ type: 'silentSetField', name: 'dataSources', value: [] });
}
}catch(e) {
console.log(e, body);
message.error('请求列数据失败');
}
},
*saveWithThumbnail(action, {put, call}) {
let thumbnail;
yield call(async ()=> {
try {
await html2canvas(document.getElementsByClassName('viewlayout')[0]).then(
function(canvas){
thumbnail = canvas.toDataURL('image/png', 1.0);
}
)
}catch (e) {
return null;
}
});
try {
yield put.resolve({ type: 'setField', name: 'thumbnail', value: thumbnail })
yield put.resolve({ type: 'dashboard/remoteModify' })
}catch (e){
message.error('保存失败');
}
}
},
subscription: {
},
};