fix: 问题

This commit is contained in:
2026-02-22 21:08:07 +08:00
parent df4b956a32
commit 227dd4f78d
2 changed files with 404 additions and 305 deletions

View File

@@ -1,52 +1,54 @@
<template>
<FullWidthLayout :show-padding="false" class="agents-layout">
<div class="agents-container">
<!-- 筛选器区域 -->
<aside class="agents-sidebar">
<div class="sidebar-content">
<h3 class="sidebar-title">领域分类</h3>
<nav class="category-nav">
<button
v-for="category in categories"
:key="category.id"
class="category-btn"
:class="{ 'category-btn--active': activeCategory === category.id }"
@click="handleCategoryChange(category.id)"
>
<span>{{ category.name }}</span>
<span class="category-count">{{ category.count }}</span>
</button>
</nav>
<!-- 头部区域搜索 + 分类 -->
<div class="agents-header">
<div class="header-content">
<!-- <h1 class="header-title">AI Agent Store</h1>
<p class="header-subtitle">Discover the perfect AI assistant for your workflow</p> -->
<!-- 搜索栏 -->
<div class="search-section">
<div class="search-input-wrapper">
<SearchOutlined class="search-icon" />
<input
v-model="searchKeyword"
type="text"
placeholder="搜索智能体风格,如:文案、数据分析..."
class="search-input"
@keydown.enter="handleSearch"
/>
<CloseOutlined v-if="searchKeyword" class="search-clear" @click="searchKeyword = ''; handleSearch()" />
</div>
</div>
<!-- 分类筛选 -->
<div class="category-section">
<nav class="category-nav">
<button
v-for="category in categories"
:key="category.id"
class="category-btn"
:class="{ 'category-btn--active': activeCategory === category.id }"
@click="handleCategoryChange(category.id)"
>
<span>{{ category.name }}</span>
<span class="category-count" v-if="category.count > 0">{{ category.count }}</span>
</button>
</nav>
</div>
</div>
</aside>
</div>
<!-- 主内容区域 -->
<main class="agents-main">
<!-- 搜索栏 -->
<div class="search-bar">
<div class="search-input-wrapper">
<SearchOutlined class="search-icon" />
<input
v-model="searchKeyword"
type="text"
placeholder="搜索智能体风格,如:文案、数据分析..."
class="search-input"
@keydown.enter="handleSearch"
/>
<CloseOutlined v-if="searchKeyword" class="search-clear" @click="searchKeyword = ''; handleSearch()" />
</div>
<div class="sort-info">
排序<span class="sort-active">热度 <i class="icon-arrow-down"></i></span>
</div>
</div>
<!-- 智能体卡片网格 -->
<div class="agents-content">
<a-spin :spinning="loading" tip="加载中...">
<template v-if="agentList.length > 0">
<template v-if="filteredAgentList.length > 0">
<div class="agents-grid">
<div
v-for="agent in agentList"
v-for="agent in filteredAgentList"
:key="agent.id"
class="agent-card"
@click="handleAgentClick(agent)"
@@ -80,19 +82,6 @@
</template>
<a-empty v-else description="暂无智能体" />
</a-spin>
<!-- 分页 -->
<div v-if="agentList.length > 0" class="pagination-wrapper">
<a-pagination
v-model:current="pagination.current"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:show-size-changer="true"
:show-quick-jumper="true"
:show-total="(total) => `${total} 个智能体`"
@change="handlePageChange"
/>
</div>
</div>
</main>
</div>
@@ -107,7 +96,7 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ref, computed, onMounted } from 'vue'
import {
SearchOutlined,
RobotOutlined,
@@ -198,28 +187,32 @@ const agentList = ref([
}
])
// 分页
const pagination = reactive({
current: 1,
pageSize: 12,
total: 0
// 计算属性:过滤后的列表
const filteredAgentList = computed(() => {
let list = agentList.value
if (activeCategory.value !== 'all') {
list = list.filter(a => a.categoryId === activeCategory.value)
}
if (searchKeyword.value) {
const keyword = searchKeyword.value.toLowerCase()
list = list.filter(a =>
a.name.toLowerCase().includes(keyword) ||
a.description.toLowerCase().includes(keyword)
)
}
return list
})
// 方法
const handleCategoryChange = (categoryId) => {
activeCategory.value = categoryId
pagination.current = 1
loadAgentList()
}
const handleSearch = () => {
pagination.current = 1
loadAgentList()
}
const handlePageChange = (page) => {
pagination.current = page
loadAgentList()
// 搜索逻辑通过 computed 自动处理这里可以留作扩展如埋点、API请求等
}
const handleAgentClick = (agent) => {
@@ -244,29 +237,6 @@ const formatNumber = (num) => {
return (num / 1000).toFixed(1) + 'w'
}
const loadAgentList = async () => {
loading.value = true
try {
// TODO: 调用 API 获取数据
// 模拟筛选
let filteredList = agentList.value
if (activeCategory.value !== 'all') {
filteredList = agentList.value.filter(a => a.categoryId === activeCategory.value)
}
if (searchKeyword.value) {
filteredList = filteredList.filter(a =>
a.name.includes(searchKeyword.value) || a.description.includes(searchKeyword.value)
)
}
pagination.total = filteredList.length
} catch (error) {
console.error('加载智能体列表失败:', error)
message.error('加载失败,请重试')
} finally {
loading.value = false
}
}
// 初始化
onMounted(() => {
// 更新分类数量
@@ -277,7 +247,6 @@ onMounted(() => {
cat.count = agentList.value.filter(a => a.categoryId === cat.id).length
}
})
pagination.total = agentList.value.length
})
</script>
@@ -288,135 +257,78 @@ onMounted(() => {
.agents-container {
display: flex;
flex-direction: column;
height: 100%;
background: #F8FAFC;
}
// 侧边栏
.agents-sidebar {
width: 260px;
background: #fff;
border-right: 1px solid #E2E8F0;
flex-shrink: 0;
padding: 20px;
}
.sidebar-content {
position: sticky;
top: 0;
}
.sidebar-title {
font-size: 12px;
font-weight: 700;
color: #94A3B8;
text-transform: uppercase;
letter-spacing: 0.5px;
margin: 0 0 12px 0;
}
.category-nav {
display: flex;
flex-direction: column;
gap: 4px;
}
.category-btn {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 12px;
border-radius: 8px;
font-size: 14px;
color: #64748B;
background: transparent;
border: none;
cursor: pointer;
transition: all 0.2s ease;
text-align: left;
width: 100%;
&:hover {
background: #F1F5F9;
color: #334155;
}
&--active {
background: #EFF6FF;
color: #1D4ED8;
font-weight: 600;
}
}
.category-count {
font-size: 10px;
background: #E2E8F0;
color: #64748B;
padding: 2px 6px;
border-radius: 12px;
font-weight: 500;
.category-btn--active & {
background: #BFDBFE;
color: #1E40AF;
}
}
// 主内容区域
.agents-main {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
// 头部区域
.agents-header {
background: #F8FAFC;
padding: 64px 0 48px;
display: flex;
flex-direction: column;
align-items: center;
border-bottom: 1px solid #F1F5F9;
}
.search-bar {
padding: 16px 24px;
.header-content {
width: 100%;
max-width: 800px;
display: flex;
justify-content: space-between;
flex-direction: column;
align-items: center;
gap: 24px;
flex-shrink: 0;
background: #fff;
border-bottom: 1px solid #F1F5F9;
margin: 0 12px;
@media (max-width: 768px) {
flex-direction: column;
align-items: stretch;
padding: 16px;
gap: 12px;
}
text-align: center;
padding: 0 24px;
}
.header-title {
font-size: 48px;
font-weight: 800;
color: #1E293B;
margin: 0 0 16px 0;
letter-spacing: -0.02em;
}
.header-subtitle {
font-size: 18px;
color: #64748B;
margin: 0 0 40px 0;
max-width: 600px;
line-height: 1.6;
}
.search-section {
width: 100%;
display: flex;
justify-content: center;
margin-bottom: 32px;
}
.search-input-wrapper {
position: relative;
width: 380px;
max-width: 100%;
@media (max-width: 768px) {
width: 100%;
}
width: 100%;
max-width: 600px;
}
.search-icon {
position: absolute;
left: 14px;
left: 20px;
top: 50%;
transform: translateY(-50%);
color: #94A3B8;
font-size: 14px;
font-size: 20px;
z-index: 1;
pointer-events: none;
}
.search-clear {
position: absolute;
right: 12px;
right: 18px;
top: 50%;
transform: translateY(-50%);
color: #94A3B8;
font-size: 12px;
font-size: 16px;
cursor: pointer;
z-index: 2;
transition: all 0.2s ease;
@@ -428,23 +340,25 @@ onMounted(() => {
.search-input {
width: 100%;
height: 42px;
padding: 0 40px 0 42px;
height: 56px;
padding: 0 52px 0 56px;
border: 1px solid #E2E8F0;
border-radius: 10px;
font-size: 14px;
border-radius: 28px;
font-size: 16px;
color: #1E293B;
background: #fff;
background: #F8FAFC;
outline: none;
transition: all 0.2s ease;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
&::placeholder {
color: #94A3B8;
}
&:focus {
border-color: #3B82F6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
border-color: #94A3B8;
background: #fff;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
}
&:hover {
@@ -452,39 +366,121 @@ onMounted(() => {
}
}
.sort-info {
font-size: 12px;
color: #94A3B8;
white-space: nowrap;
// 分类筛选
.category-section {
width: 100%;
padding: 0 20px;
display: flex;
justify-content: center;
/* Mobile optimization: Keep horizontal scroll on small screens if desired,
but user asked for PC fix. Let's make it responsive. */
@media (max-width: 640px) {
display: block;
overflow-x: auto;
white-space: nowrap;
justify-content: flex-start;
mask-image: linear-gradient(to right, transparent, black 20px, black 90%, transparent);
-webkit-mask-image: linear-gradient(to right, transparent, black 20px, black 90%, transparent);
/* Hide scrollbar */
&::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none;
scrollbar-width: none;
}
}
.sort-active {
font-weight: 600;
color: #1E293B;
.category-nav {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 12px;
max-width: 1000px;
margin: 0 auto;
padding: 4px 20px;
@media (max-width: 640px) {
display: inline-flex;
flex-wrap: nowrap;
width: max-content;
justify-content: flex-start;
margin: 0;
}
}
.category-btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
font-weight: 500;
color: #64748B;
background: #F1F5F9;
border: 1px solid transparent;
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
&:hover {
background: #E2E8F0;
color: #334155;
}
&--active {
background: #1E293B;
color: #fff;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
&:hover {
background: #334155;
color: #fff;
}
}
}
.icon-arrow-down {
display: inline-block;
font-size: 10px;
margin-left: 2px;
.category-count {
font-size: 12px;
background: rgba(255, 255, 255, 0.5);
color: #64748B;
padding: 0 6px;
height: 18px;
line-height: 18px;
border-radius: 9px;
font-weight: 600;
transition: all 0.2s ease;
.category-btn--active & {
background: rgba(255, 255, 255, 0.2);
color: #fff;
}
}
// 主内容区域
.agents-main {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
max-width: 1400px;
width: 100%;
margin: 0 auto;
}
// 智能体内容区域
.agents-content {
flex: 1;
padding: 24px;
padding: 40px 24px;
overflow-y: auto;
@media (max-width: 768px) {
padding: 16px;
}
}
.agents-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 24px;
@media (max-width: 640px) {
grid-template-columns: 1fr;
@@ -494,17 +490,22 @@ onMounted(() => {
// 智能体卡片
.agent-card {
background: #fff;
border: 1px solid #E2E8F0;
border-radius: 12px;
padding: 20px;
border: 1px solid #F1F5F9;
border-radius: 16px;
padding: 24px;
cursor: pointer;
transition: all 0.3s ease;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
height: 100%;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.02);
&:hover {
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.08);
border-color: #93C5FD;
transform: translateY(-4px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.05), 0 4px 6px -2px rgba(0, 0, 0, 0.02);
border-color: #E2E8F0;
}
}
@@ -512,20 +513,24 @@ onMounted(() => {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 12px;
margin-bottom: 20px;
}
.agent-avatar {
width: 48px;
height: 48px;
border-radius: 50%;
width: 56px;
height: 56px;
border-radius: 12px;
overflow: hidden;
border: 2px solid #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: 1px solid #F1F5F9;
background: #F8FAFC;
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.3s ease;
.agent-card:hover & {
transform: scale(1.05);
}
img {
width: 100%;
@@ -535,140 +540,100 @@ onMounted(() => {
}
.avatar-placeholder {
font-size: 24px;
color: rgba(255, 255, 255, 0.8);
font-size: 28px;
color: #94A3B8;
}
.agent-tag {
font-size: 10px;
padding: 4px 8px;
border-radius: 12px;
font-weight: 600;
border: 1px solid;
font-size: 12px;
padding: 4px 10px;
border-radius: 6px;
font-weight: 500;
&--blue {
background: #EFF6FF;
color: #1D4ED8;
border-color: #BFDBFE;
color: #3B82F6;
}
&--green {
background: #F0FDF4;
color: #16A34A;
border-color: #BBF7D0;
color: #22C55E;
}
&--purple {
background: #FAF5FF;
color: #9333EA;
border-color: #E9D5FF;
color: #A855F7;
}
&--pink {
background: #FDF2F8;
color: #DB2777;
border-color: #FBCFE8;
color: #EC4899;
}
&--amber {
background: #FFFBEB;
color: #D97706;
border-color: #FDE68A;
color: #F59E0B;
}
}
.card-title {
font-size: 16px;
font-size: 18px;
font-weight: 600;
color: #1E293B;
margin: 0 0 6px 0;
margin: 0 0 8px 0;
line-height: 1.4;
}
.card-description {
font-size: 12px;
font-size: 14px;
color: #64748B;
margin: 0 0 16px 0;
margin: 0 0 24px 0;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-line-clamp: 3;
line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
line-height: 1.5;
line-height: 1.6;
flex: 1;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 16px;
border-top: 1px solid #F1F5F9;
margin-top: auto;
}
.usage-count {
font-size: 10px;
font-size: 12px;
color: #94A3B8;
font-weight: 500;
display: flex;
align-items: center;
gap: 6px;
}
.chat-btn {
background: #F1F5F9;
color: #64748B;
color: #475569;
border: none;
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
padding: 8px 16px;
border-radius: 8px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
.agent-card:hover & {
background: #3B82F6;
background: #1E293B;
color: #fff;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
}
// 分页
.pagination-wrapper {
padding-top: 24px;
display: flex;
justify-content: center;
:deep(.ant-pagination) {
.ant-pagination-item {
border-radius: 6px;
border-color: #E2E8F0;
a {
color: #64748B;
}
&:hover {
border-color: #3B82F6;
a {
color: #3B82F6;
}
}
&-active {
background: #3B82F6;
border-color: #3B82F6;
a {
color: #fff;
}
}
}
.ant-pagination-prev,
.ant-pagination-next {
.ant-pagination-item-link {
border-radius: 6px;
border-color: #E2E8F0;
&:hover {
border-color: #3B82F6;
color: #3B82F6;
}
}
}
&:hover {
background: #334155 !important;
}
}
</style>