Skip to content

Commit a07a902

Browse files
committed
Refine task prompts and model tags
1 parent 70f5aef commit a07a902

5 files changed

Lines changed: 141 additions & 108 deletions

File tree

frontend/doc.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,9 @@
402402

403403
当前展示的固定价格如下:
404404

405-
- `gpt5.4``1000` 积分
406-
- `gpt5.2``600` 积分
407-
- `gpt5.3-codex``600` 积分
405+
- `gpt5.4``500` 积分
406+
- `gpt5.2``300` 积分
407+
- `gpt5.3-codex``300` 积分
408408
- `gpt5.1``500` 积分
409409
- `minimax-m2.7`:免费
410410
- `glm-5.1``600` 积分

frontend/src/components/console/project/start-develop-task-dialog.tsx

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ import { useCommonData } from "@/components/console/data-provider"
44
import { Badge } from "@/components/ui/badge"
55
import { Button } from "@/components/ui/button"
66
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
7+
import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
78
import { Input } from "@/components/ui/input"
89
import { Label } from "@/components/ui/label"
910
import { Textarea } from "@/components/ui/textarea"
1011
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
1112
import { Spinner } from "@/components/ui/spinner"
12-
import { canUseModelBySubscription, getBrandFromModelName, getModelPricingItem, getModelPricingPriceLabel, getOwnerTypeBadge, selectHost, selectImage, selectPreferredTaskModel } from "@/utils/common"
13+
import { TASK_PROMPT_PLACEHOLDER, canUseModelBySubscription, getBrandFromModelName, getModelPricingItem, getOwnerTypeBadge, selectHost, selectImage, selectPreferredTaskModel } from "@/utils/common"
1314
import { apiRequest } from "@/utils/requestUtils"
14-
import { IconHelpCircle, IconSparkles } from "@tabler/icons-react"
15-
import { useState, useEffect, useRef } from "react"
15+
import { IconChevronDown, IconHelpCircle, IconSparkles } from "@tabler/icons-react"
16+
import { useState, useEffect, useMemo, useRef } from "react"
1617
import { useNavigate } from "react-router-dom"
1718
import { toast } from "sonner"
1819
import { TaskConcurrentLimitDialog } from "@/components/console/task/task-concurrent-limit-dialog"
@@ -41,6 +42,10 @@ export default function StartDevelopTaskDialog({
4142
const [userMessage, setUserMessage] = useState<string>('')
4243
const [selectedModelId, setSelectedModelId] = useState<string>('')
4344
const { images, models, hosts, subscription } = useCommonData()
45+
const selectedModel = useMemo(
46+
() => models.find((model) => model.id === selectedModelId),
47+
[models, selectedModelId]
48+
)
4449

4550
const handleOpenModelPricing = () => {
4651
window.dispatchEvent(new CustomEvent(OPEN_WALLET_DIALOG_EVENT, {
@@ -251,42 +256,59 @@ export default function StartDevelopTaskDialog({
251256
<div className="space-y-2">
252257
<Label>大模型</Label>
253258
<div className="flex items-center gap-2">
254-
<Select value={selectedModelId} onValueChange={setSelectedModelId}>
255-
<SelectTrigger className="w-full">
256-
<SelectValue placeholder="选择大模型" />
257-
</SelectTrigger>
258-
<SelectContent>
259-
{models.map((model) => (
260-
(() => {
261-
const showPricingSummary = model.owner?.type === ConstsOwnerType.OwnerTypePublic
262-
const pricing = showPricingSummary ? getModelPricingItem(model.model) : undefined
263-
const pricingLabel = getModelPricingPriceLabel(pricing)
259+
<div className="flex-1">
260+
<DropdownMenu>
261+
<DropdownMenuTrigger asChild>
262+
<Button type="button" variant="outline" className="w-full justify-between">
263+
{selectedModel ? (
264+
<div className="flex min-w-0 flex-1 items-center gap-2">
265+
<Icon name={getBrandFromModelName(selectedModel.model || "")} className="size-4" />
266+
<span className="truncate">{selectedModel.model}</span>
267+
</div>
268+
) : (
269+
<span className="truncate text-muted-foreground">选择大模型</span>
270+
)}
271+
<IconChevronDown className="size-4 shrink-0 text-muted-foreground" />
272+
</Button>
273+
</DropdownMenuTrigger>
274+
<DropdownMenuContent align="start" className="w-(--radix-dropdown-menu-trigger-width) min-w-[320px]">
275+
<DropdownMenuRadioGroup value={selectedModelId} onValueChange={setSelectedModelId}>
276+
{models.map((model) => (
277+
(() => {
278+
const showPricingSummary = model.owner?.type === ConstsOwnerType.OwnerTypePublic
279+
const pricing = showPricingSummary ? getModelPricingItem(model.model) : undefined
280+
const pricingTags = pricing?.tags ?? []
264281

265-
return (
266-
<SelectItem key={model.id} value={model.id || ""}>
267-
<div className="flex w-full items-center justify-between gap-3">
268-
<div className="flex min-w-0 items-center gap-2">
269-
<Icon name={getBrandFromModelName(model.model || '')} className="size-4" />
282+
return (
283+
<DropdownMenuRadioItem
284+
key={model.id}
285+
value={model.id || ""}
286+
className="w-full justify-between gap-3 pr-2 [&>[data-slot=dropdown-menu-radio-item-indicator]]:hidden"
287+
>
288+
<div className="flex min-w-0 flex-1 items-center gap-2">
289+
<Icon name={getBrandFromModelName(model.model || "")} className="size-4" />
270290
<span className="truncate">{model.model}</span>
271-
{showPricingSummary && pricingLabel && (
291+
</div>
292+
<div className="ml-auto flex shrink-0 items-center justify-end gap-1.5">
293+
{showPricingSummary && pricingTags.map((tag) => (
272294
<Badge
273-
variant={pricing?.credits === 0 ? "default" : "secondary"}
274-
className={pricing?.credits === 0 ? "shrink-0 !text-primary-foreground" : "shrink-0 !text-secondary-foreground"}
295+
key={`${model.id}-${tag}`}
296+
variant="default"
297+
className="shrink-0 !bg-primary !text-primary-foreground"
275298
>
276-
{pricingLabel}
299+
{tag}
277300
</Badge>
278-
)}
279-
</div>
280-
<div className="flex shrink-0 items-center gap-1.5">
301+
))}
281302
{model.owner?.type !== ConstsOwnerType.OwnerTypePublic && getOwnerTypeBadge(model.owner)}
282303
</div>
283-
</div>
284-
</SelectItem>
285-
)
286-
})()
287-
))}
288-
</SelectContent>
289-
</Select>
304+
</DropdownMenuRadioItem>
305+
)
306+
})()
307+
))}
308+
</DropdownMenuRadioGroup>
309+
</DropdownMenuContent>
310+
</DropdownMenu>
311+
</div>
290312
<Button
291313
type="button"
292314
size="icon-sm"
@@ -304,7 +326,7 @@ export default function StartDevelopTaskDialog({
304326
<Textarea
305327
value={userMessage}
306328
onChange={(e) => setUserMessage(e.target.value)}
307-
placeholder="请输入任务内容"
329+
placeholder={TASK_PROMPT_PLACEHOLDER}
308330
rows={4}
309331
className="resize-none break-all"
310332
/>

frontend/src/components/console/task/create-default-task-dialog.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ import {
5757
getHostBadges,
5858
getImageShortName,
5959
getModelPricingItem,
60-
getModelPricingPriceLabel,
6160
getOSFromImageName,
6261
getOwnerTypeBadge,
6362
getRepoIcon,
6463
getRepoNameFromUrl,
6564
getSkillTagIcon,
65+
TASK_PROMPT_PLACEHOLDER,
6666
selectHost,
6767
selectImage,
6868
selectPreferredTaskModel,
@@ -571,7 +571,7 @@ export default function CreateDefaultTaskDialog({
571571
<Textarea
572572
value={content}
573573
onChange={(e) => setContent(e.target.value)}
574-
placeholder="请输入任务内容"
574+
placeholder={TASK_PROMPT_PLACEHOLDER}
575575
className="min-h-36 resize-none"
576576
/>
577577

@@ -967,27 +967,28 @@ export default function CreateDefaultTaskDialog({
967967
(() => {
968968
const showPricingSummary = model.owner?.type === ConstsOwnerType.OwnerTypePublic
969969
const pricing = showPricingSummary ? getModelPricingItem(model.model) : undefined
970-
const pricingLabel = getModelPricingPriceLabel(pricing)
970+
const pricingTags = pricing?.tags ?? []
971971

972972
return (
973973
<DropdownMenuRadioItem
974974
key={model.id}
975975
value={model.id || ""}
976976
className="w-full justify-between gap-3 pr-2 [&>[data-slot=dropdown-menu-radio-item-indicator]]:hidden"
977977
>
978-
<div className="flex min-w-0 items-center gap-2">
978+
<div className="flex min-w-0 flex-1 items-center gap-2">
979979
<Icon name={getBrandFromModelName(model.model || "")} className="size-4" />
980980
<span className="truncate">{model.model}</span>
981-
{showPricingSummary && pricingLabel && (
981+
</div>
982+
<div className="ml-auto flex shrink-0 items-center justify-end gap-1.5">
983+
{showPricingSummary && pricingTags.map((tag) => (
982984
<Badge
983-
variant={pricing?.credits === 0 ? "default" : "secondary"}
984-
className={pricing?.credits === 0 ? "shrink-0 !text-primary-foreground" : "shrink-0 !text-secondary-foreground"}
985+
key={`${model.id}-${tag}`}
986+
variant="default"
987+
className="shrink-0 !bg-primary !text-primary-foreground"
985988
>
986-
{pricingLabel}
989+
{tag}
987990
</Badge>
988-
)}
989-
</div>
990-
<div className="flex shrink-0 items-center justify-end gap-1.5">
991+
))}
991992
{model.owner?.type !== ConstsOwnerType.OwnerTypePublic && getOwnerTypeBadge(model.owner)}
992993
</div>
993994
</DropdownMenuRadioItem>

frontend/src/components/console/task/task-input.tsx

Lines changed: 57 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Button } from "@/components/ui/button";
66
import { Checkbox } from "@/components/ui/checkbox";
77
import { Command, CommandGroup, CommandItem, CommandList } from "@/components/ui/command";
88
import { 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";
1010
import { Field, FieldContent, FieldLabel } from "@/components/ui/field";
1111
import { Input } from "@/components/ui/input";
1212
import { InputGroup, InputGroupTextarea } from "@/components/ui/input-group";
@@ -16,9 +16,9 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
1616
import { Separator } from "@/components/ui/separator";
1717
import { Spinner } from "@/components/ui/spinner";
1818
import { 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";
2020
import { 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";
2222
import { useEffect, useMemo, useRef, useState } from "react";
2323
import { useNavigate } from "react-router-dom";
2424
import { 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

Comments
 (0)