fix: restore zq dashboard home quality
This commit is contained in:
@@ -32,6 +32,7 @@ const modules = import.meta.glob([
|
||||
'./langs/**/core.json',
|
||||
'./langs/**/database-connection.json',
|
||||
'./langs/**/database-manager.json',
|
||||
'./langs/**/dashboard-design.json',
|
||||
'./langs/**/dept.json',
|
||||
'./langs/**/dict.json',
|
||||
'./langs/**/file-manager.json',
|
||||
|
||||
@@ -1,249 +1,28 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, defineAsyncComponent, onMounted, ref, watch } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { ElEmpty, ElMessage, ElScrollbar } from 'element-plus';
|
||||
|
||||
import { getPageByCodeApi } from '#/api/core/page-manager';
|
||||
import DashboardRenderer from '#/components/dashboard-design/DashboardRenderer.vue';
|
||||
|
||||
defineOptions({ name: 'PageRender' });
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const DashboardRenderer = defineAsyncComponent(
|
||||
() => import('#/components/dashboard-design/DashboardRenderer.vue'),
|
||||
);
|
||||
|
||||
const loading = ref(false);
|
||||
const pageConfig = ref('');
|
||||
|
||||
const aiHomeMenus = [
|
||||
{
|
||||
color: 'rgba(59, 130, 246, 0.85)',
|
||||
icon: 'lucide:bot',
|
||||
id: 'ai-agent',
|
||||
path: '/ai-platform/agent',
|
||||
title: '智能体',
|
||||
},
|
||||
{
|
||||
color: 'rgba(22, 163, 74, 0.85)',
|
||||
icon: 'lucide:git-branch',
|
||||
id: 'ai-workflow',
|
||||
path: '/ai-platform/workflow',
|
||||
title: '流程编排',
|
||||
},
|
||||
{
|
||||
color: 'rgba(15, 118, 110, 0.85)',
|
||||
icon: 'lucide:database',
|
||||
id: 'knowledge-base',
|
||||
path: '/ai-platform/knowledge-base',
|
||||
title: '知识库',
|
||||
},
|
||||
{
|
||||
color: 'rgba(124, 58, 237, 0.85)',
|
||||
icon: 'lucide:history',
|
||||
id: 'ai-workflow-runs',
|
||||
path: '/ai-platform/workflow-runs',
|
||||
title: '执行历史',
|
||||
},
|
||||
{
|
||||
color: 'rgba(71, 85, 105, 0.85)',
|
||||
icon: 'lucide:settings',
|
||||
id: 'model-config',
|
||||
path: '/ai-platform/model',
|
||||
title: '模型配置',
|
||||
},
|
||||
{
|
||||
color: 'rgba(249, 115, 22, 0.85)',
|
||||
icon: 'lucide:message-square-code',
|
||||
id: 'codex-chat',
|
||||
path: '/agent-chat/codex',
|
||||
title: 'Codex',
|
||||
},
|
||||
];
|
||||
|
||||
const adminHomeMenus = [
|
||||
{
|
||||
bgColor: 'linear-gradient(135deg, #60a5fa, #2563eb)',
|
||||
icon: 'lucide:users',
|
||||
id: 'system-user',
|
||||
path: '/system/user',
|
||||
title: '用户管理',
|
||||
},
|
||||
{
|
||||
bgColor: 'linear-gradient(135deg, #a78bfa, #7c3aed)',
|
||||
icon: 'lucide:shield-check',
|
||||
id: 'system-role',
|
||||
path: '/system/role',
|
||||
title: '角色权限',
|
||||
},
|
||||
{
|
||||
bgColor: 'linear-gradient(135deg, #fb923c, #f97316)',
|
||||
icon: 'lucide:menu',
|
||||
id: 'system-menu',
|
||||
path: '/system/menu',
|
||||
title: '菜单管理',
|
||||
},
|
||||
{
|
||||
bgColor: 'linear-gradient(135deg, #2dd4bf, #0f766e)',
|
||||
icon: 'lucide:key-round',
|
||||
id: 'system-permission',
|
||||
path: '/system/new-permission',
|
||||
title: 'API 权限',
|
||||
},
|
||||
{
|
||||
bgColor: 'linear-gradient(135deg, #4ade80, #16a34a)',
|
||||
icon: 'lucide:megaphone',
|
||||
id: 'announcement',
|
||||
path: '/message/announcement',
|
||||
title: '公告管理',
|
||||
},
|
||||
{
|
||||
bgColor: 'linear-gradient(135deg, #94a3b8, #475569)',
|
||||
icon: 'lucide:inbox',
|
||||
id: 'message-list',
|
||||
path: '/message/list',
|
||||
title: '消息列表',
|
||||
},
|
||||
];
|
||||
|
||||
const opsHomeMenus = [
|
||||
{
|
||||
icon: 'lucide:send',
|
||||
id: 'requirements-agent',
|
||||
path: '/ai-platform/agent',
|
||||
title: '需求分析',
|
||||
},
|
||||
{
|
||||
icon: 'lucide:workflow',
|
||||
id: 'collaboration-flow',
|
||||
path: '/ai-platform/workflow',
|
||||
title: '协作流程',
|
||||
},
|
||||
{
|
||||
icon: 'lucide:activity',
|
||||
id: 'observability',
|
||||
path: '/ai-platform/workflow-runs',
|
||||
title: '可观测性',
|
||||
},
|
||||
{
|
||||
icon: 'lucide:sliders-horizontal',
|
||||
id: 'model-config',
|
||||
path: '/ai-platform/model',
|
||||
title: '模型配置',
|
||||
},
|
||||
];
|
||||
|
||||
const homeSections = [
|
||||
{
|
||||
description: '智能体、流程、知识库、模型和运行历史',
|
||||
id: 'ai',
|
||||
menus: aiHomeMenus,
|
||||
title: 'AI 协作',
|
||||
},
|
||||
{
|
||||
description: '用户、角色、菜单、权限和公告消息',
|
||||
id: 'admin',
|
||||
menus: adminHomeMenus,
|
||||
title: '基础管理',
|
||||
},
|
||||
{
|
||||
description: '需求分析、协作流程、可观测性和模型配置',
|
||||
id: 'ops',
|
||||
menus: opsHomeMenus,
|
||||
title: '协作运维',
|
||||
},
|
||||
];
|
||||
|
||||
function toQuickLinksWidget(widget: any, title: string, menus: any[]) {
|
||||
return {
|
||||
...widget,
|
||||
props: {
|
||||
...widget.props,
|
||||
columns: widget.w >= 6 ? 3 : 4,
|
||||
menus,
|
||||
rows: 2,
|
||||
title,
|
||||
},
|
||||
title,
|
||||
type: 'quick-links',
|
||||
};
|
||||
}
|
||||
|
||||
function toApprovalCenterWidget(widget: any, title: string, menus: any[]) {
|
||||
return {
|
||||
...widget,
|
||||
props: {
|
||||
...widget.props,
|
||||
menus,
|
||||
showMore: false,
|
||||
title,
|
||||
},
|
||||
title,
|
||||
type: 'approval-center',
|
||||
};
|
||||
}
|
||||
|
||||
function toStaticAppsWidget(widget: any, title: string, menus: any[]) {
|
||||
return {
|
||||
...widget,
|
||||
props: {
|
||||
...widget.props,
|
||||
maxCount: menus.length,
|
||||
menus,
|
||||
showMore: false,
|
||||
title,
|
||||
},
|
||||
title,
|
||||
type: 'my-apps',
|
||||
};
|
||||
}
|
||||
|
||||
function getLightMainHomeConfig(config: Record<string, any>) {
|
||||
const next = JSON.parse(JSON.stringify(config));
|
||||
if (!Array.isArray(next.widgets)) return next;
|
||||
|
||||
const hasApprovalCenter = next.widgets.some(
|
||||
(widget: any) => widget.type === 'approval-center',
|
||||
);
|
||||
|
||||
next.widgets = next.widgets.map((widget: any) => {
|
||||
if (widget.type === 'welcome-card') {
|
||||
return {
|
||||
...widget,
|
||||
props: {
|
||||
...widget.props,
|
||||
subtitle: '今天是个好日子',
|
||||
title: widget.props?.title || '欢迎回来',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (widget.type === 'approval-center') {
|
||||
return toApprovalCenterWidget(widget, '审批中心', aiHomeMenus);
|
||||
}
|
||||
|
||||
if (widget.type === 'my-apps') {
|
||||
return toStaticAppsWidget(widget, '我的应用', adminHomeMenus);
|
||||
}
|
||||
|
||||
if (widget.type === 'quick-links') {
|
||||
if (!hasApprovalCenter && widget.props?.title === 'AI 协作') {
|
||||
return toApprovalCenterWidget(widget, '审批中心', aiHomeMenus);
|
||||
}
|
||||
return toQuickLinksWidget(widget, '快捷入口', opsHomeMenus);
|
||||
}
|
||||
|
||||
return widget;
|
||||
});
|
||||
|
||||
return next;
|
||||
}
|
||||
const pageName = ref('');
|
||||
const pageCode = ref('');
|
||||
|
||||
function getPageCode(): string {
|
||||
if (route.query.pageCode) return route.query.pageCode as string;
|
||||
if (route.params.code) return route.params.code as string;
|
||||
if (route.query.pageCode) {
|
||||
return route.query.pageCode as string;
|
||||
}
|
||||
|
||||
if (route.params.code) {
|
||||
return route.params.code as string;
|
||||
}
|
||||
|
||||
const pathParts = route.path.split('/').filter(Boolean);
|
||||
const length = pathParts.length;
|
||||
@@ -254,12 +33,6 @@ function getPageCode(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
const isMainHome = computed(() => getPageCode() === 'main_home');
|
||||
|
||||
function goTo(path: string) {
|
||||
router.push(path);
|
||||
}
|
||||
|
||||
async function loadPageData() {
|
||||
const code = getPageCode();
|
||||
if (!code) {
|
||||
@@ -267,22 +40,16 @@ async function loadPageData() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (code === 'main_home') {
|
||||
pageConfig.value = '';
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
pageCode.value = code;
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
const page = await getPageByCodeApi(code);
|
||||
const config =
|
||||
pageName.value = page.name;
|
||||
pageConfig.value =
|
||||
page.page_config && Object.keys(page.page_config).length > 0
|
||||
? code === 'main_home'
|
||||
? getLightMainHomeConfig(page.page_config)
|
||||
: page.page_config
|
||||
: undefined;
|
||||
pageConfig.value = config ? JSON.stringify(config) : '';
|
||||
? JSON.stringify(page.page_config)
|
||||
: '';
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error?.message || '加载页面失败');
|
||||
} finally {
|
||||
@@ -304,62 +71,7 @@ watch(
|
||||
|
||||
<template>
|
||||
<ElScrollbar class="rounded-[8px] py-3">
|
||||
<div
|
||||
v-if="isMainHome"
|
||||
class="min-h-[calc(100vh-120px)] rounded-[8px] px-3 pb-6"
|
||||
>
|
||||
<div class="mb-4 px-1">
|
||||
<h1 class="text-foreground text-xl font-semibold">AI Agent Admin</h1>
|
||||
<p class="text-muted-foreground mt-1 text-sm">
|
||||
面向智能体协作的轻量后台
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-3 xl:grid-cols-3">
|
||||
<section
|
||||
v-for="section in homeSections"
|
||||
:key="section.id"
|
||||
class="border-border bg-card rounded-[8px] border p-4"
|
||||
>
|
||||
<div class="mb-4">
|
||||
<h2 class="text-foreground text-sm font-semibold">
|
||||
{{ section.title }}
|
||||
</h2>
|
||||
<p class="text-muted-foreground mt-1 text-xs">
|
||||
{{ section.description }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<button
|
||||
v-for="item in section.menus"
|
||||
:key="item.id"
|
||||
class="border-border hover:border-primary/70 hover:bg-accent group flex min-h-20 flex-col items-start justify-between rounded-[8px] border p-3 text-left transition-colors"
|
||||
type="button"
|
||||
@click="goTo(item.path)"
|
||||
>
|
||||
<span
|
||||
class="flex size-8 items-center justify-center rounded-[6px] text-white shadow-sm"
|
||||
:style="{ background: item.color || item.bgColor }"
|
||||
>
|
||||
<IconifyIcon :icon="item.icon" class="size-4" />
|
||||
</span>
|
||||
<span
|
||||
class="text-foreground group-hover:text-primary mt-3 text-sm font-medium"
|
||||
>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
v-loading="loading"
|
||||
class="h-[calc(100vh-120px)] rounded-[8px] px-3"
|
||||
>
|
||||
<div v-loading="loading" class="h-[calc(100vh-120px)] rounded-[8px] px-3">
|
||||
<DashboardRenderer v-if="pageConfig" :config="pageConfig" />
|
||||
<ElEmpty v-else-if="!loading" description="暂无页面配置" />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user