我正在使用 Quasar Framework 以及 Vue 3(利用带有语法的 Composition API)和 TypeScript 开发一个应用程序。我尝试在routes.ts文件中实现Navigation Guard来处理路由身份验证,但遇到以下错误:
ERROR in src/router/index.ts:26:5
TS2740: Type 'Router' is missing the following properties from type 'readonly RouteRecordRaw[]': length, concat, join, slice, and 16 more.
24 | const Router = createRouter({
25 | scrollBehavior: () => ({ left: 0, top: 0 }),
> 26 | routes,
| ^^^^^^
27 |
28 | // Leave this as is and make changes in quasar.conf.js instead!
29 | // quasar.conf.js -> build -> vueRouterMode
这是我迄今为止尝试过的:
路线.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import { useAuthStore } from 'src/stores/auth-store'; // Ensure you import your auth store
import MainLayout from 'layouts/MainLayout.vue';
import AdminLayout from 'layouts/AdminLayout.vue';
import IndexPage from 'pages/IndexPage.vue';
import SignUp from 'pages/Authentication/SignUp.vue';
import SignIn from 'pages/Authentication/SignIn.vue';
import DashboardPage from 'pages/SuperAdmin/DashboardPage.vue';
const routes: Array<RouteRecordRaw> = [
{
path: '/',
component: MainLayout,
children: [
{ path: '', component: SignUp },
{ path: '/home', component: IndexPage },
{ path: '/login', component: SignIn }
],
},
{
path: '/admin',
component: AdminLayout,
children: [
{ path: '', component: DashboardPage },
],
meta: { requiresAdmin: true }
},
{
path: '/:catchAll(.*)*',
component: () => import('pages/ErrorNotFound.vue'),
},
];
const router = createRouter({
history: createWebHistory(),
routes, // This is correct
});
router.beforeEach((to, from, next) => {
const auth = useAuthStore();
if (to.matched.some(record => record.meta.requiresAdmin)) {
if (auth.isAdminUser) {
next();
} else {
next('/');
}
} else {
next();
}
});
export default router;
auth-store.ts
import { defineStore } from 'pinia';
import AuthRequests from 'boot/api/AuthRequests';
import jwt_decode from 'jwt-decode';
import { api } from 'boot/axios';
import { Roles } from 'src/utils/Constants'
interface AuthState {
jwt: string | null;
expiration: number | null;
}
interface DecodedJWT {
permissions?: string[];
exp: number;
}
export const useAuthStore = defineStore('auth', {
state: (): AuthState => {
return JSON.parse(localStorage.getItem('authStore') as string) || {
jwt: null,
expiration: null
};
},
getters: {
isAuthenticated: (state: AuthState): boolean => {
return state.jwt !== null;
},
hasPermission: (state: AuthState) => (permission: string): boolean => {
if (!state.jwt) return false;
const decoded_jwt: DecodedJWT = jwt_decode(state.jwt);
return decoded_jwt.permissions ? decoded_jwt.permissions.includes(permission) : false;
},
isAdminUser: (): boolean => useAuthStore().hasPermission(Roles.ADMIN),
isVenueOwner: (): boolean => useAuthStore().hasPermission(Roles.VENUE_OWNER),
isStaff: (): boolean => useAuthStore().hasPermission(Roles.STAFF),
isEventOrganizer: (): boolean => useAuthStore().hasPermission(Roles.EVENT_ORGANIZER),
isGroupAdmin: (): boolean => useAuthStore().hasPermission(Roles.GROUP_ADMIN),
isStandardUser: (): boolean => useAuthStore().hasPermission(Roles.USER),
},
actions: {
async authenticate(email: string, password: string): Promise<void> {
try {
const { data } = await AuthRequests.authenticate(email, password);
const decoded_jwt: DecodedJWT = jwt_decode(data);
this.jwt = data;
this.expiration = decoded_jwt.exp;
api.defaults.headers.common['Authorization'] = 'Bearer ' + data;
localStorage.setItem('authStore', JSON.stringify({
jwt: data,
expiration: decoded_jwt.exp,
}));
} catch (e) {
console.error(e);
}
},
logout(): void {
this.jwt = null;
delete api.defaults.headers.common['Authorization'];
localStorage.removeItem('authStore');
}
}
});
src/路由器/index.ts
import { route } from 'quasar/wrappers';
import {
createMemoryHistory,
createRouter,
createWebHashHistory,
createWebHistory,
} from 'vue-router';
import routes from './routes';
export default route(function (/* { store, ssrContext } */) {
const createHistory = process.env.SERVER
? createMemoryHistory
: (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory);
const Router = createRouter({
scrollBehavior: () => ({ left: 0, top: 0 }),
routes,
history: createHistory(
process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE
),
});
return Router;
});
似乎您创建了两次路由器,一次在index.ts中,一次在routes.ts中。我建议将创建内容保留在 index.ts 内,并在那里添加防护。基本上将其从
routes.ts
中删除并仅导出 routes
:
const router = createRouter({
history: createWebHistory(),
routes, // This is correct
});
router.beforeEach((to, from, next) => {
const auth = useAuthStore();
if (to.matched.some(record => record.meta.requiresAdmin)) {
if (auth.isAdminUser) {
next();
} else {
next('/');
}
} else {
next();
}
});
并将其添加到
index.ts
:
export default route(function (/* { store, ssrContext } */) {
const createHistory = process.env.SERVER
? createMemoryHistory
: (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory);
const Router = createRouter({
scrollBehavior: () => ({ left: 0, top: 0 }),
routes,
history: createHistory(
process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE
),
});
Router.beforeEach((to, from, next) => {
const auth = useAuthStore();
if (to.matched.some(record => record.meta.requiresAdmin)) {
if (auth.isAdminUser) {
next();
} else {
next('/');
}
} else {
next();
}
});
return Router;
});