javaScript蓝桥杯----商城管理系统

目录

  • 一、介绍
  • 二、准备
  • 三、目标
  • 四、代码
  • 五、完成


一、介绍

在商城管理系统中,超级管理员和普通管理员因为权限不同,登录进入后看到的菜单也会是不同的。

本题需要你完成商城管理系统中权限数据的处理。

二、准备

开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:

├── css
├── images
├── js
│   ├── auth.js
│   └── menu.js
├── effect.gif
├── login.html
└── index.html

其中:

css 是样式文件夹。
images 是图片文件夹。
login.html 是登录页。
index.html 是商城首页。
js/menu.js 是渲染左侧菜单的 js 文件。
js/auth.js 是需要补充代码的 js 文件。
effect.gif 是最终完成的效果图。

在浏览器中预览 login.html 页面效果如下
javaScript蓝桥杯----商城管理系统_第1张图片

三、目标

请在 js/auth.js 文件中补全 getMenuListAndAuth 函数代码。

在登录页 login.html 点击管理员登录和超级管理员登录时会根据管理员的权限不同,在商城首页 index.html 的左侧显示不同的菜单列表。但是后端同学给的数据是不符合前端展示要求的,所以我们需要做些处理,假如后端提供的数据是这样的:

[
  { parentId: -1, name: "商品管理", id: 1, auth: "cart" },
  { parentId: 1, name: "商品列表", id: 4, auth: "cart-list" },
  { parentId: -1, name: "添加管理员", id: 10, auth: "admin" },
];

其中数据中对象字段的含义说明:

  • id 表示当前节点
  • parentId 表示父级节点,如果为 -1 则表示顶级数据
  • auth 表示权限
    具体需求如下:
  1. 将待处理数据(一维数组)根据 parentId 字段值处理成树形结构存入 menus 变量中。

把数据处理成如下格式(每一项都必须有 children 字段,没有子级时,children 为空数组):

[
  {
    parentId: -1,
    name: "商品管理",
    id: 1,
    auth: "cart",
    children: [
      {
        parentId: 1,
        name: "商品列表",
        id: 4,
        auth: "cart-list",
        children: [],
      },
    ],
  },
  {
    parentId: -1,
    name: "添加管理员",
    id: 10,
    auth: "admin",
    children: [],
  },
];

注意:js/auth.js 中的 menuList 仅为后端返回的数据结构示例,非固定数据。实际使用中,后端返回的数据转化成树形结构时层级可能更多,封装方法时务必考虑通用性。

  1. 将待处理数据中的 auth 字段提取出来并存入 auths 变量中,左侧菜单会根据传入的权限列表数组和 auths 对比后进行菜单渲染。
    经过 getMenuListAndAuth 处理后 auths 的结果为:
["cart", "cart-list", "admin"];

