chartDesigner.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. import { message } from 'antd'
  2. import * as service from '../services/index'
  3. import URLS from '../constants/url'
  4. import STATISTICS_OPTION from '../components/chartDesigner/sections/statisticsOption.json'
  5. export default {
  6. namespace: 'chartDesigner',
  7. state: {
  8. originData: {
  9. code: null,
  10. header: { label: '未命名' },
  11. baseConfig: { dataSource: '', viewType: '' },
  12. preparing: { groupBy: {} },
  13. aggregateTableConfig: {},
  14. dataViewConfig: {},
  15. barConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} } },
  16. lineConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} } },
  17. pieConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} } },
  18. scatterConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} } },
  19. style: {},
  20. filters: [],
  21. chartOption: {},
  22. autoRefresh: true
  23. },
  24. columns: [],
  25. allPermission: [
  26. { value: 'owner', name: '创建人' },
  27. { value: 'anyone', name: '所有人' }
  28. ],
  29. header: {
  30. label: '标题'
  31. },
  32. baseConfig: {
  33. dataSource: '',
  34. viewType: ''
  35. },
  36. preparing: {
  37. groupBy: []
  38. },
  39. aggregateTableConfig: {
  40. },
  41. dataViewConfig: {
  42. viewColumns: [],
  43. sortColumn: {
  44. }
  45. },
  46. barConfig: {
  47. xAxis: {
  48. column: {},
  49. granularity: {}
  50. },
  51. yAxis: {
  52. column: {},
  53. gauge: {}
  54. }
  55. },
  56. lineConfig: {
  57. xAxis: {
  58. column: {},
  59. granularity: {}
  60. },
  61. yAxis: {
  62. column: {},
  63. gauge: {}
  64. }
  65. },
  66. pieConfig: {
  67. xAxis: {
  68. column: {},
  69. granularity: {}
  70. },
  71. yAxis: {
  72. column: {},
  73. gauge: {}
  74. }
  75. },
  76. scatterConfig: {
  77. xAxis: {
  78. column: {},
  79. granularity: {}
  80. },
  81. yAxis: {
  82. column: {},
  83. gauge: {}
  84. }
  85. },
  86. styleConfig: {
  87. },
  88. otherConfig:{
  89. },
  90. description: '',
  91. filters: [],
  92. chartOption: {},
  93. autoRefresh: true,
  94. dirty: false
  95. },
  96. reducers: {
  97. /**
  98. * 更新model字段值
  99. * 1. 进入撤销重做历史
  100. */
  101. setField(state, action) {
  102. const { name, value } = action;
  103. let obj = {};
  104. obj[name] = value;
  105. let newState = Object.assign({}, state, obj);
  106. return Object.assign({}, newState, {dirty: true});
  107. },
  108. /**
  109. * 批量更新model字段值
  110. * 1. 进入撤销重做历史
  111. */
  112. setFields(state, action) {
  113. const { fields } = action;
  114. let obj = {};
  115. fields.map(f => (obj[f.name] = f.value));
  116. let newState = Object.assign({}, state, obj);
  117. return Object.assign({}, newState, {dirty: true});
  118. },
  119. /**
  120. * 更新model字段值
  121. * 1. 不进入撤销重做历史
  122. */
  123. silentSetField(state, action) {
  124. const { name, value } = action;
  125. let obj = {};
  126. obj[name] = value;
  127. let newState = Object.assign({}, state, obj);
  128. return newState;
  129. },
  130. /**
  131. * 批量更新model字段值
  132. * 1. 不进入撤销重做历史
  133. */
  134. silentSetFields(state, action) {
  135. const { fields } = action;
  136. let obj = {};
  137. fields.map(f => (obj[f.name] = f.value));
  138. let newState = Object.assign({}, state, obj);
  139. return newState;
  140. },
  141. reset(state, action) {
  142. let newState = Object.assign({}, state, state.originData);
  143. return Object.assign({}, newState, {dirty: false});
  144. },
  145. setDirty(state, action) {
  146. const { dirty } = action;
  147. let newState = Object.assign({}, state, { dirty });
  148. console.log(newState);
  149. return newState;
  150. }
  151. },
  152. effects: {
  153. /**
  154. * 初始化批量更新model字段值
  155. * 触发数据刷新、不进入撤销重做历史
  156. */
  157. *defaultChangeFields(action, { select, call, put }) {
  158. const { fields } = action;
  159. yield put({ type: 'silentSetFields', fields });
  160. const chartDesigner = yield select(state => state.present.chartDesigner);
  161. const { autoRefresh } = chartDesigner;
  162. if(autoRefresh) {
  163. yield put({ type: 'fetchChartData' });
  164. }
  165. },
  166. /**
  167. * 更新model字段值
  168. * 可能影响到数据刷新的model字段改变一般用该action
  169. */
  170. *changeField(action, { select, call, put }) {
  171. const { name, value } = action;
  172. yield put({ type: 'setField', name, value });
  173. const chartDesigner = yield select(state => state.present.chartDesigner);
  174. const { autoRefresh } = chartDesigner;
  175. if(autoRefresh) {
  176. yield put({ type: 'fetchChartData' });
  177. }
  178. },
  179. /**
  180. * 批量更新model字段值
  181. */
  182. *changeFields(action, { select, call, put }) {
  183. const { fields } = action;
  184. yield put({ type: 'setFields', fields });
  185. const chartDesigner = yield select(state => state.present.chartDesigner);
  186. const { autoRefresh } = chartDesigner;
  187. if(autoRefresh) {
  188. yield put({ type: 'fetchChartData' });
  189. }
  190. },
  191. *changeDataSource(action, { select, call, put }) {
  192. const { value } = action;
  193. yield put({ type: 'silentSetField', name: 'baseConfig', value });
  194. yield put({ type: 'remoteDataColumn', code: value.dataSource });
  195. },
  196. *remoteQucikAdd(action, { select, call, put }) {
  197. try{
  198. const { dataSource } = action;
  199. yield put({ type: 'silentSetFields', fields: [
  200. { name: 'baseConfig', value: { dataSource: dataSource.code, viewType: '' } }
  201. ] });
  202. const chartDesigner = yield select(state => state.present.chartDesigner);
  203. const { baseConfig, preparing } = chartDesigner;
  204. let body = {
  205. chartName: dataSource.name + '(未命名)',
  206. dataId: baseConfig.dataSource,
  207. groupBy: preparing.groupBy && preparing.groupBy.key ? [{
  208. columnName: preparing.groupBy.key,
  209. columnRamane: preparing.groupBy.label
  210. }] : [],
  211. createBy: 'zhuth',
  212. describes: '',
  213. style: '',
  214. chartConfig: '{}',
  215. chartType: ''
  216. };
  217. const res = yield call(service.fetch, {
  218. url: URLS.CHART_ADD,
  219. body: body
  220. })
  221. if(!res.err && res.data.data > 0) {
  222. yield put({ type: 'chart/fetchList', mandatory: true });
  223. yield put({ type: 'main/redirect', path: '/chart/' + res.data.data });
  224. }else {
  225. message.error('新增失败');
  226. }
  227. }catch(e) {
  228. console.error(e);
  229. message.error('新增失败');
  230. }
  231. },
  232. *remoteDataColumn(action, { select, call, put }) {
  233. const code = action.code;
  234. try {
  235. const res = yield call(service.fetch, {
  236. url: URLS.DATASOURCE_QUERY_DATACOLUMNS,
  237. body: code
  238. });
  239. console.log(code, res);
  240. if(!res.err && res.data.code > 0) {
  241. let resData = res.data.data;
  242. let columns = resData.map((c, i) => {
  243. return {
  244. key: i,
  245. name: c.columnName,
  246. label: c.columnRaname,
  247. type: c.columnType,
  248. selection: []
  249. }
  250. })
  251. yield put({ type: 'silentSetField', name: 'columns', value: columns });
  252. }else {
  253. message.error('请求列数据失败');
  254. yield put({ type: 'silentSetField', name: 'columns', value: [] });
  255. }
  256. }catch(e) {
  257. message.error('请求列数据失败');
  258. yield put({ type: 'silentSetField', name: 'columns', value: [] });
  259. }
  260. },
  261. *fetchChartData(action, { select, call, put }) {
  262. const chartDesigner = yield select(state => state.present.chartDesigner);
  263. const { baseConfig } = chartDesigner;
  264. const { viewType } = baseConfig;
  265. if(viewType === 'bar') {
  266. yield put({ type: 'fetchBarData' });
  267. }else if(viewType === 'pie') {
  268. yield put({ type: 'fetchPieData' });
  269. }else if(viewType === 'line') {
  270. yield put({ type: 'fetchLineData' });
  271. }else if(viewType === 'scatter') {
  272. yield put({ type: 'fetchScatterData' })
  273. }else if(viewType === 'dataView') {
  274. yield put({ type: 'fetchDataViewData' });
  275. }else if(viewType === 'aggregateTable') {
  276. yield put({ type: 'fetchAggregateTableData' });
  277. }else {
  278. console.log('nothing.......')
  279. }
  280. },
  281. *fetchBarData(action, { select, call, put }) {
  282. try {
  283. const chartDesigner = yield select(state => state.present.chartDesigner);
  284. const { code, barConfig, preparing } = chartDesigner;
  285. const body = {
  286. id: code,
  287. groups: preparing.groupBy && preparing.groupBy.key ? [preparing.groupBy.key] : [],
  288. xAxis: {
  289. columnRename: barConfig.xAxis.column.value,
  290. columnType: barConfig.xAxis.column.type,
  291. showDataType: barConfig.xAxis.granularity.value
  292. },
  293. yAxis: {
  294. columnRename: barConfig.yAxis.column.value,
  295. showDataType: barConfig.yAxis.gauge.value
  296. }
  297. };
  298. console.log(body);
  299. let res = yield call(service.fetch, {
  300. url: URLS.CHART_BAR_OPTION,
  301. body: body
  302. });
  303. if(!res.err && res.data.code > 0) {
  304. let xTitle = barConfig.xAxis?`${barConfig.xAxis.column.label}${barConfig.xAxis.granularity.value?'('+barConfig.xAxis.granularity.label+')':''}`:null
  305. let yTitle = barConfig.yAxis?`${barConfig.yAxis.column.label}${barConfig.yAxis.gauge.value?'('+barConfig.yAxis.gauge.label+')':''}`:null
  306. let config = {
  307. viewType: 'bar',
  308. option: {
  309. xAxis: res.data.data.xAxis,
  310. serieses: res.data.data.serieses,
  311. xTitle,
  312. yTitle,
  313. }
  314. }
  315. yield put({ type: 'silentSetField', name: 'chartOption', value: config });
  316. }else {
  317. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  318. }
  319. }catch(e) {
  320. console.error(e);
  321. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  322. }
  323. },
  324. *fetchPieData(action, { select, call, put }) {
  325. try {
  326. const chartDesigner = yield select(state => state.present.chartDesigner);
  327. const { code, pieConfig } = chartDesigner;
  328. const body = {
  329. id: code,
  330. legendData: {
  331. columnRename: pieConfig.xAxis.column.value,
  332. columnType: pieConfig.xAxis.column.type,
  333. showDataType: pieConfig.xAxis.granularity.value
  334. },
  335. series: {
  336. columnRename: pieConfig.yAxis.column.value,
  337. columnName: pieConfig.yAxis.column.label,
  338. showDataType: pieConfig.yAxis.gauge.value
  339. }
  340. };
  341. let res = yield call(service.fetch, {
  342. url: URLS.CHART_PIE_OPTION,
  343. body: body
  344. });
  345. if(!res.err && res.data.code > 0) {
  346. let columnName = pieConfig.xAxis.column.label + (pieConfig.xAxis.granularity.value ? '('+pieConfig.xAxis.granularity.label+')' : '');
  347. let config = {
  348. viewType: 'pie',
  349. option: {
  350. xAxis: res.data.data.xAxis,
  351. columnName: columnName,
  352. serieses: res.data.data.serieses
  353. }
  354. }
  355. yield put({ type: 'silentSetField', name: 'chartOption', value: config });
  356. }else {
  357. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  358. }
  359. }catch(e) {
  360. console.error(e);
  361. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  362. }
  363. },
  364. *fetchLineData(action, { select, call, put }) {
  365. try {
  366. const chartDesigner = yield select(state => state.present.chartDesigner);
  367. const { code, lineConfig, preparing } = chartDesigner;
  368. const body = {
  369. id: code,
  370. xAxis: {
  371. columnRename: lineConfig.xAxis.column.value,
  372. columnType: lineConfig.xAxis.column.type
  373. },
  374. yAxis: {
  375. columnRename: lineConfig.yAxis.column.value,
  376. showDataType: lineConfig.yAxis.gauge.value
  377. },
  378. groups: preparing.groupBy && preparing.groupBy.key ? [preparing.groupBy.key] : [],
  379. };
  380. let res = yield call(service.fetch, {
  381. url: URLS.CHART_LINE_OPTION,
  382. body: body
  383. });
  384. if(!res.err && res.data.code > 0) {
  385. let xTitle = lineConfig.xAxis?`${lineConfig.xAxis.column.label}${lineConfig.xAxis.granularity.value?'('+lineConfig.xAxis.granularity.label+')':''}`:null
  386. let yTitle = lineConfig.yAxis?`${lineConfig.yAxis.column.label}${lineConfig.yAxis.gauge.value?'('+lineConfig.yAxis.gauge.label+')':''}`:null
  387. let config = {
  388. viewType: 'line',
  389. option: {
  390. viewType: 'line',
  391. serieses: res.data.data.serieses,
  392. xTitle,
  393. yTitle
  394. }
  395. }
  396. yield put({ type: 'silentSetField', name: 'chartOption', value: config });
  397. }else {
  398. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  399. }
  400. }catch(e) {
  401. console.error(e);
  402. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  403. }
  404. },
  405. *fetchScatterData(action, { select, call, put }) {
  406. try {
  407. const chartDesigner = yield select(state => state.present.chartDesigner);
  408. const { code, scatterConfig, preparing } = chartDesigner;
  409. const body = {
  410. id: code,
  411. xAxis: {
  412. columnRename: scatterConfig.xAxis.column.value,
  413. columnType: scatterConfig.xAxis.column.type
  414. },
  415. yAxis: {
  416. columnRename: scatterConfig.yAxis.column.value,
  417. showDataType: scatterConfig.yAxis.gauge.value
  418. },
  419. groups: preparing.groupBy && preparing.groupBy.key ? [preparing.groupBy.key] : [],
  420. };
  421. console.log(body);
  422. let res = yield call(service.fetch, {
  423. url: URLS.CHART_SCATTER_OPTION,
  424. body: body
  425. });
  426. console.log(res);
  427. if(!res.err && res.data.code > 0) {
  428. res.viewType = 'scatter';
  429. let xTitle = scatterConfig.xAxis?`${scatterConfig.xAxis.column.label}${scatterConfig.xAxis.granularity.value?'('+scatterConfig.xAxis.granularity.label+')':''}`:null
  430. let yTitle = scatterConfig.yAxis?`${scatterConfig.yAxis.column.label}${scatterConfig.yAxis.gauge.value?'('+scatterConfig.yAxis.gauge.label+')':''}`:null
  431. let config = {
  432. viewType: 'scatter',
  433. option: {
  434. serieses: res.data.data.serieses,
  435. xTitle,
  436. yTitle,
  437. }
  438. }
  439. yield put({ type: 'silentSetField', name: 'chartOption', value: config });
  440. }else {
  441. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  442. }
  443. }catch(e) {
  444. console.error(e);
  445. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  446. }
  447. },
  448. *fetchDataViewData(action, { select, call, put }) {
  449. try {
  450. const chartDesigner = yield select(state => state.present.chartDesigner);
  451. const { code, dataViewConfig } = chartDesigner;
  452. const body = {
  453. id: code,
  454. columnName: dataViewConfig.targetColumn,
  455. columnListName: dataViewConfig.viewColumns,
  456. sort: "desc",
  457. showLine: dataViewConfig.maxRows,
  458. operation: ''
  459. };
  460. console.log(body);return;
  461. }catch(e) {
  462. console.error(e);
  463. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  464. }
  465. },
  466. *fetchAggregateTableData(action, { select, call, put }) {
  467. try {
  468. const chartDesigner = yield select(state => state.present.chartDesigner);
  469. const { code, aggregateTableConfig, preparing } = chartDesigner;
  470. const { targetColumn, statistics } = aggregateTableConfig;
  471. const body = {
  472. id: code,
  473. columnName: "Y_",
  474. operatorList: statistics,
  475. groupByList: preparing.groupBy && preparing.groupBy.key ? [preparing.groupBy.key] : [],
  476. };
  477. let res = yield call(service.fetch, {
  478. url: URLS.CHART_AGGREGATETABLE_OPTION,
  479. body: body
  480. });
  481. console.log(body, res);return;
  482. if(!res.err && res.data.code > 0) {
  483. let c = chartDesigner.columns.filter(c => c.name === targetColumn)[0];
  484. const resData = res.data.data;
  485. let stypes = STATISTICS_OPTION.filter(o => statistics.indexOf(o.value) !== -1);
  486. let columns = [{
  487. title: '分析目标',
  488. dataIndex: 'targetColumn'
  489. }].concat(stypes.map(st => {
  490. return {
  491. title: st.label,
  492. dataIndex: st.value
  493. }
  494. }));
  495. let data = {
  496. targetColumn: c.label
  497. }
  498. let d = resData.valueList;
  499. for(let k in d) {
  500. data[k] = d[k]
  501. }
  502. let config = {
  503. viewType: 'aggregateTable',
  504. option: {
  505. columns: columns,
  506. data: [data]
  507. }
  508. }
  509. yield put({ type: 'silentSetField', name: 'chartOption', value: config });
  510. }else {
  511. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  512. }
  513. }catch(e) {
  514. console.error(e);
  515. yield put({ type: 'silentSetField', name: 'chartOption', value: {} });
  516. }
  517. }
  518. },
  519. subscriptions: {
  520. setup({ dispatch, history }) {
  521. return history.listen(({ pathname, query }) => {
  522. });
  523. },
  524. },
  525. };