feat(网页端): 完善登录后工作台与项目管理体验
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled

This commit is contained in:
Cheng Zhou
2026-07-09 14:59:06 +08:00
parent 0aff10fe0d
commit 1dc10f569d
15 changed files with 1418 additions and 185 deletions
+32 -27
View File
@@ -13,6 +13,7 @@ import ForgotPassword from "../views/ForgotPassword.vue";
import DesktopServerSettings from "../views/DesktopServerSettings.vue";
import DesktopProjectEntry from "../views/DesktopProjectEntry.vue";
import DesktopSessionRestore from "../views/DesktopSessionRestore.vue";
import WebWorkbenchEntry from "../views/WebWorkbenchEntry.vue";
import StudyHome from "../views/StudyHome.vue";
import FaqDetail from "../views/FaqDetail.vue";
import AuditLogs from "../views/admin/AuditLogs.vue";
@@ -63,6 +64,14 @@ import { DESKTOP_SESSION_RESTORE_PATH, shouldPreserveDesktopSessionOnAuthCheckFa
const SYSTEM_PERMISSION_READ = "system:permissions:read";
const SYSTEM_PERMISSION_PROJECT_CONFIG = "system:permissions:project_config";
const WEB_WORKBENCH_ENTRY_PATH = "/workbench";
const DESKTOP_PROJECT_ENTRY_PATH = "/desktop/project-entry";
const resolveWorkbenchEntryPath = (isDesktopRuntime: boolean) =>
isDesktopRuntime ? DESKTOP_PROJECT_ENTRY_PATH : WEB_WORKBENCH_ENTRY_PATH;
const isWorkbenchEntryPath = (path: string) =>
path === WEB_WORKBENCH_ENTRY_PATH || path === DESKTOP_PROJECT_ENTRY_PATH;
const routes: RouteRecordRaw[] = [
{
@@ -96,7 +105,13 @@ const routes: RouteRecordRaw[] = [
meta: { public: true, title: "恢复登录状态" },
},
{
path: "/desktop/project-entry",
path: WEB_WORKBENCH_ENTRY_PATH,
name: "WorkbenchEntry",
component: WebWorkbenchEntry,
meta: { title: "工作台入口" },
},
{
path: DESKTOP_PROJECT_ENTRY_PATH,
name: "DesktopProjectEntry",
component: DesktopProjectEntry,
meta: { title: "选择工作入口" },
@@ -533,6 +548,14 @@ router.beforeEach(async (to, _from, next) => {
next({ path: desktopRedirect });
return;
}
if (isDesktopRuntime && to.path === WEB_WORKBENCH_ENTRY_PATH) {
next({ path: DESKTOP_PROJECT_ENTRY_PATH });
return;
}
if (!isDesktopRuntime && to.path === DESKTOP_PROJECT_ENTRY_PATH) {
next({ path: WEB_WORKBENCH_ENTRY_PATH });
return;
}
const auth = useAuthStore();
const studyStore = useStudyStore();
@@ -559,23 +582,17 @@ router.beforeEach(async (to, _from, next) => {
next({ path: "/login" });
return;
}
if (token && !studyStore.currentStudy && !isDesktopRuntime) {
if (isAdmin) {
await studyStore.ensureDefaultActiveStudy();
} else {
await studyStore.ensureDefaultStudy();
}
}
const workbenchEntryPath = resolveWorkbenchEntryPath(isDesktopRuntime);
if (token && studyStore.currentStudy && auth.user?.email) {
studyStore.rememberCurrentStudyForUser(auth.user.email);
}
if (isDesktopRuntime && token && to.path === "/desktop/project-entry" && studyStore.currentStudy) {
if (token && isWorkbenchEntryPath(to.path) && studyStore.currentStudy) {
studyStore.clearCurrentStudy();
}
if (isDesktopRuntime && token && !isAdmin && to.path.startsWith("/admin")) {
next({ path: "/desktop/project-entry" });
next({ path: DESKTOP_PROJECT_ENTRY_PATH });
return;
}
@@ -584,28 +601,16 @@ router.beforeEach(async (to, _from, next) => {
}
if (isDesktopRuntime && token && to.path === "/") {
next({ path: studyStore.currentStudy ? "/project/overview" : "/desktop/project-entry" });
next({ path: studyStore.currentStudy ? "/project/overview" : DESKTOP_PROJECT_ENTRY_PATH });
return;
}
if (isAdmin && to.path === "/") {
next({ path: studyStore.currentStudy ? "/project/overview" : "/admin/users" });
if (token && to.path === "/") {
next({ path: studyStore.currentStudy ? "/project/overview" : workbenchEntryPath });
return;
}
if ((to.path === "/login" || to.path === "/register") && token) {
if (!auth.forceLogin) {
if (isDesktopRuntime) {
next({ path: "/desktop/project-entry" });
return;
}
next({
path: isAdmin
? studyStore.currentStudy
? "/project/overview"
: "/admin/users"
: studyStore.currentStudy
? "/project/overview"
: "/admin/projects",
});
next({ path: workbenchEntryPath });
return;
}
}
@@ -668,7 +673,7 @@ router.beforeEach(async (to, _from, next) => {
}
}
if (to.meta.requiresStudy && !studyStore.currentStudy) {
next({ path: isDesktopRuntime ? "/desktop/project-entry" : isAdmin ? "/admin/users" : "/admin/projects" });
next({ path: workbenchEntryPath });
return;
}
if (to.meta.requiresStudy && studyStore.currentStudy) {