【前端】系统

App.vue

<template>
  <router-view></router-view>
</template>

<script setup>
</script>

<style scoped>
</style>

main.js

// import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'
import directives from "@/directives";

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.use(directives)

app.mount('#app')

views/LoginView.vue

<template>
  <h1>用户登录</h1>
  <div>
    <input type="text" placeholder="用户名" v-model="state.username">
  </div>
  <div>
    <input type="text" placeholder="密码" v-model="state.password">
  </div>
  <button @click="doLogin">登录</button>
</template>

<script setup>
import {reactive, ref} from "vue";
import {userInfoStore} from "@/stores/counter.js";
import {useRouter} from 'vue-router'

const store = userInfoStore()
const router = useRouter()

const state = reactive({
  username: "root",
  password: "123"
})

function doLogin(){
  // 1. 向后端发送请求登录
  // 2. 登陆成功
  let response = {
    token: "djfjwb-kfj-dsjvn",
    username: "root",
    role: "admin",
    permission: {
      "user-list": ["get", "post"],
      "user-detail": ["get", "post", "put", "delete"],
      "info-list": ["get", "post"]
    }
  }
  // 3. 保存到localstorage和内存中
  store.doLogin(response)
  // 4. 重定向
  router.push({name:"home"})
}
</script>

<style scoped>

</style>

views/AdminView.vue

<template>
  <!--  <router-link :to="{name:'home'}">首页</router-link>-->
  <!--  |-->
  <!--  <router-link :to="{name:'user'}">用户中心</router-link>-->
  <!--  |-->
  <!--  <router-link :to="{name:'info'}">信息管理</router-link>-->
  <!--  |-->
  <!--  <router-link :to="{name:'video'}">视频管理</router-link>-->
  <router-link v-for="item in menuRouterList" :to="{name:item.name}">{{ item.meta.title }}</router-link>

  <router-view></router-view>
</template>

<script setup>
import {useRouter} from "vue-router"
import {computed} from "vue";
import {userInfoStore} from "@/stores/counter.js";

const router = useRouter()
const store = userInfoStore()

const menuRouterList = computed(() => {
  // 1、获取所有路由
  let totalRouterList = router.getRoutes()
// 2、删选出isMenu=true
  return totalRouterList.filter((item) => {
    let userRole = store.userRole
    if (item.meta.isMenu && item.meta.role.indexOf(userRole) !== -1) {
      return true
    }
  })
})


</script>

<style scoped>

</style>

views/admin/InfoView.vue

<template>
  <h1>信息管理</h1>
  <div>
    <button v-if="hasPermission(['admin','manager', 'user'])">新增</button>
    <button v-if="hasPermission(['admin','manager'])">编辑</button>
    <button v-if="hasPermission(['admin','manager'])">删除</button>
  </div>

  <div>
    <button v-if="hasPermission2('info-list','post')">新增2</button>
    <button v-if="hasPermission2('info-detail','put')">编辑2</button>
    <button v-if="hasPermission2('info-detail','delete')">删除2</button>
  </div>

  <div>
    <button v-per="['admin','manager', 'user']">新增</button>
    <button v-per="['admin','manager']">编辑</button>
    <button v-per="['admin','manager']">删除</button>
  </div>

  <div>
    <button v-per2="['info-list','post']">新增2</button>
    <button v-per2="['info-detail','put']">编辑2</button>
    <button v-per2="['info-detail','delete']">删除2</button>
  </div>
</template>

<script setup>
import {hasPermission, hasPermission2} from "@/stores/permission.js"
</script>

<style scoped>

</style>

stores/counter.js

import {ref, computed} from 'vue'
import {defineStore} from 'pinia'

export const userInfoStore = defineStore('counter', () => {
    const userString = ref(localStorage.getItem("userInfo") || null)
    const userDict = computed(() => userString.value ? JSON.parse(userString.value) : null)
    const userToken = computed(() => userDict.value ? userDict.value.token : null)
    const userRole = computed(() => userDict.value ? userDict.value.role : null)
    const userPermission = computed(() => userDict.value ? userDict.value.permission : null)

    function doLogin(userInfo) {
        // 放到内存
        userString.value = JSON.stringify(userInfo)
        // 写入LocalStorage
        localStorage.setItem("userInfo", JSON.stringify(userInfo))
    }

    return {userPermission, userString, userToken, userRole, doLogin}
})

stores/permission.js

import {userInfoStore} from "@/stores/counter.js";

const store = userInfoStore()

export function hasPermission(allowRoleList) {
    return allowRoleList.indexOf(store.userRole) !== -1
}

export function hasPermission2(name, method) {
    const methodList = store.userPermission[name]
    if (!methodList) {
        return false;
    }
    return methodList.indexOf(method) !== -1;
}

router/index.js

import {createRouter, createWebHistory} from 'vue-router'
import {userInfoStore} from "@/stores/counter.js"

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/',
            component: () => import('../views/AdminView.vue'),
            children: [
                {
                    path: 'home',
                    name: 'home',
                    component: () => import('../views/admin/HomeView.vue'),
                    meta: {isMenu: true, title: "首页", role: ["admin", "manager", "user"]}
                },
                {
                    path: 'user',
                    name: 'user',
                    component: () => import('../views/admin/UserView.vue'),
                    meta: {isMenu: true, title: "用户管理", role: ["admin", "manager"]}
                },
                {
                    path: 'info',
                    name: 'info',
                    component: () => import('../views/admin/InfoView.vue'),
                    meta: {isMenu: true, title: "信息管理", role: ["admin", "manager","user"]}
                },
                {
                    path: 'video',
                    name: 'video',
                    component: () => import('../views/admin/VideoView.vue'),
                    meta: {isMenu: true, title: "视频管理", role: ["admin", "user"]}
                },
            ]
        },
        {
            path: '/login',
            name: 'login',
            component: () => import('../views/LoginView.vue'),
        },
    ],
})

router.beforeEach((to, from, next) => {
    if (to.name === "login") {
        next()
        return;
    }
    const info = userInfoStore()
    if (!info.userToken) {
        next({"name": "login"})
        return;
    }
    next()
})

export default router

directives/index.js

import per from './per'
import per2 from './per2'

const directives = {
    per,
    per2,
}

export default {
    install(Vue) {
        Object.keys(directives).forEach(key => {
            Vue.directive(key, directives[key])
        })
    }
}

directives/per.js

import {userInfoStore} from "@/stores/counter.js";

export default {
    mounted(element, bindings) {
        let allowRoleList = bindings.value
        let store = userInfoStore()
        if (allowRoleList.indexOf(store.userRole) === -1) {
            element.parentNode && element.parentNode.removeChild(element)
        }
    }
}

directives/per2.js

import {userInfoStore} from "@/stores/counter.js";

export default {
    mounted(element, bindings) {
        let [name, method] = bindings.value
        const store = userInfoStore()
        const methodList = store.userPermission[name]

        if (!methodList) {
            element.parentNode && element.parentNode.removeChild(element)
            return
        }
        if (methodList.indexOf(method) === -1) {
            element.parentNode && element.parentNode.removeChild(element)
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值