path_tree.bak.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /**
  2. * 重构前备份
  3. *
  4. * 构建pathTree
  5. * 可动态加载子节点,要求子节点获取接口按/xxx/get-children定义
  6. * @param {Object} setting - 设置
  7. * @returns {PathTree}
  8. */
  9. const createNewPathTree = function (setting) {
  10. const treeSetting = JSON.parse(JSON.stringify(setting));
  11. const itemsPre = 'id_';
  12. const PathTree = function () {
  13. // 无索引
  14. this.datas = [];
  15. // 以key为索引
  16. this.items = {};
  17. // 以排序为索引
  18. this.nodes = [];
  19. };
  20. const proto = PathTree.prototype;
  21. /**
  22. * 树结构根据显示排序
  23. */
  24. proto.sortTreeNode = function () {
  25. const self = this;
  26. const addSortNodes = function (nodes) {
  27. for (let i = 0; i < nodes.length; i++) {
  28. self.nodes.push(nodes[i]);
  29. addSortNodes(self.getChildren(nodes[i]));
  30. }
  31. };
  32. self.nodes = [];
  33. addSortNodes(this.getChildren(null));
  34. };
  35. /**
  36. * 加载数据(初始化), 并给数据添加部分树结构必须数据
  37. * @param datas
  38. */
  39. proto.loadDatas = function (datas) {
  40. // 清空旧数据
  41. this.items = {};
  42. this.nodes = [];
  43. // 加载全部数据
  44. for (const data of datas) {
  45. const keyName = itemsPre + data[treeSetting.id];
  46. this.items[keyName] = JSON.parse(JSON.stringify(data));
  47. this.datas.push(this.items[keyName]);
  48. }
  49. this.sortTreeNode();
  50. for (const node of this.nodes) {
  51. const children = this.getChildren(node);
  52. node.expanded = children.length > 0;
  53. node.visible = true;
  54. }
  55. };
  56. /**
  57. * 加载数据(动态),只加载不同部分
  58. * @param {Array} datas
  59. * @return {Array} 加载到树的数据
  60. * @privateA
  61. */
  62. proto._updateData = function (datas) {
  63. const loadedData = [];
  64. for (const data of datas) {
  65. let node = this.getItems(data[treeSetting.id]);
  66. if (node) {
  67. for (const prop in node) {
  68. if (data[prop] !== undefined) {
  69. node[prop] = data[prop];
  70. }
  71. }
  72. loadedData.push(node);
  73. }
  74. }
  75. for (const node of loadedData) {
  76. const children = this.getChildren(node);
  77. node.expanded = children.length > 0 && children[0].visible;
  78. }
  79. this.sortTreeNode();
  80. return loadedData;
  81. };
  82. /**
  83. * 加载数据(动态),只加载不同部分
  84. * @param {Array} datas
  85. * @return {Array} 加载到树的数据
  86. * @privateA
  87. */
  88. proto._loadData = function (datas) {
  89. const loadedData = [];
  90. for (const data of datas) {
  91. let node = this.getItems(data[treeSetting.id]);
  92. if (node) {
  93. for (const prop in node) {
  94. if (data[prop] !== undefined) {
  95. node[prop] = data[prop];
  96. }
  97. }
  98. loadedData.push(node);
  99. } else {
  100. const keyName = itemsPre + data[treeSetting.id];
  101. const node = JSON.parse(JSON.stringify(data));
  102. this.items[keyName] = node;
  103. this.datas.push(node);
  104. node.expanded = false;
  105. node.visible = true;
  106. loadedData.push(node);
  107. }
  108. }
  109. this.sortTreeNode();
  110. for (const node of loadedData) {
  111. const children = this.getChildren(node);
  112. if (!node.expanded && children.length > 0) {
  113. node.expanded = true;
  114. this._refreshChildrenVisible(node);
  115. }
  116. }
  117. return loadedData;
  118. };
  119. /**
  120. * 清理数据(动态)
  121. * @param datas
  122. * @private
  123. */
  124. proto._freeData = function (datas) {
  125. const removeArrayData = function (array, data) {
  126. const index = array.indexOf(data);
  127. array.splice(index, 1);
  128. };
  129. for (const data of datas) {
  130. const node = this.getItems(data[treeSetting.id]);
  131. if (node) {
  132. delete this.items[itemsPre + node[treeSetting.id]];
  133. removeArrayData(this.datas, node);
  134. removeArrayData(this.nodes, node);
  135. }
  136. }
  137. };
  138. /**
  139. * 加载需展开的数据
  140. * @param {Array} datas
  141. * @returns {Array}
  142. * @private
  143. */
  144. proto._loadExpandData = function (datas) {
  145. const loadedData = [], existData = [], expandData = [];
  146. for (const data of datas) {
  147. let node = this.getItems(data[treeSetting.id]);
  148. if (node) {
  149. existData.push(node);
  150. } else {
  151. const keyName = itemsPre + data[treeSetting.id];
  152. const node = JSON.parse(JSON.stringify(data));
  153. this.items[keyName] = node;
  154. this.datas.push(node);
  155. node.expanded = false;
  156. node.visible = true;
  157. loadedData.push(node);
  158. }
  159. }
  160. this.sortTreeNode();
  161. for (const node of loadedData) {
  162. const children = this.getChildren(node);
  163. if (!node.expanded && children.length > 0) {
  164. node.expaned = true;
  165. this._refreshChildrenVisible(node);
  166. }
  167. }
  168. for (const node of existData) {
  169. const children = this.getChildren(node);
  170. if (!node.expanded && children.length > 0) {
  171. node.expanded = children.length > 0;
  172. this._refreshChildrenVisible(node);
  173. expandData.push(node);
  174. }
  175. }
  176. return [loadedData, expandData];
  177. };
  178. /**
  179. * 根据id获取树结构节点数据
  180. * @param {Number} id
  181. * @returns {Object}
  182. */
  183. proto.getItems = function (id) {
  184. return this.items[itemsPre + id];
  185. };
  186. /**
  187. * 查找node的parent
  188. * @param {Object} node
  189. * @returns {Object}
  190. */
  191. proto.getParent = function (node) {
  192. return this.getItems(node[treeSetting.pid]);
  193. };
  194. /**
  195. * 查询node的已下载子节点
  196. * @param {Object} node
  197. * @returns {Array}
  198. */
  199. proto.getChildren = function (node) {
  200. const pid = node ? node[treeSetting.id] : treeSetting.rootId;
  201. const children = this.datas.filter(function (x) {
  202. return x[treeSetting.pid] === pid;
  203. });
  204. children.sort(function (a, b) {
  205. return a.order - b.order;
  206. });
  207. return children;
  208. };
  209. /**
  210. * 查询node的已下载的全部后代
  211. * @param {Object} node
  212. * @returns {Array}
  213. */
  214. proto.getPosterity = function (node) {
  215. const field = this.setting.fullPath;
  216. const reg = new RegExp('^' + node[field] + '.');
  217. return this.datas.filter(function (x) {
  218. return reg.test(x[field]);
  219. })
  220. };
  221. /**
  222. * 查询node是否是父节点的最后一个子节点
  223. * @param {Object} node
  224. * @returns {boolean}
  225. */
  226. proto.isLastSibling = function (node) {
  227. const siblings = this.getChildren(this.getParent(node));
  228. return node[this.setting.order] === siblings[siblings.length - 1][this.setting.order];
  229. };
  230. /**
  231. * 刷新子节点是否可见
  232. * @param {Object} node
  233. * @private
  234. */
  235. proto._refreshChildrenVisible = function (node) {
  236. const children = this.getChildren(node);
  237. for (const child of children) {
  238. child.visible = node.expanded && node.visible;
  239. this._refreshChildrenVisible(child);
  240. }
  241. }
  242. /**
  243. * 设置节点是否展开, 并控制子节点可见
  244. * @param {Object} node
  245. * @param {Boolean} expanded
  246. */
  247. proto.setExpanded = function (node, expanded) {
  248. node.expanded = expanded;
  249. this._refreshChildrenVisible(node);
  250. };
  251. /**
  252. * 提取节点key和索引数据
  253. * @param {Object} node - 节点
  254. * @returns {key}
  255. */
  256. proto.getNodeKeyData = function (node) {
  257. const data = {};
  258. for (const key of treeSetting.keys) {
  259. data[key] = node[key];
  260. }
  261. return data;
  262. }
  263. /**
  264. * 得到树结构构成id
  265. * @param node
  266. * @returns {*}
  267. */
  268. proto.getNodeKey = function (node) {
  269. return node[treeSetting.id];
  270. }
  271. /**
  272. * 以下方法需等待响应, 通过callback刷新界面
  273. */
  274. /**
  275. * 加载子节点
  276. * @param {Object} node
  277. * @param {function} callback
  278. */
  279. proto.loadChildren = function (node, callback) {
  280. const self = this;
  281. const url = treeSetting.preUrl ? treeSetting.preUrl + '/get-children' : 'get-children';
  282. postData(url, this.getNodeKeyData(node), function (data) {
  283. self._loadData(data);
  284. callback();
  285. });
  286. };
  287. /**
  288. * 树结构基本操作
  289. * @param {String} url - 请求地址
  290. * @param {Object} node - 操作节点
  291. * @param {String} type - 操作类型
  292. * @param {function} callback - 界面刷新
  293. */
  294. proto.baseOperation = function (url, node, type, callback) {
  295. const self = this;
  296. const data = {
  297. id: node[treeSetting.id],
  298. postType: type
  299. };
  300. postData(url, data, function (datas) {
  301. const result = {};
  302. if (datas.update) {
  303. result.update = self._updateData(datas.update);
  304. }
  305. if (datas.create) {
  306. result.create = self._loadData(datas.create);
  307. }
  308. if (datas.delete) {
  309. result.delete = self._freeData(datas.delete);
  310. }
  311. callback(result);
  312. });
  313. };
  314. /**
  315. * 节点数据编辑
  316. * @param {String} url - 请求地址
  317. * @param {Array|Object} updateData - 需更新的数据
  318. * @param {function} callback - 界面刷新
  319. */
  320. proto.update = function (url, updateData, callback) {
  321. const self = this;
  322. postData(url, updateData, function (datas) {
  323. const result = self._updateData(datas);
  324. callback(result);
  325. }, function () {
  326. if (updateData instanceof Array) {
  327. const result = [];
  328. for (const data of updateData) {
  329. result.push(self.getItems(data[treeSetting.id]));
  330. }
  331. callback(result)
  332. } else {
  333. callback([self.getItems(updateData[treeSetting.id])]);
  334. }
  335. });
  336. };
  337. /**
  338. * 复制粘贴整块(目前仅可粘贴为后项)
  339. * @param {String} url - 请求地址
  340. * @param {Object} node - 操作节点
  341. * @param {Array} block - 被复制整块的节点列表
  342. * @param {function} callback - 界面刷新
  343. */
  344. proto.pasteBlock = function (url, node, block, callback) {
  345. const self = this;
  346. const data = {
  347. id: node[treeSetting.id],
  348. block: block
  349. };
  350. postData(url, data, function (datas) {
  351. const result = {};
  352. if (datas.update) {
  353. result.update = self._updateData(datas.update);
  354. }
  355. if (datas.create) {
  356. result.create = self._loadData(datas.create);
  357. }
  358. if (datas.delete) {
  359. result.delete = self._freeData(datas.delete);
  360. }
  361. callback(result);
  362. });
  363. };
  364. /**
  365. * 提交数据
  366. * @param {String} url - 请求地址
  367. * @param {Object} node - 当前选中节点
  368. * @param {Object} data - 提交的数据
  369. * @param {function} callback - 界面刷新
  370. */
  371. proto.postData = function (url, node, data, callback) {
  372. const self = this;
  373. data.id = node[treeSetting.id];
  374. postData(url, data, function (datas) {
  375. const result = {};
  376. if (datas.update) {
  377. result.update = self._updateData(datas.update);
  378. }
  379. if (datas.create) {
  380. result.create = self._loadData(datas.create);
  381. }
  382. if (datas.delete) {
  383. result.delete = self._freeData(datas.delete);
  384. }
  385. if (datas.expand) {
  386. const [create, update] = self._loadExpandData(datas.expand);
  387. result.create = result.create.concat(create);
  388. result.expand = update;
  389. }
  390. callback(result);
  391. });
  392. };
  393. proto.batchInsert = function (url, node, data, callback) {
  394. const self = this;
  395. data.id = node[treeSetting.id];
  396. postData(url, data, function (datas) {
  397. const result = {};
  398. if (datas.update) {
  399. result.update = self._updateData(datas.update);
  400. }
  401. if (datas.create) {
  402. result.create = self._loadData(datas.create);
  403. }
  404. if (datas.delete) {
  405. result.delete = self._freeData(datas.delete);
  406. }
  407. callback(result);
  408. });
  409. }
  410. return new PathTree();
  411. }