最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

1. 简单版

来源:博客园


(资料图片仅供参考)

1.组件简介

该版本开发速度较快,项目业务内容固定的场景

  • 用户的角色固定
  • 角色对应的权限固定

2. 设计思路

  • 确定所有的角色:管理员,财务,审核员
  • 确定每个角色具备的权限

2.1 前端

  • 登录,选择角色登录,vuex中保存用户的角色和token
  • 根据登录的角色,动态加载菜单
    • 在路由中定义is_menu和role字段,来判断该路由是否为菜单和能显示的角色
    • {        path: "/front",        name: "Front",        component: () => import("../views/FrontView"),        meta:{            is_menu:true,            roles:["manager", "admin"]        }    },
  • 用户是否访问某一个页面
    • 通过路由的导航守卫来实现
    • 基于vuex中的角色。判断该角色是否能访问对应的路由
  • 页面中的局部功能,如增删改查
    • 按钮的展示:根据vuex中的角色判断是否展示v-if
      新建
    • 功能: 角色只有有对应的权限,才允许发送ajax请求,我们也可以进行角色权限的判定
      if(has_permission("admin", "manager")){  }else{  }  

2.2 后端

  • 用户登录,生成token返回
  • 再次请求,根据认证组件,判定token,是否登陆成功
  • 权限的校验,根据当前登录的角色,和token中的权限进行判断
    • 我们可以在每一个视图函数中判断权限
    • 也可以使用drf中的权限组件进行判断 + 配置文件中的权限配置
  • api的实现

3. 项目的实现

3.1 前端

页面展示效果

部分后端数据通过模拟实现

  • 登录页面的实现
    <script setup>import {reactive} from "vue";import {useStore} from "vuex";import {useRouter} from "vue-router";const router = useRouter()const store = useStore()const state = reactive({  form: {    role: "管理员",    username: "cisco",    password: "123"  },  options: [    {title: "管理员", value: "manager"},    {title: "财务", value: "caiwu"},    {title: "运维", value: "yunwei"},  ]})function onSubmit() {//  1. 向后端发送登录请求//  2. 接收后端响应数据  const context = {    role: state.form.role,    token: "9a81a00f-fe88-4c4b-ad2d-68cd17dceb4a"  }//  3. 保存在vuex中  store.commit("login", context)//  4.页面跳转  router.push({name: "basic"})}</script>
  • vuex的实现,用于保存用户登录数据
    import {createStore} from "vuex"export default createStore({    state: {        token: localStorage.getItem("token") || "",        role: localStorage.getItem("role") || "",    },    getters: {},    mutations: {        login(state, {token, role}) {            state.token = token            state.role = role            localStorage.setItem("token", token)            localStorage.setItem("role", role)        }    },    actions: {},    modules: {}})
  • 路由的编写
    • 确定路由是否为菜单
    • 确定路由能够访问的角色
    • 菜单名字
    • 路由导航守卫的编写
      import {createRouter, createWebHistory} from "vue-router"import store from "@/store";const routes = [    {        path: "/login",        name: "login",        component: () => import("../views/LoginView.vue")    },    {        path: "/admin",        name: "admin",        component: () => import("../views/AdminView.vue"),        children: [            {                path: "basic",                name: "basic",                component: () => import("../views/admin/BasicView.vue"),                meta: {                    role: ["manager", "caiwu", "yunwei"],                    is_menu: true,                    title: "基本信息",                }            },            {                path: "user",                name: "user",                component: () => import("../views/admin/UserView.vue"),                meta: {                    role: ["manager", "yunwei"],                    is_menu: true,                    title: "用户管理",                }            },            {                path: "role",                name: "role",                component: () => import("../views/admin/RoleView.vue"),                meta: {                    role: ["manager", "caiwu"],                    is_menu: true,                    title: "角色管理"                }            }        ]    }]const router = createRouter({    history: createWebHistory(process.env.BASE_URL),    routes})router.beforeEach((to, from, next) => {    console.log(to)    if (to.meta.role) {        const role = store.state.role        console.log(role)        if (to.meta.role.indexOf(role) === -1) {            router.push({name: "login"})        } else {            next()        }    } else {        next()    }})export default router
  • 按钮的展示
    • 添加,删除和编辑三个按钮同过角色来进行确定是否渲染在页面
    • 自定义has_permission函数
      <script setup>import {reactive} from "vue";import store from "@/store";const state = reactive({  tableData: [    {      name: "张三",      age: 16,      address: "上海市"    }  ]})function hasPermission(roleList) {  const role = store.state.role  if (roleList.indexOf(role) !== -1) {    return true  }}</script>

前端就可以动态的显示菜单和按钮

  • 管理员身份
  • 运维身份

3.2 后端

假设有一个学生表,我们对学生表进行操作

  • 模型类
    from django.db import models# Create your models here.class User(models.Model):    username = models.CharField(verbose_name="用户名", max_length=32)    password = models.CharField(verbose_name="密码", max_length=32)    role_choice = ((1, "admin"), (2, "caiwu"), (3, "yunwei"))    role = models.SmallIntegerField(verbose_name="角色", choices=role_choice, default=1)class Student(models.Model):    username = models.CharField(verbose_name="用户名", max_length=32)    age = models.SmallIntegerField(verbose_name="年龄")    address = models.CharField(verbose_name="住址", max_length=32)
  • 路由
    from django.contrib import adminfrom django.urls import pathfrom rest_framework import routersfrom api import viewsrouter = routers.SimpleRouter()router.register("api/student", viewset=views.StudentView, basename="student")urlpatterns = [    path("admin/", admin.site.urls),]urlpatterns += router.urls
  • 认证
    class User:    def __init__(self, name=None, role=None):        self.name = name        self.role = roleclass MineAuthentication(BaseAuthentication):    def authenticate(self, request):        token = request.query_params.get("token")        if not token:            raise AuthenticationFailed("认证失败")        role = request.query_params.get("role")        user = User("xxx", role)        return (user, token)    def authenticate_header(self, request):        return "API"
  • 权限
    class MinePermission(BasePermission):    def has_permission(self, request, view):        """        判断角色是否有对应的权限        :param request:        :param view:        :return:        """        role = request.user.role        permission_dict = settings.PERMISSIONS.get(role)        request_method = request.method        request_name = request_method.reslover_match.url_name        if not permission_dict:            return False        method_list = permission_dict[request_name]        if method_list and request_method in method_list:            return True        return False
  • 视图
    class StudentView(ModelViewSet):    queryset = models.Student.objects.all()    serializer_class = StudentModelSerializers    authentication_classes = [MineAuthentication, ]    permission_classes = [MinePermission, ]
  • 配置文件
    PERMISSIONS = {    "manager": {        "student-detail": ["GET", "POST"],        "student-list": ["GET", "POST", "PATCH", "DELETE", "PUT"],    },    "caiwu": {        "student-detail": ["GET", "POST"],    },    "yunwei": {        "student-detail": ["GET", "POST"],        "student-list": ["GET", ]    }}REST_FRAMEWORK = {    "UNAUTHENTICATED_USER": None,    "UNAUTHENTICATED_TOKEN": None,}

关键词: 进行判断 基本信息 配置文件