feat(组件): 模型选择器支持 Gemini 图片模型

- 新增 Gemini 图片模型卡片配置
- 添加 gemini 模型类型检测逻辑
- 实现 Gemini 模型选择和高亮显示
- 添加模型类型切换提示信息
This commit is contained in:
gaoziman 2025-12-27 15:02:04 +08:00
parent 81e437d0b4
commit 6a70b236b6

View File

@ -48,8 +48,18 @@ const CODEX_MODEL_CARDS = [
},
];
// Gemini 图片模型卡片配置
const GEMINI_MODEL_CARDS = [
{
id: 'gemini-3-pro-image-preview',
name: 'Gemini 图片',
description: '文生图',
modelIdPattern: 'gemini',
},
];
// 模型类型
type ModelType = 'claude' | 'codex';
type ModelType = 'claude' | 'codex' | 'gemini';
interface ModelCardSelectorProps {
value: string;
@ -73,6 +83,9 @@ export function ModelCardSelector({
if (modelId.startsWith('gpt-') && modelId.includes('codex')) {
return 'codex';
}
if (modelId.includes('gemini') || modelId.includes('imagen')) {
return 'gemini';
}
return 'claude';
};
@ -107,9 +120,22 @@ export function ModelCardSelector({
return model?.modelId || cardId;
};
// 根据当前选中的模型ID判断选中的卡片Gemini
const getSelectedGeminiCard = (modelId: string): string | null => {
const matchedCard = GEMINI_MODEL_CARDS.find((card) => modelId.includes(card.modelIdPattern));
return matchedCard?.id || null;
};
// 根据卡片类型找到对应的实际模型IDGemini
const findGeminiModelIdByCard = (cardId: string): string => {
const model = models.find((m) => m.modelId === cardId);
return model?.modelId || cardId;
};
const currentModelType = getModelType(value);
const selectedClaudeCard = getSelectedClaudeCard(value);
const selectedCodexCard = getSelectedCodexCard(value);
const selectedGeminiCard = getSelectedGeminiCard(value);
// 处理模型选择
const handleModelSelect = (modelId: string, modelType: ModelType) => {
@ -137,6 +163,9 @@ export function ModelCardSelector({
// 检查是否有 Codex 模型可用
const hasCodexModels = models.some(m => m.modelType === 'codex' || (m.modelId.startsWith('gpt-') && m.modelId.includes('codex')));
// 检查是否有 Gemini 模型可用
const hasGeminiModels = models.some(m => m.modelType === 'gemini' || m.modelId.includes('gemini') || m.modelId.includes('imagen'));
return (
<div className="space-y-6">
{/* 模型切换提示 */}
@ -148,6 +177,8 @@ export function ModelCardSelector({
<p className="text-amber-600 dark:text-amber-300 mt-1">
{currentModelType === 'codex'
? 'Codex 模型不支持思考模式Thinking但支持工具调用。'
: currentModelType === 'gemini'
? 'Gemini 图片模型专注于图片生成,不支持思考模式和工具调用。'
: 'Claude 模型支持思考模式和工具调用。'}
</p>
</div>
@ -271,6 +302,70 @@ export function ModelCardSelector({
</div>
</div>
)}
{/* Gemini 图片模型组 */}
{hasGeminiModels && (
<div>
<div className="text-xs font-medium text-[var(--color-text-tertiary)] mb-3 flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-blue-500"></span>
Gemini
<span className="text-[10px] px-1.5 py-0.5 rounded bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400">
Google
</span>
</div>
<div className="flex gap-3">
{GEMINI_MODEL_CARDS.map((card) => {
const isSelected = selectedGeminiCard === card.id;
// 检查该模型是否在可用模型列表中
const isAvailable = models.some(m => m.modelId === card.id || m.modelId.includes(card.modelIdPattern));
if (!isAvailable) return null;
return (
<button
key={card.id}
onClick={() => {
const newModelId = findGeminiModelIdByCard(card.id);
handleModelSelect(newModelId, 'gemini');
}}
disabled={disabled}
className={cn(
'flex flex-col items-center justify-center',
'w-[120px] h-[72px] rounded-md',
'border-2 transition-all duration-200',
'focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500',
isSelected
? 'bg-blue-50 dark:bg-blue-900/20 border-blue-500'
: 'bg-[var(--color-bg-tertiary)] border-transparent hover:border-blue-300 dark:hover:border-blue-700',
disabled && 'opacity-50 cursor-not-allowed'
)}
>
<span
className={cn(
'text-sm font-semibold',
isSelected
? 'text-blue-600 dark:text-blue-400'
: 'text-[var(--color-text-primary)]'
)}
>
{card.name}
</span>
<span
className={cn(
'text-xs mt-1',
isSelected
? 'text-blue-500 dark:text-blue-400'
: 'text-[var(--color-text-tertiary)]'
)}
>
{card.description}
</span>
</button>
);
})}
</div>
</div>
)}
</div>
);
}