完成后的效果见文件夹下面的 gif 图,图片名称为 effect.gif(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。

四、代码

login.html

DOCTYPE html>
<html>
<head>
    <title>商城管理系统title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <link href="css/login.css" rel="stylesheet" type="text/css">
<body>
    <div class="main">
        <div class="container">
            <h2>立即登录h2>
            <input type="text" value="admin" />
            <input value="PASSWORD" name="Password" type="password" />
            <span><input type="checkbox" checked />记住我span>
            <h6><a href="#">忘记密码?a>h6>
            <div class="clear">
                <input type="submit" onclick="adminLogin()" value="管理员登录">
                <input type="submit" onclick="superLogin()" value="超级管理员登录">
            div>
            <p>还没有账号?<a href="#">立即注册a>p>
        div>
    div>
    <footer>
        <p>© 2022 蓝桥杯 | 商城管理系统 <a>bootstrap搭建a>p>
    footer>
    <script>
        let adminLogin = () => {
            window.location.href = "./index.html?name=admin";
        }
        let superLogin = () => {
            window.location.href = "./index.html?name=super";
        }
    script>
body>

html>

index.html

DOCTYPE html>
<html>
  <head>
    <title>商城管理系统title>
    <meta charset="UTF-8" />
    <link href="css/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <link href="css/style.css" rel="stylesheet" type="text/css" />
  head>
  <body class="skin-black">
    <header class="header">
      <a href="index.html" class="logo"> 商城管理系统 a>
      <nav class="navbar navbar-static-top">
        <div class="navbar-right">
          <ul class="nav navbar-nav">
            <li class="dropdown">
              <a href="./login.html" class="dropdown-toggle">
                <span>退出span>
              a>
            li>
          ul>
        div>
      nav>
    header>
    <div class="wrapper row-offcanvas row-offcanvas-left">
      <div class="left-side sidebar-offcanvas">
        <section class="sidebar">
          <div class="user-panel">
            <div class="pull-left image">
              <img src="images/admin.jpg" class="img-circle" alt="User Image" />
            div>
            <div class="pull-left info">
              <p id="admin">你好,管理员p>
              <a href="#">
                <i class="text-success">在线i>
              a>
            div>
          div>
          
          <ul id="sidebarmenu" class="text-success">ul>
        section>
      div>
      <div class="right-side">
        <section class="content">
          <div class="row" style="margin-bottom: 5px">
            <div class="col-md-3">
              <div class="sm-st clearfix">
                <span class="sm-block-icon block-red">1span>
                <div class="sm-block-info">
                  <span>3200span>
                  商城访问量
                div>
              div>
            div>
            <div class="col-md-3">
              <div class="sm-st clearfix">
                <span class="sm-block-icon block-violet">2span>
                <div class="sm-block-info">
                  <span>2200span>
                  售出商品数
                div>
              div>
            div>
            <div class="col-md-3">
              <div class="sm-st clearfix">
                <span class="sm-block-icon block-blue">3span>
                <div class="sm-block-info">
                  <span>100,320span>
                  总销售额
                div>
              div>
            div>
            <div class="col-md-3">
              <div class="sm-st clearfix">
                <span class="sm-block-icon block-green">4span>
                <div class="sm-block-info">
                  <span>4567span>
                  总利润
                div>
              div>
            div>
          div>
          <div class="row">
            <div class="col-md-12">
              <section class="panel">
                <header class="panel-heading">热销商品header>
                <div class="panel-body table-responsive">
                  <table class="table table-hover">
                    <thead>
                      <tr>
                        <th>#th>
                        <th>商品名称th>
                        <th>库存th>
                        <th>上架时间th>
                        <th>状态th>
                        <th>售出量th>
                      tr>
                    thead>
                    <tbody>
                      <tr>
                        <td>1td>
                        <td>macbook pro 2021td>
                        <td>1000td>
                        <td>1/5/2022td>
                        <td><span class="label label-info">余量充足span>td>
                        <td><span class="badge badge-info">50%span>td>
                      tr>
                      <tr>
                        <td>2td>
                        <td>macbook pro 2019td>
                        <td>3000td>
                        <td>06/08/2021td>
                        <td><span class="label label-success">已售罄span>td>
                        <td><span class="badge badge-success">100%span>td>
                      tr>
                      <tr>
                        <td>3td>
                        <td>iphone 12td>
                        <td>520td>
                        <td>10/12/2019td>
                        <td><span class="label label-info">余量充足span>td>
                        <td><span class="badge badge-info">75%span>td>
                      tr>
                      <tr>
                        <td>4td>
                        <td>Xiaomi 12 Protd>
                        <td>400td>
                        <td>03/22/2022td>
                        <td><span class="label label-info">余量充足span>td>
                        <td><span class="badge badge-info">65%span>td>
                      tr>
                      <tr>
                        <td>5td>
                        <td>Hua Wei Meta 40td>
                        <td>730td>
                        <td>03/11/2022td>
                        <td>
                          <span class="label label-warning">即将售罄span>
                        td>
                        <td><span class="badge badge-danger">95%span>td>
                      tr>
                      <tr>
                        <td>6td>
                        <td>Hua Wei Meta V30td>
                        <td>300td>
                        <td>05/11/2019td>
                        <td>
                          <span class="label label-warning">即将售罄span>
                        td>
                        <td><span class="badge badge-danger">95%span>td>
                      tr>
                    tbody>
                  table>
                div>
              section>
            div>
          div>
        section>
      div>
    div>
    <script src="./js/auth.js ">script>
    <script src="./js/menu.js ">script>
  body>
html>

js/auth.js

// menuList 仅为示例数据,非实际使用数据,实际使用数据层级不确定(可能是四级五级六级等),数据结构与 menuList 一致
// 1. `parentId` 如果为 `-1`,则表示此条数据为顶级数据。
// 2. `parentId` 为该条数据的父级数据的 `id`。

let menuList = [
  { parentId: -1, name: "添加管理员", id: 10, auth: "admin" },
  { parentId: 10, name: "管理员权限分配", id: 11, auth: "admin-auth" },
  { parentId: -1, name: "商品管理", id: 1, auth: "product" },
  { parentId: 1, name: "商品列表", id: 4, auth: "productList" },
  { parentId: 4, name: "商品分类", id: 5, auth: "category" },
  { parentId: 5, name: "添加分类", id: 8, auth: "addClassification" },
  { parentId: 4, name: "商品上架", id: 6, auth: "product" },
  { parentId: -1, name: "评论管理", id: 2, auth: "comments" },
  { parentId: -1, name: "个人中心", id: 3, auth: "profile" },
];

/**
 * @param {*} menuList 传入的数据
 * @return {*} menus 转化后的树形结构数据,auths 转化后的权限列表数组
 */

const getMenuListAndAuth = (menuList) => {
  // TODO:待补充代码
  return { menus, auths }; // menus 转化后的树形结构数据,auths 转化后的权限列表数组
};

// 请勿删除和修改以下代码
try {
  module.exports = { getMenuListAndAuth };
} catch (e) {}

js/menu.js

let admin = document.getElementById("admin");

let authList;
let url = location.href;

// 获取最终要渲染的菜单列表
let res = getMenuListAndAuth(menuList);

function getUrlParam(key) {
  let args = {};
  const arr = url.match(/\w+=\w+/gi).map((kv) => kv.split("="));
  for (let item of arr) {
    args[item[0]] = item[1];
  }
  return args[key];
}

let role = getUrlParam("name");

if (role == "admin") {
  // 管理员
  authList = ["profile", "comments", "product", "productList", "category"];
  admin.innerHTML = `你好,管理员`;
} else {
  // 超级管理员
  authList = [
    "profile",
    "comments",
    "product",
    "productList",
    "category",
    "addClassification",
    "admin",
    "product",
    "admin-auth",
  ];
  admin.innerHTML = `你好,超级管理员`;
}
// 全部的菜单列表
let sidelistall = res.menus;
let sidebarmenu = document.querySelector("#sidebarmenu");

/**
 * @param {*} auth 传入的权限列表
 * @return {*}  根据传入的权限列表返回需要显示的菜单列表
 */
const getNav = (auth) => {
  const filter = (sidelistall) => {
    return sidelistall.filter((item) => {
      if (auth.includes(item.auth)) {
        if (item.children) {
          item.children = filter(item.children);
        }
        return true;
      }
    });
  };
  return filter(sidelistall);
};
renderSide();

// 根据权限渲染左侧菜单
function renderSide() {
  let menuListside = getNav(authList);
  const rendermenu = (children) => {
    let childrenhtml = "";
    childrenhtml += children
      .map((child) => {
        let childrenH2 = "";
        if (child.children && !!child.children.length) {
          childrenH2 = rendermenu(child.children);
        }
        return `
  • ${child.name} ${childrenH2 ? ` ${childrenH2}` : ""}
`
; }) .join(""); return childrenhtml; }; // 渲染菜单 menuListside.map((item, index) => { let childrenhtml = ""; // 首先判断 item 有没有子级 if (item.children && !!item.children.length) { childrenhtml = rendermenu(item.children); } sidebarmenu.innerHTML += `
  • ${item.name} ${ childrenhtml ? childrenhtml : "" }
  • `
    ; }); }

    css/login.css

    body {
      font-family: Verdana;
      background: url("../images/bg.jpg") no-repeat 62% 34%;
      background-size: cover;
      text-align: center;
    }
    
    .container h2 {
      color: #fff;
      font-size: 29px;
      letter-spacing: 2px;
      text-transform: uppercase;
      padding-bottom: 15px;
    }
    
    .container {
      width: 25%;
      margin: 0 auto;
      background: rgba(0, 0, 0, 0.34);
      padding: 42px 35px;
    }
    
    .main {
      margin-top: 100px;
    }
    
    input[type="text"],
    input[type="password"] {
      width: 88%;
      padding: 15px 0px 15px 42px;
      border: 1px solid #fff;
      outline: none;
      font-size: 14px;
      color: #fff;
      margin: 14px 0px;
    }
    
    input[type="text"] {
      background: url("../images/user.svg") no-repeat 10px 11px;
      background-size: 24px;
    }
    
    input[type="password"] {
      background: url("../images/key.svg") no-repeat 8px 9px;
      background-size: 28px;
    }
    
    .container span {
      font-size: 16px;
      color: #fff;
      float: left;
      width: 32%;
      margin-top: 8px;
    }
    
    .container h6 {
      font-size: 16px;
      float: right;
      width: 37%;
      color: #fff;
      letter-spacing: 1px;
      margin-top: 8px;
      text-decoration: underline;
    }
    
    .container a {
      color: #fff;
      transition: 0.5s all;
      -webkit-transition: 0.5s all;
      -o-transition: 0.5s all;
      -moz-transition: 0.5s all;
      -ms-transition: 0.5s all;
    }
    
    .container a:hover {
      color: rgba(208, 95, 216, 0.9);
      transition: 0.5s all;
      -webkit-transition: 0.5s all;
      -o-transition: 0.5s all;
      -moz-transition: 0.5s all;
      -ms-transition: 0.5s all;
    }
    .clear {
      clear: both;
    }
    input[type="submit"] {
      padding: 12px 38px;
      font-size: 1px;
      text-transform: uppercase;
      letter-spacing: 2px;
      background: #003b64;
      color: white;
      border: none;
      outline: none;
      cursor: pointer;
    
      margin: 45px auto 31px;
      transition: 0.5s all;
      -webkit-transition: 0.5s all;
      -o-transition: 0.5s all;
      -moz-transition: 0.5s all;
      -ms-transition: 0.5s all;
    }
    
    input[type="submit"]:hover {
      background: rgba(213, 38, 133, 0.64);
      transition: 0.5s all;
      -webkit-transition: 0.5s all;
      -o-transition: 0.5s all;
      -moz-transition: 0.5s all;
      -ms-transition: 0.5s all;
    }
    
    .container p a {
      text-transform: uppercase;
      font-size: 18px;
      text-decoration: underline;
      letter-spacing: 1px;
      color: #fff;
      padding: 10px;
    }
    
    .container p {
      font-size: 17px;
      color: #fff;
    }
    
    footer p {
      margin: 4em 0em;
      color: #fff;
      font-size: 15px;
      font-weight: 300;
      letter-spacing: 2px;
    }
    
    footer a {
      color: rgba(208, 95, 216, 0.9);
    }
    
    footer a:hover {
      color: rgba(19, 129, 206, 0.82);
      text-decoration: underline;
    }
    
    @media (max-width: 1440px) {
      .container {
        width: 28%;
      }
    }
    
    @media (max-width: 1366px) {
      .container {
        width: 30%;
      }
    }
    
    @media (max-width: 1280px) {
      .container {
        width: 33%;
      }
    
      .agileheader h1 {
        font-size: 41px;
      }
    
      .container h2 {
        font-size: 27px;
      }
    }
    
    @media (max-width: 1080px) {
      .container {
        width: 49%;
      }
    }
    
    

    css/style.css

    html,
    body {
      overflow-x: hidden !important;
      -webkit-font-smoothing: antialiased;
      min-height: 100%;
      background: #f1f2f7;
    }
    a {
      color: #3c8dbc;
    }
    .right-side,
    .left-side {
      min-height: 100%;
      display: block;
    }
    
    .right-side {
      background-color: #f1f2f7;
      margin-left: 220px;
    }
    .left-side {
      position: absolute;
      width: 220px;
      top: 0;
    }
    
    @media screen and (min-width: 992px) {
      .left-side {
        top: 50px;
      }
    
      .right-side.strech {
        margin-left: 0;
      }
      .right-side.strech > .content-header {
        margin-top: 0px;
      }
      .left-side.collapse-left {
        left: -220px;
      }
    }
    
    .content {
      padding: 20px 15px;
      background: #f0f3f4;
      overflow: auto;
    }
    
    img {
      max-width: 100% !important;
    }
    
    .badge-success {
      background-color: #27c24c;
      color: #dff5e4;
    }
    
    .badge-info {
      background-color: #23b7e5;
      color: #e3f6fc;
    }
    .badge-danger {
      background-color: #f05050;
      color: #fae6e6;
    }
    
    body > .header .navbar {
      height: 50px;
      margin-bottom: 0;
      margin-left: 220px;
    }
    body > .header .logo {
      float: left;
      font-size: 20px;
      line-height: 50px;
      text-align: center;
      padding: 0 10px;
      width: 220px;
      font-weight: 500;
      height: 50px;
      display: block;
    }
    .user-panel {
      padding: 10px;
    }
    .user-panel:before,
    .user-panel:after {
      display: table;
      content: " ";
    }
    .user-panel:after {
      clear: both;
    }
    .user-panel > .image > img {
      width: 45px;
      height: 45px;
    }
    
    @media screen and (max-width: 992px) {
      .relative {
        position: relative;
      }
      body.fixed .sidebar-offcanvas {
        margin-top: 50px;
        left: -220px;
      }
      body.fixed .row-offcanvas-left.active .navbar {
        left: 220px !important;
        right: 0;
      }
      body.fixed .row-offcanvas-left.active .sidebar-offcanvas {
        left: 0px;
      }
    }
    
    .skin-black .navbar {
      background-color: #ffffff;
      border-bottom: 1px solid #eee;
    }
    .skin-black .navbar .nav a {
      color: #333333;
    }
    
    .skin-black .logo {
      background-color: #283744;
      color: #f9f9f9;
    }
    .skin-black .logo > a {
      color: #f9f9f9;
    }
    .skin-black .right-side > .content-header {
      background: #fff;
      box-shadow: none;
    }
    .skin-black .user-panel > .image > img {
      border: 1px solid #444;
    }
    .skin-black .user-panel > .info,
    .skin-black .user-panel > .info > a {
      color: #eee;
    }
    .skin-black .sidebar {
      border-bottom: 1px solid #39435c;
    }
    .skin-black .sidebar > .sidebar-menu > li > .treeview-menu {
      margin: 0 1px;
      background: #35404d;
    }
    .skin-black .left-side {
      background: #39435c;
      padding-top: 20px;
    }
    .skin-black .sidebar a {
      color: #eee;
    }
    .sm-st {
      background: #fff;
      padding: 20px;
      -webkit-border-radius: 3px;
      -moz-border-radius: 3px;
      border-radius: 3px;
      margin-bottom: 20px;
      -webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
      box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
    }
    .sm-block-icon {
      width: 60px;
      height: 60px;
      line-height: 60px;
      text-align: center;
      font-size: 30px;
      background: #eee;
      -webkit-border-radius: 5px;
      -moz-border-radius: 5px;
      border-radius: 5px;
      float: left;
      margin-right: 10px;
      color: #fff;
    }
    .sm-block-info {
      font-size: 12px;
      padding-top: 2px;
    }
    .sm-block-info span {
      display: block;
      font-size: 24px;
      font-weight: 600;
    }
    .stat-elem {
      background-color: #fff;
      padding: 18px;
      border-radius: 40px;
    }
    
    .stat-info {
      text-align: center;
      background-color: #fff;
      border-radius: 5px;
      margin-top: -5px;
      padding: 8px;
      -webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
      box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
      font-style: italic;
    }
    
    .stat-icon {
      text-align: center;
      margin-bottom: 5px;
    }
    
    .block-red {
      background-color: #f05050;
    }
    .block-green {
      background-color: #27c24c;
    }
    .block-violet {
      background-color: #7266ba;
    }
    .block-blue {
      background-color: #23b7e5;
    }
    
    #sidebarmenu {
      margin-top: 20px;
      line-height: 20px;
    }
    
    #sidebarmenu li {
      color: #fff;
      line-height: 40px;
    }
    #sidebarmenu ul {
      padding: 0 20px;
    }
    .pull-left.info {
      margin-left: 20px;
    }
    
    

    五、完成

    js/auth.js

    /**
     * @param {*} menuList 传入的数据
     * @return {*} menus 转化后的树形结构数据,auths 转化后的权限列表数组
     */
    
    const getMenuListAndAuth = (menuList) => {
      // TODO:待补充代码
      const auths = dealUserAuths(menuList)
      const menus = dealUserMenu(menuList)
      
      return { menus, auths }; // menus 转化后的树形结构数据,auths 转化后的权限列表数组
    
    };
    function dealUserMenu(users,rootId=-1){
      let newArr=[]
      users.forEach(item=>{
        if(rootId==item.parentId){
          newArr.push(item)
          item.children=dealUserMenu(users,item.id)
        }
      })
      return newArr
    }
    function dealUserAuths(users){
      let newArr=[]
      users.forEach(item=>{
        newArr.push(item.auth)
      })
      return newArr
    }
    

    你可能感兴趣的:(javaScript,javascript,蓝桥杯,java)