From eb8ded2565e746a360985f702c556b26f750d35a Mon Sep 17 00:00:00 2001
From: skyouc
Date: 星期二, 25 三月 2025 09:07:51 +0800
Subject: [PATCH] Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop

---
 rsf-admin/src/page/basicInfo/locArea/LocAreaEdit.jsx                                                |    3 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocAreaMat.java                      |  217 ++
 rsf-admin/src/page/basicInfo/locAreaMat/BindLocModal.jsx                                            |  220 ++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MatnrGroupServiceImpl.java     |   32 
 rsf-admin/src/page/system/host/HostList.jsx                                                         |    4 
 rsf-admin/src/page/fields/FieldsList.jsx                                                            |    8 
 rsf-admin/src/page/system/userLogin/UserLoginList.jsx                                               |    4 
 rsf-admin/src/page/basicInfo/locType/LocTypeList.jsx                                                |   33 
 rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java                             |    4 
 rsf-admin/src/page/warehouseAreasItem/WarehouseAreasItemList.jsx                                    |    2 
 rsf-admin/src/page/basicInfo/matnr/PrintModal.jsx                                                   |    9 
 rsf-server/src/main/resources/mapper/manager/LocAreaMatMapper.xml                                   |    5 
 rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatList.jsx                                          |  156 ++
 rsf-admin/src/page/basicInfo/companys/CompanysEdit.jsx                                              |    1 
 rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatCreate.jsx                                        |  137 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WarehouseAreasController.java    |    8 
 rsf-admin/src/page/container/ContainerEdit.jsx                                                      |    1 
 rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictTypeController.java           |   14 
 rsf-admin/src/page/system/dicts/dictData/DictDataEdit.jsx                                           |    1 
 rsf-admin/src/i18n/en.js                                                                            |   18 
 rsf-admin/src/page/ResourceContent.js                                                               |    7 
 rsf-admin/.env                                                                                      |    4 
 rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatEdit.jsx                                          |  109 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrGroupController.java        |   15 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MatnrGroupService.java              |    4 
 rsf-admin/src/page/basicInfo/locArea/LocAreaList.jsx                                                |    2 
 rsf-admin/src/page/components/ConfirmModal.jsx                                                      |   50 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocAreaMatService.java              |    8 
 rsf-admin/src/page/system/tenant/TenantList.jsx                                                     |    4 
 rsf-admin/src/page/qlyInspect/QlyInspectList.jsx                                                    |    4 
 rsf-admin/src/page/system/dicts/dictData/DictDataList.jsx                                           |    2 
 rsf-admin/src/page/basicInfo/loc/InitModal.jsx                                                      |    2 
 rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaList.jsx                                        |  154 ++
 rsf-admin/src/page/basicInfo/matnr/BindModal.jsx                                                    |  186 ++
 rsf-admin/src/page/basicInfo/loc/LocEdit.jsx                                                        |    2 
 rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx                                                    |   28 
 rsf-admin/package-lock.json                                                                         |  432 +----
 rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaCreate.jsx                                      |  123 +
 rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupCreate.jsx                                        |    3 
 rsf-admin/src/page/system/serialRuleItem/SerialRuleItemList.jsx                                     |    2 
 rsf-admin/src/page/contract/ContractEdit.jsx                                                        |    1 
 rsf-admin/src/page/basicInfo/locAreaMat/index.jsx                                                   |   18 
 rsf-admin/src/page/asnOrderItem/AsnOrderItemList.jsx                                                |    2 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocAreaMatRelaServiceImpl.java |  115 +
 rsf-admin/src/page/fieldsItem/FieldsItemList.jsx                                                    |    4 
 rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaEdit.jsx                                  |  152 ++
 rsf-admin/src/page/qlyIsptItem/QlyIsptItemList.jsx                                                  |    4 
 rsf-admin/src/page/basicInfo/loc/BindModal.jsx                                                      |  197 ++
 rsf-admin/src/page/basicInfo/loc/LocCreate.jsx                                                      |    1 
 rsf-common/src/main/java/com/vincent/rsf/common/utils/Utils.java                                    |   20 
 rsf-admin/src/page/basicInfo/locArea/LocAreaCreate.jsx                                              |    2 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocTypeRela.java                     |   38 
 rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupEdit.jsx                                          |   77 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/LocAreaMatMapper.java                |   12 
 rsf-server/src/main/resources/application.yml                                                       |    4 
 rsf-admin/src/i18n/zh.js                                                                            |   20 
 rsf-admin/src/page/system/dicts/dictData/DictDataCreate.jsx                                         |    1 
 rsf-admin/src/page/basicInfo/warehouse/WarehouseEdit.jsx                                            |    1 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocAreaMatController.java        |  112 +
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/LocAreaMatsParam.java     |    6 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocAreaMatRela.java                  |    6 
 rsf-server/src/main/resources/mapper/test/LocAreaMatMapper.xml                                      |    5 
 rsf-admin/src/page/basicInfo/locAreaRela/index.jsx                                                  |   18 
 rsf-admin/src/page/system/serialRule/SerialRuleList.jsx                                             |    2 
 rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaList.jsx                                  |  158 ++
 rsf-admin/src/page/basicInfo/locType/LocTypeEdit.jsx                                                |    1 
 rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaPanel.jsx                                       |   63 
 rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx                                          |    4 
 rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaPanel.jsx                                 |   28 
 rsf-admin/src/page/basicInfo/loc/LocList.jsx                                                        |   41 
 rsf-admin/src/page/basicInfo/matnr/MatnrEdit.jsx                                                    |    1 
 rsf-admin/src/page/purchaseItem/PurchaseItemList.jsx                                                |    2 
 rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx                                            |    2 
 /dev/null                                                                                           |   23 
 rsf-admin/src/page/basicInfo/locType/BindModal.jsx                                                  |  199 ++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocAreaMatRelaController.java    |   82 
 rsf-admin/src/page/system/config/ConfigList.jsx                                                     |    4 
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocAreaMatServiceImpl.java     |   12 
 rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaEdit.jsx                                        |   95 +
 rsf-admin/src/page/basicInfo/locAreaMatRela/index.jsx                                               |   18 
 rsf-admin/src/page/basicInfo/locAreaMat/BindMatnrModal.jsx                                          |  216 ++
 rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictDataController.java           |   15 
 rsf-admin/src/page/system/dicts/dictType/DictTypeList.jsx                                           |    2 
 rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaCreate.jsx                                |  179 ++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocAreaMatRelaService.java          |   14 
 rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx                                         |  411 +++++
 86 files changed, 3,929 insertions(+), 477 deletions(-)

diff --git a/rsf-admin/.env b/rsf-admin/.env
index ac2bce4..a8ce658 100644
--- a/rsf-admin/.env
+++ b/rsf-admin/.env
@@ -1,3 +1,3 @@
-VITE_BASE_IP=192.168.4.16
-#VITE_BASE_IP=47.76.147.249
+VITE_BASE_IP=192.168.4.24
+# VITE_BASE_IP=47.76.147.249
 VITE_BASE_PORT=8080
diff --git a/rsf-admin/package-lock.json b/rsf-admin/package-lock.json
index 2c2e71f..f731a50 100644
--- a/rsf-admin/package-lock.json
+++ b/rsf-admin/package-lock.json
@@ -23,17 +23,14 @@
         "pixi.js": "^7.4.0",
         "prop-types": "^15.8.1",
         "ra-i18n-polyglot": "^5.6.2",
-        "ra-language-chinese": "^2.0.10",
         "ra-language-english": "^5.6.2",
         "react": "^18.3.0",
-        "react-admin": "^5.6.3",
-        "react-barcode": "^1.6.1",
+        "react-admin": "^5.1.0",
         "react-dom": "^18.3.0",
         "react-hook-form": "^7.53.0",
         "react-router": "^6.22.0",
         "react-router-dom": "^6.26.1",
         "react-syntax-highlighter": "^15.5.0",
-        "react-to-print": "^3.0.5",
         "three": "^0.155.0",
         "tweedle.js": "^2.1.0"
       },
@@ -369,16 +366,15 @@
       }
     },
     "node_modules/@emotion/babel-plugin": {
-      "version": "11.13.5",
-      "resolved": "https://registry.npmmirror.com/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
-      "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==",
-      "license": "MIT",
+      "version": "11.12.0",
+      "resolved": "https://registry.npmmirror.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz",
+      "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==",
       "dependencies": {
         "@babel/helper-module-imports": "^7.16.7",
         "@babel/runtime": "^7.18.3",
         "@emotion/hash": "^0.9.2",
         "@emotion/memoize": "^0.9.0",
-        "@emotion/serialize": "^1.3.3",
+        "@emotion/serialize": "^1.2.0",
         "babel-plugin-macros": "^3.1.0",
         "convert-source-map": "^1.5.0",
         "escape-string-regexp": "^4.0.0",
@@ -390,14 +386,12 @@
     "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
       "version": "1.9.0",
       "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.9.0.tgz",
-      "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
-      "license": "MIT"
+      "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
     },
     "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
       "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "license": "MIT",
       "engines": {
         "node": ">=10"
       },
@@ -437,17 +431,16 @@
       "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="
     },
     "node_modules/@emotion/react": {
-      "version": "11.14.0",
-      "resolved": "https://registry.npmmirror.com/@emotion/react/-/react-11.14.0.tgz",
-      "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
-      "license": "MIT",
+      "version": "11.13.3",
+      "resolved": "https://registry.npmmirror.com/@emotion/react/-/react-11.13.3.tgz",
+      "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==",
       "dependencies": {
         "@babel/runtime": "^7.18.3",
-        "@emotion/babel-plugin": "^11.13.5",
-        "@emotion/cache": "^11.14.0",
-        "@emotion/serialize": "^1.3.3",
-        "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
-        "@emotion/utils": "^1.4.2",
+        "@emotion/babel-plugin": "^11.12.0",
+        "@emotion/cache": "^11.13.0",
+        "@emotion/serialize": "^1.3.1",
+        "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
+        "@emotion/utils": "^1.4.0",
         "@emotion/weak-memoize": "^0.4.0",
         "hoist-non-react-statics": "^3.3.1"
       },
@@ -479,17 +472,16 @@
       "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="
     },
     "node_modules/@emotion/styled": {
-      "version": "11.14.0",
-      "resolved": "https://registry.npmmirror.com/@emotion/styled/-/styled-11.14.0.tgz",
-      "integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==",
-      "license": "MIT",
+      "version": "11.13.0",
+      "resolved": "https://registry.npmmirror.com/@emotion/styled/-/styled-11.13.0.tgz",
+      "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==",
       "dependencies": {
         "@babel/runtime": "^7.18.3",
-        "@emotion/babel-plugin": "^11.13.5",
+        "@emotion/babel-plugin": "^11.12.0",
         "@emotion/is-prop-valid": "^1.3.0",
-        "@emotion/serialize": "^1.3.3",
-        "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
-        "@emotion/utils": "^1.4.2"
+        "@emotion/serialize": "^1.3.0",
+        "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
+        "@emotion/utils": "^1.4.0"
       },
       "peerDependencies": {
         "@emotion/react": "^11.0.0-rc.0",
@@ -507,10 +499,9 @@
       "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="
     },
     "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmmirror.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz",
-      "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==",
-      "license": "MIT",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz",
+      "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==",
       "peerDependencies": {
         "react": ">=16.8.0"
       }
@@ -1249,13 +1240,13 @@
       "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
     },
     "node_modules/@mui/private-theming": {
-      "version": "6.4.8",
-      "resolved": "https://registry.npmmirror.com/@mui/private-theming/-/private-theming-6.4.8.tgz",
-      "integrity": "sha512-sWwQoNSn6elsPTAtSqCf+w5aaGoh7AASURNmpy+QTTD/zwJ0Jgwt0ZaaP6mXq2IcgHxYnYloM/+vJgHPMkRKTQ==",
+      "version": "6.4.6",
+      "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.6.tgz",
+      "integrity": "sha512-T5FxdPzCELuOrhpA2g4Pi6241HAxRwZudzAuL9vBvniuB5YU82HCmrARw32AuCiyTfWzbrYGGpZ4zyeqqp9RvQ==",
       "license": "MIT",
       "dependencies": {
         "@babel/runtime": "^7.26.0",
-        "@mui/utils": "^6.4.8",
+        "@mui/utils": "^6.4.6",
         "prop-types": "^15.8.1"
       },
       "engines": {
@@ -1276,13 +1267,13 @@
       }
     },
     "node_modules/@mui/private-theming/node_modules/@mui/utils": {
-      "version": "6.4.8",
-      "resolved": "https://registry.npmmirror.com/@mui/utils/-/utils-6.4.8.tgz",
-      "integrity": "sha512-C86gfiZ5BfZ51KqzqoHi1WuuM2QdSKoFhbkZeAfQRB+jCc4YNhhj11UXFVMMsqBgZ+Zy8IHNJW3M9Wj/LOwRXQ==",
+      "version": "6.4.6",
+      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.6.tgz",
+      "integrity": "sha512-43nZeE1pJF2anGafNydUcYFPtHwAqiBiauRtaMvurdrZI3YrUjHkAu43RBsxef7OFtJMXGiHFvq43kb7lig0sA==",
       "license": "MIT",
       "dependencies": {
         "@babel/runtime": "^7.26.0",
-        "@mui/types": "~7.2.24",
+        "@mui/types": "^7.2.21",
         "@types/prop-types": "^15.7.14",
         "clsx": "^2.1.1",
         "prop-types": "^15.8.1",
@@ -1307,14 +1298,14 @@
     },
     "node_modules/@mui/private-theming/node_modules/react-is": {
       "version": "19.0.0",
-      "resolved": "https://registry.npmmirror.com/react-is/-/react-is-19.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz",
       "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==",
       "license": "MIT"
     },
     "node_modules/@mui/styled-engine": {
-      "version": "6.4.8",
-      "resolved": "https://registry.npmmirror.com/@mui/styled-engine/-/styled-engine-6.4.8.tgz",
-      "integrity": "sha512-oyjx1b1FvUCI85ZMO4trrjNxGm90eLN3Ohy0AP/SqK5gWvRQg1677UjNf7t6iETOKAleHctJjuq0B3aXO2gtmw==",
+      "version": "6.4.6",
+      "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.6.tgz",
+      "integrity": "sha512-vSWYc9ZLX46be5gP+FCzWVn5rvDr4cXC5JBZwSIkYk9xbC7GeV+0kCvB8Q6XLFQJy+a62bbqtmdwS4Ghi9NBlQ==",
       "license": "MIT",
       "dependencies": {
         "@babel/runtime": "^7.26.0",
@@ -1346,16 +1337,16 @@
       }
     },
     "node_modules/@mui/system": {
-      "version": "6.4.8",
-      "resolved": "https://registry.npmmirror.com/@mui/system/-/system-6.4.8.tgz",
-      "integrity": "sha512-gV7iBHoqlsIenU2BP0wq14BefRoZcASZ/4LeyuQglayBl+DfLX5rEd3EYR3J409V2EZpR0NOM1LATAGlNk2cyA==",
+      "version": "6.4.7",
+      "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.7.tgz",
+      "integrity": "sha512-7wwc4++Ak6tGIooEVA9AY7FhH2p9fvBMORT4vNLMAysH3Yus/9B9RYMbrn3ANgsOyvT3Z7nE+SP8/+3FimQmcg==",
       "license": "MIT",
       "dependencies": {
         "@babel/runtime": "^7.26.0",
-        "@mui/private-theming": "^6.4.8",
-        "@mui/styled-engine": "^6.4.8",
-        "@mui/types": "~7.2.24",
-        "@mui/utils": "^6.4.8",
+        "@mui/private-theming": "^6.4.6",
+        "@mui/styled-engine": "^6.4.6",
+        "@mui/types": "^7.2.21",
+        "@mui/utils": "^6.4.6",
         "clsx": "^2.1.1",
         "csstype": "^3.1.3",
         "prop-types": "^15.8.1"
@@ -1386,13 +1377,13 @@
       }
     },
     "node_modules/@mui/system/node_modules/@mui/utils": {
-      "version": "6.4.8",
-      "resolved": "https://registry.npmmirror.com/@mui/utils/-/utils-6.4.8.tgz",
-      "integrity": "sha512-C86gfiZ5BfZ51KqzqoHi1WuuM2QdSKoFhbkZeAfQRB+jCc4YNhhj11UXFVMMsqBgZ+Zy8IHNJW3M9Wj/LOwRXQ==",
+      "version": "6.4.6",
+      "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.6.tgz",
+      "integrity": "sha512-43nZeE1pJF2anGafNydUcYFPtHwAqiBiauRtaMvurdrZI3YrUjHkAu43RBsxef7OFtJMXGiHFvq43kb7lig0sA==",
       "license": "MIT",
       "dependencies": {
         "@babel/runtime": "^7.26.0",
-        "@mui/types": "~7.2.24",
+        "@mui/types": "^7.2.21",
         "@types/prop-types": "^15.7.14",
         "clsx": "^2.1.1",
         "prop-types": "^15.8.1",
@@ -1417,14 +1408,14 @@
     },
     "node_modules/@mui/system/node_modules/react-is": {
       "version": "19.0.0",
-      "resolved": "https://registry.npmmirror.com/react-is/-/react-is-19.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz",
       "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==",
       "license": "MIT"
     },
     "node_modules/@mui/types": {
-      "version": "7.2.24",
-      "resolved": "https://registry.npmmirror.com/@mui/types/-/types-7.2.24.tgz",
-      "integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==",
+      "version": "7.2.21",
+      "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.21.tgz",
+      "integrity": "sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==",
       "license": "MIT",
       "peerDependencies": {
         "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
@@ -2315,8 +2306,7 @@
     "node_modules/@types/parse-json": {
       "version": "4.0.2",
       "resolved": "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.2.tgz",
-      "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
-      "license": "MIT"
+      "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="
     },
     "node_modules/@types/prop-types": {
       "version": "15.7.14",
@@ -2343,11 +2333,10 @@
       }
     },
     "node_modules/@types/react-transition-group": {
-      "version": "4.4.12",
-      "resolved": "https://registry.npmmirror.com/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
-      "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
-      "license": "MIT",
-      "peerDependencies": {
+      "version": "4.4.11",
+      "resolved": "https://registry.npmmirror.com/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
+      "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==",
+      "dependencies": {
         "@types/react": "*"
       }
     },
@@ -2356,13 +2345,6 @@
       "resolved": "https://registry.npmmirror.com/@types/semver/-/semver-7.5.8.tgz",
       "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
       "dev": true
-    },
-    "node_modules/@types/trusted-types": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
-      "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
-      "license": "MIT",
-      "optional": true
     },
     "node_modules/@types/unist": {
       "version": "2.0.11",
@@ -2795,10 +2777,9 @@
       "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
     },
     "node_modules/attr-accept": {
-      "version": "2.2.5",
-      "resolved": "https://registry.npmmirror.com/attr-accept/-/attr-accept-2.2.5.tgz",
-      "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==",
-      "license": "MIT",
+      "version": "2.2.2",
+      "resolved": "https://registry.npmmirror.com/attr-accept/-/attr-accept-2.2.2.tgz",
+      "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==",
       "engines": {
         "node": ">=4"
       }
@@ -2807,7 +2788,6 @@
       "version": "3.3.4",
       "resolved": "https://registry.npmmirror.com/autosuggest-highlight/-/autosuggest-highlight-3.3.4.tgz",
       "integrity": "sha512-j6RETBD2xYnrVcoV1S5R4t3WxOlWZKyDQjkwnggDPSjF5L4jV98ZltBpvPvbkM1HtoSe5o+bNrTHyjPbieGeYA==",
-      "license": "MIT",
       "dependencies": {
         "remove-accents": "^0.4.2"
       }
@@ -2841,7 +2821,6 @@
       "version": "3.1.0",
       "resolved": "https://registry.npmmirror.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
       "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
-      "license": "MIT",
       "dependencies": {
         "@babel/runtime": "^7.12.5",
         "cosmiconfig": "^7.0.0",
@@ -2853,20 +2832,16 @@
       }
     },
     "node_modules/babel-plugin-macros/node_modules/resolve": {
-      "version": "1.22.10",
-      "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.10.tgz",
-      "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
-      "license": "MIT",
+      "version": "1.22.8",
+      "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz",
+      "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
       "dependencies": {
-        "is-core-module": "^2.16.0",
+        "is-core-module": "^2.13.0",
         "path-parse": "^1.0.7",
         "supports-preserve-symlinks-flag": "^1.0.0"
       },
       "bin": {
         "resolve": "bin/resolve"
-      },
-      "engines": {
-        "node": ">= 0.4"
       },
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
@@ -3075,7 +3050,6 @@
       "version": "7.1.0",
       "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
       "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
-      "license": "MIT",
       "dependencies": {
         "@types/parse-json": "^4.0.0",
         "import-fresh": "^3.2.1",
@@ -3112,8 +3086,7 @@
     "node_modules/css-mediaquery": {
       "version": "0.1.2",
       "resolved": "https://registry.npmmirror.com/css-mediaquery/-/css-mediaquery-0.1.2.tgz",
-      "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==",
-      "license": "BSD"
+      "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q=="
     },
     "node_modules/csstype": {
       "version": "3.1.3",
@@ -3284,13 +3257,9 @@
       }
     },
     "node_modules/dompurify": {
-      "version": "3.2.4",
-      "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.2.4.tgz",
-      "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==",
-      "license": "(MPL-2.0 OR Apache-2.0)",
-      "optionalDependencies": {
-        "@types/trusted-types": "^2.0.7"
-      }
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-2.5.6.tgz",
+      "integrity": "sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ=="
     },
     "node_modules/earcut": {
       "version": "2.2.4",
@@ -3307,7 +3276,6 @@
       "version": "1.3.2",
       "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz",
       "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
-      "license": "MIT",
       "dependencies": {
         "is-arrayish": "^0.2.1"
       }
@@ -3945,22 +3913,20 @@
       }
     },
     "node_modules/file-selector": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmmirror.com/file-selector/-/file-selector-2.1.2.tgz",
-      "integrity": "sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==",
-      "license": "MIT",
+      "version": "0.6.0",
+      "resolved": "https://registry.npmmirror.com/file-selector/-/file-selector-0.6.0.tgz",
+      "integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==",
       "dependencies": {
-        "tslib": "^2.7.0"
+        "tslib": "^2.4.0"
       },
       "engines": {
         "node": ">= 12"
       }
     },
     "node_modules/file-selector/node_modules/tslib": {
-      "version": "2.8.1",
-      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
-      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
-      "license": "0BSD"
+      "version": "2.6.3",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
     },
     "node_modules/fill-range": {
       "version": "7.1.1",
@@ -3985,8 +3951,7 @@
     "node_modules/find-root": {
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/find-root/-/find-root-1.1.0.tgz",
-      "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
-      "license": "MIT"
+      "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
     },
     "node_modules/find-up": {
       "version": "5.0.0",
@@ -4416,6 +4381,11 @@
         "react-is": "^16.7.0"
       }
     },
+    "node_modules/hotscript": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmmirror.com/hotscript/-/hotscript-1.0.13.tgz",
+      "integrity": "sha512-C++tTF1GqkGYecL+2S1wJTfoH6APGAsbb7PAWQ3iVIwgG/EFseAfEVOKFgAFq4yK3+6j1EjUD4UQ9dRJHX/sSQ=="
+    },
     "node_modules/ignore": {
       "version": "5.3.2",
       "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz",
@@ -4529,8 +4499,7 @@
     "node_modules/is-arrayish": {
       "version": "0.2.1",
       "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz",
-      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
-      "license": "MIT"
+      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
     },
     "node_modules/is-async-function": {
       "version": "2.0.0",
@@ -4588,10 +4557,9 @@
       }
     },
     "node_modules/is-core-module": {
-      "version": "2.16.1",
-      "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz",
-      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
-      "license": "MIT",
+      "version": "2.15.1",
+      "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.15.1.tgz",
+      "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
       "dependencies": {
         "hasown": "^2.0.2"
       },
@@ -4930,12 +4898,6 @@
         "js-yaml": "bin/js-yaml.js"
       }
     },
