path_tree.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. /**
  2. * 构建pathTree
  3. * 可动态加载子节点,要求子节点获取接口按/xxx/get-children定义
  4. * @param {Object} setting - 设置
  5. * @returns {PathTree}
  6. */
  7. 'use strict';
  8. class PosData {
  9. /**
  10. * 构造函数
  11. * @param {id|Number, masterId|Number} setting
  12. */
  13. constructor (setting) {
  14. // 无索引
  15. this.datas = null;
  16. // 以key为索引
  17. this.items = {};
  18. // 以分类id为索引的有序
  19. this.masterRange = {};
  20. // pos设置
  21. this.setting = setting;
  22. }
  23. /**
  24. * 加载部位明细数据
  25. * @param datas
  26. */
  27. loadDatas(datas) {
  28. this.datas = datas;
  29. for (const data of this.datas) {
  30. const key = itemsPre + data[this.setting.id];
  31. this.items[key] = data;
  32. const masterKey = itemsPre + data[this.setting.masterId];
  33. if (!this.masterRange[masterKey]) {
  34. this.masterRange[masterKey] = [];
  35. }
  36. this.masterRange[masterKey].push(data);
  37. }
  38. }
  39. /**
  40. * 更新数据
  41. * @param datas
  42. */
  43. updateDatas(data) {
  44. const datas = data instanceof Array ? data : [data];
  45. for (const d of datas) {
  46. const key = itemsPre + d[this.setting.id];
  47. if (!this.items[key]) {
  48. this.datas.push(d);
  49. this.items[key] = d;
  50. const masterKey = itemsPre + d[this.setting.masterId];
  51. if (!this.masterRange[masterKey]) {
  52. this.masterRange[masterKey] = [];
  53. }
  54. this.masterRange[masterKey].push(d);
  55. } else {
  56. const pos = this.items[key];
  57. for (const prop in d) {
  58. pos[prop] = d[prop];
  59. }
  60. }
  61. }
  62. }
  63. /**
  64. * 移除数据
  65. * @param datas
  66. */
  67. removeDatas(data) {
  68. const datas = data instanceof Array ? data : [data];
  69. for (let i = datas.length - 1; i >= 0; i--) {
  70. const d = datas[i];
  71. this.datas.splice(this.datas.indexOf(d), 1);
  72. const key = itemsPre + d[this.setting.id];
  73. delete this.items[key];
  74. const masterKey = itemsPre + d[this.setting.masterId];
  75. const range = this.masterRange[masterKey];
  76. range.splice(range.indexOf(d), 1);
  77. if (range.length === 0) {
  78. delete this.masterRange[masterKey];
  79. }
  80. }
  81. }
  82. /**
  83. * 移除数据 - 根据分类id
  84. * @param mid
  85. */
  86. removeDatasByMasterId (mid) {
  87. const masterKey = itemsPre + mid;
  88. const range = this.masterRange(mid);
  89. delete this.masterRange[masterKey];
  90. for (const r of range) {
  91. this.datas.splice(this.datas.indexOf(r), 1);
  92. const key = itemsPre + r[this.setting.id];
  93. delete this.items[key];
  94. }
  95. }
  96. getPos(id) {
  97. return this.items[itemsPre + id];
  98. }
  99. getMasterRange(mid) {
  100. return this.masterRange[itemsPre + mid];
  101. }
  102. }
  103. class StagePosData extends PosData {
  104. loadStageData(datas, fieldPre, fields) {
  105. datas = datas instanceof Array ? datas : [datas];
  106. const loadedData = [];
  107. for (const data of datas) {
  108. let node = this.getPos(data.pid);
  109. if (node) {
  110. for (const prop of fields) {
  111. if (data[fieldPre + prop] !== undefined) {
  112. node[fieldPre + prop] = data[prop];
  113. }
  114. }
  115. if (this.setting.calcFun) {
  116. this.setting.calcFun(node);
  117. }
  118. loadedData.push(node);
  119. }
  120. }
  121. }
  122. loadPreStageData(datas) {
  123. this.loadStageData(datas, 'pre_', this.setting.updateFields);
  124. }
  125. loadCurStageData(datas) {
  126. this.loadStageData(datas, '', this.setting.updateFields);
  127. }
  128. calculateAll() {
  129. if (!this.setting.calcFun) { return; }
  130. for (const pos of this.datas) {
  131. this.setting.calcFun(pos);
  132. }
  133. }
  134. }
  135. const itemsPre = 'id_';
  136. const createNewPathTree = function (type, setting) {
  137. class BaseTree {
  138. /**
  139. * 构造函数
  140. */
  141. constructor (setting) {
  142. // 无索引
  143. this.datas = [];
  144. // 以key为索引
  145. this.items = {};
  146. // 以排序为索引
  147. this.nodes = [];
  148. // 根节点
  149. this.children = {};
  150. // 树设置
  151. this.setting = setting;
  152. }
  153. /**
  154. * 树结构根据显示排序
  155. */
  156. sortTreeNode (isResort) {
  157. const self = this;
  158. const addSortNodes = function (nodes) {
  159. if (!nodes) { return }
  160. for (let i = 0; i < nodes.length; i++) {
  161. self.nodes.push(nodes[i]);
  162. nodes[i].index = self.nodes.length - 1;
  163. if (!isResort) {
  164. nodes[i].children = self.getChildren(nodes[i]);
  165. }
  166. addSortNodes(nodes[i].children);
  167. }
  168. };
  169. self.nodes = [];
  170. addSortNodes(this.getChildren(null));
  171. }
  172. /**
  173. * 加载数据(初始化), 并给数据添加部分树结构必须数据
  174. * @param datas
  175. */
  176. loadDatas (datas) {
  177. // 清空旧数据
  178. this.items = {};
  179. this.nodes = [];
  180. // 加载全部数据
  181. for (const data of datas) {
  182. const keyName = itemsPre + data[this.setting.id];
  183. this.items[keyName] = JSON.parse(JSON.stringify(data));
  184. this.datas.push(this.items[keyName]);
  185. }
  186. this.sortTreeNode();
  187. for (const node of this.nodes) {
  188. node.expanded = node.children.length > 0;
  189. node.visible = true;
  190. }
  191. }
  192. getItemsByIndex(index) {
  193. return this.nodes[index];
  194. }
  195. /**
  196. * 根据id获取树结构节点数据
  197. * @param {Number} id
  198. * @returns {Object}
  199. */
  200. getItems (id) {
  201. return this.items[itemsPre + id];
  202. };
  203. /**
  204. * 查找node的parent
  205. * @param {Object} node
  206. * @returns {Object}
  207. */
  208. getParent (node) {
  209. return this.getItems(node[this.setting.pid]);
  210. };
  211. /**
  212. * 根据path查找完整节点
  213. * @param {Number} path
  214. */
  215. getFullPathNodes (path) {
  216. const self = this, ids = path.split('.');
  217. if (ids.length > 0) {
  218. return this.nodes.filter((x) => {
  219. return ids.indexOf('' + x[self.setting.id]) >= 0;
  220. });
  221. } else {
  222. return [];
  223. }
  224. };
  225. /**
  226. * 查询node的已下载子节点
  227. * @param {Object} node
  228. * @returns {Array}
  229. */
  230. getChildren (node) {
  231. const setting = this.setting;
  232. const pid = node ? node[setting.id] : setting.rootId;
  233. const children = this.datas.filter(function (x) {
  234. return x[setting.pid] === pid;
  235. });
  236. children.sort(function (a, b) {
  237. return a.order - b.order;
  238. });
  239. return children;
  240. };
  241. /**
  242. * 查询node的已下载的全部后代
  243. * @param {Object} node
  244. * @returns {Array}
  245. */
  246. getPosterity (node) {
  247. const reg = new RegExp('^' + node.full_path + '.');
  248. return this.datas.filter(function (x) {
  249. return reg.test(x.full_path);
  250. })
  251. };
  252. /**
  253. * 查询node是否是父节点的最后一个子节点
  254. * @param {Object} node
  255. * @returns {boolean}
  256. */
  257. isLastSibling (node) {
  258. const siblings = this.getChildren(this.getParent(node));
  259. return node.order === siblings[siblings.length - 1].order;
  260. };
  261. /**
  262. * 刷新子节点是否可见
  263. * @param {Object} node
  264. * @private
  265. */
  266. _refreshChildrenVisible (node) {
  267. if (!node.children) {
  268. node.children = this.getChildren(node);
  269. }
  270. if (node.children && node.children.length > 0) {
  271. for (const child of node.children) {
  272. child.visible = node.expanded && node.visible;
  273. this._refreshChildrenVisible(child);
  274. }
  275. }
  276. };
  277. /**
  278. * 设置节点是否展开, 并控制子节点可见
  279. * @param {Object} node
  280. * @param {Boolean} expanded
  281. */
  282. setExpanded (node, expanded) {
  283. node.expanded = expanded;
  284. this._refreshChildrenVisible(node);
  285. };
  286. /**
  287. * 提取节点key和索引数据
  288. * @param {Object} node - 节点
  289. * @returns {key}
  290. */
  291. getNodeKeyData (node) {
  292. const data = {};
  293. for (const key of this.setting.keys) {
  294. data[key] = node[key];
  295. }
  296. return data;
  297. };
  298. /**
  299. * 得到树结构构成id
  300. * @param node
  301. * @returns {*}
  302. */
  303. getNodeKey (node) {
  304. return node[this.setting.id];
  305. };
  306. }
  307. class MeasureTree extends BaseTree {
  308. addData (datas) {
  309. const loadedData = [];
  310. for (const data of datas) {
  311. let node = this.getItems(data[this.setting.id]);
  312. if (node) {
  313. for (const prop in node) {
  314. if (data[prop] !== undefined) {
  315. node[prop] = data[prop];
  316. }
  317. }
  318. loadedData.push(node);
  319. } else {
  320. const keyName = itemsPre + data[this.setting.id];
  321. const node = JSON.parse(JSON.stringify(data));
  322. this.items[keyName] = node;
  323. this.datas.push(node);
  324. node.expanded = false;
  325. node.visible = true;
  326. loadedData.push(node);
  327. }
  328. }
  329. this.sortTreeNode();
  330. for (const node of loadedData) {
  331. const children = node.children;
  332. if (!node.expanded && children.length > 0) {
  333. node.expanded = true;
  334. this._refreshChildrenVisible(node);
  335. }
  336. }
  337. return loadedData;
  338. }
  339. removeData (datas) {
  340. datas.sort(function (a, b) {
  341. return b.level - a.level;
  342. });
  343. console.log(datas);
  344. const removeArrayData = function (array, data) {
  345. const index = array.indexOf(data);
  346. array.splice(index, 1);
  347. };
  348. for (const data of datas) {
  349. const node = this.getItems(data[this.setting.id]);
  350. if (node && this.getChildren(node).length === 0) {
  351. delete this.items[itemsPre + node[this.setting.id]];
  352. if (node[this.setting.pid] !== this.setting.rootId) {
  353. const parent = this.items[itemsPre + node[this.setting.pid]];
  354. removeArrayData(parent.children, node);
  355. }
  356. removeArrayData(this.datas, node);
  357. removeArrayData(this.nodes, node);
  358. }
  359. }
  360. };
  361. loadLeafData (data) {
  362. const datas = data instanceof Array ? data : [data];
  363. for (const d of datas) {
  364. let node = this.getItems(d[this.setting.id]);
  365. if (node && node.is_leaf) {
  366. for (const prop in node) {
  367. if (data[prop] !== undefined) {
  368. node[prop] = d[prop];
  369. }
  370. }
  371. }
  372. }
  373. };
  374. }
  375. class LedgerTree extends BaseTree {
  376. /**
  377. * 加载数据(动态),只加载不同部分
  378. * @param {Array} datas
  379. * @return {Array} 加载到树的数据
  380. * @privateA
  381. */
  382. _updateData (datas) {
  383. datas = datas instanceof Array ? datas : [datas];
  384. const loadedData = [];
  385. for (const data of datas) {
  386. let node = this.getItems(data[this.setting.id]);
  387. if (node) {
  388. for (const prop in node) {
  389. if (data[prop] !== undefined) {
  390. node[prop] = data[prop];
  391. }
  392. }
  393. loadedData.push(node);
  394. }
  395. }
  396. for (const node of loadedData) {
  397. const children = this.getChildren(node);
  398. node.expanded = children.length > 0 && children[0].visible;
  399. }
  400. this.sortTreeNode(true);
  401. return loadedData;
  402. };
  403. /**
  404. * 加载数据(动态),只加载不同部分
  405. * @param {Array} datas
  406. * @return {Array} 加载到树的数据
  407. * @privateA
  408. */
  409. _loadData (datas) {
  410. datas = datas instanceof Array ? datas : [datas];
  411. const loadedData = [], resortData = [];
  412. for (const data of datas) {
  413. let node = this.getItems(data[this.setting.id]);
  414. if (node) {
  415. const parent = this.getItems(node[this.setting.pid]);
  416. for (const prop in node) {
  417. if (data[prop] !== undefined && data[prop] !== node[prop]) {
  418. node[prop] = data[prop];
  419. if (parent && resortData.indexOf(parent) === -1) {
  420. resortData.push(parent);
  421. }
  422. }
  423. }
  424. loadedData.push(node);
  425. } else {
  426. const keyName = itemsPre + data[this.setting.id];
  427. const node = JSON.parse(JSON.stringify(data));
  428. this.items[keyName] = node;
  429. this.datas.push(node);
  430. node.expanded = false;
  431. node.visible = true;
  432. loadedData.push(node);
  433. if (resortData.indexOf(node) === -1) {
  434. resortData.push(node);
  435. }
  436. const parent = this.getItems(node[this.setting.pid]);
  437. if (parent && resortData.indexOf(parent) === -1) {
  438. resortData.push(parent);
  439. }
  440. }
  441. }
  442. for (const node of resortData) {
  443. node.children = this.getChildren(node);
  444. }
  445. this.sortTreeNode(true);
  446. for (const node of loadedData) {
  447. if (!node.expanded) {
  448. this.setExpanded(node, true);
  449. }
  450. }
  451. return loadedData;
  452. };
  453. /**
  454. * 清理数据(动态)
  455. * @param datas
  456. * @private
  457. */
  458. _freeData (datas) {
  459. datas = datas instanceof Array ? datas : [datas];
  460. const freeDatas = [];
  461. const removeArrayData = function (array, data) {
  462. const index = array.indexOf(data);
  463. array.splice(index, 1);
  464. };
  465. for (const data of datas) {
  466. const node = this.getItems(data[this.setting.id]);
  467. if (node) {
  468. freeDatas.push(node);
  469. delete this.items[itemsPre + node[this.setting.id]];
  470. if (node[this.setting.pid] !== this.setting.rootId) {
  471. const parent = this.getItems(node[this.setting.pid]);
  472. if (parent) {
  473. removeArrayData(parent.children, node);
  474. }
  475. }
  476. removeArrayData(this.datas, node);
  477. removeArrayData(this.nodes, node);
  478. }
  479. }
  480. return freeDatas;
  481. };
  482. /**
  483. * 加载需展开的数据
  484. * @param {Array} datas
  485. * @returns {Array}
  486. * @private
  487. */
  488. _loadExpandData (datas) {
  489. datas = datas instanceof Array ? datas : [datas];
  490. const loadedData = [], existData = [], expandData = [], resortData = [];
  491. for (const data of datas) {
  492. let node = this.getItems(data[this.setting.id]);
  493. if (node) {
  494. existData.push(node);
  495. } else {
  496. const keyName = itemsPre + data[this.setting.id];
  497. const node = JSON.parse(JSON.stringify(data));
  498. this.items[keyName] = node;
  499. this.datas.push(node);
  500. node.expanded = false;
  501. node.visible = true;
  502. loadedData.push(node);
  503. if (resortData.indexOf(node) === -1) {
  504. resortData.push(node);
  505. }
  506. const parent = this.getItems(node[this.setting.pid]);
  507. if (parent && resortData.indexOf(parent) === -1) {
  508. resortData.push(parent);
  509. }
  510. }
  511. }
  512. for (const node of resortData) {
  513. node.children = this.getChildren(node);
  514. }
  515. this.sortTreeNode(true);
  516. for (const node of loadedData) {
  517. if (!node.expanded) {
  518. this.setExpanded(node, true);
  519. }
  520. }
  521. for (const node of existData) {
  522. const parent = this.getItems(node[this.setting.pid]);
  523. if (expandData.indexOf(parent) === -1) {
  524. expandData.push(parent);
  525. if (!parent.expanded) {
  526. this.setExpanded(parent, true);
  527. }
  528. }
  529. if (!node.expanded) {
  530. this.setExpanded(node, true);
  531. }
  532. }
  533. return [loadedData, expandData];
  534. };
  535. /**
  536. *
  537. * @param parent
  538. * @param node
  539. * @private
  540. */
  541. _getNodesParents(parents, nodes) {
  542. for (const node of nodes) {
  543. const parent = this.getParent(node);
  544. if (parent) {
  545. const paths = this.getFullPathNodes(parent.full_path);
  546. for (const p of paths) {
  547. if (parents.indexOf(p) === -1) {
  548. parents.push(p);
  549. }
  550. }
  551. }
  552. if (node.children.length > 0) {
  553. parents.push(node);
  554. }
  555. }
  556. }
  557. isLeafXmj(node) {
  558. for (const child of node.children) {
  559. if (child.code !== '') {
  560. return false;
  561. }
  562. }
  563. return true;
  564. }
  565. /**
  566. * 因为提交其他数据,引起的树结构数据更新,调用该方法
  567. *
  568. * @param data - 更新的数据 {update, create, delete}
  569. * @param {function} callback - 界面刷新
  570. */
  571. loadPostData(data, callback) {
  572. const result = {}, parents = [];
  573. if (data.update) {
  574. result.update = this._updateData(data.update);
  575. this._getNodesParents(parents, result.update);
  576. }
  577. if (data.create) {
  578. result.create = this._loadData(data.create);
  579. this._getNodesParents(parents, result.create);
  580. }
  581. if (data.delete) {
  582. result.delete = this._freeData(data.delete);
  583. this._getNodesParents(parents, result.delete);
  584. }
  585. parents.sort((a, b) => {
  586. return b.level - a.level;
  587. });
  588. for (const parent of parents) {
  589. treeCalc.calculateNode(this, parent, this.setting.calcFields, this.setting.calcFun);
  590. }
  591. result.update = result.update ? result.update.concat(parents) : parents;
  592. callback(result);
  593. }
  594. /**
  595. * 以下方法需等待响应, 通过callback刷新界面
  596. */
  597. /**
  598. * 加载子节点
  599. * @param {Object} node
  600. * @param {function} callback
  601. */
  602. loadChildren (node, callback) {
  603. const self = this;
  604. const url = this.setting.preUrl ? this.setting.preUrl + '/get-children' : 'get-children';
  605. console.log(url);
  606. postData(url, this.getNodeKeyData(node), function (data) {
  607. self._loadData(data);
  608. callback();
  609. });
  610. };
  611. /**
  612. * 树结构基本操作
  613. * @param {String} url - 请求地址
  614. * @param {Object} node - 操作节点
  615. * @param {String} type - 操作类型
  616. * @param {function} callback - 界面刷新
  617. */
  618. baseOperation (url, node, type, callback) {
  619. const self = this;
  620. const data = {
  621. id: node[this.setting.id],
  622. postType: type
  623. };
  624. postData(url, data, function (datas) {
  625. self.loadPostData(datas, callback);
  626. });
  627. };
  628. /**
  629. * 节点数据编辑
  630. * @param {String} url - 请求地址
  631. * @param {Array|Object} updateData - 需更新的数据
  632. * @param {function} callback - 界面刷新
  633. */
  634. update (url, updateData, callback) {
  635. const self = this;
  636. postData(url, updateData, function (datas) {
  637. self.loadPostData(datas, callback);
  638. }, function () {
  639. if (updateData instanceof Array) {
  640. const result = [];
  641. for (const data of updateData) {
  642. result.push(self.getItems(data[self.setting.id]));
  643. }
  644. callback(result)
  645. } else {
  646. callback([self.getItems(updateData[self.setting.id])]);
  647. }
  648. });
  649. };
  650. /**
  651. * 复制粘贴整块(目前仅可粘贴为后项)
  652. * @param {String} url - 请求地址
  653. * @param {Object} node - 操作节点
  654. * @param {Array} block - 被复制整块的节点列表
  655. * @param {function} callback - 界面刷新
  656. */
  657. pasteBlock (url, node, block, callback) {
  658. const self = this;
  659. const data = {
  660. id: node[self.setting.id],
  661. block: block
  662. };
  663. postData(url, data, function (datas) {
  664. self.loadPostData(datas, callback);
  665. });
  666. };
  667. /**
  668. * 提交数据
  669. * @param {String} url - 请求地址
  670. * @param {Object} node - 当前选中节点
  671. * @param {Object} data - 提交的数据
  672. * @param {function} callback - 界面刷新
  673. */
  674. postData (url, node, data, callback) {
  675. const self = this;
  676. if (node) {
  677. data.id = node[self.setting.id];
  678. }
  679. postData(url, data, function (datas) {
  680. const result = {};
  681. if (datas.update) {
  682. result.update = self._updateData(datas.update);
  683. }
  684. if (datas.create) {
  685. result.create = self._loadData(datas.create);
  686. }
  687. if (datas.delete) {
  688. result.delete = self._freeData(datas.delete);
  689. }
  690. if (datas.expand) {
  691. const [create, update] = self._loadExpandData(datas.expand);
  692. result.create = result.create ? result.create.concat(create) : create;
  693. result.expand = update;
  694. }
  695. callback(result);
  696. });
  697. };
  698. }
  699. class StageTree extends BaseTree {
  700. /**
  701. * 构造函数
  702. */
  703. constructor (setting) {
  704. super(setting);
  705. // stage关联索引
  706. this.stageItems = {};
  707. }
  708. /**
  709. * 加载数据(初始化), 并给数据添加部分树结构必须数据
  710. * @param datas
  711. */
  712. loadDatas (datas) {
  713. super.loadDatas(datas);
  714. // 清空旧数据
  715. this.stageItems = {};
  716. // 加载全部数据
  717. for (const data of this.datas) {
  718. const keyName = itemsPre + data[this.setting.stageId];
  719. this.stageItems[keyName] = data;
  720. }
  721. }
  722. getStageItems(id) {
  723. return this.stageItems[itemsPre + id];
  724. }
  725. loadStageData(datas, fieldPre, fields) {
  726. datas = datas instanceof Array ? datas : [datas];
  727. const loadedData = [];
  728. for (const data of datas) {
  729. let node = this.getStageItems(data.lid);
  730. if (node) {
  731. for (const prop of fields) {
  732. if (data[fieldPre + prop] !== undefined) {
  733. node[fieldPre + prop] = data[prop];
  734. }
  735. }
  736. loadedData.push(node);
  737. }
  738. }
  739. }
  740. loadPreStageData(preStageData) {
  741. this.loadStageData(curStageData, 'pre_', this.setting.updateFields);
  742. }
  743. loadCurStageData(curStageData) {
  744. this.loadStageData(curStageData, '', this.setting.updateFields);
  745. }
  746. /**
  747. * 加载数据(动态),只加载不同部分
  748. * @param {Array} datas
  749. * @return {Array} 加载到树的数据
  750. * @privateA
  751. */
  752. _updateStageData (datas) {
  753. datas = datas instanceof Array ? datas : [datas];
  754. const loadedData = [];
  755. for (const data of datas) {
  756. let node = this.getStageItems(data.lid);
  757. if (node) {
  758. for (const prop of this.setting.updateFields) {
  759. if (data[prop] !== undefined) {
  760. node[prop] = data[prop];
  761. }
  762. }
  763. loadedData.push(node);
  764. }
  765. }
  766. return loadedData;
  767. };
  768. /**
  769. *
  770. * @param parent
  771. * @param node
  772. * @private
  773. */
  774. _getNodesParents(parents, nodes) {
  775. for (const node of nodes) {
  776. const parent = this.getParent(node);
  777. if (parent) {
  778. const paths = this.getFullPathNodes(parent.full_path);
  779. for (const p of paths) {
  780. if (parents.indexOf(p) === -1) {
  781. parents.push(p);
  782. }
  783. }
  784. }
  785. if (node.children && node.children.length > 0) {
  786. parents.push(node);
  787. }
  788. }
  789. }
  790. isLeafXmj(node) {
  791. for (const child of node.children) {
  792. if (child.code !== '') {
  793. return false;
  794. }
  795. }
  796. return true;
  797. }
  798. /**
  799. * 提交数据至后端,返回的前端树结构应刷新的部分
  800. * StageTree仅有更新CurStage部分,不需要增删
  801. *
  802. * @param data - 需要更新的数据
  803. * @returns {Array} - 界面需要刷新的数据
  804. */
  805. loadPostStageData(data) {
  806. let result, parents = [];
  807. if (data) {
  808. result = this._updateStageData(data);
  809. this._getNodesParents(parents, result);
  810. }
  811. result = result ? result.concat(parents) : parents;
  812. result.sort((a, b) => {
  813. return b.level - a.level;
  814. });
  815. for (const node of result) {
  816. treeCalc.calculateNode(this, node);
  817. }
  818. return result;
  819. }
  820. }
  821. if (type === 'base') {
  822. return new BaseTree(setting);
  823. } else if (type === 'stage') {
  824. return new StageTree(setting);
  825. } else if (type === 'ledger') {
  826. return new LedgerTree(setting);
  827. } else if (type === 'measure') {
  828. return new MeasureTree(setting);
  829. }
  830. };
  831. const treeCalc = {
  832. getMaxLevel: function (tree) {
  833. return Math.max.apply(Math, tree.datas.map(function(o) {return o.level}));
  834. },
  835. calculateNode: function (tree, node) {
  836. if (node.children && node.children.length > 0) {
  837. const gather = node.children.reduce(function (rst, x) {
  838. const result = {};
  839. const fieldCalc = function (field) {
  840. if (rst[field]) {
  841. result[field] = x[field] ? rst[field] + x[field] : rst[field];
  842. } else {
  843. result[field] = x[field] ? x[field] : undefined;
  844. }
  845. }
  846. for (const cf of tree.setting.calcFields) {
  847. fieldCalc(cf);
  848. }
  849. return result;
  850. });
  851. // 汇总子项
  852. for (const cf of tree.setting.calcFields) {
  853. if (gather[cf]) {
  854. node[cf] = gather[cf];
  855. } else {
  856. node[cf] = null;
  857. }
  858. }
  859. }
  860. // 自身运算
  861. if (tree.setting.calcFun) {
  862. tree.setting.calcFun(node);
  863. }
  864. },
  865. calculateLevelNode: function (tree, level) {
  866. const nodes = tree.datas.filter((n) => { return n.level === level });
  867. for (const node of nodes) {
  868. this.calculateNode(tree, node);
  869. }
  870. },
  871. calculateAll: function (tree) {
  872. for (let i = this.getMaxLevel(tree); i >= 0; i--) {
  873. this.calculateLevelNode(tree, i);
  874. }
  875. },
  876. calculateParent: function (tree, node) {
  877. const nodes = tree.getFullPathNodes(node.full_path);
  878. nodes.sort((a, b) => {
  879. return b.level - a.level;
  880. });
  881. for (const n of nodes) {
  882. this.calculateNode(tree, n);
  883. }
  884. return nodes;
  885. }
  886. };