main.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <template>
  2. <div class="flex pd-20">
  3. <el-card class="box-card flex1">
  4. <div slot="header" class="flex jc-sb">
  5. <span>{{leftNum}}项</span>
  6. <el-checkbox v-if="showAllCheck" v-model="allChecked" @change="checkChang">默认全部引用</el-checkbox>
  7. </div>
  8. <div v-loading="leftloading">
  9. <el-scrollbar :style="scrollbarStyle">
  10. <el-tree show-checkbox
  11. :data="leftTreeData" @check-change="checkChange('leftTree')"
  12. :props="defaultProps" :expand-on-click-node="false"
  13. highlight-current node-key="id"
  14. ref="leftTree" @node-expand="nodeExpand">
  15. </el-tree>
  16. </el-scrollbar>
  17. </div>
  18. </el-card>
  19. <div class="flex flex-d-c flex-center" style="width:50px;">
  20. <div><el-button @click="addTree" :type="leftNum <= 0 ? '' : 'success'" :disabled="leftNum <= 0" size="mini" icon="el-icon-arrow-right"></el-button></div>
  21. <div style="margin-top: 10px"><el-button @click="delTree" :type="rightNum <= 0 ? '' : 'success'" :disabled="rightNum <= 0" size="mini" icon="el-icon-arrow-left"></el-button></div>
  22. </div>
  23. <el-card class="box-card flex1">
  24. <div slot="header" class="clearfix">
  25. <span>{{rightNum}}项</span>
  26. </div>
  27. <div v-loading="rightloading">
  28. <el-scrollbar :style="scrollbarStyle">
  29. <el-tree show-checkbox
  30. :data="rightTreeData" @check-change="checkChange('rightTree')"
  31. :props="rightProps?rightProps:defaultProps" :expand-on-click-node="false"
  32. highlight-current node-key="id"
  33. ref="rightTree" :default-expanded-keys="rightExpands">
  34. </el-tree>
  35. </el-scrollbar>
  36. </div>
  37. </el-card>
  38. </div>
  39. </template>
  40. <script>
  41. export default {
  42. name: "treeTree",
  43. props: {
  44. leftTreeData: {
  45. type: Array,
  46. default: function () {
  47. return [];
  48. }
  49. },
  50. scrollbarStyle:{
  51. type:String,
  52. default:'height:calc(100vh - 400px)'
  53. },
  54. showAllCheck:{
  55. type:Boolean,
  56. default:false
  57. },
  58. rightProps:{
  59. type:Object,
  60. default: function () {
  61. return null;
  62. }
  63. },
  64. leftloading:{
  65. type:Boolean,
  66. default:false,
  67. },
  68. rightloading:{
  69. type:Boolean,
  70. default:false,
  71. }
  72. },
  73. computed: {
  74. },
  75. data(){
  76. return{
  77. defaultProps: {
  78. children: 'children',
  79. label: 'title',
  80. },
  81. leftNum:0,
  82. rightTreeData:[],
  83. rightNum:0,
  84. rightExpands:[],
  85. allChecked:false,
  86. }
  87. },
  88. methods:{
  89. addTree(){
  90. if(this.rightTreeData.length < 1){
  91. //直接把左边勾选的树复制到右侧
  92. //console.log(this.$refs.leftTree.getCheckedNodes())
  93. let allTree = JSON.parse(JSON.stringify(this.leftTreeData));
  94. //把半选和选中的数组key合并
  95. let keys = this.$refs.leftTree.getCheckedKeys().concat(this.$refs.leftTree.getHalfCheckedKeys());
  96. //console.log(keys,'keys');
  97. //console.log(allTree,'allTree');
  98. this.getRightTree(allTree,keys);
  99. this.rightTreeData = allTree;
  100. this.$emit('onAddTree',this.rightTreeData);
  101. }else{
  102. //只增加右侧树没有的节点,不会覆盖右侧树多余的节点
  103. let checkNodes = this.$refs.leftTree.getCheckedNodes(false,true);
  104. //console.log(checkNodes)
  105. let rIdMap = new Map();
  106. checkNodes.forEach((data)=>{
  107. rIdMap.set(data.id,data)
  108. })
  109. let lIdSet = new Set();
  110. this.getRightTreeData(lIdSet,this.rightTreeData);
  111. //在右侧id减去左侧有的id,剩下的就是新增的id
  112. lIdSet.forEach((id)=>{
  113. rIdMap.delete(id);
  114. })
  115. //console.log(rIdSet)
  116. let addMap = new Map();
  117. rIdMap.forEach((data)=>{
  118. if(data.parentId != '0'){
  119. //在左侧树能找到父节点的,新增
  120. let lNode = this.$refs.rightTree.getNode(data.parentId);
  121. if(lNode){
  122. addMap.set(data,lNode.data.id);
  123. }
  124. }
  125. })
  126. //把半选和选中的数组key合并
  127. let keys = this.$refs.leftTree.getCheckedKeys().concat(this.$refs.leftTree.getHalfCheckedKeys());
  128. const myArray = Array.from(addMap.keys());
  129. let myright= JSON.parse(JSON.stringify(myArray));
  130. this.getRightTree(myright,keys);
  131. myright.forEach((data)=>{
  132. this.$refs.rightTree.append(data,data.parentId);
  133. })
  134. // addMap.forEach((value,key)=>{
  135. // this.$refs.rightTree.append(key,value);
  136. // })
  137. }
  138. },
  139. getRightTree(arr,keys){
  140. //对比所有的node和选中的key
  141. for (let i = arr.length-1; i >= 0; i--) {
  142. let isIn = false;
  143. if(this.rightProps){
  144. //名称使用传入的字段
  145. arr[i][this.rightProps.label] = arr[i].title;
  146. }
  147. for (let j = keys.length-1; j >= 0; j--) {
  148. if(keys[j] == arr[i].id){
  149. isIn = true;
  150. //已经匹配到的key移除,节省性能
  151. keys.splice(j,1);
  152. break;
  153. }
  154. }
  155. if(isIn){
  156. //包含在选中的节点,如果有childer继续递归判断
  157. if(arr[i].children && arr[i].children.length){
  158. this.getRightTree(arr[i].children,keys);
  159. }
  160. }else{
  161. //不包含在选中key的node删除
  162. arr.splice(i,1);
  163. }
  164. }
  165. },
  166. getRightTreeData(set,arr){
  167. arr.forEach((data)=>{
  168. set.add(data.id);
  169. if(data.children && data.children.length){
  170. this.getRightTreeData(set,data.children);
  171. }
  172. })
  173. },
  174. delTree(){
  175. let delNodes = this.$refs.rightTree.getCheckedNodes();
  176. //只把选中的节点移除
  177. delNodes.forEach((node)=>{
  178. //console.log(node)
  179. this.$refs.rightTree.remove(node);
  180. this.$refs.leftTree.setChecked(node.id,false);
  181. })
  182. this.getRightNum();
  183. this.getLeftNum();
  184. this.$emit('onDelTree',delNodes);
  185. },
  186. nodeExpand(data){
  187. this.rightExpands = this.rightExpands.concat([data.id]);
  188. },
  189. checkChange(treeName){
  190. switch (treeName) {
  191. case 'leftTree':
  192. this.getLeftNum();
  193. break;
  194. case 'rightTree':
  195. this.getRightNum();
  196. break;
  197. }
  198. },
  199. setRightTree(data){
  200. this.rightTreeData = data;
  201. let ids = [];
  202. for (let i = 0; i < data.length; i++) {
  203. this.getLeafIds(ids,data[i])
  204. }
  205. //在左边把右边的节点勾选上
  206. this.$nextTick(()=>{
  207. this.$refs.leftTree.setCheckedKeys(ids,true);
  208. })
  209. },
  210. getTreeAllId(treeName){
  211. let tree = this.$refs[treeName];
  212. if(this.allChecked){
  213. tree = this.$refs.leftTree;
  214. }
  215. //console.log(tree.data);
  216. let ids = [];
  217. for (let i = 0; i < tree.data.length; i++) {
  218. this.getIds(ids,tree.data[i]);
  219. }
  220. //console.log(obj)
  221. return ids.join(',');
  222. },
  223. getIds(ids,data){
  224. ids.push(data.id);
  225. if(data.children && data.children.length){
  226. for (let i = 0; i < data.children.length; i++) {
  227. this.getIds(ids,data.children[i]);
  228. }
  229. }
  230. },
  231. getLeafIds(ids,data){
  232. if(data.children && data.children.length){
  233. for (let i = 0; i < data.children.length; i++) {
  234. this.getLeafIds(ids,data.children[i]);
  235. }
  236. }else{
  237. ids.push(data.id)
  238. }
  239. },
  240. checkChang(){
  241. this.$emit('onCheckAll');
  242. },
  243. getLeftNum(){
  244. let checkNum = this.$refs.leftTree.getCheckedKeys().length;
  245. let halfNum = this.$refs.leftTree.getHalfCheckedKeys().length;
  246. this.leftNum = checkNum+halfNum;
  247. },
  248. getRightNum(){
  249. let checkNum = this.$refs.rightTree.getCheckedKeys().length;
  250. let halfNum = this.$refs.rightTree.getHalfCheckedKeys().length;
  251. this.rightNum = checkNum+halfNum;
  252. }
  253. }
  254. };
  255. </script>