-    "node_modules/jsbarcode": {
-      "version": "3.11.6",
-      "resolved": "https://registry.npmmirror.com/jsbarcode/-/jsbarcode-3.11.6.tgz",
-      "integrity": "sha512-G5TKGyKY1zJo0ZQKFM1IIMfy0nF2rs92BLlCz+cU4/TazIc4ZH+X1GYeDRt7TKjrYqmPfTjwTBkU/QnQlsYiuA==",
-      "license": "MIT"
-    },
     "node_modules/jsesc": {
       "version": "2.5.2",
       "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz",
@@ -4956,8 +4918,7 @@
     "node_modules/json-parse-even-better-errors": {
       "version": "2.3.1",
       "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
-      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
-      "license": "MIT"
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
     },
     "node_modules/json-schema-traverse": {
       "version": "0.4.1",
@@ -5031,8 +4992,7 @@
     "node_modules/lines-and-columns": {
       "version": "1.2.4",
       "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
-      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
-      "license": "MIT"
+      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
     },
     "node_modules/locate-path": {
       "version": "6.0.0",
@@ -5438,7 +5398,6 @@
       "version": "5.2.0",
       "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz",
       "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
-      "license": "MIT",
       "dependencies": {
         "@babel/code-frame": "^7.0.0",
         "error-ex": "^1.3.1",
@@ -5746,12 +5705,6 @@
         "ra-core": "^5.6.3"
       }
     },
-    "node_modules/ra-language-chinese": {
-      "version": "2.0.10",
-      "resolved": "https://registry.npmmirror.com/ra-language-chinese/-/ra-language-chinese-2.0.10.tgz",
-      "integrity": "sha512-k+X6XdkBEZnmpKIJZj9Lb77Lj8LCmterilJTj2ovp3i8/H/dLo9IujASfjFypjHnVUpN7Y63LT19kgPrS6+row==",
-      "license": "MIT"
-    },
     "node_modules/ra-language-english": {
       "version": "5.6.3",
       "resolved": "https://registry.npmjs.org/ra-language-english/-/ra-language-english-5.6.3.tgz",
@@ -5778,154 +5731,38 @@
       }
     },
     "node_modules/react-admin": {
-      "version": "5.6.3",
-      "resolved": "https://registry.npmmirror.com/react-admin/-/react-admin-5.6.3.tgz",
-      "integrity": "sha512-nZAlX1uRKgQKAQcOxMwugkjbDL7CPuU799lxoaxLK59O7AbkQl161uVqWLNUo4eaZRCpXCVqIe2an4lGlxs10g==",
-      "license": "MIT",
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/react-admin/-/react-admin-5.1.2.tgz",
+      "integrity": "sha512-f3L0XVEQrmMx5kbaApbE4GDJA5oSz9MPORlBD2ZHdVqcTJCfkbbDpR5McTT6Je6QRT8KSrOdWhcJQc3UTdHFyw==",
       "dependencies": {
-        "@emotion/react": "^11.14.0",
-        "@emotion/styled": "^11.14.0",
-        "@mui/icons-material": "^5.16.12 || ^6.0.0",
-        "@mui/material": "^5.16.12 || ^6.0.0",
-        "ra-core": "^5.6.3",
-        "ra-i18n-polyglot": "^5.6.3",
-        "ra-language-english": "^5.6.3",
-        "ra-ui-materialui": "^5.6.3",
-        "react-hook-form": "^7.53.0",
-        "react-router": "^6.28.1 || ^7.1.1",
-        "react-router-dom": "^6.28.1 || ^7.1.1"
+        "@emotion/react": "^11.4.1",
+        "@emotion/styled": "^11.3.0",
+        "@mui/icons-material": "^5.15.20",
+        "@mui/material": "^5.15.20",
+        "ra-core": "^5.1.2",
+        "ra-i18n-polyglot": "^5.1.2",
+        "ra-language-english": "^5.1.2",
+        "ra-ui-materialui": "^5.1.2",
+        "react-hook-form": "^7.52.0",
+        "react-router": "^6.22.0",
+        "react-router-dom": "^6.22.0"
       },
       "peerDependencies": {
         "react": "^18.0.0 || ^19.0.0",
         "react-dom": "^18.0.0 || ^19.0.0"
       }
     },
-    "node_modules/react-admin/node_modules/@mui/core-downloads-tracker": {
-      "version": "6.4.8",
-      "resolved": "https://registry.npmmirror.com/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.8.tgz",
-      "integrity": "sha512-vjP4+A1ybyCRhDZC7r5EPWu/gLseFZxaGyPdDl94vzVvk6Yj6gahdaqcjbhkaCrJjdZj90m3VioltWPAnWF/zw==",
-      "license": "MIT",
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/mui-org"
-      }
-    },
-    "node_modules/react-admin/node_modules/@mui/icons-material": {
-      "version": "6.4.8",
-      "resolved": "https://registry.npmmirror.com/@mui/icons-material/-/icons-material-6.4.8.tgz",
-      "integrity": "sha512-LKGWiLWRyoOw3dWxZQ+lV//mK+4DVTTAiLd2ljmJdD6XV0rDB8JFKjRD9nyn9cJAU5XgWnii7ZR3c93ttUnMKg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/runtime": "^7.26.0"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/mui-org"
-      },
-      "peerDependencies": {
-        "@mui/material": "^6.4.8",
-        "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
-        "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/react": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/react-admin/node_modules/@mui/material": {
-      "version": "6.4.8",
-      "resolved": "https://registry.npmmirror.com/@mui/material/-/material-6.4.8.tgz",
-      "integrity": "sha512-5S9UTjKZZBd9GfbcYh/nYfD9cv6OXmj5Y7NgKYfk7JcSoshp8/pW5zP4wecRiroBSZX8wcrywSgogpVNO+5W0Q==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/runtime": "^7.26.0",
-        "@mui/core-downloads-tracker": "^6.4.8",
-        "@mui/system": "^6.4.8",
-        "@mui/types": "~7.2.24",
-        "@mui/utils": "^6.4.8",
-        "@popperjs/core": "^2.11.8",
-        "@types/react-transition-group": "^4.4.12",
-        "clsx": "^2.1.1",
-        "csstype": "^3.1.3",
-        "prop-types": "^15.8.1",
-        "react-is": "^19.0.0",
-        "react-transition-group": "^4.4.5"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/mui-org"
-      },
-      "peerDependencies": {
-        "@emotion/react": "^11.5.0",
-        "@emotion/styled": "^11.3.0",
-        "@mui/material-pigment-css": "^6.4.8",
-        "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
-        "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
-        "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
-      },
-      "peerDependenciesMeta": {
-        "@emotion/react": {
-          "optional": true
-        },
-        "@emotion/styled": {
-          "optional": true
-        },
-        "@mui/material-pigment-css": {
-          "optional": true
-        },
-        "@types/react": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/react-admin/node_modules/@mui/utils": {
-      "version": "6.4.8",
-      "resolved": "https://registry.npmmirror.com/@mui/utils/-/utils-6.4.8.tgz",
-      "integrity": "sha512-C86gfiZ5BfZ51KqzqoHi1WuuM2QdSKoFhbkZeAfQRB+jCc4YNhhj11UXFVMMsqBgZ+Zy8IHNJW3M9Wj/LOwRXQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/runtime": "^7.26.0",
-        "@mui/types": "~7.2.24",
-        "@types/prop-types": "^15.7.14",
-        "clsx": "^2.1.1",
-        "prop-types": "^15.8.1",
-        "react-is": "^19.0.0"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/mui-org"
-      },
-      "peerDependencies": {
-        "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
-        "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/react": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/react-admin/node_modules/ra-ui-materialui": {
-      "version": "5.6.3",
-      "resolved": "https://registry.npmmirror.com/ra-ui-materialui/-/ra-ui-materialui-5.6.3.tgz",
-      "integrity": "sha512-3KOCo0JWBJ5BeqVb8g1cdnw00+GMnpI7jlX1VqX7YIyDT3TwDbFx1sDGUOvNiLrN7qZA5dIrZWfdYlutjZT/2Q==",
-      "license": "MIT",
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/ra-ui-materialui/-/ra-ui-materialui-5.1.2.tgz",
+      "integrity": "sha512-hhR5+NCC5tDNB6WtPl2sY7mKAqfs4A0S+x2Kh/GsYYxs7nFIRFIBMu7UE40vpVJqFrBCc2fyVB/3d9D2eEdoZA==",
       "dependencies": {
-        "@tanstack/react-query": "^5.21.7",
+        "@tanstack/react-query": "^5.8.4",
         "autosuggest-highlight": "^3.1.1",
         "clsx": "^2.1.1",
         "css-mediaquery": "^0.1.2",
-        "dompurify": "^3.2.4",
+        "dompurify": "^2.4.3",
+        "hotscript": "^1.0.12",
         "inflection": "^3.0.0",
         "jsonexport": "^3.2.0",
         "lodash": "~4.17.5",
@@ -5935,36 +5772,22 @@
         "react-transition-group": "^4.4.5"
       },
       "peerDependencies": {
-        "@mui/icons-material": "^5.16.12 || ^6.0.0",
-        "@mui/material": "^5.16.12 || ^6.0.0",
-        "@mui/utils": "^5.15.20 || ^6.0.0",
+        "@mui/icons-material": "^5.15.20",
+        "@mui/material": "^5.15.20",
         "ra-core": "^5.0.0",
         "react": "^18.0.0 || ^19.0.0",
         "react-dom": "^18.0.0 || ^19.0.0",
         "react-hook-form": "*",
-        "react-is": "^18.0.0 || ^19.0.0",
-        "react-router": "^6.28.1 || ^7.1.1",
-        "react-router-dom": "^6.28.1 || ^7.1.1"
+        "react-is": "^18.0.0",
+        "react-router": "^6.22.0",
+        "react-router-dom": "^6.22.0"
       }
     },
     "node_modules/react-admin/node_modules/react-is": {
-      "version": "19.0.0",
-      "resolved": "https://registry.npmmirror.com/react-is/-/react-is-19.0.0.tgz",
-      "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==",
-      "license": "MIT"
-    },
-    "node_modules/react-barcode": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmmirror.com/react-barcode/-/react-barcode-1.6.1.tgz",
-      "integrity": "sha512-pc4ftnO5syHa/UjCruEeRsomlhoxKSugIgTA8T4dH0fvc89UMHL+/1Sp25IAphqG44pJkE5hMXhv89iS09jQyw==",
-      "license": "ISC",
-      "dependencies": {
-        "jsbarcode": "^3.8.0",
-        "prop-types": "^15.6.2"
-      },
-      "peerDependencies": {
-        "react": "16 - 19"
-      }
+      "version": "18.3.1",
+      "resolved": "https://registry.npmmirror.com/react-is/-/react-is-18.3.1.tgz",
+      "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+      "peer": true
     },
     "node_modules/react-dom": {
       "version": "18.3.1",
@@ -5979,13 +5802,12 @@
       }
     },
     "node_modules/react-dropzone": {
-      "version": "14.3.8",
-      "resolved": "https://registry.npmmirror.com/react-dropzone/-/react-dropzone-14.3.8.tgz",
-      "integrity": "sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug==",
-      "license": "MIT",
+      "version": "14.2.3",
+      "resolved": "https://registry.npmmirror.com/react-dropzone/-/react-dropzone-14.2.3.tgz",
+      "integrity": "sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==",
       "dependencies": {
-        "attr-accept": "^2.2.4",
-        "file-selector": "^2.1.0",
+        "attr-accept": "^2.2.2",
+        "file-selector": "^0.6.0",
         "prop-types": "^15.8.1"
       },
       "engines": {
@@ -6125,15 +5947,6 @@
         "react": ">= 0.14.0"
       }
     },
-    "node_modules/react-to-print": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmmirror.com/react-to-print/-/react-to-print-3.0.5.tgz",
-      "integrity": "sha512-Z15MwMOzYCHWi26CZeFNwflAg7Nr8uWD6FTj+EkfIOjYyjr0MXGbI0c7rF4Fgrbj3XG9hFndb1ourxpPz2RAiA==",
-      "license": "MIT",
-      "peerDependencies": {
-        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ~19"
-      }
-    },
     "node_modules/react-transition-group": {
       "version": "4.4.5",
       "resolved": "https://registry.npmmirror.com/react-transition-group/-/react-transition-group-4.4.5.tgz",
@@ -6226,8 +6039,7 @@
     "node_modules/remove-accents": {
       "version": "0.4.4",
       "resolved": "https://registry.npmmirror.com/remove-accents/-/remove-accents-0.4.4.tgz",
-      "integrity": "sha512-EpFcOa/ISetVHEXqu+VwI96KZBmq+a8LJnGkaeFw45epGlxIZz5dhEEnNZMsQXgORu3qaMoLX4qJCzOik6ytAg==",
-      "license": "MIT"
+      "integrity": "sha512-EpFcOa/ISetVHEXqu+VwI96KZBmq+a8LJnGkaeFw45epGlxIZz5dhEEnNZMsQXgORu3qaMoLX4qJCzOik6ytAg=="
     },
     "node_modules/reselect": {
       "version": "5.1.1",
@@ -6481,7 +6293,6 @@
       "version": "0.5.7",
       "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz",
       "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
-      "license": "BSD-3-Clause",
       "engines": {
         "node": ">=0.10.0"
       }
@@ -7115,7 +6926,6 @@
       "version": "1.10.2",
       "resolved": "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz",
       "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
-      "license": "ISC",
       "engines": {
         "node": ">= 6"
       }
diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index cb54b18..fe02573 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -129,6 +129,8 @@
         loc: 'Loc',
         locType: 'LocType',
         locArea: 'locArea',
+        LocAreaMat: 'LocAreaMat',
+        locAreaMatRela: 'LocAreaMatRela',
         container: 'Container',
         contract: 'Contract',
         qlyInspect: 'QlyInspect',
@@ -367,6 +369,18 @@
                 name: "name",
                 code: "code",
                 areaId: "areaId",
+                locId: "locId",
+            },
+            locAreaMat: {
+                code: "code",
+                depict: "depict",
+            },
+            locAreaMatRela: {
+                areaId: "areaId",
+                code: "code",
+                matnrId: "matnrId",
+                groupId: "groupId",
+                locTypeId: "locTypeId",
                 locId: "locId",
             },
             container: {
@@ -627,7 +641,9 @@
         locInit: 'loc init',
         batch: 'batch',
         confirm: 'confirm',
-        subzone: 'subzone'
+        subzone: 'subzone',
+        bindmatnr: 'bind matnr',
+        bindloc: 'bind loc',
     },
 };
 
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index 2f2f96b..f6dd347 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -129,6 +129,8 @@
         loc: '搴撲綅',
         locType: '搴撲綅绫诲瀷',
         locArea: '閫昏緫鍒嗗尯',
+        locAreaMat: '閫昏緫鍒嗗尯',
+        locAreaMatRela: '搴撳尯鐗╂枡鍏崇郴',
         container: '瀹瑰櫒绠$悊',
         contract: '鍚堝悓淇℃伅',
         qlyInspect: '璐ㄦ淇℃伅',
@@ -299,7 +301,7 @@
             warehouseAreas: {
                 uuid: "鍞竴缂栫爜",
                 name: "鍚嶇О",
-                wareId: "浠撳簱",
+                wareId: "鎵�灞炰粨搴�",
                 code: "缂栫爜",
                 shipperId: "璐т富",
                 supplierId: "渚涘簲鍟�",
@@ -367,6 +369,18 @@
                 name: "鍚嶇О",
                 code: "缂栫爜",
                 areaId: "搴撳尯",
+                locId: "搴撲綅",
+            },
+            locAreaMat: {
+                code: "閫昏緫缂栫爜",
+                depict: "閫昏緫鎻忚堪",
+            },
+            locAreaMatRela: {
+                areaId: "搴撳尯",
+                code: "缂栫爜",
+                matnrId: "鐗╂枡",
+                groupId: "鐗╂枡鍒嗙粍",
+                locTypeId: "搴撲綅绫诲瀷",
                 locId: "搴撲綅",
             },
             container: {
@@ -629,7 +643,9 @@
         locInit: '聽搴撲綅鍒濆鍖�',
         batch: '鎵归噺鎿嶄綔',
         confirm: '纭',
-        subzone: '缁戝畾鍒嗗尯'
+        subzone: '缁戝畾鍒嗗尯',
+        bindmatnr: '缁戝畾鐗╂枡',
+        bindloc: '缁戝畾搴撲綅',
     },
 };
 
diff --git a/rsf-admin/src/page/ResourceContent.js b/rsf-admin/src/page/ResourceContent.js
index b5b46b3..fb93236 100644
--- a/rsf-admin/src/page/ResourceContent.js
+++ b/rsf-admin/src/page/ResourceContent.js
@@ -27,6 +27,8 @@
 import companys from './basicInfo/companys';
 import locType from './basicInfo/locType';
 import locArea from './basicInfo//locArea';
+import locAreaMatRela from './basicInfo/locAreaMatRela';
+import locAreaMat from './basicInfo/locAreaMat';
 import serialRuleItem from './system/serialRuleItem';
 import serialRule from './system/serialRule';
 import whMat from './basicInfo/whMat';
@@ -106,6 +108,11 @@
             return locType;
         case 'locArea':
             return locArea;
+        case 'locAreaMatRela':
+            return locAreaMatRela;
+        case 'locAreaMat':
+            return locAreaMat;
+
 
         default:
             return {
diff --git a/rsf-admin/src/page/asnOrderItem/AsnOrderItemList.jsx b/rsf-admin/src/page/asnOrderItem/AsnOrderItemList.jsx
index c9a8366..c159ad9 100644
--- a/rsf-admin/src/page/asnOrderItem/AsnOrderItemList.jsx
+++ b/rsf-admin/src/page/asnOrderItem/AsnOrderItemList.jsx
@@ -142,8 +142,6 @@
             preferenceKey='asnOrderItem'
             bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
             rowClick={(id, resource, record) => false}
-            expand={() => <AsnOrderItemPanel />}
-            expandSingle={true}
             omit={['id', 'createTime', 'createBy', 'memo']}
           >
             <NumberField source="id" />
diff --git a/rsf-admin/src/page/basicInfo/companys/CompanysEdit.jsx b/rsf-admin/src/page/basicInfo/companys/CompanysEdit.jsx
index 72e465e..741ecf7 100644
--- a/rsf-admin/src/page/basicInfo/companys/CompanysEdit.jsx
+++ b/rsf-admin/src/page/basicInfo/companys/CompanysEdit.jsx
@@ -50,6 +50,7 @@
             mutationMode={EDIT_MODE}
             actions={<CustomerTopToolBar />}
             aside={<EditBaseAside />}
+            title={"menu.companys"}
         >
             <SimpleForm
                 shouldUnregister
diff --git a/rsf-admin/src/page/basicInfo/loc/BindModal.jsx b/rsf-admin/src/page/basicInfo/loc/BindModal.jsx
new file mode 100644
index 0000000..04cd607
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/loc/BindModal.jsx
@@ -0,0 +1,197 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    CreateBase,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SaveButton,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    Toolbar,
+    required,
+    useDataProvider,
+    useNotify,
+    Form,
+    useCreateController,
+    useListContext,
+    useRefresh,
+    SelectArrayInput
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    Grid,
+    TextField,
+    Box,
+    Button,
+    Paper,
+    TableContainer,
+    Table,
+    TableHead,
+    TableBody,
+    TableRow,
+    TableCell,
+    Tooltip,
+    IconButton,
+    styled,
+
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import DictionarySelect from "../../components/DictionarySelect";
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import SaveIcon from '@mui/icons-material/Save';
+import request from '@/utils/request';
+import { Add, Edit, Delete } from '@mui/icons-material';
+import _ from 'lodash';
+import { DataGrid } from '@mui/x-data-grid';
+import StatusSelectInput from "../../components/StatusSelectInput";
+import TreeSelectInput from "@/page/components/TreeSelectInput";
+const MatnrModal = ({ open, setOpen }) => {
+    const refresh = useRefresh();
+    const translate = useTranslate();
+
+
+    const notify = useNotify();
+
+    const [formData, setFormData] = useState({
+        areaId: null,
+        groupId: null,
+        matnrId: null,
+    });
+
+    const { selectedIds, onUnselectItems } = useListContext();
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+            reset()
+            refresh();
+            onUnselectItems()
+        }
+    };
+
+    const reset = () => {
+        setFormData({
+            areaId: null,
+            groupId: null,
+            matnrId: null,
+        })
+    }
+
+    const handleReset = (e) => {
+        e.preventDefault();
+    };
+
+    const handleChange = (value, name) => {
+        setFormData((prevData) => ({
+            ...prevData,
+            [name]: value
+        }));
+        refresh()
+    };
+
+    const removeEmptyKeys = (obj) => {
+        return _.pickBy(obj, (value) => {
+            if (_.isObject(value)) {
+                const newObj = removeEmptyKeys(value);
+                return !_.isEmpty(newObj);
+            }
+            return !_.isNil(value) && (_.isNumber(value) ? value !== 0 : !_.isEmpty(value));
+        });
+    }
+
+    const handleSubmit = async () => {
+        const parmas = {
+            locId: selectedIds,
+            areaId: formData.areaId,
+            matnrId: formData.matnrId,
+        }
+
+        const res = await request.post(`/locAreaMatRela/matnr/bind`, parmas);
+        if (res?.data?.code === 200) {
+            handleClose()
+
+        } else {
+            notify(res.data.msg);
+        }
+
+
+    }
+
+    const [groupId, setGroupId] = useState();
+
+    const warehouseChange = (e) => {
+        setGroupId(e.target.value)
+    }
+
+    return (
+        <Dialog open={open} maxWidth="md" fullWidth>
+            <Form onSubmit={handleSubmit}>
+                <DialogCloseButton onClose={handleClose} />
+                <DialogTitle>{translate('toolbar.bindmatnr')}</DialogTitle>
+                <DialogContent sx={{ mt: 2 }}>
+                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
+                        <Grid container spacing={2}>
+                            <Grid item xs={4}>
+                                <ReferenceInput
+                                    source="areaId"
+                                    reference="warehouseAreas"
+                                >
+                                    <AutocompleteInput
+                                        label="table.field.loc.areaId"
+                                        optionText="name"
+                                        onChange={(value) => handleChange(value, 'areaId')}
+                                        value={formData.areaId}
+                                        validate={required()}
+                                        filterToQuery={(val) => ({ name: val })}
+                                    />
+                                </ReferenceInput>
+
+                            </Grid>
+
+                            <Grid item xs={4}>
+                                <TreeSelectInput
+                                    label="table.field.locAreaMatRela.groupId"
+                                    resource={'matnrGroup'}
+                                    source="groupId"
+                                    value={formData.groupId}
+                                    onChange={(e) => handleChange(e.target.value, 'groupId')}
+                                />
+                            </Grid>
+
+
+                            <Grid item xs={4}>
+                                <ReferenceArrayInput source="matnrId" reference="matnr" filter={{ groupId: formData.groupId }}>
+                                    <SelectArrayInput
+                                        label="table.field.locAreaMatRela.matnrId"
+                                        validate={required()}
+                                        value={formData.matnrId}
+                                        onChange={(e) => handleChange(e.target.value, 'matnrId')}
+                                    />
+                                </ReferenceArrayInput>
+
+                            </Grid>
+
+                        </Grid>
+
+                    </Box>
+                </DialogContent>
+                <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                    <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}>
+                        <Button type="submit" variant="contained" startIcon={<SaveIcon />}>
+                            {translate('toolbar.confirm')}
+                        </Button>
+                    </Box>
+                </DialogActions>
+            </Form>
+        </Dialog>
+    );
+}
+
+export default MatnrModal;
\ No newline at end of file
diff --git a/rsf-admin/src/page/basicInfo/loc/InitModal.jsx b/rsf-admin/src/page/basicInfo/loc/InitModal.jsx
index 16a287a..931b943 100644
--- a/rsf-admin/src/page/basicInfo/loc/InitModal.jsx
+++ b/rsf-admin/src/page/basicInfo/loc/InitModal.jsx
@@ -153,7 +153,7 @@
 
                             <Grid item xs={4}>
                                 <ReferenceArrayInput source="typeIds" reference="locType" >
-                                    <SelectArrayInput label="table.field.loc.type" onChange={(e) => handleChange(e.target.value, 'typeIds')} />
+                                    <SelectArrayInput label="table.field.loc.type" onChange={(e) => handleChange(e.target.value, 'typeIds')} validate={[required()]} />
                                 </ReferenceArrayInput>
                             </Grid>
 
diff --git a/rsf-admin/src/page/basicInfo/loc/LocCreate.jsx b/rsf-admin/src/page/basicInfo/loc/LocCreate.jsx
index e5eb67a..23465f9 100644
--- a/rsf-admin/src/page/basicInfo/loc/LocCreate.jsx
+++ b/rsf-admin/src/page/basicInfo/loc/LocCreate.jsx
@@ -270,6 +270,7 @@
                                         label={translate("table.field.loc.useStatus")}
                                         name="useStatus"
                                         size="small"
