select 框添加树结构(todu)

目录

1. 案例:

 2. 代码

2.1 html部分

2.2 script部分

3. 父子页面完整代码(可不看)

 3.1 父组件

3.2 子组件


1. 案例:

 2. 代码

2.1 html部分
 <el-form
      ref="newFrom"
      :form="form"
      :model="newFrom"
      :rules="rules"
      label-width="100px"
      style="padding-left: 7px"
    >
<!-- ParentID: 父级的ID    ParentName:父节点名称    -->
      <el-form-item
        label="父级名称"
        prop="ParentID"
      >
        <el-select
          v-model="newFrom.ParentID"
          clearable
        >
          <!-- :label="item.Text" :value="item.ID"  input框显示的值-->
          <el-option
            :key="newFrom.ParentID"
            :value="newFrom.ParentID"
            :label="newFrom.ParentName"
            placeholder="请选择父节点"
            class="aa"
          >

 <!-- partendData:树结构数据    handleNodeClick:树结构点击事件-->

            <el-tree
              :data="partendData"
              node-key="ID"
              :props="defaultProps"
              @node-click="handleNodeClick"
            ></el-tree>
          </el-option>
        </el-select>
      </el-form-item>
      
    </el-form>
2.2 script部分
props: ["form", "formID", "partend"],  //父子传值,这是接收父节点传过来的值

//定义
data() {
    
    return {
      newFrom: {
        DataName: "", //名称
        ParentID: "", //父节点ID
        SortID: "", //排序
        Dsc: "", //备注
        DictID: "", //与左侧关联ID
        DataID: "", //字典编号
        ParentName: "", //父节点名称
      },
    
      //#region 父节点
      
      partendData: [], //1. 接收父组件传递过来的父节点的值
      defaultProps: {  //2. 下拉框的值
        children: "Children",
        label: "Text",
        id: "ID",
      },
      //#endregion
    };
  },

//监听
watch: {
//监听partend的变化(partend 这个值就是下拉框数据,我这边是父组件查询号,然后传过来的)
    partend: {
      deep: true, //深度监听
      immediate: true, //初始化时监听
      handler(n, o) {
        this.partendData = n;  //把最新的值赋给partendData (定义的树结构字典)
        console.log("监听父节点数据的变化", n); 
      },
    },
  },

//方法
methods:{
  //点击方法(下拉框点击之后,吧选中的值赋给ParentID ,ParentName )
    handleNodeClick(val) {
      console.log(val, "zzzz");
      this.newFrom.ParentID = val.ID;
      this.newFrom.ParentName = val.Text;
      this.treeID = val.ID;
    },
}
3. 父子页面完整代码(可不看)
 3.1 父组件
<template>
  <div
    class="dictionaryIndex"
    style="width: 100%; height: 96%"
  >
    <div class="mainStyle">
      <el-row
        :gutter="6"
        style="width: 100%; height: 100%"
      >
        <el-col
          :span="3"
          style="padding-top: 3%;"
        >
          <div
            class="grid-content bg-purple"
            style="background-color: #fff"
          >
            <p class="jbTypeStyle">字典类型</p>
            <!-- defaultProps :这个里面的字段要与后端返回过来的字段一致 -->
            <!-- <el-tree>
              vue2 简单插槽写法
              <span
                class="custom-tree-node"
                slot-scope="{ node }"
              >
                <span> <i class="custom_icon"></i>{
   
   { node.Text }} </span>
              </span>
            </el-tree> -->
            <el-tree
              :data="treeData"
              :props="defaultProps"
              @node-click="handleNodeClick"
              node-key="ID"
              default-expand-all
              highlight-current
              :key="itemKey"
            >
              <!-- vue3 插槽写法 -->
              <template #default="{ node, data }">
                <span class="custom-tree-node">
                  <span>
                    <i class="custom_icon"></i>
                    {
   
   { node.label }}
                  </span>
                </span></template>
            </el-tree>

          </div>
          <el-divider direction="vertical"></el-divider>
        </el-col>
        <el-col :span="21">
          <div class="dic_btnStyle">

            <ButtonView
              ref="ButtonRef"
              @ButtonMessage="GetBtnClick"
            />
          </div>
          <div>
            <cummonTable
              ref="cummonTable"
              :columns="columns"
              :pagination="pagination"
              @rowClick="GetrowClick"
            />
          </div>
        </el-col>
      </el-row>
    </div>

    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="33%"
      center
      draggable
      destroy-on-close
      append-to-body
      class="dialogStyle"
      :before-close="handleClose"
    >
      <dictionaryForm
        ref="fromViewRef"
        :form="formData"
        :formID="formID"
        :partend="partend"
        @formClose="GetcloseData"
        @fathernewFrom="GetCondition"
      />
    </el-dialog>
  </div>
