chartDesigner.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. import { message } from 'antd'
  2. import * as service from '../services/index'
  3. import URLS from '../constants/url'
  4. import parseChartOption from './parseChartOption'
  5. import moment from 'moment'
  6. function getBodyFilters(filters) {
  7. let bodyFilters = [];
  8. filters.filter(f => f.using).forEach(f => {
  9. let { name, operator, type, value1, value2 } = f;
  10. if(((type === 'index' || type === 'string') && !!value1) || // 因为数字类型会生成数字字符串,所以为0也是可以正常传入条件的
  11. ((type === 'scale' || type === 'time' || type === 'ordinal') && (operator === 'between' ? (!!value1 && !!value2) : (!!value1))) ||
  12. (type === 'categorical' &&
  13. (operator === 'contain' || operator === 'notContain' ?
  14. (value1 && value1.length > 0) : (!!value1)
  15. )
  16. )) {
  17. let bodyFilter = {
  18. columnName: name,
  19. columnType: type,
  20. symbol: operator,
  21. value: value1
  22. };
  23. if(type === 'scale' && operator === 'between') {
  24. bodyFilter['value'] = value1 + ',' + value2;
  25. }else if(type === 'time') {
  26. let v1 = value1.dynamic ? value1.name : moment(value1).format('YYYY-MM-DD');
  27. let v2 = value2.dynamic ? value2.name : moment(value2).format('YYYY-MM-DD');
  28. if(operator === 'between') {
  29. bodyFilter['value'] = v1 + ',' + v2;
  30. }else {
  31. bodyFilter['value'] = v1;
  32. }
  33. }else if(type === 'categorical' && (operator === 'contain' || operator === 'notContain')) {
  34. bodyFilter['value'] = JSON.stringify(value1);
  35. }
  36. bodyFilters.push(bodyFilter);
  37. }
  38. });
  39. return bodyFilters;
  40. }
  41. export default {
  42. namespace: 'chartDesigner',
  43. state: {
  44. originData: {
  45. code: null,
  46. creatorCode: null,
  47. creatorName: null,
  48. header: { label: '无标题' },
  49. columns: [],
  50. baseConfig: { dataSource: { code: '' }, viewType: '' },
  51. aggregateTableConfig: { targetColumn: {}, statistics: [], groupBy: [] },
  52. dataViewConfig: { viewColumns: [], sortColumn: {key: ''}, sortType: 'asc' },
  53. barConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''}, threshold: 1000 },
  54. lineConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''}, threshold: 1000 },
  55. pieConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, threshold: 1000 },
  56. scatterConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''}, threshold: 1000 },
  57. styleConfig: { visibleIndex: true },
  58. otherConfig:{},
  59. description: '',
  60. filters: [],
  61. chartOption: {},
  62. dirty: false,
  63. fetchConfig: {},
  64. demo: false
  65. },
  66. },
  67. reducers: {
  68. /**
  69. * 更新model字段值
  70. * 1. 进入撤销重做历史
  71. */
  72. setField(state, action) {
  73. const { name, value } = action;
  74. let obj = {};
  75. obj[name] = value;
  76. let newState = Object.assign({}, state, obj);
  77. return Object.assign({}, newState, {dirty: true});
  78. },
  79. /**
  80. * 批量更新model字段值
  81. * 1. 进入撤销重做历史
  82. */
  83. setFields(state, action) {
  84. const { fields } = action;
  85. let obj = {};
  86. fields.map(f => (obj[f.name] = f.value));
  87. let newState = Object.assign({}, state, obj);
  88. return Object.assign({}, newState, {dirty: true});
  89. },
  90. /**
  91. * 更新model字段值
  92. * 1. 不进入撤销重做历史
  93. */
  94. silentSetField(state, action) {
  95. const { name, value } = action;
  96. let obj = {};
  97. obj[name] = value;
  98. let newState = Object.assign({}, state, obj);
  99. return newState;
  100. },
  101. /**
  102. * 批量更新model字段值
  103. * 1. 不进入撤销重做历史
  104. */
  105. silentSetFields(state, action) {
  106. const { fields } = action;
  107. let obj = {};
  108. fields.map(f => (obj[f.name] = f.value));
  109. let newState = Object.assign({}, state, obj);
  110. return newState;
  111. },
  112. reset(state, action) {
  113. let newState = Object.assign({}, state, state.originData);
  114. return Object.assign({}, newState);
  115. },
  116. setDirty(state, action) {
  117. const { dirty } = action;
  118. let newState = Object.assign({}, state, { dirty });
  119. return newState;
  120. }
  121. },
  122. effects: {
  123. /**
  124. * 初始化批量更新model字段值
  125. * 触发数据刷新、不进入撤销重做历史
  126. */
  127. *defaultChangeFields(action, { select, call, put }) {
  128. const { fields } = action;
  129. yield put({ type: 'silentSetFields', fields });
  130. const { autoRefresh } = action;
  131. if(autoRefresh === undefined ? true : autoRefresh) {
  132. yield put({ type: 'fetchChartData' });
  133. }
  134. },
  135. /**
  136. * 更新model字段值
  137. * 可能影响到数据刷新的model字段改变一般用该action
  138. */
  139. *changeField(action, { select, call, put }) {
  140. const { name, value } = action;
  141. yield put({ type: 'setField', name, value });
  142. const { autoRefresh } = action;
  143. if(autoRefresh === undefined ? true : autoRefresh) {
  144. yield put({ type: 'fetchChartData' });
  145. }
  146. },
  147. /**
  148. * 批量更新model字段值
  149. */
  150. *changeFields(action, { select, call, put }) {
  151. const { fields } = action;
  152. yield put({ type: 'setFields', fields });
  153. const { autoRefresh } = action;
  154. if(autoRefresh === undefined ? true : autoRefresh) {
  155. yield put({ type: 'fetchChartData' });
  156. }
  157. },
  158. *changeDataSource(action, { select, call, put }) {
  159. const { dataSource } = action;
  160. const chartDesigner = yield select(state => state.present.chartDesigner);
  161. const { baseConfig } = chartDesigner;
  162. yield put({ type: 'changeField', name: 'baseConfig', value: { ...baseConfig, dataSource } });
  163. yield put({ type: 'remoteDataColumn', code: dataSource.code });
  164. },
  165. *remoteQucikAdd(action, { select, call, put }) {
  166. try{
  167. const { dataSource } = action;
  168. yield put({ type: 'silentSetFields', fields: [
  169. { name: 'baseConfig', value: { dataSource: dataSource.code, viewType: '' } }
  170. ] });
  171. let body = {
  172. chartName: dataSource.name + '_未命名',
  173. dataId: dataSource.code,
  174. describes: '',
  175. chartConfig: '{}',
  176. chartType: '',
  177. };
  178. const res = yield call(service.fetch, {
  179. url: URLS.CHART_ADD,
  180. body: body
  181. })
  182. if(!res.err && res.data.data > 0) {
  183. yield put({ type: 'chart/fetchList', mandatory: true });
  184. yield put({ type: 'main/redirect', path: '/chart/' + res.data.data });
  185. // yield put({ type: 'chart/remoteDetail', code: res.data.data });
  186. }else {
  187. message.error('新增失败: ' + (res.err || res.data.msg));
  188. }
  189. }catch(e) {
  190. message.error('新增失败: ' + e.message);
  191. }
  192. },
  193. /**
  194. * 复制新增
  195. */
  196. *remoteCopyAdd(action, { select, call, put }) {
  197. try{
  198. yield put({ type: 'chart/remoteModify' });
  199. const { newHeaderLabel } = action;
  200. const chartDesigner = yield select(state => state.present.chartDesigner);
  201. const { filters, baseConfig, pieConfig, lineConfig, aggregateTableConfig, dataViewConfig,
  202. barConfig, scatterConfig, otherConfig, description, group, chartOption, fetchConfig, styleConfig } = chartDesigner;
  203. let body = {
  204. filters: JSON.stringify(filters),
  205. chartName: newHeaderLabel,
  206. dataId: baseConfig.dataSource.code,
  207. describes: description || '',
  208. style: JSON.stringify(styleConfig),
  209. otherConfig: JSON.stringify(otherConfig),
  210. chartsGroup: group+'' ? group : '-1',
  211. chartOption: JSON.stringify(chartOption),
  212. fetchConfig: JSON.stringify(fetchConfig),
  213. }; // 基本属性
  214. if(baseConfig.viewType === 'bar') {
  215. body.chartType = 'Histogram';
  216. body.chartConfig = JSON.stringify(barConfig);
  217. }else if(baseConfig.viewType === 'pie') {
  218. body.chartType = 'Pie';
  219. body.chartConfig = JSON.stringify(pieConfig);
  220. }else if(baseConfig.viewType === 'line') {
  221. body.chartType = 'Line';
  222. body.chartConfig = JSON.stringify(lineConfig);
  223. }else if(baseConfig.viewType === 'scatter') {
  224. body.chartType = 'scatter';
  225. body.chartConfig = JSON.stringify(scatterConfig);
  226. }else if(baseConfig.viewType === 'aggregateTable') {
  227. body.chartType = 'population';
  228. body.chartConfig = JSON.stringify(aggregateTableConfig);
  229. }else if(baseConfig.viewType === 'dataView') {
  230. body.chartType = 'individual';
  231. body.chartConfig = JSON.stringify(dataViewConfig);;
  232. }else {
  233. body.chartType = '';
  234. body.chartConfig = JSON.stringify({});
  235. }
  236. const res = yield call(service.fetch, {
  237. url: URLS.CHART_ADD,
  238. body: body
  239. })
  240. if(!res.err && res.data.code > 0) {
  241. yield put({ type: 'chart/fetchList', mandatory: true });
  242. yield put({ type: 'main/redirect', path: '/chart/' + res.data.data , reload: true});
  243. }else {
  244. message.error('创建副本失败: ' + (res.err || res.data.msg));
  245. }
  246. }catch(e) {
  247. message.error('创建副本失败: ' + e.message);
  248. }
  249. },
  250. *remoteDataColumn(action, { select, call, put }) {
  251. const code = action.code;
  252. try {
  253. const res = yield call(service.fetch, {
  254. url: URLS.DATASOURCE_QUERY_DATACOLUMNS,
  255. body: code
  256. });
  257. if(!res.err && res.data.code > 0) {
  258. let resData = res.data.data;
  259. let columns = resData.map((c, i) => {
  260. return {
  261. key: i,
  262. name: c.columnName,
  263. label: c.columnRaname,
  264. type: c.columnType,
  265. groupable: c.isGroup==='1'?true:false,
  266. filterable: c.isFilter==='1'?true:false,
  267. bucketizable: c.isSubsection==='1'?true:false,
  268. selection: []
  269. }
  270. })
  271. yield put({ type: 'silentSetField', name: 'columns', value: columns });
  272. }else {
  273. message.error('请求列数据失败:' + (res.err || res.data.msg));
  274. yield put({ type: 'silentSetField', name: 'columns', value: [] });
  275. }
  276. }catch(e) {
  277. message.error('请求列数据失败: ' + e.message);
  278. yield put({ type: 'silentSetField', name: 'columns', value: [] });
  279. }
  280. },
  281. *fetchChartData(action, { select, call, put }) {
  282. const chartDesigner = yield select(state => state.present.chartDesigner);
  283. const { baseConfig } = chartDesigner;
  284. const { viewType } = baseConfig;
  285. yield put({ type: 'silentSetField', name: 'fetchConfig', value: {} });
  286. if(viewType === 'bar') {
  287. const { barConfig } = chartDesigner;
  288. if(barConfig.xAxis.column.value && barConfig.yAxis.column.value) {
  289. yield put({ type: 'fetchBarData' });
  290. }else {
  291. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  292. }
  293. }else if(viewType === 'pie') {
  294. const { pieConfig } = chartDesigner;
  295. if(pieConfig.xAxis.column.value && pieConfig.yAxis.column.value) {
  296. yield put({ type: 'fetchPieData' });
  297. }else {
  298. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  299. }
  300. }else if(viewType === 'line') {
  301. const { lineConfig } = chartDesigner;
  302. if(lineConfig.xAxis.column.value && lineConfig.yAxis.column.value) {
  303. yield put({ type: 'fetchLineData' });
  304. }else {
  305. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  306. }
  307. }else if(viewType === 'scatter') {
  308. const { scatterConfig } = chartDesigner;
  309. if(scatterConfig.xAxis.column.value && scatterConfig.yAxis.column.value) {
  310. yield put({ type: 'fetchScatterData' });
  311. }else {
  312. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  313. }
  314. }else if(viewType === 'dataView') {
  315. const { dataViewConfig } = chartDesigner;
  316. if(dataViewConfig.viewColumns.length > 0 &&
  317. dataViewConfig.sortColumn.key &&
  318. dataViewConfig.sortType) {
  319. yield put({ type: 'fetchDataViewData' });
  320. }else {
  321. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  322. }
  323. }else if(viewType === 'aggregateTable') {
  324. const { aggregateTableConfig } = chartDesigner;
  325. if(aggregateTableConfig.targetColumn.name && aggregateTableConfig.statistics.length > 0) {
  326. yield put({ type: 'fetchAggregateTableData' });
  327. }else {
  328. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  329. }
  330. }else {
  331. console.log('no viewType......')
  332. }
  333. },
  334. *fetchBarData(action, { select, call, put }) {
  335. try {
  336. const chartDesigner = yield select(state => state.present.chartDesigner);
  337. const { code, barConfig, filters } = chartDesigner;
  338. const body = {
  339. id: code,
  340. groups: barConfig.groupBy && barConfig.groupBy.key ? [barConfig.groupBy.key] : [],
  341. xAxis: {
  342. columnRename: barConfig.xAxis.column.value,
  343. columnType: barConfig.xAxis.column.type,
  344. showDataType: barConfig.xAxis.granularity.value
  345. },
  346. yAxis: {
  347. columnRename: barConfig.yAxis.column.value,
  348. showDataType: barConfig.yAxis.gauge.value
  349. },
  350. filters: getBodyFilters(filters),
  351. maxCount: barConfig.threshold
  352. };
  353. let res = yield call(service.fetch, {
  354. url: URLS.CHART_BAR_OPTION,
  355. body: body,
  356. timeout: 30000
  357. });
  358. if(!res.err && res.data.code > 0) {
  359. let option = parseChartOption('bar', res.data.data, barConfig);
  360. yield put({ type: 'silentSetField', name: 'chartOption', value: option });
  361. }else {
  362. message.error('请求柱状图数据失败: ' + (res.err || res.data.msg));
  363. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  364. }
  365. yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
  366. }catch(e) {
  367. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  368. message.error('请求柱状图数据失败: ' + e.message);
  369. }
  370. },
  371. *fetchPieData(action, { select, call, put }) {
  372. try {
  373. const chartDesigner = yield select(state => state.present.chartDesigner);
  374. const { code, pieConfig, filters } = chartDesigner;
  375. const body = {
  376. id: code,
  377. legendData: {
  378. columnRename: pieConfig.xAxis.column.value,
  379. columnType: pieConfig.xAxis.column.type,
  380. showDataType: pieConfig.xAxis.granularity.value
  381. },
  382. series: {
  383. columnRename: pieConfig.yAxis.column.value,
  384. columnName: pieConfig.yAxis.column.label,
  385. showDataType: pieConfig.yAxis.gauge.value
  386. },
  387. filters: getBodyFilters(filters),
  388. maxCount: pieConfig.threshold
  389. };
  390. let res = yield call(service.fetch, {
  391. url: URLS.CHART_PIE_OPTION,
  392. body: body,
  393. timeout: 30000
  394. });
  395. if(!res.err && res.data.code > 0) {
  396. let option = parseChartOption('pie', res.data.data, pieConfig);
  397. yield put({ type: 'silentSetField', name: 'chartOption', value: option });
  398. }else {
  399. message.error('请求饼图数据失败: ' + (res.err || res.data.msg));
  400. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  401. }
  402. yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
  403. }catch(e) {
  404. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  405. message.error('请求饼图数据失败: ' + e.message);
  406. }
  407. },
  408. *fetchLineData(action, { select, call, put }) {
  409. try {
  410. const chartDesigner = yield select(state => state.present.chartDesigner);
  411. const { code, lineConfig, filters } = chartDesigner;
  412. const body = {
  413. id: code,
  414. xAxis: {
  415. columnRename: lineConfig.xAxis.column.value,
  416. columnType: lineConfig.xAxis.column.type
  417. },
  418. yAxis: {
  419. columnRename: lineConfig.yAxis.column.value,
  420. showDataType: lineConfig.yAxis.gauge.value
  421. },
  422. groups: lineConfig.groupBy && lineConfig.groupBy.key ? [lineConfig.groupBy.key] : [],
  423. filters: getBodyFilters(filters),
  424. maxCount: lineConfig.threshold
  425. };
  426. let res = yield call(service.fetch, {
  427. url: URLS.CHART_LINE_OPTION,
  428. body: body,
  429. timeout: 30000
  430. });
  431. if(!res.err && res.data.code > 0) {
  432. let option = parseChartOption('line', res.data.data, lineConfig);
  433. yield put({ type: 'silentSetField', name: 'chartOption', value: option });
  434. }else {
  435. message.error('请求折线图数据失败: ' + (res.err || res.data.msg));
  436. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  437. }
  438. yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
  439. }catch(e) {
  440. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  441. message.error('请求折线图数据失败: ' + e.message);
  442. }
  443. },
  444. *fetchScatterData(action, { select, call, put }) {
  445. try {
  446. const chartDesigner = yield select(state => state.present.chartDesigner);
  447. const { code, scatterConfig, filters } = chartDesigner;
  448. const body = {
  449. id: code,
  450. xAxis: {
  451. columnRename: scatterConfig.xAxis.column.value,
  452. columnType: scatterConfig.xAxis.column.type
  453. },
  454. yAxis: {
  455. columnRename: scatterConfig.yAxis.column.value,
  456. showDataType: scatterConfig.yAxis.gauge.value
  457. },
  458. groups: scatterConfig.groupBy && scatterConfig.groupBy.key ? [scatterConfig.groupBy.key] : [],
  459. filters: getBodyFilters(filters),
  460. maxCount: scatterConfig.threshold
  461. };
  462. let res = yield call(service.fetch, {
  463. url: URLS.CHART_SCATTER_OPTION,
  464. body: body,
  465. timeout: 30000
  466. });
  467. if(!res.err && res.data.code > 0) {
  468. let option = parseChartOption('scatter', res.data.data, scatterConfig);
  469. yield put({ type: 'silentSetField', name: 'chartOption', value: option });
  470. }else {
  471. message.error('请求散点图数据失败: ' + (res.err || res.data.msg));
  472. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  473. }
  474. yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
  475. }catch(e) {
  476. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  477. message.error('请求散点图数据失败: ' + e.message);
  478. }
  479. },
  480. *fetchDataViewData(action, { select, call, put }) {
  481. try {
  482. const chartDesigner = yield select(state => state.present.chartDesigner);
  483. const { code, dataViewConfig, filters } = chartDesigner;
  484. const { page, pageSize } = action;
  485. const body = {
  486. id: code,
  487. columnListName: dataViewConfig.viewColumns.map(c => c.name),
  488. sortColumn: dataViewConfig.sortColumn.key,
  489. sort: dataViewConfig.sortType,
  490. filters: getBodyFilters(filters),
  491. testPage: {
  492. pageNum: page || 1,
  493. pageSize: pageSize || 25,
  494. }
  495. };
  496. let res = yield call(service.fetch, {
  497. url: URLS.CHART_DATAVIEW_OPTION,
  498. body: body,
  499. timeout: 30000
  500. });
  501. if(!res.err && res.data.code > 0) {
  502. let option = parseChartOption('dataView', res.data.data, dataViewConfig);
  503. yield put({ type: 'silentSetField', name: 'chartOption', value: option });
  504. }else {
  505. message.error('请求列表数据失败: ' + (res.err || res.data.msg));
  506. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  507. }
  508. yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
  509. }catch(e) {
  510. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  511. message.error('请求列表数据失败: ' + e.message);
  512. }
  513. },
  514. *fetchAggregateTableData(action, { select, call, put }) {
  515. try {
  516. const chartDesigner = yield select(state => state.present.chartDesigner);
  517. const { code, aggregateTableConfig, filters } = chartDesigner;
  518. const { targetColumn, statistics } = aggregateTableConfig;
  519. const body = {
  520. id: code,
  521. columnName: targetColumn.name,
  522. operatorList: statistics,
  523. groupByList: aggregateTableConfig.groupBy && aggregateTableConfig.groupBy.length > 0 ? aggregateTableConfig.groupBy.map(g => g.key) : [],
  524. filters: getBodyFilters(filters),
  525. testPage: {
  526. pageNum: 1,
  527. pageSize: 999,
  528. }
  529. };
  530. let res = yield call(service.fetch, {
  531. url: URLS.CHART_AGGREGATETABLE_OPTION,
  532. body: body,
  533. timeout: 30000
  534. });
  535. if(!res.err && res.data.code > 0) {
  536. let option = parseChartOption('aggregateTable', res.data.data, aggregateTableConfig);
  537. yield put({ type: 'silentSetField', name: 'chartOption', value: option });
  538. }else {
  539. message.error('请求统计数据失败: ' + (res.err || res.data.msg));
  540. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  541. }
  542. yield put({ type: 'silentSetField', name: 'fetchConfig', value: body });
  543. }catch(e) {
  544. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  545. message.error('请求统计数据失败: ' + e.message);
  546. }
  547. },
  548. /**
  549. * 将图表数据以表格的方式作为预览
  550. */
  551. *remoteChartDataList(action, { select, call, put }) {
  552. try {
  553. const chartDesigner = yield select(state => state.present.chartDesigner);
  554. const { code, baseConfig, aggregateTableConfig, lineConfig, barConfig, pieConfig, scatterConfig, dataViewConfig, filters } = chartDesigner;
  555. const { viewType } = baseConfig;
  556. const { page, pageSize } = action;
  557. let columns = [];
  558. let columnListName = [];
  559. let sortColumn = null;
  560. if(viewType === 'aggregateTable') {
  561. const { groupBy, targetColumn } = aggregateTableConfig;
  562. groupBy.map(g => ({
  563. title: g.label,
  564. dataIndex: g.key,
  565. // render: g.columnType === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  566. })).concat({
  567. title: targetColumn.label,
  568. dataIndex: targetColumn.name,
  569. render: targetColumn.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  570. }).filter(x => !!x.dataIndex).forEach(x => {
  571. if(!columns.find(c => c.dataIndex === x.dataIndex)) {
  572. columns.push(x);
  573. }
  574. });;
  575. sortColumn = targetColumn.name;
  576. }else if(viewType === 'line') {
  577. const { groupBy, xAxis, yAxis } = lineConfig;
  578. [{
  579. title: groupBy ? groupBy.label : '',
  580. dataIndex: groupBy ?groupBy.key : '',
  581. // render: g.columnType === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  582. }, {
  583. title: xAxis.column.label,
  584. dataIndex: xAxis.column.value,
  585. render: xAxis.column.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  586. }, {
  587. title: yAxis.column.label,
  588. dataIndex: yAxis.column.value,
  589. render: yAxis.column.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  590. }].filter(x => !!x.dataIndex).forEach(x => {
  591. if(!columns.find(c => c.dataIndex === x.dataIndex)) {
  592. columns.push(x);
  593. }
  594. });;
  595. sortColumn = xAxis.column.value;
  596. }else if(viewType === 'bar') {
  597. const { groupBy, xAxis, yAxis } = barConfig;
  598. [{
  599. title: groupBy ? groupBy.label : '',
  600. dataIndex: groupBy ? groupBy.key : '',
  601. // render: g.columnType === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  602. }, {
  603. title: xAxis.column.label,
  604. dataIndex: xAxis.column.value,
  605. render: xAxis.column.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  606. }, {
  607. title: yAxis.column.label,
  608. dataIndex: yAxis.column.value,
  609. render: yAxis.column.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  610. }].filter(x => !!x.dataIndex).forEach(x => {
  611. if(!columns.find(c => c.dataIndex === x.dataIndex)) {
  612. columns.push(x);
  613. }
  614. });;
  615. sortColumn = xAxis.column.value;
  616. }else if(viewType === 'pie') {
  617. const { xAxis, yAxis } = pieConfig;
  618. [{
  619. title: xAxis.column.label,
  620. dataIndex: xAxis.column.value,
  621. render: xAxis.column.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  622. }, {
  623. title: yAxis.column.label,
  624. dataIndex: yAxis.column.value,
  625. render: yAxis.column.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  626. }].filter(x => !!x.dataIndex).forEach(x => {
  627. if(!columns.find(c => c.dataIndex === x.dataIndex)) {
  628. columns.push(x);
  629. }
  630. });;
  631. sortColumn = xAxis.column.value;
  632. }else if(viewType === 'scatter') {
  633. const { groupBy, xAxis, yAxis } = scatterConfig;
  634. [{
  635. title: groupBy ? groupBy.label : '',
  636. dataIndex: groupBy ? groupBy.key : '',
  637. // render: g.columnType === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  638. }, {
  639. title: xAxis.column.label,
  640. dataIndex: xAxis.column.value,
  641. render: xAxis.column.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  642. }, {
  643. title: yAxis.column.label,
  644. dataIndex: yAxis.column.value,
  645. render: yAxis.column.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  646. }].filter(x => !!x.dataIndex).forEach(x => {
  647. if(!columns.find(c => c.dataIndex === x.dataIndex)) {
  648. columns.push(x);
  649. }
  650. });;
  651. sortColumn = xAxis.column.value;
  652. }else if(viewType === 'dataView') {
  653. columns = dataViewConfig.viewColumns.map(c => ({
  654. title: c.label,
  655. dataIndex: c.name,
  656. render: c.type === 'time' ? ((v, r, i) => moment(v).format('YYYY-MM-DD')) : v => v
  657. }));
  658. sortColumn = dataViewConfig.sortColumn.key;
  659. }
  660. columnListName = columns.map(c => c.dataIndex);
  661. const body = {
  662. id: code,
  663. columnListName: columnListName,
  664. sortColumn: sortColumn,
  665. sort: 'asc',
  666. filters: getBodyFilters(filters),
  667. testPage: {
  668. pageNum: page || 1,
  669. pageSize: pageSize || 25,
  670. }
  671. };
  672. yield put({ type: 'dataList/setField', name: 'loading', value: true });
  673. let res = yield call(service.fetch, {
  674. url: URLS.CHART_DATAVIEW_OPTION,
  675. body: body,
  676. timeout: 30000
  677. });
  678. if(!res.err && res.data.code > 0) {
  679. const { valueList } = res.data.data;
  680. const { list: dataSource, pageSize, total } = valueList;
  681. yield put({ type: 'dataList/setFields', fields: [
  682. { name: 'columns', value: columns },
  683. { name: 'dataSource', value: dataSource },
  684. { name: 'pageSize', value: pageSize },
  685. { name: 'total', value: total }
  686. ] });
  687. }else {
  688. // message.error('请求列表数据失败: ' + (res.err || res.data.msg));
  689. // yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  690. }
  691. }catch(e) {
  692. message.error('请求数据列表失败: ' + e.message);
  693. }finally {
  694. yield put({ type: 'dataList/setField', name: 'loading', value: false });
  695. }
  696. },
  697. },
  698. subscriptions: {
  699. setup({ dispatch, history }) {
  700. dispatch({ type: 'reset' });
  701. },
  702. },
  703. };