后台管理系统根据后台返回配置动态菜单栏

工作中提出的需求是这样的:根据登录后返回数据的菜单数据来配置菜单栏 而不是在app.vue将菜单栏进行定死
  • 登录成功后 后台返回的数据样式
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 实现的效果(分为header头部和tab按钮部分)
    在这里插入图片描述
  • header的实现全部代码;定义成了一个组件进行引入调用
<template>
  <div class="header-box">
     
    <div class="header">
      <!-- <div
        @click="homePage"
        :class="{'isActive':firstActive}"
        v-for="(item,i) in menus"
        :key="i"
       v-if="i == 0"
      >{{item.menuName}}</div> -->
      <div class="f_align" style='float:right'>
        <el-breadcrumb separator="|">
          <el-breadcrumb-item>
            <el-dropdown trigger="click" size="small">
              <span class="el-dropdown-link">
                {{userName}}
                <i class="el-icon-arrow-down el-icon--right"></i>
              </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item @click.native="exit">退出登录</el-dropdown-item>
                <el-dropdown-item @click.native="password">修改密码</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </el-breadcrumb-item>

          <el-breadcrumb-item
            :to="index==0? {path: '/'}:''"
            v-for="(item,index) in menus"                      
            :key="index"
            :class="{'isActive':item.active}"
            @click.native="breadcrumbMenu(item,index)"
          >{{item.menuName}}</el-breadcrumb-item>
          
          <!-- <el-breadcrumb-item
            :to="crumbMenuPath"
            v-for="(item,index) in crumbMenu"
            :key="index"
          >{{item.menuName}}</el-breadcrumb-item> -->
        </el-breadcrumb>
      </div>
    </div>


    <div class="header-menu">
      <div class="header-menu-box">        
        <div class="header-menu-logo f_align"  ><img :src="moren"></div>
        <!-- <div class="header-menu-logo f_align" ../assets/images/logo_jm.png  v-if="tspId != '3952800789893101'"><img src="../assets/images/logo_2.png"></div> -->

        <ul>
          <li
            class="header-menu-name"
            v-for="(item,key) in menuArr"
            :key="key"
            @click="subMenu(item)"
          >{{item.menuName}}</li>
        </ul>
      </div>
    </div>

    <el-dialog
      class="dialog_contact"
      style
      title="修改密码"
      :visible.sync="changeshow"
      :modal-append-to-body="false"
      :close-on-click-modal="false"
      width="28%"
      top="25vh"
     >
      <el-row>
        <el-col :span="22">
          <el-form :model="form" :rules="registRule" ref="form" label-width="120px">
            <el-form-item label="旧密码:">
              <el-input size="small" v-model="form.oldpwd" placeholder='请输入旧密码' show-password></el-input>
            </el-form-item>

            <el-form-item label="新密码:">
              <el-input size="small" v-model="form.pwd" placeholder='请输入新密码' show-password></el-input>
            </el-form-item>

            <el-form-item label="确认密码:">
              <el-input size="small" v-model="form.checkpwd" placeholder='请确认新密码' show-password></el-input>
            </el-form-item>
          </el-form>
        </el-col>
      </el-row>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" size="small" @click="confrim">确定</el-button>
        <el-button size="small" @click="changeshow=false">关闭</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { mapState } from "vuex";