+                                        validate={[required()]}
                                         dictTypeCode="sys_loc_use_stas"
                                     />
                                     {/* <ReferenceInput
diff --git a/rsf-admin/src/page/basicInfo/loc/LocEdit.jsx b/rsf-admin/src/page/basicInfo/loc/LocEdit.jsx
index 5c640c5..5b1182e 100644
--- a/rsf-admin/src/page/basicInfo/loc/LocEdit.jsx
+++ b/rsf-admin/src/page/basicInfo/loc/LocEdit.jsx
@@ -59,6 +59,7 @@
             mutationMode={EDIT_MODE}
             actions={<CustomerTopToolBar />}
             aside={<EditBaseAside />}
+            title={"menu.loc"}
         >
             <SimpleForm
                 shouldUnregister
@@ -177,6 +178,7 @@
                                 <DictionarySelect
                                     label={translate("table.field.loc.useStatus")}
                                     name="useStatus"
+                                    validate={[required()]}
                                     size="small"
                                     dictTypeCode="sys_loc_use_stas"
                                 />
diff --git a/rsf-admin/src/page/basicInfo/loc/LocList.jsx b/rsf-admin/src/page/basicInfo/loc/LocList.jsx
index d07243d..449dc0f 100644
--- a/rsf-admin/src/page/basicInfo/loc/LocList.jsx
+++ b/rsf-admin/src/page/basicInfo/loc/LocList.jsx
@@ -38,7 +38,7 @@
 import { Box, Typography, Card, Stack } from '@mui/material';
 import { styled } from '@mui/material/styles';
 import LocCreate from "./LocCreate";
-import LocPanel from "./LocPanel";
+import BindModal from "./BindModal";
 import EmptyData from "../../components/EmptyData";
 import DynamicField from "../../components/DynamicField";
 import MyCreateButton from "../../components/MyCreateButton";
@@ -54,7 +54,7 @@
 import EditIcon from '@mui/icons-material/Edit';
 import request from '@/utils/request';
 import DiscountIcon from '@mui/icons-material/Discount';
-import { textAlign } from "@mui/system";
+import LinkIcon from '@mui/icons-material/Link';
 
 const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
     '& .css-1vooibu-MuiSvgIcon-root': {
@@ -70,14 +70,17 @@
     },
     '& .RaDatagrid-headerCell': {
         textAlign: 'left'
+    },
+    '& .RaDatagrid-rowCell': {
+        textAlign: 'left'
     }
 }));
 
 const filters = [
     <SearchInput source="condition" alwaysOn />,
 
-    <NumberField source="warehouseId$" label="table.field.loc.warehouseId" />,
-    <NumberField source="areaId$" label="table.field.loc.areaId" />,
+    <TextInput source="warehouseId$" label="table.field.loc.warehouseId" />,
+    <TextInput source="areaId$" label="table.field.loc.areaId" />,
     <TextInput source="code" label="table.field.loc.code" />,
     <TextInput source="type" label="table.field.loc.type" />,
     <TextInput source="name" label="table.field.loc.name" />,
@@ -148,6 +151,7 @@
                     bulkActionButtons={
                         <>
                             <BatchButton />
+                            <BindButton />
                             <SubzoneButton />
                             <BulkDeleteButton />
                         </>
@@ -157,9 +161,9 @@
                 >
                     <NumberField source="id" />
                     <NumberField source="warehouseId$" label="table.field.loc.warehouseId" />
-                    <NumberField source="areaId$" label="table.field.loc.areaId" align="left" />
-                    <TextField source="code" label="table.field.loc.code" align="left" />
-                    <TextField source="typeIds$" label="table.field.loc.type" align="left" />
+                    <NumberField source="areaId$" label="table.field.loc.areaId" />
+                    <TextField source="code" label="table.field.loc.code" />
+                    <TextField source="typeIds$" label="table.field.loc.type" />
                     {/* <TextField source="name" label="table.field.loc.name" /> */}
                     {/* <NumberField source="flagLogic" label="table.field.loc.flagLogic" />
                     <TextField source="fucAtrrs" label="table.field.loc.fucAtrrs" />
@@ -282,4 +286,27 @@
         </>
 
     )
+}
+
+const BindButton = () => {
+    const record = useRecordContext();
+    const notify = useNotify();
+    const refresh = useRefresh();
+
+
+    const [createDialog, setCreateDialog] = useState(false);
+
+    return (
+        <>
+            <Button onClick={() => setCreateDialog(true)} label={"toolbar.bindmatnr"}>
+                <LinkIcon />
+            </Button>
+
+            <BindModal
+                open={createDialog}
+                setOpen={setCreateDialog}
+            />
+        </>
+
+    )
 }
\ No newline at end of file
diff --git a/rsf-admin/src/page/basicInfo/locArea/LocAreaCreate.jsx b/rsf-admin/src/page/basicInfo/locArea/LocAreaCreate.jsx
index 38ac67a..363386b 100644
--- a/rsf-admin/src/page/basicInfo/locArea/LocAreaCreate.jsx
+++ b/rsf-admin/src/page/basicInfo/locArea/LocAreaCreate.jsx
@@ -88,6 +88,7 @@
                                     <TextInput
                                         label="table.field.locArea.name"
                                         source="name"
+                                        validate={[required()]}
                                         parse={v => v}
                                         autoFocus
                                     />
@@ -107,6 +108,7 @@
                                         <AutocompleteInput
                                             label="table.field.locArea.areaId"
                                             optionText="name"
+                                            validate={[required()]}
                                             filterToQuery={(val) => ({ name: val })}
                                         />
                                     </ReferenceInput>
diff --git a/rsf-admin/src/page/basicInfo/locArea/LocAreaEdit.jsx b/rsf-admin/src/page/basicInfo/locArea/LocAreaEdit.jsx
index afd0a4c..8e356d2 100644
--- a/rsf-admin/src/page/basicInfo/locArea/LocAreaEdit.jsx
+++ b/rsf-admin/src/page/basicInfo/locArea/LocAreaEdit.jsx
@@ -49,6 +49,7 @@
             mutationMode={EDIT_MODE}
             actions={<CustomerTopToolBar />}
             aside={<EditBaseAside />}
+            title={"menu.locArea"}
         >
             <SimpleForm
                 shouldUnregister
@@ -67,6 +68,7 @@
                             <TextInput
                                 label="table.field.locArea.name"
                                 source="name"
+                                validate={[required()]}
                                 parse={v => v}
                                 autoFocus
                             />
@@ -86,6 +88,7 @@
                                 <AutocompleteInput
                                     label="table.field.locArea.areaId"
                                     optionText="name"
+                                    validate={[required()]}
                                     filterToQuery={(val) => ({ name: val })}
                                 />
                             </ReferenceInput>
diff --git a/rsf-admin/src/page/basicInfo/locArea/LocAreaList.jsx b/rsf-admin/src/page/basicInfo/locArea/LocAreaList.jsx
index 9f92799..faacd4e 100644
--- a/rsf-admin/src/page/basicInfo/locArea/LocAreaList.jsx
+++ b/rsf-admin/src/page/basicInfo/locArea/LocAreaList.jsx
@@ -115,8 +115,6 @@
                     preferenceKey='locArea'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <LocAreaPanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'createBy', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/BindLocModal.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/BindLocModal.jsx
new file mode 100644
index 0000000..07f22b4
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMat/BindLocModal.jsx
@@ -0,0 +1,220 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    CreateBase,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SaveButton,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    Toolbar,
+    required,
+    useDataProvider,
+    useNotify,
+    Form,
+    useCreateController,
+    useListContext,
+    useRefresh,
+    SelectArrayInput,
+    useRecordContext,
+
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    Grid,
+    TextField,
+    Box,
+    Button,
+    Paper,
+    TableContainer,
+    Table,
+    TableHead,
+    TableBody,
+    TableRow,
+    TableCell,
+    Tooltip,
+    IconButton,
+    styled,
+
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import DictionarySelect from "../../components/DictionarySelect";
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import SaveIcon from '@mui/icons-material/Save';
+import request from '@/utils/request';
+import { Add, Edit, Delete } from '@mui/icons-material';
+import _ from 'lodash';
+import { DataGrid } from '@mui/x-data-grid';
+import StatusSelectInput from "../../components/StatusSelectInput";
+import TreeSelectInput from "@/page/components/TreeSelectInput";
+const BindMatnrModal = ({ open, setOpen, reload }) => {
+    const refresh = useRefresh();
+    const translate = useTranslate();
+    const record = useRecordContext();
+
+    const notify = useNotify();
+
+    const [formData, setFormData] = useState({
+        areaId: null,
+        warehouseId: null,
+        matnrId: null,
+        typeId: null,
+    });
+
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+            reset()
+        }
+    };
+
+    const reset = () => {
+        setFormData({
+            areaId: null,
+            matnrId: null,
+            warehouseId: null,
+            typeId: null,
+        })
+    }
+
+
+    const handleChange = (value, name) => {
+        setFormData((prevData) => ({
+            ...prevData,
+            [name]: value
+        }));
+        refresh()
+    };
+
+    const removeEmptyKeys = (obj) => {
+        return _.pickBy(obj, (value) => {
+            if (_.isObject(value)) {
+                const newObj = removeEmptyKeys(value);
+                return !_.isEmpty(newObj);
+            }
+            return !_.isNil(value) && (_.isNumber(value) ? value !== 0 : !_.isEmpty(value));
+        });
+    }
+
+    const handleSubmit = async () => {
+        const parmas = {
+            areaMatId: record.id,
+            matnrId: formData.matnrId,
+            areaId: formData.areaId,
+            warehouseId: formData.warehouseId,
+            typeId: formData.typeId,
+        }
+
+
+        const res = await request.post(`/locAreaMatRela/matnr/bind`, parmas);
+        if (res?.data?.code === 200) {
+            handleClose()
+            reload()
+
+        } else {
+            notify(res.data.msg);
+        }
+    }
+
+    const [groupId, setGroupId] = useState();
+
+    const warehouseChange = (e) => {
+        setGroupId(e.target.value)
+    }
+
+    return (
+        <Dialog open={open} maxWidth="md" fullWidth>
+            <Form onSubmit={handleSubmit}>
+                <DialogCloseButton onClose={handleClose} />
+                <DialogTitle>{translate('toolbar.bindmatnr')}</DialogTitle>
+                <DialogContent sx={{ mt: 2 }}>
+                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
+                        <Grid container spacing={2}>
+                            <Grid item xs={4}>
+                                <ReferenceInput
+                                    source="warehouseId"
+                                    reference="warehouse"
+                                >
+                                    <AutocompleteInput
+                                        label="table.field.loc.warehouseId"
+                                        optionText="name"
+                                        onChange={(value) => handleChange(value, 'warehouseId')}
+                                        value={formData.warehouseId}
+                                        validate={required()}
+                                        filterToQuery={(val) => ({ name: val })}
+                                    />
+                                </ReferenceInput>
+
+                            </Grid>
+
+                            <Grid item xs={4}>
+                                <ReferenceInput
+                                    source="areaId"
+                                    reference="warehouseAreas"
+                                >
+                                    <AutocompleteInput
+                                        label="table.field.loc.areaId"
+                                        optionText="name"
+                                        onChange={(value) => handleChange(value, 'areaId')}
+                                        value={formData.areaId}
+                                        validate={required()}
+                                        filterToQuery={(val) => ({ name: val })}
+                                    />
+                                </ReferenceInput>
+
+                            </Grid>
+
+                            <Grid item xs={4}>
+                                <ReferenceArrayInput source="typeId" reference="locType" >
+                                    <SelectArrayInput
+                                        label="table.field.locAreaMatRela.locTypeId"
+                                        validate={required()}
+                                        optionText={'name'}
+                                        value={formData.typeId}
+                                        onChange={(e) => handleChange(e.target.value, 'typeId')}
+                                    />
+                                </ReferenceArrayInput>
+
+                            </Grid>
+
+
+                            <Grid item xs={4}>
+                                <ReferenceArrayInput source="matnrId" reference="matnr" filter={{ groupId: formData.groupId }}>
+                                    <SelectArrayInput
+                                        label="table.field.locAreaMatRela.matnrId"
+                                        validate={required()}
+                                        value={formData.matnrId}
+                                        onChange={(e) => handleChange(e.target.value, 'matnrId')}
+                                    />
+                                </ReferenceArrayInput>
+                            </Grid>
+
+
+
+
+
+                        </Grid>
+
+                    </Box>
+                </DialogContent>
+                <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                    <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}>
+                        <Button type="submit" variant="contained" startIcon={<SaveIcon />}>
+                            {translate('toolbar.confirm')}
+                        </Button>
+                    </Box>
+                </DialogActions>
+            </Form>
+        </Dialog>
+    );
+}
+
+export default BindMatnrModal;
\ No newline at end of file
diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/BindMatnrModal.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/BindMatnrModal.jsx
new file mode 100644
index 0000000..9523f61
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMat/BindMatnrModal.jsx
@@ -0,0 +1,216 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    CreateBase,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SaveButton,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    Toolbar,
+    required,
+    useDataProvider,
+    useNotify,
+    Form,
+    useCreateController,
+    useListContext,
+    useRefresh,
+    SelectArrayInput,
+    useRecordContext,
+
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    Grid,
+    TextField,
+    Box,
+    Button,
+    Paper,
+    TableContainer,
+    Table,
+    TableHead,
+    TableBody,
+    TableRow,
+    TableCell,
+    Tooltip,
+    IconButton,
+    styled,
+
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import DictionarySelect from "../../components/DictionarySelect";
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import SaveIcon from '@mui/icons-material/Save';
+import request from '@/utils/request';
+import { Add, Edit, Delete } from '@mui/icons-material';
+import _ from 'lodash';
+import { DataGrid } from '@mui/x-data-grid';
+import StatusSelectInput from "../../components/StatusSelectInput";
+import TreeSelectInput from "@/page/components/TreeSelectInput";
+const BindMatnrModal = ({ open, setOpen, reload }) => {
+    const refresh = useRefresh();
+    const translate = useTranslate();
+    const record = useRecordContext();
+
+    const notify = useNotify();
+
+    const [formData, setFormData] = useState({
+        areaId: null,
+        warehouseId: null,
+        groupId: null,
+        locId: null,
+    });
+
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+            reset()
+        }
+    };
+
+    const reset = () => {
+        setFormData({
+            areaId: null,
+            warehouseId: null,
+            groupId: null,
+            locId: null,
+        })
+    }
+
+
+    const handleChange = (value, name) => {
+        setFormData((prevData) => ({
+            ...prevData,
+            [name]: value
+        }));
+        refresh()
+    };
+
+    const removeEmptyKeys = (obj) => {
+        return _.pickBy(obj, (value) => {
+            if (_.isObject(value)) {
+                const newObj = removeEmptyKeys(value);
+                return !_.isEmpty(newObj);
+            }
+            return !_.isNil(value) && (_.isNumber(value) ? value !== 0 : !_.isEmpty(value));
+        });
+    }
+
+    const handleSubmit = async () => {
+        const parmas = {
+            areaMatId: record.id,
+            groupId: [formData.groupId],
+            areaId: formData.areaId,
+            warehouseId: formData.warehouseId,
+            locId: formData.locId,
+        }
+
+
+        const res = await request.post(`/locAreaMatRela/matnr/bind`, parmas);
+        if (res?.data?.code === 200) {
+            handleClose()
+            reload()
+
+        } else {
+            notify(res.data.msg);
+        }
+    }
+
+    const [groupId, setGroupId] = useState();
+
+    const warehouseChange = (e) => {
+        setGroupId(e.target.value)
+    }
+
+    return (
+        <Dialog open={open} maxWidth="md" fullWidth>
+            <Form onSubmit={handleSubmit}>
+                <DialogCloseButton onClose={handleClose} />
+                <DialogTitle>{translate('toolbar.bindloc')}</DialogTitle>
+                <DialogContent sx={{ mt: 2 }}>
+                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
+                        <Grid container spacing={2}>
+                            <Grid item xs={4}>
+                                <ReferenceInput
+                                    source="warehouseId"
+                                    reference="warehouse"
+                                >
+                                    <AutocompleteInput
+                                        label="table.field.loc.warehouseId"
+                                        optionText="name"
+                                        onChange={(value) => handleChange(value, 'warehouseId')}
+                                        value={formData.warehouseId}
+                                        validate={required()}
+                                        filterToQuery={(val) => ({ name: val })}
+                                    />
+                                </ReferenceInput>
+                            </Grid>
+
+                            <Grid item xs={4}>
+                                <ReferenceInput
+                                    source="areaId"
+                                    reference="warehouseAreas"
+                                >
+                                    <AutocompleteInput
+                                        label="table.field.loc.areaId"
+                                        optionText="name"
+                                        onChange={(value) => handleChange(value, 'areaId')}
+                                        value={formData.areaId}
+                                        validate={required()}
+                                        filterToQuery={(val) => ({ name: val })}
+                                    />
+                                </ReferenceInput>
+
+                            </Grid>
+
+                            <Grid item xs={4}>
+                                <TreeSelectInput
+                                    label="table.field.locAreaMatRela.groupId"
+                                    resource={'matnrGroup'}
+                                    source="groupId"
+                                    value={formData.groupId}
+                                    onChange={(e) => handleChange(e.target.value, 'groupId')}
+                                />
+                            </Grid>
+
+
+
+
+                            <Grid item xs={4}>
+                                <ReferenceArrayInput source="locId" reference="loc" >
+                                    <SelectArrayInput
+                                        label="table.field.locAreaMatRela.locId"
+                                        validate={required()}
+                                        optionText={'code'}
+                                        value={formData.locId}
+                                        onChange={(e) => handleChange(e.target.value, 'locId')}
+                                    />
+                                </ReferenceArrayInput>
+
+                            </Grid>
+
+                        </Grid>
+
+                    </Box>
+                </DialogContent>
+                <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                    <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}>
+                        <Button type="submit" variant="contained" startIcon={<SaveIcon />}>
+                            {translate('toolbar.confirm')}
+                        </Button>
+                    </Box>
+                </DialogActions>
+            </Form>
+        </Dialog>
+    );
+}
+
+export default BindMatnrModal;
\ No newline at end of file
diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatCreate.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatCreate.jsx
new file mode 100644
index 0000000..9f726dc
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatCreate.jsx
@@ -0,0 +1,137 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    CreateBase,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SaveButton,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    Toolbar,
+    required,
+    useDataProvider,
+    useNotify,
+    Form,
+    useCreateController,
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    Stack,
+    Grid,
+    Box,
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import StatusSelectInput from "../../components/StatusSelectInput";
+import MemoInput from "../../components/MemoInput";
+
+const LocAreaMatCreate = (props) => {
+    const { open, setOpen } = props;
+
+    const translate = useTranslate();
+    const notify = useNotify();
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+        }
+    };
+
+    const handleSuccess = async (data) => {
+        setOpen(false);
+        notify('common.response.success');
+    };
+
+    const handleError = async (error) => {
+        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
+    };
+
+    return (
+        <>
+            <CreateBase
+                record={{}}
+                transform={(data) => {
+                    return data;
+                }}
+                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
+            >
+                <Dialog
+                    open={open}
+                    onClose={handleClose}
+                    aria-labelledby="form-dialog-title"
+                    fullWidth
+                    disableRestoreFocus
+                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+                >
+                    <Form>
+                        <DialogTitle id="form-dialog-title" sx={{
+                            position: 'sticky',
+                            top: 0,
+                            backgroundColor: 'background.paper',
+                            zIndex: 1000
+                        }}
+                        >
+                            {translate('create.title')}
+                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+                                <DialogCloseButton onClose={handleClose} />
+                            </Box>
+                        </DialogTitle>
+                        <DialogContent sx={{ mt: 2 }}>
+                            <Grid container rowSpacing={2} columnSpacing={2}>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <TextInput
+                                        label="table.field.locAreaMat.code"
+                                        source="code"
+                                        parse={v => v}
+                                        autoFocus
+                                    />
+                                </Grid>
+                                {/* <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.locAreaMat.warehouseId"
+                                        source="warehouseId"
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.locAreaMat.areaId"
+                                        source="areaId"
+                                    />
+                                </Grid> */}
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <TextInput
+                                        label="table.field.locAreaMat.depict"
+                                        source="depict"
+                                        parse={v => v}
+                                    />
+                                </Grid>
+
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <StatusSelectInput />
+                                </Grid>
+                                <Grid item xs={12} display="flex" gap={1}>
+                                    <Stack direction="column" spacing={1} width={'100%'}>
+                                        <MemoInput />
+                                    </Stack>
+                                </Grid>
+                            </Grid>
+                        </DialogContent>
+                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
+                                <SaveButton />
+                            </Toolbar>
+                        </DialogActions>
+                    </Form>
+                </Dialog>
+            </CreateBase>
+        </>
+    )
+}
+
+export default LocAreaMatCreate;
diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatEdit.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatEdit.jsx
new file mode 100644
index 0000000..752dbfd
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatEdit.jsx
@@ -0,0 +1,109 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    Edit,
+    SimpleForm,
+    FormDataConsumer,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    SaveButton,
+    Toolbar,
+    Labeled,
+    NumberField,
+    required,
+    useRecordContext,
+    DeleteButton,
+} from 'react-admin';
+import { useWatch, useFormContext } from "react-hook-form";
+import { Stack, Grid, Box, Typography } from '@mui/material';
+import * as Common from '@/utils/common';
+import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
+import EditBaseAside from "../../components/EditBaseAside";
+import CustomerTopToolBar from "../../components/EditTopToolBar";
+import MemoInput from "../../components/MemoInput";
+import StatusSelectInput from "../../components/StatusSelectInput";
+
+const FormToolbar = () => {
+    const { getValues } = useFormContext();
+
+    return (
+        <Toolbar sx={{ justifyContent: 'space-between' }}>
+            <SaveButton />
+            <DeleteButton mutationMode="optimistic" />
+        </Toolbar>
+    )
+}
+
+const LocAreaMatEdit = () => {
+    const translate = useTranslate();
+
+    return (
+        <Edit
+            redirect="list"
+            mutationMode={EDIT_MODE}
+            actions={<CustomerTopToolBar />}
+            aside={<EditBaseAside />}
+        >
+            <SimpleForm
+                shouldUnregister
+                warnWhenUnsavedChanges
+                toolbar={<FormToolbar />}
+                mode="onTouched"
+                defaultValues={{}}
+            // validate={(values) => { }}
+            >
+                <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
+                    <Grid item xs={12} md={8}>
+                        <Typography variant="h6" gutterBottom>
+                            {translate('common.edit.title.main')}
+                        </Typography>
+                        <Stack direction='row' gap={2}>
+                            <TextInput
+                                label="table.field.locAreaMat.code"
+                                source="code"
+                                parse={v => v}
+                                autoFocus
+                            />
+                        </Stack>
+                        {/* <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.locAreaMat.warehouseId"
+                                source="warehouseId"
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.locAreaMat.areaId"
+                                source="areaId"
+                            />
+                        </Stack> */}
+                        <Stack direction='row' gap={2}>
+                            <TextInput
+                                label="table.field.locAreaMat.depict"
+                                source="depict"
+                                parse={v => v}
+                            />
+                        </Stack>
+
+                    </Grid>
+                    <Grid item xs={12} md={4}>
+                        <Typography variant="h6" gutterBottom>
+                            {translate('common.edit.title.common')}
+                        </Typography>
+                        <StatusSelectInput />
+                        <Box mt="2em" />
+                        <MemoInput />
+                    </Grid>
+                </Grid>
+            </SimpleForm>
+        </Edit >
+    )
+}
+
+export default LocAreaMatEdit;
diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatList.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatList.jsx
new file mode 100644
index 0000000..a27e68c
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatList.jsx
@@ -0,0 +1,156 @@
+import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
+import { useNavigate } from 'react-router-dom';
+import {
+    List,
+    DatagridConfigurable,
+    SearchInput,
+    TopToolbar,
+    SelectColumnsButton,
+    EditButton,
+    FilterButton,
+    CreateButton,
+    ExportButton,
+    BulkDeleteButton,
+    WrapperField,
+    useRecordContext,
+    useTranslate,
+    useNotify,
+    useListContext,
+    FunctionField,
+    TextField,
+    NumberField,
+    DateField,
+    BooleanField,
+    ReferenceField,
+    TextInput,
+    DateTimeInput,
+    DateInput,
+    SelectInput,
+    NumberInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    DeleteButton,
+} from 'react-admin';
+import { Box, Typography, Card, Stack } from '@mui/material';
+import { styled } from '@mui/material/styles';
+import LocAreaMatCreate from "./LocAreaMatCreate";
+import LocAreaMatPanel from "./LocAreaMatPanel";
+import EmptyData from "../../components/EmptyData";
+import MyCreateButton from "../../components/MyCreateButton";
+import MyExportButton from '../../components/MyExportButton';
+import PageDrawer from "../../components/PageDrawer";
+import MyField from "../../components/MyField";
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import * as Common from '@/utils/common';
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+    '& .css-1vooibu-MuiSvgIcon-root': {
+        height: '.9em'
+    },
+    '& .RaDatagrid-row': {
+        cursor: 'auto'
+    },
+    '& .column-name': {
+    },
+    '& .opt': {
+        width: 200
+    },
+}));
+
+const filters = [
+    <SearchInput source="condition" alwaysOn />,
+
+    <TextInput source="code" label="table.field.locAreaMat.code" />,
+    <NumberInput source="warehouseId" label="table.field.locAreaMat.warehouseId" />,
+    <NumberInput source="areaId" label="table.field.locAreaMat.areaId" />,
+    <TextInput source="depict" label="table.field.locAreaMat.depict" />,
+
+    <TextInput label="common.field.memo" source="memo" />,
+    <SelectInput
+        label="common.field.status"
+        source="status"
+        choices={[
+            { id: '1', name: 'common.enums.statusTrue' },
+            { id: '0', name: 'common.enums.statusFalse' },
+        ]}
+        resettable
+    />,
+]
+
+const LocAreaMatList = () => {
+    const translate = useTranslate();
+
+    const [createDialog, setCreateDialog] = useState(false);
+    const [drawerVal, setDrawerVal] = useState(false);
+
+    return (
+        <Box display="flex">
+            <List
+                sx={{
+                    flexGrow: 1,
+                    transition: (theme) =>
+                        theme.transitions.create(['all'], {
+                            duration: theme.transitions.duration.enteringScreen,
+                        }),
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                }}
+                title={"menu.locAreaMat"}
+                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
+                filters={filters}
+                sort={{ field: "create_time", order: "desc" }}
+                actions={(
+                    <TopToolbar>
+                        <FilterButton />
+                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
+                        <SelectColumnsButton preferenceKey='locAreaMat' />
+                        <MyExportButton />
+                    </TopToolbar>
+                )}
+                perPage={DEFAULT_PAGE_SIZE}
+            >
+                <StyledDatagrid
+                    preferenceKey='locAreaMat'
+                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
+                    rowClick={(id, resource, record) => false}
+                    expand={() => <LocAreaMatPanel />}
+                    expandSingle={true}
+                    omit={['id', 'createTime', 'createBy', 'memo']}
+                >
+                    <NumberField source="id" />
+                    <TextField source="code" label="table.field.locAreaMat.code" />
+                    {/* <NumberField source="warehouseId" label="table.field.locAreaMat.warehouseId" />
+                    <NumberField source="areaId" label="table.field.locAreaMat.areaId" /> */}
+                    <TextField source="depict" label="table.field.locAreaMat.depict" />
+
+                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
+                        <TextField source="nickname" />
+                    </ReferenceField>
+                    <DateField source="updateTime" label="common.field.updateTime" showTime />
+                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
+                        <TextField source="nickname" />
+                    </ReferenceField>
+                    <DateField source="createTime" label="common.field.createTime" showTime />
+                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
+                    <TextField source="memo" label="common.field.memo" sortable={false} />
+                    <WrapperField cellClassName="opt" label="common.field.opt">
+                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
+                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
+                    </WrapperField>
+                </StyledDatagrid>
+            </List>
+            <LocAreaMatCreate
+                open={createDialog}
+                setOpen={setCreateDialog}
+            />
+            <PageDrawer
+                title='LocAreaMat Detail'
+                drawerVal={drawerVal}
+                setDrawerVal={setDrawerVal}
+            >
+            </PageDrawer>
+        </Box>
+    )
+}
+
+export default LocAreaMatList;
diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx
new file mode 100644
index 0000000..6ca9111
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx
@@ -0,0 +1,411 @@
+import React, { useState, useRef, useEffect } from "react";
+import {
+    Grid, Card, Typography, Button, Checkbox, Tooltip,
+    IconButton,
+} from '@mui/material';
+import { useTranslate, useRecordContext, useNotify } from 'react-admin';
+import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
+import { TreeItem2 } from "@mui/x-tree-view/TreeItem2";
+import { useTreeViewApiRef } from '@mui/x-tree-view/hooks';
+import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord';
+import AddIcon from '@mui/icons-material/Add';
+import DeleteIcon from '@mui/icons-material/Delete';
+import BindMatnrModal from './BindMatnrModal';
+import BindLocModal from './BindLocModal';
+import ConfirmModal from "@/page/components/ConfirmModal";
+import { DataGrid } from '@mui/x-data-grid';
+import request from '@/utils/request';
+
+const LocAreaMatPanel = () => {
+    const record = useRecordContext();
+    if (!record) return null;
+    const translate = useTranslate();
+    const notify = useNotify();
+
+    const columns = [
+        { field: 'id', headerName: 'ID', width: 100 },
+        { field: 'areaId$', headerName: translate('table.field.locAreaMatRela.areaId'), width: 100 },
+        { field: 'matnrId$', headerName: translate('table.field.locAreaMatRela.matnrId'), width: 100 },
+        { field: 'groupId$', headerName: translate('table.field.locAreaMatRela.groupId'), width: 100 },
+        { field: 'locTypeId$', headerName: translate('table.field.locAreaMatRela.locTypeId'), width: 100 },
+        { field: 'locId$', headerName: translate('table.field.locAreaMatRela.locId'), width: 100 },
+        {
+            field: 'action',
+            headerName: '鎿嶄綔',
+            minWidth: 100,
+            sticky: 'left',
+            flex: 1,
+            renderCell: (params) => (
+                <Tooltip title="Delete">
+                    <IconButton onClick={(e) => handleDelete(params.row, e)}>
+                        <DeleteIcon />
+                    </IconButton>
+                </Tooltip>
+            ),
+        },
+    ];
+
+    const handleDelete = async (row, e) => {
+        e.stopPropagation()
+        const { data: { code, data, msg } } = await request.post(`/locAreaMatRela/remove/${row.id}`);
+
+        if (code === 200) {
+            reload()
+            notify(msg);
+        } else {
+            notify(msg);
+        }
+
+    }
+
+    const [parmas, setParmas] = useState({
+        areaMatId: record.id,
+    });
+
+    const [tableData, setTableData] = useState([]);
+    const [matnrTree, setMatnrTree] = useState([]);
+    const [locTree, setLocTree] = useState([]);
+
+    useEffect(() => {
+        reload()
+    }, [parmas])
+
+    const reload = () => {
+        requestTable()
+        requestMatnr()
+        requestLocType()
+    }
+
+    const requestTable = async () => {
+        const { data: { code, data, msg } } = await request.post(`/locAreaMatRela/page`, parmas);
+
+        if (code === 200) {
+            setTableData(data.records || [])
+        } else {
+            notify(msg);
+        }
+    }
+
+    const requestMatnr = async () => {
+        const { data: { code, data, msg } } = await request.get(`/locAreaMatRela/groups/${record.id}`);
+
+        if (code === 200) {
+            setMatnrTree(data || [])
+        } else {
+            notify(msg);
+        }
+    }
+
+    const requestLocType = async () => {
+        const { data: { code, data, msg } } = await request.get(`/locAreaMatRela/locType/${record.id}`);
+
+        if (code === 200) {
+            setLocTree(data || [])
+        } else {
+            notify(msg);
+        }
+    }
+
+
+    return (
+        <Grid container spacing={2}>
+            {/* 鐗╂枡鍒嗙粍 */}
+            <Grid item xs={2}>
+                <MatnrTree matnrTree={matnrTree} setParmas={setParmas} reload={reload} />
+            </Grid>
+
+            {/* 搴撲綅绫诲瀷 */}
+            <Grid item xs={2}>
+                <LocTree locTree={locTree} setParmas={setParmas} reload={reload} />
+            </Grid>
+
+            {/* 鍏朵粬鍐呭 */}
+            <Grid item xs={8}>
+                <DataGrid
+                    size="small"
+                    rows={tableData}
+                    columns={columns}
+                    checkboxSelection
+                    disableColumnMenu={true}
+                    disableColumnSorting
+                    disableMultipleColumnsSorting
+                    columnBufferPx={100}
+                />
+            </Grid>
+        </Grid>
+    );
+};
+
+export default LocAreaMatPanel;
+
+
+const MatnrTree = ({ matnrTree, setParmas, reload }) => {
+
+    const record = useRecordContext();
+    const notify = useNotify();
+
+    function getItemDescendantsIds(item) {
+        const ids = [];
+        item.children?.forEach((child) => {
+            ids.push(child.id);
+            ids.push(...getItemDescendantsIds(child));
+        });
+
+        return ids;
+    }
+
+    const [selectedItems, setSelectedItems] = useState([]);
+    const toggledItemRef = useRef({});
+    const apiRef = useTreeViewApiRef();
+
+    const handleItemSelectionToggle = (event, itemId, isSelected) => {
+        event.stopPropagation()
+        event.preventDefault();
+        toggledItemRef.current[itemId] = isSelected;
+    };
+
+    const handleSelectedItemsChange = (event, newSelectedItems) => {
+        event.stopPropagation()
+        event.preventDefault();
+        setSelectedItems(newSelectedItems);
+
+        const itemsToSelect = [];
+        const itemsToUnSelect = {};
+        Object.entries(toggledItemRef.current).forEach(([itemId, isSelected]) => {
+            const item = apiRef.current.getItem(itemId);
+            if (isSelected) {
+                itemsToSelect.push(...getItemDescendantsIds(item));
+            } else {
+                getItemDescendantsIds(item).forEach((descendantId) => {
+                    itemsToUnSelect[descendantId] = true;
+                });
+            }
+        });
+
+        const newSelectedItemsWithChildren = Array.from(
+            new Set(
+                [...newSelectedItems, ...itemsToSelect].filter(
+                    (itemId) => !itemsToUnSelect[itemId],
+                ),
+            ),
+        );
+
+        setSelectedItems(newSelectedItemsWithChildren);
+
+        toggledItemRef.current = {};
+    };
+
+    const [addDialog, setAddDialog] = useState(false);
+    const [delectDialog, setDelectDialog] = useState(false);
+
+
+    const handleDelete = () => {
+        if (selectedItems.length > 0) {
+            setDelectDialog(true)
+        } else {
+            notify('璇烽�夋嫨鐗╂枡鍒嗙粍');
+        }
+
+    };
+
+    const contirmDelete = async () => {
+        const parmas = {
+            aeaMatId: record.id,
+            groupId: selectedItems
+        }
+
+        const res = await request.post(`/locAreaMatRela/group/remove/`, parmas);
+        if (res?.data?.code === 200) {
+            reload()
+            notify(res.data.msg);
+
+        } else {
+            notify(res.data.msg);
+        }
+
+    };
+
+    const handleAdd = () => {
+        setAddDialog(true)
+
+    };
+
+    const handleNodeSelect = (event, nodeId) => {
+        event.stopPropagation()
+    };
+
+    return (
+        <Card sx={{ p: 1 }}>
+            <div style={{ display: 'flex', justifyContent: 'space-between', paddingBottom: '3px', marginBottom: '3px', borderBottom: '1px dashed #d4d4d4' }}>
+                <div style={{ fontSize: '17px' }}>鐗╂枡鍒嗙粍</div>
+                <div style={{ display: 'flex', alignItems: 'center', gap: '3px' }}>
+                    <AddIcon color={'info'} sx={{ cursor: 'pointer' }} onClick={() => handleAdd()} />
+
+                    <DeleteIcon color={'warning'} sx={{ cursor: 'pointer' }} onClick={() => handleDelete()} />
+                </div>
+            </div>
+
+            <RichTreeView
+                expansionTrigger="iconContainer"
+                checkboxSelection
+                multiSelect
+                items={matnrTree}
+                apiRef={apiRef}
+                selectedItems={selectedItems}
+                getItemId={(item) => item.id}
+                getItemLabel={(item) => item.name}
+                defaultExpandedItems={['grid']}
+                onSelectedItemsChange={handleSelectedItemsChange}
+                onItemSelectionToggle={handleItemSelectionToggle}
+                onItemClick={handleNodeSelect}
+            />
+
+            <BindMatnrModal
+                open={addDialog}
+                setOpen={setAddDialog}
+                selectedItems={selectedItems}
+                reload={reload}
+            />
+
+            <ConfirmModal
+                open={delectDialog}
+                setOpen={setDelectDialog}
+                onConfirm={contirmDelete}
+            />
+        </Card>
+    )
+}
+
+const LocTree = ({ locTree, setParmas, reload }) => {
+
+    const record = useRecordContext();
+    const notify = useNotify();
+
+    function getItemDescendantsIds(item) {
+        const ids = [];
+        item.children?.forEach((child) => {
+            ids.push(child.id);
+            ids.push(...getItemDescendantsIds(child));
+        });
+
+        return ids;
+    }
+
+    const [selectedItems, setSelectedItems] = useState([]);
+    const toggledItemRef = useRef({});
+    const apiRef = useTreeViewApiRef();
+
+    const handleItemSelectionToggle = (event, itemId, isSelected) => {
+        toggledItemRef.current[itemId] = isSelected;
+    };
+
+    const handleSelectedItemsChange = (event, newSelectedItems) => {
+        setSelectedItems(newSelectedItems);
+
+        const itemsToSelect = [];
+        const itemsToUnSelect = {};
+        Object.entries(toggledItemRef.current).forEach(([itemId, isSelected]) => {
+            const item = apiRef.current.getItem(itemId);
+            if (isSelected) {
+                itemsToSelect.push(...getItemDescendantsIds(item));
+            } else {
+                getItemDescendantsIds(item).forEach((descendantId) => {
+                    itemsToUnSelect[descendantId] = true;
+                });
+            }
+        });
+
+        const newSelectedItemsWithChildren = Array.from(
+            new Set(
+                [...newSelectedItems, ...itemsToSelect].filter(
+                    (itemId) => !itemsToUnSelect[itemId],
+                ),
+            ),
+        );
+
+        setSelectedItems(newSelectedItemsWithChildren);
+
+        toggledItemRef.current = {};
+    };
+
+    const [addDialog, setAddDialog] = useState(false);
+    const [delectDialog, setDelectDialog] = useState(false);
+
+
+    const handleDelete = () => {
+        if (selectedItems.length > 0) {
+            setDelectDialog(true)
+        } else {
+            notify('璇烽�夋嫨搴撲綅绫诲瀷');
+        }
+
+    };
+
+    const contirmDelete = async () => {
+        const parmas = {
+            areaMatId: record.id,
+            typeId: selectedItems
+        }
+
+        const res = await request.post(`/locAreaMatRela/locType/remove/`, parmas);
+        if (res?.data?.code === 200) {
+            reload()
+            notify(res.data.msg);
+
+        } else {
+            notify(res.data.msg);
+        }
+
+    };
+
+    const handleAdd = () => {
+        setAddDialog(true)
+
+    };
+
+    const handleNodeSelect = (event, nodeId) => {
+        // event.preventDefault();
+        console.log(nodeId)
+    };
+
+    return (
+        <Card sx={{ p: 1 }}>
+            <div style={{ display: 'flex', justifyContent: 'space-between', paddingBottom: '3px', marginBottom: '3px', borderBottom: '1px dashed #d4d4d4' }}>
+                <div style={{ fontSize: '17px' }}>搴撲綅绫诲瀷</div>
+                <div style={{ display: 'flex', alignItems: 'center', gap: '3px' }}>
+                    <AddIcon color={'info'} sx={{ cursor: 'pointer' }} onClick={() => handleAdd()} />
+
+                    <DeleteIcon color={'warning'} sx={{ cursor: 'pointer' }} onClick={() => handleDelete()} />
+                </div>
+            </div>
+
+            <RichTreeView
+                expansionTrigger="iconContainer"
+                checkboxSelection
+                multiSelect
+                items={locTree}
+                apiRef={apiRef}
+                selectedItems={selectedItems}
+                getItemId={(item) => item.id}
+                getItemLabel={(item) => item.name}
+                defaultExpandedItems={['grid']}
+                onSelectedItemsChange={handleSelectedItemsChange}
+                onItemSelectionToggle={handleItemSelectionToggle}
+                onItemClick={handleNodeSelect}
+            />
+
+            <BindLocModal
+                open={addDialog}
+                setOpen={setAddDialog}
+                selectedItems={selectedItems}
+                reload={reload}
+            />
+
+            <ConfirmModal
+                open={delectDialog}
+                setOpen={setDelectDialog}
+                onConfirm={contirmDelete}
+            />
+        </Card>
+    )
+}
\ No newline at end of file
diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/index.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/index.jsx
new file mode 100644
index 0000000..625a369
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMat/index.jsx
@@ -0,0 +1,18 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    ListGuesser,
+    EditGuesser,
+    ShowGuesser,
+} from "react-admin";
+
+import LocAreaMatList from "./LocAreaMatList";
+import LocAreaMatEdit from "./LocAreaMatEdit";
+
+export default {
+    list: LocAreaMatList,
+    edit: LocAreaMatEdit,
+    show: ShowGuesser,
+    recordRepresentation: (record) => {
+        return `${record.id}`
+    }
+};
diff --git a/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaCreate.jsx b/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaCreate.jsx
new file mode 100644
index 0000000..c685d20
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaCreate.jsx
@@ -0,0 +1,179 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    CreateBase,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SaveButton,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    SelectArrayInput,
+    Toolbar,
+    required,
+    useDataProvider,
+    useNotify,
+    Form,
+    useCreateController,
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    Stack,
+    Grid,
+    Box,
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import StatusSelectInput from "../../components/StatusSelectInput";
+import MemoInput from "../../components/MemoInput";
+import TreeSelectInput from "@/page/components/TreeSelectInput";
+
+const LocAreaMatRelaCreate = (props) => {
+    const { open, setOpen } = props;
+
+    const translate = useTranslate();
+    const notify = useNotify();
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+        }
+    };
+
+    const handleSuccess = async (data) => {
+        setOpen(false);
+        notify('common.response.success');
+    };
+
+    const handleError = async (error) => {
+        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
+    };
+
+    return (
+        <>
+            <CreateBase
+                record={{}}
+                transform={(data) => {
+                    return data;
+                }}
+                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
+            >
+                <Dialog
+                    open={open}
+                    onClose={handleClose}
+                    aria-labelledby="form-dialog-title"
+                    fullWidth
+                    disableRestoreFocus
+                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+                >
+                    <Form>
+                        <DialogTitle id="form-dialog-title" sx={{
+                            position: 'sticky',
+                            top: 0,
+                            backgroundColor: 'background.paper',
+                            zIndex: 1000
+                        }}
+                        >
+                            {translate('create.title')}
+                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+                                <DialogCloseButton onClose={handleClose} />
+                            </Box>
+                        </DialogTitle>
+                        <DialogContent sx={{ mt: 2 }}>
+                            <Grid container rowSpacing={2} columnSpacing={2}>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <ReferenceInput
+                                        source="areaId"
+                                        reference="warehouseAreas"
+                                    >
+                                        <AutocompleteInput
+                                            label="table.field.locAreaMatRela.areaId"
+                                            optionText="name"
+                                            validate={[required()]}
+                                            filterToQuery={(val) => ({ name: val })}
+                                        />
+                                    </ReferenceInput>
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <TextInput
+                                        label="table.field.locAreaMatRela.code"
+                                        source="code"
+                                        parse={v => v}
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <ReferenceInput
+                                        source="matnrId"
+                                        reference="matnr"
+                                    >
+                                        <AutocompleteInput
+                                            label="table.field.locAreaMatRela.matnrId"
+                                            optionText="name"
+                                            filterToQuery={(val) => ({ name: val })}
+                                        />
+                                    </ReferenceInput>
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <TreeSelectInput
+                                        label="table.field.locAreaMatRela.groupId"
+                                        resource={'matnrGroup'}
+                                        source="groupId"
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <ReferenceInput
+                                        source="locId"
+                                        reference="loc"
+                                    >
+                                        <AutocompleteInput
+                                            label="table.field.locAreaMatRela.locId"
+                                            optionText="code"
+                                            filterToQuery={(val) => ({ code: val })}
+                                        />
+                                    </ReferenceInput>
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    {/* <ReferenceArrayInput source="locTypeId" reference="locType" >
+                                        <SelectArrayInput label="table.field.locAreaMatRela.locTypeId" />
+                                    </ReferenceArrayInput> */}
+                                    <ReferenceInput
+                                        source="locTypeId"
+                                        reference="locType"
+                                    >
+                                        <AutocompleteInput
+                                            label="table.field.locAreaMatRela.locTypeId"
+                                            optionText="name"
+                                            filterToQuery={(val) => ({ name: val })}
+                                        />
+                                    </ReferenceInput>
+                                </Grid>
+
+
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <StatusSelectInput />
+                                </Grid>
+                                <Grid item xs={12} display="flex" gap={1}>
+                                    <Stack direction="column" spacing={1} width={'100%'}>
+                                        <MemoInput />
+                                    </Stack>
+                                </Grid>
+                            </Grid>
+                        </DialogContent>
+                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
+                                <SaveButton />
+                            </Toolbar>
+                        </DialogActions>
+                    </Form>
+                </Dialog>
+            </CreateBase>
+        </>
+    )
+}
+
+export default LocAreaMatRelaCreate;
diff --git a/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaEdit.jsx b/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaEdit.jsx
new file mode 100644
index 0000000..63bb3ae
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaEdit.jsx
@@ -0,0 +1,152 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    Edit,
+    SimpleForm,
+    FormDataConsumer,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    SelectArrayInput,
+    SaveButton,
+    Toolbar,
+    Labeled,
+    NumberField,
+    required,
+    useRecordContext,
+    DeleteButton,
+} from 'react-admin';
+import { useWatch, useFormContext } from "react-hook-form";
+import { Stack, Grid, Box, Typography } from '@mui/material';
+import * as Common from '@/utils/common';
+import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
+import EditBaseAside from "../../components/EditBaseAside";
+import CustomerTopToolBar from "../../components/EditTopToolBar";
+import MemoInput from "../../components/MemoInput";
+import StatusSelectInput from "../../components/StatusSelectInput";
+import TreeSelectInput from "@/page/components/TreeSelectInput";
+
+const FormToolbar = () => {
+    const { getValues } = useFormContext();
+
+    return (
+        <Toolbar sx={{ justifyContent: 'space-between' }}>
+            <SaveButton />
+            <DeleteButton mutationMode="optimistic" />
+        </Toolbar>
+    )
+}
+
+const LocAreaMatRelaEdit = () => {
+    const translate = useTranslate();
+
+    return (
+        <Edit
+            redirect="list"
+            mutationMode={EDIT_MODE}
+            actions={<CustomerTopToolBar />}
+            aside={<EditBaseAside />}
+            title={"menu.locAreaMatRela"}
+        >
+            <SimpleForm
+                shouldUnregister
+                warnWhenUnsavedChanges
+                toolbar={<FormToolbar />}
+                mode="onTouched"
+                defaultValues={{}}
+            // validate={(values) => { }}
+            >
+                <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
+                    <Grid item xs={12} md={8}>
+                        <Typography variant="h6" gutterBottom>
+                            {translate('common.edit.title.main')}
+                        </Typography>
+                        <Stack direction='row' gap={2}>
+                            <ReferenceInput
+                                source="areaId"
+                                reference="warehouseAreas"
+                            >
+                                <AutocompleteInput
+                                    label="table.field.locAreaMatRela.areaId"
+                                    optionText="name"
+                                    validate={[required()]}
+                                    filterToQuery={(val) => ({ name: val })}
+                                />
+                            </ReferenceInput>
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <TextInput
+                                label="table.field.locAreaMatRela.code"
+                                source="code"
+                                parse={v => v}
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <ReferenceInput
+                                source="matnrId"
+                                reference="matnr"
+                            >
+                                <AutocompleteInput
+                                    label="table.field.locAreaMatRela.matnrId"
+                                    optionText="name"
+                                    filterToQuery={(val) => ({ name: val })}
+                                />
+                            </ReferenceInput>
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <TreeSelectInput
+                                label="table.field.locAreaMatRela.groupId"
+                                resource={'matnrGroup'}
+                                source="groupId"
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <ReferenceInput
+                                source="locId"
+                                reference="loc"
+                            >
+                                <AutocompleteInput
+                                    label="table.field.locAreaMatRela.locId"
+                                    optionText="code"
+                                    filterToQuery={(val) => ({ code: val })}
+                                />
+                            </ReferenceInput>
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            {/* <ReferenceArrayInput source="locTypeId" reference="locType" >
+                                <SelectArrayInput label="table.field.locAreaMatRela.locTypeId" />
+                            </ReferenceArrayInput> */}
+                            <ReferenceInput
+                                source="locTypeId"
+                                reference="locType"
+                            >
+                                <AutocompleteInput
+                                    label="table.field.locAreaMatRela.locTypeId"
+                                    optionText="name"
+                                    filterToQuery={(val) => ({ name: val })}
+                                />
+                            </ReferenceInput>
+                        </Stack>
+
+
+                    </Grid>
+                    <Grid item xs={12} md={4}>
+                        <Typography variant="h6" gutterBottom>
+                            {translate('common.edit.title.common')}
+                        </Typography>
+                        <StatusSelectInput />
+                        <Box mt="2em" />
+                        <MemoInput />
+                    </Grid>
+                </Grid>
+            </SimpleForm>
+        </Edit >
+    )
+}
+
+export default LocAreaMatRelaEdit;
diff --git a/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaList.jsx b/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaList.jsx
new file mode 100644
index 0000000..2af0ab4
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaList.jsx
@@ -0,0 +1,158 @@
+import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
+import { useNavigate } from 'react-router-dom';
+import {
+    List,
+    DatagridConfigurable,
+    SearchInput,
+    TopToolbar,
+    SelectColumnsButton,
+    EditButton,
+    FilterButton,
+    CreateButton,
+    ExportButton,
+    BulkDeleteButton,
+    WrapperField,
+    useRecordContext,
+    useTranslate,
+    useNotify,
+    useListContext,
+    FunctionField,
+    TextField,
+    NumberField,
+    DateField,
+    BooleanField,
+    ReferenceField,
+    TextInput,
+    DateTimeInput,
+    DateInput,
+    SelectInput,
+    NumberInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    DeleteButton,
+} from 'react-admin';
+import { Box, Typography, Card, Stack } from '@mui/material';
+import { styled } from '@mui/material/styles';
+import LocAreaMatRelaCreate from "./LocAreaMatRelaCreate";
+import LocAreaMatRelaPanel from "./LocAreaMatRelaPanel";
+import EmptyData from "../../components/EmptyData";
+import MyCreateButton from "../../components/MyCreateButton";
+import MyExportButton from '../../components/MyExportButton';
+import PageDrawer from "../../components/PageDrawer";
+import MyField from "../../components/MyField";
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import * as Common from '@/utils/common';
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+    '& .css-1vooibu-MuiSvgIcon-root': {
+        height: '.9em'
+    },
+    '& .RaDatagrid-row': {
+        cursor: 'auto'
+    },
+    '& .column-name': {
+    },
+    '& .opt': {
+        width: 200
+    },
+}));
+
+const filters = [
+    <SearchInput source="condition" alwaysOn />,
+
+    <NumberInput source="areaId" label="table.field.locAreaMatRela.areaId" />,
+    <TextInput source="code" label="table.field.locAreaMatRela.code" />,
+    <NumberInput source="matnrId" label="table.field.locAreaMatRela.matnrId" />,
+    <NumberInput source="groupId" label="table.field.locAreaMatRela.groupId" />,
+    <NumberInput source="locTypeId" label="table.field.locAreaMatRela.locTypeId" />,
+    <NumberInput source="locId" label="table.field.locAreaMatRela.locId" />,
+
+    <TextInput label="common.field.memo" source="memo" />,
+    <SelectInput
+        label="common.field.status"
+        source="status"
+        choices={[
+            { id: '1', name: 'common.enums.statusTrue' },
+            { id: '0', name: 'common.enums.statusFalse' },
+        ]}
+        resettable
+    />,
+]
+
+const LocAreaMatRelaList = () => {
+    const translate = useTranslate();
+
+    const [createDialog, setCreateDialog] = useState(false);
+    const [drawerVal, setDrawerVal] = useState(false);
+
+    return (
+        <Box display="flex">
+            <List
+                sx={{
+                    flexGrow: 1,
+                    transition: (theme) =>
+                        theme.transitions.create(['all'], {
+                            duration: theme.transitions.duration.enteringScreen,
+                        }),
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                }}
+                title={"menu.locAreaMatRela"}
+                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
+                filters={filters}
+                sort={{ field: "create_time", order: "desc" }}
+                actions={(
+                    <TopToolbar>
+                        <FilterButton />
+                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
+                        <SelectColumnsButton preferenceKey='locAreaMatRela' />
+                        <MyExportButton />
+                    </TopToolbar>
+                )}
+                perPage={DEFAULT_PAGE_SIZE}
+            >
+                <StyledDatagrid
+                    preferenceKey='locAreaMatRela'
+                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
+                    rowClick={(id, resource, record) => false}
+                    omit={['id', 'createTime', 'createBy', 'memo']}
+                >
+                    <NumberField source="id" />
+                    <NumberField source="areaId$" label="table.field.locAreaMatRela.areaId" />
+                    <TextField source="code" label="table.field.locAreaMatRela.code" />
+                    <NumberField source="matnrId$" label="table.field.locAreaMatRela.matnrId" />
+                    <NumberField source="groupId$" label="table.field.locAreaMatRela.groupId" />
+                    <NumberField source="locTypeId$" label="table.field.locAreaMatRela.locTypeId" />
+                    <NumberField source="locId$" label="table.field.locAreaMatRela.locId" />
+
+                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
+                        <TextField source="nickname" />
+                    </ReferenceField>
+                    <DateField source="updateTime" label="common.field.updateTime" showTime />
+                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
+                        <TextField source="nickname" />
+                    </ReferenceField>
+                    <DateField source="createTime" label="common.field.createTime" showTime />
+                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
+                    <TextField source="memo" label="common.field.memo" sortable={false} />
+                    <WrapperField cellClassName="opt" label="common.field.opt">
+                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
+                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
+                    </WrapperField>
+                </StyledDatagrid>
+            </List>
+            <LocAreaMatRelaCreate
+                open={createDialog}
+                setOpen={setCreateDialog}
+            />
+            <PageDrawer
+                title='LocAreaMatRela Detail'
+                drawerVal={drawerVal}
+                setDrawerVal={setDrawerVal}
+            >
+            </PageDrawer>
+        </Box>
+    )
+}
+
+export default LocAreaMatRelaList;
diff --git a/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaPanel.jsx b/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaPanel.jsx
new file mode 100644
index 0000000..47c1a00
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMatRela/LocAreaMatRelaPanel.jsx
@@ -0,0 +1,28 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
+import {
+    useTranslate,
+    useRecordContext,
+} from 'react-admin';
+import PanelTypography from "../../components/PanelTypography";
+import * as Common from '@/utils/common'
+
+const LocAreaMatRelaPanel = () => {
+    const record = useRecordContext();
+    if (!record) return null;
+    const translate = useTranslate();
+    return (
+        <>
+            <Card >
+                <CardContent>
+                    <Grid container spacing={2}>1</Grid>
+                    <Grid container spacing={2}>1</Grid>
+                    <Grid container spacing={2}>1</Grid>
+
+                </CardContent >
+            </Card >
+        </>
+    );
+};
+
+export default LocAreaMatRelaPanel;
diff --git a/rsf-admin/src/page/basicInfo/locAreaMatRela/index.jsx b/rsf-admin/src/page/basicInfo/locAreaMatRela/index.jsx
new file mode 100644
index 0000000..87ce528
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMatRela/index.jsx
@@ -0,0 +1,18 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    ListGuesser,
+    EditGuesser,
+    ShowGuesser,
+} from "react-admin";
+
+import LocAreaMatRelaList from "./LocAreaMatRelaList";
+import LocAreaMatRelaEdit from "./LocAreaMatRelaEdit";
+
+export default {
+    list: LocAreaMatRelaList,
+    edit: LocAreaMatRelaEdit,
+    show: ShowGuesser,
+    recordRepresentation: (record) => {
+        return `${record.areaId}`
+    }
+};
diff --git a/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaCreate.jsx b/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaCreate.jsx
new file mode 100644
index 0000000..fdbc7a7
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaCreate.jsx
@@ -0,0 +1,123 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    CreateBase,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SaveButton,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    Toolbar,
+    required,
+    useDataProvider,
+    useNotify,
+    Form,
+    useCreateController,
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    Stack,
+    Grid,
+    Box,
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import StatusSelectInput from "../../components/StatusSelectInput";
+import MemoInput from "../../components/MemoInput";
+
+const LocAreaRelaCreate = (props) => {
+    const { open, setOpen } = props;
+
+    const translate = useTranslate();
+    const notify = useNotify();
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+        }
+    };
+
+    const handleSuccess = async (data) => {
+        setOpen(false);
+        notify('common.response.success');
+    };
+
+    const handleError = async (error) => {
+        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
+    };
+
+    return (
+        <>
+            <CreateBase
+                record={{}}
+                transform={(data) => {
+                    return data;
+                }}
+                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
+            >
+                <Dialog
+                    open={open}
+                    onClose={handleClose}
+                    aria-labelledby="form-dialog-title"
+                    fullWidth
+                    disableRestoreFocus
+                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+                >
+                    <Form>
+                        <DialogTitle id="form-dialog-title" sx={{
+                            position: 'sticky',
+                            top: 0,
+                            backgroundColor: 'background.paper',
+                            zIndex: 1000
+                        }}
+                        >
+                            {translate('create.title')}
+                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+                                <DialogCloseButton onClose={handleClose} />
+                            </Box>
+                        </DialogTitle>
+                        <DialogContent sx={{ mt: 2 }}>
+                            <Grid container rowSpacing={2} columnSpacing={2}>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.locAreaRela.locAreaId"
+                                        source="locAreaId"
+                                        autoFocus
+                                    />
+                                </Grid>
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <NumberInput
+                                        label="table.field.locAreaRela.locId"
+                                        source="locId"
+                                    />
+                                </Grid>
+
+                                <Grid item xs={6} display="flex" gap={1}>
+                                    <StatusSelectInput />
+                                </Grid>
+                                <Grid item xs={12} display="flex" gap={1}>
+                                    <Stack direction="column" spacing={1} width={'100%'}>
+                                        <MemoInput />
+                                    </Stack>
+                                </Grid>
+                            </Grid>
+                        </DialogContent>
+                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
+                                <SaveButton />
+                            </Toolbar>
+                        </DialogActions>
+                    </Form>
+                </Dialog>
+            </CreateBase>
+        </>
+    )
+}
+
+export default LocAreaRelaCreate;
diff --git a/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaEdit.jsx b/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaEdit.jsx
new file mode 100644
index 0000000..fd66e5f
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaEdit.jsx
@@ -0,0 +1,95 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    Edit,
+    SimpleForm,
+    FormDataConsumer,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    SaveButton,
+    Toolbar,
+    Labeled,
+    NumberField,
+    required,
+    useRecordContext,
+    DeleteButton,
+} from 'react-admin';
+import { useWatch, useFormContext } from "react-hook-form";
+import { Stack, Grid, Box, Typography } from '@mui/material';
+import * as Common from '@/utils/common';
+import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
+import EditBaseAside from "../../components/EditBaseAside";
+import CustomerTopToolBar from "../../components/EditTopToolBar";
+import MemoInput from "../../components/MemoInput";
+import StatusSelectInput from "../../components/StatusSelectInput";
+
+const FormToolbar = () => {
+    const { getValues } = useFormContext();
+
+    return (
+        <Toolbar sx={{ justifyContent: 'space-between' }}>
+            <SaveButton />
+            <DeleteButton mutationMode="optimistic" />
+        </Toolbar>
+    )
+}
+
+const LocAreaRelaEdit = () => {
+    const translate = useTranslate();
+
+    return (
+        <Edit
+            redirect="list"
+            mutationMode={EDIT_MODE}
+            actions={<CustomerTopToolBar />}
+            aside={<EditBaseAside />}
+        >
+            <SimpleForm
+                shouldUnregister
+                warnWhenUnsavedChanges
+                toolbar={<FormToolbar />}
+                mode="onTouched"
+                defaultValues={{}}
+            // validate={(values) => { }}
+            >
+                <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
+                    <Grid item xs={12} md={8}>
+                        <Typography variant="h6" gutterBottom>
+                            {translate('common.edit.title.main')}
+                        </Typography>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.locAreaRela.locAreaId"
+                                source="locAreaId"
+                                autoFocus
+                            />
+                        </Stack>
+                        <Stack direction='row' gap={2}>
+                            <NumberInput
+                                label="table.field.locAreaRela.locId"
+                                source="locId"
+                            />
+                        </Stack>
+
+                    </Grid>
+                    <Grid item xs={12} md={4}>
+                        <Typography variant="h6" gutterBottom>
+                            {translate('common.edit.title.common')}
+                        </Typography>
+                        <StatusSelectInput />
+                        <Box mt="2em" />
+                        <MemoInput />
+                    </Grid>
+                </Grid>
+            </SimpleForm>
+        </Edit >
+    )
+}
+
+export default LocAreaRelaEdit;
diff --git a/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaList.jsx b/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaList.jsx
new file mode 100644
index 0000000..46e26d8
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaList.jsx
@@ -0,0 +1,154 @@
+import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
+import { useNavigate } from 'react-router-dom';
+import {
+    List,
+    DatagridConfigurable,
+    SearchInput,
+    TopToolbar,
+    SelectColumnsButton,
+    EditButton,
+    FilterButton,
+    CreateButton,
+    ExportButton,
+    BulkDeleteButton,
+    WrapperField,
+    useRecordContext,
+    useTranslate,
+    useNotify,
+    useListContext,
+    FunctionField,
+    TextField,
+    NumberField,
+    DateField,
+    BooleanField,
+    ReferenceField,
+    TextInput,
+    DateTimeInput,
+    DateInput,
+    SelectInput,
+    NumberInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    DeleteButton,
+} from 'react-admin';
+import { Box, Typography, Card, Stack } from '@mui/material';
+import { styled } from '@mui/material/styles';
+import LocAreaRelaCreate from "./LocAreaRelaCreate";
+import LocAreaRelaPanel from "./LocAreaRelaPanel";
+import EmptyData from "../../components/EmptyData";
+import MyCreateButton from "../../components/MyCreateButton";
+import MyExportButton from '../../components/MyExportButton';
+import PageDrawer from "../../components/PageDrawer";
+import MyField from "../../components/MyField";
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import * as Common from '@/utils/common';
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+    '& .css-1vooibu-MuiSvgIcon-root': {
+        height: '.9em'
+    },
+    '& .RaDatagrid-row': {
+        cursor: 'auto'
+    },
+    '& .column-name': {
+    },
+    '& .opt': {
+        width: 200
+    },
+}));
+
+const filters = [
+    <SearchInput source="condition" alwaysOn />,
+    <DateInput label='common.time.after' source="timeStart" alwaysOn />,
+    <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
+
+    <NumberInput source="locAreaId" label="table.field.locAreaRela.locAreaId" />,
+    <NumberInput source="locId" label="table.field.locAreaRela.locId" />,
+
+    <TextInput label="common.field.memo" source="memo" />,
+    <SelectInput
+        label="common.field.status"
+        source="status"
+        choices={[
+            { id: '1', name: 'common.enums.statusTrue' },
+            { id: '0', name: 'common.enums.statusFalse' },
+        ]}
+        resettable
+    />,
+]
+
+const LocAreaRelaList = () => {
+    const translate = useTranslate();
+
+    const [createDialog, setCreateDialog] = useState(false);
+    const [drawerVal, setDrawerVal] = useState(false);
+
+    return (
+        <Box display="flex">
+            <List
+                sx={{
+                    flexGrow: 1,
+                    transition: (theme) =>
+                        theme.transitions.create(['all'], {
+                            duration: theme.transitions.duration.enteringScreen,
+                        }),
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                }}
+                title={"menu.locAreaRela"}
+                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
+                filters={filters}
+                sort={{ field: "create_time", order: "desc" }}
+                actions={(
+                    <TopToolbar>
+                        <FilterButton />
+                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
+                        <SelectColumnsButton preferenceKey='locAreaRela' />
+                        <MyExportButton />
+                    </TopToolbar>
+                )}
+                perPage={DEFAULT_PAGE_SIZE}
+            >
+                <StyledDatagrid
+                    preferenceKey='locAreaRela'
+                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
+                    rowClick={(id, resource, record) => false}
+                    expand={() => <LocAreaRelaPanel />}
+                    expandSingle={true}
+                    omit={['id', 'createTime', 'createBy', 'memo']}
+                >
+                    <NumberField source="id" />
+                    <NumberField source="locAreaId" label="table.field.locAreaRela.locAreaId" />
+                    <NumberField source="locId" label="table.field.locAreaRela.locId" />
+
+                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
+                        <TextField source="nickname" />
+                    </ReferenceField>
+                    <DateField source="updateTime" label="common.field.updateTime" showTime />
+                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
+                        <TextField source="nickname" />
+                    </ReferenceField>
+                    <DateField source="createTime" label="common.field.createTime" showTime />
+                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
+                    <TextField source="memo" label="common.field.memo" sortable={false} />
+                    <WrapperField cellClassName="opt" label="common.field.opt">
+                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
+                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
+                    </WrapperField>
+                </StyledDatagrid>
+            </List>
+            <LocAreaRelaCreate
+                open={createDialog}
+                setOpen={setCreateDialog}
+            />
+            <PageDrawer
+                title='LocAreaRela Detail'
+                drawerVal={drawerVal}
+                setDrawerVal={setDrawerVal}
+            >
+            </PageDrawer>
+        </Box>
+    )
+}
+
+export default LocAreaRelaList;
diff --git a/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaPanel.jsx b/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaPanel.jsx
new file mode 100644
index 0000000..47c67d4
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaRela/LocAreaRelaPanel.jsx
@@ -0,0 +1,63 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
+import {
+    useTranslate,
+    useRecordContext,
+} from 'react-admin';
+import PanelTypography from "../../components/PanelTypography";
+import * as Common from '@/utils/common'
+
+const LocAreaRelaPanel = () => {
+    const record = useRecordContext();
+    if (!record) return null;
+    const translate = useTranslate();
+    return (
+        <>
+            <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}>
+                <CardContent>
+                    <Grid container spacing={2}>
+                        <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}>
+                            <Typography variant="h6" gutterBottom align="left" sx={{
+                                maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' },
+                                whiteSpace: 'nowrap',
+                                overflow: 'hidden',
+                                textOverflow: 'ellipsis',
+                            }}>
+                                {Common.camelToPascalWithSpaces(translate('table.field.locAreaRela.locAreaId'))}: {record.locAreaId}
+                            </Typography>
+                            {/*  inherit, primary, secondary, textPrimary, textSecondary, error */}
+                            <Typography variant="h6" gutterBottom align="right" >
+                                ID: {record.id}
+                            </Typography>
+                        </Grid>
+                    </Grid>
+                    <Grid container spacing={2}>
+                        <Grid item xs={12} container alignContent="flex-end">
+                            <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
+                                {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo}
+                            </Typography>
+                        </Grid>
+                    </Grid>
+                    <Box height={20}>&nbsp;</Box>
+                    <Grid container spacing={2}>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.locAreaRela.locAreaId"
+                                property={record.locAreaId}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.locAreaRela.locId"
+                                property={record.locId}
+                            />
+                        </Grid>
+
+                    </Grid>
+                </CardContent>
+            </Card >
+        </>
+    );
+};
+
+export default LocAreaRelaPanel;
diff --git a/rsf-admin/src/page/basicInfo/locAreaRela/index.jsx b/rsf-admin/src/page/basicInfo/locAreaRela/index.jsx
new file mode 100644
index 0000000..a68c3b2
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaRela/index.jsx
@@ -0,0 +1,18 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    ListGuesser,
+    EditGuesser,
+    ShowGuesser,
+} from "react-admin";
+
+import LocAreaRelaList from "./LocAreaRelaList";
+import LocAreaRelaEdit from "./LocAreaRelaEdit";
+
+export default {
+    list: LocAreaRelaList,
+    edit: LocAreaRelaEdit,
+    show: ShowGuesser,
+    recordRepresentation: (record) => {
+        return `${record.locAreaId}`
+    }
+};
diff --git a/rsf-admin/src/page/basicInfo/locType/BindModal.jsx b/rsf-admin/src/page/basicInfo/locType/BindModal.jsx
new file mode 100644
index 0000000..310dd74
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locType/BindModal.jsx
@@ -0,0 +1,199 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    CreateBase,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SaveButton,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    Toolbar,
+    required,
+    useDataProvider,
+    useNotify,
+    Form,
+    useCreateController,
+    useListContext,
+    useRefresh,
+    SelectArrayInput
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    Grid,
+    TextField,
+    Box,
+    Button,
+    Paper,
+    TableContainer,
+    Table,
+    TableHead,
+    TableBody,
+    TableRow,
+    TableCell,
+    Tooltip,
+    IconButton,
+    styled,
+
+
+
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import DictionarySelect from "../../components/DictionarySelect";
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import SaveIcon from '@mui/icons-material/Save';
+import request from '@/utils/request';
+import { Add, Edit, Delete } from '@mui/icons-material';
+import _ from 'lodash';
+import { DataGrid } from '@mui/x-data-grid';
+import StatusSelectInput from "../../components/StatusSelectInput";
+import TreeSelectInput from "@/page/components/TreeSelectInput";
+const MatnrModal = ({ open, setOpen }) => {
+    const refresh = useRefresh();
+    const translate = useTranslate();
+
+
+    const notify = useNotify();
+
+    const [formData, setFormData] = useState({
+        areaId: null,
+        groupId: null,
+        matnrId: null,
+    });
+
+    const { selectedIds, onUnselectItems } = useListContext();
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+            reset()
+            refresh();
+            onUnselectItems()
+        }
+    };
+
+    const reset = () => {
+        setFormData({
+            areaId: null,
+            groupId: null,
+            matnrId: null,
+        })
+    }
+
+    const handleReset = (e) => {
+        e.preventDefault();
+    };
+
+    const handleChange = (value, name) => {
+        setFormData((prevData) => ({
+            ...prevData,
+            [name]: value
+        }));
+        refresh()
+    };
+
+    const removeEmptyKeys = (obj) => {
+        return _.pickBy(obj, (value) => {
+            if (_.isObject(value)) {
+                const newObj = removeEmptyKeys(value);
+                return !_.isEmpty(newObj);
+            }
+            return !_.isNil(value) && (_.isNumber(value) ? value !== 0 : !_.isEmpty(value));
+        });
+    }
+
+    const handleSubmit = async () => {
+        const parmas = {
+            typeId: selectedIds,
+            areaId: formData.areaId,
+            matnrId: formData.matnrId,
+        }
+
+        const res = await request.post(`/locAreaMatRela/matnr/bind`, parmas);
+        if (res?.data?.code === 200) {
+            handleClose()
+
+        } else {
+            notify(res.data.msg);
+        }
+
+
+    }
+
+    const [groupId, setGroupId] = useState();
+
+    const warehouseChange = (e) => {
+        setGroupId(e.target.value)
+    }
+
+    return (
+        <Dialog open={open} maxWidth="md" fullWidth>
+            <Form onSubmit={handleSubmit}>
+                <DialogCloseButton onClose={handleClose} />
+                <DialogTitle>{translate('toolbar.bindmatnr')}</DialogTitle>
+                <DialogContent sx={{ mt: 2 }}>
+                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
+                        <Grid container spacing={2}>
+                            <Grid item xs={4}>
+                                <ReferenceInput
+                                    source="areaId"
+                                    reference="warehouseAreas"
+                                >
+                                    <AutocompleteInput
+                                        label="table.field.loc.areaId"
+                                        optionText="name"
+                                        onChange={(value) => handleChange(value, 'areaId')}
+                                        value={formData.areaId}
+                                        validate={required()}
+                                        filterToQuery={(val) => ({ name: val })}
+                                    />
+                                </ReferenceInput>
+
+                            </Grid>
+
+                            <Grid item xs={4}>
+                                <TreeSelectInput
+                                    label="table.field.locAreaMatRela.groupId"
+                                    resource={'matnrGroup'}
+                                    source="groupId"
+                                    value={formData.groupId}
+                                    onChange={(e) => handleChange(e.target.value, 'groupId')}
+                                />
+                            </Grid>
+
+
+                            <Grid item xs={4}>
+                                <ReferenceArrayInput source="matnrId" reference="matnr" filter={{ groupId: formData.groupId }}>
+                                    <SelectArrayInput
+                                        label="table.field.locAreaMatRela.matnrId"
+                                        validate={required()}
+                                        value={formData.matnrId}
+                                        onChange={(e) => handleChange(e.target.value, 'matnrId')}
+                                    />
+                                </ReferenceArrayInput>
+
+                            </Grid>
+
+                        </Grid>
+
+                    </Box>
+                </DialogContent>
+                <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                    <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}>
+                        <Button type="submit" variant="contained" startIcon={<SaveIcon />}>
+                            {translate('toolbar.confirm')}
+                        </Button>
+                    </Box>
+                </DialogActions>
+            </Form>
+        </Dialog>
+    );
+}
+
+export default MatnrModal;
\ No newline at end of file
diff --git a/rsf-admin/src/page/basicInfo/locType/LocTypeEdit.jsx b/rsf-admin/src/page/basicInfo/locType/LocTypeEdit.jsx
index a630b99..666cd88 100644
--- a/rsf-admin/src/page/basicInfo/locType/LocTypeEdit.jsx
+++ b/rsf-admin/src/page/basicInfo/locType/LocTypeEdit.jsx
@@ -49,6 +49,7 @@
             mutationMode={EDIT_MODE}
             actions={<CustomerTopToolBar />}
             aside={<EditBaseAside />}
