本文档详细记录了 AgentHub 前端页面的美化和优化方案,包括统一组件、弹窗改造、视觉效果优化等内容。
实施日期: 2026-05-09
涉及页面: 15+ 配置管理页面
主要改进: 统一UI组件、弹窗化表单、毛玻璃效果、浮动按钮
CustomSelect 组件CustomButton 组件ModalDialog 组件位置: src/components/CustomSelect.vue
功能特性:
使用示例:
<CustomSelect
v-model="selectedValue"
:options="options"
placeholder="请选择"
/>
位置: src/components/CustomButton.vue
按钮类型:
primary - 主要按钮(蓝色)secondary - 次要按钮(灰色)success - 成功按钮(绿色)danger - 危险按钮(红色)warning - 警告按钮(黄色)ghost - 幽灵按钮(透明)link - 链接按钮(无背景)按钮尺寸:
small - 小尺寸medium - 中等尺寸(默认)large - 大尺寸使用示例:
<CustomButton type="primary" size="medium" @click="handleClick">
保存
</CustomButton>
位置: src/components/ModalDialog.vue
功能特性:
使用示例:
<ModalDialog
v-model:visible="showDialog"
title="创建配置"
@confirm="handleSubmit"
@close="showDialog = false"
confirm-text="创建"
>
<form>
<!-- 表单内容 -->
</form>
</ModalDialog>
CSS 实现:
.glass-effect {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px) saturate(180%);
border-radius: 16px;
border: 1px solid transparent;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}
应用场景:
CSS 实现:
.float-effect {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.float-effect:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
全局样式 (src/common/base.css):
div, section, article, aside, main, nav,
.panel, .stat, .card, .config-item {
border-radius: 12px !important;
}
.panel, .stat, .config-item {
border: 1px solid transparent !important;
}
位置: src/components/EffectToggle.vue
功能:
位置: 右下角 (bottom: 24px, right: 24px)
功能: 跳转到设置页面
样式: 蓝色圆形按钮,48x48px
位置: 右下角 (bottom: 84px, right: 24px)
功能: 打开视觉效果设置弹窗
样式: 蓝色圆形按钮,48x48px
位置: 右下角 (bottom: 140px, right: 24px)
功能: 触发 global-add 事件,打开当前页面的新增弹窗
样式: 绿色圆形按钮,48x48px,带加号图标
智能显示: 只在配置页面显示
布局示意:
右下角:
├── FloatingSettingsButton (bottom: 24px) - 设置按钮(蓝色)
├── FloatingEffectButton (bottom: 84px) - 视觉效果按钮(蓝色)
└── FloatingAddButton (bottom: 140px) - 新增按钮(绿色,智能显示)
import ModalDialog from '@/components/ModalDialog.vue'
<!-- 移除前 -->
<button @click="showCreateForm = true">新建配置</button>
<!-- 移除后 -->
<!-- 使用右侧浮动新增按钮 -->
<!-- 移除前 -->
<form v-if="showCreateForm" class="form">
<!-- 表单内容 -->
</form>
<!-- 改为 -->
<ModalDialog
v-model:visible="showCreateForm"
title="创建配置"
@confirm="handleSubmit"
@close="showCreateForm = false"
>
<form>
<!-- 表单内容 -->
</form>
</ModalDialog>
onMounted(() => {
window.addEventListener('global-add', () => {
editingId.value = null // 重置编辑状态
showCreateForm.value = true
})
})
function handleEdit(item) {
editingId.value = item.id
// 填充表单数据
formData.name = item.name
// ... 其他字段
showEditForm.value = true // 打开弹窗
}
<template>
<section class="grid">
<!-- 标题板块 -->
<div class="page-header">
<h2>页面标题</h2>
<p class="muted">页面描述</p>
</div>
<!-- 列表板块 -->
<article class="table-card">
<table>
<!-- 表格内容 -->
</table>
</article>
</section>
</template>
策略配置管理页面包含 4 种策略,每种策略有独立的子组件:
主页面事件监听:
// StrategyManagementView.vue
onMounted(() => {
window.addEventListener('global-add', () => {
// 根据当前标签页触发对应的子组件事件
window.dispatchEvent(new CustomEvent(`strategy-${activeTab.value}-add`))
})
})
子组件事件监听:
// RetrievalStrategyPanel.vue
onMounted(() => {
window.addEventListener('strategy-retrieval-add', () => {
showCreateForm.value = true
})
})
位置: src/common/base.css
.grid {
display: flex;
flex-direction: column;
gap: 24px;
}
.page-header {
padding: 24px;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border-radius: 16px;
border: 1px solid transparent;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}
.table-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border-radius: 16px;
border: 1px solid transparent;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
overflow: hidden;
}
table {
width: 100%;
border-collapse: collapse;
}
thead {
background: rgba(58, 138, 214, 0.05);
}
th, td {
padding: 16px;
text-align: left;
border-bottom: 1px solid rgba(38, 66, 102, 0.08);
}
tr:hover {
background: rgba(58, 138, 214, 0.02);
}
用户点击右侧新增按钮
↓
触发 global-add 事件
↓
当前页面监听到事件
↓
重置编辑状态 (editingId = null)
↓
打开新增弹窗 (showCreateForm = true)
↓
用户填写表单
↓
点击确认按钮
↓
调用创建 API
↓
关闭弹窗
↓
刷新列表
用户点击编辑按钮
↓
调用 handleEdit 函数
↓
设置编辑 ID (editingId = item.id)
↓
填充表单数据
↓
打开编辑弹窗 (showEditForm = true)
↓
用户修改数据
↓
点击更新按钮
↓
调用更新 API
↓
关闭弹窗
↓
刷新列表
const showAddButton = computed(() => {
const path = route.path
return path.includes('workspace') ||
path.includes('agents') ||
path.includes('strategies') ||
path.includes('vector-stores') ||
path.includes('models') ||
path.includes('agent-configs') ||
path.includes('knowledge') ||
path.includes('retrieval') ||
path.includes('mcp-tool') ||
path.includes('prompt-template') ||
path.includes('memory') ||
path.includes('skill') ||
path.includes('workflow') ||
path.includes('agent-team') ||
path.includes('security-policy') ||
path.includes('scheduled-task')
})
cd src/main/web
npm run dev
如果弹窗不显示,首先检查 ModalDialog 是否已导入:
import ModalDialog from '@/components/ModalDialog.vue'
在 global-add 事件中,必须重置编辑状态:
window.addEventListener('global-add', () => {
editingId.value = null // 必须重置
showCreateForm.value = true
})
前端表单字段必须与后端 DTO 完全一致,否则会导致:
更新函数必须提交所有可编辑字段,不要只提交部分字段:
// 错误示例 - 只提交2个字段
await updateStrategy(id, {
name: data.name,
description: data.description,
})
// 正确示例 - 提交所有字段
await updateStrategy(id, {
name: data.name,
description: data.description,
field1: data.field1,
field2: data.field2,
// ... 所有字段
})
本次前端美化和优化方案实现了:
改造页面数量: 15+
新增组件数量: 6
代码质量: 编译通过,无错误
用户体验: 大幅提升
文档版本: 1.0
最后更新: 2026-05-09