利用 ant design vue里面checkbox组件写一个横向的授权组件。

说明:这个菜单授权的代码目前只实现了一、二级菜单授权。

实现效果

 代码分成两部分:1.vue页面

<template>
  <div class="container">
    <a-card :bordered="false">
      <span class="back-box" @click="backPage"><a-icon type="left" />返回</span>
      <p class="left-top-title">角色</p>
      <a-form
        layout="horizontal"
        :form="form"
        :label-col="{ span: 7 }"
        :wrapper-col="{ span: 12 }"
      >
        <a-row type="flex" justify="center">
          <a-col :span="20">
            <a-form-item label="角色">
              <a-input
                placeholder="请输入名称"
                v-decorator="[
                  'name',
                  { rules: [{ required: true, message: '请输入角色名称' }] },
                ]"
              ></a-input>
            </a-form-item>
          </a-col>
          <a-col :span="20">
            <a-form-item label="角色描述">
              <a-textarea
                placeholder="请输入角色描述"
                v-decorator="['remark']"
              />
            </a-form-item>
          </a-col>
        </a-row>
      </a-form>
      <p class="left-top-title">授权</p>
      <div class="all-item">
        <div
          v-for="(item, index) in menuAll"
          :key="index"
          :class="
            item.children.length == 0 || item.close
              ? 'clear-margin'
              : 'check-item'
          "
        >
          <div class="header-box-style">
            <a-checkbox
              :indeterminate="item.indeterminate"
              :checked="item.checkAll"
              @change="onCheckAllChange(index, $event)"
            >
              {{ item.name }}
            </a-checkbox>
            <p
              class="open-or-close"
              v-if="item.children.length"
              @click="closeShow(index)"
            >
              {{ item.close ? "展开" : "关闭" }}
            </p>
          </div>
          <br />
          <a-checkbox-group
            v-if="item.children.length && !item.close"
            v-model="item.checklist"
            :options="item.children | backArr"
            @change="onChange(item.checklist, item.children.length, index)"
          />
        </div>
      </div>
      <div class="bottom-btn-box">
        <a-button type="default" @click="backPage">取消</a-button>
        <a-button type="primary" @click="submit">确认</a-button>
      </div>
    </a-card>
  </div>
</template>

<script>
import store from "@/store";
import { initData, handleOriginal } from "@/common/permissions/handleCheck.js";
export default {
  name: "",
  data() {
    return {
      form: this.$form.createForm(this),
      indeterminate: true,
      checkAll: false,
      permissions: [],
      checkedList: [],
      menuAll: [],
    };
  },
  filters: {
    backArr(value) {
      let temp = [];
      value.forEach((item) => {
        let obj = {
          label: item.name,
          value: item.id,
        };
        temp.push(obj);
      });
      return temp;
    },
  },
  mounted() {
    this.getItemRole();
  },
  methods: {
    // 获得角色数据
    getItemRole() {
      this.$http.get("/role/" + this.$route.query.id).then((res) => {
        if (res.code == 1) {
          this.form.setFieldsValue({
            name: res.data.name,
            remark: res.data.remark,
          });
          this.permissions = res.data.permissions;
          this.editId = res.data.id;
          this.menuAll = initData(store.state.Menu.routes[0].children.slice());
          this.menuAll =
            this.permissions.length > 0
              ? handleOriginal(this.menuAll, this.permissions)
              : this.menuAll;
        }
      });
    },
    // 提交
    submit() {
      //  获取选中id集合
      this.checkedList = this.backChecked(this.menuAll);
      this.form.validateFields((err, fieldsValue) => {
        if (err) {
          return;
        }
        let permis = this.checkedList;
        this.$set(fieldsValue, "permissions", permis);
        this.$set(fieldsValue, "id", this.editId);
        this.$http.put("/role", fieldsValue).then((res) => {
          if (res.code == 1) {
            this.$message.success(res.msg);
            this.$router.push("/user/permission");
          } else {
            this.$message.error(res.msg);
          }
        });
      });
    },
    // 返回选中id数组
    backChecked(list) {
      let checkArr = [];
      list.forEach((item) => {
        if (item.children.length == 0 && item.checkAll) {
          checkArr.push(item.id);
        }
        checkArr.push(...item.checklist);
      });
      return checkArr;
    },
    closeShow(index) {
      this.menuAll[index].close = !this.menuAll[index].close;
    },
    // 跳转到列表页
    backPage() {
      this.$router.push("/user/permission");
    },
    onChange(list, maxlength, index) {
      // 当前选中内容的内容长度
      if (list.length == maxlength) {
        // 选中父级
        this.menuAll[index].checkAll = true;
        this.menuAll[index].indeterminate = false;
      } else {
        if (list.length > 0) {
          this.menuAll[index].indeterminate = true;
        } else {
          this.menuAll[index].checkAll = false;
          this.menuAll[index].indeterminate = false;
        }
      }
    },
    onCheckAllChange(index) {
      // 父控制自己选中显示样式
      this.menuAll[index].checkAll = !this.menuAll[index].checkAll;
      this.menuAll[index].indeterminate = false;
      // 子都选中样式
      if (this.menuAll[index].checkAll) {
        this.menuAll[index].checklist = this.menuAll[index].children.map(
          (item) => {
            return item.id;
          }
        );
      } else {
        this.menuAll[index].checklist = [];
      }
    },
  },
};
</script>
<style scoped lang="less">
// 返回功能位置修饰
/deep/.ant-card-body {
  padding-top: 10px;
}
.back-box {
  display: inline-block;
  margin-bottom: 15px;
}
.left-top-title {
  font-weight: 600;
  color: rgb(150, 150, 150);
  line-height: 30px;
  font-size: 16px;
}
.left-top-title::before {
  content: "";
  display: inline-block;
  width: 4px;
  height: 14px;
  background: rgb(0, 164, 230);
  margin-right: 8px;
  margin-bottom: 0px;
}
.clear-margin {
}
.all-item {
  height: 480px;
  overflow-y: auto;
  padding-top: 20px;
}
.check-item {
  margin-bottom: 20px;
}
.header-box-style {
  width: 100%;
  height: 36px;
  line-height: 36px;
  background: #f5f5f5;
  padding-left: 10px;
  position: relative;
  .open-or-close {
    position: absolute;
    right: 10px;
    top: 0;
    color: rgb(0, 164, 230);
    cursor: pointer;
  }
}
.ant-checkbox-group {
  padding-left: 20px;
}
.bottom-btn-box {
  display: flex;
  justify-content: center;
  padding-top: 20px;
  .ant-btn-primary {
    margin-left: 16px;
  }
}
</style>

