重构消息通知弹窗

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, 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>

View File

@ -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');

View File

@ -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;
}; };
} }