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>