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

View File

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