1- import { ConstsCliName , ConstsTaskSubType , ConstsTaskType } from "@/api/Api"
1+ import { ConstsCliName , ConstsTaskSubType , ConstsTaskType , ConstsGitPlatform , type DomainProject , type DomainBranch } from "@/api/Api"
22import { useCommonData } from "@/components/console/data-provider"
33import { Button } from "@/components/ui/button"
4- import { Dialog , DialogContent , DialogDescription , DialogFooter , DialogHeader , DialogTitle } from "@/components/ui/dialog"
4+ import { Dialog , DialogContent , DialogFooter , DialogHeader , DialogTitle } from "@/components/ui/dialog"
5+ import { Input } from "@/components/ui/input"
6+ import { Label } from "@/components/ui/label"
7+ import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from "@/components/ui/select"
58import { Spinner } from "@/components/ui/spinner"
69import { packAndUploadFilesAsZip , selectHost , selectImage , selectModel } from "@/utils/common"
710import { apiRequest } from "@/utils/requestUtils"
811import { IconSparkles } from "@tabler/icons-react"
9- import { useState } from "react"
12+ import { useState , useEffect } from "react"
1013import { toast } from "sonner"
1114
1215interface GenerateDocDialogProps {
1316 open : boolean
1417 onOpenChange : ( open : boolean ) => void
1518 projectId : string
1619 projectName : string
20+ project ?: DomainProject
1721}
1822
1923export default function GenerateDocDialog ( {
2024 open,
2125 onOpenChange,
2226 projectId,
23- projectName
27+ projectName,
28+ project
2429} : GenerateDocDialogProps ) {
2530 const [ selectedFiles , setSelectedFiles ] = useState < File [ ] > ( [ ] )
2631 const [ submitting , setSubmitting ] = useState < boolean > ( false )
32+ const [ branches , setBranches ] = useState < string [ ] > ( [ ] )
33+ const [ selectedBranch , setSelectedBranch ] = useState < string > ( '' )
34+ const [ loadingBranches , setLoadingBranches ] = useState < boolean > ( false )
2735 const { images, models, hosts } = useCommonData ( )
2836
37+ const fetchBranches = async ( ) => {
38+ if ( ! project ?. git_identity_id || ! project ?. repo_url ) {
39+ return
40+ }
41+
42+ // internal 平台不需要获取分支列表
43+ if ( project . platform === ConstsGitPlatform . GitPlatformInternal ) {
44+ setSelectedBranch ( '' )
45+ setBranches ( [ ] )
46+ return
47+ }
48+
49+ setLoadingBranches ( true )
50+
51+ try {
52+ // 直接使用 full_name 字段
53+ const escapedRepoFullName = project ?. full_name || ''
54+
55+ if ( ! escapedRepoFullName ) {
56+ toast . error ( '无法获取仓库信息' )
57+ setLoadingBranches ( false )
58+ return
59+ }
60+
61+ // URL 编码仓库名称
62+ const encodedRepoName = encodeURIComponent ( escapedRepoFullName )
63+
64+ await apiRequest ( 'v1UsersGitIdentitiesBranchesDetail' , { } , [ project . git_identity_id , encodedRepoName ] , ( resp ) => {
65+ if ( resp . code === 0 && resp . data ) {
66+ const branchList = resp . data . map ( ( b : DomainBranch ) => b . name || '' ) . filter ( Boolean )
67+ setBranches ( branchList )
68+
69+ // 优先选择 main 或 master,否则选择第一个
70+ if ( branchList . includes ( 'main' ) ) {
71+ setSelectedBranch ( 'main' )
72+ } else if ( branchList . includes ( 'master' ) ) {
73+ setSelectedBranch ( 'master' )
74+ } else if ( branchList . length > 0 ) {
75+ setSelectedBranch ( branchList [ 0 ] )
76+ }
77+ } else {
78+ toast . error ( '获取分支列表失败: ' + resp . message )
79+ }
80+ } )
81+ } catch ( error ) {
82+ console . error ( 'Fetch branches error:' , error )
83+ toast . error ( '获取分支列表失败' )
84+ } finally {
85+ setLoadingBranches ( false )
86+ }
87+ }
88+
89+ useEffect ( ( ) => {
90+ if ( open ) {
91+ fetchBranches ( )
92+ }
93+ } , [ open , project ] )
94+
2995 const handleOpenChange = ( open : boolean ) => {
3096 onOpenChange ( open )
3197 if ( ! open ) {
3298 // 重置表单状态
3399 setSelectedFiles ( [ ] )
100+ setSelectedBranch ( '' )
101+ setBranches ( [ ] )
34102 }
35103 }
36104
37105 const handleSubmit = async ( ) => {
106+ if ( project ?. platform !== ConstsGitPlatform . GitPlatformInternal && ! selectedBranch ) {
107+ toast . error ( '请选择分支' )
108+ return
109+ }
110+
38111 setSubmitting ( true )
39112
40113 let repoInfo : { zip_url ?: string ; repo_filename ?: string } = { }
@@ -68,6 +141,7 @@ export default function GenerateDocDialog({
68141 } ,
69142 extra : {
70143 project_id : projectId ,
144+ branch : project ?. platform === ConstsGitPlatform . GitPlatformInternal ? '' : selectedBranch ,
71145 } ,
72146 task_type : ConstsTaskType . TaskTypeDesign ,
73147 sub_type : ConstsTaskSubType . TaskSubTypeGenerateDocs ,
@@ -89,10 +163,43 @@ export default function GenerateDocDialog({
89163 < DialogContent >
90164 < DialogHeader >
91165 < DialogTitle > 生成项目文档</ DialogTitle >
92- < DialogDescription >
93- AI 将根据你的需求为你生成项目架构设计文档
94- </ DialogDescription >
95166 </ DialogHeader >
167+
168+ < div className = "space-y-4 py-4" >
169+ < div className = "space-y-2" >
170+ < Label > 仓库地址</ Label >
171+ < Input
172+ value = { project ?. repo_url || '-' }
173+ readOnly
174+ className = "bg-muted"
175+ />
176+ </ div >
177+ { ( project ?. platform !== ConstsGitPlatform . GitPlatformInternal ) && (
178+ < div className = "space-y-2" >
179+ < Label > 选择分支</ Label >
180+ < Select value = { selectedBranch } onValueChange = { setSelectedBranch } disabled = { loadingBranches || branches . length === 0 } >
181+ < SelectTrigger >
182+ { loadingBranches ? (
183+ < div className = "flex items-center gap-2" >
184+ < Spinner className = "size-4" />
185+ < span > 加载中...</ span >
186+ </ div >
187+ ) : (
188+ < SelectValue placeholder = "请选择分支" />
189+ ) }
190+ </ SelectTrigger >
191+ < SelectContent >
192+ { branches . map ( ( branch ) => (
193+ < SelectItem key = { branch } value = { branch } >
194+ { branch }
195+ </ SelectItem >
196+ ) ) }
197+ </ SelectContent >
198+ </ Select >
199+ </ div >
200+ ) }
201+ </ div >
202+
96203 < DialogFooter >
97204 < Button
98205 onClick = { handleSubmit }
@@ -106,4 +213,3 @@ export default function GenerateDocDialog({
106213 </ Dialog >
107214 )
108215}
109-
0 commit comments