diff --git a/web/src/components/layout/NavBar.vue b/web/src/components/layout/NavBar.vue index fba8a7d..6aa4c6e 100644 --- a/web/src/components/layout/NavBar.vue +++ b/web/src/components/layout/NavBar.vue @@ -19,6 +19,45 @@ > 项目 + + 对话 + + + 模板 + + + 我的用量 + + + | + + LLM Endpoints + + + LLM Models + + + 全局用量 + + import('@/views/workspaces/WorkspaceHomeView.vue'), meta: { requiresAuth: true }, }, + { + path: '/chat', + name: 'chat-home', + component: () => import('@/views/chat/ChatHomeView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/chat/:conversationId', + name: 'chat-detail', + component: () => import('@/views/chat/ChatDetailView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/projects/:pid/chat', + name: 'project-chat-home', + component: () => import('@/views/chat/ChatHomeView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/projects/:pid/chat/:conversationId', + name: 'project-chat-detail', + component: () => import('@/views/chat/ChatDetailView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/prompt-templates', + name: 'prompt-templates', + component: () => + import('@/views/prompt-templates/PromptTemplatesView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/me/usage', + name: 'me-usage', + component: () => import('@/views/admin/UsageView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/admin/llm-endpoints', + name: 'admin-llm-endpoints', + component: () => import('@/views/admin/LLMEndpointsView.vue'), + meta: { requiresAuth: true, requiresAdmin: true }, + }, + { + path: '/admin/llm-models', + name: 'admin-llm-models', + component: () => import('@/views/admin/LLMModelsView.vue'), + meta: { requiresAuth: true, requiresAdmin: true }, + }, + { + path: '/admin/usage', + name: 'admin-usage', + component: () => import('@/views/admin/UsageView.vue'), + props: { adminMode: true }, + meta: { requiresAuth: true, requiresAdmin: true }, + }, ] const router = createRouter({ @@ -74,6 +130,9 @@ router.beforeEach((to) => { if (to.meta.requiresAuth && !auth.isAuthenticated) { return { name: 'login', query: { next: to.fullPath } } } + if (to.meta.requiresAdmin && !auth.isAdmin) { + return { name: 'home' } + } if (to.name === 'login' && auth.isAuthenticated) { return { name: 'home' } } diff --git a/web/src/stores/auth.ts b/web/src/stores/auth.ts index 14b0162..2ea507d 100644 --- a/web/src/stores/auth.ts +++ b/web/src/stores/auth.ts @@ -53,6 +53,7 @@ export const useAuthStore = defineStore('auth', () => { const user = ref(safeReadJSON('user', null)) const isAuthenticated = computed(() => !!token.value) + const isAdmin = computed(() => !!user.value?.is_admin) function setSession(t: string, u: User) { token.value = t @@ -68,5 +69,5 @@ export const useAuthStore = defineStore('auth', () => { safeRemove('user') } - return { token, user, isAuthenticated, setSession, clearSession } + return { token, user, isAuthenticated, isAdmin, setSession, clearSession } }) diff --git a/web/src/views/prompt-templates/PromptTemplatesView.vue b/web/src/views/prompt-templates/PromptTemplatesView.vue new file mode 100644 index 0000000..386840a --- /dev/null +++ b/web/src/views/prompt-templates/PromptTemplatesView.vue @@ -0,0 +1,184 @@ + + + + + + Prompt 模板 + + + + 新增 + + + + + + + + + + + + 个人(仅自己可见) + + + 系统(所有用户可见) + + + + + + + + + + + 取消 + + + 保存 + + + + + + + + +