js.传参处理。

/* 
给菜单数据里面添加新的参数
 */
export function initData(arr) {
  let menuAll = arr.concat();
  let menu = [];
  menuAll.forEach((item) => {
    let obj = {
      ...item,
      close: false,
      indeterminate: false,
      checklist: [],
      checkAll: false,
    };
    menu.push(obj);
  });
  return menu;
}
/* 
params:list 是完整菜单
params:arr 后端返回权限数组
 */
export function handleOriginal(arr0, arr) {
  let list = arr0.concat();
  let menu = arr0.concat();
  list.forEach((element, index) => {
    if (element.children.length > 0) {
      let children = element.children.map((item) => item.id);
      menu[index] = { ...element, ...findChecked(children, arr) };
    } else {
      arr.forEach((item) => {
        if (item == element.id) {
          menu[index].checkAll = true;
        }
      });
    }
  });
  return menu;
}
/* 
params:child 子id集合
params:permis 子id集合
 */
export function findChecked(child, permis) {
  let checklist = [];
  let checkAll = false;
  let indeterminate = false;
  child.forEach((item) => {
    permis.forEach((pe) => {
      if (item == pe) {
        checklist.push(pe);
      }
    });
  });
  if (checklist.length == child.length) {
    //   子集群都包含
    checkAll = true;
    indeterminate = false;
  } else {
    checkAll = false;
    indeterminate = true;
    if (checklist.length == 0) {
      indeterminate = false;
    }
  }
  return {
    checklist: checklist,
    checkAll: checkAll,
    indeterminate: indeterminate,
  };
}

最开始项目设计授权的时候,只考虑了二级菜单授权问题。后来研究了一下,项目其实是包含三级菜单的。授权就要落到三级上面,可惜,这个上面手写的授权组件不好用了,实现三级会很麻烦。果断换成了树状。呼呼。

如果用大家知道这个checkbox点击时候,只点击选框才选中点击文字不选中,希望留言一下。现在实现三级主要是卡在这地方了。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ant design vue2 是由阿里巴巴 Ant Design 团队开发的一套 Vue.js 组件库,它基于 Ant Design 的设计语言,为开发者提供了一系列常用的页面组件和业务组件,用于快速地搭建现代化的 Web 应用。ant design vue2 开发者友好,提供了全面的文档和代码示例,使得开发者可以快速上手,减少开发时间。 ant design vue2 的特点包括: 1. 丰富的组件库:ant design vue2 包括了丰富的页面组件和业务组件,例如表格、表单、日期选择器、模态框等,可以供开发者使用,减少开发时间。 2. 简洁的样式:ant design vue2 遵循 Ant Design 的设计语言,采用简洁美观的样式风格,符合现代化 Web 应用的设计风格。 3. 易于定制:ant design vue2 提供了多样的主题定制方式,开发者可以按照自己的需求进行修改和定制,使得应用更符合品牌需求。 4. 支持国际化:ant design vue2 提供了多语言支持,无论是中文、英文或者其他语言,都可以轻松地实现国际化。 5. 生态完备:ant design vue2 是基于 Vue.js 框架开发的,与 Vue.js 的生态完备结合,使得开发者可以使用如 Vuex、Vue Router、Axios 等社区流行的工具集,轻松地开发出符合需求的 Web 应用。 总之,ant design vue2 作为一套成熟的 Vue.js 组件库,为开发现代化 Web 应用提供了有力的支持。其简洁美观的风格和丰富的组件库,让开发者可以快速搭建一款现代化的 Web 应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值