path_tree.bak.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  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 reg = new RegExp('^' + node.full_path + '.');
  216. return this.datas.filter(function (x) {
  217. return reg.test(x.full_path);
  218. })
  219. };
  220. /**
  221. * 查询node是否是父节点的最后一个子节点
  222. * @param {Object} node
  223. * @returns {boolean}
  224. */
  225. proto.isLastSibling = function (node) {
  226. const siblings = this.getChildren(this.getParent(node));
  227. return node.order === siblings[siblings.length - 1].order;
  228. };
  229. /**
  230. * 刷新子节点是否可见
  231. * @param {Object} node
  232. * @private
  233. */
  234. proto._refreshChildrenVisible = function (node) {
  235. const children = this.getChildren(node);
  236. for (const child of children) {
  237. child.visible = node.expanded && node.visible;
  238. this._refreshChildrenVisible(child);
  239. }
  240. }
  241. /**
  242. * 设置节点是否展开, 并控制子节点可见
  243. * @param {Object} node
  244. * @param {Boolean} expanded
  245. */
  246. proto.setExpanded = function (node, expanded) {
  247. node.expanded = expanded;
  248. this._refreshChildrenVisible(node);
  249. };
  250. /**
  251. * 提取节点key和索引数据
  252. * @param {Object} node - 节点
  253. * @returns {key}
  254. */
  255. proto.getNodeKeyData = function (node) {
  256. const data = {};
  257. for (const key of treeSetting.keys) {
  258. data[key] = node[key];
  259. }
  260. return data;
  261. }
  262. /**
  263. * 得到树结构构成id
  264. * @param node
  265. * @returns {*}
  266. */
  267. proto.getNodeKey = function (node) {
  268. return node[treeSetting.id];
  269. }
  270. /**
  271. * 以下方法需等待响应, 通过callback刷新界面
  272. */
  273. /**
  274. * 加载子节点
  275. * @param {Object} node
  276. * @param {function} callback
  277. */
  278. proto.loadChildren = function (node, callback) {
  279. const self = this;
  280. const url = treeSetting.preUrl ? treeSetting.preUrl + '/get-children' : 'get-children';
  281. postData(url, this.getNodeKeyData(node), function (data) {
  282. self._loadData(data);
  283. callback();
  284. });
  285. };
  286. /**
  287. * 树结构基本操作
  288. * @param {String} url - 请求地址
  289. * @param {Object} node - 操作节点
  290. * @param {String} type - 操作类型
  291. * @param {function} callback - 界面刷新
  292. */
  293. proto.baseOperation = function (url, node, type, callback) {
  294. const self = this;
  295. const data = {
  296. id: node[treeSetting.id],
  297. postType: type
  298. };
  299. postData(url, data, function (datas) {
  300. const result = {};
  301. if (datas.update) {
  302. result.update = self._updateData(datas.update);
  303. }
  304. if (datas.create) {
  305. result.create = self._loadData(datas.create);
  306. }
  307. if (datas.delete) {
  308. result.delete = self._freeData(datas.delete);
  309. }
  310. callback(result);
  311. });
  312. };
  313. /**
  314. * 节点数据编辑
  315. * @param {String} url - 请求地址
  316. * @param {Array|Object} updateData - 需更新的数据
  317. * @param {function} callback - 界面刷新
  318. */
  319. proto.update = function (url, updateData, callback) {
  320. const self = this;
  321. postData(url, updateData, function (datas) {
  322. const result = self._updateData(datas);
  323. callback(result);
  324. }, function () {
  325. if (updateData instanceof Array) {
  326. const result = [];
  327. for (const data of updateData) {
  328. result.push(self.getItems(data[treeSetting.id]));
  329. }
  330. callback(result)
  331. } else {
  332. callback([self.getItems(updateData[treeSetting.id])]);
  333. }
  334. });
  335. };
  336. /**
  337. * 复制粘贴整块(目前仅可粘贴为后项)
  338. * @param {String} url - 请求地址
  339. * @param {Object} node - 操作节点
  340. * @param {Array} block - 被复制整块的节点列表
  341. * @param {function} callback - 界面刷新
  342. */
  343. proto.pasteBlock = function (url, node, block, callback) {
  344. const self = this;
  345. const data = {
  346. id: node[treeSetting.id],
  347. block: block
  348. };
  349. postData(url, data, function (datas) {
  350. const result = {};
  351. if (datas.update) {
  352. result.update = self._updateData(datas.update);
  353. }
  354. if (datas.create) {
  355. result.create = self._loadData(datas.create);
  356. }
  357. if (datas.delete) {
  358. result.delete = self._freeData(datas.delete);
  359. }
  360. callback(result);
  361. });
  362. };
  363. /**
  364. * 提交数据
  365. * @param {String} url - 请求地址
  366. * @param {Object} node - 当前选中节点
  367. * @param {Object} data - 提交的数据
  368. * @param {function} callback - 界面刷新
  369. */
  370. proto.postData = function (url, node, data, callback) {
  371. const self = this;
  372. data.id = node[treeSetting.id];
  373. postData(url, data, function (datas) {
  374. const result = {};
  375. if (datas.update) {
  376. result.update = self._updateData(datas.update);
  377. }
  378. if (datas.create) {
  379. result.create = self._loadData(datas.create);
  380. }
  381. if (datas.delete) {
  382. result.delete = self._freeData(datas.delete);
  383. }
  384. if (datas.expand) {
  385. const [create, update] = self._loadExpandData(datas.expand);
  386. result.create = result.create.concat(create);
  387. result.expand = update;
  388. }
  389. callback(result);
  390. });
  391. };
  392. proto.batchInsert = function (url, node, data, callback) {
  393. const self = this;
  394. data.id = node[treeSetting.id];
  395. postData(url, data, function (datas) {
  396. const result = {};
  397. if (datas.update) {
  398. result.update = self._updateData(datas.update);
  399. }
  400. if (datas.create) {
  401. result.create = self._loadData(datas.create);
  402. }
  403. if (datas.delete) {
  404. result.delete = self._freeData(datas.delete);
  405. }
  406. callback(result);
  407. });
  408. }
  409. return new PathTree();
  410. }