mirror of
				https://github.com/pure-admin/vue-pure-admin.git
				synced 2025-11-03 13:44:47 +08:00 
			
		
		
		
	refactor: permission (#357)
* refactor: permission * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * fix: 修复`mix`混合模式导航在生产环境左侧菜单一定机率不显示的问题 * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update
This commit is contained in:
		
							parent
							
								
									cedc84d31a
								
							
						
					
					
						commit
						6ef4cf9fb6
					
				@ -32,7 +32,7 @@ menus:
 | 
				
			|||||||
  hsRole: Role Manage
 | 
					  hsRole: Role Manage
 | 
				
			||||||
  hsDept: Dept Manage
 | 
					  hsDept: Dept Manage
 | 
				
			||||||
  hseditor: Editor
 | 
					  hseditor: Editor
 | 
				
			||||||
  hserror: Error Page
 | 
					  hsabnormal: Abnormal Page
 | 
				
			||||||
  hsfourZeroFour: "404"
 | 
					  hsfourZeroFour: "404"
 | 
				
			||||||
  hsfourZeroOne: "403"
 | 
					  hsfourZeroOne: "403"
 | 
				
			||||||
  hsFive: "500"
 | 
					  hsFive: "500"
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,7 @@ menus:
 | 
				
			|||||||
  hsRole: 角色管理
 | 
					  hsRole: 角色管理
 | 
				
			||||||
  hsDept: 部门管理
 | 
					  hsDept: 部门管理
 | 
				
			||||||
  hseditor: 编辑器
 | 
					  hseditor: 编辑器
 | 
				
			||||||
  hserror: 错误页面
 | 
					  hsabnormal: 异常页面
 | 
				
			||||||
  hsfourZeroFour: "404"
 | 
					  hsfourZeroFour: "404"
 | 
				
			||||||
  hsfourZeroOne: "403"
 | 
					  hsfourZeroOne: "403"
 | 
				
			||||||
  hsFive: "500"
 | 
					  hsFive: "500"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,12 @@
 | 
				
			|||||||
// 根据角色动态生成路由
 | 
					// 模拟后端动态生成路由
 | 
				
			||||||
import { MockMethod } from "vite-plugin-mock";
 | 
					import { MockMethod } from "vite-plugin-mock";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// http://mockjs.com/examples.html#Object
 | 
					/**
 | 
				
			||||||
 | 
					 * roles:页面级别权限,这里模拟二种 "admin"、"common"
 | 
				
			||||||
 | 
					 * admin:管理员角色
 | 
				
			||||||
 | 
					 * common:普通角色
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const systemRouter = {
 | 
					const systemRouter = {
 | 
				
			||||||
  path: "/system",
 | 
					  path: "/system",
 | 
				
			||||||
  meta: {
 | 
					  meta: {
 | 
				
			||||||
@ -15,7 +20,8 @@ const systemRouter = {
 | 
				
			|||||||
      name: "User",
 | 
					      name: "User",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        icon: "flUser",
 | 
					        icon: "flUser",
 | 
				
			||||||
        title: "menus.hsUser"
 | 
					        title: "menus.hsUser",
 | 
				
			||||||
 | 
					        roles: ["admin"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -23,7 +29,8 @@ const systemRouter = {
 | 
				
			|||||||
      name: "Role",
 | 
					      name: "Role",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        icon: "role",
 | 
					        icon: "role",
 | 
				
			||||||
        title: "menus.hsRole"
 | 
					        title: "menus.hsRole",
 | 
				
			||||||
 | 
					        roles: ["admin"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -31,7 +38,8 @@ const systemRouter = {
 | 
				
			|||||||
      name: "Dept",
 | 
					      name: "Dept",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        icon: "dept",
 | 
					        icon: "dept",
 | 
				
			||||||
        title: "menus.hsDept"
 | 
					        title: "menus.hsDept",
 | 
				
			||||||
 | 
					        roles: ["admin"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -41,7 +49,8 @@ const systemRouter = {
 | 
				
			|||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        icon: "dict",
 | 
					        icon: "dict",
 | 
				
			||||||
        title: "menus.hsDict",
 | 
					        title: "menus.hsDict",
 | 
				
			||||||
        keepAlive: true
 | 
					        keepAlive: true,
 | 
				
			||||||
 | 
					        roles: ["admin"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
@ -52,13 +61,14 @@ const permissionRouter = {
 | 
				
			|||||||
  meta: {
 | 
					  meta: {
 | 
				
			||||||
    title: "menus.permission",
 | 
					    title: "menus.permission",
 | 
				
			||||||
    icon: "lollipop",
 | 
					    icon: "lollipop",
 | 
				
			||||||
    rank: 7
 | 
					    rank: 10
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  children: [
 | 
					  children: [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      path: "/permission/page/index",
 | 
					      path: "/permission/page/index",
 | 
				
			||||||
      name: "PermissionPage",
 | 
					      name: "PermissionPage",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
 | 
					        roles: ["admin", "common"],
 | 
				
			||||||
        title: "menus.permissionPage"
 | 
					        title: "menus.permissionPage"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -67,7 +77,8 @@ const permissionRouter = {
 | 
				
			|||||||
      name: "PermissionButton",
 | 
					      name: "PermissionButton",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        title: "menus.permissionButton",
 | 
					        title: "menus.permissionButton",
 | 
				
			||||||
        authority: []
 | 
					        roles: ["admin", "common"],
 | 
				
			||||||
 | 
					        auths: ["btn_add", "btn_edit", "btn_delete"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
@ -78,7 +89,7 @@ const frameRouter = {
 | 
				
			|||||||
  meta: {
 | 
					  meta: {
 | 
				
			||||||
    icon: "monitor",
 | 
					    icon: "monitor",
 | 
				
			||||||
    title: "menus.hsExternalPage",
 | 
					    title: "menus.hsExternalPage",
 | 
				
			||||||
    rank: 10
 | 
					    rank: 7
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  children: [
 | 
					  children: [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -86,14 +97,16 @@ const frameRouter = {
 | 
				
			|||||||
      name: "FramePure",
 | 
					      name: "FramePure",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        title: "menus.hsPureDocument",
 | 
					        title: "menus.hsPureDocument",
 | 
				
			||||||
        frameSrc: "http://yiming_chang.gitee.io/pure-admin-doc"
 | 
					        frameSrc: "http://yiming_chang.gitee.io/pure-admin-doc",
 | 
				
			||||||
 | 
					        roles: ["admin", "common"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      path: "/external",
 | 
					      path: "/external",
 | 
				
			||||||
      name: "http://yiming_chang.gitee.io/pure-admin-doc",
 | 
					      name: "http://yiming_chang.gitee.io/pure-admin-doc",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        title: "menus.externalLink"
 | 
					        title: "menus.externalLink",
 | 
				
			||||||
 | 
					        roles: ["admin", "common"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -101,7 +114,8 @@ const frameRouter = {
 | 
				
			|||||||
      name: "FrameEp",
 | 
					      name: "FrameEp",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        title: "menus.hsEpDocument",
 | 
					        title: "menus.hsEpDocument",
 | 
				
			||||||
        frameSrc: "https://element-plus.org/zh-CN/"
 | 
					        frameSrc: "https://element-plus.org/zh-CN/",
 | 
				
			||||||
 | 
					        roles: ["admin", "common"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
@ -119,7 +133,8 @@ const tabsRouter = {
 | 
				
			|||||||
      path: "/tabs/index",
 | 
					      path: "/tabs/index",
 | 
				
			||||||
      name: "Tabs",
 | 
					      name: "Tabs",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        title: "menus.hstabs"
 | 
					        title: "menus.hstabs",
 | 
				
			||||||
 | 
					        roles: ["admin", "common"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -127,7 +142,8 @@ const tabsRouter = {
 | 
				
			|||||||
      name: "TabQueryDetail",
 | 
					      name: "TabQueryDetail",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        // 不在menu菜单中显示
 | 
					        // 不在menu菜单中显示
 | 
				
			||||||
        showLink: false
 | 
					        showLink: false,
 | 
				
			||||||
 | 
					        roles: ["admin", "common"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -135,39 +151,22 @@ const tabsRouter = {
 | 
				
			|||||||
      component: "params-detail",
 | 
					      component: "params-detail",
 | 
				
			||||||
      name: "TabParamsDetail",
 | 
					      name: "TabParamsDetail",
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        showLink: false
 | 
					        showLink: false,
 | 
				
			||||||
 | 
					        roles: ["admin", "common"]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 添加不同按钮权限到/permission/button页面中
 | 
					 | 
				
			||||||
function setDifAuthority(authority, routes) {
 | 
					 | 
				
			||||||
  routes.children[1].meta.authority = [authority];
 | 
					 | 
				
			||||||
  return routes;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default [
 | 
					export default [
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    url: "/getAsyncRoutes",
 | 
					    url: "/getAsyncRoutes",
 | 
				
			||||||
    method: "get",
 | 
					    method: "get",
 | 
				
			||||||
    response: ({ query }) => {
 | 
					    response: () => {
 | 
				
			||||||
      if (query.name === "admin") {
 | 
					      return {
 | 
				
			||||||
        return {
 | 
					        success: true,
 | 
				
			||||||
          code: 0,
 | 
					        data: [systemRouter, permissionRouter, frameRouter, tabsRouter]
 | 
				
			||||||
          info: [
 | 
					      };
 | 
				
			||||||
            tabsRouter,
 | 
					 | 
				
			||||||
            frameRouter,
 | 
					 | 
				
			||||||
            systemRouter,
 | 
					 | 
				
			||||||
            setDifAuthority("v-admin", permissionRouter)
 | 
					 | 
				
			||||||
          ]
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
          code: 0,
 | 
					 | 
				
			||||||
          info: [tabsRouter, setDifAuthority("v-test", permissionRouter)]
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
] as MockMethod[];
 | 
					] as MockMethod[];
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ export default [
 | 
				
			|||||||
    method: "post",
 | 
					    method: "post",
 | 
				
			||||||
    response: () => {
 | 
					    response: () => {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        code: 0,
 | 
					        success: true,
 | 
				
			||||||
        data: {
 | 
					        data: {
 | 
				
			||||||
          list: [
 | 
					          list: [
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										36
									
								
								mock/login.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								mock/login.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					// 根据角色动态生成路由
 | 
				
			||||||
 | 
					import { MockMethod } from "vite-plugin-mock";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: "/login",
 | 
				
			||||||
 | 
					    method: "post",
 | 
				
			||||||
 | 
					    response: ({ body }) => {
 | 
				
			||||||
 | 
					      if (body.username === "admin") {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          success: true,
 | 
				
			||||||
 | 
					          data: {
 | 
				
			||||||
 | 
					            username: "admin",
 | 
				
			||||||
 | 
					            // 一个用户可能有多个角色
 | 
				
			||||||
 | 
					            roles: ["admin"],
 | 
				
			||||||
 | 
					            accessToken: "eyJhbGciOiJIUzUxMiJ9.admin",
 | 
				
			||||||
 | 
					            refreshToken: "eyJhbGciOiJIUzUxMiJ9.adminRefresh",
 | 
				
			||||||
 | 
					            expires: "2023/10/30 00:00:00"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          success: true,
 | 
				
			||||||
 | 
					          data: {
 | 
				
			||||||
 | 
					            username: "common",
 | 
				
			||||||
 | 
					            // 一个用户可能有多个角色
 | 
				
			||||||
 | 
					            roles: ["common"],
 | 
				
			||||||
 | 
					            accessToken: "eyJhbGciOiJIUzUxMiJ9.common",
 | 
				
			||||||
 | 
					            refreshToken: "eyJhbGciOiJIUzUxMiJ9.commonRefresh",
 | 
				
			||||||
 | 
					            expires: "2023/10/30 00:00:00"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					] as MockMethod[];
 | 
				
			||||||
@ -29,8 +29,8 @@ export default [
 | 
				
			|||||||
    method: "get",
 | 
					    method: "get",
 | 
				
			||||||
    response: () => {
 | 
					    response: () => {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        code: 0,
 | 
					        success: true,
 | 
				
			||||||
        info: mapList()
 | 
					        data: mapList()
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										27
									
								
								mock/refreshToken.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								mock/refreshToken.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					import { MockMethod } from "vite-plugin-mock";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 模拟刷新token接口
 | 
				
			||||||
 | 
					export default [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: "/refreshToken",
 | 
				
			||||||
 | 
					    method: "post",
 | 
				
			||||||
 | 
					    response: ({ body }) => {
 | 
				
			||||||
 | 
					      if (body.refreshToken) {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          success: true,
 | 
				
			||||||
 | 
					          data: {
 | 
				
			||||||
 | 
					            accessToken: "eyJhbGciOiJIUzUxMiJ9.admin",
 | 
				
			||||||
 | 
					            refreshToken: "eyJhbGciOiJIUzUxMiJ9.adminRefresh",
 | 
				
			||||||
 | 
					            // `expires`选择这种日期格式是为了方便调试,后端直接设置时间戳或许更方便(每次都应该递增)。如果后端返回的是时间戳格式,前端开发请来到这个目录`src/utils/auth.ts`,把第`38`行的代码换成expires = data.expires即可。
 | 
				
			||||||
 | 
					            expires: "2023/10/30 23:59:59"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          success: false,
 | 
				
			||||||
 | 
					          data: {}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					] as MockMethod[];
 | 
				
			||||||
@ -6,7 +6,7 @@ export default [
 | 
				
			|||||||
    method: "post",
 | 
					    method: "post",
 | 
				
			||||||
    response: () => {
 | 
					    response: () => {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        code: 0,
 | 
					        success: true,
 | 
				
			||||||
        data: {
 | 
					        data: {
 | 
				
			||||||
          list: [
 | 
					          list: [
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -71,7 +71,7 @@ export default [
 | 
				
			|||||||
    method: "post",
 | 
					    method: "post",
 | 
				
			||||||
    response: () => {
 | 
					    response: () => {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        code: 0,
 | 
					        success: true,
 | 
				
			||||||
        data: [
 | 
					        data: [
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            name: "杭州总公司",
 | 
					            name: "杭州总公司",
 | 
				
			||||||
@ -212,7 +212,7 @@ export default [
 | 
				
			|||||||
    method: "post",
 | 
					    method: "post",
 | 
				
			||||||
    response: () => {
 | 
					    response: () => {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        code: 0,
 | 
					        success: true,
 | 
				
			||||||
        data: {
 | 
					        data: {
 | 
				
			||||||
          list: [
 | 
					          list: [
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
				
			|||||||
@ -35,7 +35,7 @@
 | 
				
			|||||||
    "@pureadmin/components": "^1.1.0",
 | 
					    "@pureadmin/components": "^1.1.0",
 | 
				
			||||||
    "@pureadmin/descriptions": "^1.1.0",
 | 
					    "@pureadmin/descriptions": "^1.1.0",
 | 
				
			||||||
    "@pureadmin/table": "^1.2.0",
 | 
					    "@pureadmin/table": "^1.2.0",
 | 
				
			||||||
    "@pureadmin/utils": "^1.1.4",
 | 
					    "@pureadmin/utils": "^1.1.5",
 | 
				
			||||||
    "@vueuse/core": "^9.3.0",
 | 
					    "@vueuse/core": "^9.3.0",
 | 
				
			||||||
    "@vueuse/motion": "^2.0.0-beta.12",
 | 
					    "@vueuse/motion": "^2.0.0-beta.12",
 | 
				
			||||||
    "@vueuse/shared": "^9.3.0",
 | 
					    "@vueuse/shared": "^9.3.0",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@ -22,7 +22,7 @@ specifiers:
 | 
				
			|||||||
  "@pureadmin/descriptions": ^1.1.0
 | 
					  "@pureadmin/descriptions": ^1.1.0
 | 
				
			||||||
  "@pureadmin/table": ^1.2.0
 | 
					  "@pureadmin/table": ^1.2.0
 | 
				
			||||||
  "@pureadmin/theme": ^2.4.0
 | 
					  "@pureadmin/theme": ^2.4.0
 | 
				
			||||||
  "@pureadmin/utils": ^1.1.4
 | 
					  "@pureadmin/utils": ^1.1.5
 | 
				
			||||||
  "@types/element-resize-detector": 1.1.3
 | 
					  "@types/element-resize-detector": 1.1.3
 | 
				
			||||||
  "@types/js-cookie": ^3.0.1
 | 
					  "@types/js-cookie": ^3.0.1
 | 
				
			||||||
  "@types/lodash": ^4.14.180
 | 
					  "@types/lodash": ^4.14.180
 | 
				
			||||||
@ -132,7 +132,7 @@ dependencies:
 | 
				
			|||||||
  "@pureadmin/components": 1.1.0_vue@3.2.40
 | 
					  "@pureadmin/components": 1.1.0_vue@3.2.40
 | 
				
			||||||
  "@pureadmin/descriptions": 1.1.0
 | 
					  "@pureadmin/descriptions": 1.1.0
 | 
				
			||||||
  "@pureadmin/table": 1.2.0
 | 
					  "@pureadmin/table": 1.2.0
 | 
				
			||||||
  "@pureadmin/utils": 1.1.4_888d42e6b1d4aaf209a7326195b5949d
 | 
					  "@pureadmin/utils": 1.1.5_888d42e6b1d4aaf209a7326195b5949d
 | 
				
			||||||
  "@vueuse/core": 9.3.0_vue@3.2.40
 | 
					  "@vueuse/core": 9.3.0_vue@3.2.40
 | 
				
			||||||
  "@vueuse/motion": 2.0.0-beta.12_vue@3.2.40
 | 
					  "@vueuse/motion": 2.0.0-beta.12_vue@3.2.40
 | 
				
			||||||
  "@vueuse/shared": 9.3.0_vue@3.2.40
 | 
					  "@vueuse/shared": 9.3.0_vue@3.2.40
 | 
				
			||||||
@ -1428,10 +1428,10 @@ packages:
 | 
				
			|||||||
      string-hash: 1.1.3
 | 
					      string-hash: 1.1.3
 | 
				
			||||||
    dev: true
 | 
					    dev: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /@pureadmin/utils/1.1.4_888d42e6b1d4aaf209a7326195b5949d:
 | 
					  /@pureadmin/utils/1.1.5_888d42e6b1d4aaf209a7326195b5949d:
 | 
				
			||||||
    resolution:
 | 
					    resolution:
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        integrity: sha512-c3Zl9v6usKUqz6y8wYhk89g/hXz/I5QzHS7dTum8/YomqDMBph7c70u0J1dAgruDnEIIB2SNDuEWyGD8054WsQ==
 | 
					        integrity: sha512-5nQZyFAbs59gkMBj0WLox7BlY7llILR/ENo2QNEKW6avMt8sDL1+858EFjEbELl6enPsVvJpoCTxatmZzVjyAw==
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    peerDependencies:
 | 
					    peerDependencies:
 | 
				
			||||||
      dayjs: "*"
 | 
					      dayjs: "*"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,11 @@
 | 
				
			|||||||
import { http } from "../utils/http";
 | 
					import { http } from "../utils/http";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Result = {
 | 
					type Result = {
 | 
				
			||||||
 | 
					  success: boolean;
 | 
				
			||||||
  data?: {
 | 
					  data?: {
 | 
				
			||||||
    /** 列表数据 */
 | 
					    /** 列表数据 */
 | 
				
			||||||
    list: Array<any>;
 | 
					    list: Array<any>;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  code?: number;
 | 
					 | 
				
			||||||
  msg?: string;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 卡片列表 */
 | 
					/** 卡片列表 */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
import { http } from "../utils/http";
 | 
					import { http } from "../utils/http";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Result = {
 | 
					type Result = {
 | 
				
			||||||
  code: number;
 | 
					  success: boolean;
 | 
				
			||||||
  info: Array<any>;
 | 
					  data: Array<any>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 地图数据 */
 | 
					/** 地图数据 */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
import { http } from "../utils/http";
 | 
					import { http } from "../utils/http";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Result = {
 | 
					type Result = {
 | 
				
			||||||
  code: number;
 | 
					  success: boolean;
 | 
				
			||||||
  info: Array<any>;
 | 
					  data: Array<any>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getAsyncRoutes = (params?: object) => {
 | 
					export const getAsyncRoutes = () => {
 | 
				
			||||||
  return http.request<Result>("get", "/getAsyncRoutes", { params });
 | 
					  return http.request<Result>("get", "/getAsyncRoutes");
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,13 @@
 | 
				
			|||||||
import { http } from "../utils/http";
 | 
					import { http } from "../utils/http";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Result = {
 | 
					type Result = {
 | 
				
			||||||
 | 
					  success: boolean;
 | 
				
			||||||
  data?: {
 | 
					  data?: {
 | 
				
			||||||
    /** 列表数据 */
 | 
					    /** 列表数据 */
 | 
				
			||||||
    list: Array<any>;
 | 
					    list: Array<any>;
 | 
				
			||||||
    /** 总数 */
 | 
					    /** 总数 */
 | 
				
			||||||
    total: number;
 | 
					    total?: number;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  code?: number;
 | 
					 | 
				
			||||||
  msg?: string;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 获取用户管理列表 */
 | 
					/** 获取用户管理列表 */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,26 +1,39 @@
 | 
				
			|||||||
import { http } from "../utils/http";
 | 
					import { http } from "../utils/http";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Result = {
 | 
					export type UserResult = {
 | 
				
			||||||
  svg?: string;
 | 
					  success: boolean;
 | 
				
			||||||
  code?: number;
 | 
					  data: {
 | 
				
			||||||
  info?: object;
 | 
					    /** 用户名 */
 | 
				
			||||||
 | 
					    username: string;
 | 
				
			||||||
 | 
					    /** 当前登陆用户的角色 */
 | 
				
			||||||
 | 
					    roles: Array<string>;
 | 
				
			||||||
 | 
					    /** `token` */
 | 
				
			||||||
 | 
					    accessToken: string;
 | 
				
			||||||
 | 
					    /** 用于调用刷新`accessToken`的接口时所需的`token` */
 | 
				
			||||||
 | 
					    refreshToken: string;
 | 
				
			||||||
 | 
					    /** `accessToken`的过期时间(格式'xxxx/xx/xx xx:xx:xx') */
 | 
				
			||||||
 | 
					    expires: Date;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 获取验证码 */
 | 
					export type RefreshTokenResult = {
 | 
				
			||||||
export const getVerify = () => {
 | 
					  success: boolean;
 | 
				
			||||||
  return http.request<Result>("get", "/captcha");
 | 
					  data: {
 | 
				
			||||||
 | 
					    /** `token` */
 | 
				
			||||||
 | 
					    accessToken: string;
 | 
				
			||||||
 | 
					    /** 用于调用刷新`accessToken`的接口时所需的`token` */
 | 
				
			||||||
 | 
					    refreshToken: string;
 | 
				
			||||||
 | 
					    /** `accessToken`的过期时间(格式'xxxx/xx/xx xx:xx:xx') */
 | 
				
			||||||
 | 
					    expires: Date;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 登录 */
 | 
					/** 登录 */
 | 
				
			||||||
export const getLogin = (data: object) => {
 | 
					export const getLogin = (data?: object) => {
 | 
				
			||||||
  return http.request("post", "/login", { data });
 | 
					  return http.request<UserResult>("post", "/login", { data });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 刷新token */
 | 
					/** 刷新token */
 | 
				
			||||||
export const refreshToken = (data: object) => {
 | 
					export const refreshTokenApi = (data?: object) => {
 | 
				
			||||||
  return http.request("post", "/refreshToken", { data });
 | 
					  return http.request<RefreshTokenResult>("post", "/refreshToken", { data });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
// export const searchVague = (data: object) => {
 | 
					 | 
				
			||||||
//   return http.request("post", "/searchVague", { data });
 | 
					 | 
				
			||||||
// };
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								src/components/ReAuth/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/components/ReAuth/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					import auth from "./src/auth";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Auth = auth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { Auth };
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/components/ReAuth/src/auth.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/components/ReAuth/src/auth.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					import { defineComponent, Fragment } from "vue";
 | 
				
			||||||
 | 
					import { hasAuth } from "/@/router/utils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default defineComponent({
 | 
				
			||||||
 | 
					  name: "Auth",
 | 
				
			||||||
 | 
					  props: {
 | 
				
			||||||
 | 
					    value: {
 | 
				
			||||||
 | 
					      type: undefined,
 | 
				
			||||||
 | 
					      default: []
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  setup(props, { slots }) {
 | 
				
			||||||
 | 
					    return () => {
 | 
				
			||||||
 | 
					      if (!slots) return null;
 | 
				
			||||||
 | 
					      return hasAuth(props.value) ? (
 | 
				
			||||||
 | 
					        <Fragment>{slots.default?.()}</Fragment>
 | 
				
			||||||
 | 
					      ) : null;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -116,7 +116,8 @@ onMounted(() => {
 | 
				
			|||||||
            :disabled="item.disabled"
 | 
					            :disabled="item.disabled"
 | 
				
			||||||
            :style="{
 | 
					            :style="{
 | 
				
			||||||
              cursor: item.disabled === false ? 'pointer' : 'not-allowed',
 | 
					              cursor: item.disabled === false ? 'pointer' : 'not-allowed',
 | 
				
			||||||
              color: item.disabled === false ? '' : '#00000040'
 | 
					              color: item.disabled === false ? '' : '#00000040',
 | 
				
			||||||
 | 
					              background: 'transparent'
 | 
				
			||||||
            }"
 | 
					            }"
 | 
				
			||||||
            @click="onControl(item, key)"
 | 
					            @click="onControl(item, key)"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
 | 
				
			|||||||
@ -92,8 +92,8 @@ onBeforeMount(() => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      // 获取模拟车辆信息
 | 
					      // 获取模拟车辆信息
 | 
				
			||||||
      mapJson()
 | 
					      mapJson()
 | 
				
			||||||
        .then(({ info }) => {
 | 
					        .then(({ data }) => {
 | 
				
			||||||
          let points: object = info.map(v => {
 | 
					          let points: object = data.map(v => {
 | 
				
			||||||
            return {
 | 
					            return {
 | 
				
			||||||
              lnglat: [v.lng, v.lat],
 | 
					              lnglat: [v.lng, v.lat],
 | 
				
			||||||
              ...v
 | 
					              ...v
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										13
									
								
								src/directives/auth/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/directives/auth/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import { hasAuth } from "/@/router/utils";
 | 
				
			||||||
 | 
					import { Directive, type DirectiveBinding } from "vue";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const auth: Directive = {
 | 
				
			||||||
 | 
					  mounted(el: HTMLElement, binding: DirectiveBinding) {
 | 
				
			||||||
 | 
					    const { value } = binding;
 | 
				
			||||||
 | 
					    if (value) {
 | 
				
			||||||
 | 
					      !hasAuth(value) && el.parentNode.removeChild(el);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      throw new Error("need auths! Like v-auth=\"['btn.add','btn.edit']\"");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -1,2 +1,2 @@
 | 
				
			|||||||
export * from "./permission";
 | 
					export * from "./auth";
 | 
				
			||||||
export * from "./elResizeDetector";
 | 
					export * from "./elResizeDetector";
 | 
				
			||||||
 | 
				
			|||||||
@ -1,18 +0,0 @@
 | 
				
			|||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
					 | 
				
			||||||
import { Directive } from "vue";
 | 
					 | 
				
			||||||
import type { DirectiveBinding } from "vue";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const auth: Directive = {
 | 
					 | 
				
			||||||
  mounted(el: HTMLElement, binding: DirectiveBinding) {
 | 
					 | 
				
			||||||
    const { value } = binding;
 | 
					 | 
				
			||||||
    if (value) {
 | 
					 | 
				
			||||||
      const authRoles = value;
 | 
					 | 
				
			||||||
      const hasAuth = usePermissionStoreHook().buttonAuth.includes(authRoles);
 | 
					 | 
				
			||||||
      if (!hasAuth) {
 | 
					 | 
				
			||||||
        el.parentNode.removeChild(el);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      throw new Error("need roles! Like v-auth=\"['admin','test']\"");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { useRouter } from "vue-router";
 | 
					import { useRouter } from "vue-router";
 | 
				
			||||||
 | 
					import { cloneDeep } from "lodash-unified";
 | 
				
			||||||
import SearchResult from "./SearchResult.vue";
 | 
					import SearchResult from "./SearchResult.vue";
 | 
				
			||||||
import SearchFooter from "./SearchFooter.vue";
 | 
					import SearchFooter from "./SearchFooter.vue";
 | 
				
			||||||
import { useNav } from "/@/layout/hooks/useNav";
 | 
					import { useNav } from "/@/layout/hooks/useNav";
 | 
				
			||||||
@ -31,7 +32,7 @@ const handleSearch = useDebounceFn(search, 300);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/** 菜单树形结构 */
 | 
					/** 菜单树形结构 */
 | 
				
			||||||
const menusData = computed(() => {
 | 
					const menusData = computed(() => {
 | 
				
			||||||
  return deleteChildren(usePermissionStoreHook().menusTree);
 | 
					  return deleteChildren(cloneDeep(usePermissionStoreHook().wholeMenus));
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const show = computed({
 | 
					const show = computed({
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,7 @@ import panel from "../panel/index.vue";
 | 
				
			|||||||
import { emitter } from "/@/utils/mitt";
 | 
					import { emitter } from "/@/utils/mitt";
 | 
				
			||||||
import { resetRouter } from "/@/router";
 | 
					import { resetRouter } from "/@/router";
 | 
				
			||||||
import { templateRef } from "@vueuse/core";
 | 
					import { templateRef } from "@vueuse/core";
 | 
				
			||||||
 | 
					import { removeToken } from "/@/utils/auth";
 | 
				
			||||||
import { routerArrays } from "/@/layout/types";
 | 
					import { routerArrays } from "/@/layout/types";
 | 
				
			||||||
import { useNav } from "/@/layout/hooks/useNav";
 | 
					import { useNav } from "/@/layout/hooks/useNav";
 | 
				
			||||||
import { useAppStoreHook } from "/@/store/modules/app";
 | 
					import { useAppStoreHook } from "/@/store/modules/app";
 | 
				
			||||||
@ -131,7 +132,7 @@ const multiTagsCacheChange = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/** 清空缓存并返回登录页 */
 | 
					/** 清空缓存并返回登录页 */
 | 
				
			||||||
function onReset() {
 | 
					function onReset() {
 | 
				
			||||||
  router.push("/login");
 | 
					  removeToken();
 | 
				
			||||||
  storageLocal.clear();
 | 
					  storageLocal.clear();
 | 
				
			||||||
  storageSession.clear();
 | 
					  storageSession.clear();
 | 
				
			||||||
  const { Grey, Weak, MultiTagsCache, EpThemeColor, Layout } = getConfig();
 | 
					  const { Grey, Weak, MultiTagsCache, EpThemeColor, Layout } = getConfig();
 | 
				
			||||||
@ -140,6 +141,7 @@ function onReset() {
 | 
				
			|||||||
  useMultiTagsStoreHook().multiTagsCacheChange(MultiTagsCache);
 | 
					  useMultiTagsStoreHook().multiTagsCacheChange(MultiTagsCache);
 | 
				
			||||||
  toggleClass(Grey, "html-grey", document.querySelector("html"));
 | 
					  toggleClass(Grey, "html-grey", document.querySelector("html"));
 | 
				
			||||||
  toggleClass(Weak, "html-weakness", document.querySelector("html"));
 | 
					  toggleClass(Weak, "html-weakness", document.querySelector("html"));
 | 
				
			||||||
 | 
					  router.push("/login");
 | 
				
			||||||
  useMultiTagsStoreHook().handleTags("equal", [...routerArrays]);
 | 
					  useMultiTagsStoreHook().handleTags("equal", [...routerArrays]);
 | 
				
			||||||
  resetRouter();
 | 
					  resetRouter();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -48,7 +48,7 @@ nextTick(() => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(
 | 
					watch(
 | 
				
			||||||
  () => route.path,
 | 
					  () => [route.path, usePermissionStoreHook().wholeMenus],
 | 
				
			||||||
  () => {
 | 
					  () => {
 | 
				
			||||||
    getDefaultActive(route.path);
 | 
					    getDefaultActive(route.path);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ const menuData = computed(() => {
 | 
				
			|||||||
    : usePermissionStoreHook().wholeMenus;
 | 
					    : usePermissionStoreHook().wholeMenus;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getSubMenuData(path) {
 | 
					function getSubMenuData(path: string) {
 | 
				
			||||||
  // path的上级路由组成的数组
 | 
					  // path的上级路由组成的数组
 | 
				
			||||||
  const parentPathArr = getParentPaths(
 | 
					  const parentPathArr = getParentPaths(
 | 
				
			||||||
    path,
 | 
					    path,
 | 
				
			||||||
@ -41,6 +41,7 @@ function getSubMenuData(path) {
 | 
				
			|||||||
  if (!parenetRoute?.children) return;
 | 
					  if (!parenetRoute?.children) return;
 | 
				
			||||||
  subMenuData.value = parenetRoute?.children;
 | 
					  subMenuData.value = parenetRoute?.children;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
getSubMenuData(route.path);
 | 
					getSubMenuData(route.path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onBeforeMount(() => {
 | 
					onBeforeMount(() => {
 | 
				
			||||||
@ -50,7 +51,7 @@ onBeforeMount(() => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(
 | 
					watch(
 | 
				
			||||||
  () => route.path,
 | 
					  () => [route.path, usePermissionStoreHook().wholeMenus],
 | 
				
			||||||
  () => {
 | 
					  () => {
 | 
				
			||||||
    getSubMenuData(route.path);
 | 
					    getSubMenuData(route.path);
 | 
				
			||||||
    menuSelect(route.path, routers);
 | 
					    menuSelect(route.path, routers);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,27 +1,26 @@
 | 
				
			|||||||
import { computed } from "vue";
 | 
					import { computed } from "vue";
 | 
				
			||||||
import { router } from "/@/router";
 | 
					 | 
				
			||||||
import { getConfig } from "/@/config";
 | 
					import { getConfig } from "/@/config";
 | 
				
			||||||
import { useRouter } from "vue-router";
 | 
					import { useRouter } from "vue-router";
 | 
				
			||||||
import { emitter } from "/@/utils/mitt";
 | 
					import { emitter } from "/@/utils/mitt";
 | 
				
			||||||
import { routeMetaType } from "../types";
 | 
					import { routeMetaType } from "../types";
 | 
				
			||||||
import type { StorageConfigs } from "/#/index";
 | 
					import { useGlobal } from "@pureadmin/utils";
 | 
				
			||||||
import { routerArrays } from "/@/layout/types";
 | 
					 | 
				
			||||||
import { transformI18n } from "/@/plugins/i18n";
 | 
					import { transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
 | 
					import { router, remainingPaths } from "/@/router";
 | 
				
			||||||
import { useAppStoreHook } from "/@/store/modules/app";
 | 
					import { useAppStoreHook } from "/@/store/modules/app";
 | 
				
			||||||
import { remainingPaths, resetRouter } from "/@/router";
 | 
					 | 
				
			||||||
import { i18nChangeLanguage } from "@wangeditor/editor";
 | 
					import { i18nChangeLanguage } from "@wangeditor/editor";
 | 
				
			||||||
import { storageSession, useGlobal } from "@pureadmin/utils";
 | 
					import { useUserStoreHook } from "/@/store/modules/user";
 | 
				
			||||||
import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
 | 
					import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
 | 
				
			||||||
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const errorInfo = "当前路由配置不正确,请检查配置";
 | 
					const errorInfo = "当前路由配置不正确,请检查配置";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function useNav() {
 | 
					export function useNav() {
 | 
				
			||||||
  const pureApp = useAppStoreHook();
 | 
					  const pureApp = useAppStoreHook();
 | 
				
			||||||
  const routers = useRouter().options.routes;
 | 
					  const routers = useRouter().options.routes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** 用户名 */
 | 
					  /** 用户名 */
 | 
				
			||||||
  const username: string =
 | 
					  const username = computed(() => {
 | 
				
			||||||
    storageSession.getItem<StorageConfigs>("info")?.username;
 | 
					    return useUserStoreHook()?.username;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** 设置国际化选中后的样式 */
 | 
					  /** 设置国际化选中后的样式 */
 | 
				
			||||||
  const getDropdownItemStyle = computed(() => {
 | 
					  const getDropdownItemStyle = computed(() => {
 | 
				
			||||||
@ -40,7 +39,7 @@ export function useNav() {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const avatarsStyle = computed(() => {
 | 
					  const avatarsStyle = computed(() => {
 | 
				
			||||||
    return username ? { marginRight: "10px" } : "";
 | 
					    return username.value ? { marginRight: "10px" } : "";
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const isCollapse = computed(() => {
 | 
					  const isCollapse = computed(() => {
 | 
				
			||||||
@ -69,10 +68,7 @@ export function useNav() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  /** 退出登录 */
 | 
					  /** 退出登录 */
 | 
				
			||||||
  function logout() {
 | 
					  function logout() {
 | 
				
			||||||
    useMultiTagsStoreHook().handleTags("equal", [...routerArrays]);
 | 
					    useUserStoreHook().logOut();
 | 
				
			||||||
    storageSession.removeItem("info");
 | 
					 | 
				
			||||||
    router.push("/login");
 | 
					 | 
				
			||||||
    resetRouter();
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function backHome() {
 | 
					  function backHome() {
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ export type routeMetaType = {
 | 
				
			|||||||
  icon?: string;
 | 
					  icon?: string;
 | 
				
			||||||
  showLink?: boolean;
 | 
					  showLink?: boolean;
 | 
				
			||||||
  savedPosition?: boolean;
 | 
					  savedPosition?: boolean;
 | 
				
			||||||
  authority?: Array<string>;
 | 
					  auths?: Array<string>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type RouteConfigs = {
 | 
					export type RouteConfigs = {
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,10 @@ app.component("IconifyIconOffline", IconifyIconOffline);
 | 
				
			|||||||
app.component("IconifyIconOnline", IconifyIconOnline);
 | 
					app.component("IconifyIconOnline", IconifyIconOnline);
 | 
				
			||||||
app.component("FontIcon", FontIcon);
 | 
					app.component("FontIcon", FontIcon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 全局注册按钮级别权限组件
 | 
				
			||||||
 | 
					import { Auth } from "/@/components/ReAuth";
 | 
				
			||||||
 | 
					app.component("Auth", Auth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
getServerConfig(app).then(async config => {
 | 
					getServerConfig(app).then(async config => {
 | 
				
			||||||
  app.use(router);
 | 
					  app.use(router);
 | 
				
			||||||
  await router.isReady();
 | 
					  await router.isReady();
 | 
				
			||||||
 | 
				
			|||||||
@ -2,8 +2,8 @@ import { getConfig } from "/@/config";
 | 
				
			|||||||
import { toRouteType } from "./types";
 | 
					import { toRouteType } from "./types";
 | 
				
			||||||
import NProgress from "/@/utils/progress";
 | 
					import NProgress from "/@/utils/progress";
 | 
				
			||||||
import { findIndex } from "lodash-unified";
 | 
					import { findIndex } from "lodash-unified";
 | 
				
			||||||
import type { StorageConfigs } from "/#/index";
 | 
					 | 
				
			||||||
import { transformI18n } from "/@/plugins/i18n";
 | 
					import { transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
 | 
					import { sessionKey, type DataInfo } from "/@/utils/auth";
 | 
				
			||||||
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 | 
					import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 | 
				
			||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
					import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -15,6 +15,7 @@ import {
 | 
				
			|||||||
import {
 | 
					import {
 | 
				
			||||||
  ascending,
 | 
					  ascending,
 | 
				
			||||||
  initRouter,
 | 
					  initRouter,
 | 
				
			||||||
 | 
					  isOneOfArray,
 | 
				
			||||||
  getHistoryMode,
 | 
					  getHistoryMode,
 | 
				
			||||||
  findRouteByPath,
 | 
					  findRouteByPath,
 | 
				
			||||||
  handleAliveRoute,
 | 
					  handleAliveRoute,
 | 
				
			||||||
@ -121,10 +122,10 @@ router.beforeEach((to: toRouteType, _from, next) => {
 | 
				
			|||||||
      handleAliveRoute(newMatched);
 | 
					      handleAliveRoute(newMatched);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  const name = storageSession.getItem<StorageConfigs>("info");
 | 
					  const userInfo = storageSession.getItem<DataInfo<number>>(sessionKey);
 | 
				
			||||||
  NProgress.start();
 | 
					  NProgress.start();
 | 
				
			||||||
  const externalLink = isUrl(to?.name as string);
 | 
					  const externalLink = isUrl(to?.name as string);
 | 
				
			||||||
  if (!externalLink)
 | 
					  if (!externalLink) {
 | 
				
			||||||
    to.matched.some(item => {
 | 
					    to.matched.some(item => {
 | 
				
			||||||
      if (!item.meta.title) return "";
 | 
					      if (!item.meta.title) return "";
 | 
				
			||||||
      const Title = getConfig().Title;
 | 
					      const Title = getConfig().Title;
 | 
				
			||||||
@ -132,7 +133,12 @@ router.beforeEach((to: toRouteType, _from, next) => {
 | 
				
			|||||||
        document.title = `${transformI18n(item.meta.title)} | ${Title}`;
 | 
					        document.title = `${transformI18n(item.meta.title)} | ${Title}`;
 | 
				
			||||||
      else document.title = transformI18n(item.meta.title);
 | 
					      else document.title = transformI18n(item.meta.title);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  if (name) {
 | 
					  }
 | 
				
			||||||
 | 
					  if (userInfo) {
 | 
				
			||||||
 | 
					    // 无权限跳转403页面
 | 
				
			||||||
 | 
					    if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
 | 
				
			||||||
 | 
					      next({ path: "/error/403" });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (_from?.name) {
 | 
					    if (_from?.name) {
 | 
				
			||||||
      // name为超链接
 | 
					      // name为超链接
 | 
				
			||||||
      if (externalLink) {
 | 
					      if (externalLink) {
 | 
				
			||||||
@ -143,8 +149,11 @@ router.beforeEach((to: toRouteType, _from, next) => {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      // 刷新
 | 
					      // 刷新
 | 
				
			||||||
      if (usePermissionStoreHook().wholeMenus.length === 0)
 | 
					      if (
 | 
				
			||||||
        initRouter(name.username).then((router: Router) => {
 | 
					        usePermissionStoreHook().wholeMenus.length === 0 &&
 | 
				
			||||||
 | 
					        to.path !== "/login"
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					        initRouter().then((router: Router) => {
 | 
				
			||||||
          if (!useMultiTagsStoreHook().getMultiTagsCache) {
 | 
					          if (!useMultiTagsStoreHook().getMultiTagsCache) {
 | 
				
			||||||
            const { path } = to;
 | 
					            const { path } = to;
 | 
				
			||||||
            const index = findIndex(remainingRouter, v => {
 | 
					            const index = findIndex(remainingRouter, v => {
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ const errorRouter: RouteConfigsTable = {
 | 
				
			|||||||
  redirect: "/error/403",
 | 
					  redirect: "/error/403",
 | 
				
			||||||
  meta: {
 | 
					  meta: {
 | 
				
			||||||
    icon: "information-line",
 | 
					    icon: "information-line",
 | 
				
			||||||
    title: $t("menus.hserror"),
 | 
					    title: $t("menus.hsabnormal"),
 | 
				
			||||||
    rank: 9
 | 
					    rank: 9
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  children: [
 | 
					  children: [
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ import { RouteLocationNormalized } from "vue-router";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export interface toRouteType extends RouteLocationNormalized {
 | 
					export interface toRouteType extends RouteLocationNormalized {
 | 
				
			||||||
  meta: {
 | 
					  meta: {
 | 
				
			||||||
 | 
					    roles: Array<string>;
 | 
				
			||||||
    keepAlive?: boolean;
 | 
					    keepAlive?: boolean;
 | 
				
			||||||
    dynamicLevel?: string;
 | 
					    dynamicLevel?: string;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
				
			|||||||
@ -9,10 +9,16 @@ import {
 | 
				
			|||||||
import { router } from "./index";
 | 
					import { router } from "./index";
 | 
				
			||||||
import { isProxy, toRaw } from "vue";
 | 
					import { isProxy, toRaw } from "vue";
 | 
				
			||||||
import { loadEnv } from "../../build";
 | 
					import { loadEnv } from "../../build";
 | 
				
			||||||
import { cloneDeep } from "lodash-unified";
 | 
					 | 
				
			||||||
import { useTimeoutFn } from "@vueuse/core";
 | 
					import { useTimeoutFn } from "@vueuse/core";
 | 
				
			||||||
import { RouteConfigs } from "/@/layout/types";
 | 
					import { RouteConfigs } from "/@/layout/types";
 | 
				
			||||||
import { buildHierarchyTree } from "@pureadmin/utils";
 | 
					import {
 | 
				
			||||||
 | 
					  isString,
 | 
				
			||||||
 | 
					  storageSession,
 | 
				
			||||||
 | 
					  buildHierarchyTree,
 | 
				
			||||||
 | 
					  isIncludeAllChildren
 | 
				
			||||||
 | 
					} from "@pureadmin/utils";
 | 
				
			||||||
 | 
					import { cloneDeep, intersection } from "lodash-unified";
 | 
				
			||||||
 | 
					import { sessionKey, type DataInfo } from "/@/utils/auth";
 | 
				
			||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
					import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
				
			||||||
const IFrame = () => import("/@/layout/frameView.vue");
 | 
					const IFrame = () => import("/@/layout/frameView.vue");
 | 
				
			||||||
// https://cn.vitejs.dev/guide/features.html#glob-import
 | 
					// https://cn.vitejs.dev/guide/features.html#glob-import
 | 
				
			||||||
@ -38,7 +44,7 @@ function ascending(arr: any[]) {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 过滤meta中showLink为false的路由 */
 | 
					/** 过滤meta中showLink为false的菜单 */
 | 
				
			||||||
function filterTree(data: RouteComponent[]) {
 | 
					function filterTree(data: RouteComponent[]) {
 | 
				
			||||||
  const newTree = cloneDeep(data).filter(
 | 
					  const newTree = cloneDeep(data).filter(
 | 
				
			||||||
    (v: { meta: { showLink: boolean } }) => v.meta?.showLink !== false
 | 
					    (v: { meta: { showLink: boolean } }) => v.meta?.showLink !== false
 | 
				
			||||||
@ -49,6 +55,37 @@ function filterTree(data: RouteComponent[]) {
 | 
				
			|||||||
  return newTree;
 | 
					  return newTree;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 过滤children长度为0的的目录,当目录下没有菜单时,会过滤此目录,目录没有赋予roles权限,当目录下只要有一个菜单有显示权限,那么此目录就会显示 */
 | 
				
			||||||
 | 
					function filterChildrenTree(data: RouteComponent[]) {
 | 
				
			||||||
 | 
					  const newTree = cloneDeep(data).filter((v: any) => v?.children?.length !== 0);
 | 
				
			||||||
 | 
					  newTree.forEach(
 | 
				
			||||||
 | 
					    (v: { children }) => v.children && (v.children = filterTree(v.children))
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  return newTree;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 判断两个数组彼此是否存在相同值 */
 | 
				
			||||||
 | 
					function isOneOfArray(a: Array<string>, b: Array<string>) {
 | 
				
			||||||
 | 
					  return Array.isArray(a) && Array.isArray(b)
 | 
				
			||||||
 | 
					    ? intersection(a, b).length > 0
 | 
				
			||||||
 | 
					      ? true
 | 
				
			||||||
 | 
					      : false
 | 
				
			||||||
 | 
					    : true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 从sessionStorage里取出当前登陆用户的角色roles,过滤无权限的菜单 */
 | 
				
			||||||
 | 
					function filterNoPermissionTree(data: RouteComponent[]) {
 | 
				
			||||||
 | 
					  const currentRoles =
 | 
				
			||||||
 | 
					    storageSession.getItem<DataInfo<number>>(sessionKey).roles ?? [];
 | 
				
			||||||
 | 
					  const newTree = cloneDeep(data).filter((v: any) =>
 | 
				
			||||||
 | 
					    isOneOfArray(v.meta?.roles, currentRoles)
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  newTree.forEach(
 | 
				
			||||||
 | 
					    (v: any) => v.children && (v.children = filterNoPermissionTree(v.children))
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  return filterChildrenTree(newTree);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 批量删除缓存路由(keepalive) */
 | 
					/** 批量删除缓存路由(keepalive) */
 | 
				
			||||||
function delAliveRoutes(delAliveRouteList: Array<RouteConfigs>) {
 | 
					function delAliveRoutes(delAliveRouteList: Array<RouteConfigs>) {
 | 
				
			||||||
  delAliveRouteList.forEach(route => {
 | 
					  delAliveRouteList.forEach(route => {
 | 
				
			||||||
@ -115,13 +152,13 @@ function addPathMatch() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 初始化路由 */
 | 
					/** 初始化路由 */
 | 
				
			||||||
function initRouter(name: string) {
 | 
					function initRouter() {
 | 
				
			||||||
  return new Promise(resolve => {
 | 
					  return new Promise(resolve => {
 | 
				
			||||||
    getAsyncRoutes({ name }).then(({ info }) => {
 | 
					    getAsyncRoutes().then(({ data }) => {
 | 
				
			||||||
      if (info.length === 0) {
 | 
					      if (data.length === 0) {
 | 
				
			||||||
        usePermissionStoreHook().changeSetting(info);
 | 
					        usePermissionStoreHook().handleWholeMenus(data);
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        formatFlatteningRoutes(addAsyncRoutes(info)).map(
 | 
					        formatFlatteningRoutes(addAsyncRoutes(data)).map(
 | 
				
			||||||
          (v: RouteRecordRaw) => {
 | 
					          (v: RouteRecordRaw) => {
 | 
				
			||||||
            // 防止重复添加路由
 | 
					            // 防止重复添加路由
 | 
				
			||||||
            if (
 | 
					            if (
 | 
				
			||||||
@ -144,7 +181,7 @@ function initRouter(name: string) {
 | 
				
			|||||||
            resolve(router);
 | 
					            resolve(router);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        usePermissionStoreHook().changeSetting(info);
 | 
					        usePermissionStoreHook().handleWholeMenus(data);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      addPathMatch();
 | 
					      addPathMatch();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@ -275,30 +312,29 @@ function getHistoryMode(): RouterHistory {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 是否有权限 */
 | 
					/** 获取当前页面按钮级别的权限 */
 | 
				
			||||||
function hasPermissions(value: Array<string>): boolean {
 | 
					function getAuths(): Array<string> {
 | 
				
			||||||
  if (value && value instanceof Array && value.length > 0) {
 | 
					  return router.currentRoute.value.meta.auths as Array<string>;
 | 
				
			||||||
    const roles = usePermissionStoreHook().buttonAuth;
 | 
					}
 | 
				
			||||||
    const permissionRoles = value;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const hasPermission = roles.some(role => {
 | 
					/** 是否有按钮级别的权限 */
 | 
				
			||||||
      return permissionRoles.includes(role);
 | 
					function hasAuth(value: string | Array<string>): boolean {
 | 
				
			||||||
    });
 | 
					  if (!value) return false;
 | 
				
			||||||
 | 
					  /** 从当前路由的`meta`字段里获取按钮级别的所有自定义`code`值 */
 | 
				
			||||||
    if (!hasPermission) {
 | 
					  const metaAuths = getAuths();
 | 
				
			||||||
      return false;
 | 
					  const isAuths = isString(value)
 | 
				
			||||||
    }
 | 
					    ? metaAuths.includes(value)
 | 
				
			||||||
    return true;
 | 
					    : isIncludeAllChildren(value, metaAuths);
 | 
				
			||||||
  } else {
 | 
					  return isAuths ? true : false;
 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export {
 | 
					export {
 | 
				
			||||||
 | 
					  hasAuth,
 | 
				
			||||||
 | 
					  getAuths,
 | 
				
			||||||
  ascending,
 | 
					  ascending,
 | 
				
			||||||
  filterTree,
 | 
					  filterTree,
 | 
				
			||||||
  initRouter,
 | 
					  initRouter,
 | 
				
			||||||
  hasPermissions,
 | 
					  isOneOfArray,
 | 
				
			||||||
  getHistoryMode,
 | 
					  getHistoryMode,
 | 
				
			||||||
  addAsyncRoutes,
 | 
					  addAsyncRoutes,
 | 
				
			||||||
  delAliveRoutes,
 | 
					  delAliveRoutes,
 | 
				
			||||||
@ -306,5 +342,6 @@ export {
 | 
				
			|||||||
  findRouteByPath,
 | 
					  findRouteByPath,
 | 
				
			||||||
  handleAliveRoute,
 | 
					  handleAliveRoute,
 | 
				
			||||||
  formatTwoStageRoutes,
 | 
					  formatTwoStageRoutes,
 | 
				
			||||||
  formatFlatteningRoutes
 | 
					  formatFlatteningRoutes,
 | 
				
			||||||
 | 
					  filterNoPermissionTree
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -2,9 +2,7 @@ import { defineStore } from "pinia";
 | 
				
			|||||||
import { store } from "/@/store";
 | 
					import { store } from "/@/store";
 | 
				
			||||||
import { cacheType } from "./types";
 | 
					import { cacheType } from "./types";
 | 
				
			||||||
import { constantMenus } from "/@/router";
 | 
					import { constantMenus } from "/@/router";
 | 
				
			||||||
import { cloneDeep } from "lodash-unified";
 | 
					import { ascending, filterTree, filterNoPermissionTree } from "/@/router/utils";
 | 
				
			||||||
import { RouteConfigs } from "/@/layout/types";
 | 
					 | 
				
			||||||
import { ascending, filterTree } from "/@/router/utils";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const usePermissionStore = defineStore({
 | 
					export const usePermissionStore = defineStore({
 | 
				
			||||||
  id: "pure-permission",
 | 
					  id: "pure-permission",
 | 
				
			||||||
@ -13,40 +11,15 @@ export const usePermissionStore = defineStore({
 | 
				
			|||||||
    constantMenus,
 | 
					    constantMenus,
 | 
				
			||||||
    // 整体路由生成的菜单(静态、动态)
 | 
					    // 整体路由生成的菜单(静态、动态)
 | 
				
			||||||
    wholeMenus: [],
 | 
					    wholeMenus: [],
 | 
				
			||||||
    // 深拷贝一个菜单树,与导航菜单不突出
 | 
					 | 
				
			||||||
    menusTree: [],
 | 
					 | 
				
			||||||
    buttonAuth: [],
 | 
					 | 
				
			||||||
    // 缓存页面keepAlive
 | 
					    // 缓存页面keepAlive
 | 
				
			||||||
    cachePageList: []
 | 
					    cachePageList: []
 | 
				
			||||||
  }),
 | 
					  }),
 | 
				
			||||||
  actions: {
 | 
					  actions: {
 | 
				
			||||||
    /** 获取异步路由菜单 */
 | 
					    /** 组装整体路由生成的菜单 */
 | 
				
			||||||
    asyncActionRoutes(routes) {
 | 
					    handleWholeMenus(routes: any[]) {
 | 
				
			||||||
      if (this.wholeMenus.length > 0) return;
 | 
					      this.wholeMenus = filterNoPermissionTree(
 | 
				
			||||||
      this.wholeMenus = filterTree(
 | 
					 | 
				
			||||||
        ascending(this.constantMenus.concat(routes))
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.menusTree = cloneDeep(
 | 
					 | 
				
			||||||
        filterTree(ascending(this.constantMenus.concat(routes)))
 | 
					        filterTree(ascending(this.constantMenus.concat(routes)))
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					 | 
				
			||||||
      const getButtonAuth = (arrRoutes: Array<RouteConfigs>) => {
 | 
					 | 
				
			||||||
        if (!arrRoutes || !arrRoutes.length) return;
 | 
					 | 
				
			||||||
        arrRoutes.forEach((v: RouteConfigs) => {
 | 
					 | 
				
			||||||
          if (v.meta && v.meta.authority) {
 | 
					 | 
				
			||||||
            this.buttonAuth.push(...v.meta.authority);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          if (v.children) {
 | 
					 | 
				
			||||||
            getButtonAuth(v.children);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      getButtonAuth(this.wholeMenus);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    async changeSetting(routes) {
 | 
					 | 
				
			||||||
      await this.asyncActionRoutes(routes);
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    cacheOperate({ mode, name }: cacheType) {
 | 
					    cacheOperate({ mode, name }: cacheType) {
 | 
				
			||||||
      switch (mode) {
 | 
					      switch (mode) {
 | 
				
			||||||
@ -64,8 +37,6 @@ export const usePermissionStore = defineStore({
 | 
				
			|||||||
    /** 清空缓存页面 */
 | 
					    /** 清空缓存页面 */
 | 
				
			||||||
    clearAllCachePage() {
 | 
					    clearAllCachePage() {
 | 
				
			||||||
      this.wholeMenus = [];
 | 
					      this.wholeMenus = [];
 | 
				
			||||||
      this.menusTree = [];
 | 
					 | 
				
			||||||
      this.buttonAuth = [];
 | 
					 | 
				
			||||||
      this.cachePageList = [];
 | 
					      this.cachePageList = [];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -37,8 +37,8 @@ export type setType = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type userType = {
 | 
					export type userType = {
 | 
				
			||||||
  token: string;
 | 
					  username?: string;
 | 
				
			||||||
  name?: string;
 | 
					  roles?: Array<string>;
 | 
				
			||||||
  verifyCode?: string;
 | 
					  verifyCode?: string;
 | 
				
			||||||
  currentPage?: number;
 | 
					  currentPage?: number;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,55 +1,56 @@
 | 
				
			|||||||
import { defineStore } from "pinia";
 | 
					import { defineStore } from "pinia";
 | 
				
			||||||
import { store } from "/@/store";
 | 
					import { store } from "/@/store";
 | 
				
			||||||
import { userType } from "./types";
 | 
					import { userType } from "./types";
 | 
				
			||||||
import { router } from "/@/router";
 | 
					 | 
				
			||||||
import { routerArrays } from "/@/layout/types";
 | 
					import { routerArrays } from "/@/layout/types";
 | 
				
			||||||
 | 
					import { router, resetRouter } from "/@/router";
 | 
				
			||||||
import { storageSession } from "@pureadmin/utils";
 | 
					import { storageSession } from "@pureadmin/utils";
 | 
				
			||||||
import { getLogin, refreshToken } from "/@/api/user";
 | 
					import { getLogin, refreshTokenApi } from "/@/api/user";
 | 
				
			||||||
import { getToken, setToken, removeToken } from "/@/utils/auth";
 | 
					import { UserResult, RefreshTokenResult } from "/@/api/user";
 | 
				
			||||||
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 | 
					import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
const data = getToken();
 | 
					  type DataInfo,
 | 
				
			||||||
let token = "";
 | 
					  setToken,
 | 
				
			||||||
let name = "";
 | 
					  removeToken,
 | 
				
			||||||
if (data) {
 | 
					  sessionKey
 | 
				
			||||||
  const dataJson = JSON.parse(data);
 | 
					} from "/@/utils/auth";
 | 
				
			||||||
  if (dataJson) {
 | 
					 | 
				
			||||||
    token = dataJson?.accessToken;
 | 
					 | 
				
			||||||
    name = dataJson?.name ?? "admin";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useUserStore = defineStore({
 | 
					export const useUserStore = defineStore({
 | 
				
			||||||
  id: "pure-user",
 | 
					  id: "pure-user",
 | 
				
			||||||
  state: (): userType => ({
 | 
					  state: (): userType => ({
 | 
				
			||||||
    token,
 | 
					    username:
 | 
				
			||||||
    name,
 | 
					      storageSession.getItem<DataInfo<number>>(sessionKey)?.username ?? "",
 | 
				
			||||||
 | 
					    // 页面级别权限
 | 
				
			||||||
 | 
					    roles: storageSession.getItem<DataInfo<number>>(sessionKey)?.roles ?? [],
 | 
				
			||||||
    // 前端生成的验证码(按实际需求替换)
 | 
					    // 前端生成的验证码(按实际需求替换)
 | 
				
			||||||
    verifyCode: "",
 | 
					    verifyCode: "",
 | 
				
			||||||
    // 登录显示组件判断 0:登录 1:手机登录 2:二维码登录 3:注册 4:忘记密码,默认0:登录
 | 
					    // 判断登录页面显示哪个组件(0:登录(默认)、1:手机登录、2:二维码登录、3:注册、4:忘记密码)
 | 
				
			||||||
    currentPage: 0
 | 
					    currentPage: 0
 | 
				
			||||||
  }),
 | 
					  }),
 | 
				
			||||||
  actions: {
 | 
					  actions: {
 | 
				
			||||||
    SET_TOKEN(token) {
 | 
					    /** 存储用户名 */
 | 
				
			||||||
      this.token = token;
 | 
					    SET_USERNAME(username: string) {
 | 
				
			||||||
 | 
					      this.username = username;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    SET_NAME(name) {
 | 
					    /** 存储角色 */
 | 
				
			||||||
      this.name = name;
 | 
					    SET_ROLES(roles: Array<string>) {
 | 
				
			||||||
 | 
					      this.roles = roles;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    SET_VERIFYCODE(verifyCode) {
 | 
					    /** 存储前端生成的验证码 */
 | 
				
			||||||
 | 
					    SET_VERIFYCODE(verifyCode: string) {
 | 
				
			||||||
      this.verifyCode = verifyCode;
 | 
					      this.verifyCode = verifyCode;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    SET_CURRENTPAGE(value) {
 | 
					    /** 存储登录页面显示哪个组件 */
 | 
				
			||||||
 | 
					    SET_CURRENTPAGE(value: number) {
 | 
				
			||||||
      this.currentPage = value;
 | 
					      this.currentPage = value;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /** 登入 */
 | 
					    /** 登入 */
 | 
				
			||||||
    async loginByUsername(data) {
 | 
					    async loginByUsername(data) {
 | 
				
			||||||
      return new Promise<void>((resolve, reject) => {
 | 
					      return new Promise<UserResult>((resolve, reject) => {
 | 
				
			||||||
        getLogin(data)
 | 
					        getLogin(data)
 | 
				
			||||||
          .then(data => {
 | 
					          .then(data => {
 | 
				
			||||||
            if (data) {
 | 
					            if (data) {
 | 
				
			||||||
              setToken(data);
 | 
					              setToken(data.data);
 | 
				
			||||||
              resolve();
 | 
					              resolve(data);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          })
 | 
					          })
 | 
				
			||||||
          .catch(error => {
 | 
					          .catch(error => {
 | 
				
			||||||
@ -57,23 +58,28 @@ export const useUserStore = defineStore({
 | 
				
			|||||||
          });
 | 
					          });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /** 登出 清空缓存 */
 | 
					    /** 前端登出(不调用接口) */
 | 
				
			||||||
    logOut() {
 | 
					    logOut() {
 | 
				
			||||||
      this.token = "";
 | 
					      this.username = "";
 | 
				
			||||||
      this.name = "";
 | 
					      this.roles = [];
 | 
				
			||||||
      removeToken();
 | 
					      removeToken();
 | 
				
			||||||
      storageSession.clear();
 | 
					 | 
				
			||||||
      useMultiTagsStoreHook().handleTags("equal", routerArrays);
 | 
					 | 
				
			||||||
      router.push("/login");
 | 
					      router.push("/login");
 | 
				
			||||||
 | 
					      useMultiTagsStoreHook().handleTags("equal", [...routerArrays]);
 | 
				
			||||||
 | 
					      resetRouter();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /** 刷新token */
 | 
					    /** 刷新`token` */
 | 
				
			||||||
    async refreshToken(data) {
 | 
					    async handRefreshToken(data) {
 | 
				
			||||||
      removeToken();
 | 
					      return new Promise<RefreshTokenResult>((resolve, reject) => {
 | 
				
			||||||
      return refreshToken(data).then(data => {
 | 
					        refreshTokenApi(data)
 | 
				
			||||||
        if (data) {
 | 
					          .then(data => {
 | 
				
			||||||
          setToken(data);
 | 
					            if (data) {
 | 
				
			||||||
          return data;
 | 
					              setToken(data.data);
 | 
				
			||||||
        }
 | 
					              resolve(data);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .catch(error => {
 | 
				
			||||||
 | 
					            reject(error);
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -33,7 +33,7 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.is-dark {
 | 
					.is-dark {
 | 
				
			||||||
  z-index: 99999 !important;
 | 
					  z-index: 9999 !important;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 重置 el-button 中 icon 的 margin */
 | 
					/* 重置 el-button 中 icon 的 margin */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,42 +1,72 @@
 | 
				
			|||||||
import Cookies from "js-cookie";
 | 
					import Cookies from "js-cookie";
 | 
				
			||||||
 | 
					import { storageSession } from "@pureadmin/utils";
 | 
				
			||||||
import { useUserStoreHook } from "/@/store/modules/user";
 | 
					import { useUserStoreHook } from "/@/store/modules/user";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TokenKey = "authorized-token";
 | 
					export interface DataInfo<T> {
 | 
				
			||||||
 | 
					  /** token */
 | 
				
			||||||
type paramsMapType = {
 | 
					 | 
				
			||||||
  name: string;
 | 
					 | 
				
			||||||
  expires: number;
 | 
					 | 
				
			||||||
  accessToken: string;
 | 
					  accessToken: string;
 | 
				
			||||||
};
 | 
					  /** `accessToken`的过期时间(时间戳) */
 | 
				
			||||||
 | 
					  expires: T;
 | 
				
			||||||
/** 获取token */
 | 
					  /** 用于调用刷新accessToken的接口时所需的token */
 | 
				
			||||||
export function getToken() {
 | 
					  refreshToken: string;
 | 
				
			||||||
  // 此处与TokenKey相同,此写法解决初始化时Cookies中不存在TokenKey报错
 | 
					  /** 用户名 */
 | 
				
			||||||
  return Cookies.get("authorized-token");
 | 
					  username?: string;
 | 
				
			||||||
 | 
					  /** 当前登陆用户的角色 */
 | 
				
			||||||
 | 
					  roles?: Array<string>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 设置token以及过期时间(cookies、sessionStorage各一份),后端需要将用户信息和token以及过期时间都返回给前端,过期时间主要用于刷新token */
 | 
					export const sessionKey = "user-info";
 | 
				
			||||||
export function setToken(data) {
 | 
					export const TokenKey = "authorized-token";
 | 
				
			||||||
  const { accessToken, expires, name } = data;
 | 
					
 | 
				
			||||||
  // 提取关键信息进行存储
 | 
					/** 获取`token` */
 | 
				
			||||||
  const paramsMap: paramsMapType = {
 | 
					export function getToken(): DataInfo<number> {
 | 
				
			||||||
    name,
 | 
					  // 此处与`TokenKey`相同,此写法解决初始化时`Cookies`中不存在`TokenKey`报错
 | 
				
			||||||
    expires: Date.now() + parseInt(expires),
 | 
					  return Cookies.get(TokenKey)
 | 
				
			||||||
    accessToken
 | 
					    ? JSON.parse(Cookies.get(TokenKey))
 | 
				
			||||||
  };
 | 
					    : storageSession.getItem(sessionKey);
 | 
				
			||||||
  const dataString = JSON.stringify(paramsMap);
 | 
					}
 | 
				
			||||||
  useUserStoreHook().SET_TOKEN(accessToken);
 | 
					
 | 
				
			||||||
  useUserStoreHook().SET_NAME(name);
 | 
					/**
 | 
				
			||||||
 | 
					 * @description 设置`token`以及一些必要信息并采用无感刷新`token`方案
 | 
				
			||||||
 | 
					 * 无感刷新:后端返回`accessToken`(访问接口使用的`token`)、`refreshToken`(用于调用刷新`accessToken`的接口时所需的`token`,`refreshToken`的过期时间(比如30天)应大于`accessToken`的过期时间(比如2小时))、`expires`(`accessToken`的过期时间)
 | 
				
			||||||
 | 
					 * 将`accessToken`、`expires`这两条信息放在key值为authorized-token的cookie里(过期自动销毁)
 | 
				
			||||||
 | 
					 * 将`username`、`roles`、`refreshToken`、`expires`这四条信息放在key值为`user-info`的sessionStorage里(浏览器关闭自动销毁)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function setToken(data: DataInfo<Date>) {
 | 
				
			||||||
 | 
					  let expires = 0;
 | 
				
			||||||
 | 
					  const { accessToken, refreshToken } = data;
 | 
				
			||||||
 | 
					  expires = new Date(data.expires).getTime();
 | 
				
			||||||
 | 
					  const cookieString = JSON.stringify({ accessToken, expires });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  expires > 0
 | 
					  expires > 0
 | 
				
			||||||
    ? Cookies.set(TokenKey, dataString, {
 | 
					    ? Cookies.set(TokenKey, cookieString, {
 | 
				
			||||||
        expires: expires / 86400000
 | 
					        expires: (expires - Date.now()) / 86400000
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    : Cookies.set(TokenKey, dataString);
 | 
					    : Cookies.set(TokenKey, cookieString);
 | 
				
			||||||
  sessionStorage.setItem(TokenKey, dataString);
 | 
					
 | 
				
			||||||
 | 
					  function setSessionKey(username: string, roles: Array<string>) {
 | 
				
			||||||
 | 
					    useUserStoreHook().SET_USERNAME(username);
 | 
				
			||||||
 | 
					    useUserStoreHook().SET_ROLES(roles);
 | 
				
			||||||
 | 
					    storageSession.setItem(sessionKey, {
 | 
				
			||||||
 | 
					      refreshToken,
 | 
				
			||||||
 | 
					      expires,
 | 
				
			||||||
 | 
					      username,
 | 
				
			||||||
 | 
					      roles
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (data.username && data.roles) {
 | 
				
			||||||
 | 
					    const { username, roles } = data;
 | 
				
			||||||
 | 
					    setSessionKey(username, roles);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    const { username, roles } =
 | 
				
			||||||
 | 
					      storageSession.getItem<DataInfo<number>>(sessionKey);
 | 
				
			||||||
 | 
					    setSessionKey(username, roles);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 删除token */
 | 
					/** 删除`token`以及key值为`user-info`的session信息 */
 | 
				
			||||||
export function removeToken() {
 | 
					export function removeToken() {
 | 
				
			||||||
  Cookies.remove(TokenKey);
 | 
					  Cookies.remove(TokenKey);
 | 
				
			||||||
  sessionStorage.removeItem(TokenKey);
 | 
					  sessionStorage.removeItem(sessionKey);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,5 @@
 | 
				
			|||||||
import Axios, { AxiosInstance, AxiosRequestConfig } from "axios";
 | 
					import Axios, { AxiosInstance, AxiosRequestConfig } from "axios";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  resultType,
 | 
					 | 
				
			||||||
  PureHttpError,
 | 
					  PureHttpError,
 | 
				
			||||||
  RequestMethods,
 | 
					  RequestMethods,
 | 
				
			||||||
  PureHttpResponse,
 | 
					  PureHttpResponse,
 | 
				
			||||||
@ -21,7 +20,7 @@ const defaultConfig: AxiosRequestConfig = {
 | 
				
			|||||||
  //   process.env.NODE_ENV === "production"
 | 
					  //   process.env.NODE_ENV === "production"
 | 
				
			||||||
  //     ? VITE_PROXY_DOMAIN_REAL
 | 
					  //     ? VITE_PROXY_DOMAIN_REAL
 | 
				
			||||||
  //     : VITE_PROXY_DOMAIN,
 | 
					  //     : VITE_PROXY_DOMAIN,
 | 
				
			||||||
  // 当前使用mock模拟请求,将baseURL制空,如果你的环境用到了http请求,请删除下面的baseURL启用上面的baseURL,并将11行、16行代码注释取消
 | 
					  // 当前使用mock模拟请求,将baseURL制空,如果你的环境用到了http请求,请删除下面的baseURL启用上面的baseURL,并将第10行、15行代码注释取消
 | 
				
			||||||
  baseURL: "",
 | 
					  baseURL: "",
 | 
				
			||||||
  timeout: 10000,
 | 
					  timeout: 10000,
 | 
				
			||||||
  headers: {
 | 
					  headers: {
 | 
				
			||||||
@ -47,7 +46,7 @@ class PureHttp {
 | 
				
			|||||||
  /** 请求拦截 */
 | 
					  /** 请求拦截 */
 | 
				
			||||||
  private httpInterceptorsRequest(): void {
 | 
					  private httpInterceptorsRequest(): void {
 | 
				
			||||||
    PureHttp.axiosInstance.interceptors.request.use(
 | 
					    PureHttp.axiosInstance.interceptors.request.use(
 | 
				
			||||||
      (config: PureHttpRequestConfig) => {
 | 
					      async (config: PureHttpRequestConfig) => {
 | 
				
			||||||
        const $config = config;
 | 
					        const $config = config;
 | 
				
			||||||
        // 开启进度条动画
 | 
					        // 开启进度条动画
 | 
				
			||||||
        NProgress.start();
 | 
					        NProgress.start();
 | 
				
			||||||
@ -60,26 +59,33 @@ class PureHttp {
 | 
				
			|||||||
          PureHttp.initConfig.beforeRequestCallback($config);
 | 
					          PureHttp.initConfig.beforeRequestCallback($config);
 | 
				
			||||||
          return $config;
 | 
					          return $config;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const token = getToken();
 | 
					        /** 请求白名单(通过设置请求白名单,防止token过期后再请求造成的死循环问题) */
 | 
				
			||||||
        if (token) {
 | 
					        const whiteList = ["/refreshToken", "/login"];
 | 
				
			||||||
          const data = JSON.parse(token);
 | 
					        return whiteList.some(v => config.url.indexOf(v) > -1)
 | 
				
			||||||
          const now = new Date().getTime();
 | 
					          ? config
 | 
				
			||||||
          const expired = parseInt(data.expires) - now <= 0;
 | 
					          : new Promise(resolve => {
 | 
				
			||||||
          if (expired) {
 | 
					              const data = getToken();
 | 
				
			||||||
            // token过期刷新
 | 
					              if (data) {
 | 
				
			||||||
            useUserStoreHook()
 | 
					                const now = new Date().getTime();
 | 
				
			||||||
              .refreshToken(data)
 | 
					                const expired = parseInt(data.expires) - now <= 0;
 | 
				
			||||||
              .then((res: resultType) => {
 | 
					                if (expired) {
 | 
				
			||||||
                config.headers["Authorization"] = "Bearer " + res.accessToken;
 | 
					                  // token过期刷新
 | 
				
			||||||
                return $config;
 | 
					                  useUserStoreHook()
 | 
				
			||||||
              });
 | 
					                    .handRefreshToken({ refreshToken: data.refreshToken })
 | 
				
			||||||
          } else {
 | 
					                    .then(res => {
 | 
				
			||||||
            config.headers["Authorization"] = "Bearer " + data.accessToken;
 | 
					                      config.headers["Authorization"] =
 | 
				
			||||||
            return $config;
 | 
					                        "Bearer " + res.data.accessToken;
 | 
				
			||||||
          }
 | 
					                      resolve($config);
 | 
				
			||||||
        } else {
 | 
					                    });
 | 
				
			||||||
          return $config;
 | 
					                } else {
 | 
				
			||||||
        }
 | 
					                  config.headers["Authorization"] =
 | 
				
			||||||
 | 
					                    "Bearer " + data.accessToken;
 | 
				
			||||||
 | 
					                  resolve($config);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                resolve($config);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      error => {
 | 
					      error => {
 | 
				
			||||||
        return Promise.reject(error);
 | 
					        return Promise.reject(error);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { computed } from "vue";
 | 
					import { computed } from "vue";
 | 
				
			||||||
 | 
					import { cloneDeep } from "lodash-unified";
 | 
				
			||||||
import { transformI18n } from "/@/plugins/i18n";
 | 
					import { transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
import ElTreeLine from "/@/components/ReTreeLine";
 | 
					import ElTreeLine from "/@/components/ReTreeLine";
 | 
				
			||||||
import { extractPathList, deleteChildren } from "@pureadmin/utils";
 | 
					import { extractPathList, deleteChildren } from "@pureadmin/utils";
 | 
				
			||||||
@ -9,8 +10,9 @@ defineOptions({
 | 
				
			|||||||
  name: "LineTree"
 | 
					  name: "LineTree"
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let menusTree = cloneDeep(usePermissionStoreHook().wholeMenus);
 | 
				
			||||||
let menusData = computed(() => {
 | 
					let menusData = computed(() => {
 | 
				
			||||||
  return deleteChildren(usePermissionStoreHook().menusTree);
 | 
					  return deleteChildren(menusTree);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
let expandedKeys = extractPathList(menusData.value);
 | 
					let expandedKeys = extractPathList(menusData.value);
 | 
				
			||||||
let dataProps = {
 | 
					let dataProps = {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { ref, computed } from "vue";
 | 
					import { ref, computed } from "vue";
 | 
				
			||||||
 | 
					import { cloneDeep } from "lodash-unified";
 | 
				
			||||||
import type { ElTreeV2 } from "element-plus";
 | 
					import type { ElTreeV2 } from "element-plus";
 | 
				
			||||||
import { transformI18n } from "/@/plugins/i18n";
 | 
					import { transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
 | 
					import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
 | 
				
			||||||
@ -23,9 +24,10 @@ let dataProps = ref({
 | 
				
			|||||||
  children: "children"
 | 
					  children: "children"
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
const treeRef = ref<InstanceType<typeof ElTreeV2>>();
 | 
					const treeRef = ref<InstanceType<typeof ElTreeV2>>();
 | 
				
			||||||
 | 
					let menusTree = cloneDeep(usePermissionStoreHook().wholeMenus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let menusData = computed(() => {
 | 
					let menusData = computed(() => {
 | 
				
			||||||
  return deleteChildren(usePermissionStoreHook().menusTree);
 | 
					  return deleteChildren(menusTree);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let expandedKeys = extractPathList(menusData.value);
 | 
					let expandedKeys = extractPathList(menusData.value);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,12 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  ref,
 | 
				
			||||||
 | 
					  reactive,
 | 
				
			||||||
 | 
					  watch,
 | 
				
			||||||
 | 
					  computed,
 | 
				
			||||||
 | 
					  onMounted,
 | 
				
			||||||
 | 
					  onBeforeUnmount
 | 
				
			||||||
 | 
					} from "vue";
 | 
				
			||||||
import { useI18n } from "vue-i18n";
 | 
					import { useI18n } from "vue-i18n";
 | 
				
			||||||
import Motion from "./utils/motion";
 | 
					import Motion from "./utils/motion";
 | 
				
			||||||
import { useRouter } from "vue-router";
 | 
					import { useRouter } from "vue-router";
 | 
				
			||||||
@ -12,7 +20,6 @@ import { initRouter } from "/@/router/utils";
 | 
				
			|||||||
import { useNav } from "/@/layout/hooks/useNav";
 | 
					import { useNav } from "/@/layout/hooks/useNav";
 | 
				
			||||||
import { message } from "@pureadmin/components";
 | 
					import { message } from "@pureadmin/components";
 | 
				
			||||||
import type { FormInstance } from "element-plus";
 | 
					import type { FormInstance } from "element-plus";
 | 
				
			||||||
import { storageSession } from "@pureadmin/utils";
 | 
					 | 
				
			||||||
import { $t, transformI18n } from "/@/plugins/i18n";
 | 
					import { $t, transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
import { operates, thirdParty } from "./utils/enums";
 | 
					import { operates, thirdParty } from "./utils/enums";
 | 
				
			||||||
import { useLayout } from "/@/layout/hooks/useLayout";
 | 
					import { useLayout } from "/@/layout/hooks/useLayout";
 | 
				
			||||||
@ -22,14 +29,6 @@ import { ReImageVerify } from "/@/components/ReImageVerify";
 | 
				
			|||||||
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
 | 
					import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
 | 
				
			||||||
import { useTranslationLang } from "/@/layout/hooks/useTranslationLang";
 | 
					import { useTranslationLang } from "/@/layout/hooks/useTranslationLang";
 | 
				
			||||||
import { useDataThemeChange } from "/@/layout/hooks/useDataThemeChange";
 | 
					import { useDataThemeChange } from "/@/layout/hooks/useDataThemeChange";
 | 
				
			||||||
import {
 | 
					 | 
				
			||||||
  ref,
 | 
					 | 
				
			||||||
  reactive,
 | 
					 | 
				
			||||||
  watch,
 | 
					 | 
				
			||||||
  computed,
 | 
					 | 
				
			||||||
  onMounted,
 | 
					 | 
				
			||||||
  onBeforeUnmount
 | 
					 | 
				
			||||||
} from "vue";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dayIcon from "/@/assets/svg/day.svg?component";
 | 
					import dayIcon from "/@/assets/svg/day.svg?component";
 | 
				
			||||||
import darkIcon from "/@/assets/svg/dark.svg?component";
 | 
					import darkIcon from "/@/assets/svg/dark.svg?component";
 | 
				
			||||||
@ -38,6 +37,7 @@ import globalization from "/@/assets/svg/globalization.svg?component";
 | 
				
			|||||||
defineOptions({
 | 
					defineOptions({
 | 
				
			||||||
  name: "Login"
 | 
					  name: "Login"
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const imgCode = ref("");
 | 
					const imgCode = ref("");
 | 
				
			||||||
const router = useRouter();
 | 
					const router = useRouter();
 | 
				
			||||||
const loading = ref(false);
 | 
					const loading = ref(false);
 | 
				
			||||||
@ -47,11 +47,11 @@ const currentPage = computed(() => {
 | 
				
			|||||||
  return useUserStoreHook().currentPage;
 | 
					  return useUserStoreHook().currentPage;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { t } = useI18n();
 | 
				
			||||||
const { initStorage } = useLayout();
 | 
					const { initStorage } = useLayout();
 | 
				
			||||||
initStorage();
 | 
					initStorage();
 | 
				
			||||||
 | 
					 | 
				
			||||||
const { t } = useI18n();
 | 
					 | 
				
			||||||
const { dataTheme, dataThemeChange } = useDataThemeChange();
 | 
					const { dataTheme, dataThemeChange } = useDataThemeChange();
 | 
				
			||||||
 | 
					dataThemeChange();
 | 
				
			||||||
const { title, getDropdownItemStyle, getDropdownItemClass } = useNav();
 | 
					const { title, getDropdownItemStyle, getDropdownItemClass } = useNav();
 | 
				
			||||||
const { locale, translationCh, translationEn } = useTranslationLang();
 | 
					const { locale, translationCh, translationEn } = useTranslationLang();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -66,17 +66,17 @@ const onLogin = async (formEl: FormInstance | undefined) => {
 | 
				
			|||||||
  if (!formEl) return;
 | 
					  if (!formEl) return;
 | 
				
			||||||
  await formEl.validate((valid, fields) => {
 | 
					  await formEl.validate((valid, fields) => {
 | 
				
			||||||
    if (valid) {
 | 
					    if (valid) {
 | 
				
			||||||
      // 模拟请求,需根据实际开发进行修改
 | 
					      useUserStoreHook()
 | 
				
			||||||
      setTimeout(() => {
 | 
					        .loginByUsername({ username: ruleForm.username })
 | 
				
			||||||
        loading.value = false;
 | 
					        .then(res => {
 | 
				
			||||||
        storageSession.setItem("info", {
 | 
					          if (res.success) {
 | 
				
			||||||
          username: "admin",
 | 
					            // 获取后端路由
 | 
				
			||||||
          accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
 | 
					            initRouter().then(() => {
 | 
				
			||||||
 | 
					              message.success("登录成功");
 | 
				
			||||||
 | 
					              router.push("/");
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        initRouter("admin").then(() => {});
 | 
					 | 
				
			||||||
        message.success("登录成功");
 | 
					 | 
				
			||||||
        router.push("/");
 | 
					 | 
				
			||||||
      }, 2000);
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      loading.value = false;
 | 
					      loading.value = false;
 | 
				
			||||||
      return fields;
 | 
					      return fields;
 | 
				
			||||||
@ -84,16 +84,6 @@ const onLogin = async (formEl: FormInstance | undefined) => {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function onHandle(value) {
 | 
					 | 
				
			||||||
  useUserStoreHook().SET_CURRENTPAGE(value);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
watch(imgCode, value => {
 | 
					 | 
				
			||||||
  useUserStoreHook().SET_VERIFYCODE(value);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
dataThemeChange();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 使用公共函数,避免`removeEventListener`失效 */
 | 
					/** 使用公共函数,避免`removeEventListener`失效 */
 | 
				
			||||||
function onkeypress({ code }: KeyboardEvent) {
 | 
					function onkeypress({ code }: KeyboardEvent) {
 | 
				
			||||||
  if (code === "Enter") {
 | 
					  if (code === "Enter") {
 | 
				
			||||||
@ -108,6 +98,10 @@ onMounted(() => {
 | 
				
			|||||||
onBeforeUnmount(() => {
 | 
					onBeforeUnmount(() => {
 | 
				
			||||||
  window.document.removeEventListener("keypress", onkeypress);
 | 
					  window.document.removeEventListener("keypress", onkeypress);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(imgCode, value => {
 | 
				
			||||||
 | 
					  useUserStoreHook().SET_VERIFYCODE(value);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
@ -258,7 +252,7 @@ onBeforeUnmount(() => {
 | 
				
			|||||||
                    :key="index"
 | 
					                    :key="index"
 | 
				
			||||||
                    class="w-full mt-4"
 | 
					                    class="w-full mt-4"
 | 
				
			||||||
                    size="default"
 | 
					                    size="default"
 | 
				
			||||||
                    @click="onHandle(index + 1)"
 | 
					                    @click="useUserStoreHook().SET_CURRENTPAGE(index + 1)"
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    {{ t(item.title) }}
 | 
					                    {{ t(item.title) }}
 | 
				
			||||||
                  </el-button>
 | 
					                  </el-button>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,36 +1,80 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { ref } from "vue";
 | 
					import { type CSSProperties, computed } from "vue";
 | 
				
			||||||
import type { StorageConfigs } from "/#/index";
 | 
					import { hasAuth, getAuths } from "/@/router/utils";
 | 
				
			||||||
import { storageSession } from "@pureadmin/utils";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineOptions({
 | 
					defineOptions({
 | 
				
			||||||
  name: "PermissionButton"
 | 
					  name: "PermissionButton"
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const auth = ref(
 | 
					let width = computed((): CSSProperties => {
 | 
				
			||||||
  storageSession.getItem<StorageConfigs>("info").username || "admin"
 | 
					  return {
 | 
				
			||||||
);
 | 
					    width: "85vw"
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
function changRole(value) {
 | 
					});
 | 
				
			||||||
  storageSession.setItem("info", {
 | 
					 | 
				
			||||||
    username: value,
 | 
					 | 
				
			||||||
    accessToken: `eyJhbGciOiJIUzUxMiJ9.${value}`
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  window.location.reload();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <el-card>
 | 
					  <el-space direction="vertical" size="large">
 | 
				
			||||||
    <template #header>
 | 
					    <el-tag :style="width" size="large" effect="dark">
 | 
				
			||||||
      <div class="card-header">
 | 
					      当前拥有的code列表:{{ getAuths() }}
 | 
				
			||||||
        <el-radio-group v-model="auth" @change="changRole">
 | 
					    </el-tag>
 | 
				
			||||||
          <el-radio-button label="admin" />
 | 
					
 | 
				
			||||||
          <el-radio-button label="test" />
 | 
					    <el-card shadow="never" :style="width">
 | 
				
			||||||
        </el-radio-group>
 | 
					      <template #header>
 | 
				
			||||||
      </div>
 | 
					        <div class="card-header">组件方式判断权限</div>
 | 
				
			||||||
    </template>
 | 
					      </template>
 | 
				
			||||||
    <p v-auth="'v-admin'">只有admin可看</p>
 | 
					      <Auth value="btn_add">
 | 
				
			||||||
    <p v-auth="'v-test'">只有test可看</p>
 | 
					        <el-button type="success"> 拥有code:'btn_add' 权限可见 </el-button>
 | 
				
			||||||
  </el-card>
 | 
					      </Auth>
 | 
				
			||||||
 | 
					      <Auth :value="['btn_edit']">
 | 
				
			||||||
 | 
					        <el-button type="primary"> 拥有code:['btn_edit'] 权限可见 </el-button>
 | 
				
			||||||
 | 
					      </Auth>
 | 
				
			||||||
 | 
					      <Auth :value="['btn_add', 'btn_edit', 'btn_delete']">
 | 
				
			||||||
 | 
					        <el-button type="danger">
 | 
				
			||||||
 | 
					          拥有code:['btn_add', 'btn_edit', 'btn_delete'] 权限可见
 | 
				
			||||||
 | 
					        </el-button>
 | 
				
			||||||
 | 
					      </Auth>
 | 
				
			||||||
 | 
					    </el-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <el-card shadow="never" :style="width">
 | 
				
			||||||
 | 
					      <template #header>
 | 
				
			||||||
 | 
					        <div class="card-header">函数方式判断权限</div>
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					      <el-button type="success" v-if="hasAuth('btn_add')">
 | 
				
			||||||
 | 
					        拥有code:'btn_add' 权限可见
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					      <el-button type="primary" v-if="hasAuth(['btn_edit'])">
 | 
				
			||||||
 | 
					        拥有code:['btn_edit'] 权限可见
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					      <el-button
 | 
				
			||||||
 | 
					        type="danger"
 | 
				
			||||||
 | 
					        v-if="hasAuth(['btn_add', 'btn_edit', 'btn_delete'])"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        拥有code:['btn_add', 'btn_edit', 'btn_delete'] 权限可见
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					    </el-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <el-card shadow="never" :style="width">
 | 
				
			||||||
 | 
					      <template #header>
 | 
				
			||||||
 | 
					        <div class="card-header">
 | 
				
			||||||
 | 
					          指令方式判断权限(该方式不能动态修改权限)
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					      <el-button type="success" v-auth="'btn_add'">
 | 
				
			||||||
 | 
					        拥有code:'btn_add' 权限可见
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					      <el-button type="primary" v-auth="['btn_edit']">
 | 
				
			||||||
 | 
					        拥有code:['btn_edit'] 权限可见
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					      <el-button type="danger" v-auth="['btn_add', 'btn_edit', 'btn_delete']">
 | 
				
			||||||
 | 
					        拥有code:['btn_add', 'btn_edit', 'btn_delete'] 权限可见
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					    </el-card>
 | 
				
			||||||
 | 
					  </el-space>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					:deep(.el-tag) {
 | 
				
			||||||
 | 
					  justify-content: start;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,53 +1,69 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { ref, unref } from "vue";
 | 
					import { initRouter } from "/@/router/utils";
 | 
				
			||||||
import type { StorageConfigs } from "/#/index";
 | 
					import { type CSSProperties, ref, computed } from "vue";
 | 
				
			||||||
import { storageSession } from "@pureadmin/utils";
 | 
					import { useUserStoreHook } from "/@/store/modules/user";
 | 
				
			||||||
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
 | 
					import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineOptions({
 | 
					defineOptions({
 | 
				
			||||||
  name: "PermissionPage"
 | 
					  name: "PermissionPage"
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let purview = ref<string>(
 | 
					let width = computed((): CSSProperties => {
 | 
				
			||||||
  storageSession.getItem<StorageConfigs>("info").username
 | 
					  return {
 | 
				
			||||||
);
 | 
					    width: "85vw"
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function changRole() {
 | 
					let username = ref(useUserStoreHook()?.username);
 | 
				
			||||||
  if (unref(purview) === "admin") {
 | 
					
 | 
				
			||||||
    storageSession.setItem("info", {
 | 
					const options = [
 | 
				
			||||||
      username: "test",
 | 
					  {
 | 
				
			||||||
      accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
 | 
					    value: "admin",
 | 
				
			||||||
    });
 | 
					    label: "管理员角色"
 | 
				
			||||||
    window.location.reload();
 | 
					  },
 | 
				
			||||||
  } else {
 | 
					  {
 | 
				
			||||||
    storageSession.setItem("info", {
 | 
					    value: "common",
 | 
				
			||||||
      username: "admin",
 | 
					    label: "普通角色"
 | 
				
			||||||
      accessToken: "eyJhbGciOiJIUzUxMiJ9.admin"
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    window.location.reload();
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onChange() {
 | 
				
			||||||
 | 
					  useUserStoreHook()
 | 
				
			||||||
 | 
					    .loginByUsername({ username: username.value })
 | 
				
			||||||
 | 
					    .then(res => {
 | 
				
			||||||
 | 
					      if (res.success) {
 | 
				
			||||||
 | 
					        usePermissionStoreHook().clearAllCachePage();
 | 
				
			||||||
 | 
					        initRouter();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <el-card>
 | 
					  <el-space direction="vertical" size="large">
 | 
				
			||||||
    <template #header>
 | 
					    <el-tag :style="width" size="large" effect="dark">
 | 
				
			||||||
      <div class="card-header">
 | 
					      模拟后台根据不同角色返回对应路由,观察左侧菜单变化(管理员角色可查看系统管理菜单、普通角色不可查看系统管理菜单)
 | 
				
			||||||
        <span>
 | 
					    </el-tag>
 | 
				
			||||||
          当前角色:
 | 
					    <el-card shadow="never" :style="width">
 | 
				
			||||||
          <span style="font-size: 26px">{{ purview }}</span>
 | 
					      <template #header>
 | 
				
			||||||
          <p style="color: #ffa500">
 | 
					        <div class="card-header">
 | 
				
			||||||
            查看左侧菜单变化(系统管理),模拟后台根据不同角色返回对应路由
 | 
					          <span>当前角色:{{ username }}</span>
 | 
				
			||||||
          </p>
 | 
					        </div>
 | 
				
			||||||
        </span>
 | 
					      </template>
 | 
				
			||||||
      </div>
 | 
					      <el-select v-model="username" @change="onChange">
 | 
				
			||||||
    </template>
 | 
					        <el-option
 | 
				
			||||||
    <el-button
 | 
					          v-for="item in options"
 | 
				
			||||||
      type="primary"
 | 
					          :key="item.value"
 | 
				
			||||||
      @click="changRole"
 | 
					          :label="item.label"
 | 
				
			||||||
      :icon="useRenderIcon('user', { color: '#fff' })"
 | 
					          :value="item.value"
 | 
				
			||||||
    >
 | 
					        />
 | 
				
			||||||
      切换角色
 | 
					      </el-select>
 | 
				
			||||||
    </el-button>
 | 
					    </el-card>
 | 
				
			||||||
  </el-card>
 | 
					  </el-space>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					:deep(.el-tag) {
 | 
				
			||||||
 | 
					  justify-content: start;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { ref, computed } from "vue";
 | 
					import { ref, computed } from "vue";
 | 
				
			||||||
 | 
					import { cloneDeep } from "lodash-unified";
 | 
				
			||||||
import { transformI18n } from "/@/plugins/i18n";
 | 
					import { transformI18n } from "/@/plugins/i18n";
 | 
				
			||||||
import { TreeSelect } from "@pureadmin/components";
 | 
					import { TreeSelect } from "@pureadmin/components";
 | 
				
			||||||
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 | 
					import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
 | 
				
			||||||
@ -16,13 +17,12 @@ defineOptions({
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { toDetail, router } = useDetail();
 | 
					const { toDetail, router } = useDetail();
 | 
				
			||||||
 | 
					let menusTree = cloneDeep(usePermissionStoreHook().wholeMenus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let treeData = computed(() => {
 | 
					let treeData = computed(() => {
 | 
				
			||||||
  return appendFieldByUniqueId(
 | 
					  return appendFieldByUniqueId(deleteChildren(menusTree), 0, {
 | 
				
			||||||
    deleteChildren(usePermissionStoreHook().menusTree),
 | 
					    disabled: true
 | 
				
			||||||
    0,
 | 
					  });
 | 
				
			||||||
    { disabled: true }
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const value = ref<string[]>([]);
 | 
					const value = ref<string[]>([]);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								types/global.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								types/global.d.ts
									
									
									
									
										vendored
									
									
								
							@ -14,6 +14,7 @@ declare module "vue" {
 | 
				
			|||||||
    IconifyIconOffline: typeof import("../src/components/ReIcon")["IconifyIconOffline"];
 | 
					    IconifyIconOffline: typeof import("../src/components/ReIcon")["IconifyIconOffline"];
 | 
				
			||||||
    IconifyIconOnline: typeof import("../src/components/ReIcon")["IconifyIconOnline"];
 | 
					    IconifyIconOnline: typeof import("../src/components/ReIcon")["IconifyIconOnline"];
 | 
				
			||||||
    FontIcon: typeof import("../src/components/ReIcon")["FontIcon"];
 | 
					    FontIcon: typeof import("../src/components/ReIcon")["FontIcon"];
 | 
				
			||||||
 | 
					    Auth: typeof import("../src/components/ReAuth")["Auth"];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -74,8 +74,10 @@ export interface RouteChildrenConfigsTable {
 | 
				
			|||||||
    showLink?: boolean;
 | 
					    showLink?: boolean;
 | 
				
			||||||
    /** 是否显示父级菜单 `可选` */
 | 
					    /** 是否显示父级菜单 `可选` */
 | 
				
			||||||
    showParent?: boolean;
 | 
					    showParent?: boolean;
 | 
				
			||||||
    /** 路由权限设置 `可选` */
 | 
					    /** 页面级别权限设置 `可选` */
 | 
				
			||||||
    authority?: Array<string>;
 | 
					    roles?: Array<string>;
 | 
				
			||||||
 | 
					    /** 按钮级别权限设置 `可选` */
 | 
				
			||||||
 | 
					    auths?: Array<string>;
 | 
				
			||||||
    /** 路由组件缓存(开启 `true`、关闭 `false`)`可选` */
 | 
					    /** 路由组件缓存(开启 `true`、关闭 `false`)`可选` */
 | 
				
			||||||
    keepAlive?: boolean;
 | 
					    keepAlive?: boolean;
 | 
				
			||||||
    /** 内嵌的`iframe`链接 `可选` */
 | 
					    /** 内嵌的`iframe`链接 `可选` */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user