|
@@ -6,9 +6,9 @@ import { deepAssign } from '../utils/baseUtils';
|
|
|
import STATISTICS_OPTION from '../components/chartDesigner/sections/statisticsOption.json';
|
|
import STATISTICS_OPTION from '../components/chartDesigner/sections/statisticsOption.json';
|
|
|
import moment from 'moment';
|
|
import moment from 'moment';
|
|
|
|
|
|
|
|
-function getBodyFilters(filters) {
|
|
|
|
|
|
|
+function getBodyFilters(filters,drillDown) {
|
|
|
let bodyFilters = [];
|
|
let bodyFilters = [];
|
|
|
- filters.filter(f => f.using).forEach(f => {
|
|
|
|
|
|
|
+ filters.forEach(f => {
|
|
|
let { name, operator, type, value1, value2 } = f;
|
|
let { name, operator, type, value1, value2 } = f;
|
|
|
if(((type === 'index' || type === 'string') && !!value1) || // 因为数字类型会生成数字字符串,所以为0也是可以正常传入条件的
|
|
if(((type === 'index' || type === 'string') && !!value1) || // 因为数字类型会生成数字字符串,所以为0也是可以正常传入条件的
|
|
|
((type === 'scale' || type === 'time' || type === 'ordinal') && (operator === 'between' ? (!!value1 && !!value2) : (!!value1))) ||
|
|
((type === 'scale' || type === 'time' || type === 'ordinal') && (operator === 'between' ? (!!value1 && !!value2) : (!!value1))) ||
|
|
@@ -29,6 +29,12 @@ function getBodyFilters(filters) {
|
|
|
let v1 = value1.dynamic ? value1.name : moment(value1).format('YYYY-MM-DD');
|
|
let v1 = value1.dynamic ? value1.name : moment(value1).format('YYYY-MM-DD');
|
|
|
let v2 = value2.dynamic ? value2.name : moment(value2).format('YYYY-MM-DD');
|
|
let v2 = value2.dynamic ? value2.name : moment(value2).format('YYYY-MM-DD');
|
|
|
|
|
|
|
|
|
|
+ if(drillDown){
|
|
|
|
|
+ v1 = value1;
|
|
|
|
|
+ v2 = value2;
|
|
|
|
|
+ bodyFilter['type'] = f.drillDownType;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if(operator === 'between') {
|
|
if(operator === 'between') {
|
|
|
bodyFilter['value'] = v1 + ',' + v2;
|
|
bodyFilter['value'] = v1 + ',' + v2;
|
|
|
}else {
|
|
}else {
|
|
@@ -396,28 +402,40 @@ export default {
|
|
|
const chartDesigner = yield select(state => state.present.chartDesigner);
|
|
const chartDesigner = yield select(state => state.present.chartDesigner);
|
|
|
const { baseConfig } = chartDesigner;
|
|
const { baseConfig } = chartDesigner;
|
|
|
const { viewType } = baseConfig;
|
|
const { viewType } = baseConfig;
|
|
|
- const { page, pageSize } = action;
|
|
|
|
|
|
|
+ const { page, pageSize, drillDown } = action;
|
|
|
|
|
|
|
|
try{
|
|
try{
|
|
|
yield put({ type: 'silentSetField', name: 'fetchConfig', value: {} });
|
|
yield put({ type: 'silentSetField', name: 'fetchConfig', value: {} });
|
|
|
if(viewType === 'bar') {
|
|
if(viewType === 'bar') {
|
|
|
const { barConfig } = chartDesigner;
|
|
const { barConfig } = chartDesigner;
|
|
|
- if(barConfig.xAxis.column.value && barConfig.yAxis.column.value) {
|
|
|
|
|
- yield put({ type: 'fetchBarData' });
|
|
|
|
|
|
|
+ if(barConfig.xAxis.column.value && barConfig.yAxis.column.value &&
|
|
|
|
|
+ barConfig.drillable?barConfig.drillList.filter(item=>{
|
|
|
|
|
+ return Object.keys(item.column).length===0
|
|
|
|
|
+ }).length===0:true) {
|
|
|
|
|
+ //开启了钻取 并且钻取配置不能有空的配置 否则不显示图表
|
|
|
|
|
+ yield put({ type: 'fetchBarData', drillDown });
|
|
|
}else {
|
|
}else {
|
|
|
yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
|
|
yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
|
|
|
}
|
|
}
|
|
|
}else if(viewType === 'pie') {
|
|
}else if(viewType === 'pie') {
|
|
|
const { pieConfig } = chartDesigner;
|
|
const { pieConfig } = chartDesigner;
|
|
|
- if(pieConfig.xAxis.column.value && pieConfig.yAxis.column.value) {
|
|
|
|
|
- yield put({ type: 'fetchPieData' });
|
|
|
|
|
|
|
+ if(pieConfig.xAxis.column.value && pieConfig.yAxis.column.value &&
|
|
|
|
|
+ pieConfig.drillable?pieConfig.drillList.filter(item=>{
|
|
|
|
|
+ return Object.keys(item.column).length===0
|
|
|
|
|
+ }).length===0:true) {
|
|
|
|
|
+ //开启了钻取 并且钻取配置不能有空的配置 否则不显示图表
|
|
|
|
|
+ yield put({ type: 'fetchPieData', drillDown });
|
|
|
}else {
|
|
}else {
|
|
|
yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
|
|
yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
|
|
|
}
|
|
}
|
|
|
}else if(viewType === 'line') {
|
|
}else if(viewType === 'line') {
|
|
|
const { lineConfig } = chartDesigner;
|
|
const { lineConfig } = chartDesigner;
|
|
|
- if(lineConfig.xAxis.column.value && lineConfig.yAxis.column.value) {
|
|
|
|
|
- yield put({ type: 'fetchLineData' });
|
|
|
|
|
|
|
+ if(lineConfig.xAxis.column.value && lineConfig.yAxis.column.value &&
|
|
|
|
|
+ lineConfig.drillable?lineConfig.drillList.filter(item=>{
|
|
|
|
|
+ return Object.keys(item.column).length===0
|
|
|
|
|
+ }).length===0:true) {
|
|
|
|
|
+ //开启了钻取 并且钻取配置不能有空的配置 否则不显示图表
|
|
|
|
|
+ yield put({ type: 'fetchLineData', drillDown });
|
|
|
}else {
|
|
}else {
|
|
|
yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
|
|
yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
|
|
|
}
|
|
}
|
|
@@ -450,7 +468,7 @@ export default {
|
|
|
yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
|
|
yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
|
|
|
}
|
|
}
|
|
|
}else {
|
|
}else {
|
|
|
- console.log('no viewType......')
|
|
|
|
|
|
|
+ yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
|
|
|
}
|
|
}
|
|
|
}catch(e) {
|
|
}catch(e) {
|
|
|
message.error('加载数据错误: ' + e.message);
|
|
message.error('加载数据错误: ' + e.message);
|
|
@@ -458,9 +476,19 @@ export default {
|
|
|
},
|
|
},
|
|
|
*fetchBarData(action, { select, call, put }) {
|
|
*fetchBarData(action, { select, call, put }) {
|
|
|
try {
|
|
try {
|
|
|
- const chartDesigner = yield select(state => state.present.chartDesigner);
|
|
|
|
|
- const { code, barConfig, filters, theme, styleConfig, defaultBarThreshold } = chartDesigner;
|
|
|
|
|
|
|
+ const { inDashBoard, item } = action;
|
|
|
|
|
+ let chartDesigner = yield select(state => state.present.chartDesigner);
|
|
|
|
|
+ let dashboardDesigner = yield select(state => state.present.dashboardDesigner);
|
|
|
|
|
+ let { code, barConfig, filters, theme, styleConfig, defaultBarThreshold } = chartDesigner;
|
|
|
|
|
+ if(inDashBoard){
|
|
|
|
|
+ code = item.code;
|
|
|
|
|
+ filters = item.filters || [];
|
|
|
|
|
+ styleConfig = item.styleConfig;
|
|
|
|
|
+ theme = dashboardDesigner.theme;
|
|
|
|
|
+ barConfig = item.chartOption.baseOption.originConfig
|
|
|
|
|
+ }
|
|
|
const { groupBy, xAxis, yAxis, sortTarget, sortType, threshold } = barConfig;
|
|
const { groupBy, xAxis, yAxis, sortTarget, sortType, threshold } = barConfig;
|
|
|
|
|
+ const { drillDown } = action;
|
|
|
const body = {
|
|
const body = {
|
|
|
id: code,
|
|
id: code,
|
|
|
groups: groupBy && groupBy.key ? [groupBy.key] : [],
|
|
groups: groupBy && groupBy.key ? [groupBy.key] : [],
|
|
@@ -479,19 +507,42 @@ export default {
|
|
|
rule: groupBy && groupBy.key ? undefined : (sortType || 'ASC'),
|
|
rule: groupBy && groupBy.key ? undefined : (sortType || 'ASC'),
|
|
|
maxCount: threshold || defaultBarThreshold
|
|
maxCount: threshold || defaultBarThreshold
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
+ //钻取逻辑
|
|
|
|
|
+ if(drillDown){
|
|
|
|
|
+ let curDrillDown = drillDown.slice(-1)[0];
|
|
|
|
|
+ body.sort = groupBy && groupBy.key ? undefined : (sortTarget ? (sortTarget === 'y' ? yAxis.column.value : curDrillDown.field) : curDrillDown.field);
|
|
|
|
|
+ body.xAxis.columnRename = curDrillDown.field;
|
|
|
|
|
+ body.xAxis.columnType = curDrillDown.type;
|
|
|
|
|
+ //如果是时间类型 需要替换showDataType
|
|
|
|
|
+ if(curDrillDown.type==='time'){
|
|
|
|
|
+ body.xAxis.showDataType = curDrillDown.showDataType
|
|
|
|
|
+ }
|
|
|
|
|
+ //加上所有层级过滤条件
|
|
|
|
|
+ let drillDownFilters = [];
|
|
|
|
|
+ drillDown.forEach(f => {
|
|
|
|
|
+ //空对象的filter过滤掉
|
|
|
|
|
+ if( f.filter && Object.keys(f.filter).length !== 0 ){
|
|
|
|
|
+ drillDownFilters.push(f.filter)
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ body.filters.push(...getBodyFilters( drillDownFilters, true ));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
let res = yield call(service.fetch, {
|
|
let res = yield call(service.fetch, {
|
|
|
url: URLS.CHART_BAR_OPTION,
|
|
url: URLS.CHART_BAR_OPTION,
|
|
|
body: body,
|
|
body: body,
|
|
|
timeout: 30000
|
|
timeout: 30000
|
|
|
});
|
|
});
|
|
|
|
|
+ let option;
|
|
|
if(res.code > 0) {
|
|
if(res.code > 0) {
|
|
|
- let option = parseChartOption('bar', res.data, barConfig, theme, styleConfig.bar || {});
|
|
|
|
|
|
|
+ option = parseChartOption('bar', res.data, barConfig, theme, styleConfig.bar || {}, drillDown );
|
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
|
{ name: 'resData', value: res.data },
|
|
{ name: 'resData', value: res.data },
|
|
|
{ name: 'chartOption', value: option },
|
|
{ name: 'chartOption', value: option },
|
|
|
] });
|
|
] });
|
|
|
}else {
|
|
}else {
|
|
|
|
|
+ option = {}
|
|
|
message.error('请求柱状图数据失败: ' + res.msg);
|
|
message.error('请求柱状图数据失败: ' + res.msg);
|
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
|
{ name: 'resData', value: null },
|
|
{ name: 'resData', value: null },
|
|
@@ -499,18 +550,31 @@ export default {
|
|
|
] });
|
|
] });
|
|
|
}
|
|
}
|
|
|
yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
|
|
yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
|
|
|
|
|
+ return option
|
|
|
}catch(e) {
|
|
}catch(e) {
|
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
|
{ name: 'resData', value: null },
|
|
{ name: 'resData', value: null },
|
|
|
{ name: 'chartOption', value: {} },
|
|
{ name: 'chartOption', value: {} },
|
|
|
] });
|
|
] });
|
|
|
message.error('请求柱状图数据失败: ' + e.message);
|
|
message.error('请求柱状图数据失败: ' + e.message);
|
|
|
|
|
+ return {}
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
*fetchPieData(action, { select, call, put }) {
|
|
*fetchPieData(action, { select, call, put }) {
|
|
|
try {
|
|
try {
|
|
|
- const chartDesigner = yield select(state => state.present.chartDesigner);
|
|
|
|
|
- const { code, pieConfig, filters, theme, styleConfig, defaultPieThreshold } = chartDesigner;
|
|
|
|
|
|
|
+ const { inDashBoard, item } = action;
|
|
|
|
|
+ let chartDesigner = yield select(state => state.present.chartDesigner);
|
|
|
|
|
+ let dashboardDesigner = yield select(state => state.present.dashboardDesigner);
|
|
|
|
|
+ let { code, pieConfig, filters, theme, styleConfig, defaultPieThreshold } = chartDesigner;
|
|
|
|
|
+ if(inDashBoard){
|
|
|
|
|
+ code = item.code;
|
|
|
|
|
+ filters = item.filters || [];
|
|
|
|
|
+ styleConfig = item.styleConfig;
|
|
|
|
|
+ theme = dashboardDesigner.theme;
|
|
|
|
|
+ pieConfig = item.chartOption.baseOption.originConfig
|
|
|
|
|
+ }
|
|
|
|
|
+ const { drillDown } = action;
|
|
|
|
|
+
|
|
|
const body = {
|
|
const body = {
|
|
|
id: code,
|
|
id: code,
|
|
|
legendData: {
|
|
legendData: {
|
|
@@ -528,18 +592,40 @@ export default {
|
|
|
maxCount: pieConfig.threshold || defaultPieThreshold
|
|
maxCount: pieConfig.threshold || defaultPieThreshold
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ //钻取逻辑
|
|
|
|
|
+ if(drillDown){
|
|
|
|
|
+ let curDrillDown = drillDown.slice(-1)[0];
|
|
|
|
|
+ body.legendData.columnRename = curDrillDown.field;
|
|
|
|
|
+ body.legendData.columnType = curDrillDown.type;
|
|
|
|
|
+ //如果是时间类型 需要替换showDataType
|
|
|
|
|
+ if(curDrillDown.type==='time'){
|
|
|
|
|
+ body.legendData.showDataType = curDrillDown.showDataType
|
|
|
|
|
+ }
|
|
|
|
|
+ //加上所有层级过滤条件
|
|
|
|
|
+ let drillDownFilters = [];
|
|
|
|
|
+ drillDown.forEach(f => {
|
|
|
|
|
+ //空对象的filter过滤掉
|
|
|
|
|
+ if( f.filter && Object.keys(f.filter).length !== 0 ){
|
|
|
|
|
+ drillDownFilters.push(f.filter)
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ body.filters.push(...getBodyFilters( drillDownFilters, true ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
let res = yield call(service.fetch, {
|
|
let res = yield call(service.fetch, {
|
|
|
url: URLS.CHART_PIE_OPTION,
|
|
url: URLS.CHART_PIE_OPTION,
|
|
|
body: body,
|
|
body: body,
|
|
|
timeout: 30000
|
|
timeout: 30000
|
|
|
});
|
|
});
|
|
|
|
|
+ let option;
|
|
|
if(res.code > 0) {
|
|
if(res.code > 0) {
|
|
|
- let option = parseChartOption('pie', res.data, pieConfig, theme, styleConfig.pie || {});
|
|
|
|
|
|
|
+ option = parseChartOption('pie', res.data, pieConfig, theme, styleConfig.pie || {}, drillDown );
|
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
|
{ name: 'resData', value: res.data },
|
|
{ name: 'resData', value: res.data },
|
|
|
{ name: 'chartOption', value: option },
|
|
{ name: 'chartOption', value: option },
|
|
|
] });
|
|
] });
|
|
|
}else {
|
|
}else {
|
|
|
|
|
+ option = {}
|
|
|
message.error('请求饼图数据失败: ' + res.msg);
|
|
message.error('请求饼图数据失败: ' + res.msg);
|
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
|
{ name: 'resData', value: null },
|
|
{ name: 'resData', value: null },
|
|
@@ -547,18 +633,31 @@ export default {
|
|
|
] });
|
|
] });
|
|
|
}
|
|
}
|
|
|
yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
|
|
yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
|
|
|
|
|
+ return option
|
|
|
}catch(e) {
|
|
}catch(e) {
|
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
|
{ name: 'resData', value: null },
|
|
{ name: 'resData', value: null },
|
|
|
{ name: 'chartOption', value: {} },
|
|
{ name: 'chartOption', value: {} },
|
|
|
] });
|
|
] });
|
|
|
message.error('请求饼图数据失败: ' + e.message);
|
|
message.error('请求饼图数据失败: ' + e.message);
|
|
|
|
|
+ return {}
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
*fetchLineData(action, { select, call, put }) {
|
|
*fetchLineData(action, { select, call, put }) {
|
|
|
try {
|
|
try {
|
|
|
const chartDesigner = yield select(state => state.present.chartDesigner);
|
|
const chartDesigner = yield select(state => state.present.chartDesigner);
|
|
|
- const { code, lineConfig, filters, theme, styleConfig, defaultLineThreshold } = chartDesigner;
|
|
|
|
|
|
|
+ let { code, lineConfig, filters, theme, styleConfig, defaultLineThreshold } = chartDesigner;
|
|
|
|
|
+ const { inDashBoard, item } = action;
|
|
|
|
|
+ let dashboardDesigner = yield select(state => state.present.dashboardDesigner);
|
|
|
|
|
+ if(inDashBoard){
|
|
|
|
|
+ code = item.code;
|
|
|
|
|
+ filters = item.filters || [];
|
|
|
|
|
+ styleConfig = item.styleConfig;
|
|
|
|
|
+ theme = dashboardDesigner.theme;
|
|
|
|
|
+ lineConfig = item.chartOption.baseOption.originConfig
|
|
|
|
|
+ }
|
|
|
|
|
+ const { drillDown } = action;
|
|
|
|
|
+
|
|
|
const body = {
|
|
const body = {
|
|
|
id: code,
|
|
id: code,
|
|
|
xAxis: {
|
|
xAxis: {
|
|
@@ -576,18 +675,40 @@ export default {
|
|
|
maxCount: lineConfig.threshold || defaultLineThreshold
|
|
maxCount: lineConfig.threshold || defaultLineThreshold
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ //钻取逻辑
|
|
|
|
|
+ if(drillDown){
|
|
|
|
|
+ let curDrillDown = drillDown.slice(-1)[0];
|
|
|
|
|
+ body.xAxis.columnRename = curDrillDown.field;
|
|
|
|
|
+ body.xAxis.columnType = curDrillDown.type;
|
|
|
|
|
+ //如果是时间类型 需要替换showDataType
|
|
|
|
|
+ if(curDrillDown.type==='time'){
|
|
|
|
|
+ body.xAxis.showDataType = curDrillDown.showDataType
|
|
|
|
|
+ }
|
|
|
|
|
+ //加上所有层级过滤条件
|
|
|
|
|
+ let drillDownFilters = [];
|
|
|
|
|
+ drillDown.forEach(f => {
|
|
|
|
|
+ //空对象的filter过滤掉
|
|
|
|
|
+ if( f.filter && Object.keys(f.filter).length !== 0 ){
|
|
|
|
|
+ drillDownFilters.push(f.filter)
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ body.filters.push(...getBodyFilters( drillDownFilters, true ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
let res = yield call(service.fetch, {
|
|
let res = yield call(service.fetch, {
|
|
|
url: URLS.CHART_LINE_OPTION,
|
|
url: URLS.CHART_LINE_OPTION,
|
|
|
body: body,
|
|
body: body,
|
|
|
timeout: 30000
|
|
timeout: 30000
|
|
|
});
|
|
});
|
|
|
|
|
+ let option;
|
|
|
if(res.code > 0) {
|
|
if(res.code > 0) {
|
|
|
- let option = parseChartOption('line', res.data, lineConfig, theme, styleConfig.line || {});
|
|
|
|
|
|
|
+ option = parseChartOption('line', res.data, lineConfig, theme, styleConfig.line || {}, drillDown );
|
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
|
{ name: 'resData', value: res.data },
|
|
{ name: 'resData', value: res.data },
|
|
|
{ name: 'chartOption', value: option },
|
|
{ name: 'chartOption', value: option },
|
|
|
] });
|
|
] });
|
|
|
}else {
|
|
}else {
|
|
|
|
|
+ option = {}
|
|
|
message.error('请求折线图数据失败: ' + res.msg);
|
|
message.error('请求折线图数据失败: ' + res.msg);
|
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
|
{ name: 'resData', value: null },
|
|
{ name: 'resData', value: null },
|
|
@@ -595,12 +716,14 @@ export default {
|
|
|
] });
|
|
] });
|
|
|
}
|
|
}
|
|
|
yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
|
|
yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
|
|
|
|
|
+ return option
|
|
|
}catch(e) {
|
|
}catch(e) {
|
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
yield put({ type: 'silentSetFields', fields: [
|
|
|
{ name: 'resData', value: null },
|
|
{ name: 'resData', value: null },
|
|
|
{ name: 'chartOption', value: {} },
|
|
{ name: 'chartOption', value: {} },
|
|
|
] });
|
|
] });
|
|
|
message.error('请求折线图数据失败: ' + e.message);
|
|
message.error('请求折线图数据失败: ' + e.message);
|
|
|
|
|
+ return {}
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
*fetchScatterData(action, { select, call, put }) {
|
|
*fetchScatterData(action, { select, call, put }) {
|