chart.js 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. import { message } from 'antd'
  2. import * as service from '../services/index'
  3. import URLS from '../constants/url'
  4. import CHART_TYPE from './chartType.json'
  5. export default {
  6. namespace: 'chart',
  7. state: {
  8. originData: {
  9. list: [],
  10. filterLabel: '',
  11. typeLabel: 'name',
  12. groupList: [],
  13. currentGroup: null,
  14. filterItems: [ // 可选过滤字段
  15. { name: 'name', label: '图表名称', type: 'string' },
  16. // { name: 'description', label: '备注', type: 'string' },
  17. { name: 'creatorName', label: '创建人', type: 'string' },
  18. { name: 'createTime', label: '创建时间', type: 'date' },
  19. { name: 'dataSourceCode', label: '数据源', type: 'enum', options: () => {
  20. return service.fetch({
  21. url: URLS.DATASOURCE_LIST,
  22. method: 'GET',
  23. body: {
  24. pageNum: 1,
  25. pageSize: 999
  26. }
  27. }).then(res => {
  28. if(!res.error && res.data.code > 0) {
  29. return res.data.data.list.map(l => ({
  30. name: l.dataId,
  31. label: l.dataName,
  32. }));
  33. }else {
  34. message.error('获取数据源下拉列表失败: ' + res.data.msg);
  35. }
  36. }).catch(e => {
  37. message.error('获取数据源下拉列表失败: ' + e.message);
  38. });
  39. } },
  40. { name: 'dataConnectCode', label: '数据链接', type: 'enum', options: () => {
  41. return service.fetch({
  42. url: URLS.DATACONNECT_LIST,
  43. method: 'GET',
  44. body: {
  45. pageNum: 1,
  46. pageSize: 999
  47. }
  48. }).then(res => {
  49. if(!res.error && res.data.code > 0) {
  50. return res.data.data.list.map(l => ({
  51. name: l.id,
  52. label: l.name,
  53. }));
  54. }else {
  55. message.error('获取数据链接下拉列表失败: ' + res.data.msg);
  56. }
  57. }).catch(e => {
  58. message.error('获取数据链接下拉列表失败: ' + e.message);
  59. });
  60. } }
  61. ],
  62. filterItem: { name: 'name', label: '图表名称', type: 'string' }, // 已选过滤字段
  63. listScrollTop: 0, // 记录列表界面滚动条位置
  64. },
  65. },
  66. reducers: {
  67. setField(state, action) {
  68. const { name, value } = action;
  69. let obj = {};
  70. obj[name] = value;
  71. return Object.assign({}, state, obj);
  72. },
  73. setFields(state, action) {
  74. const { fields } = action;
  75. let obj = {};
  76. fields.map(f => (obj[f.name] = f.value));
  77. return Object.assign({}, state, obj);
  78. },
  79. add(state, action) {
  80. const { data } = action;
  81. let list = state.list;
  82. list.push(data);
  83. return Object.assign({}, state, {list});
  84. },
  85. list(state, action) {
  86. let list = action.list;
  87. return Object.assign({}, state, {list: list});
  88. },
  89. setFilterItem(state, action) {
  90. const { item } = action;
  91. return Object.assign({}, state, {filterItem: item, filterLabel: ''});
  92. },
  93. setFilterLabel(state, action) {
  94. const { label } = action;
  95. return Object.assign({}, state, {filterLabel: label});
  96. },
  97. groupList(state, action) {
  98. let data = action.data;
  99. return Object.assign({}, state, {groupList: data});
  100. },
  101. /**
  102. * 设置数据源过滤用分组
  103. */
  104. setCurrentGroup(state, action) {
  105. const { group } = action;
  106. return Object.assign({}, state, {currentGroup: group});
  107. },
  108. addGroup(state, action) {
  109. const { group } = action;
  110. let list = state.groupList;
  111. list.push(group);
  112. return Object.assign({}, state, {groupList: list});
  113. },
  114. modifyGroup(state, action) {
  115. const { group } = action;
  116. let list = state.groupList;
  117. let dirty = false;
  118. for(let i = 0; i < list.length; i++) {
  119. let l = list[i];
  120. if(l.code === group.code) {
  121. for(let k in l) {
  122. if(group[k] !== undefined && l[k] !== group[k]) {
  123. l[k] = group[k];
  124. dirty = true;
  125. }
  126. }
  127. break;
  128. }
  129. }
  130. return Object.assign({}, state, {groupDirty: dirty, groupList: list});
  131. },
  132. modifyGroups(state, action) {
  133. const { groups } = action;
  134. let list = state.groupList;
  135. const modifyGroupCodes = groups.map(g => g.code);
  136. list = list.filter(l => modifyGroupCodes.indexOf(l.code) === -1);
  137. list = list.concat(groups);
  138. return Object.assign({}, state, {groupList: list});
  139. },
  140. deleteGroup(state, action) {
  141. const { group } = action;
  142. let list = state.groupList;
  143. for(let i = 0; i < list.length; i++) {
  144. let l = list[i];
  145. if(l.code === group.code) {
  146. list.splice(i, 1);
  147. break;
  148. }
  149. }
  150. return Object.assign({}, state, {groupList: list});
  151. },
  152. setGroupDirty(state, action) {
  153. let dirty = action.dirty;
  154. return Object.assign({}, state, {groupDirty: dirty});
  155. },
  156. /**
  157. * 设置图表所属分组
  158. */
  159. setChartGroup(state, action) {
  160. const { chartCode, groupCode } = action;
  161. let list = state.list;
  162. for(let i = 0; i < list.length; i++) {
  163. let l = list[i];
  164. if(l.code === chartCode) {
  165. l.groupCode = groupCode;
  166. break;
  167. }
  168. }
  169. return Object.assign({}, state, {list: list});
  170. },
  171. reset(state, action) {
  172. let newState = Object.assign({}, state, state.originData);
  173. return Object.assign({}, newState);
  174. },
  175. },
  176. effects: {
  177. *fetchList(action, { select, call, put }) {
  178. const { pageNum, pageSize } = action;
  179. const body = {
  180. pageNum: pageNum || 1,
  181. pageSize: pageSize || 999
  182. }
  183. try{
  184. const chart = yield select(state => state.present.chart);
  185. if(!action.mandatory && chart.list.length > 0) {
  186. return;
  187. }
  188. const res = yield call(service.fetch, {
  189. url: URLS.CHART_LIST,
  190. method: 'GET',
  191. body
  192. });
  193. if(!res.err && res.data.code > 0) {
  194. let list = res.data.data.list.map(d => {
  195. let chartOption = d.chartOption ? JSON.parse(d.chartOption) : {};
  196. return {
  197. code: d.chartId+'',
  198. name: d.chartName,
  199. dataSourceCode: d.dataId + '',
  200. dataSourceName: d.dataName,
  201. dataConnectCode: d.dataConnectionId,
  202. dataConnectName: d.dataConnectionName,
  203. access: d.authority === '1', // 权限
  204. database: d.dbStatus === '0', // 数据源是否还存在
  205. type: CHART_TYPE[d.chartType],
  206. creatorCode: d.createId + '',
  207. creatorName: d.createBy,
  208. createTime: d.createDate,
  209. description: d.describes || '',
  210. groupCode: d.chartsGroup + '',
  211. chartOption: chartOption,
  212. demo: d.demo
  213. }
  214. })
  215. yield put({ type: 'list', list: list });
  216. }else {
  217. message.error('请求图表列表失败: ' + (res.err || res.data.msg));
  218. }
  219. }catch(e) {
  220. message.error('请求图表列表失败: ' + e.message);
  221. }
  222. },
  223. *remoteDetail(action, { select, call, put }) {
  224. const code = action.code;
  225. if(!code){
  226. return
  227. }
  228. try {
  229. const res = yield call(service.fetch, {
  230. url: URLS.CHART_DETAIL,
  231. method: 'GET',
  232. body: {
  233. id: code
  234. }
  235. });
  236. if(!res.err && res.data.code > 0) {
  237. let resData = res.data.data;
  238. let chartConfig = JSON.parse(resData.chartConfig || '{ "xAxis": { "column": {}, "granularity": {} }, "yAxis": { "column": {}, "gauge": {} } }');
  239. let styleConfig = JSON.parse(resData.style || '{}');
  240. let otherConfig = JSON.parse(resData.otherConfig || '{}');
  241. let viewType = CHART_TYPE[resData.chartType];
  242. let filters = JSON.parse(resData.filters || '[]');
  243. let chartOption = JSON.parse(resData.chartOption || '{}');
  244. let data = {
  245. code: resData.chartId + '',
  246. creatorCode: resData.createId+'',
  247. creatorName: resData.createBy,
  248. dataSourceCode: resData.dataId + '',
  249. dataSourceName: resData.dataName,
  250. dataConnectCode: resData.dataConnectionId,
  251. dataConnectName: resData.dataConnectionName,
  252. header: {
  253. label: resData.chartName
  254. },
  255. baseConfig: {
  256. dataSource: {
  257. code: resData.dataId + '',
  258. name: resData.dataName,
  259. },
  260. viewType: viewType
  261. },
  262. styleConfig: styleConfig,
  263. otherConfig: otherConfig,
  264. description: resData.describes,
  265. group: resData.chartsGroup+'',
  266. filters: filters,
  267. chartOption: chartOption,
  268. demo: resData.demo
  269. }
  270. if(viewType === 'bar') {
  271. data.barConfig = chartConfig;
  272. }else if(viewType === 'pie') {
  273. data.pieConfig = chartConfig;
  274. }else if(viewType === 'line') {
  275. data.lineConfig = chartConfig;
  276. }else if(viewType === 'scatter') {
  277. data.scatterConfig = chartConfig;
  278. }else if(viewType === 'aggregateTable') {
  279. data.aggregateTableConfig = chartConfig;
  280. }else if(viewType === 'dataView') {
  281. data.dataViewConfig = chartConfig;
  282. }
  283. let fields = [];
  284. for(let key in data) {
  285. fields.push({
  286. name: key,
  287. value: data[key]
  288. })
  289. }
  290. yield put({ type: 'chartDesigner/silentChangeFields', fields: fields });
  291. yield put({ type: 'chartDesigner/silentChangeDataSource', dataSource: data.baseConfig.dataSource });
  292. }else {
  293. message.error('解析图表错误: ' + (res.err || res.data.msg));
  294. }
  295. }catch(e) {
  296. message.error('解析图表错误: ' + e.message);
  297. }
  298. },
  299. *remoteAdd(action, { select, call, put }) {
  300. try{
  301. const chartDesigner = yield select(state => state.present.chartDesigner);
  302. const { header, baseConfig, pieConfig, lineConfig, aggregateTableConfig, dataViewConfig,
  303. barConfig, scatterConfig, otherConfig, description, group, filters, chartOption } = chartDesigner;
  304. let body = {
  305. chartName: header.label,
  306. dataId: baseConfig.dataSource.code,
  307. describes: description,
  308. style: '{}',
  309. otherConfig: JSON.stringify(otherConfig),
  310. chartsGroup: group ? group : '-1',
  311. filters: JSON.stringify(filters),
  312. chartOption: JSON.stringify(chartOption),
  313. }; // 基本属性
  314. if(baseConfig.viewType === 'bar') {
  315. body.chartType = 'Histogram';
  316. body.chartConfig = JSON.stringify(barConfig);
  317. }else if(baseConfig.viewType === 'pie') {
  318. body.chartType = 'Pie';
  319. body.chartConfig = JSON.stringify(pieConfig);
  320. }else if(baseConfig.viewType === 'line') {
  321. body.chartType = 'Line';
  322. body.chartConfig = JSON.stringify(lineConfig);
  323. }else if(baseConfig.viewType === 'scatter') {
  324. body.chartType = 'scatter';
  325. body.chartConfig = JSON.stringify(scatterConfig);
  326. }else if(baseConfig.viewType === 'aggregateTable') {
  327. body.chartType = 'population';
  328. body.chartConfig = JSON.stringify(aggregateTableConfig);
  329. }else if(baseConfig.viewType === 'dataView') {
  330. body.chartType = 'individual';
  331. body.chartConfig = JSON.stringify(dataViewConfig);
  332. }else {
  333. body.chartType = '';
  334. body.chartConfig = JSON.stringify({});
  335. }
  336. const res = yield call(service.fetch, {
  337. url: URLS.CHART_ADD,
  338. body: body
  339. })
  340. if(!res.err && res.data.code > 0) {
  341. message.success('新增成功');
  342. yield put({ type: 'fetchList', mandatory: true });
  343. }else {
  344. message.error('新增失败: ' + (res.err || res.data.msg));
  345. }
  346. }catch(e) {
  347. console.error(e);
  348. message.error('新增失败: ' + e.message);
  349. }
  350. },
  351. *remoteModify(action, { select, call, put }) {
  352. try{
  353. const chartDesigner = yield select(state => state.present.chartDesigner);
  354. const { filters, code, header, baseConfig, pieConfig, lineConfig, aggregateTableConfig, dataViewConfig,
  355. barConfig, scatterConfig, otherConfig, description, group, chartOption, fetchConfig, styleConfig } = chartDesigner;
  356. let body = {
  357. chartId: code,
  358. filters: JSON.stringify(filters),
  359. chartName: header.label,
  360. dataId: baseConfig.dataSource.code,
  361. describes: description || '',
  362. style: JSON.stringify(styleConfig),
  363. otherConfig: JSON.stringify(otherConfig),
  364. chartsGroup: group+'' ? group : '-1',
  365. chartOption: JSON.stringify(chartOption),
  366. fetchConfig: JSON.stringify(fetchConfig),
  367. }; // 基本属性
  368. if(baseConfig.viewType === 'bar') {
  369. body.chartType = 'Histogram';
  370. body.chartConfig = JSON.stringify(barConfig);
  371. }else if(baseConfig.viewType === 'pie') {
  372. body.chartType = 'Pie';
  373. body.chartConfig = JSON.stringify(pieConfig);
  374. }else if(baseConfig.viewType === 'line') {
  375. body.chartType = 'Line';
  376. body.chartConfig = JSON.stringify(lineConfig);
  377. }else if(baseConfig.viewType === 'scatter') {
  378. body.chartType = 'scatter';
  379. body.chartConfig = JSON.stringify(scatterConfig);
  380. }else if(baseConfig.viewType === 'aggregateTable') {
  381. body.chartType = 'population';
  382. body.chartConfig = JSON.stringify(aggregateTableConfig);
  383. }else if(baseConfig.viewType === 'dataView') {
  384. body.chartType = 'individual';
  385. body.chartConfig = JSON.stringify(dataViewConfig);
  386. }
  387. const res = yield call(service.fetch, {
  388. url: URLS.CHART_UPDATE,
  389. body: body
  390. })
  391. if(!res.err && res.data.code > 0) {
  392. message.success('修改成功');
  393. yield put({ type: 'fetchList', mandatory: true });
  394. }else {
  395. message.error('修改失败: ' + (res.err || res.data.msg));
  396. }
  397. }catch(e) {
  398. console.error(e);
  399. message.error('修改失败: ' + e.message);
  400. }
  401. },
  402. *remoteDelete(action, { select, call, put, takeEvery, takeLatest }) {
  403. const chart = yield select(state => state.present.chart);
  404. const code = action.code;
  405. let list = chart.list;
  406. try {
  407. const res = yield call(service.fetch, {
  408. url: URLS.CHART_DELETE,
  409. body: code
  410. });
  411. if(!res.err && res.data.code > 0) {
  412. for(let i = 0; i < list.length; i++) {
  413. if(list[i].code === code) {
  414. list.splice(i, 1);
  415. break;
  416. }
  417. }
  418. yield put({ type: 'list', list: list });
  419. message.success('删除成功');
  420. }else {
  421. message.error('删除失败: ' + (res.err || res.data.msg));
  422. }
  423. }catch(e) {
  424. message.error('删除失败: ' + e.message);
  425. }
  426. },
  427. *remoteGroupList(action, { select, call, put }) {
  428. try {
  429. const chart = yield select(state => state.present.chart);
  430. if(!action.mandatory && chart.groupList.length > 0) {
  431. return;
  432. }
  433. const res = yield call(service.fetch, {
  434. url: URLS.GROUP_CHART_LIST,
  435. });
  436. if(!res.err && res.data.code > 0) {
  437. const resData = res.data.data;
  438. let data = resData.map(d => {
  439. return {
  440. code: d.id+'',
  441. pcode: d.fatherId+'',
  442. index: +d.groupIndex,
  443. label: d.groupName+'',
  444. }
  445. });
  446. yield put({ type: 'groupList', data });
  447. }else {
  448. message.error('读取图表分组列表错误: ' + (res.err || res.data.msg));
  449. }
  450. }catch(e) {
  451. message.error('读取图表分组列表错误: ' + e.message);
  452. }
  453. },
  454. *remoteSetGroups(action, { select, call, put }) {
  455. const { aGroups, mGroups, dGroups } = action;
  456. const body = aGroups.concat(mGroups).concat(dGroups).map(g => ({
  457. id: g.operate === 'add' ? null : g.code,
  458. fatherId: g.pcode,
  459. groupIndex: g.index,
  460. operate: g.operate,
  461. groupName: g.label
  462. }))
  463. try{
  464. const res = yield call(service.fetch, {
  465. url: URLS.GROUP_CHART_BATCH_SET,
  466. body
  467. });
  468. if(!res.err && res.data.code > 0) {
  469. message.success('修改分组信息成功');
  470. yield put({ type: 'remoteGroupList', mandatory: true });
  471. }else {
  472. message.error('修改分组信息失败: ' + (res.data.msg));
  473. }
  474. }catch(e) {
  475. message.error('修改分组信息失败: ' + e.message);
  476. }
  477. },
  478. /**
  479. * 新增分组/子分组,需要传入父节点code
  480. */
  481. *remoteAddGroup(action, { select, call, put }) {
  482. try {
  483. const chart = yield select((state) => state.present.chart);
  484. const group = chart.groupList;
  485. const pgroups = group.filter(g => g.pcode === '-1');
  486. const cgroups = group.filter(g => g.pcode !== '-1');
  487. const { pgroup } = action;
  488. let body = {};
  489. if(pgroup) {
  490. body = {
  491. fatherId: pgroup.code,
  492. groupName: '新子分组',
  493. groupIndex: cgroups.filter(c => c.pcode === pgroup.code).length,
  494. }
  495. }else {
  496. body = {
  497. fatherId: '-1',
  498. groupName: '新分组',
  499. groupIndex: pgroups.length,
  500. }
  501. }
  502. const res = yield call(service.fetch, {
  503. url: URLS.GROUP_CHART_ADD,
  504. body: body
  505. });
  506. if(!res.err && res.data.code > 0) {
  507. let group = {
  508. code: res.data.data + '',
  509. pcode: body.fatherId + '',
  510. index: body.groupIndex,
  511. label: body.groupName+'',
  512. }
  513. yield put({ type: 'addGroup', group });
  514. }else {
  515. message.error('添加分组失败: ' + (res.err || res.data.msg));
  516. }
  517. }catch(e) {
  518. message.error('添加分组失败: ' + e.message);
  519. }
  520. },
  521. /**
  522. * 修改单个分组信息(因为不涉及顺序号的修改,所以一般只用于label的修改)
  523. */
  524. *remoteModifyGroup(action, { select, call, put }) {
  525. try {
  526. const chart = yield select((state) => state.present.chart);
  527. const groupDirty = chart.groupDirty;
  528. const group = action.group;
  529. if(!groupDirty) { // 如果属性无改动则取消修改请求
  530. return;
  531. }
  532. let body = {
  533. id: group.code,
  534. fatherId: group.pcode,
  535. groupName: group.label,
  536. groupIndex: group.index,
  537. }
  538. const res = yield call(service.fetch, {
  539. url: URLS.GROUP_CHART_UPDATE,
  540. body: body
  541. });
  542. if(!res.err && res.data.code > 0) {
  543. yield put({ type: 'setGroupDirty', dirty: false });
  544. }else {
  545. message.error('修改分组失败: ' + (res.err || res.data.msg));
  546. }
  547. }catch(e) {
  548. message.error('修改分组失败: ' + e.message);
  549. }
  550. },
  551. /**
  552. * 批量修改多个分组信息(在移动位置时用)
  553. */
  554. *remoteModifyGroups(action, { select, call, put }) {
  555. try {
  556. const groups = action.groups;
  557. let body = groups.map(g => {
  558. return {
  559. id: g.code,
  560. groupName: g.label,
  561. groupIndex: g.index,
  562. fatherId: g.pcode,
  563. }
  564. });
  565. const res = yield call(service.fetch, {
  566. url: URLS.GROUP_CHART_LIST_UPDATE,
  567. body: body
  568. });
  569. if(!res.err && res.data.code > 0) {
  570. yield put({ type: 'modifyGroups', groups: groups });
  571. }else {
  572. message.error('修改分组失败: ' + (res.err || res.data.msg));
  573. }
  574. }catch(e) {
  575. message.error('修改分组失败: ' + e.message);
  576. }
  577. },
  578. *remoteDeleteGroup(action, { select, call, put }) {
  579. try {
  580. const chart = yield select((state) => state.present.chart);
  581. const groupList = chart.groupList;
  582. const { group } = action;
  583. let bgroups = groupList.filter(l => l.pcode === group.pcode);
  584. bgroups.splice(group.index, 1);
  585. bgroups = bgroups.map((b, i) => {
  586. return { ...b, index: i }
  587. });
  588. yield put({ type: 'remoteModifyGroups', groups: bgroups });
  589. const res = yield call(service.fetch, {
  590. url: URLS.GROUP_CHART_DELETE,
  591. body: group.code
  592. });
  593. if(!res.err && res.data.code > 0) {
  594. yield put({ type: 'deleteGroup', group});
  595. }else {
  596. message.error('删除分组失败: ' + (res.err || res.data.msg));
  597. }
  598. }catch(e) {
  599. message.error('删除分组失败: ' + e.message);
  600. }
  601. },
  602. *remoteMoveGroup(action, { select, call, put }) {
  603. try {
  604. const { dragCode, dropCode, dropPosition } = action;
  605. const chart = yield select((state) => state.present.chart);
  606. let group = chart.groupList;
  607. const dragGroup = group.filter(g => g.code === dragCode)[0];
  608. const dropGroup = group.filter(g => g.code === dropCode)[0];
  609. let modifyGroups = [];
  610. if((dragGroup.pcode === '-1' || dropGroup.pcode === '-1') && (dragGroup.pcode !== dropGroup.pcode)) { // 跨级
  611. if(dropGroup.pcode !== '-1') { // 从父级到子级
  612. return; // 不允许
  613. }else { // 从子级到父级
  614. if(dragGroup.pcode === dropGroup.code) { // 不跨组
  615. if(dropPosition === -1) { // 目标前
  616. let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
  617. let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
  618. dragGroups.splice(dragGroup.index, 1);
  619. dragGroups = dragGroups.map((g, i) => {
  620. return { ...g, index: i }
  621. });
  622. dropGroups.splice(dropGroup.index, 0, dragGroup);
  623. dropGroups = dropGroups.map((g, i) => {
  624. return { ...g, index: i, pcode: dropGroup.pcode }
  625. });
  626. modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
  627. }else if(dropPosition === 0) { // 目标内
  628. return; // 无变化
  629. }else if(dropPosition === 1) { // 目标后
  630. let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
  631. let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
  632. dragGroups.splice(dragGroup.index, 1);
  633. dragGroups = dragGroups.map((g, i) => {
  634. return { ...g, index: i }
  635. });
  636. dropGroups.splice(dropGroup.index + 1, 0, dragGroup);
  637. dropGroups = dropGroups.map((g, i) => {
  638. return { ...g, index: i, pcode: dropGroup.pcode }
  639. });
  640. modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
  641. }
  642. }else { // 跨组
  643. let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
  644. let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
  645. let dropChildrenGroups = group.filter(g => g.pcode === dropGroup.code).sort((a, b) => a.index - b.index);
  646. dragGroups.splice(dragGroup.index, 1);
  647. dragGroups = dragGroups.map((g, i) => {
  648. return { ...g, index: i }
  649. });
  650. if(dropPosition === -1) { // 目标前
  651. dropGroups.splice(dropGroup.index, 0, dragGroup);
  652. dropGroups = dropGroups.map((g, i) => {
  653. return { ...g, index: i, pcode: dropGroup.pcode }
  654. });
  655. modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
  656. }else if(dropPosition === 0) { // 目标内
  657. dropChildrenGroups.push({
  658. ...dragGroup,
  659. index: dropChildrenGroups.length,
  660. pcode: dropGroup.code
  661. });
  662. modifyGroups = modifyGroups.concat(dragGroups, dropChildrenGroups);
  663. }else if(dropPosition === 1) { // 目标后
  664. dropGroups.splice(dropGroup.index + 1, 0, dragGroup);
  665. dropGroups = dropGroups.map((g, i) => {
  666. return { ...g, index: i, pcode: dropGroup.pcode }
  667. });
  668. modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
  669. }
  670. }
  671. }
  672. }else { // 不跨级
  673. if(dragGroup.pcode === dropGroup.pcode) { // 不跨组
  674. let dGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
  675. dGroups.splice(dragGroup.index, 1, {code: 'temp', index: dragGroup.index});
  676. if(dropPosition === -1) { // 目标前
  677. dGroups.splice(dropGroup.index, 0, dragGroup);
  678. dGroups = dGroups.filter(g => g.code !== 'temp').map((g, i) => {
  679. return { ...g, index: i }
  680. });
  681. modifyGroups = modifyGroups.concat(dGroups);
  682. }else if(dropPosition === 0) { // 目标内
  683. return;
  684. }else if(dropPosition === 1) { // 目标后
  685. dGroups.splice(dropGroup.index + 1, 0, dragGroup);
  686. dGroups = dGroups.filter(g => g.code !== 'temp').map((g, i) => {
  687. return { ...g, index: i }
  688. });
  689. modifyGroups = modifyGroups.concat(dGroups);
  690. }
  691. }else { // 跨组
  692. let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
  693. let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
  694. dragGroups.splice(dragGroup.index, 1);
  695. dragGroups = dragGroups.map((g, i) => {
  696. return { ...g, index: i }
  697. });
  698. for(let i = 0; i < dropGroups.length; i++) {
  699. if(dropGroups[i].code === dropGroup.code) {
  700. if(dropPosition === -1) { // 目标前
  701. dropGroups.splice(i, 0, dragGroup);
  702. dropGroups = dropGroups.map((g, i) => {
  703. return { ...g, index: i, pcode: dropGroup.pcode }
  704. });
  705. modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
  706. }else if(dropPosition === 0) { // 目标内
  707. return; // 不允许
  708. }else if(dropPosition === 1) { // 目标后
  709. dropGroups.splice(i + 1, 0, dragGroup);
  710. dropGroups = dropGroups.map((g, i) => {
  711. return { ...g, index: i, pcode: dropGroup.pcode }
  712. });
  713. modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
  714. }
  715. break;
  716. }
  717. }
  718. }
  719. }
  720. yield put({ type: 'remoteModifyGroups', groups: modifyGroups });
  721. }catch(e) {
  722. message.error('位置调整失败: ' + e.message);
  723. }
  724. },
  725. /**
  726. * 设置图表所属分组
  727. */
  728. *remoteSetGroup(action, { select, call, put }) {
  729. const { chart, group } = action;
  730. const chartCode = chart.code;
  731. const groupCode = group.code;
  732. try {
  733. let body = {
  734. id: chartCode,
  735. groupId: groupCode
  736. }
  737. let res = yield call(service.fetch, {
  738. url: URLS.GROUP_CHART_SET_GROUP,
  739. body: body
  740. });
  741. if(!res.err && res.data.code > 0) {
  742. yield put({ type: 'setChartGroup', chartCode, groupCode });
  743. }else {
  744. message.error('设置分组失败: ' + (res.err || res.data.msg));
  745. }
  746. } catch(e) {
  747. message.error('设置分组失败: ' + e.message);
  748. }
  749. },
  750. *transfer(action, { put, call, select }) {
  751. const { userCode, chartCode } = action;
  752. const body = {
  753. userId: userCode,
  754. id: chartCode
  755. };
  756. try {
  757. const res = yield call(service.fetch, {
  758. url: URLS.CHART_TRANSFER,
  759. body
  760. });
  761. if(!res.err && res.data.code > 0) {
  762. const chart = yield select(state => state.present.chart);
  763. const list = chart.list;
  764. for(let i = 0; i < list.length; i++) {
  765. if(list[i].code === chartCode) {
  766. list.splice(i, 1);
  767. break;
  768. }
  769. }
  770. yield put({ type: 'list', list });
  771. message.success('移交成功');
  772. }else {
  773. message.error('移交失败: ' + (res.err || res.data.msg));
  774. }
  775. }catch(e) {
  776. message.error('移交失败: ' + e.message);
  777. }
  778. },
  779. },
  780. subscriptions: {
  781. setup({ dispatch, history }) {
  782. dispatch({ type: 'reset' });
  783. }
  784. }
  785. }