dialog.vue 10.2 KB
<template>
  <el-dialog
    class="entryDialog classCUploadDialog"
    :title="title"
    :visible.sync="outerVisible"
    :show-close="false"
    width="25%"
    :close-on-click-modal="false"
    :destroy-on-close="true"
    v-loading="loadings.dialogLoading"
    @close="close(false)"
  >
    <div class="modelItem">
      <el-form
        v-if="type != 'menuChange'"
        class="fedexFormStyle"
        ref="formData"
        :model="formData"
        :rules="rules"
        label-position="top"
        size="small"
      >
        <Formitem label="角色名称" prop="roleName" type="edit">
          <el-input
            type="text"
            class="inputShadow"
            id="inputInner-edit-roleName"
            resize="none"
            v-model="formData.roleName"
            clearable
            placeholder=""
          ></el-input>
        </Formitem>
      </el-form>
      <el-tree
        ref="tree"
        class="menuTree"
        v-else
        :data="treeData"
        show-checkbox
        default-expand-all
        node-key="menuId"
        :default-expanded-keys="expandedKeys"
        :default-checked-keys="checkedKeys"
        :props="defaultProps"
        @check="treeCheckChange"
      >
      </el-tree>
    </div>
    <div class="dialogOption entrySave">
      <el-button
        class="entrySaveButton"
        :disabled="loadings.submitLoading"
        @click="submit"
        >确 定</el-button
      >
      <el-button
        class="entrySaveButton"
        :disabled="loadings.uploadLoading"
        @click="close(false)"
        >关 闭</el-button
      >
    </div>
  </el-dialog>
</template>