+            title={"menu.locType"}
         >
             <SimpleForm
                 shouldUnregister
diff --git a/rsf-admin/src/page/basicInfo/locType/LocTypeList.jsx b/rsf-admin/src/page/basicInfo/locType/LocTypeList.jsx
index 45a4e4d..5fd0003 100644
--- a/rsf-admin/src/page/basicInfo/locType/LocTypeList.jsx
+++ b/rsf-admin/src/page/basicInfo/locType/LocTypeList.jsx
@@ -31,6 +31,9 @@
     ReferenceArrayInput,
     AutocompleteInput,
     DeleteButton,
+    useRefresh,
+    Button,
+    useList
 } from 'react-admin';
 import { Box, Typography, Card, Stack } from '@mui/material';
 import { styled } from '@mui/material/styles';
@@ -42,6 +45,8 @@
 import PageDrawer from "../../components/PageDrawer";
 import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
 import * as Common from '@/utils/common';
+import BindModal from "./BindModal";
+import LinkIcon from '@mui/icons-material/Link';
 
 const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
     '& .css-1vooibu-MuiSvgIcon-root': {
@@ -109,7 +114,10 @@
             >
                 <StyledDatagrid
                     preferenceKey='locType'
-                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
+                    bulkActionButtons={<>
+                        <BindButton />
+                        <BulkDeleteButton />
+                    </>}
                     rowClick={(id, resource, record) => false}
                     omit={['id', 'createTime', 'createBy', 'memo']}
                 >
@@ -150,3 +158,26 @@
 }
 
 export default LocTypeList;
