重构消息通知弹窗
This commit is contained in:
parent
a0ac1c5205
commit
828a0da526
@ -34,6 +34,7 @@ import {
|
|||||||
getTeamEnvironmentConfig,
|
getTeamEnvironmentConfig,
|
||||||
updateTeamEnvironmentConfig,
|
updateTeamEnvironmentConfig,
|
||||||
getNotificationChannels,
|
getNotificationChannels,
|
||||||
|
getNotificationTemplates,
|
||||||
} from '../service';
|
} from '../service';
|
||||||
|
|
||||||
// 表单验证 Schema
|
// 表单验证 Schema
|
||||||
@ -44,8 +45,11 @@ const formSchema = z
|
|||||||
id: z.number().optional(),
|
id: z.number().optional(),
|
||||||
notificationChannelId: z.number().nullish(),
|
notificationChannelId: z.number().nullish(),
|
||||||
deployNotificationEnabled: z.boolean().default(false),
|
deployNotificationEnabled: z.boolean().default(false),
|
||||||
|
deployNotificationTemplateId: z.number().nullish(),
|
||||||
buildNotificationEnabled: z.boolean().default(false),
|
buildNotificationEnabled: z.boolean().default(false),
|
||||||
|
buildNotificationTemplateId: z.number().nullish(),
|
||||||
buildFailureFileEnabled: z.boolean().default(false),
|
buildFailureFileEnabled: z.boolean().default(false),
|
||||||
|
buildFailureNotificationTemplateId: z.number().nullish(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
})
|
})
|
||||||
@ -76,6 +80,12 @@ interface NotificationChannel {
|
|||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface NotificationTemplate {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
type?: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface NotificationConfigDialogProps {
|
interface NotificationConfigDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
@ -97,6 +107,10 @@ export const NotificationConfigDialog: React.FC<
|
|||||||
NotificationChannel[]
|
NotificationChannel[]
|
||||||
>([]);
|
>([]);
|
||||||
const [loadingChannels, setLoadingChannels] = useState(false);
|
const [loadingChannels, setLoadingChannels] = useState(false);
|
||||||
|
const [notificationTemplates, setNotificationTemplates] = useState<
|
||||||
|
NotificationTemplate[]
|
||||||
|
>([]);
|
||||||
|
const [loadingTemplates, setLoadingTemplates] = useState(false);
|
||||||
|
|
||||||
const form = useForm<FormData>({
|
const form = useForm<FormData>({
|
||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
@ -104,8 +118,11 @@ export const NotificationConfigDialog: React.FC<
|
|||||||
notificationConfig: {
|
notificationConfig: {
|
||||||
notificationChannelId: undefined,
|
notificationChannelId: undefined,
|
||||||
deployNotificationEnabled: false,
|
deployNotificationEnabled: false,
|
||||||
|
deployNotificationTemplateId: undefined,
|
||||||
buildNotificationEnabled: false,
|
buildNotificationEnabled: false,
|
||||||
buildFailureFileEnabled: false
|
buildNotificationTemplateId: undefined,
|
||||||
|
buildFailureFileEnabled: false,
|
||||||
|
buildFailureNotificationTemplateId: undefined,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -127,6 +144,23 @@ export const NotificationConfigDialog: React.FC<
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 加载通知模板列表
|
||||||
|
const loadNotificationTemplates = async () => {
|
||||||
|
setLoadingTemplates(true);
|
||||||
|
try {
|
||||||
|
const templates = await getNotificationTemplates();
|
||||||
|
setNotificationTemplates(templates || []);
|
||||||
|
} catch (error: any) {
|
||||||
|
toast({
|
||||||
|
title: '加载失败',
|
||||||
|
description: error.message || '无法加载通知模板列表',
|
||||||
|
variant: 'destructive',
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setLoadingTemplates(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 加载环境配置
|
// 加载环境配置
|
||||||
const loadEnvironmentConfig = async () => {
|
const loadEnvironmentConfig = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@ -140,8 +174,11 @@ export const NotificationConfigDialog: React.FC<
|
|||||||
notificationConfig: config.notificationConfig || {
|
notificationConfig: config.notificationConfig || {
|
||||||
notificationChannelId: undefined,
|
notificationChannelId: undefined,
|
||||||
deployNotificationEnabled: false,
|
deployNotificationEnabled: false,
|
||||||
|
deployNotificationTemplateId: undefined,
|
||||||
buildNotificationEnabled: false,
|
buildNotificationEnabled: false,
|
||||||
|
buildNotificationTemplateId: undefined,
|
||||||
buildFailureFileEnabled: false,
|
buildFailureFileEnabled: false,
|
||||||
|
buildFailureNotificationTemplateId: undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -170,6 +207,7 @@ export const NotificationConfigDialog: React.FC<
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
loadNotificationChannels();
|
loadNotificationChannels();
|
||||||
|
loadNotificationTemplates();
|
||||||
loadEnvironmentConfig();
|
loadEnvironmentConfig();
|
||||||
}
|
}
|
||||||
}, [open, teamId, environmentId]);
|
}, [open, teamId, environmentId]);
|
||||||
@ -196,8 +234,11 @@ export const NotificationConfigDialog: React.FC<
|
|||||||
id: data.notificationConfig.id,
|
id: data.notificationConfig.id,
|
||||||
notificationChannelId: data.notificationConfig.notificationChannelId,
|
notificationChannelId: data.notificationConfig.notificationChannelId,
|
||||||
deployNotificationEnabled: data.notificationConfig.deployNotificationEnabled ?? false,
|
deployNotificationEnabled: data.notificationConfig.deployNotificationEnabled ?? false,
|
||||||
|
deployNotificationTemplateId: data.notificationConfig.deployNotificationTemplateId ?? undefined,
|
||||||
buildNotificationEnabled: data.notificationConfig.buildNotificationEnabled ?? false,
|
buildNotificationEnabled: data.notificationConfig.buildNotificationEnabled ?? false,
|
||||||
|
buildNotificationTemplateId: data.notificationConfig.buildNotificationTemplateId ?? undefined,
|
||||||
buildFailureFileEnabled: data.notificationConfig.buildFailureFileEnabled ?? false,
|
buildFailureFileEnabled: data.notificationConfig.buildFailureFileEnabled ?? false,
|
||||||
|
buildFailureNotificationTemplateId: data.notificationConfig.buildFailureNotificationTemplateId ?? undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +277,7 @@ export const NotificationConfigDialog: React.FC<
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
<DialogContent className="max-w-md">
|
<DialogContent className="max-w-3xl">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>通知配置</DialogTitle>
|
<DialogTitle>通知配置</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
@ -305,70 +346,220 @@ export const NotificationConfigDialog: React.FC<
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 部署通知 */}
|
{/* 部署通知 */}
|
||||||
<FormField
|
<div className="grid grid-cols-2 gap-4 rounded-lg border p-4">
|
||||||
control={form.control}
|
<FormField
|
||||||
name="notificationConfig.deployNotificationEnabled"
|
control={form.control}
|
||||||
render={({ field }) => (
|
name="notificationConfig.deployNotificationEnabled"
|
||||||
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
render={({ field }) => (
|
||||||
<div className="space-y-0.5">
|
<FormItem className="flex flex-row items-center justify-between space-y-0">
|
||||||
<FormLabel className="text-base">部署通知</FormLabel>
|
<div className="space-y-0.5 flex-1">
|
||||||
<div className="text-sm text-muted-foreground">
|
<FormLabel className="text-base">部署通知</FormLabel>
|
||||||
部署状态变更时发送通知
|
<div className="text-sm text-muted-foreground">
|
||||||
|
部署状态变更时发送通知
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<FormControl>
|
||||||
<FormControl>
|
<Switch
|
||||||
<Switch
|
checked={field.value}
|
||||||
checked={field.value}
|
onCheckedChange={field.onChange}
|
||||||
onCheckedChange={field.onChange}
|
/>
|
||||||
/>
|
</FormControl>
|
||||||
</FormControl>
|
</FormItem>
|
||||||
</FormItem>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="notificationConfig.deployNotificationTemplateId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex flex-col justify-center space-y-2">
|
||||||
|
<ClearableSelect
|
||||||
|
value={field.value?.toString()}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
field.onChange(value ? Number(value) : null)
|
||||||
|
}
|
||||||
|
disabled={loadingTemplates}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger
|
||||||
|
clearable
|
||||||
|
hasValue={!!field.value}
|
||||||
|
onClear={() => {
|
||||||
|
field.onChange(null);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={
|
||||||
|
loadingTemplates
|
||||||
|
? '加载中...'
|
||||||
|
: '请选择通知模板(可选)'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{notificationTemplates.map((template) => (
|
||||||
|
<SelectItem
|
||||||
|
key={template.id}
|
||||||
|
value={template.id.toString()}
|
||||||
|
>
|
||||||
|
{template.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</ClearableSelect>
|
||||||
|
<div className="text-sm text-muted-foreground">
|
||||||
|
部署通知模板
|
||||||
|
</div>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* 构建通知 */}
|
{/* 构建通知 */}
|
||||||
<FormField
|
<div className="grid grid-cols-2 gap-4 rounded-lg border p-4">
|
||||||
control={form.control}
|
<FormField
|
||||||
name="notificationConfig.buildNotificationEnabled"
|
control={form.control}
|
||||||
render={({ field }) => (
|
name="notificationConfig.buildNotificationEnabled"
|
||||||
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
render={({ field }) => (
|
||||||
<div className="space-y-0.5">
|
<FormItem className="flex flex-row items-center justify-between space-y-0">
|
||||||
<FormLabel className="text-base">构建通知</FormLabel>
|
<div className="space-y-0.5 flex-1">
|
||||||
<div className="text-sm text-muted-foreground">
|
<FormLabel className="text-base">构建通知</FormLabel>
|
||||||
构建状态变更时发送通知
|
<div className="text-sm text-muted-foreground">
|
||||||
|
构建状态变更时发送通知
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<FormControl>
|
||||||
<FormControl>
|
<Switch
|
||||||
<Switch
|
checked={field.value}
|
||||||
checked={field.value}
|
onCheckedChange={field.onChange}
|
||||||
onCheckedChange={field.onChange}
|
/>
|
||||||
/>
|
</FormControl>
|
||||||
</FormControl>
|
</FormItem>
|
||||||
</FormItem>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="notificationConfig.buildNotificationTemplateId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex flex-col justify-center space-y-2">
|
||||||
|
<ClearableSelect
|
||||||
|
value={field.value?.toString()}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
field.onChange(value ? Number(value) : null)
|
||||||
|
}
|
||||||
|
disabled={loadingTemplates}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger
|
||||||
|
clearable
|
||||||
|
hasValue={!!field.value}
|
||||||
|
onClear={() => {
|
||||||
|
field.onChange(null);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={
|
||||||
|
loadingTemplates
|
||||||
|
? '加载中...'
|
||||||
|
: '请选择通知模板(可选)'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{notificationTemplates.map((template) => (
|
||||||
|
<SelectItem
|
||||||
|
key={template.id}
|
||||||
|
value={template.id.toString()}
|
||||||
|
>
|
||||||
|
{template.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</ClearableSelect>
|
||||||
|
<div className="text-sm text-muted-foreground">
|
||||||
|
构建通知模板
|
||||||
|
</div>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* 失败日志 */}
|
{/* 失败日志 */}
|
||||||
<FormField
|
<div className="grid grid-cols-2 gap-4 rounded-lg border p-4">
|
||||||
control={form.control}
|
<FormField
|
||||||
name="notificationConfig.buildFailureFileEnabled"
|
control={form.control}
|
||||||
render={({ field }) => (
|
name="notificationConfig.buildFailureFileEnabled"
|
||||||
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
render={({ field }) => (
|
||||||
<div className="space-y-0.5">
|
<FormItem className="flex flex-row items-center justify-between space-y-0">
|
||||||
<FormLabel className="text-base">失败日志</FormLabel>
|
<div className="space-y-0.5 flex-1">
|
||||||
<div className="text-sm text-muted-foreground">
|
<FormLabel className="text-base">失败日志</FormLabel>
|
||||||
构建失败时是否发送日志
|
<div className="text-sm text-muted-foreground">
|
||||||
|
构建失败时是否发送日志
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<FormControl>
|
||||||
<FormControl>
|
<Switch
|
||||||
<Switch
|
checked={field.value}
|
||||||
checked={field.value}
|
onCheckedChange={field.onChange}
|
||||||
onCheckedChange={field.onChange}
|
/>
|
||||||
/>
|
</FormControl>
|
||||||
</FormControl>
|
</FormItem>
|
||||||
</FormItem>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="notificationConfig.buildFailureNotificationTemplateId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex flex-col justify-center space-y-2">
|
||||||
|
<ClearableSelect
|
||||||
|
value={field.value?.toString()}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
field.onChange(value ? Number(value) : null)
|
||||||
|
}
|
||||||
|
disabled={loadingTemplates}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger
|
||||||
|
clearable
|
||||||
|
hasValue={!!field.value}
|
||||||
|
onClear={() => {
|
||||||
|
field.onChange(null);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={
|
||||||
|
loadingTemplates
|
||||||
|
? '加载中...'
|
||||||
|
: '请选择通知模板(可选)'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{notificationTemplates.map((template) => (
|
||||||
|
<SelectItem
|
||||||
|
key={template.id}
|
||||||
|
value={template.id.toString()}
|
||||||
|
>
|
||||||
|
{template.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</ClearableSelect>
|
||||||
|
<div className="text-sm text-muted-foreground">
|
||||||
|
失败日志通知模板
|
||||||
|
</div>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</DialogBody>
|
</DialogBody>
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
|||||||
@ -174,3 +174,10 @@ export const updateTeamEnvironmentConfig = (
|
|||||||
export const deleteTeamEnvironmentConfig = (id: number) =>
|
export const deleteTeamEnvironmentConfig = (id: number) =>
|
||||||
request.delete(`/api/v1/team-environment-config/${id}`);
|
request.delete(`/api/v1/team-environment-config/${id}`);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取通知模板列表
|
||||||
|
*/
|
||||||
|
export const getNotificationTemplates = () =>
|
||||||
|
request.get<any[]>('/api/v1/notification-template/list');
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -54,8 +54,11 @@ export interface NotificationConfig {
|
|||||||
environmentId?: number;
|
environmentId?: number;
|
||||||
notificationChannelId?: number;
|
notificationChannelId?: number;
|
||||||
deployNotificationEnabled?: boolean;
|
deployNotificationEnabled?: boolean;
|
||||||
|
deployNotificationTemplateId?: number;
|
||||||
buildNotificationEnabled?: boolean;
|
buildNotificationEnabled?: boolean;
|
||||||
|
buildNotificationTemplateId?: number;
|
||||||
buildFailureFileEnabled?: boolean;
|
buildFailureFileEnabled?: boolean;
|
||||||
|
buildFailureNotificationTemplateId?: number;
|
||||||
notificationChannelName?: string; // 关联数据
|
notificationChannelName?: string; // 关联数据
|
||||||
channelType?: string; // 渠道类型:WEWORK, EMAIL, DINGTALK等
|
channelType?: string; // 渠道类型:WEWORK, EMAIL, DINGTALK等
|
||||||
updateTime?: string; // 更新时间
|
updateTime?: string; // 更新时间
|
||||||
@ -94,8 +97,11 @@ export interface TeamEnvironmentConfigRequest {
|
|||||||
id?: number;
|
id?: number;
|
||||||
notificationChannelId?: number;
|
notificationChannelId?: number;
|
||||||
deployNotificationEnabled?: boolean;
|
deployNotificationEnabled?: boolean;
|
||||||
|
deployNotificationTemplateId?: number;
|
||||||
buildNotificationEnabled?: boolean;
|
buildNotificationEnabled?: boolean;
|
||||||
|
buildNotificationTemplateId?: number;
|
||||||
buildFailureFileEnabled?: boolean;
|
buildFailureFileEnabled?: boolean;
|
||||||
|
buildFailureNotificationTemplateId?: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user