fix(WebSearch): fix web search condition check (#9310)

* fix(web搜索): 修正web搜索功能的条件判断和逻辑处理

修复web搜索启用条件的判断逻辑,统一使用webSearchProviderId作为启用标志
重命名相关函数以更准确表达其功能,并优化quickPanel打开逻辑

* fix(WebSearchButton): 修复快速面板点击逻辑

重构 web search provider 更新逻辑,提取为独立的 updateQuickPanelItem 方法
添加 onClick 处理函数统一管理按钮点击行为

* refactor(WebSearchButton): 更新依赖项数组

* refactor(WebSearchButton): 移除重复的颜色计算并简化图标组件

将颜色计算逻辑从WebSearchIcon组件中移出,统一在父组件中处理
This commit is contained in:
Phantom 2025-08-24 13:42:10 +08:00 committed by GitHub
parent d6866052c4
commit 17cee98617
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 42 deletions

View File

@ -28,48 +28,62 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
const { providers } = useWebSearchProviders()
const { updateAssistant } = useAssistant(assistant.id)
// 注意assistant.enableWebSearch 有不同的语义
/** 表示是否启用网络搜索 */
const enableWebSearch = assistant?.webSearchProviderId || assistant.enableWebSearch
const WebSearchIcon = useCallback(
({ pid, size = 18 }: { pid?: WebSearchProviderId; size?: number }) => {
const iconColor = enableWebSearch ? 'var(--color-primary)' : 'var(--color-icon)'
({ pid, size = 18, color }: { pid?: WebSearchProviderId; size?: number; color?: string }) => {
switch (pid) {
case 'bocha':
return <BochaLogo width={size} height={size} color={iconColor} />
return <BochaLogo width={size} height={size} color={color} />
case 'exa':
// size微调视觉上和其他图标平衡一些
return <ExaLogo width={size - 2} height={size} color={iconColor} />
return <ExaLogo width={size - 2} height={size} color={color} />
case 'tavily':
return <TavilyLogo width={size} height={size} color={iconColor} />
return <TavilyLogo width={size} height={size} color={color} />
case 'searxng':
return <SearXNGLogo width={size} height={size} color={iconColor} />
return <SearXNGLogo width={size} height={size} color={color} />
case 'local-baidu':
return <BaiduOutlined size={size} style={{ color: iconColor, fontSize: size }} />
return <BaiduOutlined size={size} style={{ color, fontSize: size }} />
case 'local-bing':
return <BingLogo width={size} height={size} color={iconColor} />
return <BingLogo width={size} height={size} color={color} />
case 'local-google':
return <GoogleOutlined size={size} style={{ color: iconColor, fontSize: size }} />
return <GoogleOutlined size={size} style={{ color, fontSize: size }} />
default:
return <Globe size={size} style={{ color: iconColor, fontSize: size }} />
return <Globe size={size} style={{ color, fontSize: size }} />
}
},
[enableWebSearch]
)
const updateSelectedWebSearchProvider = useCallback(
const updateWebSearchProvider = useCallback(
async (providerId?: WebSearchProvider['id']) => {
// TODO: updateAssistant有性能问题会导致关闭快捷面板卡顿
const currentWebSearchProviderId = assistant.webSearchProviderId
const newWebSearchProviderId = currentWebSearchProviderId === providerId ? undefined : providerId
startTransition(() => {
updateAssistant({ ...assistant, webSearchProviderId: newWebSearchProviderId, enableWebSearch: false })
updateAssistant({
...assistant,
webSearchProviderId: providerId,
enableWebSearch: false
})
})
},
[assistant, updateAssistant]
)
const updateSelectedWebSearchBuiltin = useCallback(async () => {
const updateQuickPanelItem = useCallback(
async (providerId?: WebSearchProvider['id']) => {
// TODO: updateAssistant有性能问题会导致关闭快捷面板卡顿
if (providerId === assistant.webSearchProviderId) {
updateWebSearchProvider(undefined)
} else {
updateWebSearchProvider(providerId)
}
},
[assistant.webSearchProviderId, updateWebSearchProvider]
)
const updateToModelBuiltinWebSearch = useCallback(async () => {
// TODO: updateAssistant有性能问题会导致关闭快捷面板卡顿
startTransition(() => {
updateAssistant({ ...assistant, webSearchProviderId: undefined, enableWebSearch: !assistant.enableWebSearch })
@ -90,7 +104,7 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
icon: <WebSearchIcon size={13} pid={p.id} />,
isSelected: p.id === assistant?.webSearchProviderId,
disabled: !WebSearchService.isWebSearchEnabled(p.id),
action: () => updateSelectedWebSearchProvider(p.id)
action: () => updateQuickPanelItem(p.id)
}))
.filter((o) => !o.disabled)
@ -103,7 +117,7 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
icon: <Globe />,
isSelected: assistant.enableWebSearch,
disabled: !isWebSearchModelEnabled,
action: () => updateSelectedWebSearchBuiltin()
action: () => updateToModelBuiltinWebSearch()
})
}
@ -115,36 +129,18 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
assistant?.webSearchProviderId,
providers,
t,
updateSelectedWebSearchBuiltin,
updateSelectedWebSearchProvider
updateQuickPanelItem,
updateToModelBuiltinWebSearch
])
const openQuickPanel = useCallback(() => {
if (assistant.webSearchProviderId) {
updateSelectedWebSearchProvider(undefined)
return
}
if (assistant.enableWebSearch) {
updateSelectedWebSearchBuiltin()
return
}
quickPanel.open({
title: t('chat.input.web_search.label'),
list: providerItems,
symbol: '?',
pageSize: 9
})
}, [
assistant.webSearchProviderId,
assistant.enableWebSearch,
quickPanel,
t,
providerItems,
updateSelectedWebSearchProvider,
updateSelectedWebSearchBuiltin
])
}, [quickPanel, t, providerItems])
const handleOpenQuickPanel = useCallback(() => {
if (quickPanel.isVisible && quickPanel.symbol === '?') {
@ -154,18 +150,28 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
}
}, [openQuickPanel, quickPanel])
const onClick = useCallback(() => {
if (enableWebSearch) {
updateWebSearchProvider(undefined)
} else {
handleOpenQuickPanel()
}
}, [enableWebSearch, handleOpenQuickPanel, updateWebSearchProvider])
useImperativeHandle(ref, () => ({
openQuickPanel
}))
const color = enableWebSearch ? 'var(--color-primary)' : 'var(--color-icon)'
return (
<Tooltip
placement="top"
title={enableWebSearch ? t('common.close') : t('chat.input.web_search.label')}
mouseLeaveDelay={0}
arrow>
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
<WebSearchIcon pid={assistant.webSearchProviderId} />
<ToolbarButton type="text" onClick={onClick}>
<WebSearchIcon color={color} pid={assistant.webSearchProviderId} />
</ToolbarButton>
</Tooltip>
)

View File

@ -477,8 +477,9 @@ export async function fetchChatCompletion({
assistant.settings?.reasoning_effort !== undefined) ||
(isReasoningModel(model) && (!isSupportedThinkingTokenModel(model) || !isSupportedReasoningEffortModel(model)))
// NOTEassistant.enableWebSearch 的语义是是否启用模型内置搜索功能
const enableWebSearch =
(assistant.enableWebSearch && isWebSearchModel(model)) ||
(assistant.webSearchProviderId && isWebSearchModel(model)) ||
isOpenRouterBuiltInWebSearchModel(model) ||
model.id.includes('sonar') ||
false