export default {
  name: "Header",
  props: {}, 
  computed: {
    ...mapState(["loginUserCode", "frspName", "frspId", "menus", "twoMenus",'userName'])
  }, 
  data() {
    var checkPsd = (rule, value, callback) => {
      var regExp = new RegExp("^.{6,}$", "i");
      if (!value) {
        return callback(new Error("密码不能为空!"));
      } else if (!regExp.test(value)) {
        return callback(new Error("密码不能小于6位字符!"));
      } else {
        callback();
      }
    };
    var checkRepsd = (rule, value, callback) => {
      if (!value) {
        callback(new Error("请再次输入密码"));
      } else if (value !== this.form.pwd) {
        callback(new Error("两次输入密码不一致!"));
      } else {
        callback();
      }
    };
    return {
      firstActive: true,
      menuArr: [],     
      tspId:'',
      moren:require('@/assets/images/logo_jm.png'),   
      changeshow: false,
      form: {
        pwd: "",
        oldpwd: "",
        checkpwd: ""
      },
      registRule: {
        pwd: [{ validator: checkPsd, trigger: "blur" }],
        checkpwd: [{ validator: checkRepsd, trigger: "blur" }]
      }
    };
  },
  methods: {
    crumbMenuPath(val) {
      console.log("val**************", val);
    },
    breadcrumbMenu(item, index) {
      // 一级菜单 面包屑菜单
      let menuId = item.menuId;
      let twoMenu = Object.keys(this.twoMenus); //关于Object.keys的用法在下面有解释
     
      this.firstActive = false;

      twoMenu.forEach(item => {
        // 二级菜单
        if (menuId == item) {
          this.menuArr = this.twoMenus[item];
        }
      });

      this.menus.forEach((key, i) => {
        // active 样式
        if (index == i) {
          this.$set(key, "active", true);
        } else {
          this.$set(key, "active", false);
        }
      });
    },
    subMenu(item) {
      // 子菜
      let menuId = "";
      let href = location.href.split("/");
      let url = href[0] + "//" + href[2];

      this.menus.forEach(ele => {
        // 获取结算中心 key值 settlement
        if (ele.menuName == "结算中心") {
          menuId = ele.menuId;
        }
      });

      this.menuArr.forEach(key => {
        if (menuId == key.fmenuId) {
          // 结算中心 open新页面
          // window.open(url + "/settlement/" + item.menuUrl, "_blank")
          let menuUrl = url + "/settlement/" + item.menuUrl;

          this.$router.push({
            name: item.menuName,
            params: { url: menuUrl }
          });
          return;
        } else {
          //其他路由跳转
          this.$router.push({ path: item.menuUrl });
          return;
        }
      });
    },
    homePage() {
      // 首页
      this.$router.push({ path: "/" });
      this.firstActive = true;
      this.menus.forEach(key => {
        this.$set(key, "active", false);
      });
    },
    orderCenter() {
      // 订单中心
      this.$router.push({ path: "/OrderCenter" });
    },
    onlineOrder() {
      // 在线下单
      this.$router.push({ path: "/OnlineOrder" });
    },
    exit() {
      //退出
      sessionStorage.removeItem('hasLogin');
      sessionStorage.clear();
      // localStorage.clear(); 
      this.menuArr = [];         
      this.$router.push({ path: "/login" });     
    },
    password() {
      //修改密码
      this.pwd = "";
      this.oldpwd = "";
      this.checkpwd = "";
      this.changeshow = true;     
    },
    confrim() {
      var regExp = new RegExp("^.{6,}$", "i");
      if (!regExp.test(this.form.pwd)) {
        this.$message({
          type: "warning",
          message: "密码不能小于6位字符"
        });
        return;
      }
      if (this.form.pwd != this.form.checkpwd) {
        this.$message({
          type: "warning",
          message: "新密码必须一致!"
        });
        return;
      }
      let that = this;
      this.$http({
        method: "post",
        url: "/api" + this.$api.system.changePwd,
        data: {
          tspId: localStorage.getItem('tspId'),
          loginUserCode: localStorage.getItem('userLogcode'),
          oldPwd: this.form.oldpwd,
          newPwd: this.form.pwd,
          platformType:JSON.parse(localStorage.getItem('userInfo')).datas.data.platformType
        },
        success: function(res) {
          that.$message({
            type: "success",
            message: "修改成功"
          });
          that.changeshow = false;
          that.pwd = "";
          that.oldpwd = "";
          that.checkpwd = "";
          setTimeout(() => {
            that.exit();
          }, 1000);
        }
      });
    },
    getLogo(){     
      //根据配置获取logo
      this.$http({
        method: "post",
        url: "/api" + this.$api.user.searchLogBywwl,
        data: {
          tspWwl:window.location.host
          // tspWwl:"hfjy.1stline.cn"
        },
        success: function(res) {
          console.log("1111")
          if(res.datas){
              this.moren="http://oms.imton.cn/services/file-service/api/file/image/"+res.datas;
            }else {
              this.moren=require('@/assets/images/logo_jm.png')
            }     
        }.bind(this),     
      });    
    }
  },
  created() {  
      this.twoMenus=JSON.parse(localStorage.getItem('userInfo')).datas.twoMenus,
      this.menus=JSON.parse(localStorage.getItem('userInfo')).datas.menus,
      this.menus.forEach(key => {
      this.$set(key, "active", false);
    });      
  },  
  mounted(){
    this.getLogo();
  }
};
</script>

<style lang="scss" scoped>
.header-box {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  color: #909399;
  // border: 1px solid red;
  .header {    
    padding:0 10%;
    height: 40%;
    display: flex;
    font-size: 14px;
    background: #f2f6f7;
    align-items: center;
    justify-content: flex-end;
    margin: 0 auto;
    cursor: pointer !important;
  }

  .header-menu {
    width: 100%;
    height: 60%;   
    //  background: url(../assets/icon/bl.png) no-repeat center bottom;
    .header-menu-box {      
      height: 100%;
      display: flex;
      align-items: center;
      margin: 0 auto;
      color: #909399;
      .header-menu-logo {
       
        margin-right: 35px;
        img {
          height: 80%;
          margin-right: 15px;
        }
      }

      ul {
        flex: 1;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: flex-start;
        .header-menu-name {
          padding: 0 15px;
          font-size: 16px;
        //   font-weight: bold;
          cursor: pointer;
        }
      }
    }
  }
  /deep/ .el-breadcrumb__inner:hover {
    cursor: pointer !important;
  }
  /deep/ .el-breadcrumb__inner {
    font-weight: 500;
    color: #999;
    font-size: 12px;
  }

  /deep/ .el-dropdown {
    color: #999;
    font-size: 12px;
  }
  .isActive {
    color: #3296fa;
    /deep/ .el-breadcrumb__inner {
      color: #3296fa;
    }
  }
}
</style>
  • 关于object.key的用法
    在这里插入图片描述
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
后台管理系统左侧菜单分类是通过后端返回的menuList来确定的。在调用登录接口时,后端会返回一个menuList,然后将这个menuList存储到localStorage中。每个菜单项都有一个对应的code值,前后端需要沟通好每个code值对应的菜单项名称。在前端的power.js文件中,会从localStorage中取出menuList,并逐个判断对应的code值是否为true,如果为true,则显示该菜单项。这样就实现了根据后端返回菜单权限来显示左侧菜单的分类。\[1\]在src/store/modules/menu.js文件中,还定义了slideWidth来控制左侧菜单的折叠状态。通过改变slideWidth的值,可以实现菜单的展开和折叠。\[2\]同时,给折叠按钮绑定了点击事件,点击按钮时会调用handleSlideWidth方法来改变slideWidth的值,从而实现菜单的折叠和展开。\[3\] #### 引用[.reference_title] - *1* [后台管理系统左侧菜单权限怎么控制](https://blog.csdn.net/Frazier1995/article/details/121161841)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [后台管理左侧菜单](https://blog.csdn.net/Jiaodaqiaobiluo/article/details/126266864)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值