tree.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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)]" size="14" 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. switch (type) {
  103. case "export":
  104. ElMessageBox.confirm("确认导出当前节点的所有数据?", "导出", {
  105. confirmButtonText: "确认",
  106. cancelButtonText: "取消",
  107. type: "warning",
  108. }).then(() => {
  109. const a = document.createElement("a");
  110. const childs = data.childs.map((o) => o.id);
  111. a.href =
  112. config.baseURL + "/data/option/download?ids=" + childs.join(",");
  113. a.download = "";
  114. a.click();
  115. });
  116. break;
  117. case "delete":
  118. ElMessageBox.confirm("确认删除当前节点的所有数据?", "删除", {
  119. confirmButtonText: "确认",
  120. cancelButtonText: "取消",
  121. type: "warning",
  122. }).then(async () => {
  123. let deleteArr = [];
  124. const repeatArr = (arr, deleteArr) => {
  125. for (const unit of arr) {
  126. if (unit.childs?.length) {
  127. deleteArr.push(...unit.childs.map((o) => o.id));
  128. } else if (unit.children?.length) {
  129. repeatArr(unit.children, deleteArr);
  130. }
  131. }
  132. };
  133. if (data.childs?.length) {
  134. deleteArr = data.childs.map((o) => o.id);
  135. } else if (data.children?.length) {
  136. repeatArr(data.children, deleteArr);
  137. }
  138. const res = await request.get("/data/option/delete", {
  139. params: { ids: deleteArr.join(",") },
  140. }); //删除当前节点
  141. if (res.code === 200) {
  142. ElMessage.success(res.msg);
  143. emits("refresh");
  144. }
  145. });
  146. break;
  147. }
  148. };
  149. const getCheckedNodes = () => {
  150. console.log(treeRef.value!.getCheckedNodes(false, false));
  151. };
  152. const getCheckedKeys = () => {
  153. console.log(treeRef.value!.getCheckedKeys(false));
  154. };
  155. const setCheckedNodes = () => {
  156. treeRef.value!.setCheckedNodes(
  157. [
  158. {
  159. id: 5,
  160. label: "Level two 2-1",
  161. },
  162. {
  163. id: 9,
  164. label: "Level three 1-1-1",
  165. },
  166. ],
  167. false
  168. );
  169. };
  170. const setCheckedKeys = () => {
  171. treeRef.value!.setCheckedKeys([3], false);
  172. };
  173. const resetChecked = () => {
  174. treeRef.value!.setCheckedKeys([], false);
  175. };
  176. const defaultProps = {
  177. children: "children",
  178. label: "label",
  179. };
  180. </script>