阅读 38

马艳泽-智能生活,系列一(菜单篇)

完整项目地址:

前端:gitee.com/mayanze123/…

后端:gitee.com/mayanze123/…

最终效果:

image.png

一、数据库

本着以用户为基准而不是角色,所以菜单数据库表,我分了3个部分,其中菜单有一些是公共菜单,所以加了公共属性区分:

1.用户


-- Table structure for user


DROP TABLE IF EXISTS user; CREATE TABLE user ( id varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, open_id varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '绑定微信ID', name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '用户名', sex int(255) NULL DEFAULT 1 COMMENT '性别:1:男,2:女', phone varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '电话', photo varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '照片', email varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '邮箱', create_time datetime(0) NULL DEFAULT NULL COMMENT '创建时间', remarks varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '备注', PRIMARY KEY (id) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '用户表' ROW_FORMAT = Dynamic;

2.菜单


-- Table structure for menu


DROP TABLE IF EXISTS menu; CREATE TABLE menu ( id varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, pId varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '父阶ID', icon varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '图标', name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '菜单名称', url varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '菜单地址', sn float(255, 2) NULL DEFAULT NULL COMMENT '排序', public int(1) NULL DEFAULT 0 COMMENT '0: 公共菜单,1:私有菜单', PRIMARY KEY (id) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

3.用户-菜单关系表


-- Table structure for user_menu


DROP TABLE IF EXISTS user_menu; CREATE TABLE user_menu ( id varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, user_id varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '用户ID', menu_id varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '菜单ID', PRIMARY KEY (id) USING BTREE, INDEX fk_user_userMenu(user_id) USING BTREE, INDEX fk_menu_userMenu(menu_id) USING BTREE, CONSTRAINT fk_menu_userMenu FOREIGN KEY (menu_id) REFERENCES menu (id) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT fk_user_userMenu FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

二、前端

1.前端使用的是 PanJiaChen 大神的vue-element-admin,想要改为动态菜单,主要需要改两个.js文件/src/permission.js; /src/store/modules/permission.js

2./src/permission.js 修改如下

image.png

3./src/store/modules/permission.js 修改如下,加入了generateMyRoutes方法(实力有限,写的比较繁琐,但是可以参考参考)

generateMyRoutes({ commit }, menus) {
    return new Promise(resolve => {
      const accessedRoutes = buildAsyncRoutes(menus)
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
复制代码

buildAsyncRoutes(menus) 方法

/**
 * 要求数据,符合如下要求,
 * 为什么首页两个呢,是这样设计的,菜单必须于代码目录严格对应,父级别首页,
 * 对应于首页代码放的目录dashboard,子级别首页对应具体vue index;实际目录就是dashboard/index.vue(菜单中,子节点只有一个的不显示父节点)
 * 
 * 房屋管理url 是house/index,对应父级别生活url为live;所以房屋管理实际代码目录就是 live/house/index
 * <p>
 * [{
	"children": [{
		"children": [],
		"name": "首页",
		"pId": "1",
		"id": "home",
		"url": "index"
	}],
	"name": "首页",
	"pId": "0",
	"id": "1",
	"url": "dashboard"
},{
	"children": [{
		"children": [],
		"name": "房屋管理",
		"pId": "live",
		"id": "live_1",
		"url": "house/index"
	}, {
		"children": [],
		"name": "账单管理",
		"pId": "live",
		"id": "live_2",
		"url": "bill"
	}],
	"name": "生活",
	"pId": "0",
	"id": "live",
	"url": "live"
}]
 * </p>
 * @param menus 菜单数据
 * @returns 
 */
export function buildAsyncRoutes(menus) {
  debugger
  const res = []
  menus.forEach(menu => {
    const tmp = {
      path: '/' + menu.url,
      component: Layout,
      meta: {
        title: menu.name,
        icon: menu.icon
      }
    }
    if (menu.children && menu.children.length > 0) {
      handleChildren(menu, tmp)
    } else {
      // 如果个别页面没有父界别目录走这个,因为必须在外面套一个Layout组件否则无法显示菜单等框架元素
      // const path = '@/' + menu.url
      tmp.children = []
      tmp.children.push({
        path: '',
        // component: () => import(path),
        component(resolve) {
          require(['@/views/' + menu.url], resolve)
        },
        meta: {
          title: menu.name,
          icon: menu.icon
        }
      })
    }
    res.push(tmp)
  })

  // 404 page must be placed at the end !!!
  const page404 = { path: '*', redirect: '/404', hidden: true }
  res.push(page404)

  return res
}
复制代码

handleChildren(menu, tmp) 方法

function handleChildren(menu, tmp, isChildren) {
  const children = []
  menu.children.forEach(child => {
    const tmpc = {
      path: child.url,
      component: Layout,
      meta: {
        title: child.name,
        icon: child.icon
      }
    }
    children.push(tmpc)

    if (child.children && child.children.length > 0) {
      handleChildren(child, tmpc, true)
    } else {
      tmpc.component = resolve => require.ensure([], () => resolve(require('@/views/' + menu.url + '/' + child.url)))
    }
  })
  tmp['children'] = children
}
复制代码
文章分类
代码人生
文章标签