index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <template>
  2. <div class="tree-container">
  3. <el-row :gutter="20">
  4. <el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
  5. <el-divider content-position="left">常规树</el-divider>
  6. <el-input v-model="filterText" placeholder="输入关键字过滤" />
  7. <el-tree
  8. ref="demoTree"
  9. :data="data2"
  10. :default-checked-keys="defaultCheckedKeys"
  11. :default-expanded-keys="defaultExpendedKeys"
  12. :expand-on-click-node="false"
  13. :filter-node-method="filterNode"
  14. :highlight-current="true"
  15. :props="defaultProps"
  16. class="vab-filter-tree"
  17. node-key="id"
  18. show-checkbox
  19. @check="checkNode"
  20. @node-click="nodeClick"
  21. @node-collapse="nodeCollapse"
  22. @node-expand="nodeExpand"
  23. >
  24. <template #defalut="{ node, data }" class="vab-custom-tree-node">
  25. <span class="vab-tree-item">
  26. <i v-if="node.data.rank == 4" class="el-icon-s-custom"></i>
  27. {{ node.label }}
  28. </span>
  29. <span class="vab-tree-options">
  30. <a
  31. v-if="node.data.rank !== 4"
  32. class="vab-tree-btn"
  33. title="添加"
  34. @click="() => append(node, data, 0)"
  35. >
  36. <i class="el-icon-plus"></i>
  37. </a>
  38. <a
  39. class="vab-tree-btn"
  40. title="编辑"
  41. @click="() => edit(node, data, 1)"
  42. >
  43. <i class="el-icon-edit"></i>
  44. </a>
  45. <a
  46. v-if="node.data.rank !== 1"
  47. class="vab-tree-btn"
  48. title="刪除"
  49. @click="() => remove(node, data)"
  50. >
  51. <i class="el-icon-delete"></i>
  52. </a>
  53. </span>
  54. </template>
  55. </el-tree>
  56. </el-col>
  57. <el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
  58. <el-divider content-position="left">懒加载树</el-divider>
  59. <el-input
  60. v-model.lazy="keyW"
  61. :value="keyW"
  62. class="input-with-select"
  63. placeholder="请输入内容"
  64. @keyup.enter.native="showTreeList"
  65. ></el-input>
  66. <div v-show="isShow" class="blur-tree">
  67. <el-tree
  68. ref="treeFilter"
  69. :data="filterDevLlist"
  70. :expand-on-click-node="false"
  71. :props="defaultProps"
  72. class="vab-filter-tree"
  73. default-expand-all
  74. highlight-current
  75. node-key="indexCode"
  76. @node-click="nodeClick"
  77. >
  78. <template #defalut="{ node }" class="vab-custom-tree-node">
  79. <span class="vab-tree-item">
  80. <i v-if="node.data.rank == 4" class="el-icon-s-custom"></i>
  81. {{ node.label }}
  82. </span>
  83. <span class="vab-tree-options">
  84. <a
  85. v-if="node.data.rank !== 4"
  86. class="vab-tree-btn"
  87. title="添加"
  88. >
  89. <i class="el-icon-plus"></i>
  90. </a>
  91. <a class="vab-tree-btn" title="编辑">
  92. <i class="el-icon-edit"></i>
  93. </a>
  94. <a
  95. v-if="node.data.rank !== 1"
  96. class="vab-tree-btn"
  97. title="刪除"
  98. >
  99. <i class="el-icon-delete"></i>
  100. </a>
  101. </span>
  102. </template>
  103. </el-tree>
  104. </div>
  105. <div v-show="!isShow" class="el-tree-wrap">
  106. <el-tree
  107. ref="tree"
  108. v-loading="loading"
  109. :expand-on-click-node="false"
  110. :load="loadNode"
  111. :props="defaultProps"
  112. class="vab-filter-tree"
  113. highlight-current
  114. lazy
  115. node-key="indexCode"
  116. @node-click="nodeClick"
  117. >
  118. <template #defalut="{ node }" class="vab-custom-tree-node">
  119. <span class="vab-tree-item">
  120. <i v-if="node.data.rank == 4" class="el-icon-s-custom"></i>
  121. {{ node.label }}
  122. </span>
  123. <span class="vab-tree-options">
  124. <!-- <a v-if="node.data.rank !== 4" class="vab-tree-btn" title="添加""><i class="el-icon-plus"></i></a> -->
  125. <a class="vab-tree-btn" title="编辑">
  126. <i class="el-icon-edit"></i>
  127. </a>
  128. <a
  129. v-if="node.data.rank !== 1"
  130. class="vab-tree-btn"
  131. title="刪除"
  132. >
  133. <i class="el-icon-delete"></i>
  134. </a>
  135. </span>
  136. </template>
  137. </el-tree>
  138. </div>
  139. </el-col>
  140. <el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
  141. <el-divider content-position="left">单选树</el-divider>
  142. <el-select
  143. ref="singleTree"
  144. v-model="singleSelectTreeVal"
  145. class="vab-tree-select"
  146. clearable
  147. popper-class="select-tree-popper"
  148. value-key="id"
  149. @clear="selectTreeClearHandle('single')"
  150. >
  151. <el-option :value="singleSelectTreeKey">
  152. <el-tree
  153. id="singleSelectTree"
  154. ref="singleSelectTree"
  155. :current-node-key="singleSelectTreeKey"
  156. :data="selectTreeData"
  157. :default-expanded-keys="selectTreeDefaultSelectedKeys"
  158. :highlight-current="true"
  159. :props="selectTreeDefaultProps"
  160. node-key="id"
  161. @node-click="selectTreeNodeClick"
  162. >
  163. <template #defalut="{ node }" class="vab-custom-tree-node">
  164. <span class="vab-tree-item">{{ node.label }}</span>
  165. </template>
  166. </el-tree>
  167. </el-option>
  168. </el-select>
  169. </el-col>
  170. <el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
  171. <el-divider content-position="left">多选树</el-divider>
  172. <el-select
  173. v-model="multipleSelectTreeVal"
  174. class="vab-tree-select"
  175. clearable
  176. collapse-tags
  177. multiple
  178. popper-class="select-tree-popper"
  179. @change="changeMultipleSelectTreeHandle"
  180. @clear="selectTreeClearHandle('multiple')"
  181. @remove-tag="removeSelectTreeTag"
  182. >
  183. <el-option :value="multipleSelectTreeKey">
  184. <el-tree
  185. id="multipleSelectTree"
  186. ref="multipleSelectTree"
  187. :current-node-key="multipleSelectTreeKey"
  188. :data="selectTreeData"
  189. :default-checked-keys="selectTreeDefaultSelectedKeys"
  190. :default-expanded-keys="selectTreeDefaultSelectedKeys"
  191. :highlight-current="true"
  192. :props="selectTreeDefaultProps"
  193. node-key="id"
  194. show-checkbox
  195. @check="multipleSelectTreeCheckNode"
  196. ></el-tree>
  197. </el-option>
  198. </el-select>
  199. </el-col>
  200. </el-row>
  201. <!--添加/编辑节点弹框-------------------start-->
  202. <el-dialog
  203. :title="dialogTitle"
  204. :visible.sync="treeDialogVisible"
  205. class="tree-operate-dialog"
  206. width="400px"
  207. @close="treeDialogVisible = false"
  208. >
  209. <el-form ref="treeForm" :model="treeForm">
  210. <el-form-item label="节点名称" required>
  211. <el-input v-model="treeForm.name"></el-input>
  212. </el-form-item>
  213. </el-form>
  214. <div slot="footer" class="dialog-footer">
  215. <el-button @click="treeDialogVisible = false">取 消</el-button>
  216. <el-button type="primary" @click="saveTree">确 定</el-button>
  217. </div>
  218. </el-dialog>
  219. <!--添加/编辑节点弹框-------------------end-->
  220. </div>
  221. </template>
  222. <script>
  223. import { getTreeList } from "@/api/tree";
  224. export default {
  225. name: "Tree",
  226. data() {
  227. return {
  228. dialogTitle: "添加节点",
  229. treeFlag: 0,
  230. treeDialogVisible: false,
  231. treeForm: {
  232. id: "",
  233. name: "",
  234. },
  235. checkNodeKeys: [],
  236. filterText: "",
  237. data2: [],
  238. defaultProps: {
  239. children: "children",
  240. label: "name",
  241. },
  242. defaultExpendedKeys: [],
  243. defaultCheckedKeys: [],
  244. loading: true,
  245. keyW: "",
  246. filterDevLlist: [],
  247. isShow: false,
  248. updateTree: true,
  249. /* 单选树-多选树---------开始 */
  250. selectLevel: 4, // 树可选叶子level等级
  251. singleSelectTreeVal: "", //单选树默认label值
  252. singleSelectTreeKey: "", //单选树默认key值
  253. selectTreeData: [], //单选树的值
  254. selectTreeDefaultSelectedKeys: [], //单选树默认展开的key值数组
  255. selectTreeDefaultProps: {
  256. children: "children",
  257. label: "name",
  258. },
  259. multipleSelectTreeVal: [], //多选树默认label值
  260. multipleSelectTreeKey: "", //多选树默认key值
  261. /* 单选树-多选树---------结束 */
  262. };
  263. },
  264. watch: {
  265. filterText(val) {
  266. this.$refs.demoTree.filter(val);
  267. },
  268. },
  269. mounted() {
  270. this.$nextTick(() => {
  271. this.getTreeListFuc(1);
  272. this.setCheckedKeys();
  273. // 初始化单选树
  274. this.initSingleTree("single");
  275. // 初始化多选树
  276. this.initSingleTree("multiple");
  277. });
  278. },
  279. methods: {
  280. // 树level小于n级展开方法
  281. openTree(treeData, n) {
  282. const each = (data) => {
  283. data.forEach((e) => {
  284. if (e.rank <= n) {
  285. this.defaultExpendedKeys.push(e.id);
  286. }
  287. if (e.children.length > 0) {
  288. each(e.children);
  289. }
  290. });
  291. };
  292. each(treeData);
  293. },
  294. // 获取tree数据
  295. async getTreeListFuc(flag) {
  296. const { data } = await getTreeList();
  297. this.data2 = data;
  298. if (flag) {
  299. this.openTree(this.data2, 2);
  300. }
  301. },
  302. // 节点过滤操作
  303. filterNode(value, data) {
  304. if (!value) return true;
  305. return data.name.indexOf(value) !== -1;
  306. },
  307. // 添加节点操作
  308. append(node, data, flag) {
  309. this.treeFlag = flag;
  310. this.dialogTitle = "添加节点";
  311. this.treeForm = {
  312. id: "",
  313. name: "",
  314. };
  315. this.treeDialogVisible = true;
  316. },
  317. // 编辑节点操作
  318. edit(node, data, flag) {
  319. this.treeFlag = flag;
  320. this.dialogTitle = "编辑节点";
  321. this.treeForm = {
  322. id: data.id,
  323. name: data.name,
  324. };
  325. this.treeDialogVisible = true;
  326. },
  327. // 删除节点操作
  328. remove(node, data) {
  329. this.$baseConfirm("你确定要删除该节点?", null, async () => {
  330. const { msg } = getTreeList();
  331. this.$baseMessage(msg, "success");
  332. this.getTreeListFuc(0);
  333. });
  334. },
  335. // 保存添加和编辑
  336. saveTree() {
  337. this.$refs.treeForm.validate(async (valid) => {
  338. if (valid) {
  339. const { msg } = await getTreeList();
  340. this.$baseMessage(msg, "success");
  341. this.treeDialogVisible = false;
  342. this.getTreeListFuc(0);
  343. }
  344. });
  345. },
  346. // 设置节点选中
  347. setCheckedKeys() {
  348. this.$refs.demoTree.setCheckedKeys([1]);
  349. },
  350. // 点击叶子节点
  351. nodeClick(data, node, el) {},
  352. // 节点选中操作
  353. checkNode(data, node, el) {
  354. this.checkNodeKeys = node.checkedKeys;
  355. },
  356. // 节点展开操作
  357. nodeExpand(data, node, el) {
  358. this.defaultExpendedKeys.push(data.id);
  359. },
  360. // 节点关闭操作
  361. nodeCollapse(data, node, el) {
  362. this.defaultExpendedKeys.splice(
  363. this.defaultExpendedKeys.findIndex((item) => item.id === data.id),
  364. 1
  365. );
  366. },
  367. async loadNode(node, resolve) {
  368. if (node.level === 0) {
  369. const { data } = await getTreeList();
  370. this.loading = false;
  371. return resolve(data);
  372. } else {
  373. const { data } = await getTreeList();
  374. return resolve(res.data);
  375. }
  376. },
  377. //懒加载树输入框筛选方法
  378. async showTreeList(value) {
  379. if (typeof value === "string") {
  380. this.keyW = value.trim();
  381. }
  382. if (this.keyW.length !== 0) {
  383. // 请求后台返回查询结果
  384. let treeOption = {};
  385. treeOption = {
  386. keyWord: this.keyW,
  387. };
  388. const { data } = await getTreeList();
  389. this.filterDevLlist = data;
  390. this.isShow = true;
  391. } else {
  392. this.isShow = false;
  393. }
  394. },
  395. /* 单选/多选树方法-------------------开始 */
  396. // 初始化单选树的值
  397. async initSingleTree(treeType) {
  398. const { data } = await getTreeList();
  399. this.selectTreeData = data;
  400. this.$nextTick(() => {
  401. this.selectTreeDefaultSelectedKeys = this.singleSelectTreeKey.split(
  402. ","
  403. ); // 设置默认展开
  404. if (treeType == "single") {
  405. //单选树
  406. this.$refs.singleSelectTree.setCurrentKey(this.singleSelectTreeKey); // 设置默认选中
  407. } else {
  408. // 多选树
  409. this.$refs.multipleSelectTree.setCheckedKeys(
  410. this.selectTreeDefaultSelectedKeys
  411. );
  412. }
  413. });
  414. },
  415. // 清除单选树选中
  416. selectTreeClearHandle(type) {
  417. this.selectTreeDefaultSelectedKeys = [];
  418. this.clearSelected();
  419. if (type == "single") {
  420. this.singleSelectTreeVal = "";
  421. this.singleSelectTreeKey = "";
  422. this.$refs.singleSelectTree.setCurrentKey(""); // 设置默认选中
  423. } else {
  424. this.multipleSelectTreeVal = [];
  425. this.multipleSelectTreeKey = "";
  426. this.$refs.multipleSelectTree.setCheckedKeys([]);
  427. }
  428. },
  429. /* 清空选中样式 */
  430. clearSelected() {
  431. const allNode = document.querySelectorAll(
  432. "#singleSelectTree .el-tree-node"
  433. );
  434. allNode.forEach((element) => element.classList.remove("is-current"));
  435. },
  436. // select多选时移除某项操作
  437. removeSelectTreeTag(val) {
  438. const stack = JSON.parse(JSON.stringify(this.selectTreeData));
  439. while (stack.length) {
  440. const curr = stack.shift();
  441. if (curr.name == val) {
  442. return this.$refs.multipleSelectTree.setChecked(curr.id, false);
  443. }
  444. if (curr.children && curr.children.length) {
  445. stack.unshift(...curr.children);
  446. }
  447. }
  448. },
  449. changeMultipleSelectTreeHandle(val) {},
  450. // 点击叶子节点
  451. selectTreeNodeClick(data, node, el) {
  452. if (data.rank >= this.selectLevel) {
  453. this.singleSelectTreeVal = data.name;
  454. this.singleSelectTreeKey = data.id;
  455. this.$refs.singleTree.blur();
  456. }
  457. },
  458. // 节点选中操作
  459. multipleSelectTreeCheckNode(data, node, el) {
  460. const checkedNodes = this.$refs.multipleSelectTree.getCheckedNodes();
  461. const keyArr = [];
  462. const valueArr = [];
  463. checkedNodes.forEach((item) => {
  464. if (item.rank >= this.selectLevel) {
  465. keyArr.push(item.id);
  466. valueArr.push(item.name);
  467. }
  468. });
  469. this.multipleSelectTreeVal = valueArr;
  470. this.multipleSelectTreeKey = keyArr.join(",");
  471. },
  472. /* 单选/多选树方法-------------------结束 */
  473. },
  474. };
  475. </script>