赞
踩
模块名 | 说明 |
views | 页面 |
stores | pinia全局状态管理 |
router | 路由 |
request | axios请求封装 |
modules | 模块数据格式封装 |
directive | 自定义指令 |
components | 组件 |
- //导入axios
- import axios from "axios";
- import type{ AxiosInstance, AxiosResponse, InternalAxiosRequestConfig, AxiosRequestConfig,AxiosError } from "axios"
- //element-plus 弹窗
- import { ElMessage } from 'element-plus'
- //响应结果类型
- import type{result} from '@/modules/base/Base.ts'
- //导入路由对象
- import router from '@/router/index'
- //导入token状态管理
- import {useUserInfoStore} from '@/stores/UserInfo'
- //根路径
- export const config={
- baseURL: 'http://localhost:9001',
- timeout: 10000,
- headers:{
- 'Content-Type':'application/json'
- }
- }
-
- //请求类
- export class HttpBase{
- // axios的实例
- private instance: AxiosInstance;
- // 初始化的作用
- constructor(configs: AxiosRequestConfig) {
- // 创建axios的实例
- this.instance = axios.create(configs)
- // 配置拦截器
- this.interceptors()
- }
- private interceptors() {
- // 拦截请求
- this.instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
- //获取token
- const token=useUserInfoStore().getToken
- if(token){
- config.headers.token=token
- }
- return config
- }), (error: any) => {
- error.data = {}
- error.data.message = '服务器异常请联系管理员'
- return error
- }
- // 拦截响应
- this.instance.interceptors.response.use((res: AxiosResponse) => {
- //获取token
- const token=res.headers.token;
- if(token){
- useUserInfoStore().setToken(token)
- }
- // 这里面可以做一些接口返回状态的判断
- //执行成功返回状态码以2开头,主要作用对于修改成功、新增成功等操作的消息提醒
- if ( /^2/.test(res.data.code)) {
- if(res.data.code!=200){
- ElMessage.success(res.data.message)
- }
- return Promise.resolve(res.data)
- } else {
- //执行异常的消息提醒
- ElMessage.error(res.data.message)
- return Promise.reject(res.data.message || '接口报错')
- }
- },(error: AxiosError) => {
- if(error.code==="ERR_NETWORK"){
- ElMessage.error('请检查您的网络')
-
- }else{
- const status=error.response.status;
- HttpBase.errorHandle(status)
- }
-
- return Promise.reject(error)
- })
- }
- // 下面是对几个请求方式的封装
- // post
- protected post<T = result>(url: string, data?: object): Promise<T> {
- return this.instance.post(url, data)
- }
- //put
- protected put<T = result>(url: string, data?: object): Promise<T> {
- return this.instance.put(url, data)
- }
- // get
- protected get<T = result>(url: string, params?: object): Promise<T> {
- return this.instance.get(url, { params })
- }
- // delete
- protected delete<T = result>(url: string): Promise<T> {
- return this.instance.delete(url)
- }
- // 图片上传
- protected upload<T = result>(url: string, params?: object): Promise<T> {
- return this.instance.post(url, params, {
- headers: {
- 'Content-Type': 'multipart/form-data'
- }
- })
- }
- private static errorHandle(status:number) {
- // 状态码判断
- switch (status) {
- case 404:
- router.push('/404')
- break
- case 500:
- router.push('/500')
- break
- default:
- }
- }
- }
- import {HttpBase,config} from '@/request/base/index'
- import type{ListMenu} from '@/modules/menu/MenuInfo'
- // axios的配置项
- const BaseUrl=config.baseURL+'/auth/menu'
-
- class HttpMenu extends HttpBase{
- /**
- * 获取用户可访问权限
- * @returns
- */
- async getMenuByUser():Promise<Array<ListMenu>>{
- //获取用户可访问菜单
- const url=BaseUrl+'/getMenuByUserId'
- return (await super.get(url)).data
- }
- }
- export default new HttpMenu(config);
- import type{BaseModule} from '@/modules/base/Base'
- interface ListMenu extends BaseModule{
- menuName:string,//菜单名称
- menuCode:string,//菜单编码
- parentId:number,//菜单父id
- routerPath:string,//路由地址
- componentPath:string,//组件所在位置
- menuType:number,//菜单类型
- authorityCode:string,//权限编码
- requestUrl:string,//请求路径
- children:Array<ListMenu>//子级
- icon:string//菜单图标
-
- }
-
-
- export type{ListMenu}
- import { defineStore } from 'pinia'
- import {computed, reactive, ref} from 'vue'
- import type{ListMenu} from '@/modules/menu/MenuInfo'
- import HttpMenu from '@/request/menu/Menu';
- export const useMenuInfoStore = defineStore('menuInfo', () => {
- //获取标识符
- const menuFlag=ref<Boolean>(false)
- //获取菜单是否获取标识符
- const getMenuFlag=computed(()=>menuFlag.value)
-
- //响应式菜单集合数据
- const menuListInfo=reactive<Array<ListMenu>>([]);
-
- //获取菜单权限
- const getMenu=computed(async ()=>{
- //判断是否有权限
- if(!menuFlag.value){
- await getMenuByUser();
- }
- menuFlag.value=true;
- return menuListInfo;
- })
- //发送请求获取用户可访问菜单权限
- async function getMenuByUser(){
- try{
- const result=await HttpMenu.getMenuByUser()
- menuListInfo.push(...result)
- }catch(e){
- console.log(e)
- }
- }
- return {getMenu,getMenuFlag}
- })
- import { createRouter, createWebHistory } from 'vue-router'
- //登录页
- import LoginView from '@/views/login/LoginView.vue'
- //首页
- import IndexView from '@/views/index/IndexView.vue'
- //导入token 状态管理
- import {useUserInfoStore} from '@/stores/UserInfo'
- //导入获取权限状态管理
- import { useMenuInfoStore } from '@/stores/MenuInfo'
-
-
-
- const router = createRouter({
- history: createWebHistory(import.meta.env.BASE_URL),
- routes: [
- {
- path:'/',
- redirect:'/login'
- },
- {
- path:'/login',
- name:'login',
- component: LoginView
- },
- {
- path:'/index',
- name:'index',
- component: IndexView
- }
- ]
- })
- router.beforeEach( async (to,from,next)=>{
-
- const userStore=useUserInfoStore();
- const menuStore=useMenuInfoStore();
- //验证是否登录
- if(to.path!='/login'){
- //获取token
- const token=userStore.getToken
- if(!token){
- router.push('/login')
- return ;
- }
- const menuFlag=menuStore.getMenuFlag;
- //判断是否为首页并且没有获取过菜单权限
- if(!menuFlag ){
- const modules = import.meta.glob("@/views/*/*.vue");
- //获取菜单权限
- const menuList= await menuStore.getMenu
- //循环遍历菜单
- for(const menuInfo of menuList){
-
- const children=menuInfo.children
-
- if(children){
-
- for(const childrenInfo of children){
- const menu={
- path:childrenInfo.routerPath,
- name:childrenInfo.menuCode,
- // component :() => import(`..${childrenInfo.componentPath}.vue`)
- component :modules[`/src${childrenInfo.componentPath}.vue`]
- }
- router.addRoute('index',menu)
- }
- }
- }
-
- next({...to,replace:true})
- return
- }
- }
- next()
- })
- export default router
- <template>
- <el-row class="tac">
- <el-col >
- <el-menu class="el-menu-vertical-demo" :router="true">
- <el-menu-item index="/index">
- <el-icon><House /></el-icon>
- <span>首页</span>
- </el-menu-item>
- <el-sub-menu v-for="menu in menuList" :key="menu.id" :index="menu.id">
- <template #title>
- <el-icon><component :is="menu.icon"></component></el-icon>
- <span>{{ menu.menuName }}</span>
- </template><el-menu-item-group>
- <template v-for="children in menu.children" :key="children.id">
- <el-menu-item :index="children.id" :route="children.routerPath">
- {{ children.menuName }}
- </el-menu-item>
- </template>
- </el-menu-item-group>
- </el-sub-menu>
- </el-menu>
- </el-col>
- </el-row>
- </template>
-
- <script lang="ts" setup>
- import { useMenuInfoStore } from '@/stores/MenuInfo'
- import { reactive } from 'vue'
- import type { ListMenu } from '@/modules/menu/MenuInfo'
- import { onMounted } from 'vue'
- //菜单集合
- let menuList = reactive<Array<ListMenu>>([])
- //菜单全局管理对象
- const menuStore=useMenuInfoStore();
- //获取菜单集合
- const getMenu = async () => {
- const menuInfoList = await menuStore.getMenu
- menuList.push(...menuInfoList)
- }
- onMounted(() => {
- getMenu()
- })
- </script>
- <style scoped>
- .el-row {
- height: 100%;
- }
- .el-menu {
- height: 100%;
- }
-
- </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。