tree.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <template>
  2. <div class="shadow rounded-[6px] shadow-blue-500" :style="{
  3. height:
  4. typeof props.height === 'string' ? props.height : props.height + 'px',
  5. overflowY: 'hidden'
  6. }">
  7. <el-input class="pb-[10px]" v-model="filterText" placeholder="输入关键字过滤" @input="funfilterChange" />
  8. <el-tree ref="treeRef" :style="{height: `calc(${props.height} - 46px)`, overflow: 'auto'}" icon="" :data="props.data" :show-checkbox="props.showCheckbox" default-expand-all node-key="id"
  9. highlight-current :props="defaultProps" :current-node-key="''" @check="funCheckChange"
  10. :expand-on-click-node="false" @node-click="funCurrentChange" :filter-node-method="funTreeFilter">
  11. <template #default="{ node, data }">
  12. <p v-if="node.level === 1" class="flex justify-between items-center text-[12px]"
  13. :class="[props.showCheckbox ? 'w-[84%]' : 'w-[90%]']">
  14. <span>{{ node.label }}</span>
  15. <el-icon class="!text-[rgb(64,158,255)]" title="刷新" @click.stop="emits('refresh')">
  16. <RefreshRight />
  17. </el-icon>
  18. </p>
  19. <el-dropdown ref="dropdown1" v-else size="small" trigger="contextmenu" @command="funCommand"
  20. style="margin-right: 30px">
  21. <span class="el-dropdown-link text-[12px] flex items-center">
  22. <el-icon class="mr-[4px] !text-[#E6A23C]">
  23. <Folder v-if="!node.expanded || (node.isLeaf && !node.isCurrent)" />
  24. <FolderOpened v-else />
  25. </el-icon>
  26. {{ node.label }}
  27. </span>
  28. <template #dropdown>
  29. <el-dropdown-menu>
  30. <el-dropdown-item class="text-[#409EFF]" v-if="data.childs && data.childs.length" :command="{ type: 'export', data, node }">导出
  31. </el-dropdown-item>
  32. <el-dropdown-item class="text-[#F56C6C]" :command="{ type: 'delete', data, node }">删除</el-dropdown-item>
  33. </el-dropdown-menu>
  34. </template>
  35. </el-dropdown>
  36. </template>
  37. </el-tree>
  38. <!--
  39. <div class="buttons">
  40. <el-button @click="getCheckedNodes">get by node</el-button>
  41. <el-button @click="getCheckedKeys">get by key</el-button>
  42. <el-button @click="setCheckedNodes">set by node</el-button>
  43. <el-button @click="setCheckedKeys">set by key</el-button>
  44. <el-button @click="resetChecked">reset</el-button>
  45. </div>
  46. -->
  47. </div>
  48. </template>
  49. <script lang="ts" setup name="search">
  50. import { ref } from "vue";
  51. import type Node from "element-plus/es/components/tree/src/model/node";
  52. import { ElMessage, ElMessageBox } from "element-plus";
  53. import config from "../api/config";
  54. import request from "../api/axios.js";
  55. const emits = defineEmits(["currentChange", "checkChange", "refresh"]);
  56. interface Tree {
  57. id: string;
  58. label: string;
  59. children?: Tree[];
  60. }
  61. const props = withDefaults(
  62. defineProps<{
  63. data: Tree[];
  64. height?: number | string;
  65. showCheckbox?: boolean;
  66. }>(),
  67. {
  68. data: () => [],
  69. height: 400,
  70. showCheckbox: false,
  71. }
  72. );
  73. const treeRef = ref();
  74. const filterText = ref("");
  75. /**输入框过滤 */
  76. const funfilterChange = () => {
  77. treeRef.value!.filter(filterText.value);
  78. };
  79. const funTreeFilter = (value: string, data: Tree) => {
  80. if (!value) return true;
  81. return data.label.includes(value);
  82. };
  83. /**选中节点变化 */
  84. const funCurrentChange = (current: Tree, currentNode: Node) => {
  85. emits("currentChange", { current, currentNode });
  86. };
  87. /**复选框选中变化 */
  88. const funCheckChange = (
  89. current: Tree,
  90. { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }
  91. ) => {
  92. emits("checkChange", {
  93. current,
  94. checkedNodes,
  95. checkedKeys,
  96. halfCheckedNodes,
  97. halfCheckedKeys,
  98. });
  99. };
  100. //右键时, command菜单
  101. const funCommand = async ({ type, data, node }) => {
  102. console.log(type, data, node);
  103. switch (type) {
  104. case "export":
  105. ElMessageBox.confirm("确认导出当前节点的所有数据?", "导出", {
  106. confirmButtonText: "确认",
  107. cancelButtonText: "取消",
  108. type: "warning",
  109. }).then(() => {
  110. const a = document.createElement("a");
  111. const childs = data.childs.map((o) => o.id);
  112. a.href =
  113. config.baseURL + "/data/option/download?ids=" + childs.join(",");
  114. a.download = "";
  115. a.click();
  116. });
  117. break;
  118. case "delete":
  119. ElMessageBox.confirm("确认删除当前节点的所有数据?", "删除", {
  120. confirmButtonText: "确认",
  121. cancelButtonText: "取消",
  122. type: "warning",
  123. }).then(async () => {
  124. let deleteArr = [];
  125. const repeatArr = (arr, deleteArr) => {
  126. for (const unit of arr) {
  127. if (unit.childs?.length) {
  128. deleteArr.push(...unit.childs.map((o) => o.id));
  129. } else if (unit.children?.length) {
  130. repeatArr(unit.children, deleteArr);
  131. }
  132. }
  133. };
  134. if (data.childs?.length) {
  135. deleteArr = data.childs.map((o) => o.id);
  136. } else if (data.children?.length) {
  137. repeatArr(data.children, deleteArr);
  138. }
  139. console.log(deleteArr);
  140. const res = await request.get("/data/option/delete", {
  141. params: { ids: deleteArr.join(",") },
  142. }); //删除当前节点
  143. if (res.code === 200) {
  144. ElMessage.success(res.msg);
  145. emits("refresh");
  146. }
  147. });
  148. break;
  149. }
  150. };
  151. const getCheckedNodes = () => {
  152. console.log(treeRef.value!.getCheckedNodes(false, false));
  153. };
  154. const getCheckedKeys = () => {
  155. console.log(treeRef.value!.getCheckedKeys(false));
  156. };
  157. const setCheckedNodes = () => {
  158. treeRef.value!.setCheckedNodes(
  159. [
  160. {
  161. id: 5,
  162. label: "Level two 2-1",
  163. },
  164. {
  165. id: 9,
  166. label: "Level three 1-1-1",
  167. },
  168. ],
  169. false
  170. );
  171. };
  172. const setCheckedKeys = () => {
  173. treeRef.value!.setCheckedKeys([3], false);
  174. };
  175. const resetChecked = () => {
  176. treeRef.value!.setCheckedKeys([], false);
  177. };
  178. const defaultProps = {
  179. children: "children",
  180. label: "label",
  181. };
  182. </script>