重构消息通知弹窗

This commit is contained in:
dengqichen 2025-11-13 14:00:02 +08:00
parent a0ac1c5205
commit 828a0da526
3 changed files with 263 additions and 59 deletions

View File

@ -34,6 +34,7 @@ import {
getTeamEnvironmentConfig,
updateTeamEnvironmentConfig,
getNotificationChannels,
getNotificationTemplates,
} from '../service';
// 表单验证 Schema
@ -44,8 +45,11 @@ const formSchema = z
id: z.number().optional(),
notificationChannelId: z.number().nullish(),
deployNotificationEnabled: z.boolean().default(false),
deployNotificationTemplateId: z.number().nullish(),
buildNotificationEnabled: z.boolean().default(false),
buildNotificationTemplateId: z.number().nullish(),
buildFailureFileEnabled: z.boolean().default(false),
buildFailureNotificationTemplateId: z.number().nullish(),
})
.optional(),
})
@ -76,6 +80,12 @@ interface NotificationChannel {
type: string;
}
interface NotificationTemplate {
id: number;
name: string;
type?: string;
}
interface NotificationConfigDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
@ -97,6 +107,10 @@ export const NotificationConfigDialog: React.FC<
NotificationChannel[]
>([]);
const [loadingChannels, setLoadingChannels] = useState(false);
const [notificationTemplates, setNotificationTemplates] = useState<
NotificationTemplate[]
>([]);
const [loadingTemplates, setLoadingTemplates] = useState(false);
const form = useForm<FormData>({
resolver: zodResolver(formSchema),
@ -104,8 +118,11 @@ export const NotificationConfigDialog: React.FC<
notificationConfig: {
notificationChannelId: undefined,
deployNotificationEnabled: false,
deployNotificationTemplateId: undefined,
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 () => {
setLoading(true);
@ -140,8 +174,11 @@ export const NotificationConfigDialog: React.FC<
notificationConfig: config.notificationConfig || {
notificationChannelId: undefined,
deployNotificationEnabled: false,
deployNotificationTemplateId: undefined,
buildNotificationEnabled: false,
buildNotificationTemplateId: undefined,
buildFailureFileEnabled: false,
buildFailureNotificationTemplateId: undefined,
},
});
}
@ -170,6 +207,7 @@ export const NotificationConfigDialog: React.FC<
useEffect(() => {
if (open) {
loadNotificationChannels();
loadNotificationTemplates();
loadEnvironmentConfig();
}
}, [open, teamId, environmentId]);
@ -196,8 +234,11 @@ export const NotificationConfigDialog: React.FC<
id: data.notificationConfig.id,
notificationChannelId: data.notificationConfig.notificationChannelId,
deployNotificationEnabled: data.notificationConfig.deployNotificationEnabled ?? false,
deployNotificationTemplateId: data.notificationConfig.deployNotificationTemplateId ?? undefined,
buildNotificationEnabled: data.notificationConfig.buildNotificationEnabled ?? false,
buildNotificationTemplateId: data.notificationConfig.buildNotificationTemplateId ?? undefined,
buildFailureFileEnabled: data.notificationConfig.buildFailureFileEnabled ?? false,
buildFailureNotificationTemplateId: data.notificationConfig.buildFailureNotificationTemplateId ?? undefined,
};
}
@ -236,7 +277,7 @@ export const NotificationConfigDialog: React.FC<
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-md">
<DialogContent className="max-w-3xl">
<DialogHeader>
<DialogTitle></DialogTitle>
<DialogDescription>
@ -305,70 +346,220 @@ export const NotificationConfigDialog: React.FC<
/>
{/* 部署通知 */}
<FormField
control={form.control}
name="notificationConfig.deployNotificationEnabled"
render={({ field }) => (
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<FormLabel className="text-base"></FormLabel>
<div className="text-sm text-muted-foreground">
<div className="grid grid-cols-2 gap-4 rounded-lg border p-4">
<FormField
control={form.control}
name="notificationConfig.deployNotificationEnabled"
render={({ field }) => (
<FormItem className="flex flex-row items-center justify-between space-y-0">
<div className="space-y-0.5 flex-1">
<FormLabel className="text-base"></FormLabel>
<div className="text-sm text-muted-foreground">
</div>
</div>
</div>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</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
control={form.control}
name="notificationConfig.buildNotificationEnabled"
render={({ field }) => (
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<FormLabel className="text-base"></FormLabel>
<div className="text-sm text-muted-foreground">
<div className="grid grid-cols-2 gap-4 rounded-lg border p-4">
<FormField
control={form.control}
name="notificationConfig.buildNotificationEnabled"
render={({ field }) => (
<FormItem className="flex flex-row items-center justify-between space-y-0">
<div className="space-y-0.5 flex-1">
<FormLabel className="text-base"></FormLabel>
<div className="text-sm text-muted-foreground">
</div>
</div>
</div>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</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
control={form.control}
name="notificationConfig.buildFailureFileEnabled"
render={({ field }) => (
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<FormLabel className="text-base"></FormLabel>
<div className="text-sm text-muted-foreground">
<div className="grid grid-cols-2 gap-4 rounded-lg border p-4">
<FormField
control={form.control}
name="notificationConfig.buildFailureFileEnabled"
render={({ field }) => (
<FormItem className="flex flex-row items-center justify-between space-y-0">
<div className="space-y-0.5 flex-1">
<FormLabel className="text-base"></FormLabel>
<div className="text-sm text-muted-foreground">
</div>
</div>
</div>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</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>
<DialogFooter>

View File

@ -174,3 +174,10 @@ export const updateTeamEnvironmentConfig = (
export const deleteTeamEnvironmentConfig = (id: number) =>
request.delete(`/api/v1/team-environment-config/${id}`);
/**
*
*/
export const getNotificationTemplates = () =>
request.get<any[]>('/api/v1/notification-template/list');

View File

@ -54,8 +54,11 @@ export interface NotificationConfig {
environmentId?: number;
notificationChannelId?: number;
deployNotificationEnabled?: boolean;
deployNotificationTemplateId?: number;
buildNotificationEnabled?: boolean;
buildNotificationTemplateId?: number;
buildFailureFileEnabled?: boolean;
buildFailureNotificationTemplateId?: number;
notificationChannelName?: string; // 关联数据
channelType?: string; // 渠道类型WEWORK, EMAIL, DINGTALK等
updateTime?: string; // 更新时间
@ -94,8 +97,11 @@ export interface TeamEnvironmentConfigRequest {
id?: number;
notificationChannelId?: number;
deployNotificationEnabled?: boolean;
deployNotificationTemplateId?: number;
buildNotificationEnabled?: boolean;
buildNotificationTemplateId?: number;
buildFailureFileEnabled?: boolean;
buildFailureNotificationTemplateId?: number;
};
}