+
+const BindButton = () => {
+    const record = useRecordContext();
+    const notify = useNotify();
+    const refresh = useRefresh();
+
+
+    const [createDialog, setCreateDialog] = useState(false);
+
+    return (
+        <>
+            <Button onClick={() => setCreateDialog(true)} label={"toolbar.bindmatnr"}>
+                <LinkIcon />
+            </Button>
+
+            <BindModal
+                open={createDialog}
+                setOpen={setCreateDialog}
+            />
+        </>
+
+    )
+}
diff --git a/rsf-admin/src/page/basicInfo/matnr/BindModal.jsx b/rsf-admin/src/page/basicInfo/matnr/BindModal.jsx
new file mode 100644
index 0000000..3ada880
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/matnr/BindModal.jsx
@@ -0,0 +1,186 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    CreateBase,
+    useTranslate,
+    TextInput,
+    NumberInput,
+    BooleanInput,
+    DateInput,
+    SaveButton,
+    SelectInput,
+    ReferenceInput,
+    ReferenceArrayInput,
+    AutocompleteInput,
+    Toolbar,
+    required,
+    useDataProvider,
+    useNotify,
+    Form,
+    useCreateController,
+    useListContext,
+    useRefresh,
+    SelectArrayInput
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    Grid,
+    TextField,
+    Box,
+    Button,
+    Paper,
+    TableContainer,
+    Table,
+    TableHead,
+    TableBody,
+    TableRow,
+    TableCell,
+    Tooltip,
+    IconButton,
+    styled,
+
+} from '@mui/material';
+import DialogCloseButton from "../../components/DialogCloseButton";
+import DictionarySelect from "../../components/DictionarySelect";
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import SaveIcon from '@mui/icons-material/Save';
+import request from '@/utils/request';
+import { Add, Edit, Delete } from '@mui/icons-material';
+import _ from 'lodash';
+import { DataGrid } from '@mui/x-data-grid';
+import StatusSelectInput from "../../components/StatusSelectInput";
+import TreeSelectInput from "@/page/components/TreeSelectInput";
+const MatnrModal = ({ open, setOpen }) => {
+    const refresh = useRefresh();
+    const translate = useTranslate();
+
+
+    const notify = useNotify();
+
+    const [formData, setFormData] = useState({
+        areaId: null,
+        locId: null,
+    });
+
+    const { selectedIds, onUnselectItems } = useListContext();
+
+    const handleClose = (event, reason) => {
+        if (reason !== "backdropClick") {
+            setOpen(false);
+            reset()
+            refresh();
+            onUnselectItems()
+        }
+    };
+
+    const reset = () => {
+        setFormData({
+            areaId: null,
+            locId: null,
+        })
+    }
+
+    const handleReset = (e) => {
+        e.preventDefault();
+    };
+
+    const handleChange = (value, name) => {
+        setFormData((prevData) => ({
+            ...prevData,
+            [name]: value
+        }));
+        refresh()
+    };
+
+    const removeEmptyKeys = (obj) => {
+        return _.pickBy(obj, (value) => {
+            if (_.isObject(value)) {
+                const newObj = removeEmptyKeys(value);
+                return !_.isEmpty(newObj);
+            }
+            return !_.isNil(value) && (_.isNumber(value) ? value !== 0 : !_.isEmpty(value));
+        });
+    }
+
+    const handleSubmit = async () => {
+        const parmas = {
+            matnrId: selectedIds,
+            areaId: formData.areaId,
+            locId: formData.locId,
+        }
+
+        const res = await request.post(`/locAreaMatRela/matnr/bind`, parmas);
+        if (res?.data?.code === 200) {
+            handleClose()
+
+        } else {
+            notify(res.data.msg);
+        }
+
+
+    }
+
+    const [groupId, setGroupId] = useState();
+
+    const warehouseChange = (e) => {
+        setGroupId(e.target.value)
+    }
+
+    return (
+        <Dialog open={open} maxWidth="md" fullWidth>
+            <Form onSubmit={handleSubmit}>
+                <DialogCloseButton onClose={handleClose} />
+                <DialogTitle>{translate('toolbar.bindloc')}</DialogTitle>
+                <DialogContent sx={{ mt: 2 }}>
+                    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
+                        <Grid container spacing={2}>
+                            <Grid item xs={4}>
+                                <ReferenceInput
+                                    source="areaId"
+                                    reference="warehouseAreas"
+                                >
+                                    <AutocompleteInput
+                                        label="table.field.loc.areaId"
+                                        optionText="name"
+                                        onChange={(value) => handleChange(value, 'areaId')}
+                                        value={formData.areaId}
+                                        validate={required()}
+                                        filterToQuery={(val) => ({ name: val })}
+                                    />
+                                </ReferenceInput>
+
+                            </Grid>
+
+
+                            <Grid item xs={4}>
+                                <ReferenceArrayInput source="locId" reference="loc" >
+                                    <SelectArrayInput
+                                        label="table.field.locAreaMatRela.locId"
+                                        validate={required()}
+                                        optionText={'code'}
+                                        value={formData.locId}
+                                        onChange={(e) => handleChange(e.target.value, 'locId')}
+                                    />
+                                </ReferenceArrayInput>
+
+                            </Grid>
+
+                        </Grid>
+
+                    </Box>
+                </DialogContent>
+                <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                    <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}>
+                        <Button type="submit" variant="contained" startIcon={<SaveIcon />}>
+                            {translate('toolbar.confirm')}
+                        </Button>
+                    </Box>
+                </DialogActions>
+            </Form>
+        </Dialog>
+    );
+}
+
+export default MatnrModal;
\ No newline at end of file
diff --git a/rsf-admin/src/page/basicInfo/matnr/MatnrEdit.jsx b/rsf-admin/src/page/basicInfo/matnr/MatnrEdit.jsx
index 8cb7351..2264d6e 100644
--- a/rsf-admin/src/page/basicInfo/matnr/MatnrEdit.jsx
+++ b/rsf-admin/src/page/basicInfo/matnr/MatnrEdit.jsx
@@ -101,6 +101,7 @@
             mutationMode={EDIT_MODE}
             actions={<CustomerTopToolBar />}
             aside={<EditBaseAside />}
