vue+elementui表格树
html
<template> <div class="app-container tree-container"> <el-table v-loading="loading" :data="listList" highlight-active row-key="id" :show-header="false" class="tree-dialog" default-expand-all width="100%" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" > <el-table-column :show-overflow-tooltip="true" width="140" label="父id" prop="nodeName" > <template slot-scope="scope"> <span @click.stop="editnode($event, scope.row)" :class="nodeId == scope.row.id ? 'active' : ''" :data-id="nodeId" :data-id1="scope.row.id" >{{ scope.row.nodeName }}</span > </template> </el-table-column> <el-table-column max-width="28" label="操作" class-name="flex-end"> <template slot-scope="scope"> <!-- 只有第一二级节点有新增 --> <el-button v-if="scope.row.num_node == 0 || scope.row.num_node == 1" size="mini" type="text" icon="el-icon-plus" @click.stop="handleAddNew(scope.row)" v-hasPermi="['db:list:add']" ></el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click.stop="handleDelete(scope.row)" style="color:#f00;" v-hasPermi="['db:list:remove']" ></el-button> </template> </el-table-column> </el-table> <!-- 新增或修改节点弹框 --> <!-- 设备配置弹框 --> <el-dialog :title="title" class="dialog-device-config" :visible.sync="isShowDialog" :close-on-click-modal="false" v-if="isShowDialog" width="500px" append-to-body > <!-- 第三级节点 --> <el-form v-if="addNum == 2" :model="addCheckForm" ref="addCheckForm" :rules="checkRules" class="device-add-form" > <el-form-item label="设备名称:" :label-width="formLabelWidth" prop="nodeName" > <el-input v-model="addCheckForm.nodeName" placeholder="设备名称" type="text" > </el-input> </el-form-item> <el-form-item :label-width="formLabelWidth" class="btn-info"> <el-button type="primary" class="btn" @click="addCheck" >保存</el-button > <el-button class="btn" @click="isShowDialog = false">取消</el-button> </el-form-item> </el-form> <el-form v-else-if="addNum == 1" :model="addDeviceTypeNodeForm" ref="addDeviceTypeNodeForm" :rules="typeRules" class="device-add-form" > <el-form-item label="设备类型:" :label-width="formLabelWidth" prop="nodeName" > <el-select filterable v-model="addDeviceTypeNodeForm.nodeName" placeholder="设备类型" @change="onSelectedTypeAdd" > <el-option v-for="option in checkTypes" :key="option.dictValue" :label="option.dictLabel" :value="option.dictValue" ></el-option> </el-select> </el-form-item> <el-form-item :label-width="formLabelWidth" class="btn-info"> <el-button type="primary" class="btn" @click="addDeviceTypeNode(true)" >保存</el-button > <el-button class="btn" @click="isShowDialog = false">取消</el-button> </el-form-item> </el-form> </el-dialog> </div> </template>
js
<script> import { listList, getList, delList, addList, updateList, exportList } from "@/api/zncy/p06/treeList"; import Treeselect from "@riophae/vue-treeselect"; import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import $ from "jquery"; // import { component as VueContextMenu } from "@xunlei/vue-context-menu"; export default { name: "List", components: { Treeselect // "context-menu": VueContextMenu }, // 接受父组件传递的值 props: { nodeId: { type: String, default: "" } }, data() { return { // 遮罩层 loading: true, // 显示搜索条件 showSearch: true, // 树状结构表格数据 listList: [], // 树状结构树选项 listOptions: [], // 是否显示节点名称弹框 isShowDialog: false, // 0是新增或修改顶级节点,1是设备类型节点,2是设备节点 addNum: "0", // 弹出层标题 title: "", // label宽度 formLabelWidth: "110px", // 0新增/编辑查验台 addCheckForm: { id: "", // 编辑id parentId: "", nodeName: "" }, checkRules: { nodeName: [ { required: true, message: "请输入设备名称", trigger: "blur" } ] }, // 1新增设备类型 addDeviceTypeNodeForm: { id: "", // 编辑id parentId: "", // 父节点Id typeId: "", // 设备类型Id nodeName: "" // 设备类型Name }, typeRules: { nodeName: [ { required: true, message: "请选择设备类型", trigger: "blur" } ] }, // 是否显示弹出层 open: false, // 查询参数 queryParams: { parentId: null, ancestors: null, nodeName: null, orderNum: null, status: null }, // 表单参数 form: {}, // 表单校验 rules: {}, // 右键 contextMenuTarget: document.body, //绑定的dom contextMenuVisible: false }; }, created() { // 设备类型 this.getDicts("zncy_device_type").then(response => { this.checkTypes = response.data; }); this.getList(); }, methods: { /** 查询树状结构列表 **/ getList() { let that = this; that.loading = true; listList(that.queryParams).then(response => { that.listList = that.handleTree(response.data, "id", "parentId"); if (that.listList.length > 0) { that.listList.forEach(item => { item["num_node"] = 0; if (item.children !== undefined && item.children.length > 0) { item.children.forEach(itemchild => { itemchild["num_node"] = 1; if ( itemchild.children !== undefined && itemchild.children.length > 0 ) { itemchild.children.forEach(iteminner => { iteminner["num_node"] = 2; iteminner["parentName"] = itemchild.nodeName; }); } }); } }); } that.loading = false; }); }, /** 新增顶级节点-查验台 **/ addFirstNode() { this.title = "新增查验台节点"; this.isShowDialog = true; this.num_node = 0; this.addCheckForm.parentId = "0"; this.addCheckForm.id = undefined; this.addCheckForm.nodeName = ""; }, /** 新增节点时,向父组件传值,新增节点不同,右侧表单不同 **/ handleAddNew(row) { // 初始化输入框为空 this.addCheckForm.nodeName = ""; if (row.num_node === 0) { this.title = "新增设备分类"; this.isShowDialog = true; this.addNum = 1; this.addDeviceTypeNodeForm.parentId = row.id; } else if (row.num_node === 1) { this.title = "新增设备"; this.isShowDialog = true; this.addNum = 2; this.addCheckForm.parentId = row.id; } }, /** 删除按钮操作 **/ handleDelete(row) { var mes = ["删除设备"]; this.$messageContent.messageBox("W000004", mes).then(() => { if (row.num_node === 0 || row.num_node === 1) { if (row.children !== undefined && row.children.length > 0) { // 不能删除提示弹框(先删除子设备,才能删除父设备) this.$messageContent.message("EC00021"); } else { this.delDeviceOrNode(row.id); this.getList(); // 向父组件传值 this.$emit("deviceList", row); } } else { this.delDeviceOrNode(row.id); this.getList(); // 向父组件传值 this.$emit("deviceList", row); } }); }, /** 删除设备或节点 **/ delDeviceOrNode(id) { delList(id).then(res => { if (res.code === 200) { // 成功提示弹框 this.$messageContent.message("S000003", "节点删除"); this.getList(); } }); }, /** 新增节点方法 **/ addNodeFun(form) { addList(form).then(res => { if (res.code === 200) { // 成功提示弹框 this.$messageContent.message("S000003", "新增设备节点成功"); this.getList(); this.isShowDialog = false; } }); }, /** 编辑节点方法 **/ editNodeFun(form) { updateList(form).then(res => { if (res.code === 200) { // 成功提示弹框 this.$messageContent.message("S000003", "编辑设备节点成功"); this.getList(); this.isShowDialog = false; } }); }, /** 0新增/编辑查验台,节点名 **/ addCheck() { const that = this; const form = that.addCheckForm; if (form.id != "" && form.id != undefined && form.id != null) { that.$refs.addCheckForm.validate(valid => { if (valid) { this.editNodeFun(form); } else { return false; } }); } else { delete form.id; that.$refs.addCheckForm.validate(valid => { if (valid) { this.addNodeFun(form); } else { return false; } }); } // 成功后清除表单 this.addCheckForm.nodeName = ""; this.addCheckForm.id = ""; }, /** 1新增/编辑设备类型 **/ addDeviceTypeNode() { const that = this; const form = that.addDeviceTypeNodeForm; delete form.typeId; if (form.id != "" && form.id != undefined && form.id != null) { // 编辑下拉不用验证 this.editNodeFun(form); } else { delete form.id; that.$refs.addDeviceTypeNodeForm.validate(valid => { if (valid) { this.addNodeFun(form); } else { return false; } }); } }, /** 编辑当前节点 **/ editnode($event, row) { const that = $event.currentTarget; if (row.num_node === 0) { this.$emit("editnode", row); } else if (row.num_node === 2) { this.addCheckForm.nodeName = row.nodeName; // 向父组件传值 this.$emit("editnode", row); $(".el-table span").removeClass("active"); that.className = "active"; } }, /** 新增/更新设备分类下拉 **/ onSelectedTypeAdd(val) { let obj = {}; obj = this.checkTypes.find(item => { return item.dictValue === val; }); this.addDeviceTypeNodeForm.typeId = val; // 设备分类id this.addDeviceTypeNodeForm.nodeName = obj.dictLabel; // 设备分类名称 this.$forceUpdate(); } } }; </script>
css:
<style lang="scss" scoped> .tree-container { border: 1px solid #eee; background: #fcfcfc; padding: 10px; height: 440px; width: 100%; overflow-y: auto; overflow-x: hidden; } .right-menu { border: 1px solid #eee; box-shadow: 0 0.5em 1em 0 rgba(0, 0, 0, 0.1); border-radius: 1px; display: block; font-family: Microsoft Yahei, Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; position: fixed; background: #fff; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 3px; z-index: 999; display: none; a { padding: 2px 15px; // width: 120px; height: 28px; line-height: 28px; text-align: center; display: block; color: #1a1a1a; } user agent stylesheet a:-webkit-any-link { color: -webkit-link; cursor: pointer; text-decoration: underline; } a:hover { // background: #42b983; background: #ccc; color: #fff; } } .active { color: #4181ff; } </style> <style lang="scss"> .tree-container { padding-top: 40px; .el-table { border: 0; th, tr, td { border: 0; background-color: #fcfcfc; } &::before { height: 0px; } &::after { width: 0; } .el-table__fixed:before { height: 0; } .el-table__row:hover > td { background-color: #fcfcfc !important; } .el-table__row--striped:hover > td { background-color: #fcfcfc !important; } } .el-table .cell { padding: 0; font-size: 16px; display: block; height: 32px; line-height: 32px; span { cursor: pointer; } } .el-table .flex-end { display: flex; justify-content: flex-end; } .el-table--enable-row-transition .el-table__body td { height: auto !important; } .el-table--medium th, .el-table--medium td { padding: 0; } } </style>