index.js
4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { createRouter, createWebHistory } from 'vue-router'
import { useAuth } from '@/composables/useAuth'
const routes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
},
{
path: '/',
redirect: '/agent/master'
},
{
path: '/agents/:agentId?',
redirect: to => `/agent/${to.params.agentId || 'agent-creator'}`,
},
{
path: '/agent/:agentId/:convId?',
name: 'AgentChat',
component: () => import('@/views/AgentChat.vue'),
props: true,
},
{
// agentId 必填:`/:id/agents`(无 agentId)要落到下面的 CompanyDetail 去渲染团队 tab。
// 之前写成 :agentId? 时,这条路由会抢占 /:id/agents,导致导航栏「Team」永远打开
// AgentChat,CompanyDashboard 的团队 tab(含 Org Graph 区块)完全不可达。
path: '/:id/agents/:agentId/:convId?',
name: 'CompanyAgentChat',
component: () => import('@/views/AgentChat.vue'),
props: true,
},
{
path: '/company',
name: 'CompanyList',
component: () => import('@/views/CompanyDashboard.vue'),
},
{
// 39 号文档 §二 P2:'goals'/'okr' 两个 tab 值已摘掉 —— 前者是 OKR 树的历史命名残留
// (真正的 goal/task 看板走下面 'task-board' 独立路由,不挤在这条 :tab 正则里),
// 后者是随 /okr 一起废弃的孤儿页面。
path: '/:id/:tab(overview|agents|pipelines|sop|team|files|messages|skills|jobs|workspace)',
name: 'CompanyDetail',
component: () => import('@/views/CompanyDashboard.vue'),
props: true
},
{
// P3 · 图执行控制台(org graph + work graph + 节点详情)。
// 路径段 'graph-console' 不在上面 CompanyDetail 的 :tab 白名单里,两条路由不冲突。
path: '/:id/graph-console',
name: 'GraphConsole',
component: () => import('@/views/GraphConsole.vue'),
props: true,
},
{
// 39 号文档 §二 P2:goal/task 两级看板独立页,同样不挤进 :tab 正则(信息密度高,值得一整页)。
path: '/:id/task-board',
name: 'TaskBoard',
component: () => import('@/views/TaskBoard.vue'),
props: true,
},
// 新增独立页面
{
path: '/skills',
name: 'SkillsMarket',
component: () => import('@/views/SkillsMarket.vue'),
},
{
path: '/jobs',
name: 'JobsPanel',
component: () => import('@/views/JobsPanel.vue'),
},
{
path: '/tasks/:taskId?',
name: 'TaskTimeline',
component: () => import('@/views/TaskTimeline.vue'),
},
{
path: '/pipelines',
name: 'PipelineEditor',
component: () => import('@/views/PipelineEditor.vue'),
},
{
path: '/quota',
name: 'QuotaMonitor',
component: () => import('@/views/QuotaMonitor.vue'),
},
{
path: '/dream',
name: 'DreamConsole',
component: () => import('@/views/DreamConsole.vue'),
},
// P5 · DevLoop Projects 列表 + Dashboard + Ops
{
path: '/devloop',
name: 'DevLoopProjects',
component: () => import('@/views/DevLoopProjects.vue'),
},
{
path: '/devloop/:pid',
name: 'DevLoopDashboard',
component: () => import('@/views/DevLoopDashboard.vue'),
props: true,
},
{
path: '/devloop/:pid/ops/:tab(bugs|loops|changelog|progress)',
name: 'DevLoopOps',
component: () => import('@/views/DevLoopOps.vue'),
props: true,
},
{
path: '/devloop/:pid/new-requirement',
name: 'DevLoopNewRequirement',
component: () => import('@/views/DevLoopNewRequirement.vue'),
},
]
const router = createRouter({
history: createWebHistory(),
routes,
})
// Phase 0(38 号文档):未登录访问任何非登录页 → 跳登录页;已登录访问登录页 → 跳回首页
// (或 redirect query 指回的目标)。这一步还不做「你能不能看这个 company」的归属校验
// (Phase 2 才做),只判断「你登录了没有」。
router.beforeEach(async (to) => {
if (to.name === 'Login') return true
const { user, checkAuth } = useAuth()
await checkAuth()
if (!user.value) {
return { name: 'Login', query: { redirect: to.fullPath } }
}
return true
})
export default router