+            title={"menu.matnr"}
         >
             <SimpleForm
                 shouldUnregister
diff --git a/rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx b/rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx
index e27b5e6..5dc0c6c 100644
--- a/rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx
+++ b/rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx
@@ -55,6 +55,8 @@
 import request from '@/utils/request';
 import BatchModal from './BatchModal';
 import PrintModal from './PrintModal';
+import LinkIcon from '@mui/icons-material/Link';
+import BindModal from './BindModal';
 
 const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
     '& .css-1vooibu-MuiSvgIcon-root': {
@@ -84,7 +86,7 @@
         overflow: 'hidden',
         textOverflow: 'ellipsis',
         display: 'block',
-        width: '100px',
+        width: '300px',
     },
     '& .RaDatagrid-table': {
         width: '100%'
@@ -238,6 +240,7 @@
                     preferenceKey='matnr'
                     bulkActionButtons={<>
                         <BatchButton />
+                        <BindButton />
                         <PrintButton />
                         <BulkDeleteButton mutationMode={OPERATE_MODE} />
                     </>}
@@ -379,4 +382,27 @@
         </>
 
     )
+}
+
+const BindButton = () => {
+    const record = useRecordContext();
+    const notify = useNotify();
+    const refresh = useRefresh();
+
+
+    const [createDialog, setCreateDialog] = useState(false);
+
+    return (
+        <>
+            <Button onClick={() => setCreateDialog(true)} label={"toolbar.bindloc"}>
+                <LinkIcon />
+            </Button>
+
+            <BindModal
+                open={createDialog}
+                setOpen={setCreateDialog}
+            />
+        </>
+
+    )
 }
\ No newline at end of file
diff --git a/rsf-admin/src/page/basicInfo/matnr/PrintModal.jsx b/rsf-admin/src/page/basicInfo/matnr/PrintModal.jsx
index 7513fbe..f618577 100644
--- a/rsf-admin/src/page/basicInfo/matnr/PrintModal.jsx
+++ b/rsf-admin/src/page/basicInfo/matnr/PrintModal.jsx
@@ -210,9 +210,12 @@
                 }
             }))
             setData(val)
-            val.forEach((el) => {
-                jsbarcode(`#barcode${el.code}`, el.code, { height: 30 });
-            });
+            setTimeout(() => {
+                val.forEach((el) => {
+                    jsbarcode(`#barcode${el.code}`, el.code, { height: 30 });
+                });
+            }, 10);
+
 
 
         } else {
diff --git a/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupCreate.jsx b/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupCreate.jsx
index 0146f24..4c9aa78 100644
--- a/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupCreate.jsx
+++ b/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupCreate.jsx
@@ -84,7 +84,7 @@
                         </DialogTitle>
                         <DialogContent sx={{ mt: 2 }}>
                             <Grid container rowSpacing={2} columnSpacing={2}>
-    
+
                                 <Grid item xs={6} display="flex" gap={1}>
                                     <TextInput
                                         label="table.field.matnrGroup.name"
@@ -104,6 +104,7 @@
                                 <Grid item xs={6} display="flex" gap={1}>
                                     <NumberInput
                                         label="table.field.matnrGroup.parentId"
+                                        validate={[required()]}
                                         source="parentId"
                                     />
                                 </Grid>
diff --git a/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupEdit.jsx b/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupEdit.jsx
index 206a847..1cfd61c 100644
--- a/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupEdit.jsx
+++ b/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupEdit.jsx
@@ -50,6 +50,7 @@
             <Grid item xs={6} display="flex" gap={1}>
                 <TreeSelectInput
                     label="table.field.matnrGroup.parentId"
+                    validate={[required()]}
                     value={editRecord?.parentId}
                     isTranslate
                     resource={resource}
@@ -76,7 +77,7 @@
 
 const MatnrGroupEdit = (props) => {
     const { editRecord, open, setOpen, callback, resource } = props;
-    
+
     const translate = useTranslate();
     const notify = useNotify();
 
@@ -138,43 +139,43 @@
     };
 
     return (
-    <>
-        <CreateBase>
-            <Dialog
-                open={open}
-                onClose={handleClose}
-                aria-labelledby="form-dialog-title"
-                fullWidth
-                disableRestoreFocus
-                maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
-            >
-                <Form record={editRecord} onSubmit={onSubmit}>
-                    <DialogTitle id="form-dialog-title" sx={{
-                        position: 'sticky',
-                        top: 0,
-                        backgroundColor: 'background.paper',
-                        zIndex: 1000
-                    }}
-                    >
-                        {editRecord ? translate('update.title') : translate('create.title')}
-                        <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
-                            <DialogCloseButton onClose={handleClose} />
-                        </Box>
-                    </DialogTitle>
-                    <DialogContent sx={{ mt: 2 }}>
-                        <EditContent
-                            editRecord={editRecord}
-                        />
-                    </DialogContent>
-                    <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
-                        <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
-                            <SaveButton />
-                        </Toolbar>
-                    </DialogActions>
-                </Form>
-            </Dialog>
-        </CreateBase>
-    </>
+        <>
+            <CreateBase>
+                <Dialog
+                    open={open}
+                    onClose={handleClose}
+                    aria-labelledby="form-dialog-title"
+                    fullWidth
+                    disableRestoreFocus
+                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+                >
+                    <Form record={editRecord} onSubmit={onSubmit}>
+                        <DialogTitle id="form-dialog-title" sx={{
+                            position: 'sticky',
+                            top: 0,
+                            backgroundColor: 'background.paper',
+                            zIndex: 1000
+                        }}
+                        >
+                            {editRecord ? translate('update.title') : translate('create.title')}
+                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+                                <DialogCloseButton onClose={handleClose} />
+                            </Box>
+                        </DialogTitle>
+                        <DialogContent sx={{ mt: 2 }}>
+                            <EditContent
+                                editRecord={editRecord}
+                            />
+                        </DialogContent>
+                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
+                                <SaveButton />
+                            </Toolbar>
+                        </DialogActions>
+                    </Form>
+                </Dialog>
+            </CreateBase>
+        </>
     )
 }
 
diff --git a/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx b/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx
index 732710c..5b22181 100644
--- a/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx
+++ b/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx
@@ -268,7 +268,7 @@
                     >
                         {expandAll ? translate('common.action.collapseAll') : translate('common.action.expandAll')}
                     </Button>
-                    {/* <TextField
+                    <TextField
                         label="Search"
                         value={filter}
                         onChange={({ target }) => {
@@ -278,7 +278,7 @@
                         size="small"
                         margin="dense"
                         fullWidth
-                    /> */}
+                    />
                 </Box>
                 <Box>
                     <Button
diff --git a/rsf-admin/src/page/basicInfo/warehouse/WarehouseEdit.jsx b/rsf-admin/src/page/basicInfo/warehouse/WarehouseEdit.jsx
index 18c97bd..c04ccc1 100644
--- a/rsf-admin/src/page/basicInfo/warehouse/WarehouseEdit.jsx
+++ b/rsf-admin/src/page/basicInfo/warehouse/WarehouseEdit.jsx
@@ -49,6 +49,7 @@
             mutationMode={EDIT_MODE}
             actions={<CustomerTopToolBar />}
             aside={<EditBaseAside />}
+            title={"menu.warehouse"}
         >
             <SimpleForm
                 shouldUnregister
diff --git a/rsf-admin/src/page/components/ConfirmModal.jsx b/rsf-admin/src/page/components/ConfirmModal.jsx
new file mode 100644
index 0000000..118cab1
--- /dev/null
+++ b/rsf-admin/src/page/components/ConfirmModal.jsx
@@ -0,0 +1,50 @@
+import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
+import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material';
+import {
+    useTranslate,
+} from 'react-admin';
+
+const ConfirmModal = (props) => {
+    const { open, onConfirm, setOpen } = props;
+    const translate = useTranslate();
+
+
+
+    const handleClose = (event) => {
+        event.stopPropagation();
+        setOpen(false);
+    };
+
+    const handleConfirm = (event) => {
+        handleClose(event);
+        onConfirm();
+    };
+
+    return (
+        <>
+            <Dialog
+                aria-labelledby="dialog-title"
+                aria-describedby="dialog-description"
+                open={open}
+                onClose={handleClose}
+            >
+                <DialogTitle>{translate('common.msg.confirm.tip')}</DialogTitle>
+                <DialogContent>
+                    <DialogContentText>
+                        {translate('common.msg.confirm.desc')}
+                    </DialogContentText>
+                </DialogContent>
+                <DialogActions>
+                    <Button onClick={handleClose} color="primary">
+                        {translate('ra.action.cancel')}
+                    </Button>
+                    <Button onClick={handleConfirm} color="primary">
+                        {translate('ra.action.confirm')}
+                    </Button>
+                </DialogActions>
+            </Dialog>
+        </>
+    )
+}
+
+export default ConfirmModal;
\ No newline at end of file
diff --git a/rsf-admin/src/page/container/ContainerEdit.jsx b/rsf-admin/src/page/container/ContainerEdit.jsx
index d31de24..e1623bd 100644
--- a/rsf-admin/src/page/container/ContainerEdit.jsx
+++ b/rsf-admin/src/page/container/ContainerEdit.jsx
@@ -50,6 +50,7 @@
             mutationMode={EDIT_MODE}
             actions={<CustomerTopToolBar />}
             aside={<EditBaseAside />}
+            title={"menu.container"}
         >
             <SimpleForm
                 shouldUnregister
diff --git a/rsf-admin/src/page/contract/ContractEdit.jsx b/rsf-admin/src/page/contract/ContractEdit.jsx
index 503ed00..ef0e6b5 100644
--- a/rsf-admin/src/page/contract/ContractEdit.jsx
+++ b/rsf-admin/src/page/contract/ContractEdit.jsx
@@ -49,6 +49,7 @@
             mutationMode={EDIT_MODE}
             actions={<CustomerTopToolBar />}
             aside={<EditBaseAside />}
+            title={"menu.contract"}
         >
             <SimpleForm
                 shouldUnregister
diff --git a/rsf-admin/src/page/fields/FieldsList.jsx b/rsf-admin/src/page/fields/FieldsList.jsx
index 5c1f785..78970d9 100644
--- a/rsf-admin/src/page/fields/FieldsList.jsx
+++ b/rsf-admin/src/page/fields/FieldsList.jsx
@@ -68,13 +68,13 @@
     <SelectInput source="unique" label="table.field.fields.unique"
         choices={[
             { id: 0, name: ' 闈炲敮涓�' },
-            { id:   1, name: '  鍞竴' },
+            { id: 1, name: '  鍞竴' },
         ]}
     />,
     <SelectInput source="flagEnable" label="table.field.fields.flagEnable"
         choices={[
             { id: 0, name: ' 涓嶅惎鐢�' },
-            { id:  1, name: ' 鍚敤' },
+            { id: 1, name: ' 鍚敤' },
         ]}
     />,
 
@@ -105,7 +105,7 @@
                         theme.transitions.create(['all'], {
                             duration: theme.transitions.duration.enteringScreen,
                         }),
-                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                 }}
                 title={"menu.fields"}
                 empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -125,8 +125,6 @@
                     preferenceKey='fields'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <FieldsPanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'createBy', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/fieldsItem/FieldsItemList.jsx b/rsf-admin/src/page/fieldsItem/FieldsItemList.jsx
index 41c2121..914518f 100644
--- a/rsf-admin/src/page/fieldsItem/FieldsItemList.jsx
+++ b/rsf-admin/src/page/fieldsItem/FieldsItemList.jsx
@@ -96,7 +96,7 @@
                         theme.transitions.create(['all'], {
                             duration: theme.transitions.duration.enteringScreen,
                         }),
-                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                 }}
                 title={"menu.fieldsItem"}
                 empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -116,8 +116,6 @@
                     preferenceKey='fieldsItem'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <FieldsItemPanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'createBy', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/purchaseItem/PurchaseItemList.jsx b/rsf-admin/src/page/purchaseItem/PurchaseItemList.jsx
index 139441c..ce3083d 100644
--- a/rsf-admin/src/page/purchaseItem/PurchaseItemList.jsx
+++ b/rsf-admin/src/page/purchaseItem/PurchaseItemList.jsx
@@ -129,8 +129,6 @@
             preferenceKey='purchaseItem'
             bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
             rowClick={(id, resource, record) => false}
-            expand={() => <PurchaseItemPanel />}
-            expandSingle={true}
             omit={['id', 'createTime', 'createBy', 'memo']}
           >
             <NumberField source="id" />
diff --git a/rsf-admin/src/page/qlyInspect/QlyInspectList.jsx b/rsf-admin/src/page/qlyInspect/QlyInspectList.jsx
index d1fa634..a23f223 100644
--- a/rsf-admin/src/page/qlyInspect/QlyInspectList.jsx
+++ b/rsf-admin/src/page/qlyInspect/QlyInspectList.jsx
@@ -97,7 +97,7 @@
                         theme.transitions.create(['all'], {
                             duration: theme.transitions.duration.enteringScreen,
                         }),
-                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                 }}
                 title={"menu.qlyInspect"}
                 empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -117,8 +117,6 @@
                     preferenceKey='qlyInspect'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <QlyInspectPanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'createBy', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/qlyIsptItem/QlyIsptItemList.jsx b/rsf-admin/src/page/qlyIsptItem/QlyIsptItemList.jsx
index ae7a557..b53c5c3 100644
--- a/rsf-admin/src/page/qlyIsptItem/QlyIsptItemList.jsx
+++ b/rsf-admin/src/page/qlyIsptItem/QlyIsptItemList.jsx
@@ -103,7 +103,7 @@
                         theme.transitions.create(['all'], {
                             duration: theme.transitions.duration.enteringScreen,
                         }),
-                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                 }}
                 title={"menu.qlyIsptItem"}
                 empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -123,8 +123,6 @@
                     preferenceKey='qlyIsptItem'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <QlyIsptItemPanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'createBy', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/system/config/ConfigList.jsx b/rsf-admin/src/page/system/config/ConfigList.jsx
index fb9b7c5..7dee9f5 100644
--- a/rsf-admin/src/page/system/config/ConfigList.jsx
+++ b/rsf-admin/src/page/system/config/ConfigList.jsx
@@ -100,7 +100,7 @@
                         theme.transitions.create(['all'], {
                             duration: theme.transitions.duration.enteringScreen,
                         }),
-                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                 }}
                 title={"menu.config"}
                 empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -121,8 +121,6 @@
                     preferenceKey='config'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <ConfigPanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/system/dicts/dictData/DictDataCreate.jsx b/rsf-admin/src/page/system/dicts/dictData/DictDataCreate.jsx
index f15c25d..afc4ea0 100644
--- a/rsf-admin/src/page/system/dicts/dictData/DictDataCreate.jsx
+++ b/rsf-admin/src/page/system/dicts/dictData/DictDataCreate.jsx
@@ -114,6 +114,7 @@
                                 <Grid item xs={6} display="flex" gap={1}>
                                     <TextInput
                                         label="table.field.dictData.label"
+                                        validate={required()}
                                         source="label"
                                         parse={v => v}
                                     />
diff --git a/rsf-admin/src/page/system/dicts/dictData/DictDataEdit.jsx b/rsf-admin/src/page/system/dicts/dictData/DictDataEdit.jsx
index a52a4c2..80fac6f 100644
--- a/rsf-admin/src/page/system/dicts/dictData/DictDataEdit.jsx
+++ b/rsf-admin/src/page/system/dicts/dictData/DictDataEdit.jsx
@@ -93,6 +93,7 @@
                             <TextInput
                                 label="table.field.dictData.label"
                                 source="label"
+                                validate={required()}
                                 parse={v => v}
                             />
                         </Stack>
diff --git a/rsf-admin/src/page/system/dicts/dictData/DictDataList.jsx b/rsf-admin/src/page/system/dicts/dictData/DictDataList.jsx
index 21a3f45..7af9d9d 100644
--- a/rsf-admin/src/page/system/dicts/dictData/DictDataList.jsx
+++ b/rsf-admin/src/page/system/dicts/dictData/DictDataList.jsx
@@ -128,8 +128,6 @@
                         preferenceKey='dictData'
                         bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                         rowClick={(id, resource, record) => false}
-                        expand={() => <DictDataPanel />}
-                        expandSingle={true}
                         omit={['id', 'createTime', 'createBy', 'memo']}
                     >
                         <NumberField source="id" />
diff --git a/rsf-admin/src/page/system/dicts/dictType/DictTypeList.jsx b/rsf-admin/src/page/system/dicts/dictType/DictTypeList.jsx
index 09058f4..e7d18bd 100644
--- a/rsf-admin/src/page/system/dicts/dictType/DictTypeList.jsx
+++ b/rsf-admin/src/page/system/dicts/dictType/DictTypeList.jsx
@@ -119,8 +119,6 @@
                     preferenceKey='dictType'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <DictTypePanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'createBy', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/system/host/HostList.jsx b/rsf-admin/src/page/system/host/HostList.jsx
index 1038cf0..82dd1e8 100644
--- a/rsf-admin/src/page/system/host/HostList.jsx
+++ b/rsf-admin/src/page/system/host/HostList.jsx
@@ -82,7 +82,7 @@
                         theme.transitions.create(['all'], {
                             duration: theme.transitions.duration.enteringScreen,
                         }),
-                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                 }}
                 title={"menu.host"}
                 empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -102,8 +102,6 @@
                     preferenceKey='host'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <HostPanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/system/serialRule/SerialRuleList.jsx b/rsf-admin/src/page/system/serialRule/SerialRuleList.jsx
index 355c08f..6008fab 100644
--- a/rsf-admin/src/page/system/serialRule/SerialRuleList.jsx
+++ b/rsf-admin/src/page/system/serialRule/SerialRuleList.jsx
@@ -146,8 +146,6 @@
             <BulkDeleteButton mutationMode={OPERATE_MODE} />
           )}
           rowClick={(id, resource, record) => false}
-          expand={() => <SerialRulePanel />}
-          expandSingle={true}
           omit={["id", "createTime", "createBy", "memo"]}
         >
           <NumberField source="id" />
diff --git a/rsf-admin/src/page/system/serialRuleItem/SerialRuleItemList.jsx b/rsf-admin/src/page/system/serialRuleItem/SerialRuleItemList.jsx
index 2e198d2..703190d 100644
--- a/rsf-admin/src/page/system/serialRuleItem/SerialRuleItemList.jsx
+++ b/rsf-admin/src/page/system/serialRuleItem/SerialRuleItemList.jsx
@@ -148,8 +148,6 @@
               <BulkDeleteButton mutationMode={OPERATE_MODE} />
             )}
             rowClick={(id, resource, record) => false}
