生产管理系统前端 - 瓦力提交代码&文档更新
This commit is contained in:
@@ -134,50 +134,83 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
const [systemEnabled, setSystemEnabled] = useState(false);
|
||||
const [selectedValveId, setSelectedValveId] = useState('valve-1');
|
||||
const [historyDateRange, setHistoryDateRange] = useState('7');
|
||||
const [selectedMachineId, setSelectedMachineId] = useState('wf-001');
|
||||
const [isEditMode, setIsEditMode] = useState(false);
|
||||
|
||||
// 根据路径自动切换Tab
|
||||
useEffect(() => {
|
||||
if (activePath) {
|
||||
if (activePath.includes('/params')) {
|
||||
setActiveTab('params');
|
||||
} else if (activePath.includes('/tank-realtime')) {
|
||||
setActiveTab('tank-realtime');
|
||||
} else if (activePath.includes('/valve-control')) {
|
||||
setActiveTab('valve-control');
|
||||
} else if (activePath.includes('/valve-realtime')) {
|
||||
setActiveTab('valve-realtime');
|
||||
} else if (activePath.includes('/fertilizer-history')) {
|
||||
setActiveTab('fertilizer-history');
|
||||
} else if (activePath.includes('/valve-history')) {
|
||||
setActiveTab('valve-history');
|
||||
}
|
||||
}
|
||||
}, [activePath]);
|
||||
|
||||
// 肥料桶数据
|
||||
const [tanks, setTanks] = useState<FertilizerTank[]>([
|
||||
{ id: 'tank-1', tankNo: 'A', name: 'A肥料桶', fertilizer: '氮肥溶液', concentration: 15, ratio: 40, currentLevel: 320, flowRate: 8.5 },
|
||||
{ id: 'tank-2', tankNo: 'B', name: 'B肥料桶', fertilizer: '磷肥溶液', concentration: 12, ratio: 30, currentLevel: 180, flowRate: 6.2 },
|
||||
{ id: 'tank-3', tankNo: 'C', name: 'C肥料桶', fertilizer: '钾肥溶液', concentration: 18, ratio: 30, currentLevel: 425, flowRate: 6.8 },
|
||||
// 水肥机设备列表
|
||||
const [machines, setMachines] = useState<WaterFertilizerMachine[]>([
|
||||
{
|
||||
id: 'wf-001',
|
||||
name: '1号大棚水肥一体机',
|
||||
ecValue: 2.35,
|
||||
ecTarget: 2.5,
|
||||
phValue: 6.8,
|
||||
phTarget: 6.5,
|
||||
status: '运行中',
|
||||
},
|
||||
{
|
||||
id: 'wf-002',
|
||||
name: '2号大棚水肥一体机',
|
||||
ecValue: 2.18,
|
||||
ecTarget: 2.3,
|
||||
phValue: 6.5,
|
||||
phTarget: 6.4,
|
||||
status: '待机',
|
||||
},
|
||||
{
|
||||
id: 'wf-003',
|
||||
name: '3号田块水肥一体机',
|
||||
ecValue: 2.52,
|
||||
ecTarget: 2.6,
|
||||
phValue: 6.9,
|
||||
phTarget: 6.7,
|
||||
status: '运行中',
|
||||
},
|
||||
{
|
||||
id: 'wf-004',
|
||||
name: '4号田块水肥一体机',
|
||||
ecValue: 2.08,
|
||||
ecTarget: 2.2,
|
||||
phValue: 6.3,
|
||||
phTarget: 6.2,
|
||||
status: '已停止',
|
||||
},
|
||||
]);
|
||||
|
||||
// 水肥机数据
|
||||
const [machine, setMachine] = useState<WaterFertilizerMachine>({
|
||||
id: 'wf-001',
|
||||
name: '1号水肥机',
|
||||
ecValue: 2.35,
|
||||
ecTarget: 2.5,
|
||||
phValue: 6.8,
|
||||
phTarget: 6.5,
|
||||
status: systemEnabled ? '运行中' : '已停止',
|
||||
});
|
||||
// 肥料桶数据(按水肥机分组)
|
||||
const [allTanks, setAllTanks] = useState<(FertilizerTank & { machineId: string })[]>([
|
||||
// 1号水肥机
|
||||
{ id: 'tank-1-1', machineId: 'wf-001', tankNo: 'A', name: 'A肥料桶', fertilizer: '氮肥溶液', concentration: 15, ratio: 40, currentLevel: 320, flowRate: 8.5 },
|
||||
{ id: 'tank-1-2', machineId: 'wf-001', tankNo: 'B', name: 'B肥料桶', fertilizer: '磷肥溶液', concentration: 12, ratio: 30, currentLevel: 180, flowRate: 6.2 },
|
||||
{ id: 'tank-1-3', machineId: 'wf-001', tankNo: 'C', name: 'C肥料桶', fertilizer: '钾肥溶液', concentration: 18, ratio: 30, currentLevel: 425, flowRate: 6.8 },
|
||||
// 2号水肥机
|
||||
{ id: 'tank-2-1', machineId: 'wf-002', tankNo: 'A', name: 'A肥料桶', fertilizer: '氮肥溶液', concentration: 16, ratio: 35, currentLevel: 285, flowRate: 7.2 },
|
||||
{ id: 'tank-2-2', machineId: 'wf-002', tankNo: 'B', name: 'B肥料桶', fertilizer: '磷肥溶液', concentration: 14, ratio: 35, currentLevel: 215, flowRate: 5.8 },
|
||||
{ id: 'tank-2-3', machineId: 'wf-002', tankNo: 'C', name: 'C肥料桶', fertilizer: '钾肥溶液', concentration: 17, ratio: 30, currentLevel: 380, flowRate: 6.5 },
|
||||
// 3号水肥机
|
||||
{ id: 'tank-3-1', machineId: 'wf-003', tankNo: 'A', name: 'A肥料桶', fertilizer: '氮肥溶液', concentration: 14, ratio: 42, currentLevel: 295, flowRate: 8.8 },
|
||||
{ id: 'tank-3-2', machineId: 'wf-003', tankNo: 'B', name: 'B肥料桶', fertilizer: '磷肥溶液', concentration: 13, ratio: 28, currentLevel: 165, flowRate: 5.5 },
|
||||
{ id: 'tank-3-3', machineId: 'wf-003', tankNo: 'C', name: 'C肥料桶', fertilizer: '钾肥溶液', concentration: 19, ratio: 30, currentLevel: 445, flowRate: 7.2 },
|
||||
// 4号水肥机
|
||||
{ id: 'tank-4-1', machineId: 'wf-004', tankNo: 'A', name: 'A肥料桶', fertilizer: '氮肥溶液', concentration: 15, ratio: 38, currentLevel: 310, flowRate: 0 },
|
||||
{ id: 'tank-4-2', machineId: 'wf-004', tankNo: 'B', name: 'B肥料桶', fertilizer: '磷肥溶液', concentration: 12, ratio: 32, currentLevel: 195, flowRate: 0 },
|
||||
{ id: 'tank-4-3', machineId: 'wf-004', tankNo: 'C', name: 'C肥料桶', fertilizer: '钾肥溶液', concentration: 18, ratio: 30, currentLevel: 405, flowRate: 0 },
|
||||
]);
|
||||
|
||||
// 阀门数据
|
||||
const [valves, setValves] = useState<Valve[]>([
|
||||
{ id: 'valve-1', valveNo: 'V-01', fieldName: '1号大棚', location: '东区A01', status: '开启', batteryVoltage: 12.5, solarVoltage: 18.2, pressure: 2.8, flowRate: 25.6, totalVolume: 1450 },
|
||||
{ id: 'valve-2', valveNo: 'V-02', fieldName: '2号田块', location: '西区B02', status: '关闭', batteryVoltage: 11.8, solarVoltage: 17.5, pressure: 0, flowRate: 0, totalVolume: 0 },
|
||||
{ id: 'valve-3', valveNo: 'V-03', fieldName: '3号田块', location: '南区C03', status: '开启', batteryVoltage: 12.2, solarVoltage: 18.8, pressure: 2.6, flowRate: 23.2, totalVolume: 1280 },
|
||||
{ id: 'valve-4', valveNo: 'V-04', fieldName: '4号田块', location: '北区D04', status: '故障', batteryVoltage: 10.5, solarVoltage: 15.2, pressure: 0, flowRate: 0, totalVolume: 0 },
|
||||
// 阀门数据(按水肥机分组)
|
||||
const [allValves, setAllValves] = useState<(Valve & { machineId: string })[]>([
|
||||
// 1号水肥机的阀门
|
||||
{ id: 'valve-1-1', machineId: 'wf-001', valveNo: 'V-01', fieldName: '1号大棚', location: '东区A01', status: '开启', batteryVoltage: 12.5, solarVoltage: 18.2, pressure: 2.8, flowRate: 25.6, totalVolume: 1450 },
|
||||
{ id: 'valve-1-2', machineId: 'wf-001', valveNo: 'V-02', fieldName: '1号大棚-西侧', location: '东区A02', status: '关闭', batteryVoltage: 11.8, solarVoltage: 17.5, pressure: 0, flowRate: 0, totalVolume: 0 },
|
||||
// 2号水肥机的阀门
|
||||
{ id: 'valve-2-1', machineId: 'wf-002', valveNo: 'V-03', fieldName: '2号大棚', location: '西区B01', status: '开启', batteryVoltage: 12.2, solarVoltage: 18.8, pressure: 2.6, flowRate: 23.2, totalVolume: 1280 },
|
||||
{ id: 'valve-2-2', machineId: 'wf-002', valveNo: 'V-04', fieldName: '2号大棚-东侧', location: '西区B02', status: '关闭', batteryVoltage: 12.0, solarVoltage: 18.0, pressure: 0, flowRate: 0, totalVolume: 0 },
|
||||
// 3号水肥机的阀门
|
||||
{ id: 'valve-3-1', machineId: 'wf-003', valveNo: 'V-05', fieldName: '3号田块', location: '南区C01', status: '开启', batteryVoltage: 12.8, solarVoltage: 19.2, pressure: 2.9, flowRate: 27.8, totalVolume: 1580 },
|
||||
{ id: 'valve-3-2', machineId: 'wf-003', valveNo: 'V-06', fieldName: '3号田块-北侧', location: '南区C02', status: '开启', batteryVoltage: 12.3, solarVoltage: 18.5, pressure: 2.7, flowRate: 24.5, totalVolume: 1320 },
|
||||
// 4号水肥机的阀门
|
||||
{ id: 'valve-4-1', machineId: 'wf-004', valveNo: 'V-07', fieldName: '4号田块', location: '北区D01', status: '故障', batteryVoltage: 10.5, solarVoltage: 15.2, pressure: 0, flowRate: 0, totalVolume: 0 },
|
||||
{ id: 'valve-4-2', machineId: 'wf-004', valveNo: 'V-08', fieldName: '4号田块-南侧', location: '北区D02', status: '关闭', batteryVoltage: 11.5, solarVoltage: 17.0, pressure: 0, flowRate: 0, totalVolume: 0 },
|
||||
]);
|
||||
|
||||
// 土壤数据
|
||||
@@ -222,6 +255,37 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
{ date: '10-15', tankAFlow: 190, tankBFlow: 155, tankCFlow: 160, avgEc: 2.5, avgPh: 6.6, avgPressure: 2.6, avgFlowRate: 25.8 },
|
||||
]);
|
||||
|
||||
// 根据路径自动切换Tab
|
||||
useEffect(() => {
|
||||
if (activePath) {
|
||||
if (activePath.includes('/params')) {
|
||||
setActiveTab('params');
|
||||
} else if (activePath.includes('/tank-realtime')) {
|
||||
setActiveTab('tank-realtime');
|
||||
} else if (activePath.includes('/valve-control')) {
|
||||
setActiveTab('valve-control');
|
||||
} else if (activePath.includes('/valve-realtime')) {
|
||||
setActiveTab('valve-realtime');
|
||||
} else if (activePath.includes('/fertilizer-history')) {
|
||||
setActiveTab('fertilizer-history');
|
||||
} else if (activePath.includes('/valve-history')) {
|
||||
setActiveTab('valve-history');
|
||||
}
|
||||
}
|
||||
}, [activePath]);
|
||||
|
||||
// 切换水肥机时,更新选中的阀门为当前水肥机的第一个阀门
|
||||
useEffect(() => {
|
||||
const currentMachineValves = allValves.filter(v => v.machineId === selectedMachineId);
|
||||
if (currentMachineValves.length > 0 && !currentMachineValves.find(v => v.id === selectedValveId)) {
|
||||
setSelectedValveId(currentMachineValves[0].id);
|
||||
}
|
||||
}, [selectedMachineId, allValves, selectedValveId]);
|
||||
|
||||
// 根据选中的水肥机筛选数据
|
||||
const tanks = allTanks.filter(tank => tank.machineId === selectedMachineId);
|
||||
const valves = allValves.filter(valve => valve.machineId === selectedMachineId);
|
||||
const machine = machines.find(m => m.id === selectedMachineId) || machines[0];
|
||||
const selectedValve = valves.find(v => v.id === selectedValveId) || valves[0];
|
||||
|
||||
const getValveStatusColor = (status: ValveStatus) => {
|
||||
@@ -235,20 +299,28 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
|
||||
const handleSystemToggle = (enabled: boolean) => {
|
||||
setSystemEnabled(enabled);
|
||||
setMachine({ ...machine, status: enabled ? '运行中' : '已停止' });
|
||||
toast.success(enabled ? '施肥系统已启动' : '施肥系统已停止');
|
||||
setMachines(machines.map(m =>
|
||||
m.id === selectedMachineId
|
||||
? { ...m, status: enabled ? '运行中' : '已停止' }
|
||||
: m
|
||||
));
|
||||
toast.success(`${machine.name} ${enabled ? '已启动' : '已停止'}`);
|
||||
};
|
||||
|
||||
const handleTankUpdate = (tankId: string, field: keyof FertilizerTank, value: string | number) => {
|
||||
setTanks(tanks.map(t => t.id === tankId ? { ...t, [field]: value } : t));
|
||||
setAllTanks(allTanks.map(t => t.id === tankId ? { ...t, [field]: value } : t));
|
||||
};
|
||||
|
||||
const handleMachineUpdate = (field: keyof WaterFertilizerMachine, value: number) => {
|
||||
setMachine({ ...machine, [field]: value });
|
||||
setMachines(machines.map(m =>
|
||||
m.id === selectedMachineId
|
||||
? { ...m, [field]: value }
|
||||
: m
|
||||
));
|
||||
};
|
||||
|
||||
const handleValveToggle = (valveId: string) => {
|
||||
const valve = valves.find(v => v.id === valveId);
|
||||
const valve = allValves.find(v => v.id === valveId);
|
||||
if (!valve) return;
|
||||
|
||||
if (valve.status === '故障') {
|
||||
@@ -257,10 +329,30 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
}
|
||||
|
||||
const newStatus: ValveStatus = valve.status === '开启' ? '关闭' : '开启';
|
||||
setValves(valves.map(v => v.id === valveId ? { ...v, status: newStatus } : v));
|
||||
setAllValves(allValves.map(v => v.id === valveId ? { ...v, status: newStatus } : v));
|
||||
toast.success(`${valve.valveNo} 已${newStatus === '开启' ? '开启' : '关闭'}`);
|
||||
};
|
||||
|
||||
const handleEditParams = () => {
|
||||
setIsEditMode(true);
|
||||
toast.info('进入编辑模式', {
|
||||
description: '现在可以修改肥料参数配置',
|
||||
});
|
||||
};
|
||||
|
||||
const handleSaveParams = () => {
|
||||
// 保存肥料参数配置
|
||||
setIsEditMode(false);
|
||||
toast.success(`${machine.name} 参数配置已保存`, {
|
||||
description: '肥料桶参数和EC/PH目标值已更新',
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancelEdit = () => {
|
||||
setIsEditMode(false);
|
||||
toast.info('已取消编辑');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -270,18 +362,33 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
施肥参数配置、实时监测、阀门控制、历史数据分析
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline">
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
刷新数据
|
||||
</Button>
|
||||
<Button variant="outline">
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
导出报告
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 水肥机选择 */}
|
||||
<Card className="p-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<Label>选择水肥机设备</Label>
|
||||
<Select value={selectedMachineId} onValueChange={setSelectedMachineId}>
|
||||
<SelectTrigger className="w-96">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{machines.map((machine) => (
|
||||
<SelectItem key={machine.id} value={machine.id}>
|
||||
{machine.name}
|
||||
<Badge className="ml-2 bg-green-100 text-green-700" variant="outline">
|
||||
{machine.status}
|
||||
</Badge>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
当前设备:<span className="text-foreground">{machine.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 统计卡片 */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<Card className="p-6">
|
||||
@@ -385,10 +492,31 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
|
||||
{/* 肥料桶参数 */}
|
||||
<Card className="p-6">
|
||||
<h4 className="mb-4 flex items-center gap-2">
|
||||
<Beaker className="w-5 h-5 text-blue-600" />
|
||||
肥料桶参数配置
|
||||
</h4>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h4 className="flex items-center gap-2">
|
||||
<Beaker className="w-5 h-5 text-blue-600" />
|
||||
肥料桶参数配置
|
||||
</h4>
|
||||
<div className="flex items-center gap-3">
|
||||
{!isEditMode ? (
|
||||
<Button onClick={handleEditParams} variant="outline">
|
||||
<Settings className="w-4 h-4 mr-2" />
|
||||
编辑参数
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
<Button onClick={handleCancelEdit} variant="outline">
|
||||
<XCircle className="w-4 h-4 mr-2" />
|
||||
取消编辑
|
||||
</Button>
|
||||
<Button onClick={handleSaveParams} className="bg-green-600 hover:bg-green-700">
|
||||
<CheckCircle className="w-4 h-4 mr-2" />
|
||||
保存参数配置
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{tanks.map((tank) => (
|
||||
<Card key={tank.id} className="p-4 bg-gray-50">
|
||||
@@ -403,6 +531,7 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
value={tank.fertilizer}
|
||||
onChange={(e) => handleTankUpdate(tank.id, 'fertilizer', e.target.value)}
|
||||
className="mt-2"
|
||||
disabled={!isEditMode}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -412,6 +541,7 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
value={tank.concentration}
|
||||
onChange={(e) => handleTankUpdate(tank.id, 'concentration', parseFloat(e.target.value))}
|
||||
className="mt-2"
|
||||
disabled={!isEditMode}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -421,6 +551,7 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
value={tank.ratio}
|
||||
onChange={(e) => handleTankUpdate(tank.id, 'ratio', parseFloat(e.target.value))}
|
||||
className="mt-2"
|
||||
disabled={!isEditMode}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@@ -465,6 +596,7 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
max={5}
|
||||
step={0.1}
|
||||
className="mt-2"
|
||||
disabled={!isEditMode}
|
||||
/>
|
||||
<div className="flex justify-between text-xs text-muted-foreground mt-2">
|
||||
<span>当前EC: {machine.ecValue}</span>
|
||||
@@ -484,6 +616,7 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
max={9}
|
||||
step={0.1}
|
||||
className="mt-2"
|
||||
disabled={!isEditMode}
|
||||
/>
|
||||
<div className="flex justify-between text-xs text-muted-foreground mt-2">
|
||||
<span>当前PH: {machine.phValue}</span>
|
||||
@@ -974,15 +1107,11 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
<Calendar className="w-4 h-4 mr-2" />
|
||||
自定义时段
|
||||
</Button>
|
||||
<Button variant="outline">
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
导出数据
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 统计卡片 */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-5 gap-4">
|
||||
<Card className="p-4">
|
||||
<p className="text-xs text-muted-foreground mb-2">A桶总流量</p>
|
||||
<p className="text-2xl text-blue-600">
|
||||
@@ -1023,6 +1152,14 @@ export function WaterFertilizerControl({ activePath }: WaterFertilizerControlPro
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground mt-1">mS/cm</p>
|
||||
</Card>
|
||||
|
||||
<Card className="p-4">
|
||||
<p className="text-xs text-muted-foreground mb-2">平均PH值</p>
|
||||
<p className="text-2xl text-purple-600">
|
||||
{(historyData.reduce((sum, d) => sum + d.avgPh, 0) / historyData.length).toFixed(2)}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground mt-1">pH</p>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* 肥料桶流量历史 */}
|
||||
|
||||
Reference in New Issue
Block a user