bus_role.vue 10.8 KB
<template>
  <div class="sys-container">
    <div class="sys-pb-5">
      <el-button icon="el-icon-refresh-right" size="small" @click="btnRefresh">刷新</el-button>
      <el-button type="primary" size="small" icon="el-icon-plus" @click="editOrAddOpen(null, 'add')">
        新增
      </el-button>
    </div>

    <!-- table -->
    <div class="sys-table-border">
      <el-table :data="tableData" ref="multipleTable" highlight-current-row style="width: 100%" height="570">
        <el-table-column label="序号" width="60" type="index" />
        <el-table-column prop="id" label="id" v-if="false"></el-table-column>
        <el-table-column prop="roleCode" label="角色编码" v-if="false">
        </el-table-column>
        <el-table-column prop="roleName" label="角色名称"> </el-table-column>
        <el-table-column prop="remark" label="备注"> </el-table-column>

        <el-table-column prop="created" label="创建时间" width="180">
        </el-table-column>
        <el-table-column prop="createdBy" label="创建人"> </el-table-column>
        <el-table-column label="操作" width="120">
          <template slot-scope="scope">
            <el-button type="text" @click="editOrAddOpen(scope.row, 'edit')">编辑</el-button>
            <el-button style="color: red" type="text" @click="deleteAciton(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <!-- dialog 新增和编辑 -->
    <el-dialog :title="editOrAddOpt.title" v-if="editOrAddOpt.visible" :close-on-click-modal="false"
      :visible.sync="editOrAddOpt.visible" width="60%">
      <el-form :model="editOrAddOpt.form" label-width="80px">
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="名称">
              <el-input v-model="editOrAddOpt.form.roleCode" ref="roleCode" maxlength="20" show-word-limit
                autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="备注">
              <el-input v-model="editOrAddOpt.form.remark" type="textarea" :rows="2" autocomplete="off">
              </el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col>
            <el-form-item label="权限">
              <el-tree :data="treeOpt.data" show-checkbox node-key="id" :props="treeOpt.defaultProps"
                :default-expand-all="false" :check-strictly="true" :expand-on-click-node="false"
                :highlight-current="true" style="margin-top: 5px; height: 260px; overflow-y: auto"
                @node-click="roleNodeClick" ref="treePer" @check="handleNodeCheck">
                <!-- 自定义节点模板 -->
                <template #default="{ node, data }">
                  <span class="custom-tree-node">
                    <!-- 根据权限类型显示不同图标 -->
                    <i v-if="data.permissionType === 10" class="icon-module"></i>
                    <i v-if="data.permissionType === 1" class="icon-folder"></i>
                    <i v-if="data.permissionType === 5" class="icon-menu"></i>
                    <i v-if="data.permissionType === 15" class="icon-btn"></i>
                    <span>{{ node.label }}</span>
                  </span>
                </template>
              </el-tree>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="userAddOrEditSave">确 定</el-button>
        <el-button @click="editOrAddOpt.visible = false">取 消</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import * as userApi from "@/api/systemPermission/userPermission";
