Restore control center copy
This commit is contained in:
@@ -8,7 +8,7 @@ import type {
|
||||
import type { UserAnnouncement } from '#/api/core/announcement';
|
||||
import type { Message } from '#/api/core/message';
|
||||
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
@@ -39,13 +39,7 @@ import {
|
||||
} from '@vben/icons';
|
||||
import { useUserStore } from '@vben/stores';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElEmpty,
|
||||
ElProgress,
|
||||
ElSkeleton,
|
||||
ElTag,
|
||||
} from 'element-plus';
|
||||
import { ElButton, ElEmpty, ElProgress, ElSkeleton, ElTag } from 'element-plus';
|
||||
|
||||
import {
|
||||
getAgentListApi,
|
||||
@@ -73,6 +67,7 @@ const userStore = useUserStore();
|
||||
const loading = ref(false);
|
||||
const loaded = ref(false);
|
||||
const now = ref(new Date());
|
||||
const timer = ref<number>();
|
||||
const agents = ref<AgentListItem[]>([]);
|
||||
const workflows = ref<WorkflowListItem[]>([]);
|
||||
const knowledgeBases = ref<KnowledgeBaseListItem[]>([]);
|
||||
@@ -99,26 +94,26 @@ const displayName = computed(() => {
|
||||
);
|
||||
});
|
||||
|
||||
const hour = computed(() => now.value.getHours());
|
||||
const greeting = computed(() => {
|
||||
if (hour.value < 6) return '凌晨好';
|
||||
if (hour.value < 12) return '上午好';
|
||||
if (hour.value < 18) return '下午好';
|
||||
const hour = now.value.getHours();
|
||||
if (hour < 6) return '凌晨好';
|
||||
if (hour < 12) return '上午好';
|
||||
if (hour < 18) return '下午好';
|
||||
return '晚上好';
|
||||
});
|
||||
|
||||
const currentTime = computed(() => {
|
||||
return now.value.toLocaleTimeString('zh-CN', { hour12: false });
|
||||
});
|
||||
const currentTime = computed(() =>
|
||||
now.value.toLocaleTimeString('zh-CN', { hour12: false }),
|
||||
);
|
||||
|
||||
const currentDate = computed(() => {
|
||||
return now.value.toLocaleDateString('zh-CN', {
|
||||
const currentDate = computed(() =>
|
||||
now.value.toLocaleDateString('zh-CN', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
});
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
const publishedAgents = computed(
|
||||
() => agents.value.filter((item) => item.status === 'published').length,
|
||||
@@ -151,7 +146,6 @@ const successRate = computed(() => {
|
||||
const collaborationItems = computed(() => [
|
||||
{
|
||||
color: 'blue',
|
||||
desc: '发起需求分诊、任务拆解和角色协作',
|
||||
icon: Send,
|
||||
path: '/ai-platform/agent',
|
||||
title: '我发起的',
|
||||
@@ -159,7 +153,6 @@ const collaborationItems = computed(() => [
|
||||
},
|
||||
{
|
||||
color: 'amber',
|
||||
desc: '待人工确认、待补充上下文的节点',
|
||||
icon: ClipboardList,
|
||||
path: '/ai-platform/workflow-runs',
|
||||
title: '我的待办',
|
||||
@@ -167,7 +160,6 @@ const collaborationItems = computed(() => [
|
||||
},
|
||||
{
|
||||
color: 'violet',
|
||||
desc: '正在运行或最近完成的协作流程',
|
||||
icon: Workflow,
|
||||
path: '/ai-platform/workflow-runs',
|
||||
title: '我的在办',
|
||||
@@ -175,7 +167,6 @@ const collaborationItems = computed(() => [
|
||||
},
|
||||
{
|
||||
color: 'cyan',
|
||||
desc: '已沉淀为可复用的智能体能力',
|
||||
icon: CheckCircle2,
|
||||
path: '/ai-platform/agent',
|
||||
title: '我的已办',
|
||||
@@ -183,7 +174,6 @@ const collaborationItems = computed(() => [
|
||||
},
|
||||
{
|
||||
color: 'orange',
|
||||
desc: '消息、公告和流程通知',
|
||||
icon: Bell,
|
||||
path: '/message/announcement-list',
|
||||
title: '抄送我的',
|
||||
@@ -191,7 +181,6 @@ const collaborationItems = computed(() => [
|
||||
},
|
||||
{
|
||||
color: 'green',
|
||||
desc: '进入编排器创建多 Agent 流程',
|
||||
icon: Play,
|
||||
path: '/ai-platform/workflow',
|
||||
title: '发起流程',
|
||||
@@ -271,28 +260,24 @@ const quickLinks = [
|
||||
|
||||
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',
|
||||
@@ -304,6 +289,7 @@ const serverCards = computed(() => {
|
||||
const overview = serverOverview.value;
|
||||
const realtime = realtimeStats.value;
|
||||
const memory = realtime?.memory_details || overview?.memory_info.virtual;
|
||||
|
||||
return [
|
||||
{
|
||||
desc: `${overview?.cpu_info.total_cores || '-'} 核心`,
|
||||
@@ -323,9 +309,9 @@ const serverCards = computed(() => {
|
||||
value: `${Math.round(realtime?.memory_percent ?? overview?.memory_info.virtual.percent ?? 0)}%`,
|
||||
},
|
||||
{
|
||||
desc: `累计 ${formatBytes(overview?.disk_info.total_read_bytes)} / ${formatBytes(overview?.disk_info.total_write_bytes)}`,
|
||||
desc: `累计读写 ${formatBytes(overview?.disk_info.total_read_bytes)} / ${formatBytes(overview?.disk_info.total_write_bytes)}`,
|
||||
icon: Server,
|
||||
label: '磁盘读/写',
|
||||
label: '磁盘读取',
|
||||
tone: 'amber',
|
||||
value: `${formatBytes(realtime?.disk_io.read_speed)}/s`,
|
||||
},
|
||||
@@ -370,6 +356,7 @@ function getStatusType(status: string) {
|
||||
async function loadDashboard() {
|
||||
loading.value = true;
|
||||
now.value = new Date();
|
||||
|
||||
try {
|
||||
const [
|
||||
agentRes,
|
||||
@@ -418,10 +405,14 @@ async function loadDashboard() {
|
||||
|
||||
onMounted(() => {
|
||||
loadDashboard();
|
||||
window.setInterval(() => {
|
||||
timer.value = window.setInterval(() => {
|
||||
now.value = new Date();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (timer.value) window.clearInterval(timer.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -429,10 +420,10 @@ onMounted(() => {
|
||||
<div class="workbench">
|
||||
<section class="top-grid">
|
||||
<div class="welcome-card panel">
|
||||
<div class="avatar-badge">超</div>
|
||||
<div class="avatar-badge">AI</div>
|
||||
<div class="welcome-copy">
|
||||
<h2>{{ greeting }},{{ displayName }},欢迎回来</h2>
|
||||
<p>今天是个好日子,适合让智能体把重复工作接过去。</p>
|
||||
<p>这里汇总智能体、流程编排、公告消息和服务器状态,方便快速进入协作工作。</p>
|
||||
</div>
|
||||
<div class="time-box">
|
||||
<strong>{{ currentTime }}</strong>
|
||||
@@ -440,14 +431,14 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="weather-card panel">
|
||||
<div class="panel-title">
|
||||
<div class="status-card panel">
|
||||
<div class="panel-title compact">
|
||||
<CloudSun :size="17" />
|
||||
<span>今日状态</span>
|
||||
</div>
|
||||
<div class="weather-body">
|
||||
<div class="status-body">
|
||||
<strong>{{ successRate }}%</strong>
|
||||
<span>近 6 次流程完成率</span>
|
||||
<span>最近流程完成率</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -540,7 +531,7 @@ onMounted(() => {
|
||||
<span>{{ formatTime(item.created_at) }} · {{ item.msg_type }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<ElEmpty v-else description="暂无数据" />
|
||||
<ElEmpty v-else description="暂无消息" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -551,7 +542,7 @@ onMounted(() => {
|
||||
<small>
|
||||
{{
|
||||
serverOverview
|
||||
? `${serverOverview.basic_info.hostname} (${serverOverview.basic_info.ip_address}) · 运行时间 ${serverOverview.boot_time.uptime_formatted}`
|
||||
? `${serverOverview.basic_info.hostname} (${serverOverview.basic_info.ip_address}) · 运行 ${serverOverview.boot_time.uptime_formatted}`
|
||||
: '等待服务器采集数据'
|
||||
}}
|
||||
</small>
|
||||
@@ -577,7 +568,11 @@ onMounted(() => {
|
||||
<div class="panel-title">
|
||||
<GitBranch :size="17" />
|
||||
<span>最近执行</span>
|
||||
<ElButton link type="primary" @click="go('/ai-platform/workflow-runs')">
|
||||
<ElButton
|
||||
link
|
||||
type="primary"
|
||||
@click="go('/ai-platform/workflow-runs')"
|
||||
>
|
||||
执行历史
|
||||
</ElButton>
|
||||
</div>
|
||||
@@ -667,7 +662,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div class="token-row">
|
||||
<Calendar :size="17" />
|
||||
<span>近 6 次执行消耗 {{ tokenTotal }} tokens</span>
|
||||
<span>最近执行消耗 {{ tokenTotal }} tokens</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -716,7 +711,7 @@ onMounted(() => {
|
||||
color: rgb(248 250 252);
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
height: 50px;
|
||||
justify-content: center;
|
||||
@@ -762,20 +757,20 @@ onMounted(() => {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.weather-card {
|
||||
.status-card {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
min-height: 122px;
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.weather-body {
|
||||
.status-body {
|
||||
align-items: center;
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.weather-body strong {
|
||||
.status-body strong {
|
||||
color: hsl(var(--primary));
|
||||
font-size: 26px;
|
||||
line-height: 1;
|
||||
@@ -800,6 +795,10 @@ onMounted(() => {
|
||||
padding: 14px 16px 8px;
|
||||
}
|
||||
|
||||
.panel-title.compact {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.panel-title > span {
|
||||
flex: 1;
|
||||
font-weight: 650;
|
||||
|
||||
Reference in New Issue
Block a user