@@ -6,7 +6,7 @@ import { Button } from "@/components/ui/button";
66import { Checkbox } from "@/components/ui/checkbox" ;
77import { Command , CommandGroup , CommandItem , CommandList } from "@/components/ui/command" ;
88import { Dialog , DialogContent , DialogFooter , DialogHeader , DialogTitle } from "@/components/ui/dialog" ;
9- import { DropdownMenu , DropdownMenuContent , DropdownMenuItem , DropdownMenuPortal , DropdownMenuSub , DropdownMenuSubContent , DropdownMenuSubTrigger , DropdownMenuTrigger } from "@/components/ui/dropdown-menu" ;
9+ import { DropdownMenu , DropdownMenuContent , DropdownMenuItem , DropdownMenuPortal , DropdownMenuRadioGroup , DropdownMenuRadioItem , DropdownMenuSub , DropdownMenuSubContent , DropdownMenuSubTrigger , DropdownMenuTrigger } from "@/components/ui/dropdown-menu" ;
1010import { Field , FieldContent , FieldLabel } from "@/components/ui/field" ;
1111import { Input } from "@/components/ui/input" ;
1212import { InputGroup , InputGroupTextarea } from "@/components/ui/input-group" ;
@@ -16,9 +16,9 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
1616import { Separator } from "@/components/ui/separator" ;
1717import { Spinner } from "@/components/ui/spinner" ;
1818import { cn } from "@/lib/utils" ;
19- import { canUseModelBySubscription , getBrandFromModelName , getGitPlatformIcon , getHostBadges , getImageShortName , getModelPricingItem , getModelPricingPriceLabel , getOSFromImageName , getOwnerTypeBadge , getRepoIcon , getRepoNameFromUrl , getSkillTagIcon , selectHost , selectImage , selectPreferredTaskModel } from "@/utils/common" ;
19+ import { TASK_PROMPT_PLACEHOLDER , canUseModelBySubscription , getBrandFromModelName , getGitPlatformIcon , getHostBadges , getImageShortName , getModelPricingItem , getOSFromImageName , getOwnerTypeBadge , getRepoIcon , getRepoNameFromUrl , getSkillTagIcon , selectHost , selectImage , selectPreferredTaskModel } from "@/utils/common" ;
2020import { apiRequest } from "@/utils/requestUtils" ;
21- import { IconBug , IconHelpCircle , IconLink , IconPuzzle , IconReload , IconSend , IconSourceCode , IconTerminal2 , IconUpload , IconUser , IconVocabulary , IconXboxX } from "@tabler/icons-react" ;
21+ import { IconBug , IconChevronDown , IconHelpCircle , IconLink , IconPuzzle , IconReload , IconSend , IconSourceCode , IconTerminal2 , IconUpload , IconUser , IconVocabulary , IconXboxX } from "@tabler/icons-react" ;
2222import { useEffect , useMemo , useRef , useState } from "react" ;
2323import { useNavigate } from "react-router-dom" ;
2424import { useSettingsDialog } from "@/pages/console/user/page" ;
@@ -482,7 +482,7 @@ export function TaskInput({ repos, onTaskCreated }: TaskInputProps) {
482482 < InputGroup className = "rounded-4xl p-2 pb-0" >
483483 < InputGroupTextarea
484484 className = "min-h-30 max-h-60 break-all"
485- placeholder = "请输入任务内容"
485+ placeholder = { TASK_PROMPT_PLACEHOLDER }
486486 value = { taskContent }
487487 onChange = { ( e ) => setTaskContent ( e . target . value ) }
488488 />
@@ -819,45 +819,60 @@ export function TaskInput({ repos, onTaskCreated }: TaskInputProps) {
819819 < FieldLabel > 大模型</ FieldLabel >
820820 < FieldContent >
821821 < div className = "flex items-center gap-2" >
822- < Select value = { selectedModelId } onValueChange = { setSelectedModelId } >
823- < SelectTrigger className = "w-full" >
824- < SelectValue placeholder = "选择大模型" />
825- </ SelectTrigger >
826- < SelectContent >
827- { models . map ( ( model ) => (
828- ( ( ) => {
829- const showPricingSummary = model . owner ?. type === ConstsOwnerType . OwnerTypePublic
830- const pricing = showPricingSummary ? getModelPricingItem ( model . model ) : undefined
831- const pricingLabel = getModelPricingPriceLabel ( pricing )
832-
833- return (
834- < SelectItem
835- key = { model . id }
836- value = { model . id || "" }
837- disabled = { ! adaptedModelForTool ( ) } >
838- < div className = "flex w-full items-center justify-between gap-3" >
839- < div className = "flex min-w-0 items-center gap-2" >
840- < Icon name = { getBrandFromModelName ( model . model || '' ) } className = "size-4" />
841- < span className = "truncate" > { model . model } </ span >
842- { showPricingSummary && pricingLabel && (
843- < Badge
844- variant = { pricing ?. credits === 0 ? "default" : "secondary" }
845- className = { pricing ?. credits === 0 ? "shrink-0 !text-primary-foreground" : "shrink-0 !text-secondary-foreground" }
846- >
847- { pricingLabel }
848- </ Badge >
849- ) }
822+ < div className = "flex-1" >
823+ < DropdownMenu >
824+ < DropdownMenuTrigger asChild >
825+ < Button type = "button" variant = "outline" className = "w-full justify-between" >
826+ { selectedModel ? (
827+ < div className = "flex min-w-0 flex-1 items-center gap-2" >
828+ < Icon name = { getBrandFromModelName ( selectedModel . model || "" ) } className = "size-4" />
829+ < span className = "truncate" > { selectedModel . model } </ span >
850830 </ div >
851- < div className = "flex shrink-0 items-center gap-1.5" >
852- { model . owner ?. type !== ConstsOwnerType . OwnerTypePublic && getOwnerTypeBadge ( model . owner ) }
853- </ div >
854- </ div >
855- </ SelectItem >
856- )
857- } ) ( )
858- ) ) }
859- </ SelectContent >
860- </ Select >
831+ ) : (
832+ < span className = "truncate text-muted-foreground" > 选择大模型</ span >
833+ ) }
834+ < IconChevronDown className = "size-4 shrink-0 text-muted-foreground" />
835+ </ Button >
836+ </ DropdownMenuTrigger >
837+ < DropdownMenuContent align = "start" className = "w-(--radix-dropdown-menu-trigger-width) min-w-[320px]" >
838+ < DropdownMenuRadioGroup value = { selectedModelId } onValueChange = { setSelectedModelId } >
839+ { models . map ( ( model ) => (
840+ ( ( ) => {
841+ const showPricingSummary = model . owner ?. type === ConstsOwnerType . OwnerTypePublic
842+ const pricing = showPricingSummary ? getModelPricingItem ( model . model ) : undefined
843+ const pricingTags = pricing ?. tags ?? [ ]
844+
845+ return (
846+ < DropdownMenuRadioItem
847+ key = { model . id }
848+ value = { model . id || "" }
849+ disabled = { ! adaptedModelForTool ( ) }
850+ className = "w-full justify-between gap-3 pr-2 [&>[data-slot=dropdown-menu-radio-item-indicator]]:hidden"
851+ >
852+ < div className = "flex min-w-0 flex-1 items-center gap-2" >
853+ < Icon name = { getBrandFromModelName ( model . model || "" ) } className = "size-4" />
854+ < span className = "truncate" > { model . model } </ span >
855+ </ div >
856+ < div className = "ml-auto flex shrink-0 items-center justify-end gap-1.5" >
857+ { showPricingSummary && pricingTags . map ( ( tag ) => (
858+ < Badge
859+ key = { `${ model . id } -${ tag } ` }
860+ variant = "default"
861+ className = "shrink-0 !bg-primary !text-primary-foreground"
862+ >
863+ { tag }
864+ </ Badge >
865+ ) ) }
866+ { model . owner ?. type !== ConstsOwnerType . OwnerTypePublic && getOwnerTypeBadge ( model . owner ) }
867+ </ div >
868+ </ DropdownMenuRadioItem >
869+ )
870+ } ) ( )
871+ ) ) }
872+ </ DropdownMenuRadioGroup >
873+ </ DropdownMenuContent >
874+ </ DropdownMenu >
875+ </ div >
861876 < Tooltip >
862877 < TooltipTrigger asChild >
863878 < Button
0 commit comments