为了进一步实现上面提到的动态路由功能,并且加入对每个路由的权限控制(即增、删、改、查按钮的权限控制),我们需要对数据库、后端接口、前端的设计做一些改进和扩展。下面我将详细描述如何在现有方案的基础上加入对路由的增、删、改、查权限控制。
目录
- 一、数据库设计扩展
- 1.1 修改路由表(routes)
- 1.2 修改角色与路由权限表(role_routes)
- 二、后端接口设计
- 2.1 修改获取路由接口
- 2.2 添加路由权限的接口
- 三、前端实现
- 3.1 动态生成路由
- 3.2 根据权限动态显示按钮
- 3.3 在Vuex中存储用户权限
- 四、总结
一、数据库设计扩展
为了实现更细粒度的权限控制,我们需要对数据库结构做一些修改和扩展,增加对路由权限的支持。每个路由会关联四个权限:增、删、改、查。
1.1 修改路由表(routes)
首先,我们要扩展路由表,使其支持每个路由的增、删、改、查权限。
CREATE TABLE routes (
id INT AUTO_INCREMENT PRIMARY KEY,
path VARCHAR(255) NOT NULL,
component VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
parent_id INT DEFAULT 0,
meta JSON DEFAULT NULL,
is_enabled BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- 增、删、改、查权限
permission_create BOOLEAN DEFAULT FALSE,
permission_delete BOOLEAN DEFAULT FALSE,
permission_update BOOLEAN DEFAULT FALSE,
permission_view BOOLEAN DEFAULT TRUE
);
permission_create
:该路由是否具有增权限。permission_delete
:该路由是否具有删权限。permission_update
:该路由是否具有改权限。permission_view
:该路由是否具有查权限。
1.2 修改角色与路由权限表(role_routes)
在role_routes
表中,新增字段来存储角色对路由的权限,分别对应增、删、改、查。
CREATE TABLE role_routes (
role_id INT,
route_id INT,
permission_create BOOLEAN DEFAULT FALSE,
permission_delete BOOLEAN DEFAULT FALSE,
permission_update BOOLEAN DEFAULT FALSE,
permission_view BOOLEAN DEFAULT TRUE,
PRIMARY KEY (role_id, route_id),
FOREIGN KEY (role_id) REFERENCES roles(id),
FOREIGN KEY (route_id) REFERENCES routes(id)
);
- 每条记录表示角色对某个路由的权限。
二、后端接口设计
在后端,我们需要确保路由的增、删、改、查权限在获取路由数据时被正确地返回,并且在路由的操作(如添加、删除、修改、查看)时进行权限控制。
2.1 修改获取路由接口
修改/api/get_routes
接口,增加对路由权限的支持,返回每个路由的增、删、改、查权限信息。
@app.route('/api/get_routes', methods=['GET'])
def get_routes():
role_name = request.args.get('role')
role = Role.query.filter_by(name=role_name).first()
if not role:
return jsonify({'message': 'Role not found'}), 404
routes = db.session.query(Route).join(RoleRoute).filter(RoleRoute.role_id == role.id).all()
routes_data = []
for route in routes:
role_route = RoleRoute.query.filter_by(role_id=role.id, route_id=route.id).first()
routes_data.append({
'path': route.path,
'component': route.component,
'name': route.name,
'meta': route.meta,
'permissions': {
'create': role_route.permission_create,
'delete': role_route.permission_delete,
'update': role_route.permission_update,
'view': role_route.permission_view
}
})
return jsonify(routes_data)
在这个接口中,我们通过RoleRoute
表来获取每个角色对应的路由权限,并将这些权限一起返回。
2.2 添加路由权限的接口
我们还需要提供一个接口来修改路由权限(即为角色设置增、删、改、查权限)。
@app.route('/api/set_route_permissions', methods=['POST'])
def set_route_permissions():
data = request.json
role_id = data['role_id']
route_id = data['route_id']
permission_create = data['permission_create']
permission_delete = data['permission_delete']
permission_update = data['permission_update']
permission_view = data['permission_view']
role_route = RoleRoute.query.filter_by(role_id=role_id, route_id=route_id).first()
if not role_route:
role_route = RoleRoute(role_id=role_id, route_id=route_id)
db.session.add(role_route)
role_route.permission_create = permission_create
role_route.permission_delete = permission_delete
role_route.permission_update = permission_update
role_route.permission_view = permission_view
db.session.commit()
return jsonify({'message': 'Permissions updated successfully'})
该接口接收角色ID、路由ID以及增、删、改、查权限的设置,并更新数据库中的权限数据。
三、前端实现
前端需要根据从后端接口获取的路由信息和权限数据,动态生成路由,并根据权限来控制不同路由下按钮的显示与操作权限。
3.1 动态生成路由
前端的路由配置需要动态加载,并在路由生成时判断当前用户对该路由的权限。
在router/index.js
中,我们可以根据权限信息来配置动态路由。
import Vue from 'vue';
import Router from 'vue-router';
import store from '../store';
Vue.use(Router);
const router = new Router({
routes: []
});
function generateRoutes(routes) {
const routeArray = [];
routes.forEach(route => {
const routeConfig = {
path: route.path,
name: route.name,
component: () => import(`@/views/${route.component}.vue`), // 动态加载组件
meta: route.meta,
permissions: route.permissions // 保存权限数据
};
if (route.children && route.children.length > 0) {
routeConfig.children = generateRoutes(route.children);
}
routeArray.push(routeConfig);
});
return routeArray;
}
router.beforeEach(async (to, from, next) => {
if (!store.state.routes.length) {
const res = await store.dispatch('getRoutes');
const routes = generateRoutes(res);
routes.forEach(route => {
router.addRoute(route);
});
next({ ...to, replace: true });
} else {
next();
}
});
export default router;
3.2 根据权限动态显示按钮
前端页面上的操作按钮(如增、删、改、查)需要根据用户对路由的权限来进行显示和隐藏。假设每个页面都有这些按钮,我们可以使用v-if
指令来根据权限控制显示与否。
<template>
<div>
<button v-if="hasCreatePermission">新增</button>
<button v-if="hasUpdatePermission">编辑</button>
<button v-if="hasDeletePermission">删除</button>
<button v-if="hasViewPermission">查看</button>
</div>
</template>
<script>
export default {
computed: {
hasCreatePermission() {
return this.$store.state.userPermissions.create;
},
hasUpdatePermission() {
return this.$store.state.userPermissions.update;
},
hasDeletePermission() {
return this.$store.state.userPermissions.delete;
},
hasViewPermission() {
return this.$store.state.userPermissions.view;
}
},
created() {
this.setPermissions(this.$route.meta.permissions);
},
methods: {
setPermissions(permissions) {
this.$store.commit('setUserPermissions', permissions);
}
}
}
</script>
在这个组件中,我们使用v-if
指令根据权限来显示对应的按钮。hasCreatePermission
、hasUpdatePermission
等计算属性返回当前用户对该页面的权限,setPermissions
方法会在页面加载时设置当前用户的权限。
3.3 在Vuex中存储用户权限
在Vuex中,我们可以存储用户的权限数据,并在不同的组件中访问。
// store.js
export default new Vuex.Store({
state: {
userPermissions: {
create: false,
delete: false,
update: false,
view: true
}
},
mutations: {
setUserPermissions(state, permissions) {
state.userPermissions = permissions;
}
},
actions: {
async getRoutes({ commit }) {
const res = await axios.get('/api/get_routes', { params: { role: 'admin' } });
commit('setRoutes', res.data);
return res.data;
}
}
});
四、总结
通过以上的设计和实现,我们能够在前端根据路由和权限动态生成路由,并且为每个路由设置增、删、改、查等操作的权限。后端负责根据用户的角色返回对应的权限信息,前端通过vue-router
和vuex
管理动态路由和用户权限。通过这种方式,系统可以灵活地根据角色和权限来展示不同的功能,并且有效地控制用户对数据的操作权限。
这种设计方式非常适合复杂权限管理的系统,能够提供细粒度的权限控制,并且可以随着业务需求的变化灵活调整。