From 1bc33546a044cbc84dd9595c19dbcd9a4e309fc9 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期六, 10 一月 2026 14:06:10 +0800
Subject: [PATCH] #

---
 zy-acs-flow/src/map/areaSettings/index.jsx |  199 +++++++++++++++++++++++++++++++++++--------------
 1 files changed, 143 insertions(+), 56 deletions(-)

diff --git a/zy-acs-flow/src/map/areaSettings/index.jsx b/zy-acs-flow/src/map/areaSettings/index.jsx
index 3871dfb..d86d5be 100644
--- a/zy-acs-flow/src/map/areaSettings/index.jsx
+++ b/zy-acs-flow/src/map/areaSettings/index.jsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect, useMemo } from 'react';
+import React, { useState, useEffect } from 'react';
 import { useTranslate } from "react-admin";
 import {
     Drawer,
@@ -17,13 +17,33 @@
 import { PAGE_DRAWER_WIDTH } from '@/config/setting';
 import AreaBasicTab from './AreaBasicTab';
 import AreaAdvancedTab from './AreaAdvancedTab';
-import { getAreaInfo } from '../http';
+import { getAreaInfo, fetchAgvListAll, updateAreaData, removeArea } from '../http';
+import * as Tool from '../tool';
 
 const getAgvOptionId = (option) => {
-    if (typeof option === 'string') {
-        return option;
+    if (option == null) {
+        return '';
     }
-    return option?.value ?? option?.id ?? option?.agvNo ?? option?.code ?? option?.name ?? '';
+    if (typeof option === 'string' || typeof option === 'number') {
+        return String(option);
+    }
+    return option?.id ?? '';
+};
+
+const areAgvSelectionsEqual = (aIds = [], bIds = []) => {
+    if (aIds.length !== bIds.length) {
+        return false;
+    }
+    const setA = new Set(aIds);
+    return bIds.every(id => setA.has(id));
+};
+
+const mapSelectionToOptions = (selection = [], options = []) => {
+    const optionMap = new Map(options.map(option => [getAgvOptionId(option), option]));
+    return selection
+        .map(item => optionMap.get(item) || null)
+        .filter(Boolean);
+
 };
 
 const AreaSettings = (props) => {
@@ -37,15 +57,18 @@
     }
 
     const [activeTab, setActiveTab] = useState(0);
-    const [areaName, setAreaName] = useState('');
-    const [selectedAgvs, setSelectedAgvs] = useState([]);
-    const [barcodeList, setBarcodeList] = useState('');
-    const [areaCode, setAreaCode] = useState('');
-    const [maxQty, setMaxQty] = useState('');
+    const [name, setName] = useState('');
+    const [agvList, setAgvList] = useState([]);
+    const [codeList, setCodeList] = useState([]);
+    const [code, setCode] = useState('');
+    const [maxCount, setMaxCount] = useState('');
     const [speedLimit, setSpeedLimit] = useState('');
-    const [shapeData, setShapeData] = useState('');
+    const [startPoint, setStartPoint] = useState({ x: '', y: '' });
+    const [endPoint, setEndPoint] = useState({ x: '', y: '' });
     const [priority, setPriority] = useState('');
-
+    const [memo, setMemo] = useState('');
+    const [agvOptions, setAgvOptions] = useState([]);
+    const [initialBasic, setInitialBasic] = useState({ name: '', agvIds: [] });
     const [curAreaInfo, setCurAreaInfo] = useState(null);
 
     const fetchAreaInfo = (areaId) => {
@@ -59,43 +82,56 @@
             fetchAreaInfo(sprite.data.id);
         } else {
             setCurAreaInfo(null);
-            setAreaName('');
-            setAreaCode('');
-            setMaxQty('');
+            setName('');
+            setCode('');
+            setMaxCount('');
             setSpeedLimit('');
-            setShapeData('');
+            setStartPoint({ x: '', y: '' });
+            setEndPoint({ x: '', y: '' });
             setPriority('');
-            setSelectedAgvs([]);
-            setBarcodeList('');
+            setMemo('');
+            setAgvList([]);
+            setCodeList([]);
+            setInitialBasic({ name: '', agvIds: [] });
         }
     }, [sprite]);
 
-    const agvOptions = useMemo(() => {
-        if (!curAreaInfo) {
-            return [];
+    useEffect(() => {
+        if (!open) {
+            return;
         }
-        return curAreaInfo.agvOptions || curAreaInfo.agvCandidates || curAreaInfo.agvList || [];
-    }, [curAreaInfo]);
+        fetchAgvListAll().then((options) => {
+            setAgvOptions(options || []);
+        });
+    }, [open]);
 
     useEffect(() => {
         if (curAreaInfo) {
-            setAreaName(curAreaInfo.name || '');
-            setAreaCode(curAreaInfo.code || '');
-            setMaxQty(curAreaInfo.maxQty || '');
-            setSpeedLimit(curAreaInfo.speedLimit || '');
-            setShapeData(curAreaInfo.shape || '');
-            setPriority(curAreaInfo.priority || '');
+            setName(curAreaInfo.name || '');
+            setCode(curAreaInfo.code || '');
+            setMaxCount(curAreaInfo.maxCount ?? '');
+            setSpeedLimit(curAreaInfo.speedLimit ?? '');
+            setStartPoint({
+                x: curAreaInfo.start?.x ?? '',
+                y: curAreaInfo.start?.y ?? '',
+            });
+            setEndPoint({
+                x: curAreaInfo.end?.x ?? '',
+                y: curAreaInfo.end?.y ?? '',
+            });
+            setPriority(curAreaInfo.priority ?? '');
+            setMemo(curAreaInfo.memo || '');
 
-            const selected = curAreaInfo.selectedAgvs || curAreaInfo.agvs || [];
-            if (Array.isArray(selected) && Array.isArray(agvOptions) && agvOptions.length > 0) {
-                const optionMap = new Map(agvOptions.map(option => [getAgvOptionId(option), option]));
-                setSelectedAgvs(selected.map(item => optionMap.get(getAgvOptionId(item)) || item));
-            } else {
-                setSelectedAgvs(selected);
-            }
+            const selected = curAreaInfo.agvList || [];
+            const normalizedSelection = mapSelectionToOptions(selected, agvOptions);
+            setAgvList(normalizedSelection);
+            setInitialBasic({
+                name: curAreaInfo.name || '',
+                agvIds: normalizedSelection.map(getAgvOptionId)
+            });
 
-            const barcodes = curAreaInfo.barcodes || curAreaInfo.barcodeList || [];
-            setBarcodeList(Array.isArray(barcodes) ? barcodes.join('\n') : (barcodes || ''));
+            const codes = curAreaInfo.codeList || [];
+            setCodeList(Array.isArray(codes) ? codes : []);
         }
     }, [curAreaInfo, agvOptions]);
 
@@ -103,14 +139,60 @@
         setActiveTab(newValue);
     };
 