</template>

<script>
import dictionaryForm from "./dictionaryForm.vue";

// import { Message, Notification } from "element-ui";
// import { fakeApi } from "@/api/luApi.js";
// import { PublicFunction } from "@/utils/vuePublic";
import cummonTable from "@/components/zaojia/tableCommon/cummonTable.vue";
// import conButton from "@/layout/components/conButton.vue";

export default {
  inject: ["reload"],

  components: {
    dictionaryForm,
    cummonTable,
  },
  data() {
    return {
      dialogVisible: false, //用于控制form表单显隐
      dialogTitle: "", //用于控制新增、编辑标题
      formData: {}, //定义对象,用于给子组件传值
      // selectDictIDName: "", //用于给子组件传 类型 值
      treeData: [], //定义左侧树初始化
      itemKey: "", //ces
      selectedDictIDs: "", //左边树勾选的ID
      selectLabel: "工程项目", //左侧字典项名称,默认是第一个
      defaultProps: {
        children: "Children", //要与后端返回过来的字段一致
        label: "Text", //要与后端返回过来的字段一致
      },
      //#region 传给子table
      columns: {
        isSelect: false,
        showFenYe: false,
        isSelection: false,
        isTag: false,
        defaultall: true, //默认展开
        highlightCurrent: true, //高亮选中
      },
      pagination: {
        total: null,
      },
      multipleSelection: {}, //表格勾选的值
      tableData: [],
      //#endregion

      loading: false, //加载
      formID: 0, //默认是0,说明是新增

      //#region 父节点相关
      partend: null, //传给子组件父节点的值
      //#endregion
      btnData: null, //调按钮接口传的参数
    };
  },
  created() {
    const param = {
      MenuID:
        localStorage.getItem("MenuIds") == "undefined"
          ? 0
          : localStorage.getItem("MenuIds"),
      RoleID:
        localStorage.getItem("RoleID") == "undefined"
          ? 0
          : localStorage.getItem("RoleID"),
    };
    //lu 用于查询该菜单所拥有的按钮
    this.$GetButtonByRoleAndMenus(param, this);
    this.btnData = param;
  },
  mounted() {
    this.SetTreeDatas(); //初始化左侧数据
    this.GetColDataList(); //初始化表头
  },
  methods: {
    //获取点击左侧树的数据
    handleNodeClick(data) {
      this.selectedDictIDs = data.Value; //ID 左侧树的唯一值
      this.selectLabel = data.Text;
      console.log("点击树的时候===", data);
      let param = { DictID: this.selectedDictIDs };
      this.getTabledata(param); //初始化表格数据
    },
    // 初始化按钮
    GetBtnClick(value) {
      let _this = this;
      if (value == "新增") {
        if (this.selectedDictIDs == "") {
          this.$message({
            showClose: true,
            message: "请选择字典类型",
            type: "warning",
          });
        } else {
          this.partend = this.tableData;
          console.log(
            this.multipleSelection,
            "选中的数据11111111111111",
            this.partend
          );
          if (this.multipleSelection != undefined) {
            this.dialogTitle = value;
            this.formData = {
              DataName: "", //名称
              ParentID: this.multipleSelection.ID, //父节点ID
              SortID: "", //排序
              Dsc: "", //备注
              ID: 0,
              DataID: "", //字典编号
              DictID: this.selectedDictIDs, //与左侧关联ID
              ParentName: this.multipleSelection.Text,
            };
            this.dialogVisible = true;
          } else {
            this.dialogTitle = value;
            this.formData = {
              DataName: "", //名称
              ParentID: 0, //父节点ID
              SortID: "", //排序
              Dsc: "", //备注
              ID: 0,
              DataID: "",
              DictID: this.selectedDictIDs, //与左侧关联ID
            };
            this.dialogVisible = true;
          }
        }
      } else if (value == "编辑") {
        this.dialogTitle = value;
        this.formData = this.multipleSelection;
        this.dialogVisible = true;
      } else if (value == "删除") {
        this.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        })
          .then(() => {
            //调用方法
            this.DeleteFormDatas(this.multipleSelection);
          })
          .catch(() => {
            this.$message({
              type: "info",
              message: "已取消删除",
            });
          });
      } else if (value == "新增子级") {
        this.dialogTitle = value;
        this.formData = {
          DataName: "", //名称
          ParentID: this.multipleSelection.ID, //父节点ID
          SortID: "", //排序
          Dsc: "", //备注
          DictID: this.selectedDictIDs, //与左侧关联ID
        };
        this.dialogVisible = true;
      }
    },
    // 选中行数据
    GetrowClick(row) {
      // console.log("行选中数据", val);
      if (row != undefined) {
        if (this.multipleSelection == row) {
          console.log("再次点击同一行,取消当前行选中", this.multipleSelection);
          // 取消当前行选中,清空保存的当前行数据
          this.$refs.cummonTable.setCurrent();
          this.multipleSelection = null;
        } else {
          this.multipleSelection = row;
          console.log(
            "点击新行,选中并高亮该行,获取当前行数据",
            this.multipleSelection
          );
        }
      }
    },

    //获取表单组件传递的信息,此处接收的表单乃是数据表格对应的表单
    GetCondition(datas) {
      console.log("获取form表单传过来的数据=====:", datas);
      const param = datas;
      //获取表单组件后,判断是新增/修改
      if (this.dialogTitle.search("新增") != -1) {
        //调用新增方法
        this.InsertFormDatas(param);
      }
      if (this.dialogTitle.search("编辑") != -1) {
        this.InsertFormDatas(param);
      }
    },

    //#region  新增、编辑、删除
    InsertFormDatas(data) {
      console.log("新增====", data);
      //转换数据
      // data.dataId = parseInt(data.dataId);
      this.InsertOrUpdateBySysDictData(data);
    },
    // UpdateFormDatas(data) {
    //   // console.log("编辑====", data);
    //   this.updateApi(data);
    //   this.dialogVisible = false;
    // },
    DeleteFormDatas(data) {
      let _this = this;
      let param = { IDs: data.ID };
      console.log("删除==", param);
      _this.$API.SysDictDataDelete(param).then((res) => {
        console.log(res, "调删除接口");
        this.$message({
          message: "删除成功!",
          type: "success",
        });
        let param = { DictID: this.selectedDictIDs };
        this.getTabledata(param);
      });
    },

    //#region 接口部分
    /**
     * 初始化表格数据
     * //根据左侧树形列表查询对应的内容
     */
    getTabledata(param) {
      let _this = this;
      _this.tableData = [];
      console.log("传给后端的数dicID", param);
      _this.$API.SysDictDataGetdata(param).then((res) => {
        let tempTable = res.data.data;
        console.log(_this.tableData, "表格==", res.data.data);
        if (tempTable != null) {
          tempTable.forEach((item) => {
            item.ID = item.Model.ID;
            item.ParentId = item.ParentId;
            item.DataID = item.Model.DataID;
            item.DataName = item.Model.DataName;
            item.SortID = item.Model.SortID;
            item.Dsc = item.Model.Dsc;
            item.DictID = item.Model.DictID;

            //使用递归  todo
            if (item.Children.length != 0) {
              item.Children.forEach((item) => {
                item.ID = item.Model.ID;
                item.ParentId = item.ParentId;
                item.DataID = item.Model.DataID;
                item.DataName = item.Model.DataName;
                item.SortID = item.Model.SortID;
                item.Dsc = item.Model.Dsc;
                item.DictID = item.Model.DictID;

                if (item.Children.length != 0) {
                  item.Children.forEach((item) => {
                    item.ID = item.Model.ID;
                    item.ParentId = item.ParentId;
                    item.DataID = item.Model.DataID;
                    item.DataName = item.Model.DataName;
                    item.SortID = item.Model.SortID;
                    item.Dsc = item.Model.Dsc;
                    item.DictID = item.Model.DictID;
                  });
                }
              });
            }
          });
          _this.tableData = tempTable;
        } else {
          _this.tableData = [];
        }
        if (res.data.code != 200) {
          this.$message({
            message: "没有数据,请新增数据",
            type: "warning",
            showClose: true,
          });
        }
        console.log("表格数据", _this.tableData);
        // console.log("监听父节点数据的变化1", _this.partend);
        _this.$refs.cummonTable.SettableData(_this.tableData);
      });
    },

    //新增同级或子级接口
    async InsertOrUpdateBySysDictData(data) {
      let _this = this;
      // console.log("新增成功", param);
      let param = data.Form; //表单的值
      _this.$API.SysDictDataAddandUpdate(param).then((res) => {
        console.log("成功调接口", res);
        if (res.data.msg == "字段已存在!") {
          this.$message.error("新增或删除失败,该字典名称已存在!");
        } else {
          if (this.dialogTitle.search("新增") != -1) {
            this.$message({
              message: "新增成功!",
              type: "success",
            });
            if (data.dialogVisible == true) {
              this.dialogVisible = true;
              this.formID = res.data.data.ID;
            } else {
              this.dialogVisible = false;
            }
          } else {
            this.$message({
              message: "修改成功",
              type: "success",
            });
            if (data.dialogVisible == true) {
              this.dialogVisible = true;
              this.formID = res.data.data.ID;
            } else {
              this.dialogVisible = false;
            }
          }
          let param = { DictID: this.selectedDictIDs };
          _this.getTabledata(param);
          this.$refs.cummonTable.setCurrent(); //取消选中数据
          this.multipleSelection = null; //选中的值为空
        }
      });
    },
    //#endregion

    //#endregion

    /**
     * 初始化左侧树
     * @param {*} GetDataLists
     */
    SetTreeDatas() {
      let _this = this;
      //重新渲染,itemKey用于处理Table不渲染的问题
      _this.itemKey = Math.random();
      //#region 假
      // let res = await fakeApi.dictTable();
      // GetDataLists = res.data;
      // this.treeData = GetDataLists;
      //#endregion
      _this.$API.SysDictDataGetLeftdata().then((res) => {
        _this.loading = false;
        _this.treeData = res.data.data;
        // console.log("左侧树==", res.data.data);
      });
    },

    /**
     * @GetColDataList: 初始化表头
     */
    GetColDataList() {
      let _this = this;
      let param = this.btnData;
      _this.$API.GetFieldAuthorization(param).then((res) => {
        console.log(res, "调表头接口111");
        let resData = res.data.data;
        let tempdata = [];
        resData.forEach((item) => {
          tempdata.push({ label: item.FieldDsc, prop: item.FieldName });
        });
        console.log("表头字段11==", tempdata);
        _this.$refs.cummonTable.SetDataTableHeader(tempdata);
        this.$message({
          message: "成功!",
          type: "success",
        });
      });
    },

    //关闭模态框
    handleClose(done) {
      let _this = this;
      this.$confirm("尚未保存的内容会丢失,是否确定关闭?", "提示")
        .then((_) => {
          done();
          this.dialogVisible = false;
          let param = { DictID: this.selectedDictIDs };
          _this.getTabledata(param);
          this.$refs.cummonTable.setCurrent(); //取消选中数据
        })
        .catch((_) => {});
    },

    /**
     * 点击取消 关闭form表单
     */
    GetcloseData(val) {
      this.dialogVisible = val;
      let param = { DictID: this.selectedDictIDs };
      this.getTabledata(param);
      this.$refs.cummonTable.setCurrent(); //取消选中数据
      this.multipleSelection = null; //选中的值为空
    },

    /**传递表头
     * @MenuId:该菜单项id,
     * @FieldName:列头名称
     * @FieldDsc:列头中文名称
     */
    setHead() {
      //获取菜单id进行传参
      let MenuIDs = localStorage.getItem("MenuID");
      console.log(MenuIDs, "获取数据字典的菜单id");
      let param = {
        MenuId: MenuIDs,
        FieldName: "DataName,SortID,Dsc,DataID",
        FieldDsc: "字典名称,排序,备注,字典编号",
      };
      this.$API.RoleSetMenuField(param).then((res) => {
        console.log(res, "传递表头");
      });
    },
  },
};
</script>

