Files
ClassHelper/packages/desktop-client/src/renderer/router/index.ts
T
LoveChengke c7f215a09c feat(courseware,docs): 完善课件传输与岛编辑并统一全仓文档
- 增加课件上传、班级可见范围、设备补收与传输进度
- 整合自定义灵动岛编辑器和相关客户端交互
- 同步三端契约、数据库迁移、部署配置与隔离回归
- 按源码统一文档与官网说明,移除过时任务书和审查记录
- 保持产品版本为 1.4.0
2026-10-18 11:53:37 +08:00

136 lines
4.7 KiB
TypeScript

import { createRouter, createWebHashHistory, type RouteRecordRaw } from 'vue-router';
import { useAuthStore } from '../stores/auth.js';
import { useUiStore } from '../stores/ui.js';
/**
* Electron 生产环境通过 file:// 加载页面,无法使用 history 模式,
* 因此统一使用 hash 路由(开发与打包行为一致)。
*/
const routes: RouteRecordRaw[] = [
{
path: '/login',
name: 'login',
component: () => import('../views/LoginView.vue'),
meta: { public: true, title: '登录' },
},
{
path: '/',
component: () => import('../layouts/ClientLayout.vue'),
redirect: '/schedule',
children: [
{ path: 'courseware', name: 'courseware', component: () => import('../views/CoursewareView.vue'), meta: { title: '课件' } },
{
path: 'schedule',
name: 'schedule',
component: () => import('../views/ScheduleView.vue'),
meta: { title: '课表' },
},
{
path: 'homeworks',
name: 'homeworks',
component: () => import('../views/HomeworkView.vue'),
meta: { title: '作业' },
},
{
path: 'notifications',
name: 'notifications',
component: () => import('../views/NotificationView.vue'),
meta: { title: '通知' },
},
{
path: 'grades',
name: 'grades',
component: () => import('../views/GradeView.vue'),
meta: { title: '成绩' },
},
/* 设置:主侧边栏「设置」分组下的六个子页(ClassIsland 式 主菜单+子菜单) */
{
path: 'settings',
redirect: '/settings/general',
},
{
path: 'settings/general',
name: 'settings-general',
component: () => import('../views/settings/GeneralSettingsView.vue'),
meta: { title: '通用设置' },
},
{
path: 'settings/appearance',
name: 'settings-appearance',
component: () => import('../views/settings/AppearanceView.vue'),
meta: { title: '外观' },
},
{
path: 'settings/island',
name: 'settings-island',
component: () => import('../views/settings/IslandSettingsView.vue'),
meta: { title: '灵动岛' },
},
{
path: 'settings/island/editor',
name: 'settings-island-editor',
component: () => import('../views/settings/IslandEditorView.vue'),
meta: { title: '自定义灵动岛' },
},
{
path: 'settings/reminder',
name: 'settings-reminder',
component: () => import('../views/settings/ReminderSettingsView.vue'),
meta: { title: '提醒' },
},
{
path: 'settings/account',
name: 'settings-account',
component: () => import('../views/settings/AccountSettingsView.vue'),
meta: { title: '账号' },
},
{
path: 'settings/about',
name: 'settings-about',
component: () => import('../views/settings/AboutView.vue'),
meta: { title: '关于' },
},
{
/**
* 开发者(需求 10)。入口只在 `config.developerMode === true` 时出现在侧栏上,
* 但**路由始终注册**:关掉开关后侧栏项消失,已打开的页面靠一条守卫弹回「通用」,
* 不做成条件注册 —— 条件注册会让 `router.getRoutes()` 随配置变化,
* ClientLayout 的开发期自检与直接输 URL 的行为都会变得难以预期。
*/
path: 'settings/developer',
name: 'settings-developer',
component: () => import('../views/settings/DeveloperSettingsView.vue'),
meta: { title: '开发者' },
},
],
},
{ path: '/:pathMatch(.*)*', redirect: '/schedule' },
];
export const router = createRouter({
history: createWebHashHistory(),
routes,
});
router.beforeEach((to) => {
const auth = useAuthStore();
if (to.meta.public) {
if (to.name === 'login' && auth.isAuthenticated) return { name: 'schedule' };
return true;
}
if (!auth.isAuthenticated) return { name: 'login' };
/**
* 开发者页(需求 10)只在开发者模式开启时可进:侧栏项本身也是条件显示的,
* 但配置可能是在**停留在这个页面时**被关掉的(「通用」页的开关),
* 所以需要这条守卫把它弹回「通用」,不让用户在看一个"已经不该存在"的页面。
*
* 这里读的是 ui store 里的状态(由 `ui.init()` 在首屏前从主进程配置恢复),
* 不额外调 `window.desktop.getConfig()` —— 导航守卫是同步高频路径,
* 每次跳转都跨一次 contextBridge 不值得。
*/
if (to.name === 'settings-developer' && !useUiStore().developerMode) return { name: 'settings-general' };
return true;
});
export default router;