feat: add agent favorite functionality with UI and API implementation

- Add `addFavorite` and `removeFavorite` API functions in agent.js
- Implement favorite button UI in Agents.vue with star icons
- Add login check before favorite operations using token manager
- Sort agents with favorites appearing at the top of the list
- Include success/error messages for user feedback
- Add backend API endpoints for creating/deleting agent favorites
- Update agent list response to include favorite status
- Style favorite button with hover and active states
This commit is contained in:
2026-02-26 20:15:24 +08:00
parent 120a4529a5
commit d429dc887a
8 changed files with 315 additions and 11 deletions

View File

@@ -116,3 +116,27 @@ export function getMessages(params) {
params
})
}
/**
* 添加智能体收藏
* @param {number} agentId - 智能体ID
*/
export function addFavorite(agentId) {
return request({
url: `${BASE_URL}/agent/favorite/create`,
method: 'post',
params: { agentId }
})
}
/**
* 取消智能体收藏
* @param {number} agentId - 智能体ID
*/
export function removeFavorite(agentId) {
return request({
url: `${BASE_URL}/agent/favorite/delete`,
method: 'delete',
params: { agentId }
})
}

View File

@@ -134,6 +134,15 @@
<!-- 底部操作栏 -->
<div class="card-footer">
<button
class="favorite-btn"
:class="{ 'favorite-btn--active': agent.isFavorite }"
@click.stop="handleFavorite(agent)"
>
<StarFilled v-if="agent.isFavorite" />
<StarOutlined v-else />
<span>{{ agent.isFavorite ? '已收藏' : '收藏' }}</span>
</button>
<div class="footer-spacer"></div>
<button class="chat-btn" @click.stop="handleChat(agent)">
<MessageOutlined class="chat-btn-icon" />
@@ -172,12 +181,15 @@ import {
CloseOutlined,
ArrowRightOutlined,
MessageOutlined,
AppstoreOutlined
AppstoreOutlined,
StarOutlined,
StarFilled
} from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import FullWidthLayout from '@/layouts/components/FullWidthLayout.vue'
import ChatDrawer from '@/components/agents/ChatDrawer.vue'
import { getAgentList } from '@/api/agent'
import { getAgentList, addFavorite, removeFavorite } from '@/api/agent'
import tokenManager from '@gold/utils/token-manager'
// 状态管理
const loading = ref(false)
@@ -218,7 +230,7 @@ const categories = computed(() => {
return cats
})
// 过滤后的列表
// 过滤后的列表(收藏置顶)
const filteredAgentList = computed(() => {
let list = agentList.value
@@ -234,7 +246,11 @@ const filteredAgentList = computed(() => {
)
}
return list
// 收藏的智能体置顶
return list.sort((a, b) => {
if (a.isFavorite === b.isFavorite) return 0
return a.isFavorite ? -1 : 1
})
})
// 获取智能体列表
@@ -250,7 +266,8 @@ const fetchAgentList = async () => {
description: item.description,
avatar: item.icon,
categoryName: item.categoryName || '其他',
tagColor: getTagColor(item.categoryName)
tagColor: getTagColor(item.categoryName),
isFavorite: item.isFavorite || false
}))
}
} catch (error) {
@@ -327,6 +344,30 @@ const handleSendMessage = (data) => {
console.log('发送消息:', data)
}
// 收藏切换
const handleFavorite = async (agent) => {
// 检查登录状态
if (!tokenManager.isLoggedIn()) {
message.warning('请先登录')
return
}
try {
if (agent.isFavorite) {
await removeFavorite(agent.id)
agent.isFavorite = false
message.success('已取消收藏')
} else {
await addFavorite(agent.id)
agent.isFavorite = true
message.success('收藏成功')
}
} catch (error) {
console.error('收藏操作失败:', error)
message.error('操作失败,请重试')
}
}
// 初始化
onMounted(() => {
fetchAgentList()
@@ -799,6 +840,38 @@ onMounted(() => {
font-size: 13px;
}
// 收藏按钮
.favorite-btn {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 6px 12px;
background: transparent;
border: 1px solid var(--color-gray-300);
border-radius: 8px;
font-size: 12px;
font-weight: 500;
color: var(--color-gray-600);
cursor: pointer;
transition: all 0.2s ease;
&:hover {
border-color: #F59E0B;
color: #F59E0B;
background: #FFFBEB;
}
&:active {
transform: scale(0.95);
}
&--active {
border-color: #F59E0B;
color: #F59E0B;
background: #FFFBEB;
}
}
// ============================================
// 空状态
// ============================================