-            expand={() => <SerialRuleItemPanel />}
-            expandSingle={true}
             omit={["id", "createTime", "createBy", "memo"]}
           >
             <NumberField source="id" />
diff --git a/rsf-admin/src/page/system/tenant/TenantList.jsx b/rsf-admin/src/page/system/tenant/TenantList.jsx
index 701461d..7774295 100644
--- a/rsf-admin/src/page/system/tenant/TenantList.jsx
+++ b/rsf-admin/src/page/system/tenant/TenantList.jsx
@@ -86,7 +86,7 @@
                         theme.transitions.create(['all'], {
                             duration: theme.transitions.duration.enteringScreen,
                         }),
-                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                 }}
                 title={"menu.tenant"}
                 empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -106,8 +106,6 @@
                     preferenceKey='tenant'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <TenantPanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/system/userLogin/UserLoginList.jsx b/rsf-admin/src/page/system/userLogin/UserLoginList.jsx
index b8758f8..4f66a88 100644
--- a/rsf-admin/src/page/system/userLogin/UserLoginList.jsx
+++ b/rsf-admin/src/page/system/userLogin/UserLoginList.jsx
@@ -100,7 +100,7 @@
                         theme.transitions.create(['all'], {
                             duration: theme.transitions.duration.enteringScreen,
                         }),
-                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+                    marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                 }}
                 title={"menu.userLogin"}
                 empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -120,8 +120,6 @@
                     preferenceKey='userLogin'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <UserLoginPanel />}
-                    expandSingle={true}
                     omit={['id', 'memo', 'type', 'system', 'updateTime']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx b/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx
index 227cb83..ea777c0 100644
--- a/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx
+++ b/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx
@@ -60,7 +60,7 @@
 
 const filters = [
     <SearchInput source="condition" alwaysOn />,
-
+    <TextField source="warehouseId" label="table.field.warehouseAreas.wareId" alwaysOn />,
     <TextInput source="uuid" label="table.field.warehouseAreas.uuid" />,
     <TextInput source="name" label="table.field.warehouseAreas.name" />,
     <TextInput source="code" label="table.field.warehouseAreas.code" />,
diff --git a/rsf-admin/src/page/warehouseAreasItem/WarehouseAreasItemList.jsx b/rsf-admin/src/page/warehouseAreasItem/WarehouseAreasItemList.jsx
index 9b03b48..999b8d4 100644
--- a/rsf-admin/src/page/warehouseAreasItem/WarehouseAreasItemList.jsx
+++ b/rsf-admin/src/page/warehouseAreasItem/WarehouseAreasItemList.jsx
@@ -127,8 +127,6 @@
                     preferenceKey='warehouseAreasItem'
                     bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <WarehouseAreasItemPanel />}
-                    expandSingle={true}
                     omit={['id', 'createTime', 'createBy', 'memo']}
                 >
                     <NumberField source="id" />
diff --git a/rsf-common/src/main/java/com/vincent/rsf/common/utils/Utils.java b/rsf-common/src/main/java/com/vincent/rsf/common/utils/Utils.java
index 6123a36..008d82d 100644
--- a/rsf-common/src/main/java/com/vincent/rsf/common/utils/Utils.java
+++ b/rsf-common/src/main/java/com/vincent/rsf/common/utils/Utils.java
@@ -48,6 +48,26 @@
         return result;
     }
 
+    public static <T, R> List<T> getAllTree(List<T> data, R parentId, Function<? super T, ? extends R> parentIdMapper, Function<? super T, ? extends R> idMapper, BiConsumer<T, List<T>> consumer) {
+        List<T> result = new ArrayList<>();
+        for (T datum : data) {
+            R dParentId = parentIdMapper.apply(datum);
+            R dId = idMapper.apply(datum);
+            if (dParentId.equals(dId)) {
+                List<T> children = toTreeData(data, dId, parentIdMapper, idMapper, consumer);
+                if (!children.isEmpty()) {
+                    consumer.accept(datum, children);
+                }
+                result.add(datum);
+            }
+            if (dParentId.equals(dId)) {
+                continue;
+            }
+        }
+        return result;
+    }
+
+
     public static <T> void treeRemove(List<T> list, String condition, Function<? super T, ? extends String> fetcher, Function<T, List<T>> childrenGetter) {
         Iterator<T> iterator = list.iterator();
         while (iterator.hasNext()) {
diff --git a/rsf-server/src/main/java/asnOrderItemLog.sql b/rsf-server/src/main/java/asnOrderItemLog.sql
deleted file mode 100644
index 367ed6d..0000000
--- a/rsf-server/src/main/java/asnOrderItemLog.sql
+++ /dev/null
@@ -1,43 +0,0 @@
--- save asnOrderItemLog record
--- mysql
-insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.asnOrderItemLog', '0', '/manager/asnOrderItemLog', 'asnOrderItemLog', '0' , '0', '1' , '1');
-
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query Asn order logs', '', '1', 'manager:asnOrderItemLog:list', '0', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create Asn order logs', '', '1', 'manager:asnOrderItemLog:save', '1', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update Asn order logs', '', '1', 'manager:asnOrderItemLog:update', '2', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete Asn order logs', '', '1', 'manager:asnOrderItemLog:remove', '3', '1', '1');
-
--- locale menu name
-asnOrderItemLog: 'AsnOrderItemLog',
-
--- locale field
-asnOrderItemLog: {
-    asnId: "asnId",
-    asnCode: "asnCode",
-    platItemId: "platItemId",
-    poDetlId: "poDetlId",
-    poCode: "poCode",
-    fieldsIndex: "fieldsIndex",
-    matnrId: "matnrId",
-    matnrCode: "matnrCode",
-    maktx: "maktx",
-    anfme: "anfme",
-    stockUnit: "stockUnit",
-    purQty: "purQty",
-    purUnit: "purUnit",
-    qty: "qty",
-    splrCode: "splrCode",
-    splrBatch: "splrBatch",
-    splrName: "splrName",
-    qrcode: "qrcode",
-    trackCode: "trackCode",
-    barcode: "barcode",
-    packName: "packName",
-    ntyStatus: "ntyStatus",
-},
-
--- ResourceContent
-import asnOrderItemLog from './asnOrderItemLog';
-
-case 'asnOrderItemLog':
-    return asnOrderItemLog;
diff --git a/rsf-server/src/main/java/asnOrderLog.sql b/rsf-server/src/main/java/asnOrderLog.sql
deleted file mode 100644
index 8ba0442..0000000
--- a/rsf-server/src/main/java/asnOrderLog.sql
+++ /dev/null
@@ -1,32 +0,0 @@
--- save asnOrderLog record
--- mysql
-insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.asnOrderLog', '0', '/manager/asnOrderLog', 'asnOrderLog', '0' , '0', '1' , '1');
-
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query Asn order logs', '', '1', 'manager:asnOrderLog:list', '0', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create Asn order logs', '', '1', 'manager:asnOrderLog:save', '1', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update Asn order logs', '', '1', 'manager:asnOrderLog:update', '2', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete Asn order logs', '', '1', 'manager:asnOrderLog:remove', '3', '1', '1');
-
--- locale menu name
-asnOrderLog: 'AsnOrderLog',
-
--- locale field
-asnOrderLog: {
-    code: "code",
-    poCode: "poCode",
-    poId: "poId",
-    type: "type",
-    wkType: "wkType",
-    anfme: "anfme",
-    qty: "qty",
-    logisNo: "logisNo",
-    arrTime: "arrTime",
-    rleStatus: "rleStatus",
-    ntyStatus: "ntyStatus",
-},
-
--- ResourceContent
-import asnOrderLog from './asnOrderLog';
-
-case 'asnOrderLog':
-    return asnOrderLog;
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
index 15ec114..286a6b3 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
@@ -22,8 +22,8 @@
 //        generator.username="sa";
 //        generator.password="Zoneyung@zy56$";
 
-        generator.table="man_loc_area_mat_rela";
-        generator.tableDesc="loc areas mats rela";
+        generator.table="man_loc_area_mat";
+        generator.tableDesc="loc areas mats";
         generator.packagePath="com.vincent.rsf.server.test";
 
         generator.build();
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocAreaMatController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocAreaMatController.java
new file mode 100644
index 0000000..817f37d
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocAreaMatController.java
@@ -0,0 +1,112 @@
+package com.vincent.rsf.server.manager.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.vincent.rsf.framework.common.Cools;
+import com.vincent.rsf.framework.common.R;
+import com.vincent.rsf.server.common.utils.ExcelUtil;
+import com.vincent.rsf.server.common.annotation.OperationLog;
+import com.vincent.rsf.server.common.domain.BaseParam;
+import com.vincent.rsf.server.common.domain.KeyValVo;
+import com.vincent.rsf.server.common.domain.PageParam;
+import com.vincent.rsf.server.manager.entity.LocAreaMat;
+import com.vincent.rsf.server.manager.service.LocAreaMatService;
+import com.vincent.rsf.server.system.controller.BaseController;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+
+@Api(tags = "閫昏緫鍒嗗尯")
+@RestController
+public class LocAreaMatController extends BaseController {
+
+    @Autowired
+    private LocAreaMatService locAreaMatService;
+
+    @PreAuthorize("hasAuthority('manager:locAreaMat:list')")
+    @PostMapping("/locAreaMat/page")
+    public R page(@RequestBody Map<String, Object> map) {
+        BaseParam baseParam = buildParam(map, BaseParam.class);
+        PageParam<LocAreaMat, BaseParam> pageParam = new PageParam<>(baseParam, LocAreaMat.class);
+        return R.ok().add(locAreaMatService.page(pageParam, pageParam.buildWrapper(true)));
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMat:list')")
+    @PostMapping("/locAreaMat/list")
+    public R list(@RequestBody Map<String, Object> map) {
+        return R.ok().add(locAreaMatService.list());
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMat:list')")
+    @PostMapping({"/locAreaMat/many/{ids}", "/locAreaMats/many/{ids}"})
+    public R many(@PathVariable Long[] ids) {
+        return R.ok().add(locAreaMatService.listByIds(Arrays.asList(ids)));
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMat:list')")
+    @GetMapping("/locAreaMat/{id}")
+    public R get(@PathVariable("id") Long id) {
+        return R.ok().add(locAreaMatService.getById(id));
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMat:save')")
+    @OperationLog("Create loc areas mats")
+    @PostMapping("/locAreaMat/save")
+    public R save(@RequestBody LocAreaMat locAreaMat) {
+        locAreaMat.setCreateBy(getLoginUserId());
+        locAreaMat.setCreateTime(new Date());
+        locAreaMat.setUpdateBy(getLoginUserId());
+        locAreaMat.setUpdateTime(new Date());
+        if (!locAreaMatService.save(locAreaMat)) {
+            return R.error("Save Fail");
+        }
+        return R.ok("Save Success").add(locAreaMat);
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMat:update')")
+    @OperationLog("Update loc areas mats")
+    @PostMapping("/locAreaMat/update")
+    public R update(@RequestBody LocAreaMat locAreaMat) {
+        locAreaMat.setUpdateBy(getLoginUserId());
+        locAreaMat.setUpdateTime(new Date());
+        if (!locAreaMatService.updateById(locAreaMat)) {
+            return R.error("Update Fail");
+        }
+        return R.ok("Update Success").add(locAreaMat);
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMat:remove')")
+    @OperationLog("Delete loc areas mats")
+    @PostMapping("/locAreaMat/remove/{ids}")
+    public R remove(@PathVariable Long[] ids) {
+        if (!locAreaMatService.removeByIds(Arrays.asList(ids))) {
+            return R.error("Delete Fail");
+        }
+        return R.ok("Delete Success").add(ids);
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMat:list')")
+    @PostMapping("/locAreaMat/query")
+    public R query(@RequestParam(required = false) String condition) {
+        List<KeyValVo> vos = new ArrayList<>();
+        LambdaQueryWrapper<LocAreaMat> wrapper = new LambdaQueryWrapper<>();
+        if (!Cools.isEmpty(condition)) {
+            wrapper.like(LocAreaMat::getId, condition);
+        }
+        locAreaMatService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
+                item -> vos.add(new KeyValVo(item.getId(), item.getId()))
+        );
+        return R.ok().add(vos);
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMat:list')")
+    @PostMapping("/locAreaMat/export")
+    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
+        ExcelUtil.build(ExcelUtil.create(locAreaMatService.list(), LocAreaMat.class), response);
+    }
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocAreaMatRelaController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocAreaMatRelaController.java
index 9c60d37..b44a0f5 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocAreaMatRelaController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/LocAreaMatRelaController.java
@@ -16,6 +16,7 @@
 import com.vincent.rsf.server.system.controller.BaseController;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -60,10 +61,9 @@
     @OperationLog("Create loc areas mats rela")
     @PostMapping("/locAreaMatRela/save")
     public R save(@RequestBody LocAreaMatRela locAreaMatRela) {
+
         locAreaMatRela.setCreateBy(getLoginUserId());
-        locAreaMatRela.setCreateTime(new Date());
         locAreaMatRela.setUpdateBy(getLoginUserId());
-        locAreaMatRela.setUpdateTime(new Date());
         if (!locAreaMatRelaService.save(locAreaMatRela)) {
             return R.error("Save Fail");
         }
@@ -82,10 +82,53 @@
         return R.ok("Update Success").add(locAreaMatRela);
     }
 
-    @PreAuthorize("hasAuthority('manager:locAreaMatRela:remove')")
+    @ApiOperation("鍒犻櫎鐗╂枡鍒嗙粍")
+    @GetMapping("/locAreaMatRela/group")
+    @PreAuthorize("hasAuthority('manager:locAreaMatRela:update')")
+    public R remByGroup(@RequestBody Map<String, Object> map) {
+        if (Objects.isNull(map)) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+        }
+        if (!StringUtils.isBlank(map.get("groupId").toString())) {
+            throw new CoolException("搴撲綅绫诲瀷涓嶈兘涓虹┖锛侊紒");
+        }
+        if (!StringUtils.isBlank(map.get("areaMatId").toString())) {
+            throw new CoolException("涓诲崟ID涓嶈兘涓虹┖锛侊紒");
+        }
+        if (locAreaMatRelaService.removeByGroupId(map)) {
+            return R.ok();
+        } else {
+            return R.error("鍒犻櫎澶辫触锛侊紒");
+        }
+    }
+
+    @ApiOperation("鍒犻櫎搴撲綅绫诲瀷")
+    @GetMapping("/locAreaMatRela/locType/remove")
+    @PreAuthorize("hasAuthority('manager:locAreaMatRela:update')")
+    public R removByLocType(@RequestBody Map<String, Object> param) {
+        if (Objects.isNull(param)) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒锛�");
+        }
+        if (!StringUtils.isBlank(param.get("typeId").toString())) {
+            throw new CoolException("搴撲綅绫诲瀷涓嶈兘涓虹┖锛侊紒");
+        }
+        if (!StringUtils.isBlank(param.get("areaMatId").toString())) {
+            throw new CoolException("涓诲崟ID涓嶈兘涓虹┖锛侊紒");
+        }
+        if (locAreaMatRelaService.removeByLocType(param)) {
+            return R.ok();
+        } else {
+            return R.ok("鍒犻櫎澶辫触锛侊紒");
+        }
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMatRela:list')")
     @OperationLog("Delete loc areas mats rela")
     @PostMapping("/locAreaMatRela/remove/{ids}")
     public R remove(@PathVariable Long[] ids) {
+        if (Objects.isNull(ids)) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+        }
         if (!locAreaMatRelaService.removeByIds(Arrays.asList(ids))) {
             return R.error("Delete Fail");
         }
@@ -107,6 +150,27 @@
     }
 
     @PreAuthorize("hasAuthority('manager:locAreaMatRela:list')")
+    @ApiOperation("鑾峰彇搴撳尯鐗╂枡鍒嗙粍")
+    @GetMapping("/locAreaMatRela/groups/{id}")
+    public R getAreaMatGroup(@PathVariable Long id) {
+        if (Objects.isNull(id)) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+        }
+        return R.ok(locAreaMatRelaService.getAllGroups(id));
+    }
+
+    @PreAuthorize("hasAuthority('manager:locAreaMatRela:list')")
+    @ApiOperation("鑾峰彇搴撳尯搴撲綅绫诲瀷")
+    @GetMapping("/locAreaMatRela/locType/{id}")
+    public R getAreaMatLocType(@PathVariable Long id) {
+        if (Objects.isNull(id)) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+        }
+        return R.ok(locAreaMatRelaService.getAllLocType(id));
+    }
+
+
+    @PreAuthorize("hasAuthority('manager:locAreaMatRela:list')")
     @PostMapping("/locAreaMatRela/export")
     public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
         ExcelUtil.build(ExcelUtil.create(locAreaMatRelaService.list(), LocAreaMatRela.class), response);
@@ -122,12 +186,12 @@
         if (Objects.isNull(param.getAreaId())) {
             throw new CoolException("搴撳尯涓嶈兘涓虹┖锛侊紒");
         }
-//        if (Objects.isNull(param.getTypeId()) || Objects.isNull(param.getLocId()) || param.getLocId().isEmpty() || param.getTypeId().isEmpty()) {
-//            throw new CoolException("搴撲綅绫诲瀷鎴栧簱浣嶄笉鑳戒负绌猴紒锛�");
-//        }
-//        if (Objects.isNull(param.getGroupId()) || Objects.isNull(param.getMatnrId()) || param.getMatnrId().isEmpty()) {
-//            throw new CoolException("鐗╂枡鎴栫墿鏂欏垎绫讳笉鑳戒负绌猴紒锛�");
-//        }
+        if (Objects.isNull(param.getWarehouseId())) {
+            throw new CoolException("浠撳簱涓嶈兘涓虹┖锛侊紒");
+        }
+        if (Objects.isNull(param.getAreaMatId())) {
+            throw new CoolException("涓诲崟ID涓嶈兘涓虹┖锛侊紒");
+        }
         return locAreaMatRelaService.binMatnrs(param);
     }
 
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrGroupController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrGroupController.java
index fbc7197..2b745ee 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrGroupController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrGroupController.java
@@ -23,6 +23,7 @@
 
 import javax.servlet.http.HttpServletResponse;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Api(tags = "鐗╂枡鍒嗙粍")
 @RestController
@@ -141,18 +142,12 @@
     @PreAuthorize("hasAuthority('manager:matnrGroup:list')")
     @PostMapping("/matnrGroup/tree")
     public R tree(@RequestBody(required = false) Map<String, Object> map) {
-        List<MatnrGroup> matnrs = new ArrayList<>();
         if (Objects.isNull(map)) {
-            matnrs = matnrGroupService.list(new LambdaQueryWrapper<MatnrGroup>().orderByAsc(MatnrGroup::getCode));
-        } else {
-            if (Objects.isNull(map.get("condition"))) {
-                return R.ok("condition鍙傛暟涓嶈兘涓虹┖锛侊紒");
-            }
-            matnrs = matnrGroupService.list(new LambdaQueryWrapper<MatnrGroup>()
-                    .like(MatnrGroup::getName, map.get("condition")).orderByAsc(MatnrGroup::getCode));
+            return R.error("鍙傛暟涓嶈兘涓虹┖锛侊紒");
         }
-        List<MatnrGroup> treeData = Utils.toTreeData(matnrs, 0L, MatnrGroup::getParentId, MatnrGroup::getId, MatnrGroup::setChildren);
-        return R.ok().add(treeData);
+        List<MatnrGroup> matnrs = matnrGroupService.getTreeData(map);
+
+        return R.ok().add(matnrs);
     }
 
 
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WarehouseAreasController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WarehouseAreasController.java
index 51afd7f..79b7975 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WarehouseAreasController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/WarehouseAreasController.java
@@ -98,15 +98,15 @@
             throw new CoolException("鏁版嵁閿欒锛氫粨搴撳簱鍖轰笉瀛樺湪锛侊紒");
         }
         if (!warehouseAreas.getName().equals(areas.getName())) {
-            List<WarehouseAreas> areasList = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>().eq(WarehouseAreas::getName, areas.getName()));
+            List<WarehouseAreas> areasList = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>().eq(WarehouseAreas::getName, warehouseAreas.getName()));
             if (!areasList.isEmpty()) {
-                throw new CoolException("浠撳簱鍚嶅凡瀛樺湪锛侊紒");
+                throw new CoolException("鍚嶇О宸插瓨鍦紒锛�");
             }
         }
         if (!warehouseAreas.getCode().equals(areas.getCode())) {
-            List<WarehouseAreas> areasList = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>().eq(WarehouseAreas::getCode, areas.getCode()));
+            List<WarehouseAreas> areasList = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>().eq(WarehouseAreas::getCode, warehouseAreas.getCode()));
             if (!areasList.isEmpty()) {
-                throw new CoolException("浠撳簱缂栫爜宸插瓨鍦紒锛�");
+                throw new CoolException("缂栫爜宸插瓨鍦紒锛�");
             }
         }
 
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/LocAreaMatsParam.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/LocAreaMatsParam.java
index 514452a..fb65e10 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/LocAreaMatsParam.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/params/LocAreaMatsParam.java
@@ -26,6 +26,12 @@
     @ApiModelProperty("搴撳尯ID")
     private Long areaId;
 