export default {
  data() {
    const editOrAddData = {
      roleCode: "",
      roleName: "",
      remark: null,
      Disable: false,
      //角色拥有的权限数据
      PermissionsIds: [],

      Permissions: null,
      Created: null,
      CreatedBy: null,
      Updated: null,
      UpdatedBy: null,
      Id: 0,
    };
    return {
      tableData: [],

      editOrAddOpt: {
        visible: false,
        flag: "add",
        title: "新增",
        form: { ...editOrAddData },
        formDefaultData: JSON.parse(JSON.stringify(editOrAddData)),
      },
      //临时存储的数据
      treeOpt: {
        data: [], // 处理后的数据(展示用)
        originData: [], // 原始数据
        defaultProps: {
          children: "children",
          label: "label",
        },
      },
    };
  },
  methods: {
    /**
     * 查询或者搜索
     */
    btnRefresh() {
      this.getAllPermissionList();
      this.getData();
    },

    getData() {
      userApi.getUserRole().then((res) => {
        userApi.ajaxSuccessBefore(res, (res) => {
          this.tableData = res.data;
        });
      });
    },

    /**
     * 获取权限数据
     */
    getAllPermissionList() {
      userApi.getAllPermission().then((res) => {
        userApi.ajaxSuccessBefore(res, (res) => {
          this.treeOpt.data = userApi.transformToTreeData(res.data);
          this.treeOpt.originData = res.data;
          //console.log(res.data, "all");
        });
      });
    },

    /**
     * 新增或者编辑弹出框
     */
    editOrAddOpen(row, flag) {
      debugger;
      if (this.treeOpt.data.length == 0) {
        this.$message.error(
          "权限数据加载中...请稍后在操作,反复出现请联系管理员!"
        );
        return;
      }
      this.editOrAddOpt.flag = flag;
      this.editOrAddOpt.visible = true;
      if (flag == "add") {
        this.editOrAddOpt.form = JSON.parse(
          JSON.stringify(this.editOrAddOpt.formDefaultData)
        );
        this.editOrAddOpt.title = "新增";
      } else {
        this.editOrAddOpt.title = `编辑,用户名【${row.roleName}】`;
        this.editOrAddOpt.form = row;
        userApi.getPermissionByRoleId(row.id).then((res) => {
          if (res.code !== "Success") return;
          const keys = res.data.map((x) => x.id);
          this.$nextTick(() => {
            this.$refs.treePer.setCheckedKeys(keys);
          });

          console.log(keys, "keys");
        });
      }
      this.$nextTick(() => {
        debugger;
        const firstNode = this.$refs.treePer.root.childNodes[0];
        if (firstNode) firstNode.expand();
      });
    },

    /**
     * 新增或者编辑 保存操作
     */
    userAddOrEditSave() {
      debugger;
      if (
        this.editOrAddOpt.form.roleCode == "" ||
        this.editOrAddOpt.form.roleCode == null
      ) {
        this.$message.error("权限名称不能为!");
        this.$refs.roleCode.focus();
        return;
      }
      this.editOrAddOpt.form.roleName = this.editOrAddOpt.form.roleCode;
      var selectData = this.getSelectRoleVal();
      if (selectData.length == 0) return;
      this.editOrAddOpt.form.PermissionsIds = selectData;

      if (this.editOrAddOpt.flag == "edit") {
        userApi.editRoleAndPermissions(this.editOrAddOpt.form).then((res) => {
          userApi.ajaxSuccessBefore(
            res,
            (res) => {
              this.editOrAddOpt.visible = false;
              this.getData();
            },
            this
          );
        });
        return;
      }
      userApi.addRoleAndPermissions(this.editOrAddOpt.form).then((res) => {
        userApi.ajaxSuccessBefore(
          res,
          (res) => {
            this.editOrAddOpt.visible = false;
            this.getData();
          },
          this
        );
      });
    },

    //删除
    deleteAciton(row) {
      var title = `此操作将永久删除该数据,【${row.roleName}】,是否继续?`;
      this.$confirm(title, "提示", { type: "warning" })
        .then(() => {
          userApi.deleteRoleByIds([row.id]).then((res) => {
            userApi.ajaxSuccessBefore(
              res,
              (res) => {
                this.editOrAddOpt.visible = false;
                this.getData();
              },
              this
            );
          });
        })
        .catch();
    },

    setCurrent(row) {
      this.$refs.multipleTable.setCurrentRow(row);
    },

    //获取选中的权限
    getSelectRoleVal() {
      var result = this.$refs.treePer.getCheckedKeys();
      if (result.length == 0) {
        this.$message.error("请选择权限数据!");
        return [];
      }
      return result;
    },
    roleNodeClick(data, node, event) {
      console.log("selectRowData", data);
    },
    // 处理节点勾选事件
    handleNodeCheck(data, { checkedNodes }) {
      // 新增:获取当前节点自身的选中状态
      const isChecked = checkedNodes.some((node) => node.id === data.id);

      if (isChecked) {
        // 勾选时同步子节点
        if (data.children) {
          this.toggleChildren(data.children, true);
        }
      } else {
        // 取消勾选时同步子节点(关键修复)
        if (data.children) {
          const childKeys = this.getAllChildKeys(data);
          const currentChecked = this.$refs.treePer.getCheckedKeys();
          const newChecked = currentChecked.filter(
            (k) => !childKeys.includes(k)
          );
          this.$refs.treePer.setCheckedKeys(newChecked);
        }
      }
    }, // 新增方法:获取所有子节点键值
    getAllChildKeys(node) {
      return (
        node.children?.reduce((acc, child) => {
          acc.push(child.id);
          if (child.children) acc.push(...this.getAllChildKeys(child));
          return acc;
        }, []) || []
      );
    },

    // 修改后的子节点同步方法
    toggleChildren(children, checked) {
      children.forEach((child) => {
        this.$refs.treePer.setChecked(child.id, checked);
        if (child.children) this.toggleChildren(child.children, checked);
      });
    },
  },
  mounted() {
    this.getAllPermissionList();
    this.getData();
  },
};
</script>
<style scoped lang="scss">
.sys-container {
  width: 100%;

  .sys-pb-5 {
    padding-bottom: 5px !important;
  }

  .sys-form-item {
    display: flex;
    border-radius: 4px;
    min-height: 46px;
    margin-bottom: 10px;
    align-items: center;
  }

  .sys-table-border {
    border: 1px solid #e5e9f2;
  }

  .sys-pagination-container {
    text-align: center;
  }
}

.current-row {
  background-color: #ecf5ff;
}

/* 图标样式 */
.custom-tree-node i[class^="icon-"] {
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-right: 5px;
  vertical-align: middle;
}

.icon-module {
  background: url(~@/assets/images/module.png) no-repeat center/contain;
}

.icon-folder {
  background: url(~@/assets/images/folder.png) no-repeat center/contain;
}

.icon-menu {
  background: url(~@/assets/images/menu.png) no-repeat center/contain;
}

.icon-btn {
  background: url(~@/assets/images/btn.png) no-repeat center/contain;
}
</style>