Files
smart-cropx-ui/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionFormDialog.tsx
2025-11-10 09:19:56 +08:00

329 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { Droplets, Power, PowerOff, Settings, Thermometer, Zap } from "lucide-react";
import type { DecisionFormState, DecisionLevel, ExecutionMode } from "./types";
interface DecisionFormDialogProps {
mode: 'create' | 'edit';
open: boolean;
onOpenChange: (open: boolean) => void;
formState: DecisionFormState;
onFormChange: <K extends keyof DecisionFormState>(key: K, value: DecisionFormState[K]) => void;
onSubmit: () => void;
}
const triggerDeviceOptions = [
{ value: '土壤传感器-01', label: '土壤传感器-01', icon: Droplets },
{ value: '土壤传感器-02', label: '土壤传感器-02', icon: Droplets },
{ value: '土壤传感器-03', label: '土壤传感器-03', icon: Droplets },
{ value: '温度传感器-01', label: '温度传感器-01', icon: Thermometer },
{ value: '温度传感器-02', label: '温度传感器-02', icon: Thermometer },
{ value: '湿度传感器-01', label: '湿度传感器-01' },
{ value: '光照传感器-01', label: '光照传感器-01' },
{ value: 'CO2传感器-01', label: 'CO2传感器-01' },
];
const triggerParameterOptions = [
{ value: '土壤湿度', label: '土壤湿度 (%)' },
{ value: '土壤温度', label: '土壤温度 (℃)' },
{ value: '空气温度', label: '空气温度 (℃)' },
{ value: '空气湿度', label: '空气湿度 (%)' },
{ value: '光照强度', label: '光照强度 (lux)' },
{ value: 'CO2浓度', label: 'CO₂ 浓度 (ppm)' },
{ value: 'EC值', label: 'EC 值 (mS/cm)' },
{ value: 'PH值', label: 'PH 值' },
];
const compareOperatorOptions = [
{ value: '>', label: '大于' },
{ value: '<', label: '小于' },
{ value: '>=', label: '大于等于' },
{ value: '<=', label: '小于等于' },
{ value: '==', label: '等于' },
];
const targetDeviceOptions = [
'水肥机-01',
'水肥机-02',
'灌溉阀门-A1',
'灌溉阀门-B2',
'排风扇-01',
'排风扇-02',
'喷雾器-01',
'喷雾器-02',
'补光灯-01',
'加热器-01',
];
export function DecisionFormDialog({ mode, open, onOpenChange, formState, onFormChange, onSubmit }: DecisionFormDialogProps) {
const dialogTitle = mode === 'create' ? '新建决策' : '编辑决策';
const dialogDescription =
mode === 'create'
? '创建基于设备参数的业务融合决策。'
: '更新当前决策的触发条件、执行动作与详细内容。';
const submitLabel = mode === 'create' ? '保存决策' : '保存修改';
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>{dialogTitle}</DialogTitle>
<DialogDescription>{dialogDescription}</DialogDescription>
</DialogHeader>
<div className="space-y-6">
<Card className="p-4">
<h4 className="mb-4 text-sm font-medium"></h4>
<div className="space-y-4">
<div>
<Label> *</Label>
<Input
placeholder="例如3号大棚灌溉决策"
value={formState.name}
onChange={(event) => onFormChange('name', event.target.value)}
/>
</div>
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<div>
<Label></Label>
<Select
value={formState.level}
onValueChange={(value) => onFormChange('level', value as DecisionLevel)}
>
<SelectTrigger>
<SelectValue placeholder="选择决策级别" />
</SelectTrigger>
<SelectContent>
<SelectItem value="critical"></SelectItem>
<SelectItem value="important"></SelectItem>
<SelectItem value="normal"></SelectItem>
<SelectItem value="suggestion"></SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label> (%)</Label>
<Input
type="number"
min={0}
max={100}
value={formState.confidence}
onChange={(event) => onFormChange('confidence', Number(event.target.value))}
/>
</div>
</div>
<div>
<Label> *</Label>
<Select
value={formState.executionMode}
onValueChange={(value) => onFormChange('executionMode', value as ExecutionMode)}
>
<SelectTrigger>
<SelectValue placeholder="选择执行模式" />
</SelectTrigger>
<SelectContent>
<SelectItem value="manual"></SelectItem>
<SelectItem value="auto"></SelectItem>
</SelectContent>
</Select>
<p className="text-xs text-muted-foreground mt-1">
{formState.executionMode === 'auto'
? '当触发条件满足时,系统将自动执行设备控制操作。'
: '需要人工点击执行按钮,验证触发条件后再执行。'}
</p>
</div>
</div>
</Card>
<Card className="p-4 bg-warning/10 border-warning/30">
<div className="flex items-center gap-2 mb-4">
<Settings className="w-5 h-5 text-warning" />
<h4 className="text-sm font-medium"></h4>
</div>
<p className="text-sm text-muted-foreground mb-4">
</p>
<div className="space-y-4">
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<div>
<Label> *</Label>
<Select value={formState.triggerDevice} onValueChange={(value) => onFormChange('triggerDevice', value)}>
<SelectTrigger>
<SelectValue placeholder="请选择设备" />
</SelectTrigger>
<SelectContent>
{triggerDeviceOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
<span className="flex items-center gap-2">
{option.icon ? <option.icon className="w-4 h-4" /> : null}
{option.label}
</span>
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div>
<Label> *</Label>
<Select
value={formState.triggerParameter}
onValueChange={(value) => onFormChange('triggerParameter', value)}
>
<SelectTrigger>
<SelectValue placeholder="请选择参数" />
</SelectTrigger>
<SelectContent>
{triggerParameterOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
<div>
<Label> *</Label>
<Select
value={formState.triggerOperator}
onValueChange={(value) => onFormChange('triggerOperator', value)}
>
<SelectTrigger>
<SelectValue placeholder="请选择比较符号" />
</SelectTrigger>
<SelectContent>
{compareOperatorOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.value} {option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="md:col-span-2">
<Label> *</Label>
<Input
placeholder="请输入阈值"
value={formState.triggerValue}
onChange={(event) => onFormChange('triggerValue', event.target.value)}
/>
</div>
</div>
</div>
</Card>
<Card className="p-4 bg-success/10 border-success/30">
<div className="flex items-center gap-2 mb-4">
<Zap className="w-5 h-5 text-success" />
<h4 className="text-sm font-medium"></h4>
</div>
<p className="text-sm text-muted-foreground mb-4"></p>
<div className="space-y-4">
<div>
<Label> *</Label>
<Select value={formState.targetDevice} onValueChange={(value) => onFormChange('targetDevice', value)}>
<SelectTrigger>
<SelectValue placeholder="请选择目标设备" />
</SelectTrigger>
<SelectContent>
{targetDeviceOptions.map((device) => (
<SelectItem key={device} value={device}>
{device}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<div>
<Label> *</Label>
<Select
value={formState.targetAction}
onValueChange={(value) => onFormChange('targetAction', value === 'open' ? 'open' : 'close')}
>
<SelectTrigger>
<SelectValue placeholder="请选择动作" />
</SelectTrigger>
<SelectContent>
<SelectItem value="open">
<span className="flex items-center gap-2">
<Power className="w-4 h-4 text-success" />
</span>
</SelectItem>
<SelectItem value="close">
<span className="flex items-center gap-2">
<PowerOff className="w-4 h-4 text-destructive" />
</span>
</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label>*</Label>
<Input
type="number"
min={1}
value={formState.duration}
onChange={(event) => onFormChange('duration', Number(event.target.value))}
/>
</div>
</div>
</div>
</Card>
<Card className="p-4">
<h4 className="mb-4 text-sm font-medium"></h4>
<div className="space-y-4">
<div>
<Label> *</Label>
<Textarea
rows={3}
value={formState.recommendation}
onChange={(event) => onFormChange('recommendation', event.target.value)}
/>
</div>
<div>
<Label></Label>
<Textarea
rows={5}
value={formState.explanation}
onChange={(event) => onFormChange('explanation', event.target.value)}
/>
</div>
<div>
<Label> *</Label>
<Textarea
rows={6}
value={formState.actionItems}
onChange={(event) => onFormChange('actionItems', event.target.value)}
/>
</div>
</div>
</Card>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => onOpenChange(false)}>
</Button>
<Button className="bg-success hover:bg-success/90" onClick={onSubmit}>
{submitLabel}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}