feat:初始化项目结构
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
import { appRoutes, appExternalRoutes } from '../routes';
|
||||
|
||||
const mixinRoutes = [...appRoutes, ...appExternalRoutes];
|
||||
|
||||
const appClientMenus = mixinRoutes.map((el) => {
|
||||
const { name, path, meta, redirect, children } = el;
|
||||
return {
|
||||
name,
|
||||
path,
|
||||
meta,
|
||||
redirect,
|
||||
children,
|
||||
};
|
||||
});
|
||||
|
||||
export default appClientMenus;
|
||||
@@ -0,0 +1,18 @@
|
||||
export const WHITE_LIST = [
|
||||
{ name: 'notFound', children: [] },
|
||||
{ name: 'login', children: [] },
|
||||
];
|
||||
|
||||
export const NOT_FOUND = {
|
||||
name: 'notFound',
|
||||
};
|
||||
|
||||
export const REDIRECT_ROUTE_NAME = 'Redirect';
|
||||
|
||||
export const DEFAULT_ROUTE_NAME = 'business';
|
||||
|
||||
export const DEFAULT_ROUTE = {
|
||||
title: 'menu.business.project',
|
||||
name: DEFAULT_ROUTE_NAME,
|
||||
fullPath: '/business/project',
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { Router } from 'vue-router';
|
||||
import { setRouteEmitter } from '@/utils/route-listener';
|
||||
import setupUserLoginInfoGuard from './userLoginInfo';
|
||||
import setupPermissionGuard from './permission';
|
||||
|
||||
function setupPageGuard(router: Router) {
|
||||
router.beforeEach(async (to) => {
|
||||
// emit route change
|
||||
setRouteEmitter(to);
|
||||
});
|
||||
}
|
||||
|
||||
export default function createRouteGuard(router: Router) {
|
||||
setupPageGuard(router);
|
||||
setupUserLoginInfoGuard(router);
|
||||
setupPermissionGuard(router);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import type { Router, RouteRecordNormalized } from 'vue-router';
|
||||
import NProgress from 'nprogress'; // progress bar
|
||||
|
||||
import usePermission from '@/hooks/permission';
|
||||
import { useUserStore, useAppStore } from '@/store';
|
||||
import { appRoutes } from '../routes';
|
||||
import { WHITE_LIST, NOT_FOUND } from '../constants';
|
||||
|
||||
export default function setupPermissionGuard(router: Router) {
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const appStore = useAppStore();
|
||||
const userStore = useUserStore();
|
||||
const Permission = usePermission();
|
||||
const permissionsAllow = Permission.accessRouter(to);
|
||||
if (appStore.menuFromServer) {
|
||||
// 针对来自服务端的菜单配置进行处理
|
||||
// Handle routing configuration from the server
|
||||
|
||||
// 根据需要自行完善来源于服务端的菜单配置的permission逻辑
|
||||
// Refine the permission logic from the server's menu configuration as needed
|
||||
if (
|
||||
!appStore.appAsyncMenus.length &&
|
||||
!WHITE_LIST.find((el) => el.name === to.name)
|
||||
) {
|
||||
await appStore.fetchServerMenuConfig();
|
||||
}
|
||||
const serverMenuConfig = [...appStore.appAsyncMenus, ...WHITE_LIST];
|
||||
|
||||
let exist = false;
|
||||
while (serverMenuConfig.length && !exist) {
|
||||
const element = serverMenuConfig.shift();
|
||||
if (element?.name === to.name) exist = true;
|
||||
|
||||
if (element?.children) {
|
||||
serverMenuConfig.push(
|
||||
...(element.children as unknown as RouteRecordNormalized[])
|
||||
);
|
||||
}
|
||||
}
|
||||
if (exist && permissionsAllow) {
|
||||
next();
|
||||
} else next(NOT_FOUND);
|
||||
} else {
|
||||
// eslint-disable-next-line no-lonely-if
|
||||
if (permissionsAllow) next();
|
||||
else {
|
||||
const destination =
|
||||
Permission.findFirstPermissionRoute(appRoutes, userStore.role) ||
|
||||
NOT_FOUND;
|
||||
next(destination);
|
||||
}
|
||||
}
|
||||
NProgress.done();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import type { Router, LocationQueryRaw } from 'vue-router';
|
||||
import NProgress from 'nprogress'; // progress bar
|
||||
|
||||
import { useUserStore } from '@/store';
|
||||
import { isLogin } from '@/utils/auth';
|
||||
|
||||
export default function setupUserLoginInfoGuard(router: Router) {
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
NProgress.start();
|
||||
const userStore = useUserStore();
|
||||
if (isLogin()) {
|
||||
if (userStore.role) {
|
||||
next();
|
||||
} else {
|
||||
try {
|
||||
await userStore.info();
|
||||
next();
|
||||
} catch (error) {
|
||||
await userStore.logout();
|
||||
next({
|
||||
name: 'login',
|
||||
query: {
|
||||
redirect: to.name,
|
||||
...to.query,
|
||||
} as LocationQueryRaw,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (to.name === 'login') {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
next({
|
||||
name: 'login',
|
||||
query: {
|
||||
redirect: to.name,
|
||||
...to.query,
|
||||
} as LocationQueryRaw,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import NProgress from 'nprogress'; // progress bar
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
import { appRoutes } from './routes';
|
||||
import { REDIRECT_MAIN, NOT_FOUND_ROUTE } from './routes/base';
|
||||
import createRouteGuard from './guard';
|
||||
|
||||
NProgress.configure({ showSpinner: false }); // NProgress Configuration
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
redirect: 'login',
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import('@/views/login/index.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
...appRoutes,
|
||||
REDIRECT_MAIN,
|
||||
NOT_FOUND_ROUTE,
|
||||
],
|
||||
scrollBehavior() {
|
||||
return { top: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
createRouteGuard(router);
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import { REDIRECT_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
export const DEFAULT_LAYOUT = () => import('@/layout/default-layout.vue');
|
||||
|
||||
export const REDIRECT_MAIN: RouteRecordRaw = {
|
||||
path: '/redirect',
|
||||
name: 'redirectWrapper',
|
||||
component: DEFAULT_LAYOUT,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
hideInMenu: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '/redirect/:path',
|
||||
name: REDIRECT_ROUTE_NAME,
|
||||
component: () => import('@/views/redirect/index.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
hideInMenu: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const NOT_FOUND_ROUTE: RouteRecordRaw = {
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'notFound',
|
||||
component: () => import('@/views/not-found/index.vue'),
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
export default {
|
||||
path: 'https://arco.design',
|
||||
name: 'arcoWebsite',
|
||||
meta: {
|
||||
locale: 'menu.arcoWebsite',
|
||||
icon: 'icon-link',
|
||||
requiresAuth: true,
|
||||
order: 8,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
export default {
|
||||
path: 'https://arco.design/vue/docs/pro/faq',
|
||||
name: 'faq',
|
||||
meta: {
|
||||
locale: 'menu.faq',
|
||||
icon: 'icon-question-circle',
|
||||
requiresAuth: true,
|
||||
order: 9,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
|
||||
const RESULT: AppRouteRecordRaw = {
|
||||
path: '/result',
|
||||
name: 'result',
|
||||
component: DEFAULT_LAYOUT,
|
||||
redirect:'/result/success',
|
||||
meta: {
|
||||
locale: 'menu.result',
|
||||
icon: 'icon-check-circle',
|
||||
requiresAuth: true,
|
||||
order: 5,
|
||||
isFirst:true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'success',
|
||||
name: 'Success',
|
||||
component: () => import('@/views/result/success/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.result.success',
|
||||
requiresAuth: true,
|
||||
roles: ['admin'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'error',
|
||||
name: 'Error',
|
||||
component: () => import('@/views/result/error/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.result.error',
|
||||
requiresAuth: true,
|
||||
roles: ['admin'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default RESULT;
|
||||
@@ -0,0 +1,40 @@
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
|
||||
const USER: AppRouteRecordRaw = {
|
||||
path: '/user',
|
||||
name: 'user',
|
||||
component: DEFAULT_LAYOUT,
|
||||
redirect:'/user/info',
|
||||
meta: {
|
||||
locale: 'menu.user',
|
||||
icon: 'icon-user',
|
||||
requiresAuth: true,
|
||||
order: 7,
|
||||
isFirst:true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'info',
|
||||
name: 'Info',
|
||||
component: () => import('@/views/user/info/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.user.info',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'setting',
|
||||
name: 'Setting',
|
||||
component: () => import('@/views/user/setting/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.user.setting',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default USER;
|
||||
@@ -0,0 +1,41 @@
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
|
||||
const VISUALIZATION: AppRouteRecordRaw = {
|
||||
path: '/visualization',
|
||||
name: 'visualization',
|
||||
component: DEFAULT_LAYOUT,
|
||||
redirect:'/visualization/data-analysis',
|
||||
meta: {
|
||||
locale: 'menu.visualization',
|
||||
requiresAuth: true,
|
||||
icon: 'icon-apps',
|
||||
order: 1,
|
||||
isFirst:true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'data-analysis',
|
||||
name: 'DataAnalysis',
|
||||
component: () => import('@/views/visualization/data-analysis/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.visualization.dataAnalysis',
|
||||
requiresAuth: true,
|
||||
roles: ['admin'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'multi-dimension-data-analysis',
|
||||
name: 'MultiDimensionDataAnalysis',
|
||||
component: () =>
|
||||
import('@/views/visualization/multi-dimension-data-analysis/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.visualization.multiDimensionDataAnalysis',
|
||||
requiresAuth: true,
|
||||
roles: ['admin'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default VISUALIZATION;
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { RouteRecordNormalized } from 'vue-router';
|
||||
|
||||
const modules = import.meta.glob('./modules/*.ts', { eager: true });
|
||||
const externalModules = import.meta.glob('./externalModules/*.ts', {
|
||||
eager: true,
|
||||
});
|
||||
|
||||
function formatModules(_modules: any, result: RouteRecordNormalized[]) {
|
||||
Object.keys(_modules).forEach((key) => {
|
||||
const defaultModule = _modules[key].default;
|
||||
if (!defaultModule) return;
|
||||
const moduleList = Array.isArray(defaultModule)
|
||||
? [...defaultModule]
|
||||
: [defaultModule];
|
||||
result.push(...moduleList);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export const appRoutes: RouteRecordNormalized[] = formatModules(modules, []);
|
||||
|
||||
export const appExternalRoutes: RouteRecordNormalized[] = formatModules(
|
||||
externalModules,
|
||||
[]
|
||||
);
|
||||
@@ -0,0 +1,173 @@
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
import PageLayout from '@/layout/page-layout.vue';
|
||||
// 业务路由
|
||||
const BUSINESS: AppRouteRecordRaw = {
|
||||
path: '/business',
|
||||
name: 'business',
|
||||
component: DEFAULT_LAYOUT,
|
||||
redirect: '/business/project',
|
||||
meta: {
|
||||
locale: 'menu.business',
|
||||
requiresAuth: true,
|
||||
icon: 'icon-heart-fill',
|
||||
permissionKey: 'business',
|
||||
order: 2,
|
||||
isFirst: true,
|
||||
},
|
||||
children: [
|
||||
// 项目管理
|
||||
{
|
||||
path: 'project',
|
||||
name: 'business-project',
|
||||
component: () => import('@/views/business/project/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.business.project',
|
||||
requiresAuth: true,
|
||||
roles: ['admin'],
|
||||
icon: 'icon-attachment',
|
||||
permissionKey: 'businessProject',
|
||||
},
|
||||
},
|
||||
// 空间管理
|
||||
{
|
||||
path: 'space',
|
||||
name: 'business-space',
|
||||
component: PageLayout,
|
||||
redirect: '/business/space/house-view',
|
||||
meta: {
|
||||
locale: 'menu.business.space',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-brush',
|
||||
permissionKey: 'businessSpace',
|
||||
},
|
||||
children: [
|
||||
// 房源剖视
|
||||
{
|
||||
path: 'house-view',
|
||||
name: 'business-space-house-view',
|
||||
component: () => import('@/views/business/space/house-view.vue'),
|
||||
meta: {
|
||||
locale: 'menu.business.house-view',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-brush',
|
||||
},
|
||||
},
|
||||
// 房源列表
|
||||
{
|
||||
path: 'house-list',
|
||||
name: 'business-space-house-list',
|
||||
component: () => import('@/views/business/space/house-list.vue'),
|
||||
meta: {
|
||||
locale: 'menu.business.house-list',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-brush',
|
||||
permissionKey: 'businessHouseList',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// 合同管理
|
||||
{
|
||||
path: 'contract',
|
||||
name: 'business-contract',
|
||||
component: PageLayout,
|
||||
redirect: '/business/contract/contract-list',
|
||||
meta: {
|
||||
locale: 'menu.business.contract',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-brush',
|
||||
permissionKey: 'businessContract',
|
||||
},
|
||||
children: [
|
||||
// 合同列表
|
||||
{
|
||||
path: 'contract-list',
|
||||
name: 'business-contract-list',
|
||||
component: () => import('@/views/business/contract/list.vue'),
|
||||
meta: {
|
||||
locale: 'menu.business.contract-list',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-brush',
|
||||
permissionKey: 'businessContractList',
|
||||
},
|
||||
},
|
||||
// 合同归档
|
||||
{
|
||||
path: 'contract-file',
|
||||
name: 'business-contract-file',
|
||||
component: () => import('@/views/business/contract/file.vue'),
|
||||
meta: {
|
||||
locale: 'menu.business.contract-file',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-brush',
|
||||
permissionKey: 'businessContractFile',
|
||||
},
|
||||
},
|
||||
// 合同模板
|
||||
{
|
||||
path: 'contract-template',
|
||||
name: 'business-contract-template',
|
||||
component: () => import('@/views/business/contract/template.vue'),
|
||||
meta: {
|
||||
locale: 'menu.business.contract-template',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-brush',
|
||||
permissionKey: 'businessContractTemplate',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// 租客管理
|
||||
{
|
||||
path: 'tenant',
|
||||
name: 'business-tenant',
|
||||
component: PageLayout,
|
||||
redirect: '/business/tenant/list',
|
||||
meta: {
|
||||
locale: 'menu.business.tenant',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-font-colors',
|
||||
permissionKey: 'businessTenant',
|
||||
},
|
||||
children: [
|
||||
// 租客列表
|
||||
{
|
||||
path: 'tenant-list',
|
||||
name: 'business-tenant-list',
|
||||
component: () => import('@/views/business/tenant/list.vue'),
|
||||
meta: {
|
||||
locale: 'menu.business.tenant-list',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-font-colors',
|
||||
permissionKey: 'businessTenantList',
|
||||
},
|
||||
},
|
||||
// 租客联系人
|
||||
{
|
||||
path: 'tenant-contacts',
|
||||
name: 'business-tenant-contacts',
|
||||
component: () => import('@/views/business/tenant/contacts.vue'),
|
||||
meta: {
|
||||
locale: 'menu.business.tenant.contacts',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-font-colors',
|
||||
permissionKey: 'businessTenantContacts',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default BUSINESS;
|
||||
@@ -0,0 +1,63 @@
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
import PageLayout from '@/layout/page-layout.vue';
|
||||
const DASHBOARD: AppRouteRecordRaw = {
|
||||
path: '/dashboard',
|
||||
name: 'dashboard',
|
||||
component: DEFAULT_LAYOUT,
|
||||
redirect: '/dashboard/workplace',
|
||||
meta: {
|
||||
locale: 'menu.dashboard.workplace',
|
||||
requiresAuth: true,
|
||||
icon: 'icon-dashboard',
|
||||
order: 1,
|
||||
isFirst: true,
|
||||
permissionKey: 'dashboard',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'workplace',
|
||||
name: 'Workplace',
|
||||
component: PageLayout,
|
||||
redirect: '/dashboard/workplace/step',
|
||||
meta: {
|
||||
locale: 'menu.dashboard.workplace',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-dashboard',
|
||||
permissionKey: 'workplace',
|
||||
// activeMenu: 'dashboard',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'step',
|
||||
name: 'Step',
|
||||
component: () => import('@/views/dashboard/workplace/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.form.step',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-exclamation-circle',
|
||||
permissionKey: 'step',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: 'monitor',
|
||||
name: 'Monitor',
|
||||
component: () => import('@/views/dashboard/monitor/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.dashboard.monitor',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
icon: 'icon-settings',
|
||||
permissionKey: 'monitor',
|
||||
// activeMenu: 'dashboard',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default DASHBOARD;
|
||||
@@ -0,0 +1,40 @@
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
|
||||
const FINANCE: AppRouteRecordRaw = {
|
||||
path: '/finance',
|
||||
name: 'finance',
|
||||
component: DEFAULT_LAYOUT,
|
||||
redirect: '/finance/bill',
|
||||
meta: {
|
||||
locale: 'menu.finance',
|
||||
icon: 'icon-settings',
|
||||
requiresAuth: true,
|
||||
order: 3,
|
||||
isFirst:true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'bill',
|
||||
name: 'bill',
|
||||
component: () => import('@/views/finance/bill/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.finance.bill',
|
||||
requiresAuth: true,
|
||||
roles: ['admin'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'money',
|
||||
name: 'money',
|
||||
component: () => import('@/views/finance/money/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.finance.money',
|
||||
requiresAuth: true,
|
||||
roles: ['admin'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default FINANCE;
|
||||
@@ -0,0 +1,40 @@
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
|
||||
const PROPERTY: AppRouteRecordRaw = {
|
||||
path: '/property',
|
||||
name: 'property',
|
||||
component: DEFAULT_LAYOUT,
|
||||
redirect: '/property/hydropower',
|
||||
meta: {
|
||||
locale: 'menu.property',
|
||||
requiresAuth: true,
|
||||
icon: 'icon-list',
|
||||
order: 4,
|
||||
isFirst:true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'hydropower', // The midline path complies with SEO specifications
|
||||
name: 'hydropower',
|
||||
component: () => import('@/views/property/hydropower/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.property.hydropower',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'reservation',
|
||||
name: 'reservation',
|
||||
component: () => import('@/views/property/reservation/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.property.reservation',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default PROPERTY;
|
||||
@@ -0,0 +1,69 @@
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
import PageLayout from '@/layout/page-layout.vue';
|
||||
// 设置
|
||||
const SETTING: AppRouteRecordRaw = {
|
||||
path: '/setting',
|
||||
name: 'setting',
|
||||
component: DEFAULT_LAYOUT,
|
||||
redirect: '/setting/basic',
|
||||
meta: {
|
||||
locale: 'menu.setting',
|
||||
requiresAuth: true,
|
||||
order: 5,
|
||||
// hideChildrenInMenu:true,
|
||||
isFirst: true,
|
||||
},
|
||||
children: [
|
||||
// 用户设置
|
||||
{
|
||||
path: 'user',
|
||||
name: 'user-setting',
|
||||
component: PageLayout,
|
||||
meta: {
|
||||
locale: 'menu.setting.user',
|
||||
requiresAuth: true,
|
||||
roles: ['admin'],
|
||||
icon: 'icon-file',
|
||||
},
|
||||
children: [
|
||||
// 用户列表
|
||||
{
|
||||
path: 'list',
|
||||
name: 'setting-user-list',
|
||||
component: () => import('@/views/setting/user/list.vue'),
|
||||
meta: {
|
||||
locale: 'menu.setting.user-list',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
// 角色权限
|
||||
{
|
||||
path: 'role',
|
||||
name: 'setting-user-role',
|
||||
component: () => import('@/views/setting/user/role.vue'),
|
||||
meta: {
|
||||
locale: 'menu.setting.role',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// 系统配置
|
||||
{
|
||||
path: 'system',
|
||||
name: 'system-setting',
|
||||
component: () => import('@/views/setting/system/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.setting.system',
|
||||
requiresAuth: true,
|
||||
roles: ['admin'],
|
||||
icon: 'icon-settings',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default SETTING;
|
||||
@@ -0,0 +1,22 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import type { RouteMeta, NavigationGuard } from 'vue-router';
|
||||
|
||||
export type Component<T = any> =
|
||||
| ReturnType<typeof defineComponent>
|
||||
| (() => Promise<typeof import('*.vue')>)
|
||||
| (() => Promise<T>);
|
||||
|
||||
export interface AppRouteRecordRaw {
|
||||
path: string;
|
||||
name?: string | symbol;
|
||||
meta?: RouteMeta & {
|
||||
permissionKey?: string; // 权限标识,与接口返回的perm_key对应
|
||||
};
|
||||
redirect?: string;
|
||||
component: Component | string;
|
||||
children?: AppRouteRecordRaw[];
|
||||
alias?: string | string[];
|
||||
props?: Record<string, any>;
|
||||
beforeEnter?: NavigationGuard | NavigationGuard[];
|
||||
fullPath?: string;
|
||||
}
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
import 'vue-router';
|
||||
|
||||
declare module 'vue-router' {
|
||||
interface RouteMeta {
|
||||
roles?: string[]; // Controls roles that have access to the page
|
||||
requiresAuth: boolean; // Whether login is required to access the current page (every route must declare)
|
||||
icon?: string; // The icon show in the side menu
|
||||
locale?: string; // The locale name show in side menu and breadcrumb
|
||||
hideInMenu?: boolean; // If true, it is not displayed in the side menu
|
||||
hideChildrenInMenu?: boolean; // if set true, the children are not displayed in the side menu
|
||||
activeMenu?: string; // if set name, the menu will be highlighted according to the name you set
|
||||
order?: number; // Sort routing menu items. If set key, the higher the value, the more forward it is
|
||||
noAffix?: boolean; // if set true, the tag will not affix in the tab-bar
|
||||
ignoreCache?: boolean; // if set true, the page will not be cached
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user