1
This commit is contained in:
parent
3b9a65bcc8
commit
a8c1d56e05
@ -2,11 +2,15 @@ import React, {useEffect, useState} from 'react';
|
|||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogFooter,
|
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import {Button} from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
@ -22,9 +26,10 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import {useForm} from "react-hook-form";
|
import {PlusCircle, X} from 'lucide-react';
|
||||||
|
import {useForm, useFieldArray} from "react-hook-form";
|
||||||
import {getApplicationList} from '../../../Application/List/service';
|
import {getApplicationList} from '../../../Application/List/service';
|
||||||
import {getExternalSystemList} from '../service';
|
import {getExternalSystemList, getJenkinsViewList, getJenkinsJobList} from '../service';
|
||||||
import type {ExternalSystem} from '@/pages/Deploy/External/types';
|
import type {ExternalSystem} from '@/pages/Deploy/External/types';
|
||||||
|
|
||||||
interface Application {
|
interface Application {
|
||||||
@ -32,6 +37,29 @@ interface Application {
|
|||||||
appName: string;
|
appName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface JenkinsView {
|
||||||
|
id: number;
|
||||||
|
viewName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JenkinsJob {
|
||||||
|
id: number;
|
||||||
|
jobName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EnvVariable {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormValues {
|
||||||
|
applicationId?: number;
|
||||||
|
externalSystemId?: number;
|
||||||
|
viewId?: number;
|
||||||
|
jobId?: number;
|
||||||
|
envs: EnvVariable[];
|
||||||
|
}
|
||||||
|
|
||||||
interface DeploymentConfigModalProps {
|
interface DeploymentConfigModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
@ -41,13 +69,24 @@ interface DeploymentConfigModalProps {
|
|||||||
const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({open, onCancel, onSuccess}) => {
|
const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({open, onCancel, onSuccess}) => {
|
||||||
const [applications, setApplications] = useState<Application[]>([]);
|
const [applications, setApplications] = useState<Application[]>([]);
|
||||||
const [externalSystems, setExternalSystems] = useState<ExternalSystem[]>([]);
|
const [externalSystems, setExternalSystems] = useState<ExternalSystem[]>([]);
|
||||||
const form = useForm({
|
const [jenkinsViews, setJenkinsViews] = useState<JenkinsView[]>([]);
|
||||||
|
const [jenkinsJobs, setJenkinsJobs] = useState<JenkinsJob[]>([]);
|
||||||
|
|
||||||
|
const form = useForm<FormValues>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
applicationId: undefined,
|
applicationId: undefined,
|
||||||
externalSystemId: undefined,
|
externalSystemId: undefined,
|
||||||
|
viewId: undefined,
|
||||||
|
jobId: undefined,
|
||||||
|
envs: [{key: '', value: ''}],
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const {fields, append, remove} = useFieldArray({
|
||||||
|
control: form.control,
|
||||||
|
name: "envs"
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
// 获取应用列表
|
// 获取应用列表
|
||||||
@ -61,19 +100,51 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({open, onCa
|
|||||||
}
|
}
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
|
// 当选择外部系统时获取 View 列表
|
||||||
|
const handleExternalSystemChange = async (externalSystemId: number) => {
|
||||||
|
form.setValue('externalSystemId', externalSystemId);
|
||||||
|
form.setValue('viewId', undefined);
|
||||||
|
form.setValue('jobId', undefined);
|
||||||
|
setJenkinsJobs([]);
|
||||||
|
|
||||||
|
if (externalSystemId) {
|
||||||
|
const views = await getJenkinsViewList(externalSystemId);
|
||||||
|
setJenkinsViews(views);
|
||||||
|
} else {
|
||||||
|
setJenkinsViews([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 当选择 View 时获取 Job 列表
|
||||||
|
const handleViewChange = async (viewId: number) => {
|
||||||
|
form.setValue('viewId', viewId);
|
||||||
|
form.setValue('jobId', undefined);
|
||||||
|
|
||||||
|
const externalSystemId = form.getValues('externalSystemId');
|
||||||
|
if (externalSystemId && viewId) {
|
||||||
|
const jobs = await getJenkinsJobList(externalSystemId, viewId);
|
||||||
|
setJenkinsJobs(jobs);
|
||||||
|
} else {
|
||||||
|
setJenkinsJobs([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = form.handleSubmit((values) => {
|
const handleSubmit = form.handleSubmit((values) => {
|
||||||
|
// 过滤掉空的环境变量
|
||||||
|
values.envs = values.envs.filter(env => env.key || env.value);
|
||||||
console.log('表单提交的值:', values);
|
console.log('表单提交的值:', values);
|
||||||
onSuccess?.();
|
onSuccess?.();
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={(open) => !open && onCancel()}>
|
<Dialog open={open} onOpenChange={(open) => !open && onCancel()}>
|
||||||
<DialogContent className="sm:max-w-[600px]">
|
<DialogContent className="sm:max-w-[600px] max-h-[80vh] overflow-hidden flex flex-col">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>部署配置</DialogTitle>
|
<DialogTitle>部署配置</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={handleSubmit} className="space-y-4">
|
<ScrollArea className="flex-1">
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4 pr-6">
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@ -109,7 +180,7 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({open, onCa
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>三方系统</FormLabel>
|
<FormLabel>三方系统</FormLabel>
|
||||||
<Select
|
<Select
|
||||||
onValueChange={(value) => field.onChange(Number(value))}
|
onValueChange={(value) => handleExternalSystemChange(Number(value))}
|
||||||
value={field.value?.toString()}
|
value={field.value?.toString()}
|
||||||
>
|
>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
@ -130,9 +201,129 @@ const DeploymentConfigModal: React.FC<DeploymentConfigModalProps> = ({open, onCa
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Separator className="my-4" />
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="viewId"
|
||||||
|
render={({field}) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jenkins视图选择</FormLabel>
|
||||||
|
<Select
|
||||||
|
disabled={!form.getValues('externalSystemId')}
|
||||||
|
onValueChange={(value) => handleViewChange(Number(value))}
|
||||||
|
value={field.value?.toString()}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="请选择 View" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{jenkinsViews.map((view) => (
|
||||||
|
<SelectItem key={view.id} value={String(view.id)}>
|
||||||
|
{view.viewName}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="jobId"
|
||||||
|
render={({field}) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jenkins任务选择</FormLabel>
|
||||||
|
<Select
|
||||||
|
disabled={!form.getValues('viewId')}
|
||||||
|
onValueChange={(value) => field.onChange(Number(value))}
|
||||||
|
value={field.value?.toString()}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="请选择 Job" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{jenkinsJobs.map((job) => (
|
||||||
|
<SelectItem key={job.id} value={String(job.id)}>
|
||||||
|
{job.jobName}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Separator className="my-4" />
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between bg-background z-10 py-2">
|
||||||
|
<FormLabel>环境变量</FormLabel>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => append({key: '', value: ''})}
|
||||||
|
>
|
||||||
|
<PlusCircle className="h-4 w-4 mr-2" />
|
||||||
|
添加变量
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<ScrollArea className="h-[200px]">
|
||||||
|
<div className="space-y-4 pr-2">
|
||||||
|
{fields.map((field, index) => (
|
||||||
|
<div key={field.id} className="flex gap-4 items-start">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name={`envs.${index}.key`}
|
||||||
|
render={({field}) => (
|
||||||
|
<FormItem className="flex-1">
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder="变量名" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name={`envs.${index}.value`}
|
||||||
|
render={({field}) => (
|
||||||
|
<FormItem className="flex-1">
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder="变量值" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => remove(index)}
|
||||||
|
className="mt-2"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</ScrollArea>
|
||||||
</Form>
|
</Form>
|
||||||
<DialogFooter>
|
<DialogFooter className="flex-shrink-0">
|
||||||
<Button variant="outline" onClick={onCancel}>
|
<Button variant="outline" onClick={onCancel}>
|
||||||
取消
|
取消
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -3,6 +3,16 @@ import type {DeploymentConfig, CreateDeploymentConfigRequest, UpdateDeploymentCo
|
|||||||
import type {Page} from '@/types/base';
|
import type {Page} from '@/types/base';
|
||||||
import type {ExternalSystem} from '@/pages/Deploy/External/types';
|
import type {ExternalSystem} from '@/pages/Deploy/External/types';
|
||||||
|
|
||||||
|
interface JenkinsView {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JenkinsJob {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
const BASE_URL = '/api/v1/deploy-app-config';
|
const BASE_URL = '/api/v1/deploy-app-config';
|
||||||
|
|
||||||
// 获取部署配置分页列表
|
// 获取部署配置分页列表
|
||||||
@ -36,3 +46,11 @@ export const getDeployConfigTemplates = () =>
|
|||||||
// 获取外部系统列表
|
// 获取外部系统列表
|
||||||
export const getExternalSystemList = (type: string) =>
|
export const getExternalSystemList = (type: string) =>
|
||||||
request.get<ExternalSystem[]>('/api/v1/external-system/list', {params: {type}});
|
request.get<ExternalSystem[]>('/api/v1/external-system/list', {params: {type}});
|
||||||
|
|
||||||
|
// 获取 Jenkins View 列表
|
||||||
|
export const getJenkinsViewList = (externalSystemId: number) =>
|
||||||
|
request.get<JenkinsView[]>('/api/v1/jenkins-view/list', {params: {externalSystemId}});
|
||||||
|
|
||||||
|
// 获取 Jenkins Job 列表
|
||||||
|
export const getJenkinsJobList = (externalSystemId: number, viewId: number) =>
|
||||||
|
request.get<JenkinsJob[]>('/api/v1/jenkins-job/list', {params: {externalSystemId, viewId}});
|
||||||
Loading…
Reference in New Issue
Block a user