perf: 优化智能体页面性能和体验 (#756)

* feat: improved model validation and error handling

* refactor: 优化智能体页面下拉流畅度和分类切换效果,让其更加顺畅自然

---------

Co-authored-by: kangfenmao <kangfenmao@qq.com>
Co-authored-by: magicdmer <magicdmer@163.com>
This commit is contained in:
magicdmer 2025-01-17 09:34:22 +08:00 committed by kangfenmao
parent 2300cca070
commit 999bd802c4
3 changed files with 61 additions and 42 deletions

View File

@ -120,12 +120,31 @@ const AgentsPage: FC = () => {
[i18n.language]
)
const renderAgentList = useCallback(
(agents: Agent[]) => {
return (
<Row gutter={[20, 20]}>
{agents.map((agent, index) => (
<Col span={6} key={agent.id || index}>
<AgentCard
onClick={() => onAddAgentConfirm(getAgentFromSystemAgent(agent as any))}
agent={agent as any}
/>
</Col>
))}
</Row>
);
},
[onAddAgentConfirm]
);
const tabItems = useMemo(() => {
const groups = Object.keys(filteredAgentGroups)
const groups = Object.keys(filteredAgentGroups);
return groups.map((group, i) => {
const id = String(i + 1)
const localizedGroupName = getLocalizedGroupName(group)
const id = String(i + 1);
const localizedGroupName = getLocalizedGroupName(group);
const agents = filteredAgentGroups[group] || [];
return {
label: localizedGroupName,
@ -135,25 +154,16 @@ const AgentsPage: FC = () => {
<Title level={5} key={group} style={{ marginBottom: 10 }}>
{localizedGroupName}
</Title>
<Row gutter={[20, 20]}>
{group === '我的' ? (
<MyAgents onClick={onAddAgentConfirm} search={search} />
) : (
filteredAgentGroups[group]?.map((agent, index) => (
<Col span={6} key={group + index}>
<AgentCard
onClick={() => onAddAgentConfirm(getAgentFromSystemAgent(agent as any))}
agent={agent as any}
/>
</Col>
))
)}
</Row>
{group === '我的' ? (
<MyAgents onClick={onAddAgentConfirm} search={search} />
) : (
renderAgentList(agents)
)}
</TabContent>
)
}
})
}, [filteredAgentGroups, getLocalizedGroupName, onAddAgentConfirm, search])
};
});
}, [filteredAgentGroups, getLocalizedGroupName, onAddAgentConfirm, search, renderAgentList]);
const handleSearch = () => {
if (searchInput.trim() === '') {
@ -185,26 +195,20 @@ const AgentsPage: FC = () => {
<div style={{ width: 80 }} />
</NavbarCenter>
</Navbar>
<ContentContainer id="content-container">
<ContentContainer>
<AssistantsContainer>
{Object.values(filteredAgentGroups).flat().length > 0 ? (
search.trim() ? (
<TabContent>
<Row gutter={[20, 20]}>
{Object.values(filteredAgentGroups)
.flat()
.map((agent, index, array) => (
<Col span={array.length === 1 ? 12 : 6} key={index}>
<AgentCard
onClick={() => onAddAgentConfirm(getAgentFromSystemAgent(agent as any))}
agent={agent as any}
/>
</Col>
))}
</Row>
{renderAgentList(Object.values(filteredAgentGroups).flat())}
</TabContent>
) : (
<Tabs tabPosition="right" animated items={tabItems} $language={i18n.language} />
<Tabs
tabPosition="right"
animated={false}
items={tabItems}
$language={i18n.language}
/>
)
) : (
<EmptyView>
@ -232,6 +236,7 @@ const ContentContainer = styled.div`
height: 100%;
padding: 0 10px;
padding-left: 0;
border-top: 0.5px solid var(--color-border);
`
const AssistantsContainer = styled.div`
@ -239,6 +244,7 @@ const AssistantsContainer = styled.div`
flex: 1;
flex-direction: row;
height: calc(100vh - var(--navbar-height));
border-left: 0.5px solid var(--color-border);
`
const TabContent = styled(Scrollbar)`
@ -247,6 +253,9 @@ const TabContent = styled(Scrollbar)`
margin-right: -4px;
padding-bottom: 20px !important;
overflow-x: hidden;
transform: translateZ(0);
will-change: transform;
-webkit-font-smoothing: antialiased;
`
const AgentPrompt = styled.div`
@ -268,12 +277,16 @@ const Tabs = styled(TabsAntd)<{ $language: string }>`
display: flex;
flex: 1;
flex-direction: row-reverse;
border-right: 0.5px solid var(--color-border);
.ant-tabs-tabpane {
padding-right: 0 !important;
}
.ant-tabs-nav {
min-width: ${({ $language }) => ($language.startsWith('zh') ? '120px' : '140px')};
max-width: ${({ $language }) => ($language.startsWith('zh') ? '120px' : '140px')};
position: relative;
overflow: hidden;
}
.ant-tabs-nav-list {
padding: 10px 8px;
@ -291,11 +304,14 @@ const Tabs = styled(TabsAntd)<{ $language: string }>`
border: 0.5px solid transparent;
justify-content: ${({ $language }) => ($language.startsWith('zh') ? 'center' : 'flex-start')};
user-select: none;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
.ant-tabs-tab-btn {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100px;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
&:hover {
color: var(--color-text) !important;
@ -304,12 +320,11 @@ const Tabs = styled(TabsAntd)<{ $language: string }>`
}
.ant-tabs-tab-active {
background-color: var(--color-background-soft);
border-right: none;
border: 0.5px solid var(--color-border);
transform: scale(1.02);
}
.ant-tabs-content-holder {
border-left: 0.5px solid var(--color-border);
border-right: none;
}
.ant-tabs-ink-bar {
display: none;
@ -322,6 +337,9 @@ const Tabs = styled(TabsAntd)<{ $language: string }>`
color: var(--color-text) !important;
}
}
.ant-tabs-content {
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
`
export default AgentsPage

View File

@ -3,10 +3,11 @@ import { Agent } from '@renderer/types'
import { getLeadingEmoji } from '@renderer/utils'
import { Dropdown } from 'antd'
import styled from 'styled-components'
import { FC, memo } from 'react'
interface Props {
agent: Agent
onClick?: () => void
onClick: () => void
contextMenu?: { label: string; onClick: () => void }[]
menuItems?: {
key: string
@ -17,7 +18,7 @@ interface Props {
}[]
}
const AgentCard: React.FC<Props> = ({ agent, onClick, contextMenu, menuItems }) => {
const AgentCard: FC<Props> = ({ agent, onClick, contextMenu, menuItems }) => {
const emoji = agent.emoji || getLeadingEmoji(agent.name)
const prompt = (agent.description || agent.prompt).substring(0, 100).replace(/\\n/g, '')
const content = (
@ -205,4 +206,4 @@ const MenuContainer = styled.div`
}
`
export default AgentCard
export default memo(AgentCard)

View File

@ -3,7 +3,7 @@ import { useAgents } from '@renderer/hooks/useAgents'
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
import { createAssistantFromAgent } from '@renderer/services/AssistantService'
import { Agent } from '@renderer/types'
import { Col } from 'antd'
import { Col, Row } from 'antd'
import { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
@ -43,7 +43,7 @@ const MyAgents: React.FC<Props> = ({ onClick, search }) => {
)
return (
<>
<Row gutter={[20, 20]}>
{filteredAgents.map((agent) => {
const dropdownMenuItems = [
{
@ -102,7 +102,7 @@ const MyAgents: React.FC<Props> = ({ onClick, search }) => {
<Col span={6}>
<AddAgentCard onClick={() => AddAgentPopup.show()} />
</Col>
</>
</Row>
)
}