+    @ApiModelProperty("浠撳簱ID")
+    private Long warehouseId;
+
+    @ApiModelProperty("涓诲崟ID")
+    private Long areaMatId;
+
     @ApiModelProperty("搴撲綅绫诲瀷")
     private List<Long> typeId;
 
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocAreaMat.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocAreaMat.java
new file mode 100644
index 0000000..50ba83d
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocAreaMat.java
@@ -0,0 +1,217 @@
+package com.vincent.rsf.server.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.vincent.rsf.framework.common.Cools;
+import com.vincent.rsf.framework.common.SpringUtils;
+import com.vincent.rsf.server.manager.service.WarehouseAreasService;
+import com.vincent.rsf.server.manager.service.WarehouseService;
+import com.vincent.rsf.server.system.entity.User;
+import com.vincent.rsf.server.system.service.UserService;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Data
+@TableName("man_loc_area_mat")
+public class LocAreaMat implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ApiModelProperty(value= "ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 閫昏緫缂栧彿
+     */
+    @ApiModelProperty(value= "閫昏緫缂栧彿")
+    private String code;
+
+    /**
+     * 浠撳簱ID(*)
+     */
+    @ApiModelProperty(value= "浠撳簱ID(*)")
+    private Long warehouseId;
+
+    /**
+     * 搴撳尯ID(*)
+     */
+    @ApiModelProperty(value= "搴撳尯ID(*)")
+    private Long areaId;
+
+    /**
+     * 閫昏緫鎻忚堪
+     */
+    @ApiModelProperty(value= "閫昏緫鎻忚堪")
+    private String depict;
+
+    /**
+     * 鐘舵�� 1: 姝e父  0: 鍐荤粨  
+     */
+    @ApiModelProperty(value= "鐘舵�� 1: 姝e父  0: 鍐荤粨  ")
+    private Integer status;
+
+    /**
+     * 鏄惁鍒犻櫎 1: 鏄�  0: 鍚�  
+     */
+    @ApiModelProperty(value= "鏄惁鍒犻櫎 1: 鏄�  0: 鍚�  ")
+    @TableLogic
+    private Integer deleted;
+
+    /**
+     * 绉熸埛
+     */
+    @ApiModelProperty(value= "绉熸埛")
+    private Integer tenantId;
+
+    /**
+     * 娣诲姞浜哄憳
+     */
+    @ApiModelProperty(value= "娣诲姞浜哄憳")
+    private Long createBy;
+
+    /**
+     * 娣诲姞鏃堕棿
+     */
+    @ApiModelProperty(value= "娣诲姞鏃堕棿")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /**
+     * 淇敼浜哄憳
+     */
+    @ApiModelProperty(value= "淇敼浜哄憳")
+    private Long updateBy;
+
+    /**
+     * 淇敼鏃堕棿
+     */
+    @ApiModelProperty(value= "淇敼鏃堕棿")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /**
+     * 澶囨敞
+     */
+    @ApiModelProperty(value= "澶囨敞")
+    private String memo;
+
+    public LocAreaMat() {}
+
+    public LocAreaMat(String code, Long warehouseId, Long areaId, String depict, Integer status, Integer deleted, Integer tenantId, Long createBy, Date createTime, Long updateBy, Date updateTime, String memo) {
+        this.code = code;
+        this.warehouseId = warehouseId;
+        this.areaId = areaId;
+        this.depict = depict;
+        this.status = status;
+        this.deleted = deleted;
+        this.tenantId = tenantId;
+        this.createBy = createBy;
+        this.createTime = createTime;
+        this.updateBy = updateBy;
+        this.updateTime = updateTime;
+        this.memo = memo;
+    }
+
+//    LocAreaMat locAreaMat = new LocAreaMat(
+//            null,    // 閫昏緫缂栧彿
+//            null,    // 浠撳簱ID(*)
+//            null,    // 搴撳尯ID(*)
+//            null,    // 閫昏緫鎻忚堪
+//            null,    // 鐘舵�乕闈炵┖]
+//            null,    // 鏄惁鍒犻櫎[闈炵┖]
+//            null,    // 绉熸埛
+//            null,    // 娣诲姞浜哄憳
+//            null,    // 娣诲姞鏃堕棿[闈炵┖]
+//            null,    // 淇敼浜哄憳
+//            null,    // 淇敼鏃堕棿[闈炵┖]
+//            null    // 澶囨敞
+//    );
+
+    public String getWarehouseId$(){
+        WarehouseService service = SpringUtils.getBean(WarehouseService.class);
+        Warehouse warehouse = service.getById(this.warehouseId);
+        if (!Cools.isEmpty(warehouse)){
+            return String.valueOf(warehouse.getName());
+        }
+        return null;
+    }
+
+    public String getAreaId$(){
+        WarehouseAreasService service = SpringUtils.getBean(WarehouseAreasService.class);
+        WarehouseAreas warehouseArea = service.getById(this.areaId);
+        if (!Cools.isEmpty(warehouseArea)){
+            return String.valueOf(warehouseArea.getName());
+        }
+        return null;
+    }
+
+    public String getStatus$(){
+        if (null == this.status){ return null; }
+        switch (this.status){
+            case 1:
+                return "姝e父";
+            case 0:
+                return "鍐荤粨";
+            default:
+                return String.valueOf(this.status);
+        }
+    }
+
+    public String getCreateBy$(){
+        UserService service = SpringUtils.getBean(UserService.class);
+        User user = service.getById(this.createBy);
+        if (!Cools.isEmpty(user)){
+            return String.valueOf(user.getNickname());
+        }
+        return null;
+    }
+
+    public String getCreateTime$(){
+        if (Cools.isEmpty(this.createTime)){
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
+    }
+
+    public String getUpdateBy$(){
+        UserService service = SpringUtils.getBean(UserService.class);
+        User user = service.getById(this.updateBy);
+        if (!Cools.isEmpty(user)){
+            return String.valueOf(user.getNickname());
+        }
+        return null;
+    }
+
+    public String getUpdateTime$(){
+        if (Cools.isEmpty(this.updateTime)){
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
+    }
+
+
+
+    public Boolean getStatusBool(){
+        if (null == this.status){ return null; }
+        switch (this.status){
+            case 1:
+                return true;
+            case 0:
+                return false;
+            default:
+                return null;
+        }
+    }
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocAreaMatRela.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocAreaMatRela.java
index e086af8..98f25fe 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocAreaMatRela.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocAreaMatRela.java
@@ -45,6 +45,12 @@
     private Long areaId;
 
     /**
+     * 涓诲崟ID
+     */
+    @ApiModelProperty("涓诲崟ID")
+    private Long areaMatId;
+
+    /**
      * 缂栧彿
      */
     @ApiModelProperty(value= "缂栧彿")
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocTypeRela.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocTypeRela.java
index f26a29b..80a51e7 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocTypeRela.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/LocTypeRela.java
@@ -5,6 +5,8 @@
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.vincent.rsf.server.manager.service.LocService;
+import com.vincent.rsf.server.manager.service.WarehouseService;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -16,6 +18,7 @@
 
 import java.io.Serializable;
 import java.util.Date;
+import java.util.Objects;
 
 @Data
 @Accessors(chain = true)
@@ -50,4 +53,39 @@
         this.typeId = typeId;
     }
 
+//    /**
+//     * @author Ryan
+//     * @description 鑾峰彇搴撲綅
+//     * @param
+//     * @return
+//     * @time 2025/3/24 10:28
+//     */
+//    public String getLocId$() {
+//        if (this.warehouseId == null) { return null; }
+//        WarehouseService warehouseService = SpringUtils.getBean(WarehouseService.class);
+//        Warehouse warehouse = warehouseService.getById(this.warehouseId);
+//        if (Objects.isNull(warehouse)) {
+//            return null;
+//        }
+//        return warehouse.getName();
+//    }
+
+    /**
+     * @author Ryan
+     * @description 鑾峰彇搴撳尯鍚嶇О
+     * @param
+     * @return
+     * @time 2025/3/24 10:27
+     */
+    public String getAreaId$() {
+        if (this.locId == null) { return null; }
+        LocService locService = SpringUtils.getBean(LocService.class);
+        Loc byId = locService.getById(this.locId);
+        if (Objects.isNull(byId)) {
+            return null;
+        }
+        return  byId.getCode();
+    }
+
+
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/LocAreaMatMapper.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/LocAreaMatMapper.java
new file mode 100644
index 0000000..983e57f
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/LocAreaMatMapper.java
@@ -0,0 +1,12 @@
+package com.vincent.rsf.server.manager.mapper;
+
+import com.vincent.rsf.server.manager.entity.LocAreaMat;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface LocAreaMatMapper extends BaseMapper<LocAreaMat> {
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocAreaMatRelaService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocAreaMatRelaService.java
index a8d0b3c..d9feb2c 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocAreaMatRelaService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocAreaMatRelaService.java
@@ -4,8 +4,22 @@
 import com.vincent.rsf.framework.common.R;
 import com.vincent.rsf.server.manager.controller.params.LocAreaMatsParam;
 import com.vincent.rsf.server.manager.entity.LocAreaMatRela;
+import com.vincent.rsf.server.manager.entity.LocType;
+import com.vincent.rsf.server.manager.entity.LocTypeRela;
+import com.vincent.rsf.server.manager.entity.MatnrGroup;
+
+import java.util.List;
+import java.util.Map;
 
 public interface LocAreaMatRelaService extends IService<LocAreaMatRela> {
 
     R binMatnrs(LocAreaMatsParam param);
+
+    Boolean removeByGroupId(Map<String, Object> params);
+
+    boolean removeByLocType(Map<String, Object> params);
+
+    List<MatnrGroup> getAllGroups(Long id);
+
+    List<LocType> getAllLocType(Long id);
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocAreaMatService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocAreaMatService.java
new file mode 100644
index 0000000..1c502ef
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/LocAreaMatService.java
@@ -0,0 +1,8 @@
+package com.vincent.rsf.server.manager.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.vincent.rsf.server.manager.entity.LocAreaMat;
+
+public interface LocAreaMatService extends IService<LocAreaMat> {
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MatnrGroupService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MatnrGroupService.java
index 8344c66..a4cbed1 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MatnrGroupService.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MatnrGroupService.java
@@ -3,7 +3,11 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.vincent.rsf.server.manager.entity.MatnrGroup;
 
+import java.util.List;
+import java.util.Map;
+
 
 public interface MatnrGroupService extends IService<MatnrGroup> {
 
+    List<MatnrGroup> getTreeData(Map<String, Object> map);
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocAreaMatRelaServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocAreaMatRelaServiceImpl.java
index dce36e7..2c7f1c0 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocAreaMatRelaServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocAreaMatRelaServiceImpl.java
@@ -4,20 +4,17 @@
 import com.vincent.rsf.framework.common.R;
 import com.vincent.rsf.framework.exception.CoolException;
 import com.vincent.rsf.server.manager.controller.params.LocAreaMatsParam;
-import com.vincent.rsf.server.manager.entity.LocTypeRela;
-import com.vincent.rsf.server.manager.entity.Matnr;
+import com.vincent.rsf.server.manager.entity.*;
 import com.vincent.rsf.server.manager.mapper.LocAreaMatRelaMapper;
-import com.vincent.rsf.server.manager.entity.LocAreaMatRela;
-import com.vincent.rsf.server.manager.service.LocAreaMatRelaService;
+import com.vincent.rsf.server.manager.service.*;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.vincent.rsf.server.manager.service.LocService;
-import com.vincent.rsf.server.manager.service.LocTypeRelaService;
-import com.vincent.rsf.server.manager.service.MatnrService;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
@@ -31,7 +28,13 @@
     private LocService locService;
 
     @Autowired
+    private MatnrGroupService matnrGroupService;
+
+    @Autowired
     private LocTypeRelaService locTypeRelaService;
+
+    @Autowired
+    private LocTypeService locTypeService;
 
 
     /**
@@ -73,6 +76,7 @@
                     for (Matnr matnrId : matnrIds) {
                         LocAreaMatRela locAreaMatRela = new LocAreaMatRela();
                         locAreaMatRela
+                                .setAreaMatId(param.getAreaMatId())
                                 .setAreaId(param.getAreaId())
                                 .setLocId(locId)
                                 .setLocTypeId(typeId)
@@ -94,6 +98,7 @@
                     LocAreaMatRela locAreaMatRela = new LocAreaMatRela();
                     locAreaMatRela
                             .setAreaId(param.getAreaId())
+                            .setAreaMatId(param.getAreaMatId())
                             .setLocId(locTypeRela.getLocId())
                             .setLocTypeId(locTypeRela.getTypeId())
                             .setMatnrId(matnr.getId())
@@ -107,4 +112,100 @@
         }
         return R.ok("缁戝畾鎴愬姛锛侊紒");
     }
+
+    /**
+     * @author Ryan
+     * @description 绉婚櫎鐗╂枡鍒嗙粍涓嬬粦瀹氬叧绯�
+     * @param
+     * @return
+     * @time 2025/3/24 13:33
+     */
+    @Override
+    public Boolean removeByGroupId(Map<String, Object> param) {
+        if (Objects.isNull(param)) {
+            throw new CoolException("鐗╂枡鍒嗙粍ID涓嶈兘涓虹┖锛侊紒");
+        }
+        if (!StringUtils.isBlank(param.get("groupId").toString())) {
+            throw new CoolException("鐗╂枡鍒嗙被涓嶈兘涓虹┖锛侊紒");
+        }
+        if (!StringUtils.isBlank(param.get("areaMatId").toString())) {
+            throw new CoolException("涓诲崟ID涓嶈兘涓虹┖锛侊紒");
+        }
+        if (!this.remove(new LambdaQueryWrapper<LocAreaMatRela>()
+                .eq(LocAreaMatRela::getAreaMatId, Long.parseLong(param.get("areaMatId").toString()))
+                .eq(LocAreaMatRela::getGroupId, Long.parseLong(param.get("groupId").toString())))) {
+            throw new CoolException("鍒犻櫎澶辫触锛侊紒");
+        }
+
+        return true;
+    }
+
+    /**
+     * @author Ryan
+     * @description 绉婚櫎搴撲綅绫诲瀷缁戝畾鍏崇郴
+     * @param
+     * @return
+     * @time 2025/3/24 13:32
+     */
+    @Override
+    public boolean removeByLocType(Map<String, Object> param) {
+        if (Objects.isNull(param)) {
+            throw new CoolException("搴撲綅绫诲瀷ID涓嶈兘涓虹┖锛侊紒");
+        }
+        if (!this.remove(new LambdaQueryWrapper<LocAreaMatRela>()
+                        .eq(LocAreaMatRela::getAreaMatId, Long.parseLong(param.get("areaMatId").toString()))
+                .eq(LocAreaMatRela::getLocTypeId, Long.parseLong(param.get("typeId").toString())))) {
+            throw new CoolException("鍒犻櫎澶辫触锛侊紒");
+        }
+
+        return true;
+    }
+
+    /**
+     * @author Ryan
+     * @description 鑾峰彇鐗╂枡鍒嗙粍
+     * @param
+     * @return
+     * @time 2025/3/24 13:32
+     */
+    @Override
+    public List<MatnrGroup> getAllGroups(Long id) {
+        if (Objects.isNull(id)) {
+            throw new CoolException("涓诲崟ID涓嶈兘涓虹┖锛侊紒");
+        }
+        List<LocAreaMatRela> locAreaMatRelas = this.list(new LambdaQueryWrapper<LocAreaMatRela>().eq(LocAreaMatRela::getAreaMatId, id));
+        if (locAreaMatRelas.isEmpty()) {
+            throw new CoolException("搴撳尯缁戝畾鐗╂枡涓虹┖锛侊紒");
+        }
+        List<Long> longList = locAreaMatRelas.stream().map(LocAreaMatRela::getGroupId).collect(Collectors.toList());
+        List<MatnrGroup> groups = matnrGroupService.list(new LambdaQueryWrapper<MatnrGroup>().in(MatnrGroup::getId, longList));
+        if (groups.isEmpty()) {
+            throw new CoolException("鏁版嵁閿欒锛氱墿鏂欏垎缁勪笉瀛樺湪锛侊紒");
+        }
+        return groups;
+    }
+
+    /**
+     * @author Ryan
+     * @description 鑾峰彇缁戝畾搴撲綅鐗╂枡
+     * @param
+     * @return
+     * @time 2025/3/24 13:36
+     */
+    @Override
+    public List<LocType> getAllLocType(Long id) {
+        if (Objects.isNull(id)) {
+            throw new CoolException("涓诲崟ID涓嶈兘涓虹┖锛侊紒");
+        }
+        List<LocAreaMatRela> locAreaMatRelas = this.list(new LambdaQueryWrapper<LocAreaMatRela>().eq(LocAreaMatRela::getAreaMatId, id));
+        if (locAreaMatRelas.isEmpty()) {
+            throw new CoolException("搴撳尯缁戝畾鐗╂枡涓虹┖锛侊紒");
+        }
+        List<Long> longList = locAreaMatRelas.stream().map(LocAreaMatRela::getLocTypeId).collect(Collectors.toList());
+        List<LocType> list = locTypeService.list(new LambdaQueryWrapper<LocType>().in(LocType::getId, longList));
+        if (list.isEmpty()) {
+            throw new CoolException("鏁版嵁閿欒锛氬簱浣嶇被鍨嬩笉瀛樺湪锛侊紒");
+        }
+        return list;
+    }
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocAreaMatServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocAreaMatServiceImpl.java
new file mode 100644
index 0000000..bf38451
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocAreaMatServiceImpl.java
@@ -0,0 +1,12 @@
+package com.vincent.rsf.server.manager.service.impl;
+
+import com.vincent.rsf.server.manager.mapper.LocAreaMatMapper;
+import com.vincent.rsf.server.manager.entity.LocAreaMat;
+import com.vincent.rsf.server.manager.service.LocAreaMatService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service("locAreaMatService")
+public class LocAreaMatServiceImpl extends ServiceImpl<LocAreaMatMapper, LocAreaMat> implements LocAreaMatService {
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MatnrGroupServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MatnrGroupServiceImpl.java
index 515ae19..65b0fe6 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MatnrGroupServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MatnrGroupServiceImpl.java
@@ -2,16 +2,48 @@
 
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.vincent.rsf.common.utils.Utils;
 import com.vincent.rsf.framework.common.R;
+import com.vincent.rsf.framework.exception.CoolException;
 import com.vincent.rsf.server.manager.mapper.MatnrGroupMapper;
 import com.vincent.rsf.server.manager.entity.MatnrGroup;
 import com.vincent.rsf.server.manager.service.MatnrGroupService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 @Service("matnrGroupService")
 public class MatnrGroupServiceImpl extends ServiceImpl<MatnrGroupMapper, MatnrGroup> implements MatnrGroupService {
 
+    @Override
+    public List<MatnrGroup> getTreeData(Map<String, Object> map) {
+        List<MatnrGroup> matnrs = new ArrayList<>();
+        if (Objects.isNull(map)) {
+            matnrs = this.list(new LambdaQueryWrapper<MatnrGroup>().orderByAsc(MatnrGroup::getCode));
+        } else {
+            if (Objects.isNull(map.get("condition"))) {
+                 throw new CoolException("condition鍙傛暟涓嶈兘涓虹┖锛侊紒");
+            }
+            if (!StringUtils.isBlank(map.get("condition").toString())) {
+                List<MatnrGroup> groups = this.list(new LambdaQueryWrapper<MatnrGroup>()
+                        .like(MatnrGroup::getName, map.get("condition"))
+                        .orderByAsc(MatnrGroup::getCode));
+                List<Long> collect = groups.stream().map(MatnrGroup::getId).collect(Collectors.toList());
+                List<MatnrGroup> list = this.list(new LambdaQueryWrapper<MatnrGroup>().in(MatnrGroup::getId, collect));
+                matnrs.addAll(list);
+                List<MatnrGroup> treeData = Utils.toTreeData(matnrs, 0L, MatnrGroup::getParentId, MatnrGroup::getId, MatnrGroup::setChildren);
+                return treeData;
+            } else {
+                matnrs = this.list(new LambdaQueryWrapper<MatnrGroup>().orderByAsc(MatnrGroup::getCode));
+            }
+        }
+        List<MatnrGroup> treeData = Utils.toTreeData(matnrs, 0L, MatnrGroup::getParentId, MatnrGroup::getId, MatnrGroup::setChildren);
+        return treeData;
+    }
 }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictDataController.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictDataController.java
index fdf23e4..f450eb6 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictDataController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictDataController.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.vincent.rsf.framework.common.Cools;
 import com.vincent.rsf.framework.common.R;
+import com.vincent.rsf.framework.exception.CoolException;
 import com.vincent.rsf.server.common.utils.ExcelUtil;
 import com.vincent.rsf.server.common.annotation.OperationLog;
 import com.vincent.rsf.server.common.domain.BaseParam;
@@ -55,10 +56,20 @@
     @OperationLog("Create 瀛楀吀鏁版嵁闆�")
     @PostMapping("/dictData/save")
     public R save(@RequestBody DictData dictData) {
+        if (Objects.isNull(dictData.getLabel())) {
+            throw new CoolException("鍒悕涓嶈兘涓虹┖锛侊紒");
+        }
+        if (Objects.isNull(dictData.getValue())) {
+            throw new CoolException("鍊间笉鑳戒负绌猴紒锛�");
+        }
+        if (Objects.isNull(dictData.getDictTypeCode())) {
+            throw new CoolException("缂栫爜涓嶈兘涓虹┖锛侊紒");
+        }
+        if (Objects.isNull(dictData.getDictTypeId())) {
+            throw new CoolException("涓诲崟ID涓嶈兘涓虹┖锛侊紒");
+        }
         dictData.setCreateBy(getLoginUserId());
-        dictData.setCreateTime(new Date());
         dictData.setUpdateBy(getLoginUserId());
-        dictData.setUpdateTime(new Date());
         if (!dictDataService.save(dictData)) {
             return R.error("Save Fail");
         }
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictTypeController.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictTypeController.java
index 1e06e7c..a705dd9 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictTypeController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/DictTypeController.java
@@ -61,13 +61,15 @@
         if (Objects.isNull(dictType.getName())) {
             throw new CoolException("瀛楀吀鍚嶇О涓嶈兘涓虹┖锛侊紒");
         }
-        if (Objects.isNull(dictType.getDescription())) {
-            throw new CoolException("瀛楀吀鎻忚堪涓嶈兘涓虹┖锛侊紒");
-        }
         if (Objects.isNull(dictType.getCode())) {
             throw new CoolException("瀛楀吀缂栫爜涓嶈兘涓虹┖锛侊紒");
         }
-
+        if (!dictTypeService.list(new LambdaQueryWrapper<DictType>().eq(DictType::getCode, dictType.getCode())).isEmpty()) {
+            throw new CoolException("缂栫爜涓嶈兘閲嶅锛侊紒");
+        }
+        if (!dictTypeService.list(new LambdaQueryWrapper<DictType>().eq(DictType::getName, dictType.getName())).isEmpty()) {
+            throw new CoolException("鍚嶇О涓嶈兘閲嶅锛侊紒");
+        }
         if (!dictTypeService.save(dictType)) {
             return R.error("Save Fail");
         }
@@ -78,8 +80,10 @@
     @OperationLog("Update 鏁版嵁瀛楀吀")
     @PostMapping("/dictType/update")
     public R update(@RequestBody DictType dictType) {
+        if (Objects.isNull(dictType)) {
+            throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒");
+        }
         dictType.setUpdateBy(getLoginUserId());
-        dictType.setUpdateTime(new Date());
         if (!dictTypeService.updateById(dictType)) {
             return R.error("Update Fail");
         }
diff --git a/rsf-server/src/main/java/locArea.sql b/rsf-server/src/main/java/locArea.sql
deleted file mode 100644
index 8db2b48..0000000
--- a/rsf-server/src/main/java/locArea.sql
+++ /dev/null
@@ -1,25 +0,0 @@
--- save locArea record
--- mysql
-insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.locArea', '0', '/manager/locArea', 'locArea', '0' , '0', '1' , '1');
-
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query loc areas', '185', '1', 'manager:locArea:list', '0', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create loc areas', '185', '1', 'manager:locArea:save', '1', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update loc areas', '185', '1', 'manager:locArea:update', '2', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete loc areas', '185', '1', 'manager:locArea:remove', '3', '1', '1');
-
--- locale menu name
-locArea: 'LocArea',
-
--- locale field
-locArea: {
-    name: "name",
-    code: "code",
-    areaId: "areaId",
-    locId: "locId",
-},
-
--- ResourceContent
-import locArea from './locArea';
-
-case 'locArea':
-    return locArea;
diff --git a/rsf-server/src/main/java/locAreaMatRela.sql b/rsf-server/src/main/java/locAreaMatRela.sql
deleted file mode 100644
index 5c5e032..0000000
--- a/rsf-server/src/main/java/locAreaMatRela.sql
+++ /dev/null
@@ -1,27 +0,0 @@
--- save locAreaMatRela record
--- mysql
-insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.locAreaMatRela', '0', '/manager/locAreaMatRela', 'locAreaMatRela', '0' , '0', '1' , '1');
-
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query loc areas mats rela', '', '1', 'manager:locAreaMatRela:list', '0', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create loc areas mats rela', '', '1', 'manager:locAreaMatRela:save', '1', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update loc areas mats rela', '', '1', 'manager:locAreaMatRela:update', '2', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete loc areas mats rela', '', '1', 'manager:locAreaMatRela:remove', '3', '1', '1');
-
--- locale menu name
-locAreaMatRela: 'LocAreaMatRela',
-
--- locale field
-locAreaMatRela: {
-    areaId: "areaId",
-    code: "code",
-    matnrId: "matnrId",
-    groupId: "groupId",
-    locTypeId: "locTypeId",
-    locId: "locId",
-},
-
--- ResourceContent
-import locAreaMatRela from './locAreaMatRela';
-
-case 'locAreaMatRela':
-    return locAreaMatRela;
diff --git a/rsf-server/src/main/java/locAreaRela.sql b/rsf-server/src/main/java/locAreaRela.sql
deleted file mode 100644
index d6eb58e..0000000
--- a/rsf-server/src/main/java/locAreaRela.sql
+++ /dev/null
@@ -1,23 +0,0 @@
--- save locAreaRela record
--- mysql
-insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.locAreaRela', '0', '/manager/locAreaRela', 'locAreaRela', '0' , '0', '1' , '1');
-
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query loc areas rela', '', '1', 'manager:locAreaRela:list', '0', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create loc areas rela', '', '1', 'manager:locAreaRela:save', '1', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update loc areas rela', '', '1', 'manager:locAreaRela:update', '2', '1', '1');
-insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete loc areas rela', '', '1', 'manager:locAreaRela:remove', '3', '1', '1');
-
--- locale menu name
-locAreaRela: 'LocAreaRela',
-
--- locale field
-locAreaRela: {
-    locAreaId: "locAreaId",
-    locId: "locId",
-},
-
--- ResourceContent
-import locAreaRela from './locAreaRela';
-
-case 'locAreaRela':
-    return locAreaRela;
diff --git a/rsf-server/src/main/resources/application.yml b/rsf-server/src/main/resources/application.yml
index dbc54f3..b6c0ce1 100644
--- a/rsf-server/src/main/resources/application.yml
+++ b/rsf-server/src/main/resources/application.yml
@@ -31,8 +31,8 @@
     :banner: false
     db-config:
       id-type: auto
-      logic-delete-value: 1
-      logic-not-delete-value: 0
+#      logic-delete-value: 1
+#      logic-not-delete-value: 0
 
 super:
   pwd: xltys1995
diff --git a/rsf-server/src/main/resources/mapper/manager/LocAreaMatMapper.xml b/rsf-server/src/main/resources/mapper/manager/LocAreaMatMapper.xml
new file mode 100644
index 0000000..2751811
--- /dev/null
+++ b/rsf-server/src/main/resources/mapper/manager/LocAreaMatMapper.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.vincent.rsf.server.manager.mapper.LocAreaMatMapper">
+
+</mapper>
diff --git a/rsf-server/src/main/resources/mapper/test/LocAreaMatMapper.xml b/rsf-server/src/main/resources/mapper/test/LocAreaMatMapper.xml
new file mode 100644
index 0000000..086c947
--- /dev/null
+++ b/rsf-server/src/main/resources/mapper/test/LocAreaMatMapper.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.vincent.rsf.server.test.mapper.LocAreaMatMapper">
+
+</mapper>

--
Gitblit v1.9.1