From fdeb455e474142ff60bd3260c5408f8b2f03224a Mon Sep 17 00:00:00 2001 From: peng Date: Mon, 3 Nov 2025 10:31:39 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=9F=E4=BA=A7=E7=AE=A1=E7=90=86=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=20-=20=E4=B8=9A=E5=8A=A1=E8=9E=8D=E5=90=88=EF=BC=8C?= =?UTF-8?q?=E5=86=B3=E7=AD=96=E6=A8=A1=E6=8B=9F=EF=BC=8C=E5=86=B3=E7=AD=96?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai-crop-model/data-sense-center/page.tsx | 9 +- .../fusion/components/DecisionBadges.tsx | 93 ++ .../fusion/components/DecisionFormDialog.tsx | 328 ++++ .../components/DecisionFusionHeader.tsx | 48 + .../fusion/components/DecisionListCard.tsx | 181 +++ .../components/DecisionResultDialog.tsx | 215 +++ .../fusion/components/DeleteConfirmDialog.tsx | 38 + .../components/ExecuteConfirmDialog.tsx | 108 ++ .../fusion/components/ExecuteResultDialog.tsx | 97 ++ .../decision/fusion/components/data.ts | 193 +++ .../decision/fusion/components/types.ts | 86 + .../ai-crop-model/decision/fusion/page.tsx | 1439 ++++++++++++++++- .../(app)/ai-crop-model/decision/log/page.tsx | 1161 ++++++++++++- .../decision/simulation/page.tsx | 1400 +++++++++++++++- crop-x/src/app/(app)/layout.tsx | 4 +- src/components/ai/AIBusinessFusion.tsx | 16 +- 16 files changed, 5377 insertions(+), 39 deletions(-) create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionBadges.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionFormDialog.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionFusionHeader.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionListCard.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionResultDialog.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DeleteConfirmDialog.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/ExecuteConfirmDialog.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/ExecuteResultDialog.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/data.ts create mode 100644 crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/types.ts diff --git a/crop-x/src/app/(app)/ai-crop-model/data-sense-center/page.tsx b/crop-x/src/app/(app)/ai-crop-model/data-sense-center/page.tsx index 7decd79..d236c4e 100644 --- a/crop-x/src/app/(app)/ai-crop-model/data-sense-center/page.tsx +++ b/crop-x/src/app/(app)/ai-crop-model/data-sense-center/page.tsx @@ -5,14 +5,7 @@ import { Card } from '@/components/ui/card'; export default function DataCenterPage() { return (
- -

全域数据感知中心

-
-

- 页面路径: /ai-crop-model/data-center -

-
-
+
); } \ No newline at end of file diff --git a/crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionBadges.tsx b/crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionBadges.tsx new file mode 100644 index 0000000..79e6c4f --- /dev/null +++ b/crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionBadges.tsx @@ -0,0 +1,93 @@ +import { Badge } from "@/components/ui/badge"; +import { Brain, User, Zap } from "lucide-react"; + +import type { DecisionLevel, DecisionSource, ExecutionMode } from "./types"; + +interface DecisionLevelBadgeProps { + level: DecisionLevel; +} + +export function DecisionLevelBadge({ level }: DecisionLevelBadgeProps) { + const config: Record = { + critical: { + label: "紧急", + className: "bg-error-muted text-error-muted-foreground border-error", + }, + important: { + label: "重要", + className: "bg-warning-muted text-warning-muted-foreground border-warning", + }, + normal: { + label: "一般", + className: "bg-info-muted text-info-muted-foreground border-info", + }, + suggestion: { + label: "建议", + className: "bg-success-muted text-success-muted-foreground border-success", + }, + }; + + const { label, className } = config[level]; + + return ( + + {label} + + ); +} + +interface DecisionSourceBadgeProps { + source: DecisionSource; +} + +export function DecisionSourceBadge({ source }: DecisionSourceBadgeProps) { + const config: Record = { + auto: { + label: "自动生成", + className: "bg-accent text-accent-foreground border-accent", + icon: Brain, + }, + manual: { + label: "手动添加", + className: "bg-info-muted text-info-muted-foreground border-info", + icon: User, + }, + }; + + const { label, className, icon: Icon } = config[source]; + + return ( + + + {label} + + ); +} + +interface ExecutionModeBadgeProps { + mode: ExecutionMode; +} + +export function ExecutionModeBadge({ mode }: ExecutionModeBadgeProps) { + const config: Record = { + manual: { + label: "手动执行", + className: "bg-info-muted text-info-muted-foreground border-info", + icon: User, + }, + auto: { + label: "自动执行", + className: "bg-success-muted text-success-muted-foreground border-success", + icon: Zap, + }, + }; + + const { label, className, icon: Icon } = config[mode]; + + return ( + + + {label} + + ); +} diff --git a/crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionFormDialog.tsx b/crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionFormDialog.tsx new file mode 100644 index 0000000..5505b6d --- /dev/null +++ b/crop-x/src/app/(app)/ai-crop-model/decision/fusion/components/DecisionFormDialog.tsx @@ -0,0 +1,328 @@ +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: (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 ( + + + + {dialogTitle} + {dialogDescription} + + +
+ +

基础信息

+
+
+ + onFormChange('name', event.target.value)} + /> +
+ +
+
+ + +
+
+ + onFormChange('confidence', Number(event.target.value))} + /> +
+
+ +
+ + +

+ {formState.executionMode === 'auto' + ? '当触发条件满足时,系统将自动执行设备控制操作。' + : '需要人工点击执行按钮,验证触发条件后再执行。'} +

+
+
+
+ + +
+ +

触发条件设置

+
+

+ 设置触发条件:当设备参数满足指定阈值时自动触发决策。 +

+
+
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + onFormChange('triggerValue', event.target.value)} + /> +
+
+
+
+ + +
+ +

执行设置

+
+

配置决策触发后要执行的设备和动作。

+
+
+ + +
+ +
+
+ + +
+
+ + onFormChange('duration', Number(event.target.value))} + /> +
+
+
+
+ + +

决策内容

+
+
+ +