<style scoped>
.jbTypeStyle {
  /* background: linear-gradient(#00b7f9, #018ff2, #0165eb); */
  background: linear-gradient(147deg, #70c0ff, #2f9fff);
  color: #fff;
  /* border-radius: 5px; */
  height: 46px;
  width: 103%;
  /* padding: 3% 4%; */
  padding: 7% 26%;
  margin-bottom: 0%;
}

/**表格表头背景色 */
.dictionaryIndex ::v-deep .el-table th,
::v-deep .el-table thead.is-group th.el-table__cell {
  background: linear-gradient(147deg, #70c0ff, #2f9fff);
  color: #fff;
  padding: 0;
  margin: 0;
}

.mainStyle {
  height: 100%;
  /* padding: 0 2%; */
}

.dictionaryIndex ::v-deep .el-tree-node {
  /* height: 40px; */
  padding: 2%;
}

/**选中节点,背景色 */
.dictionaryIndex
  ::v-deep
  .el-tree--highlight-current
  .el-tree-node.is-current
  > .el-tree-node__content {
  background-color: #ecf1ff;
  color: #4977fc;
  border-radius: 5px;
}

/**添加form 表单背景色 */
/* .dialogStyle >>> .el-dialog {
  background: url("../../../assets/imgList/userFormBG.jpg") no-repeat;
  background-position: center;
  background-size: 100% 100%;
} */
.custom_icon {
  background-image: url("../../../../assets/imgList/planIcon.png");
  background-size: cover;
  background-position: center;
  display: inline-block;
  width: 17px;
  height: 17px;
  vertical-align: middle;
}

.dic_btnStyle {
  padding: 0 0 1% 1%;
  float: right;
}
</style>


3.2 子组件
<template>
  <div class="DictForm">
    <!-- @change="newFrom" -->
    <el-form
      ref="newFrom"
      :form="form"
      :model="newFrom"
      :rules="rules"
      label-width="100px"
      style="padding-left: 7px"
    >
      <el-form-item
        label="父级名称"
        prop="ParentID"
      >
        <el-select
          v-model="newFrom.ParentID"
          clearable
        >
          <!--            :label="item.Text" :value="item.ID"  input框显示的值-->
          <el-option
            :key="newFrom.ParentID"
            :value="newFrom.ParentID"
            :label="newFrom.ParentName"
            placeholder="请选择父节点"
            class="aa"
          >
            <el-tree
              :data="partendData"
              node-key="ID"
              :props="defaultProps"
              @node-click="handleNodeClick"
            ></el-tree>
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item
        label="字典名称"
        prop="DataName"
      >
        <el-input v-model="newFrom.DataName"></el-input>
      </el-form-item>

      <el-form-item
        label="排序"
        prop="SortID"
      >
        <el-input v-model="newFrom.SortID"></el-input>
      </el-form-item>
      <el-form-item label="备注">
        <el-input
          v-model="newFrom.Dsc"
          type="textarea"
          resize="none"
        ></el-input>
      </el-form-item>

      <el-form-item style="width: 91%;">
        <el-button
          type="primary"
          class="formBtn submit"
          @click="onSubmit('newFrom')"
        >保存</el-button>
        <el-button
          @click="onclose()"
          class="formBtn closeSub"
          style="right: -11%;"
        >保存并关闭</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
// import formBtnStyle from "@/assets/css/formBtnStyle.css";

export default {
  props: ["form", "formID", "partend"],
  // components: { formBtnStyle },

  data() {
    let checkPriceSell = (rule, value, callback) => {
      if (value) {
        if (!/^\d+(\.\d{1,2})?$/.test(value)) {
          callback(new Error("请输入数字!"));
        } else {
          callback();
        }
      }
    };
    return {
      newFrom: {
        DataName: "", //名称
        ParentID: "", //父节点ID
        SortID: "", //排序
        Dsc: "", //备注
        DictID: "", //与左侧关联ID
        DataID: "", //字典编号
        ParentName: "", //父节点名称
      },
      rules: {
        //验证
        DataName: [
          {
            required: true,
            message: "请输入字典名称",
            trigger: "blur",
          },
        ],
        SortID: [
          {
            validator: checkPriceSell,
            required: true,
            trigger: ["blur", "change"],
          },
        ],
      },
      //#region 父节点
      //1. 接收父组件传递过来的父节点的值
      partendData: [],
      defaultProps: {
        children: "Children",
        label: "Text",
        id: "ID",
      },
      //#endregion
    };
  },
  created() {
    if (JSON.stringify(this.form) == "{}") {
      this.newFrom = {};
    } else {
      this.newFrom = this.form;
    }
  },
  watch: {
    form(newVal, oldVal) {
      if (newVal && newVal.length == 0) {
        this.newFrom = {};
      } else {
        this.newFrom = newVal;
      }
    },
    formID(n, o) {
      console.log("监听ID的变化", n);
      this.newFrom.ID = n;
    },
    partend: {
      deep: true,
      immediate: true,
      handler(n, o) {
        this.partendData = n;
        console.log("监听父节点数据的变化", n);
      },
    },
  },
  mounted() {
    console.log("接受父组件的值==form=====", this.form);
  },

  methods: {
    //保存
    onSubmit(newFrom) {
      this.$refs[newFrom].validate((valid) => {
        if (valid) {
          // 如果有值就传给父组件
          console.log("保存this.newFrom===", this.newFrom);
          let paramForm = {
            Form: this.newFrom,
            dialogVisible: true,
          };
          this.$emit("fathernewFrom", paramForm); //把this.newFrom指传给父组件
        } else {
          return false;
        }
      });
    },
    onclose() {
      let paramForm = {
        Form: this.newFrom,
        dialogVisible: false,
      };
      console.log("保存并关闭==", this.Form);
      this.$emit("fathernewFrom", paramForm);
    },
    // 点击数
    handleNodeClick(val) {
      console.log(val, "zzzz");
      this.newFrom.ParentID = val.ID;
      this.newFrom.ParentName = val.Text;
      this.treeID = val.ID;
    },
  },
};
</script>
<style scoped>
@import "@/assets/css/formBtnStyle.css";

.aa {
  height: 10rem;
  overflow-y: scroll;
}
.DictForm ::v-deep .el-select {
  width: 100%;
}
</style>

猜你喜欢

转载自blog.csdn.net/CMDN123456/article/details/131540724