Skip to content

Commit 220174a

Browse files
committed
feat(project): 环境变量和开发镜像保存时调用 v1UsersProjectsUpdate API
- edit-project-env: 保存时调用 API,env_variables 以字典形式传递 - edit-project-image: 保存时调用 API,传递 image_id - Api.ts: DomainUpdateProjectReq/DomainProject 增加 env_variables、image_id 字段 Made-with: Cursor
1 parent 9490d89 commit 220174a

File tree

3 files changed

+85
-43
lines changed

3 files changed

+85
-43
lines changed

frontend/src/api/Api.ts

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,12 @@ export interface DomainCreateModelReq {
393393
export interface DomainCreateProjectReq {
394394
/** 项目描述 */
395395
description?: string;
396+
/** 环境变量 */
397+
env_variables?: Record<string, any>;
396398
/** 关联的 git identity id */
397399
git_identity_id?: string;
400+
/** 关联的镜像ID */
401+
image_id?: string;
398402
/** 项目名 */
399403
name?: string;
400404
/** 项目平台 */
@@ -608,8 +612,6 @@ export interface DomainListGitBotResp {
608612
}
609613

610614
export interface DomainListGitBotTaskResp {
611-
/** 分页信息 */
612-
page_info?: Dbv2PageInfo;
613615
tasks?: DomainGitBotTask[];
614616
}
615617

@@ -654,10 +656,8 @@ export interface DomainListProjectResp {
654656
}
655657

656658
export interface DomainListTaskResp {
657-
/** 游标信息(游标分页时返回) */
659+
/** 游标信息 */
658660
page?: Dbv2Cursor;
659-
/** 分页信息(page/size 分页时返回) */
660-
page_info?: Dbv2PageInfo;
661661
/** 任务列表 */
662662
tasks?: DomainProjectTask[];
663663
}
@@ -717,6 +717,11 @@ export interface DomainModel {
717717
updated_at?: number;
718718
}
719719

720+
export enum DomainOAuthSiteType {
721+
OAuthSiteTypeDomestic = "domestic",
722+
OAuthSiteTypeInternational = "international",
723+
}
724+
720725
export interface DomainOAuthURLResp {
721726
url?: string;
722727
}
@@ -827,12 +832,16 @@ export interface DomainProject {
827832
created_at?: number;
828833
/** 项目描述 */
829834
description?: string;
835+
/** 环境变量 */
836+
env_variables?: Record<string, any>;
830837
/** 仓库 full_name */
831838
full_name?: string;
832839
/** 项目关联的 git identity id */
833840
git_identity_id?: string;
834841
/** 项目ID */
835842
id?: string;
843+
/** 项目关联的镜像ID */
844+
image_id?: string;
836845
/** 问题列表 */
837846
issues?: DomainProjectIssue[];
838847
/** 项目名 */
@@ -935,6 +944,7 @@ export interface DomainProjectTask {
935944
created_at?: number;
936945
/** 额外参数 */
937946
extra?: DomainTaskExtraConfig;
947+
full_name?: string;
938948
id: string;
939949
identity?: DomainGitIdentity;
940950
image?: DomainImage;
@@ -1066,7 +1076,7 @@ export interface DomainShareTerminalResp {
10661076
export interface DomainSiteInfo {
10671077
base_url?: string;
10681078
name?: string;
1069-
site_type?: string;
1079+
site_type?: DomainOAuthSiteType;
10701080
}
10711081

10721082
export interface DomainSitesResp {
@@ -1144,6 +1154,7 @@ export interface DomainTask {
11441154
created_at?: number;
11451155
/** 额外参数 */
11461156
extra?: DomainTaskExtraConfig;
1157+
full_name?: string;
11471158
id?: string;
11481159
identity?: DomainGitIdentity;
11491160
image?: DomainImage;
@@ -1352,6 +1363,10 @@ export interface DomainUpdateProjectReq {
13521363
collaborators?: DomainCreateCollaboratorItem[];
13531364
/** 项目描述 */
13541365
description?: string;
1366+
/** 环境变量 */
1367+
env_variables?: Record<string, any>;
1368+
/** 关联的镜像ID */
1369+
image_id?: string;
13551370
/** 项目名 */
13561371
name?: string;
13571372
}
@@ -1832,7 +1847,7 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
18321847
}),
18331848

18341849
/**
1835-
* @description 返回合并后的 Gitea 站点列表(团队配置优先,全局配置兜底),不含凭证信息
1850+
* @description 返回当前用户所有团队合并后的 Gitea 站点列表(团队配置优先,全局配置兜底),不含凭证信息
18361851
*
18371852
* @tags 站点管理
18381853
* @name V1GiteaSitesList
@@ -1911,7 +1926,7 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
19111926
}),
19121927

19131928
/**
1914-
* @description 返回合并后的 GitLab 站点列表(团队配置优先,全局配置兜底),不含凭证信息
1929+
* @description 返回当前用户所有团队合并后的 GitLab 站点列表(团队配置优先,全局配置兜底),不含凭证信息
19151930
*
19161931
* @tags 站点管理
19171932
* @name V1GitlabSitesList
@@ -3487,7 +3502,7 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
34873502
}),
34883503

34893504
/**
3490-
* @description Git Bot 任务列表,支持分页
3505+
* @description Git Bot 任务列表
34913506
*
34923507
* @tags 【用户】Git Bot
34933508
* @name V1UsersGitBotsTasksList
@@ -3497,14 +3512,8 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
34973512
*/
34983513
v1UsersGitBotsTasksList: (
34993514
query?: {
3500-
/** 指定 Git Bot ID,不传则查全部 */
3515+
/** ID */
35013516
id?: string;
3502-
/** 下一页标识 */
3503-
next_token?: string;
3504-
/** 分页 */
3505-
page?: number;
3506-
/** 每页多少条记录 */
3507-
size?: number;
35083517
},
35093518
params: RequestParams = {},
35103519
) =>
@@ -5078,13 +5087,7 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
50785087
cursor?: string;
50795088
/** 页数 */
50805089
limit?: number;
5081-
/** 下一页标识 */
5082-
next_token?: string;
5083-
/** 分页 */
5084-
page?: number;
50855090
project_id?: string;
5086-
/** 每页多少条记录 */
5087-
size?: number;
50885091
},
50895092
params: RequestParams = {},
50905093
) =>

frontend/src/components/console/project/edit-project-env.tsx

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import { Button } from "@/components/ui/button"
22
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
33
import { Input } from "@/components/ui/input"
44
import type { DomainProject } from "@/api/Api"
5+
import { apiRequest } from "@/utils/requestUtils"
56
import { useEffect, useState } from "react"
67
import { toast } from "sonner"
7-
import { IconPlus, IconTrash } from "@tabler/icons-react"
8+
import { IconLoader, IconPlus, IconTrash } from "@tabler/icons-react"
89

910
export type EnvVar = { key: string; value: string }
1011

@@ -22,11 +23,13 @@ export default function EditProjectEnvDialog({
2223
onSuccess,
2324
}: EditProjectEnvDialogProps) {
2425
const [envVars, setEnvVars] = useState<EnvVar[]>([])
26+
const [loading, setLoading] = useState(false)
2527

2628
useEffect(() => {
2729
if (open && project) {
28-
// TODO: 从 API 获取项目环境变量,目前使用空列表
29-
setEnvVars([])
30+
const dict = project.env_variables ?? {}
31+
const vars: EnvVar[] = Object.entries(dict).map(([key, value]) => ({ key, value: String(value ?? "") }))
32+
setEnvVars(vars.length > 0 ? vars : [])
3033
} else if (!open) {
3134
setEnvVars([])
3235
}
@@ -46,19 +49,33 @@ export default function EditProjectEnvDialog({
4649
)
4750
}
4851

49-
const handleSave = () => {
52+
const handleSave = async () => {
5053
const validVars = envVars.filter((row) => row.key.trim() !== "")
5154
const hasEmptyKey = envVars.some((row) => row.key.trim() === "" && row.value.trim() !== "")
5255
if (hasEmptyKey) {
5356
toast.error("请填写完整的键值对,或删除空行")
5457
return
5558
}
5659

57-
// TODO: 调用 API 保存环境变量
58-
console.log("保存环境变量:", validVars)
59-
toast.success("环境变量已保存(API 待实现)")
60-
onOpenChange(false)
61-
onSuccess?.()
60+
if (!project?.id) return
61+
62+
setLoading(true)
63+
const envVariables = Object.fromEntries(validVars.map((v) => [v.key.trim(), v.value]))
64+
await apiRequest(
65+
"v1UsersProjectsUpdate",
66+
{ env_variables: envVariables },
67+
[project.id],
68+
(resp) => {
69+
if (resp.code === 0) {
70+
toast.success("环境变量已保存")
71+
onOpenChange(false)
72+
onSuccess?.()
73+
} else {
74+
toast.error(resp.message || "保存环境变量失败")
75+
}
76+
}
77+
)
78+
setLoading(false)
6279
}
6380

6481
const handleCancel = () => {
@@ -107,10 +124,13 @@ export default function EditProjectEnvDialog({
107124
</Button>
108125
</div>
109126
<DialogFooter>
110-
<Button variant="outline" onClick={handleCancel}>
127+
<Button variant="outline" onClick={handleCancel} disabled={loading}>
111128
取消
112129
</Button>
113-
<Button onClick={handleSave}>保存</Button>
130+
<Button onClick={handleSave} disabled={loading}>
131+
{loading && <IconLoader className="size-4 animate-spin" />}
132+
保存
133+
</Button>
114134
</DialogFooter>
115135
</DialogContent>
116136
</Dialog>

frontend/src/components/console/project/edit-project-image.tsx

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
44
import type { DomainImage, DomainProject } from "@/api/Api"
55
import Icon from "@/components/common/Icon"
66
import { useCommonData } from "@/components/console/data-provider"
7+
import { apiRequest } from "@/utils/requestUtils"
78
import { getImageShortName, getOSFromImageName } from "@/utils/common"
89
import { useEffect, useState } from "react"
910
import { toast } from "sonner"
11+
import { IconLoader } from "@tabler/icons-react"
1012

1113
interface EditProjectImageDialogProps {
1214
open: boolean
@@ -23,22 +25,36 @@ export default function EditProjectImageDialog({
2325
}: EditProjectImageDialogProps) {
2426
const { images, loadingImages } = useCommonData()
2527
const [selectedImageId, setSelectedImageId] = useState<string>("")
28+
const [loading, setLoading] = useState(false)
2629

2730
useEffect(() => {
2831
if (open && project) {
29-
// TODO: 从 API 获取项目绑定的开发镜像,目前使用空
30-
setSelectedImageId("")
32+
const imageId = project.image_id ?? ""
33+
setSelectedImageId(imageId)
3134
} else if (!open) {
3235
setSelectedImageId("")
3336
}
3437
}, [open, project])
3538

36-
const handleSave = () => {
37-
// TODO: 调用 API 保存项目开发镜像
38-
console.log("保存开发镜像:", selectedImageId)
39-
toast.success("开发镜像已保存(API 待实现)")
40-
onOpenChange(false)
41-
onSuccess?.()
39+
const handleSave = async () => {
40+
if (!project?.id) return
41+
42+
setLoading(true)
43+
await apiRequest(
44+
"v1UsersProjectsUpdate",
45+
{ image_id: selectedImageId },
46+
[project.id],
47+
(resp) => {
48+
if (resp.code === 0) {
49+
toast.success("开发镜像已保存")
50+
onOpenChange(false)
51+
onSuccess?.()
52+
} else {
53+
toast.error(resp.message || "保存开发镜像失败")
54+
}
55+
}
56+
)
57+
setLoading(false)
4258
}
4359

4460
const handleCancel = () => {
@@ -78,10 +94,13 @@ export default function EditProjectImageDialog({
7894
</div>
7995
</div>
8096
<DialogFooter>
81-
<Button variant="outline" onClick={handleCancel}>
97+
<Button variant="outline" onClick={handleCancel} disabled={loading}>
8298
取消
8399
</Button>
84-
<Button onClick={handleSave}>保存</Button>
100+
<Button onClick={handleSave} disabled={loading}>
101+
{loading && <IconLoader className="size-4 animate-spin" />}
102+
保存
103+
</Button>
85104
</DialogFooter>
86105
</DialogContent>
87106
</Dialog>

0 commit comments

Comments
 (0)