From 4d97647ec29563c1cb0b0c01bafe9f8a70839977 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期一, 15 十二月 2025 16:17:51 +0800
Subject: [PATCH] #

---
 zy-acs-flow/src/map/http.js                       |   15 +++++
 zy-acs-flow/src/map/areaSettings/AreaBasicTab.jsx |   30 +++++----
 zy-acs-flow/src/map/areaSettings/index.jsx        |  118 ++++++++++++++++++++++++---------------
 3 files changed, 104 insertions(+), 59 deletions(-)

diff --git a/zy-acs-flow/src/map/areaSettings/AreaBasicTab.jsx b/zy-acs-flow/src/map/areaSettings/AreaBasicTab.jsx
index 13efc82..d6d6463 100644
--- a/zy-acs-flow/src/map/areaSettings/AreaBasicTab.jsx
+++ b/zy-acs-flow/src/map/areaSettings/AreaBasicTab.jsx
@@ -13,13 +13,14 @@
 import { useTranslate } from 'react-admin';
 
 const AreaBasicTab = ({
-    areaName,
-    setAreaName,
+    name,
+    setName,
     agvOptions,
-    selectedAgvs,
-    setSelectedAgvs,
-    barcodeList,
+    agvList,
+    setAgvList,
+    codeListText,
     onSave,
+    disableSave,
 }) => {
     const translate = useTranslate();
     const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
@@ -45,12 +46,9 @@
                 <TextField
                     label={translate('page.map.area.name', { _: '鍚嶇О' })}
                     fullWidth
-                    value={areaName}
-                    onChange={(e) => setAreaName(e.target.value)}
+                    value={name}
+                    onChange={(e) => setName(e.target.value)}
                 />
-                <Button variant="contained" onClick={onSave}>
-                    {translate('common.action.save', { _: '淇濆瓨' })}
-                </Button>
             </Stack>
 
             <Box>
@@ -61,11 +59,11 @@
                     multiple
                     disableCloseOnSelect
                     options={agvOptions || []}
-                    value={selectedAgvs || []}
+                    value={agvList || []}
                     getOptionLabel={getOptionLabel}
                     isOptionEqualToValue={(option, value) => getOptionId(option) === getOptionId(value)}
                     onChange={(event, newValue) => {
-                        setSelectedAgvs(newValue);
+                        setAgvList(newValue);
                     }}
                     renderOption={(props, option, { selected }) => (
                         <li {...props}>
@@ -98,10 +96,16 @@
                     multiline
                     minRows={6}
                     maxRows={10}
-                    value={barcodeList}
+                    value={codeListText}
                     InputProps={{ readOnly: true }}
                 />
             </Box>
+
+            <Box display="flex" justifyContent="flex-start">
+                <Button variant="contained" onClick={onSave} disabled={disableSave}>
+                    {translate('common.action.save', { _: '淇濆瓨' })}
+                </Button>
+            </Box>
         </Stack>
     );
 };
diff --git a/zy-acs-flow/src/map/areaSettings/index.jsx b/zy-acs-flow/src/map/areaSettings/index.jsx
index 3871dfb..1117f55 100644
--- a/zy-acs-flow/src/map/areaSettings/index.jsx
+++ b/zy-acs-flow/src/map/areaSettings/index.jsx
@@ -17,13 +17,26 @@
 import { PAGE_DRAWER_WIDTH } from '@/config/setting';
 import AreaBasicTab from './AreaBasicTab';
 import AreaAdvancedTab from './AreaAdvancedTab';
-import { getAreaInfo } from '../http';
+import { getAreaInfo, fetchAgvListAll } from '../http';
 
 const getAgvOptionId = (option) => {
     if (typeof option === 'string') {
         return option;
     }
     return option?.value ?? option?.id ?? option?.agvNo ?? option?.code ?? option?.name ?? '';
+};
+
+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(getAgvOptionId(item)) || item);
 };
 
 const AreaSettings = (props) => {
@@ -37,15 +50,16 @@
     }
 
     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 [memo, setMemo] = useState('');
     const [priority, setPriority] = useState('');
-
+    const [agvOptions, setAgvOptions] = useState([]);
+    const [initialBasic, setInitialBasic] = useState({ name: '', agvIds: [] });
     const [curAreaInfo, setCurAreaInfo] = useState(null);
 
     const fetchAreaInfo = (areaId) => {
@@ -59,43 +73,43 @@
             fetchAreaInfo(sprite.data.id);
         } else {
             setCurAreaInfo(null);
-            setAreaName('');
-            setAreaCode('');
-            setMaxQty('');
+            setName('');
+            setCode('');
+            setMaxCount('');
             setSpeedLimit('');
-            setShapeData('');
+            setMemo('');
             setPriority('');
-            setSelectedAgvs([]);
-            setBarcodeList('');
+            setAgvList([]);
+            setCodeList([]);
+            setInitialBasic({ name: '', agvIds: [] });
         }
     }, [sprite]);
 
-    const agvOptions = useMemo(() => {
-        if (!curAreaInfo) {
-            return [];
-        }
-        return curAreaInfo.agvOptions || curAreaInfo.agvCandidates || curAreaInfo.agvList || [];
-    }, [curAreaInfo]);
+    useEffect(() => {
+        fetchAgvListAll().then((options) => {
+            setAgvOptions(options || []);
+        });
+    }, []);
 
     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 ?? '');
+            setMemo(curAreaInfo.memo || '');
+            setPriority(curAreaInfo.priority ?? '');
 
-            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]);
 
@@ -105,11 +119,22 @@
 
     const handleSaveBasic = () => {
         // placeholder for save logic
+        setInitialBasic({
+            name,
+            agvIds: agvList.map(getAgvOptionId),
+        });
     };
 
     const handleSaveAdvanced = () => {
         // placeholder for save logic
     };
+
+    const codeListText = (codeList || []).join('\n');
+    const basicDirty = name !== initialBasic.name
+        || !areAgvSelectionsEqual(
+            agvList.map(getAgvOptionId),
+            initialBasic.agvIds
+        );
 
     return (
         <>
@@ -165,25 +190,26 @@
                                     <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}
+                                                codeListText={codeListText}
                                                 onSave={handleSaveBasic}
+                                                disableSave={!basicDirty}
                                             />
                                         )}
                                         {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}
+                                                shapeData={memo}
+                                                setShapeData={setMemo}
                                                 priority={priority}
                                                 setPriority={setPriority}
                                                 onSave={handleSaveAdvanced}
diff --git a/zy-acs-flow/src/map/http.js b/zy-acs-flow/src/map/http.js
index 27de2c1..11346d4 100644
--- a/zy-acs-flow/src/map/http.js
+++ b/zy-acs-flow/src/map/http.js
@@ -430,3 +430,18 @@
     }
     return null;
 }
+
+export const fetchAgvListAll = async () => {
+    try {
+        const res = await request.get('/agv/list');
+        const { code, msg, data } = res.data;
+        if (code === 200) {
+            return data || [];
+        }
+        notify.error(msg);
+    } catch (error) {
+        notify.error(error.message);
+        console.error(error.message);
+    }
+    return [];
+}

--
Gitblit v1.9.1