1.18升级

This commit is contained in:
dengqichen 2025-12-11 09:38:56 +08:00
parent 2badfa63e3
commit 19ea644e6e
3 changed files with 132 additions and 50 deletions

View File

@ -382,6 +382,8 @@ export const AlertRuleFormDialog: React.FC<AlertRuleFormDialogProps> = ({
render={({ field }) => { render={({ field }) => {
const currentAlertType = form.watch('alertType'); const currentAlertType = form.watch('alertType');
const isServerStatus = currentAlertType === AlertType.SERVER_STATUS; const isServerStatus = currentAlertType === AlertType.SERVER_STATUS;
const isNetworkType = currentAlertType === AlertType.NETWORK;
const maxValue = isNetworkType ? 10000 : 100;
const [localValue, setLocalValue] = React.useState<string>( const [localValue, setLocalValue] = React.useState<string>(
field.value?.toString() ?? '' field.value?.toString() ?? ''
); );
@ -401,7 +403,7 @@ export const AlertRuleFormDialog: React.FC<AlertRuleFormDialogProps> = ({
<Input <Input
type="number" type="number"
min="0" min="0"
max="100" max={maxValue}
step={isServerStatus ? "1" : "0.1"} step={isServerStatus ? "1" : "0.1"}
value={localValue} value={localValue}
onChange={(e) => { onChange={(e) => {
@ -440,6 +442,8 @@ export const AlertRuleFormDialog: React.FC<AlertRuleFormDialogProps> = ({
render={({ field }) => { render={({ field }) => {
const currentAlertType = form.watch('alertType'); const currentAlertType = form.watch('alertType');
const isServerStatus = currentAlertType === AlertType.SERVER_STATUS; const isServerStatus = currentAlertType === AlertType.SERVER_STATUS;
const isNetworkType = currentAlertType === AlertType.NETWORK;
const maxValue = isNetworkType ? 10000 : 100;
const [localValue, setLocalValue] = React.useState<string>( const [localValue, setLocalValue] = React.useState<string>(
field.value?.toString() ?? '' field.value?.toString() ?? ''
); );
@ -459,7 +463,7 @@ export const AlertRuleFormDialog: React.FC<AlertRuleFormDialogProps> = ({
<Input <Input
type="number" type="number"
min="0" min="0"
max="100" max={maxValue}
step={isServerStatus ? "1" : "0.1"} step={isServerStatus ? "1" : "0.1"}
value={localValue} value={localValue}
onChange={(e) => { onChange={(e) => {

View File

@ -82,17 +82,51 @@ export const alertRuleFormSchema = z.object({
alertType: z.nativeEnum(AlertType, { alertType: z.nativeEnum(AlertType, {
errorMap: () => ({ message: '请选择告警类型' }) errorMap: () => ({ message: '请选择告警类型' })
}), }),
warningThreshold: z.number() warningThreshold: z.number().min(0, '警告阈值不能小于0'),
.min(0, '警告阈值不能小于0') criticalThreshold: z.number().min(0, '严重阈值不能小于0'),
.max(100, '警告阈值不能大于100'),
criticalThreshold: z.number()
.min(0, '严重阈值不能小于0')
.max(100, '严重阈值不能大于100'),
durationMinutes: z.number() durationMinutes: z.number()
.min(1, '持续时长至少为1分钟'), .min(1, '持续时长至少为1分钟'),
enabled: z.boolean().default(true), enabled: z.boolean().default(true),
description: z.string().max(500, '描述不能超过500个字符').optional(), description: z.string().max(500, '描述不能超过500个字符').optional(),
}).superRefine((data, ctx) => { }).superRefine((data, ctx) => {
// 根据告警类型验证阈值范围
const isPercentageType = [AlertType.CPU, AlertType.MEMORY, AlertType.DISK].includes(data.alertType);
const isNetworkType = data.alertType === AlertType.NETWORK;
if (isPercentageType) {
// CPU/内存/磁盘使用率0-100
if (data.warningThreshold > 100) {
ctx.addIssue({
code: 'custom',
message: '警告阈值不能大于100',
path: ['warningThreshold'],
});
}
if (data.criticalThreshold > 100) {
ctx.addIssue({
code: 'custom',
message: '严重阈值不能大于100',
path: ['criticalThreshold'],
});
}
} else if (isNetworkType) {
// 网络流量0-10000 MB/s
if (data.warningThreshold > 10000) {
ctx.addIssue({
code: 'custom',
message: '警告阈值不能大于10000',
path: ['warningThreshold'],
});
}
if (data.criticalThreshold > 10000) {
ctx.addIssue({
code: 'custom',
message: '严重阈值不能大于10000',
path: ['criticalThreshold'],
});
}
}
// 严重阈值必须大于警告阈值 // 严重阈值必须大于警告阈值
if (data.criticalThreshold <= data.warningThreshold) { if (data.criticalThreshold <= data.warningThreshold) {
ctx.addIssue({ ctx.addIssue({

View File

@ -286,7 +286,16 @@ export const ReleaseEditDialog: React.FC<ReleaseEditDialogProps> = ({
<FormField <FormField
control={form.control} control={form.control}
name="delayMinutes" name="delayMinutes"
render={({ field }) => ( render={({ field }) => {
const [localValue, setLocalValue] = React.useState<string>(
field.value?.toString() ?? ''
);
React.useEffect(() => {
setLocalValue(field.value?.toString() ?? '');
}, [field.value]);
return (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
() <span className="text-destructive">*</span> () <span className="text-destructive">*</span>
@ -296,9 +305,21 @@ export const ReleaseEditDialog: React.FC<ReleaseEditDialogProps> = ({
type="number" type="number"
min="0" min="0"
placeholder="创建后多久开始维护" placeholder="创建后多久开始维护"
{...field} value={localValue}
value={field.value ?? 0} onChange={(e) => {
onChange={(e) => field.onChange(e.target.value ? parseInt(e.target.value) : 0)} const value = e.target.value;
setLocalValue(value);
if (value !== '') {
field.onChange(parseInt(value));
}
}}
onBlur={() => {
if (localValue === '') {
field.onChange(undefined);
}
field.onBlur();
}}
name={field.name}
/> />
</FormControl> </FormControl>
<p className="text-xs text-muted-foreground mt-1"> <p className="text-xs text-muted-foreground mt-1">
@ -306,14 +327,24 @@ export const ReleaseEditDialog: React.FC<ReleaseEditDialogProps> = ({
</p> </p>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} );
}}
/> />
{/* 预计维护时长 */} {/* 预计维护时长 */}
<FormField <FormField
control={form.control} control={form.control}
name="estimatedDuration" name="estimatedDuration"
render={({ field }) => ( render={({ field }) => {
const [localValue, setLocalValue] = React.useState<string>(
field.value?.toString() ?? ''
);
React.useEffect(() => {
setLocalValue(field.value?.toString() ?? '');
}, [field.value]);
return (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
() <span className="text-destructive">*</span> () <span className="text-destructive">*</span>
@ -323,9 +354,21 @@ export const ReleaseEditDialog: React.FC<ReleaseEditDialogProps> = ({
type="number" type="number"
min="1" min="1"
placeholder="预计维护时长" placeholder="预计维护时长"
{...field} value={localValue}
value={field.value ?? 30} onChange={(e) => {
onChange={(e) => field.onChange(e.target.value ? parseInt(e.target.value) : 30)} const value = e.target.value;
setLocalValue(value);
if (value !== '') {
field.onChange(parseInt(value));
}
}}
onBlur={() => {
if (localValue === '') {
field.onChange(undefined);
}
field.onBlur();
}}
name={field.name}
/> />
</FormControl> </FormControl>
<p className="text-xs text-muted-foreground mt-1"> <p className="text-xs text-muted-foreground mt-1">
@ -333,7 +376,8 @@ export const ReleaseEditDialog: React.FC<ReleaseEditDialogProps> = ({
</p> </p>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} );
}}
/> />
{/* 是否自动停止服务 */} {/* 是否自动停止服务 */}