chartDesigner.js 20 KB

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