123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- <template>
- <div class="shadow rounded-[6px] shadow-blue-500" :style="{
- height:
- typeof props.height === 'string' ? props.height : props.height + 'px',
- overflowY: 'hidden'
- }">
- <el-input class="pb-[10px]" v-model="filterText" placeholder="输入关键字过滤" @input="funfilterChange" />
- <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"
- highlight-current :props="defaultProps" :current-node-key="''" @check="funCheckChange"
- :expand-on-click-node="false" @node-click="funCurrentChange" :filter-node-method="funTreeFilter">
- <template #default="{ node, data }">
- <p v-if="node.level === 1" class="flex justify-between items-center text-[12px]"
- :class="[props.showCheckbox ? 'w-[84%]' : 'w-[90%]']">
- <span>{{ node.label }}</span>
- <el-icon class="!text-[rgb(64,158,255)]" size="14" title="刷新" @click.stop="emits('refresh')">
- <RefreshRight />
- </el-icon>
- </p>
- <el-dropdown ref="dropdown1" v-else size="small" trigger="contextmenu" @command="funCommand"
- style="margin-right: 30px">
- <span class="el-dropdown-link text-[12px] flex items-center">
- <el-icon class="mr-[4px] !text-[#E6A23C]">
- <Folder v-if="!node.expanded || (node.isLeaf && !node.isCurrent)" />
- <FolderOpened v-else />
- </el-icon>
- {{ node.label }}
- </span>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item class="text-[#409EFF]" v-if="data.childs && data.childs.length" :command="{ type: 'export', data, node }">导出
- </el-dropdown-item>
- <el-dropdown-item class="text-[#F56C6C]" :command="{ type: 'delete', data, node }">删除</el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- </template>
- </el-tree>
- <!--
- <div class="buttons">
- <el-button @click="getCheckedNodes">get by node</el-button>
- <el-button @click="getCheckedKeys">get by key</el-button>
- <el-button @click="setCheckedNodes">set by node</el-button>
- <el-button @click="setCheckedKeys">set by key</el-button>
- <el-button @click="resetChecked">reset</el-button>
- </div>
- -->
- </div>
- </template>
- <script lang="ts" setup name="search">
- import { ref } from "vue";
- import type Node from "element-plus/es/components/tree/src/model/node";
- import { ElMessage, ElMessageBox } from "element-plus";
- import config from "../api/config";
- import request from "../api/axios.js";
- const emits = defineEmits(["currentChange", "checkChange", "refresh"]);
- interface Tree {
- id: string;
- label: string;
- children?: Tree[];
- }
- const props = withDefaults(
- defineProps<{
- data: Tree[];
- height?: number | string;
- showCheckbox?: boolean;
- }>(),
- {
- data: () => [],
- height: 400,
- showCheckbox: false,
- }
- );
- const treeRef = ref();
- const filterText = ref("");
- /**输入框过滤 */
- const funfilterChange = () => {
- treeRef.value!.filter(filterText.value);
- };
- const funTreeFilter = (value: string, data: Tree) => {
- if (!value) return true;
- return data.label.includes(value);
- };
- /**选中节点变化 */
- const funCurrentChange = (current: Tree, currentNode: Node) => {
- emits("currentChange", { current, currentNode });
- };
- /**复选框选中变化 */
- const funCheckChange = (
- current: Tree,
- { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }
- ) => {
- emits("checkChange", {
- current,
- checkedNodes,
- checkedKeys,
- halfCheckedNodes,
- halfCheckedKeys,
- });
- };
- //右键时, command菜单
- const funCommand = async ({ type, data, node }) => {
- switch (type) {
- case "export":
- ElMessageBox.confirm("确认导出当前节点的所有数据?", "导出", {
- confirmButtonText: "确认",
- cancelButtonText: "取消",
- type: "warning",
- }).then(() => {
- const a = document.createElement("a");
- const childs = data.childs.map((o) => o.id);
- a.href =
- config.baseURL + "/data/option/download?ids=" + childs.join(",");
- a.download = "";
- a.click();
- });
- break;
- case "delete":
- ElMessageBox.confirm("确认删除当前节点的所有数据?", "删除", {
- confirmButtonText: "确认",
- cancelButtonText: "取消",
- type: "warning",
- }).then(async () => {
- let deleteArr = [];
- const repeatArr = (arr, deleteArr) => {
- for (const unit of arr) {
- if (unit.childs?.length) {
- deleteArr.push(...unit.childs.map((o) => o.id));
- } else if (unit.children?.length) {
- repeatArr(unit.children, deleteArr);
- }
- }
- };
- if (data.childs?.length) {
- deleteArr = data.childs.map((o) => o.id);
- } else if (data.children?.length) {
- repeatArr(data.children, deleteArr);
- }
- const res = await request.get("/data/option/delete", {
- params: { ids: deleteArr.join(",") },
- }); //删除当前节点
- if (res.code === 200) {
- ElMessage.success(res.msg);
- emits("refresh");
- }
- });
- break;
- }
- };
- const getCheckedNodes = () => {
- console.log(treeRef.value!.getCheckedNodes(false, false));
- };
- const getCheckedKeys = () => {
- console.log(treeRef.value!.getCheckedKeys(false));
- };
- const setCheckedNodes = () => {
- treeRef.value!.setCheckedNodes(
- [
- {
- id: 5,
- label: "Level two 2-1",
- },
- {
- id: 9,
- label: "Level three 1-1-1",
- },
- ],
- false
- );
- };
- const setCheckedKeys = () => {
- treeRef.value!.setCheckedKeys([3], false);
- };
- const resetChecked = () => {
- treeRef.value!.setCheckedKeys([], false);
- };
- const defaultProps = {
- children: "children",
- label: "label",
- };
- </script>
|