From 9fa0985c5e9afe5d321a9fd5cc0c9274de1806d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?cls=5F=E5=AE=81=E6=B3=A2=E6=9C=AC=E6=9C=BA?= <908705107@qq.com> Date: Mon, 8 Jun 2026 21:47:37 +0800 Subject: [PATCH] Restore ZQ-style lightweight control center --- .../src/views/_core/control-center/index.vue | 1350 ++++++++++------- 1 file changed, 835 insertions(+), 515 deletions(-) diff --git a/web/apps/web-ele/src/views/_core/control-center/index.vue b/web/apps/web-ele/src/views/_core/control-center/index.vue index da5eee6..908467d 100644 --- a/web/apps/web-ele/src/views/_core/control-center/index.vue +++ b/web/apps/web-ele/src/views/_core/control-center/index.vue @@ -5,36 +5,46 @@ import type { WorkflowListItem, WorkflowRunListItem, } from '#/api/ai-platform/ai-platform'; +import type { UserAnnouncement } from '#/api/core/announcement'; +import type { Message } from '#/api/core/message'; import { computed, onMounted, reactive, ref } from 'vue'; import { useRouter } from 'vue-router'; import { Page } from '@vben/common-ui'; import { + Bell, Bot, BookOpen, - CircleCheckBig, - Clock3, + Calendar, + CheckCircle2, + ClipboardList, + CloudSun, + Cpu, + Database, + FileText, GitBranch, + LayoutGrid, + Mail, MessageSquare, + Network, Play, - RefreshCw, Route, + Send, + Server, Settings, Shield, - Sparkles, Users, Workflow, } from '@vben/icons'; +import { useUserStore } from '@vben/stores'; import { ElButton, - ElCard, ElEmpty, + ElProgress, ElSkeleton, ElTag, - ElTimeline, - ElTimelineItem, } from 'element-plus'; import { @@ -43,360 +53,541 @@ import { getKnowledgeBaseListApi, getWorkflowListApi, } from '#/api/ai-platform/ai-platform'; +import { + getUnreadAnnouncementCountApi, + getUserAnnouncementListApi, +} from '#/api/core/announcement'; +import { getMessageListApi, getUnreadCountApi } from '#/api/core/message'; defineOptions({ name: 'ControlCenter' }); const router = useRouter(); +const userStore = useUserStore(); + const loading = ref(false); const loaded = ref(false); +const now = ref(new Date()); const agents = ref([]); const workflows = ref([]); const knowledgeBases = ref([]); const runs = ref([]); +const announcements = ref([]); +const messages = ref([]); const stats = reactive({ agentTotal: 0, - workflowTotal: 0, + announcementUnread: 0, knowledgeTotal: 0, + messageUnread: 0, runTotal: 0, + workflowTotal: 0, +}); + +const displayName = computed(() => { + return ( + userStore.userInfo?.realName || + userStore.userInfo?.username || + '超级管理员' + ); +}); + +const hour = computed(() => now.value.getHours()); +const greeting = computed(() => { + if (hour.value < 6) return '凌晨好'; + if (hour.value < 12) return '上午好'; + if (hour.value < 18) return '下午好'; + return '晚上好'; +}); + +const currentTime = computed(() => { + return now.value.toLocaleTimeString('zh-CN', { hour12: false }); +}); + +const currentDate = computed(() => { + return now.value.toLocaleDateString('zh-CN', { + day: 'numeric', + month: 'long', + weekday: 'long', + year: 'numeric', + }); }); const publishedAgents = computed( () => agents.value.filter((item) => item.status === 'published').length, ); + const publishedWorkflows = computed( () => workflows.value.filter((item) => item.status === 'published').length, ); -const successfulRuns = computed( - () => runs.value.filter((item) => item.status === 'success').length, + +const completedRuns = computed( + () => + runs.value.filter((item) => + ['completed', 'success'].includes(item.status), + ).length, ); + const failedRuns = computed( () => runs.value.filter((item) => item.status === 'failed').length, ); -const quickEntries = [ +const tokenTotal = computed(() => + runs.value.reduce((sum, item) => sum + (item.total_tokens || 0), 0), +); + +const successRate = computed(() => { + if (!runs.value.length) return 0; + return Math.round((completedRuns.value / runs.value.length) * 100); +}); + +const collaborationItems = computed(() => [ { - desc: '沉淀角色能力、提示词和工具调用策略', - icon: Bot, + color: 'blue', + desc: '发起需求分诊、任务拆解和角色协作', + icon: Send, path: '/ai-platform/agent', - title: '智能体', + title: '我发起的', + value: stats.agentTotal, }, { - desc: '编排多 Agent 协作、人工确认和系统调用', + color: 'amber', + desc: '待人工确认、待补充上下文的节点', + icon: ClipboardList, + path: '/ai-platform/workflow-runs', + title: '我的待办', + value: Math.max(stats.runTotal - completedRuns.value, 0), + }, + { + color: 'violet', + desc: '正在运行或最近完成的协作流程', + icon: Workflow, + path: '/ai-platform/workflow-runs', + title: '我的在办', + value: runs.value.length, + }, + { + color: 'cyan', + desc: '已沉淀为可复用的智能体能力', + icon: CheckCircle2, + path: '/ai-platform/agent', + title: '我的已办', + value: publishedAgents.value, + }, + { + color: 'orange', + desc: '消息、公告和流程通知', + icon: Bell, + path: '/message/announcement-list', + title: '抄送我的', + value: stats.messageUnread + stats.announcementUnread, + }, + { + color: 'green', + desc: '进入编排器创建多 Agent 流程', + icon: Play, + path: '/ai-platform/workflow', + title: '发起流程', + value: stats.workflowTotal, + }, +]); + +const appEntries = [ + { + color: 'blue', + icon: Bot, + path: '/ai-platform/agent', + title: '智能体协作', + }, + { + color: 'cyan', icon: Workflow, path: '/ai-platform/workflow', title: '流程编排', }, { - desc: '管理文档、分段、向量索引和检索日志', + color: 'amber', icon: BookOpen, path: '/ai-platform/knowledge-base', title: '知识库', }, { - desc: '进入 Codex 协作入口,串联开发任务', + color: 'violet', icon: MessageSquare, path: '/agent-chat/codex', - title: 'Codex', + title: 'Codex 协作', }, ]; -const adminEntries = [ - { icon: Users, path: '/system/user', title: '用户管理' }, - { icon: Shield, path: '/system/role', title: '角色权限' }, - { icon: Route, path: '/system/menu', title: '菜单管理' }, - { icon: Settings, path: '/system-config', title: '系统配置' }, +const quickLinks = [ + { + icon: Settings, + path: '/system-config', + title: '系统配置', + }, + { + icon: Users, + path: '/system/user', + title: '用户管理', + }, + { + icon: Shield, + path: '/system/role', + title: '角色权限', + }, + { + icon: Route, + path: '/system/menu', + title: '菜单管理', + }, + { + icon: FileText, + path: '/message/announcement', + title: '公告管理', + }, + { + icon: Mail, + path: '/message/announcement-list', + title: '消息中心', + }, + { + icon: GitBranch, + path: '/ai-platform/workflow-runs', + title: '执行历史', + }, + { + icon: Database, + path: '/system/new-permission', + title: 'API 管理', + }, ]; +const resourceCards = computed(() => [ + { + desc: `${publishedAgents.value} 个已发布,可参与协作`, + icon: Bot, + label: '智能体', + tone: 'blue', + value: stats.agentTotal, + }, + { + desc: `${publishedWorkflows.value} 条已发布,可直接运行`, + icon: Workflow, + label: '流程', + tone: 'cyan', + value: stats.workflowTotal, + }, + { + desc: `${knowledgeBases.value.length} 个最近维护`, + icon: BookOpen, + label: '知识库', + tone: 'amber', + value: stats.knowledgeTotal, + }, + { + desc: `成功 ${completedRuns.value} / 失败 ${failedRuns.value}`, + icon: Play, + label: '执行记录', + tone: 'green', + value: stats.runTotal, + }, +]); + function go(path: string) { router.push(path); } function formatTime(value?: string) { if (!value) return '-'; - return value.replace('T', ' ').slice(0, 19); + return value.replace('T', ' ').slice(0, 16); +} + +function getStatusType(status: string) { + if (['completed', 'published', 'success'].includes(status)) return 'success'; + if (status === 'failed') return 'danger'; + if (status === 'draft') return 'info'; + return 'primary'; } async function loadDashboard() { loading.value = true; + now.value = new Date(); try { - const [agentRes, workflowRes, knowledgeRes, runRes] = await Promise.all([ + const [ + agentRes, + workflowRes, + knowledgeRes, + runRes, + announcementRes, + announcementUnreadRes, + messageRes, + messageUnreadRes, + ] = await Promise.all([ getAgentListApi({ page: 1, pageSize: 6 }), getWorkflowListApi({ page: 1, pageSize: 6 }), getKnowledgeBaseListApi({ page: 1, pageSize: 6 }), getAllWorkflowRunsApi({ page: 1, pageSize: 6 }), + getUserAnnouncementListApi({ page: 1, pageSize: 5 }), + getUnreadAnnouncementCountApi(), + getMessageListApi({ page: 1, pageSize: 5 }), + getUnreadCountApi(), ]); + agents.value = agentRes.items || []; workflows.value = workflowRes.items || []; knowledgeBases.value = knowledgeRes.items || []; runs.value = runRes.items || []; + announcements.value = announcementRes.items || []; + messages.value = messageRes.items || []; + stats.agentTotal = agentRes.total || agents.value.length; stats.workflowTotal = workflowRes.total || workflows.value.length; stats.knowledgeTotal = knowledgeRes.total || knowledgeBases.value.length; stats.runTotal = runRes.total || runs.value.length; + stats.announcementUnread = announcementUnreadRes.count || 0; + stats.messageUnread = messageUnreadRes.total || 0; loaded.value = true; } finally { loading.value = false; } } -onMounted(loadDashboard); +onMounted(() => { + loadDashboard(); + window.setInterval(() => { + now.value = new Date(); + }, 1000); +});