<script>
import {
  addRoleData,
  updateRoleData,
  updateRoleMenuData,
  getMenuByRoleId,
} from "@/api/system/user.js";
import { getRouters } from "@/api/menu";
export default {
  props: {
    outerVisible: {
      type: Boolean,
      default: false,
    },
    title: {
      type: String,
      default: "新增角色",
    },
    type: {
      type: String,
      default: "",
    },
    active: {
      type: Object,
      default: null,
    },
  },
  watch: {
    outerVisible(val) {
      if (val) {
        this.loadings.dialogLoading = false;
        if (this.type == "update") {
          this.formData = this.active;
        } else if (this.type == "menuChange") {
          this.formData = this.active;
          this.searchTreeData();
          this.loadCheckedKeys(); //加载已绑定的菜单
        }
      }
    },
  },
  data() {
    return {
      formData: {
        roleName: "",
      },
      treeData: [],
      treeCheckData: [],
      expandedKeys: [],
      checkedKeys: [],
      rules: {
        roleName: [
          {
            required: true,
            trigger: "blur",
            message: "角色名称不能为空!",
          },
        ],
      },
      defaultProps: {
        children: "children",
        label: "menuName",
      },
      searchForm: {},
      loadings: {
        dialogLoading: false,
        uploadLoading: false,
        submitLoading: false,
      },
      loadingText: "",
    };
  },
  methods: {
    buildMenuTree(menuList) {
      const menuMap = new Map();
      const tree = [];
      menuList.forEach((menu) => {
        menuMap.set(menu.menuId, { ...menu, children: [] });
      });

      // 构建树形结构
      menuList.forEach((menu) => {
        const menuItem = menuMap.get(menu.menuId);
        if (menu.parentMenuId === 0) {
          tree.push(menuItem);
        } else {
          const parent = menuMap.get(menu.parentMenuId);
          if (parent) {
            parent.children.push(menuItem);
          }
        }
      });

      return tree;
    },
    //查询菜单数据
    searchTreeData() {
      this.loadings.dialogLoading = true;
      getRouters()
        .then((res) => {
          if (res.code === "200") {
            console.log(this.buildMenuTree(res.data));
            // console.log(res.data);
            // let arr = [];

            // res.data.forEach((item) => {
            //   let status = true;
            //   if (item.parentMenuId == 0) {
            //     let obj = {
            //       id: item.menuId,
            //       label: item.menuName,
            //       children: [],
            //     };
            //     arr.forEach((menuItem) => {
            //       if (menuItem.id == item.menuId) {
            //         status = false;
            //         menuItem.label = item.menuName;
            //       }
            //     });
            //     if (status) {
            //       arr.push(obj);
            //     }
            //   } else {
            //     let obj = {
            //       id: item.menuId,
            //       label: item.menuName,
            //     };
            //     arr.forEach((menuItem) => {
            //       if (menuItem.id == item.parentMenuId) {
            //         status = false;
            //         menuItem.children.push(obj);
            //       }
            //     });
            //     if (status) {
            //       arr.push({
            //         id: item.parentMenuId,
            //         label: "",
            //         children: [obj],
            //       });
            //     }
            //   }
            // });
            this.treeData = this.buildMenuTree(res.data);
          } else {
            this.alertWarningMsg(res.message);
          }
          this.loadings.dialogLoading = false;
        })
        .catch((err) => {
          console.log(err);
          this.loadings.dialogLoading = false;
        });
    },
    //数据保存
    submit() {
      this.loadings.dialogLoading = true;
      let obj = {};
      if (this.type == "add") {
        this.$refs.formData.validate((valid) => {
          if (valid) {
            obj.roleName = this.formData.roleName;
            this.addapi(obj);
          } else {
            this.loadings.dialogLoading = false;
          }
        });
      } else if (this.type == "update") {
        this.$refs.formData.validate((valid) => {
          if (valid) {
            obj.roleId = this.formData.roleId;
            obj.roleName = this.formData.roleName;
            this.updateapi(obj);
          } else {
            this.loadings.dialogLoading = false;
          }
        });
      } else if (this.type == "menuChange") {
        obj.menuId = this.treeCheckData; // 使用合并后的选中节点
        obj.roleId = this.formData.roleId;
        this.menuChangeapi(obj);
      }
    },
    //新增
    addapi(val) {
      addRoleData(val)
        .then((res) => {
          if (res.code === "200") {
            this.msgSuccess(res.message);
            this.close(true);
          } else {
            this.alertWarningMsg(res.message);
            this.loadings.dialogLoading = false;
          }
        })
        .catch((err) => {
          console.log(err);
          this.loadings.dialogLoading = false;
        });
    },
    //修改
    updateapi(val) {
      updateRoleData(val)
        .then((res) => {
          if (res.code === "200") {
            this.msgSuccess(res.message);
            this.close(true);
          } else {
            this.alertWarningMsg(res.message);
            this.loadings.dialogLoading = false;
          }
        })
        .catch((err) => {
          console.log(err);
          this.loadings.dialogLoading = false;
        });
    },
    //菜单权限修改
    menuChangeapi(val) {
      updateRoleMenuData(val)
        .then((res) => {
          if (res.code === "200") {
            this.msgSuccess(res.message);
            this.close(true);
            // 立即刷新菜单相当于load
            // this.$store.dispatch("GenerateRoutes");
          } else {
            this.alertWarningMsg(res.message);
            this.loadings.dialogLoading = false;
          }
        })
        .catch((err) => {
          console.log(err);
          this.loadings.dialogLoading = false;
        });
    },
    treeCheckChange(data, checked) {
      console.log(data, checked);
      let arr = [];
      arr = checked.checkedKeys.concat(checked.halfCheckedKeys);
      this.treeCheckData = arr;
    },
    close(flag = false) {
      this.formData = {
        roleName: "",
      };
      this.checkedKeys = [];
      this.$emit("close", flag);
    },
    // 加载已绑定的菜单
    getBindingLeafMenuIds(menuList) {
      const menuMap = new Map();
      const bindingMenuIds = new Set();
      const parentMenuIds = new Set();

      menuList.forEach((menu) => {
        menuMap.set(menu.menuId, menu);
        if (menu.parentMenuId !== 0) {
          parentMenuIds.add(menu.parentMenuId);
        }
        if (menu.isBinding) {
          bindingMenuIds.add(menu.menuId);
        }
      });

      parentMenuIds.forEach((parentId) => {
        bindingMenuIds.delete(parentId);
      });

      return Array.from(bindingMenuIds);
    },
    loadCheckedKeys() {
      if (this.formData.roleId) {
        getMenuByRoleId(this.formData.roleId)
          .then((res) => {
            if (res.code === "200") {
              // console.log(this.getBindingLeafMenuIds(res.data));
              this.checkedKeys = this.getBindingLeafMenuIds(res.data);
              // this.checkedKeys = res.data
              //   .filter((item) => item.isBinding && item.parentMenuId != 0)
              //   .map((item) => item.menuId);
              // console.log("初始 checkedKeys:", this.checkedKeys);
              this.$nextTick(() => {
                this.$refs.tree.setCheckedKeys(this.checkedKeys);
                this.updateTreeCheckData();
              });
            } else {
              this.alertWarningMsg(res.message);
            }
          })
          .catch((err) => {
            console.log(err);
          });
      }
    },
    //加载选中的节点及半选中的父节点
    updateTreeCheckData() {
      const checkedKeys = this.$refs.tree.getCheckedKeys();
      const halfCheckedKeys = this.$refs.tree.getHalfCheckedKeys();
      this.treeCheckData = checkedKeys.concat(halfCheckedKeys);
      //console.log('合并后的 treeCheckData:', this.treeCheckData);
    },
  },
};
</script>

<style lang="scss" scoped>
@import "@/assets/styles/variables.scss";

.menuTree {
  max-width: 350px;
  max-height: 300px;
  overflow: auto;
  margin: 0 auto;
  border: 1px solid #999;
  padding: 10px;
}
</style>