-    const handleSaveBasic = () => {
-        // placeholder for save logic
+    const submitAreaUpdate = async (payload = {}) => {
+        const id = sprite?.data?.id;
+        if (!id) {
+            return;
+        }
+        const data = await updateAreaData({ id, ...payload });
+        if (data) {
+            setCurAreaInfo(data);
+            if (sprite) {
+                Tool.updateAreaSpriteName(sprite, data.name || name);
+            }
+        }
     };
 
-    const handleSaveAdvanced = () => {
-        // placeholder for save logic
+    const handleSaveBasic = async () => {
+        await submitAreaUpdate({
+            name,
+            agvIds: agvList.map(getAgvOptionId),
+        });
     };
 
+    const handleSaveAdvanced = async () => {
+        await submitAreaUpdate({
+            name,
+            agvIds: agvList.map(getAgvOptionId),
+            code,
+            maxCount,
+            speedLimit,
+            priority,
+            memo,
+            start: startPoint,
+            end: endPoint,
+        });
+    };
+
+    const handleDeleteArea = async () => {
+        const id = sprite?.data?.id;
+        if (!id) {
+            return;
+        }
+        const success = await removeArea(id);
+        if (success) {
+            if (sprite) {
+                Tool.removeAreaSprite(sprite);
+            }
+            onCancel?.();
+        }
+    };
+
+    const basicDirty = name !== initialBasic.name
+        || !areAgvSelectionsEqual(
+            agvList.map(getAgvOptionId),
+            initialBasic.agvIds
+        );
     return (
         <>
             <Drawer
@@ -127,7 +209,7 @@
                             <Typography variant="h6" flex="1">
                                 {sprite
                                     ? translate(`page.map.devices.${sprite?.data?.type?.toLowerCase()}`) + ' - ' + sprite?.data?.name
-                                    : translate('page.map.settings.title')}
+                                    : translate('page.map.area.title')}
                             </Typography>
                             <IconButton onClick={handleClose} size="small">
                                 <CloseIcon />
@@ -156,8 +238,8 @@
                                         variant="fullWidth"
                                         sx={{ mb: 0 }}
                                     >
-                                        <Tab label={translate('page.map.area.basic', { _: '鍩虹' })} />
-                                        <Tab label={translate('page.map.area.advanced', { _: '楂樼骇' })} />
+                                        <Tab label={translate('page.map.area.tabs.basic')} />
+                                        <Tab label={translate('page.map.area.tabs.advanced')} />
                                     </Tabs>
 
                                     <Divider />
@@ -165,27 +247,32 @@
                                     <Box p={3}>
                                         {activeTab === 0 && (
                                             <AreaBasicTab
-                                                areaName={areaName}
-                                                setAreaName={setAreaName}
+                                                name={name}
+                                                setName={setName}
                                                 agvOptions={agvOptions}
-                                                selectedAgvs={selectedAgvs}
-                                                setSelectedAgvs={setSelectedAgvs}
-                                                barcodeList={barcodeList}
+                                                agvList={agvList}
+                                                setAgvList={setAgvList}
+                                                codeList={codeList}
                                                 onSave={handleSaveBasic}
+                                                disableSave={!basicDirty}
+                                                onDelete={handleDeleteArea}
+                                                canDelete={Boolean(sprite?.data?.id)}
                                             />
                                         )}
                                         {activeTab === 1 && (
                                             <AreaAdvancedTab
-                                                areaCode={areaCode}
-                                                setAreaCode={setAreaCode}
-                                                maxQty={maxQty}
-                                                setMaxQty={setMaxQty}
+                                                areaCode={code}
+                                                setAreaCode={setCode}
+                                                maxQty={maxCount}
+                                                setMaxQty={setMaxCount}
                                                 speedLimit={speedLimit}
                                                 setSpeedLimit={setSpeedLimit}
-                                                shapeData={shapeData}
-                                                setShapeData={setShapeData}
+                                                startPoint={startPoint}
+                                                endPoint={endPoint}
                                                 priority={priority}
                                                 setPriority={setPriority}
+                                                memo={memo}
+                                                setMemo={setMemo}
                                                 onSave={handleSaveAdvanced}
                                             />
                                         )}

--
Gitblit v1.9.1