Browse Source

仓库定义

汪钰 3 years ago
parent
commit
6b699cb68e
30 changed files with 7016 additions and 25 deletions
  1. 22 24
      package-lock.json
  2. 52 0
      src/api/classifyManage/index.js
  3. 53 0
      src/api/classifyManage/itemInformation.js
  4. 36 0
      src/api/warehouseManagement/warehouseDefinition.js
  5. 0 0
      src/assets/img/transform.svg
  6. 580 0
      src/assets/js/city.js
  7. 216 0
      src/components/selectTree/index.vue
  8. 3 1
      src/enum/dict.js
  9. 272 0
      src/utils/http.js
  10. 14 0
      src/utils/index.js
  11. 82 0
      src/views/warehouseManagement/common.js
  12. 230 0
      src/views/warehouseManagement/components/AssetsDialog.vue
  13. 128 0
      src/views/warehouseManagement/components/TurnToAsset/Content.vue
  14. 108 0
      src/views/warehouseManagement/components/TurnToAsset/index.vue
  15. 127 0
      src/views/warehouseManagement/components/WareHouseDailog copy.vue
  16. 232 0
      src/views/warehouseManagement/components/WareHouseDailog.vue
  17. 112 0
      src/views/warehouseManagement/components/WarehouseTree.vue
  18. 165 0
      src/views/warehouseManagement/components/enum.js
  19. 398 0
      src/views/warehouseManagement/components/outputType.vue
  20. 347 0
      src/views/warehouseManagement/components/selectType.vue
  21. 60 0
      src/views/warehouseManagement/components/tablePagination.vue
  22. 1409 0
      src/views/warehouseManagement/warehouseDefinition/add.vue
  23. 578 0
      src/views/warehouseManagement/warehouseDefinition/city.js
  24. 287 0
      src/views/warehouseManagement/warehouseDefinition/components/CodePrint.vue
  25. 83 0
      src/views/warehouseManagement/warehouseDefinition/components/GoodsInfoDialog.vue
  26. 298 0
      src/views/warehouseManagement/warehouseDefinition/components/WarehouseEdit.vue
  27. 665 0
      src/views/warehouseManagement/warehouseDefinition/details.vue
  28. 24 0
      src/views/warehouseManagement/warehouseDefinition/enum.js
  29. 393 0
      src/views/warehouseManagement/warehouseDefinition/index.vue
  30. 42 0
      src/views/warehouseManagement/warehouseDefinition/mixins.js

+ 22 - 24
package-lock.json

@@ -1935,29 +1935,6 @@
         "webpack-merge": "^5.7.3",
         "webpack-virtual-modules": "^0.4.2",
         "whatwg-fetch": "^3.6.2"
-      },
-      "dependencies": {
-        "@vue/vue-loader-v15": {
-          "version": "npm:vue-loader@15.10.1",
-          "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-15.10.1.tgz",
-          "integrity": "sha512-SaPHK1A01VrNthlix6h1hq4uJu7S/z0kdLUb6klubo738NeQoLbS6V9/d8Pv19tU0XdQKju3D1HSKuI8wJ5wMA==",
-          "dev": true,
-          "requires": {
-            "@vue/component-compiler-utils": "^3.1.0",
-            "hash-sum": "^1.0.2",
-            "loader-utils": "^1.1.0",
-            "vue-hot-reload-api": "^2.3.0",
-            "vue-style-loader": "^4.1.0"
-          },
-          "dependencies": {
-            "hash-sum": {
-              "version": "1.0.2",
-              "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz",
-              "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
-              "dev": true
-            }
-          }
-        }
       }
     },
     "@vue/cli-shared-utils": {
@@ -2107,6 +2084,27 @@
         }
       }
     },
+    "@vue/vue-loader-v15": {
+      "version": "npm:vue-loader@15.10.1",
+      "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-15.10.1.tgz",
+      "integrity": "sha512-SaPHK1A01VrNthlix6h1hq4uJu7S/z0kdLUb6klubo738NeQoLbS6V9/d8Pv19tU0XdQKju3D1HSKuI8wJ5wMA==",
+      "dev": true,
+      "requires": {
+        "@vue/component-compiler-utils": "^3.1.0",
+        "hash-sum": "^1.0.2",
+        "loader-utils": "^1.1.0",
+        "vue-hot-reload-api": "^2.3.0",
+        "vue-style-loader": "^4.1.0"
+      },
+      "dependencies": {
+        "hash-sum": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz",
+          "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
+          "dev": true
+        }
+      }
+    },
     "@vue/web-component-wrapper": {
       "version": "1.3.0",
       "resolved": "https://registry.npmmirror.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz",
@@ -10233,7 +10231,7 @@
     },
     "vue-hot-reload-api": {
       "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
+      "resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
       "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==",
       "dev": true
     },

+ 52 - 0
src/api/classifyManage/index.js

@@ -0,0 +1,52 @@
+import request from '@/utils/request';
+
+export async function getSubPage (data) {
+  const res = await request.get('/main/categoryLevel/getSubPage', {
+    params: data
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+export async function saveOrUpdate (data) {
+  const res = await request.post('/main/categoryLevel/saveOrUpdate', data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 根据父级id查分类树
+export async function getTreeByPid (parentId) {
+  const res = await request.get(`/main/categoryLevel/getTreeByPid/${parentId}`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 根据类型查分类树
+export async function getTreeByType (type) {
+  const res = await request.get(`/main/categoryLevel/getTreeByType/${type}`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 删除分类
+export async function deleteCategory (id) {
+  const res = await request.get(`/main/categoryLevel/delete/${id}`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//根据ID查询分类详情系信息
+export async function getInfoById (id) {
+  const res = await request.get(`/main/categoryLevel/getById/${id}`);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 53 - 0
src/api/classifyManage/itemInformation.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request';
+// 物品信息列表
+export async function getList (data) {
+  const res = await request.post('/main/category/getList', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 物品信息保存
+export async function informationAdd (data) {
+  const res = await request.post('/main/category/add', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 物品信息编辑
+export async function informationEdit (data) {
+  const res = await request.post('/main/category/edit', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 物品信息详情
+export async function getDetails (id) {
+  const res = await request.get(`/main/category/info/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 物品信息删除
+export async function removeItem (id) {
+  const res = await request.get(`/main/category/remove/${id}`, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 物品信息获取编码
+export async function getOrderNo (prefix) {
+  const res = await request.get(`/main/category/createOrderNo/${prefix}`, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 36 - 0
src/api/warehouseManagement/warehouseDefinition.js

@@ -0,0 +1,36 @@
+// import http from '@/utils/http';
+import request from '@/utils/request';
+export default {
+  //条件查询工厂
+  factorys: function (data) {
+    return request.post('/main/factory/info/factorys', { data });
+  },
+  //列表
+  list: function (params) {
+    return request.get('/main/org/info/list', { params });
+  },
+  //新增
+  save: function (data) {
+    return request.post('/main/org/info/save', { data });
+  },
+  //获取上级机构列表
+  parentList: function (params) {
+    return request.get('/main/org/info/parentList', { params });
+  },
+  //详情
+  info: function (params) {
+    return request.get('/main/org/info/info', { params });
+  },
+  //树
+  // tree: function (params) {
+  //     return http.asyncCall("/main/org/dept/tree", params,'get')
+  // },
+  tree: function (params) {
+    return request.get('/main/org/dept/effectiveTree', { params });
+  }
+};
+
+// 仓储管理-仓库信息的保存
+export const warehouseSave = (data) => {
+  return request.post('/warehouseGoodsshelves/newWarehouse/save', data);
+};

File diff suppressed because it is too large
+ 0 - 0
src/assets/img/transform.svg


+ 580 - 0
src/assets/js/city.js

@@ -0,0 +1,580 @@
+export default [
+  {
+    label: '湖南省',
+    value: '湖南省',
+    children: [
+      {
+        label: '长沙市',
+        value: '长沙市',
+        children: [
+          {
+            label: '芙蓉区',
+            value: '芙蓉区'
+          },
+          {
+            label: '天心区',
+            value: '天心区'
+          },
+          {
+            label: '岳麓区',
+            value: '岳麓区'
+          },
+          {
+            label: '开福区',
+            value: '开福区'
+          },
+          {
+            label: '雨花区',
+            value: '雨花区'
+          },
+          {
+            label: '望城区',
+            value: '望城区'
+          },
+          {
+            label: '长沙县',
+            value: '长沙县'
+          },
+          {
+            label: '宁乡县',
+            value: '宁乡县'
+          },
+          {
+            label: '浏阳市',
+            value: '浏阳市'
+          }
+        ]
+      },
+      {
+        label: '株洲市',
+        value: '株洲市',
+        children: [
+          {
+            label: '荷塘区',
+            value: '荷塘区'
+          },
+          {
+            label: '芦淞区',
+            value: '芦淞区'
+          },
+          {
+            label: '石峰区',
+            value: '石峰区'
+          },
+          {
+            label: '天元区',
+            value: '天元区'
+          },
+          {
+            label: '株洲县',
+            value: '株洲县'
+          },
+          {
+            label: '攸县',
+            value: '攸县'
+          },
+          {
+            label: '茶陵县',
+            value: '茶陵县'
+          },
+          {
+            label: '炎陵县',
+            value: '炎陵县'
+          },
+          {
+            label: '醴陵市',
+            value: '醴陵市'
+          }
+        ]
+      },
+      {
+        label: '湘潭市',
+        value: '湘潭市',
+        children: [
+          {
+            label: '雨湖区',
+            value: '雨湖区'
+          },
+          {
+            label: '岳塘区',
+            value: '岳塘区'
+          },
+          {
+            label: '湘潭县',
+            value: '湘潭县'
+          },
+          {
+            label: '湘乡市',
+            value: '湘乡市'
+          },
+          {
+            label: '韶山市',
+            value: '韶山市'
+          }
+        ]
+      },
+      {
+        label: '衡阳市',
+        value: '衡阳市',
+        children: [
+          {
+            label: '珠晖区',
+            value: '珠晖区'
+          },
+          {
+            label: '雁峰区',
+            value: '雁峰区'
+          },
+          {
+            label: '石鼓区',
+            value: '石鼓区'
+          },
+          {
+            label: '蒸湘区',
+            value: '蒸湘区'
+          },
+          {
+            label: '南岳区',
+            value: '南岳区'
+          },
+          {
+            label: '衡阳县',
+            value: '衡阳县'
+          },
+          {
+            label: '衡南县',
+            value: '衡南县'
+          },
+          {
+            label: '衡山县',
+            value: '衡山县'
+          },
+          {
+            label: '衡东县',
+            value: '衡东县'
+          },
+          {
+            label: '祁东县',
+            value: '祁东县'
+          },
+          {
+            label: '耒阳市',
+            value: '耒阳市'
+          },
+          {
+            label: '常宁市',
+            value: '常宁市'
+          }
+        ]
+      },
+      {
+        label: '邵阳市',
+        value: '邵阳市',
+        children: [
+          {
+            label: '双清区',
+            value: '双清区'
+          },
+          {
+            label: '大祥区',
+            value: '大祥区'
+          },
+          {
+            label: '北塔区',
+            value: '北塔区'
+          },
+          {
+            label: '邵东县',
+            value: '邵东县'
+          },
+          {
+            label: '新邵县',
+            value: '新邵县'
+          },
+          {
+            label: '邵阳县',
+            value: '邵阳县'
+          },
+          {
+            label: '隆回县',
+            value: '隆回县'
+          },
+          {
+            label: '洞口县',
+            value: '洞口县'
+          },
+          {
+            label: '绥宁县',
+            value: '绥宁县'
+          },
+          {
+            label: '新宁县',
+            value: '新宁县'
+          },
+          {
+            label: '城步苗族自治县',
+            value: '城步苗族自治县'
+          },
+          {
+            label: '武冈市',
+            value: '武冈市'
+          }
+        ]
+      },
+      {
+        label: '岳阳市',
+        value: '岳阳市',
+        children: [
+          {
+            label: '岳阳楼区',
+            value: '岳阳楼区'
+          },
+          {
+            label: '云溪区',
+            value: '云溪区'
+          },
+          {
+            label: '君山区',
+            value: '君山区'
+          },
+          {
+            label: '岳阳县',
+            value: '岳阳县'
+          },
+          {
+            label: '华容县',
+            value: '华容县'
+          },
+          {
+            label: '湘阴县',
+            value: '湘阴县'
+          },
+          {
+            label: '平江县',
+            value: '平江县'
+          },
+          {
+            label: '汨罗市',
+            value: '汨罗市'
+          },
+          {
+            label: '临湘市',
+            value: '临湘市'
+          }
+        ]
+      },
+      {
+        label: '常德市',
+        value: '常德市',
+        children: [
+          {
+            label: '武陵区',
+            value: '武陵区'
+          },
+          {
+            label: '鼎城区',
+            value: '鼎城区'
+          },
+          {
+            label: '安乡县',
+            value: '安乡县'
+          },
+          {
+            label: '汉寿县',
+            value: '汉寿县'
+          },
+          {
+            label: '澧县',
+            value: '澧县'
+          },
+          {
+            label: '临澧县',
+            value: '临澧县'
+          },
+          {
+            label: '桃源县',
+            value: '桃源县'
+          },
+          {
+            label: '石门县',
+            value: '石门县'
+          },
+          {
+            label: '津市市',
+            value: '津市市'
+          }
+        ]
+      },
+      {
+        label: '张家界市',
+        value: '张家界市',
+        children: [
+          {
+            label: '永定区',
+            value: '永定区'
+          },
+          {
+            label: '武陵源区',
+            value: '武陵源区'
+          },
+          {
+            label: '慈利县',
+            value: '慈利县'
+          },
+          {
+            label: '桑植县',
+            value: '桑植县'
+          }
+        ]
+      },
+      {
+        label: '益阳市',
+        value: '益阳市',
+        children: [
+          {
+            label: '资阳区',
+            value: '资阳区'
+          },
+          {
+            label: '赫山区',
+            value: '赫山区'
+          },
+          {
+            label: '南县',
+            value: '南县'
+          },
+          {
+            label: '桃江县',
+            value: '桃江县'
+          },
+          {
+            label: '安化县',
+            value: '安化县'
+          },
+          {
+            label: '沅江市',
+            value: '沅江市'
+          }
+        ]
+      },
+      {
+        label: '郴州市',
+        value: '郴州市',
+        children: [
+          {
+            label: '北湖区',
+            value: '北湖区'
+          },
+          {
+            label: '苏仙区',
+            value: '苏仙区'
+          },
+          {
+            label: '桂阳县',
+            value: '桂阳县'
+          },
+          {
+            label: '宜章县',
+            value: '宜章县'
+          },
+          {
+            label: '永兴县',
+            value: '永兴县'
+          },
+          {
+            label: '嘉禾县',
+            value: '嘉禾县'
+          },
+          {
+            label: '临武县',
+            value: '临武县'
+          },
+          {
+            label: '汝城县',
+            value: '汝城县'
+          },
+          {
+            label: '桂东县',
+            value: '桂东县'
+          },
+          {
+            label: '安仁县',
+            value: '安仁县'
+          },
+          {
+            label: '资兴市',
+            value: '资兴市'
+          }
+        ]
+      },
+      {
+        label: '永州市',
+        value: '永州市',
+        children: [
+          {
+            label: '零陵区',
+            value: '零陵区'
+          },
+          {
+            label: '冷水滩区',
+            value: '冷水滩区'
+          },
+          {
+            label: '祁阳县',
+            value: '祁阳县'
+          },
+          {
+            label: '东安县',
+            value: '东安县'
+          },
+          {
+            label: '双牌县',
+            value: '双牌县'
+          },
+          {
+            label: '道县',
+            value: '道县'
+          },
+          {
+            label: '江永县',
+            value: '江永县'
+          },
+          {
+            label: '宁远县',
+            value: '宁远县'
+          },
+          {
+            label: '蓝山县',
+            value: '蓝山县'
+          },
+          {
+            label: '新田县',
+            value: '新田县'
+          },
+          {
+            label: '江华瑶族自治县',
+            value: '江华瑶族自治县'
+          }
+        ]
+      },
+      {
+        label: '怀化市',
+        value: '怀化市',
+        children: [
+          {
+            label: '鹤城区',
+            value: '鹤城区'
+          },
+          {
+            label: '中方县',
+            value: '中方县'
+          },
+          {
+            label: '沅陵县',
+            value: '沅陵县'
+          },
+          {
+            label: '辰溪县',
+            value: '辰溪县'
+          },
+          {
+            label: '溆浦县',
+            value: '溆浦县'
+          },
+          {
+            label: '会同县',
+            value: '会同县'
+          },
+          {
+            label: '麻阳苗族自治县',
+            value: '麻阳苗族自治县'
+          },
+          {
+            label: '新晃侗族自治县',
+            value: '新晃侗族自治县'
+          },
+          {
+            label: '芷江侗族自治县',
+            value: '芷江侗族自治县'
+          },
+          {
+            label: '靖州苗族侗族自治县',
+            value: '靖州苗族侗族自治县'
+          },
+          {
+            label: '通道侗族自治县',
+            value: '通道侗族自治县'
+          },
+          {
+            label: '洪江市',
+            value: '洪江市'
+          }
+        ]
+      },
+      {
+        label: '娄底市',
+        value: '娄底市',
+        children: [
+          {
+            label: '娄星区',
+            value: '娄星区'
+          },
+          {
+            label: '双峰县',
+            value: '双峰县'
+          },
+          {
+            label: '新化县',
+            value: '新化县'
+          },
+          {
+            label: '冷水江市',
+            value: '冷水江市'
+          },
+          {
+            label: '涟源市',
+            value: '涟源市'
+          }
+        ]
+      },
+      {
+        label: '湘西土家族苗族自治州',
+        value: '湘西土家族苗族自治州',
+        children: [
+          {
+            label: '吉首市',
+            value: '吉首市'
+          },
+          {
+            label: '泸溪县',
+            value: '泸溪县'
+          },
+          {
+            label: '凤凰县',
+            value: '凤凰县'
+          },
+          {
+            label: '花垣县',
+            value: '花垣县'
+          },
+          {
+            label: '保靖县',
+            value: '保靖县'
+          },
+          {
+            label: '古丈县',
+            value: '古丈县'
+          },
+          {
+            label: '永顺县',
+            value: '永顺县'
+          },
+          {
+            label: '龙山县',
+            value: '龙山县'
+          }
+        ]
+      }
+    ]
+  }
+]

+ 216 - 0
src/components/selectTree/index.vue

@@ -0,0 +1,216 @@
+<template>
+  <el-select
+    ref="test"
+    :size="size"
+    :disabled="isBindPlan"
+    :value="valueTitle"
+    :clearable="clearable"
+    @clear="clearHandle"
+    :placeholder="placeholder"
+  >
+    <el-option :value="valueTitle" :label="valueTitle" class="options">
+      <slot :pHandleNodeClick="handleNodeClick">
+        <el-tree
+          id="tree-option"
+          ref="selectTree"
+          :key="treeKey"
+          :accordion="accordion"
+          :data="options"
+          :props="props"
+          :node-key="props.value"
+          :default-expand-all="true"
+          :default-expanded-keys="defaultExpandedKey"
+          @node-click="handleNodeClick"
+        >
+        </el-tree>
+      </slot>
+    </el-option>
+  </el-select>
+</template>
+
+<script>
+export default {
+  props: {
+    // 配置项
+    props: {
+      type: Object,
+      default () {
+        return {
+          value: 'value', // ID字段名
+          label: 'label', // 显示名称
+          children: 'children' // 子级字段名
+        }
+      }
+    },
+    // 选项列表数据(树形结构的对象数组)
+    options: { type: Array, default: () => [] },
+    // 初始值
+    value: { type: [String, Number], default: null },
+    // 可清空选项
+    clearable: { type: Boolean, default: false },
+    // 自动收起
+    accordion: { type: Boolean, default: false },
+    // // 可清空选项
+    // disabled: { type: Boolean, default: false },
+    // 多选
+    multiple: { type: Boolean, default: false },
+    //
+
+    placeholder: {
+      type: String,
+      default: '请选择'
+    },
+    size: {
+      type: String,
+      default: 'mini'
+    },
+    dialogType: {
+      type: String,
+      default: ''
+    },
+    tableIndex: { type: Number, default: null },
+    initStr: {
+      type: String,
+      default: ''
+    },
+    isBindPlan: {
+      type: Boolean,
+      default: function () {
+        return false
+      }
+    },
+  },
+  data () {
+    return {
+      valueId: null,
+      treeKey: true,
+      valueTitle: '',
+      defaultExpandedKey: []
+    }
+  },
+  watch: {
+    // 这个需要用深度监听,不然回显有时会失效
+    value: {
+      handler (val) {
+        this.valueId = this.value
+        this.initHandle()
+      },
+      deep: true,
+      immediate: true
+    },
+    options:{
+      handler (val) {
+        this.initHandle()
+      },
+      deep: true,
+      immediate: true
+    },
+    initStr: {
+      handler (newVal, oldVal) {
+        if (this.initStr) {
+          // console.log(newVal);
+          this.valueTitle = newVal
+        }
+      },
+      immediate: true
+    }
+  },
+  // mounted() {
+  //   this.valueId = this.value; // 初始值
+  //   setTimeout(() => {
+  //     this.initHandle();
+  //   },300)
+  // },
+  methods: {
+    // 初始化值
+    async initHandle () {
+      if (this.valueId) {
+        this.$nextTick(async () => {
+          const tempValue = await this.$refs.selectTree.getNode(this.valueId)
+          setTimeout(() => {
+            if (tempValue) {
+              this.valueTitle = tempValue.data[this.props.label] // 初始化显示
+              this.$refs.selectTree.setCurrentKey(this.valueId) // 设置默认选中
+              this.defaultExpandedKey = [this.valueId] // 设置默认展开
+            }
+          }, 300)
+        })
+      } else {
+        this.valueTitle = ''
+      }
+      this.initScroll()
+    },
+    // 初始化滚动条
+    initScroll () {
+      this.$nextTick(() => {
+        let scrollWrap = document.querySelectorAll(
+          '.el-scrollbar .el-select-dropdown__wrap'
+        )[0]
+        let scrollBar = document.querySelectorAll(
+          '.el-scrollbar .el-scrollbar__bar'
+        )
+        scrollWrap.style.cssText =
+          'margin: 0px; max-height: none; overflow: hidden;'
+        scrollBar.forEach(ele => (ele.style.width = 0))
+      })
+    },
+    // 切换选项
+    handleNodeClick (node) {
+      // 多选
+      if (this.multiple) {
+        this.valueTitle += `${node[this.props.label]} , `
+        this.valueId = node[this.props.value]
+        this.$emit('getValue', node)
+        this.defaultExpandedKey = []
+        return
+      }
+      this.valueTitle = node[this.props.label]
+      this.valueId = node[this.props.value]
+      this.$emit('getValue', node)
+      this.defaultExpandedKey = []
+      this.$refs.test.handleClose()
+    },
+    // 清除选中
+    clearHandle () {
+      this.valueTitle = ''
+      this.valueId = null
+      this.defaultExpandedKey = []
+      // this.clearSelected()
+      this.treeKey = !this.treeKey
+      this.$emit('getValue', null)
+    },
+    // 清空选中样式
+    clearSelected () {
+      let allNode = document.querySelectorAll('#tree-option .el-tree-node')
+      allNode.forEach(element => element.classList.remove('is-current'))
+    }
+  }
+}
+</script>
+<style scoped>
+.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
+  height: auto;
+  max-height: 274px;
+  padding: 0;
+  overflow: hidden;
+  overflow-y: auto;
+}
+.el-select-dropdown__item.selected {
+  font-weight: normal;
+}
+ul li >>> .el-tree .el-tree-node__content {
+  height: auto;
+  padding: 0 20px;
+}
+.el-tree-node__label {
+  font-weight: normal;
+}
+.el-tree >>> .is-current .el-tree-node__label {
+  color: #157a2c;
+  font-weight: 700;
+}
+.el-tree >>> .is-current .el-tree-node__children .el-tree-node__label {
+  color: #606266;
+  font-weight: normal;
+}
+</style>

+ 3 - 1
src/enum/dict.js

@@ -8,5 +8,7 @@ export default {
   生命周期: 'life_cycle',
   网络状态: 'network_status',
   金额单位: 'money_unit',
-  时间单位: 'time_unit'
+  时间单位: 'time_unit',
+  仓库状态: 'warehouse_status',
+  仓库类型: 'WD_inventoryList'
 };

+ 272 - 0
src/utils/http.js

@@ -0,0 +1,272 @@
+import store from '@/store';
+import router from '@/router';
+import { Message } from 'element-ui';
+import { getToken, getSeed, setToken } from '@/utils/auth';
+import user from '@/api/user';
+
+var ApiUtil = {
+  // apiPath : 'http://192.168.0.231:8001/index.php',
+  apiPath: process.env.VUE_APP_BASE_API,
+  jsPath: '/start/api/',
+  loginList: ['B00103', 'B00109', '401'],
+  showLoading() {},
+  hideLoading() {},
+  asyncCall(url, params, type, paramType, header) {
+    //异步
+    if (paramType == 'json') {
+      params = JSON.stringify(params);
+    }
+    var settings = {
+      type: type == null ? 'post' : type,
+      params: params ? params : {},
+      header:
+        header == null
+          ? {
+              'zoomwin-token': getToken(),
+              'zoomwin-sid': getSeed()
+            }
+          : '',
+      dataType: 'json',
+      processData: true,
+      contentType:
+        paramType == 'json'
+          ? 'application/json;charset=UTF-8'
+          : 'application/x-www-form-urlencoded',
+      url: url
+    };
+    return this.promiseAjax(settings);
+  },
+  syncCall(url, params, type, paramType, header) {
+    //同步
+    if (paramType == 'json') {
+      params = JSON.stringify(params);
+    }
+    var settings = {
+      type: type == null ? 'post' : type,
+      params: params ? params : {},
+      header:
+        header == null
+          ? {
+              'zoomwin-token': getToken(),
+              'zoomwin-sid': getSeed()
+            }
+          : '',
+      dataType: 'json',
+      processData: true,
+      contentType:
+        paramType == 'json'
+          ? 'application/json;charset=UTF-8'
+          : 'application/x-www-form-urlencoded',
+      url: url
+    };
+    return this.call(settings);
+  },
+  syncUploadCall(url, params) {
+    //上传图片
+    var settings = {
+      type: 'post',
+      params: params,
+      header: {
+        'zoomwin-token': getToken(),
+        'zoomwin-sid': getSeed()
+      },
+      dataType: 'json',
+      contentType: false,
+      processData: false,
+      url: url
+    };
+    return this.call(settings);
+  },
+  //同步ajax
+  call(settings) {
+    if (settings.url == null) {
+      Message.warning('访问地址不能为空!');
+      return;
+    }
+    this.showLoading();
+    var data = null;
+    let _this = this;
+    $.ajax({
+      type: settings.type,
+      data: settings.params,
+      headers: settings.header,
+      dataType: settings.dataType,
+      contentType: settings.contentType,
+      processData: settings.processData,
+      url: ApiUtil.apiPath + settings.url,
+      cache: false,
+      async: false,
+      success: function (result) {
+        if (result.success) {
+          ApiUtil.hideLoading();
+          data = result;
+        } else {
+          if (result.code == 'B00101') {
+            let info = JSON.parse(localStorage.getItem('orgInfo'));
+            let form = {
+              token: getToken(),
+              seed: info.metaSeed,
+              sid: info.sessionId
+            };
+            let token = user.refreshToken(form);
+            setToken(token);
+            settings.header['zoomwin-token'] = token;
+            data = _this.call(settings);
+          } else if (ApiUtil.loginList.includes(result.code)) {
+            Message({
+              message: result.message,
+              type: 'error',
+              duration: 1000
+            });
+            store.dispatch('user/physicalExit');
+            router.push('/login');
+          } else {
+            Message({
+              message: result.message,
+              type: 'error',
+              duration: 1000
+            });
+          }
+          data = false;
+        }
+      },
+      error: function (err) {
+        ApiUtil.hideLoading();
+        Message.error(err.statusText);
+      }
+    });
+    return data;
+  },
+  //异步ajax
+  promiseAjax(settings) {
+    if (settings.url == null) {
+      Message.warning('访问地址不能为空!');
+      return;
+    }
+    this.showLoading();
+    let _this = this;
+
+    return new Promise(function (resolve, reject) {
+      var result = null;
+      $.ajax({
+        type: settings.type,
+        data: settings.params,
+        headers: settings.header,
+        dataType: settings.dataType,
+        contentType: settings.contentType,
+        processData: settings.processData,
+        url: ApiUtil.apiPath + settings.url,
+        timeout: settings.timeout || 20000,
+        cache: false,
+        async: true,
+        success: function (res) {
+          if (res.success) {
+            resolve(res);
+          } else {
+            if (res.code == 'B00101') {
+              let info = JSON.parse(localStorage.getItem('orgInfo'));
+              let form = {
+                token: getToken(),
+                seed: info.metaSeed,
+                sid: info.sessionId
+              };
+              let token = user.refreshToken(form);
+              setToken(token);
+              settings.header['zoomwin-token'] = token;
+              _this.promiseAjax(settings).then((res) => {
+                resolve(res);
+              });
+            } else if (ApiUtil.loginList.includes(res.code)) {
+              Message.error(res.message);
+              store.dispatch('user/physicalExit');
+              router.push('/login');
+              reject(res);
+            } else {
+              Message.error(res.message);
+              reject(res);
+            }
+          }
+        },
+        error: function (err) {
+          Message.error(err.statusText);
+          reject(err.statusText);
+        }
+      });
+    });
+  },
+  import: function (modules, callback) {
+    var returnApi = {};
+    var importApi = [];
+    for (var i = 0; i < modules.length; i++) {
+      // import('./'+modules[i]+'.js').then(result=>{
+      // 	for(var apis in result){
+      // 		for(var func in result[apis]){
+      // 			window.Api[func] = result[apis][func];
+      // 		}
+      // 	}
+      // 	this.readyFunc();
+      // },error=>{
+      // 	alert('没有此API脚本')
+      // });
+      importApi.push(import(this.jsPath + modules[i] + '.js'));
+    }
+    Promise.all(importApi).then(
+      (result) => {
+        for (var i = 0; i < result.length; i++) {
+          for (var apis in result[i]) {
+            for (var func in result[i][apis]) {
+              returnApi[func] = result[i][apis][func];
+            }
+          }
+        }
+        callback(returnApi);
+      },
+      (error) => {
+        alert('没有此API脚本');
+      }
+    );
+  },
+  resetToken(url, params) {
+    var settings = {
+      type: 'post',
+      params: params,
+      header: {},
+      dataType: 'json',
+      contentType: 'application/x-www-form-urlencoded',
+      processData: true,
+      url: url
+    };
+    var token = null;
+    $.ajax({
+      type: settings.type,
+      data: settings.params,
+      headers: settings.header,
+      dataType: settings.dataType,
+      contentType: settings.contentType,
+      processData: settings.processData,
+      url: ApiUtil.apiPath + settings.url,
+      cache: false,
+      async: false,
+      success: function (result) {
+        if (result.success) {
+          token = result.data;
+        } else {
+          Message({
+            message: result.message,
+            type: 'error',
+            duration: 1000
+          });
+          token = false;
+        }
+      },
+      error: function (err) {
+        ApiUtil.hideLoading();
+        Message.error(err.statusText);
+      }
+    });
+
+    return token;
+  }
+};
+
+export default ApiUtil;

+ 14 - 0
src/utils/index.js

@@ -0,0 +1,14 @@
+export function deepClone(source) {
+  if (!source && typeof source !== 'object') {
+    throw new Error('error arguments', 'deepClone');
+  }
+  const targetObj = source.constructor === Array ? [] : {};
+  Object.keys(source).forEach((keys) => {
+    if (source[keys] && typeof source[keys] === 'object') {
+      targetObj[keys] = deepClone(source[keys]);
+    } else {
+      targetObj[keys] = source[keys];
+    }
+  });
+  return targetObj;
+}

+ 82 - 0
src/views/warehouseManagement/common.js

@@ -0,0 +1,82 @@
+export const tableHeader = selectEquiType => {
+  switch (+selectEquiType) {
+    case 3:
+      return [{ label: '牌号', prop: 'brandNum' }]
+    case 8:
+      return [
+        { label: '型号', prop: 'modelType' },
+        { label: '规格', prop: 'specification' }
+      ]
+    case 4:
+      return [
+        { label: '牌号', prop: 'brandNum' },
+        { label: '型号', prop: 'modelType' }
+      ]
+    case 5: //'周转车'
+      return [
+        { label: '规格', prop: 'specification' },
+        {
+          label: '材质',
+          prop: 'texture',
+          formatter (row) {
+            if (!row?.extendField) return ''
+            const extendField = JSON.parse(row.extendField)
+            return extendField.texture
+          }
+        },
+        {
+          label: '长宽高',
+          prop: '',
+          formatter (row) {
+            if (!row?.extendField) return ''
+            const extendField = JSON.parse(row.extendField)
+            return `${extendField.length || '-'}*${extendField.width || '-'}*${
+              extendField.high || '-'
+            }`
+          }
+        }
+      ]
+    case 2: //'舟皿'
+      return [
+        { label: '规格', prop: 'specification' },
+        { label: '型号', prop: 'modelType' },
+        {
+          label: '长宽高',
+          prop: '',
+          formatter (row) {
+            if (!row?.extendField) return ''
+            const extendField = JSON.parse(row.extendField)
+            return `${extendField.length || '-'}*${extendField.width || '-'}*${
+              extendField.high || '-'
+            }`
+          }
+        }
+      ]
+    case 1: //'设备'
+      return [
+        { label: '型号', prop: 'modelType' },
+        { label: '规格', prop: 'specification' }
+      ]
+    case 6: //'模具'
+      return [
+        { label: '牌号', prop: 'brandNum' },
+        { label: '型号', prop: 'modelType' },
+        {
+          label: '收缩系数',
+          prop: '',
+          formatter (row) {
+            if (!row?.extendField) return ''
+            const extendField = JSON.parse(row.extendField)
+            return extendField.shrinkageCoefficient
+          }
+        }
+      ]
+    case 7: //'备品备件'
+      return [
+        { label: '规格', prop: 'specification' },
+        { label: '型号', prop: 'modelType' }
+      ]
+  }
+
+  return []
+}

+ 230 - 0
src/views/warehouseManagement/components/AssetsDialog.vue

@@ -0,0 +1,230 @@
+<template>
+  <el-dialog :visible.sync="visible" :title="`${title}信息`" width="80vw">
+    <el-form :model="searchForm" label-width="100px">
+      <el-row>
+        <el-col :span="8">
+          <el-form-item label="编号">
+            <el-input
+              type="text"
+              size="small"
+              placeholder="搜索物品编码、名称"
+              v-model="searchForm.key"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8" style="padding-left: 40px">
+          <el-button type="primary" size="small" @click="doSearch"
+            >搜索</el-button
+          >
+        </el-col>
+      </el-row>
+    </el-form>
+    <el-container>
+      <el-aside width="200px" class="wrapper-assets">
+        <AssetTree
+          @handleNodeClick="handleNodeClick"
+          :type="[assetType]"
+          ref="treeList"
+        />
+      </el-aside>
+      <el-main>
+        <el-table
+          ref="multipleTable"
+          :data="tableData"
+          tooltip-effect="dark"
+          height="52vh"
+          :header-cell-style="{ background: '#F0F3F3', border: 'none' }"
+          @selection-change="handleSelectionChange"
+        >
+          <el-table-column prop="assetCode" label="物品编码"></el-table-column>
+          <el-table-column prop="assetName" label="物品名称"></el-table-column>
+          <el-table-column
+            :prop="item.prop"
+            :label="item.label"
+            v-for="(item, index) in tableHeader"
+            :key="index"
+          >
+            <template slot-scope="{ row }">
+              <template v-if="item.formatter">{{
+                item.formatter(row)
+              }}</template>
+              <template v-else>{{ row[item.prop] }}</template>
+            </template></el-table-column
+          >
+
+          <el-table-column prop="realInventoryNum" label="可用库存">
+          </el-table-column>
+          <el-table-column type="selection" width="55"> </el-table-column>
+        </el-table>
+        <div style="text-align: right; padding: 10px">
+          <el-pagination
+            background
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="total"
+            :page-sizes="[5, 10, 20, 50]"
+            :page-size.sync="pages.size"
+            :current-page.sync="pages.page"
+            @current-change="handleCurrentChange"
+            @size-change="handleSizeChange"
+          >
+          </el-pagination>
+        </div>
+      </el-main>
+    </el-container>
+
+    <div slot="footer">
+      <el-button type="primary" @click="confirm">确定</el-button>
+      <el-button @click="cancel">关闭</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+  import AssetTree from '@/components/AssetTree';
+  // import { detailSelect } from '@/api/stockManagement/stockLedger'
+  import { deepClone } from '@/utils';
+  import { tableHeader } from '../common';
+  export default {
+    components: { AssetTree },
+    props: {
+      title: String,
+      assetType: {
+        type: [String, Number],
+        default: ''
+      },
+      warehousingMaterialList: {
+        type: Array,
+        default: () => []
+      }
+    },
+    computed: {
+      tableHeader() {
+        return tableHeader(this.assetType);
+      }
+    },
+
+    data() {
+      return {
+        visible: false,
+        tableData: [],
+        total: 0,
+        pages: {
+          page: 1,
+          size: 10
+        },
+        searchForm: {
+          key: ''
+        },
+        selectionList: [],
+        materialType: '',
+        memoSelection: []
+      };
+    },
+    methods: {
+      open() {
+        this.visible = true;
+        this.selectionList = deepClone(this.warehousingMaterialList);
+        this.$nextTick(() => {
+          this.$refs.treeList.getTreeData();
+          // this.doSearch()
+        });
+      },
+      confirm() {
+        if (!(this.selectionList.length || this.memoSelection.length)) {
+          this.$message.error('请至少选择一条数据!');
+          return;
+        }
+        this.$emit('selectTableData', [
+          ...this.selectionList,
+          ...this.memoSelection
+        ]);
+        this.cancel();
+      },
+      cancel() {
+        this.memoSelection = [];
+        this.multipleSelection = [];
+        this.$refs.multipleTable.clearSelection();
+        this.visible = false;
+      },
+      handleSelectionChange(val) {
+        this.selectionList = val;
+      },
+      handleNodeClick(data) {
+        this.materialType = data.id === data.originId ? '' : data.id;
+        this.doSearch();
+      },
+      handleCurrentChange() {
+        this.getList();
+      },
+      doSearch() {
+        this.pages.page = 1;
+        this.getList();
+      },
+      handleSizeChange() {
+        this.pages.page = 1;
+        this.getList();
+      },
+      async getList() {
+        console.log('getList-------');
+        this.memoSelection = this.selectionList.reduce((cur, pre) => {
+          if (!this.memoSelection.some((i) => i.curId === pre.curId)) {
+            cur.push(pre);
+          }
+          return cur;
+        }, this.memoSelection.slice(0));
+
+        const params = {
+          ...this.pages,
+          ...this.searchForm,
+          code: this.assetType,
+          dimension: 1
+        };
+
+        if (this.materialType) {
+          params.materialType = this.materialType;
+        }
+        const res = await detailSelect(params);
+
+        if (res?.success) {
+          this.tableData = res.data.records.map((item) => {
+            item.curId =
+              item.assetCode +
+              (item.measurementUnit || '') +
+              (item.minPackUnit || '') +
+              (item.unit || '');
+
+            return item;
+          });
+          this.total = res.data.total;
+
+          this.$nextTick(() => {
+            this.tableData.forEach((item) => {
+              const index = this.memoSelection.findIndex(
+                (i) => item.curId === i.curId
+              );
+              if (index > -1) {
+                // 删除还给 multipleSelection
+                this.$refs.multipleTable.toggleRowSelection(item, true);
+                this.memoSelection.splice(index, 1);
+              }
+            });
+          });
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .el-dialog__wrapper {
+    ::v-deep .el-aside {
+      background-color: #fff !important;
+      border: 1px solid #ccc;
+    }
+  }
+
+  .wrapper-assets {
+    max-height: 53vh;
+    overflow: auto;
+  }
+</style>

+ 128 - 0
src/views/warehouseManagement/components/TurnToAsset/Content.vue

@@ -0,0 +1,128 @@
+<template>
+  <div class="asset-content" :class="{ 'asset-root': isRoot }">
+    <div
+      class="asset-items"
+      :class="{ isLeaf: !(item.children && item.children.length) }"
+      v-for="(item, index) in treeList"
+      :key="index"
+    >
+      <div class="asset-label" :title="item.name">
+        <el-radio
+          :value="selected.value"
+          v-if="!(item.children && item.children.length)"
+          :label="item.id"
+          @input="handleChange"
+          >{{ item.name }}</el-radio
+        >
+        <template v-else>
+          {{ item.name }}
+        </template>
+      </div>
+      <AssetContent
+        v-if="item.children && item.children.length"
+        :treeList="item.children"
+        :isRoot="false"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'AssetContent',
+  props: {
+    treeList: {
+      type: Array,
+      default: () => []
+    },
+    isRoot: {
+      type: Boolean,
+      default: true
+    }
+  },
+  inject: ['selected', 'handleSelectedChange'],
+  data () {
+    return {}
+  },
+  created () {},
+  methods: {
+    handleChange (val) {
+      this.handleSelectedChange(val)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+* {
+  box-sizing: border-box;
+}
+.asset-content {
+  display: flex;
+  flex-wrap: wrap;
+  flex: 1;
+
+  &.asset-root {
+    flex: none;
+    border-bottom: 1px solid rgba(170, 170, 170, 1);
+    border-top: 1px solid rgba(170, 170, 170, 1);
+    > .asset-items {
+      border-right: 1px solid rgba(170, 170, 170, 1);
+      border-left: 1px solid rgba(170, 170, 170, 1);
+      border-bottom: 1px solid rgba(170, 170, 170, 1);
+      border-top: none;
+      &:nth-of-type(1) {
+        > .asset-label {
+          // border-top: 1px solid rgba(170, 170, 170, 1) !important;
+        }
+      }
+    }
+
+    > .asset-items.isLeaf {
+      width: 100%;
+      border-right: 1px solid rgba(170, 170, 170, 1);
+      border-left: 1px solid rgba(170, 170, 170, 1);
+    }
+  }
+  > .asset-items {
+    border-bottom: 1px solid rgba(170, 170, 170, 1);
+    &:last-of-type {
+      border-bottom: none;
+    }
+  }
+  .asset-items {
+    display: flex;
+    min-height: 40px;
+    width: 100%;
+    overflow: hidden;
+    &.isLeaf {
+      width: 150px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      -webkit-line-clamp: 1;
+      flex: none;
+      border: none;
+      .asset-label {
+        border: none !important;
+        background-color: #fff;
+        padding-left: 10px;
+        justify-content: flex-start;
+      }
+    }
+
+    .asset-label {
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      -webkit-line-clamp: 1;
+      background-color: rgba(242, 242, 242, 1);
+      border-right: 1px solid rgba(170, 170, 170, 1);
+      width: 150px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+  }
+}
+</style>

+ 108 - 0
src/views/warehouseManagement/components/TurnToAsset/index.vue

@@ -0,0 +1,108 @@
+<template>
+  <el-dialog
+    :visible.sync="visible"
+    title="选择资产分类"
+    @before-close="cancel"
+    width="80vw"
+  >
+    <div v-loading="treeLoading" style="height: 60vh; overflow: auto">
+      <Content :treeList="treeList" />
+    </div>
+    <div slot="footer" class="footer">
+      <el-button type="text" @click="clear" style="float: left">清除</el-button>
+      <el-button type="primary" @click="confirm">确定选中</el-button>
+      <el-button @click="cancel">关闭</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+  import Content from './Content.vue';
+  // import common from '@/api/common'
+
+  let callback = null;
+  export default {
+    components: { Content },
+    provide() {
+      return {
+        selected: this.selected,
+        handleSelectedChange: this.handleSelectedChange
+      };
+    },
+    data() {
+      return {
+        visible: false,
+        treeLoading: false,
+        treeList: [],
+        selected: {
+          value: ''
+        }
+      };
+    },
+    created() {
+      this.getTrees();
+    },
+    methods: {
+      open(value) {
+        this.visible = true;
+        this.selected.value = value;
+        return new Promise((res) => {
+          callback = res;
+        });
+      },
+      clear() {
+        this.selected.value = '';
+      },
+      handleSelectedChange(value) {
+        this.selected.value = value;
+      },
+      confirm() {
+        callback &&
+          callback({ code: this.selected.value, name: this.getName() });
+        this.$emit('success', this.selected.value);
+        this.cancel();
+      },
+
+      getName() {
+        if (!this.selected.value) return '';
+        let res = '';
+        const fn = (list, parent = []) => {
+          if (res) return;
+          for (const p of list) {
+            const str = p.name;
+
+            if (res) break;
+            if (p.id === this.selected.value) {
+              res = [...parent, str].join('/');
+              return;
+            }
+
+            if (p.children?.length) {
+              fn(p.children, [...parent, str]);
+            }
+          }
+        };
+        fn(this.treeList);
+
+        return res;
+      },
+      cancel() {
+        this.selected.value = '';
+        this.visible = false;
+      },
+      async getTrees() {
+        this.treeLoading = true;
+        const res = await common.getClassify({ type: '1,2,5,6,7' });
+        this.treeLoading = false;
+        if (res.success) {
+          this.treeList = res.data;
+        }
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  .footer {
+    text-align: right;
+  }
+</style>

+ 127 - 0
src/views/warehouseManagement/components/WareHouseDailog copy.vue

@@ -0,0 +1,127 @@
+<template>
+  <el-dialog :visible.sync="visible" title="仓库" @before-close="cancel">
+    <h3>仓库:{{ value | valueFilter }}</h3>
+    <el-cascader-panel
+      :props="warehouseNameProps"
+      v-model="value"
+    ></el-cascader-panel>
+    <template slot="footer">
+      <el-button @click="cancel">取消</el-button>
+      <el-button type="primary" @click="confirm">确认</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+  // import {
+  //   getWarehouse,
+  //   getReservoir,
+  //   getShelves,
+  //   getLocation
+  // } from '@/api/stockManagement'
+
+  export default {
+    data() {
+      return {
+        visible: false,
+        value: '',
+        row: {},
+        warehouseNameProps: {
+          lazy: true,
+          lazyLoad(node, resolve) {
+            const { level } = node;
+
+            const api = {
+              0: getWarehouse, //仓库
+              1: getReservoir, //库区
+              2: getShelves, // 货架
+              3: getLocation //货位
+            };
+            if (api[level]) {
+              const params = {};
+              if (level > 0) {
+                params.id = node.value.split('-')[0];
+              }
+              api[level](params)
+                .then((res) => {
+                  if (res.success) {
+                    const arr = [];
+                    for (const key in res.data) {
+                      arr.push({
+                        value: `${key}-${res.data[key]}`,
+                        label: res.data[key] || key,
+                        leaf: level >= 3
+                      });
+                    }
+                    resolve(arr);
+                  }
+                })
+                .catch(() => {
+                  resolve([]);
+                });
+            } else {
+              resolve([]);
+            }
+          }
+        }
+      };
+    },
+    filters: {
+      valueFilter(inp) {
+        if (Array.isArray(inp) && inp.length) {
+          return inp.map((item) => item.split('-')[1]).join('-');
+        }
+
+        return '';
+      }
+    },
+    methods: {
+      open(row) {
+        this.row = row;
+        this.value = row.warehouseAreaGoodsAllocationCode
+          ? [
+              `${row.warehouseName}-${row.warehouseName}`,
+              `${row.warehouseAreaName}-${row.warehouseAreaName}`,
+              `${row.warehouseAreaGoodsCode}-${row.warehouseAreaGoodsCode}`,
+              `${row.warehouseAreaGoodsAllocationCode}-${row.warehouseAreaGoodsAllocationCode}`
+            ]
+          : [];
+        this.visible = true;
+      },
+      cancel() {
+        this.value = [];
+        this.visible = false;
+      },
+      confirm() {
+        if (this.value.length < 3) return this.$message.error('请选择仓库!');
+        const [warehouseId, warehouseName] = this.value[0].split('-');
+        const [warehouseAreaId, warehouseAreaName] = this.value[1].split('-');
+        const [warehouseAreaGoodsId, warehouseAreaGoodsCode] =
+          this.value[2].split('-');
+        const [
+          warehouseAreaGoodsAllocationId,
+          warehouseAreaGoodsAllocationCode
+        ] = this.value[3].split('-');
+
+        this.row.warehouseId = warehouseId;
+        this.row.warehouseName = warehouseName;
+        this.row.warehouseAreaId = warehouseAreaId;
+        this.row.warehouseAreaName = warehouseAreaName;
+        this.row.warehouseAreaGoodsId = warehouseAreaGoodsId;
+        this.row.warehouseAreaGoodsCode = warehouseAreaGoodsCode;
+        this.row.warehouseAreaGoodsAllocationId =
+          warehouseAreaGoodsAllocationId;
+        this.row.warehouseAreaGoodsAllocationCode =
+          warehouseAreaGoodsAllocationCode;
+
+        this.cancel();
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  h3 {
+    margin-bottom: 10px;
+  }
+</style>

+ 232 - 0
src/views/warehouseManagement/components/WareHouseDailog.vue

@@ -0,0 +1,232 @@
+<template>
+  <el-dialog
+    :visible.sync="visible"
+    title="仓库"
+    @before-close="cancel"
+    width="1000px"
+  >
+    <el-form :model="formData" label-width="100px">
+      <el-row>
+        <el-col :span="8">
+          <el-form-item label="选择仓库">
+            <el-select v-model="warehouse">
+              <el-option
+                v-for="(item, index) in warehouseList"
+                :key="index"
+                :label="item.name"
+                :value="item.id"
+                @click.native="formData.warehouse = item"
+              ></el-option>
+            </el-select> </el-form-item
+        ></el-col>
+        <el-col :span="8">
+          <el-form-item label="选择库区">
+            <el-select v-model="area">
+              <el-option
+                v-for="(item, index) in areaList"
+                :key="index"
+                :label="item.areaCode"
+                :value="item.areaId"
+                @click.native="formData.area = item"
+              ></el-option>
+            </el-select> </el-form-item
+        ></el-col>
+        <el-col :span="8">
+          <el-form-item label="选择货架">
+            <el-select v-model="shelves">
+              <el-option
+                v-for="(item, index) in shelvesList"
+                :key="index"
+                :label="item.goodsshelvesCode"
+                :value="item.goodsshelvesId"
+                @click.native="formData.shelves = item"
+              ></el-option>
+            </el-select> </el-form-item
+        ></el-col>
+      </el-row>
+    </el-form>
+    <div class="status-legend">
+      <div
+        v-for="(item, index) in warehouseDefinition_locationStatus"
+        :key="index"
+      >
+        <span :style="{ 'background-color': item.color }"></span
+        >{{ item.label }}
+      </div>
+    </div>
+    <div class="content-box">
+      <div
+        v-for="p in locationList"
+        :key="p.id"
+        class="box"
+        @click="cur = p"
+        :class="{ active: cur.goodsAllocationId == p.goodsAllocationId }"
+        :style="{
+          'background-color': getStatus(p.allocationStatus).color,
+          cursor: [1, 2].includes(p.allocationStatus)
+            ? 'pointer'
+            : 'not-allowed'
+        }"
+      >
+        {{ p.goodsAllocationCode }}
+      </div>
+      <div class="placeholder-box"></div>
+      <div class="placeholder-box"></div>
+      <div class="placeholder-box"></div>
+      <div class="placeholder-box"></div>
+    </div>
+    <template slot="footer">
+      <el-button @click="handleSelect" type="primary">确认</el-button>
+      <el-button @click="cancel">关闭</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+  // import { getWarehouseChildren } from '@/api/stockManagement/outgoingManagement'
+  // import { warehouseDefinition_locationStatus } from '@/utils/dict/warehouseDefinition';
+  // import { useDict } from '@/utils/dict/index';
+  export default {
+    data() {
+      return {
+        warehouseDefinition_locationStatus: [
+          { code: 1, label: '空置', color: 'rgba(202, 249, 130, 1)' },
+          { code: 2, label: '在用', color: 'rgba(129, 211, 248, 1)' },
+          { code: 3, label: '已满', color: 'rgba(255, 14, 14, 1)' },
+          { code: 4, label: '失效', color: 'rgba(215, 215, 215, 1)' }
+        ],
+        visible: false,
+        value: '',
+        row: {},
+        formData: {
+          warehouse: {},
+          area: {},
+          shelves: {}
+        },
+        warehouse: '',
+        area: '',
+        shelves: '',
+        warehouseList: [],
+        cur: {
+          cargoSpaceId: ''
+        }
+      };
+    },
+    computed: {
+      areaList() {
+        this.area = '';
+        this.shelves = '';
+        return (
+          this.warehouseList.find((i) => i.id === this.warehouse)
+            ?.wareHouseArea || []
+        );
+      },
+      shelvesList() {
+        this.shelves = '';
+        return (
+          this.areaList.find((i) => i.areaId === this.area)
+            ?.wareHouseGoodsshelves || []
+        );
+      },
+      locationList() {
+        return (
+          this.shelvesList.find((i) => i.goodsshelvesId === this.shelves)
+            ?.wareHouseGoodsAllocation || []
+        );
+      }
+    },
+    created() {
+      this._getWarehouseChildren();
+    },
+    methods: {
+      getStatus: useDict(warehouseDefinition_locationStatus),
+      open(row) {
+        this.row = row;
+        this.cur = row;
+        this.cur.goodsAllocationId = row.cargoSpaceId;
+        this.cur.goodsAllocationCode = row.cargoSpaceCode;
+        this.warehouse = this.row?.warehouseId || '';
+        this.$nextTick(() => {
+          this.area = this.row?.areaId || '';
+          this.$nextTick(() => {
+            this.shelves = this.row?.shelfId || '';
+          });
+        });
+
+        this.visible = true;
+      },
+      handleSelect() {
+        if (![1, 2].includes(this.cur.allocationStatus)) {
+          return;
+        }
+        const { warehouse, area, shelves } = this.formData;
+
+        this.row.warehouseId = warehouse.id;
+        this.row.warehouseName = warehouse.name;
+
+        this.row.areaId = area.areaId;
+        this.row.areaName = area.areaName;
+
+        this.row.shelfId = shelves.goodsshelvesId;
+        this.row.shelfCode = shelves.goodsshelvesCode;
+
+        this.row.cargoSpaceId = this.cur.goodsAllocationId;
+        this.row.cargoSpaceCode = this.cur.goodsAllocationCode;
+
+        this.cancel();
+      },
+      async _getWarehouseChildren() {
+        const res = await getWarehouseChildren();
+        if (res?.success) {
+          this.warehouseList = res.data;
+        }
+      },
+      cancel() {
+        this.row = {};
+        this.visible = false;
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .status-legend {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin: 12px 0;
+    div {
+      margin: 0 12px;
+    }
+    span {
+      display: inline-block;
+      width: 13px;
+      height: 13px;
+      margin: 0 4px;
+    }
+  }
+
+  .content-box {
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+    max-height: 40vh;
+    overflow: auto;
+    .box {
+      cursor: pointer;
+      width: 134px;
+      height: 64px;
+      background-clip: content-box;
+      margin-bottom: 4px;
+      line-height: 64px;
+      text-align: center;
+      &:hover,
+      &.active {
+        box-shadow: 2px 2px 2px 2px #ccc;
+      }
+    }
+    .placeholder-box {
+      width: 134px;
+    }
+  }
+</style>

+ 112 - 0
src/views/warehouseManagement/components/WarehouseTree.vue

@@ -0,0 +1,112 @@
+<template>
+  <el-tree
+    ref="tree"
+    :props="props"
+    :filter-node-method="filterNodeMethod"
+    :load="loadNode"
+    class="warehouse-tree"
+    node-key="value"
+    lazy
+  >
+    <template slot-scope="{ node, data }">
+      <div
+        :class="{ isDisabled: data.disabled }"
+        class="node-wrapper"
+        @click="handleNodeClick(data, node)"
+      >
+        <span>{{ node.label }}</span>
+      </div>
+    </template>
+  </el-tree>
+</template>
+
+<script>
+  // import {
+  //   getWarehouse,
+  //   getReservoir,
+  //   getShelves,
+  //   getLocation
+  // } from '@/api/stockManagement'
+  export default {
+    props: {
+      disabledList: {
+        type: Array,
+        default: () => []
+      },
+      filterNodeMethod: Function
+    },
+    data() {
+      return {
+        props: {
+          label: 'label',
+          children: 'children',
+          isLeaf: 'leaf'
+        }
+      };
+    },
+    methods: {
+      getInstance() {
+        return this.$refs.tree;
+      },
+      handleNodeClick(data, node) {
+        // if (data.disabled) return
+        this.$emit('handleNodeClick', data, node);
+      },
+      loadNode(node, resolve) {
+        const { level, data } = node;
+        const api = {
+          0: getWarehouse, //仓库
+          1: getReservoir, //库区
+          2: getShelves, // 货架
+          3: getLocation //货位
+        };
+        if (api[level]) {
+          const params = {};
+          if (level > 0) {
+            params.id = data.value.split('-')[0];
+          }
+          api[level](params)
+            .then((res) => {
+              if (res.success) {
+                const arr = [];
+                for (const key in res.data) {
+                  const value = `${key}-${res.data[key]}-${level}`;
+                  arr.push({
+                    value,
+                    label: res.data[key] || key,
+                    leaf: level >= 3,
+                    disabled: this.disabledList.includes(value)
+                  });
+                }
+                resolve(arr);
+              }
+            })
+            .catch(() => {
+              resolve([]);
+            });
+        } else {
+          resolve([]);
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .isDisabled {
+    background-color: #ccc;
+    cursor: not-allowed;
+  }
+  .node-wrapper {
+    flex: 1;
+  }
+</style>
+
+<style lang="scss">
+  .warehouse-tree {
+    .el-tree-node__content:has(.isDisabled) {
+      background-color: #ccc;
+      cursor: not-allowed;
+    }
+  }
+</style>

+ 165 - 0
src/views/warehouseManagement/components/enum.js

@@ -0,0 +1,165 @@
+// 物料表 inKey:库内
+export const tableContentData = [
+  {
+    name: '物料',
+    tableData: [
+      { label: '物料编码', key: 'materialCode', inKey: 'assetCode' },
+      { label: '物料名称', key: 'materialName', inKey: 'assetName' },
+      { label: '牌号', key: 'tradeMark', inKey: 'brand' },
+      { label: '型号', key: 'model', inKey: 'model' },
+      { label: '单位', key: 'unit', inKey: 'basePackUtil' }
+    ]
+  },
+  {
+    name: '产品',
+    tableData: [
+      { label: '产品编码', key: 'materialCode', inKey: 'assetCode' },
+      { label: '产品名称', key: 'materialName', inKey: 'assetName' },
+      { label: '牌号', key: 'brandNum', inKey: 'brand' },
+      { label: '型号', key: 'model', inKey: 'model' },
+      { label: '单位', key: 'unit', inKey: 'basePackUtil' }
+    ]
+  },
+  {
+    name: '周转车',
+    tableData: [
+      { label: '周转车编码', key: 'code', inKey: 'assetCode' },
+      { label: '周转车名称', key: 'name', inKey: 'assetName' },
+      { label: '规格型号', key: 'model', inKey: 'model' },
+      { label: '单位', key: 'unit', inKey: 'basePackUtil' }
+    ]
+  },
+  {
+    name: '舟皿',
+    tableData: [
+      { label: '舟皿编码', key: 'code', inKey: 'assetCode' },
+      { label: '舟皿名称', key: 'name', inKey: 'assetName' },
+      { label: '规格型号', key: 'model', inKey: 'model' },
+      { label: '单位', key: 'unit', inKey: 'basePackUtil' }
+    ]
+  },
+  {
+    name: '生产设备',
+    tableData: [
+      { label: '设备编码', key: 'code', inKey: 'assetCode' },
+      { label: '设备名称', key: 'name', inKey: 'assetName' },
+      { label: '规格型号', key: 'specifications', inKey: 'model' },
+      { label: '单位', key: 'pkgUnit', inKey: 'basePackUtil' }
+    ]
+  },
+  {
+    name: '模具',
+    tableData: [
+      { label: '模具编码', key: 'code', inKey: 'assetCode' },
+      { label: '模具名称', key: 'name', inKey: 'assetName' },
+      { label: '规格型号', key: 'model', inKey: 'model' },
+      { label: '单位', key: 'unit', inKey: 'basePackUtil' }
+    ]
+  },
+  {
+    name: '备品备件',
+    tableData: [
+      { label: '备件编码', key: 'code', inKey: 'assetCode' },
+      { label: '备件名称', key: 'name', inKey: 'assetName' },
+      { label: '备件类型', key: 'model', inKey: 'model' },
+      { label: '型号', key: 'unit', inKey: 'basePackUtil' }
+    ]
+  }
+]
+
+// *入库明细
+export const warehousingMaterialListTable = {
+  物料: {
+    assetId: 'id',
+    assetCode: 'materialCode', //编码
+    assetName: 'materialName', //名称
+    batchNo: 'batchNo', //批次号
+    brandNum: 'tradeMark', //牌号
+    modelType: 'model', //型号
+    materialId: 'classificationId', //类型
+    materialName: 'classificationName', //类型
+    amount: 'price', //单价
+    realInventoryNum: 'inventoryLibrary', //实时库存
+    realInventoryAmount: '', //实时库存金额
+    outInAmount: '', //入库总额
+    unit: 'unit', //单位
+    minimumPackingUnit: '', //最小包装单位
+    minimumUnit: '', //最小单元
+    warehouseName: '' //仓库
+  },
+  周转车: {
+    assetId: 'id',
+    assetCode: 'code', //编码
+    assetName: 'name', //名称
+    batchNo: '', //批次号
+    brandNum: 'model', //牌号
+    materialId: 'classificationId', //类型
+    materialName: 'classificationName', //类型
+    amount: 'price', //单价
+    realInventoryNum: 'inventoryLibrary', //实时库存
+    realInventoryAmount: '', //实时库存金额
+    outInAmount: '', //入库总额
+    unit: 'unit', //单位
+    warehouseName: '' //仓库
+  },
+  舟皿: {
+    assetId: 'id',
+    assetCode: 'code', //编码
+    assetName: 'name', //名称
+    batchNo: '', //批次号
+    brandNum: 'model', //牌号
+    materialId: 'classificationId', //类型
+    materialName: 'classificationName', //类型
+    amount: 'price', //单价
+    realInventoryNum: 'inventoryLibrary', //实时库存
+    realInventoryAmount: '', //实时库存金额
+    outInAmount: '', //入库总额
+    unit: 'unit', //单位
+    warehouseName: '' //仓库
+  },
+  生产设备: {
+    assetId: 'id',
+    assetCode: 'code', //编码
+    assetName: 'name', //名称
+    batchNo: '', //批次号
+    brandNum: 'specifications', //牌号
+    materialId: 'classificationId', //类型
+    materialName: 'classificationName', //类型
+    amount: 'price', //单价
+    realInventoryNum: 'inventoryLibrary', //实时库存
+    realInventoryAmount: '', //实时库存金额
+    outInAmount: '', //入库总额
+    unit: 'pkgUnit', //单位
+    warehouseName: '' //仓库
+  },
+  模具: {
+    assetId: 'id',
+    assetCode: 'code', //编码
+    assetName: 'name', //名称
+    batchNo: '', //批次号
+    brandNum: 'model', //牌号
+    materialId: 'classificationId', //类型
+    materialName: 'classificationName', //类型
+    amount: 'price', //单价
+    realInventoryNum: 'inventoryLibrary', //实时库存
+    realInventoryAmount: '', //实时库存金额
+    outInAmount: '', //入库总额
+    unit: 'unit', //单位
+    warehouseName: '' //仓库
+  },
+  备品备件: {
+    assetId: 'id',
+    assetCode: 'code', //编码
+    assetName: 'name', //名称
+    batchNo: '', //批次号
+    brandNum: 'model', //牌号
+    materialId: 'classificationId', //类型
+    materialName: 'classificationName', //类型
+    amount: 'price', //单价
+    realInventoryNum: 'inventoryLibrary', //实时库存
+    realInventoryAmount: '', //实时库存金额
+    outInAmount: '', //入库总额
+    unit: 'unit', //单位
+    warehouseName: '' //仓库
+  }
+}

+ 398 - 0
src/views/warehouseManagement/components/outputType.vue

@@ -0,0 +1,398 @@
+<template>
+  <el-dialog
+    :visible="visibleDialog"
+    :before-close="cancel"
+    width="80vw"
+    title="选择"
+  >
+    <el-table
+      :data="tableData"
+      ref="multipleTable"
+      border
+      height="60vh"
+      style="width: 100%"
+      :header-cell-style="{ background: '#EEEEEE', border: 'none' }"
+    >
+      <el-table-column label="仓库" prop="warehouseName"> </el-table-column>
+      <el-table-column label="库区" prop="areaName"> </el-table-column>
+      <el-table-column label="货架" prop="shelfCode"> </el-table-column>
+      <el-table-column label="货位" prop="cargoSpaceCode"> </el-table-column>
+      <el-table-column label="批次号" prop="batchNum"> </el-table-column>
+      <el-table-column label="生产日期" prop="manufactureTime">
+      </el-table-column>
+      <template v-if="isMaterial">
+        <el-table-column label="计量单位" prop="measurementUnit">
+        </el-table-column>
+        <el-table-column label="最小单元" prop="minPackUnit">
+          <template slot-scope="{ row }">
+            {{ row.unit }}/{{ row.minPackUnit }}
+          </template>
+        </el-table-column>
+      </template>
+      <template v-else>
+        <el-table-column label="单位" prop="unit"> </el-table-column>
+      </template>
+      <el-table-column label="库存量" prop="realInventoryNum">
+      </el-table-column>
+      <el-table-column label="需要出库数" prop="minimumUnit">
+        <template slot-scope="{ row, $index }">
+          <span style="width: 20px; display: inline-block">{{
+            selectList[row.curId] ||
+            +((confirmMap[row.curId] && confirmMap[row.curId].length) || 0)
+          }}</span>
+          <el-popover
+            placement="bottom"
+            width="470"
+            :key="row.cargoSpaceId"
+            trigger="manual"
+            v-model="row.visible"
+          >
+            <div class="popover-content">
+              <div class="title">
+                已选{{ isMaterial || !row.unit ? '桶数' : `${row.unit}数` }}({{
+                  selectNum
+                }})
+              </div>
+              <div
+                class="popover-row"
+                v-for="(item, index) in curBuketList"
+                :key="index"
+              >
+                <el-checkbox
+                  :value="item.checked"
+                  @click.native.prevent="handleLineSelected(item, index)"
+                ></el-checkbox>
+                <div
+                  class="items"
+                  :class="{ itemActive: itm.isSelected }"
+                  v-for="(itm, idx) in item.children"
+                  :key="idx"
+                  @click="selectBucket(itm, index)"
+                >
+                  {{ itm.num }}
+                </div>
+              </div>
+            </div>
+            <div style="text-align: right; margin: 0">
+              <el-button size="mini" type="text" @click="bucketCancel(row)"
+                >取消</el-button
+              >
+              <el-button
+                type="primary"
+                size="mini"
+                @click="bucketConfirm(row, $index)"
+                >确定</el-button
+              >
+            </div>
+            <el-button
+              type="primary"
+              size="small"
+              slot="reference"
+              @click="openBucket(row, $index)"
+              >选择{{ isMaterial ? '桶号' : '编码' }}</el-button
+            >
+          </el-popover>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="sum-box">
+      <span class="fw">累计出库量</span>
+      <span>{{ selectOpt.sumWeight }}</span>
+      <span v-if="isMaterial">{{ selectOpt.sumNum }}</span>
+    </div>
+    <template slot="footer">
+      <el-button type="primary" @click="confirm">确定</el-button>
+      <el-button @click="cancel">取消</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+  // import {
+  //   getWarehouseActualDetail,
+  //   getWarehouseActualSingle
+  // } from '@/api/stockManagement/stockLedger.js'
+  import { deepClone } from '@/utils';
+  export default {
+    props: {
+      title: {
+        type: String,
+        default: '物料'
+      },
+      warehousingType: {
+        type: [Number, String]
+      },
+      selectedList: {
+        type: Array,
+        default: () => []
+      }
+    },
+    data() {
+      return {
+        tableData: [],
+        visibleDialog: false,
+        buketMap: {}, //桶数据
+        curBuketList: [], //当前展示桶数据
+        curIndex: '', //当前选中库位
+        confirmResolve: null,
+        assetCode: '',
+        assetType: '',
+        confirmMap: {}
+      };
+    },
+    computed: {
+      isMaterial() {
+        return this.title == '物料';
+      },
+      selectList() {
+        let obj = {};
+        for (const key in this.buketMap) {
+          obj[key] = this.buketMap[key].reduce((cur, item) => {
+            return cur + item.children.filter((i) => i.isSelected).length;
+          }, 0);
+        }
+
+        return obj;
+      },
+      // 当前选中
+      selectNum() {
+        return this.curBuketList
+          .map((item) => item.children.filter((i) => i.isSelected))
+          .flat().length;
+      },
+      // 累计选中
+      selectOpt() {
+        let sum = 0;
+
+        const list = [
+          ...Object.values(this.buketMap)
+            .map((item) => {
+              return item
+                .map((i) =>
+                  i.children
+                    .filter((i) => i.isSelected)
+                    .map((i) => {
+                      delete i.createTime;
+
+                      sum += i.measurementUnit || 1;
+                      return i;
+                    })
+                )
+                .flat();
+            })
+            .flat(),
+          ...Object.values(this.confirmMap)
+            .flat()
+            .map((item) => {
+              delete item.createTime;
+
+              sum += item.measurementUnit || 1;
+              return item;
+            })
+        ];
+
+        const {
+          unit = '',
+          minPackUnit = '',
+          measurementUnit = 1
+        } = list[0] || {};
+        const outInNum = list.length;
+        return {
+          sumWeight: sum + unit,
+          outInNum,
+          sumNum: outInNum + minPackUnit,
+          list,
+          minPackUnit
+        };
+      }
+    },
+    methods: {
+      open({ assetCode, assetType }, memo = []) {
+        this.visibleDialog = true;
+        this.assetType = assetType;
+        this.assetCode = assetCode;
+        this.confirmMap = {};
+        memo.map((item) => {
+          if (this.confirmMap[item.pId]) {
+            this.confirmMap[item.pId].push(item);
+          } else {
+            this.$set(this.confirmMap, item.pId, [item]);
+          }
+        });
+        this.handleList(assetCode, assetType);
+
+        return new Promise((res) => (this.confirmResolve = res));
+      },
+      handleSelectionChange(row, val) {
+        this.$set(this.selectOpt, row.id, val);
+      },
+      // 桶号数据
+      async openBucket(row, index) {
+        this.tableData.forEach((item) => {
+          this.$set(item, 'visible', false);
+        });
+        this.$set(row, 'visible', true);
+        this.curIndex = row.curId;
+
+        if (this.buketMap[row.curId]) {
+          this.curBuketList = deepClone(this.buketMap[row.curId]);
+          return;
+        }
+
+        const res = await getWarehouseActualSingle({
+          areaId: row.areaId,
+          cargoSpaceId: row.cargoSpaceId,
+          shelfId: row.shelfId,
+          warehouseId: row.warehouseId,
+          batchNum: row.batchNum,
+          manufactureTime: row.manufactureTime,
+          warehousingType: this.assetType,
+          warehousingCode: this.assetCode
+        });
+        if (res?.success) {
+          let len = Math.ceil(res.data.length / 6);
+
+          // res.data.forEach(item => {
+          //   const same = this.selectedList.filter(i => i.assetCode === item.assetCode)
+
+          //   item.isSelected = same.length && same
+          // })
+          // if ((this.buketMap, index))
+          const confirmList = this.confirmMap[row.curId] || [];
+          this.curBuketList = Array.from(new Array(len), (itm, idx) => {
+            const item = {
+              id: idx,
+              checked: false,
+              children: res.data.slice(idx * 6, (idx + 1) * 6).map((i) => {
+                if (confirmList.some((itm) => i.num === itm.num)) {
+                  i.isSelected = true;
+                }
+                i.pId = row.curId;
+                return i;
+              })
+            };
+            return item;
+          });
+          this.$set(this.buketMap, row.curId, deepClone(this.curBuketList));
+          this.confirmMap[row.curId] = [];
+        }
+      },
+      // 桶 取消
+      bucketCancel(row) {
+        row.visible = false;
+      },
+      // 桶 确认
+      bucketConfirm(row, index) {
+        this.buketMap[row.curId] = deepClone(this.curBuketList);
+
+        this.bucketCancel(row);
+      },
+      // 桶选中
+      selectBucket(itm, parentIndex) {
+        this.$set(itm, 'isSelected', !itm.isSelected);
+
+        if (!itm.isSelected) {
+          this.curBuketList[parentIndex].checked = false;
+        }
+      },
+      // 桶全选
+      handleLineSelected(item, index) {
+        item.checked = !item.checked;
+
+        this.curBuketList[index].children.map((itm) => {
+          this.$set(itm, 'isSelected', item.checked);
+        });
+      },
+      // 表格数据
+      async handleList(assetCode, assetType) {
+        const params = {
+          assetCode,
+          assetType
+        };
+        const res = await getWarehouseActualDetail(params);
+        if (res?.success) {
+          this.tableData = res.data.map((item) => {
+            item.curId =
+              item.areaId +
+              item.measurementUnit +
+              item.minPackUnit +
+              item.unit +
+              item.warehouseName +
+              item.warehouseId +
+              item.shelfId +
+              item.cargoSpaceId +
+              item.manufactureTime +
+              item.batchNum;
+
+            return item;
+          });
+        }
+      },
+      confirm() {
+        const { list } = this.selectOpt;
+        if (!list?.length) return this.$message.error('请选择一条数据!');
+        this.confirmResolve && this.confirmResolve(this.selectOpt);
+        this.cancel();
+      },
+      cancel() {
+        this.tableData = [];
+        this.curBuketList = [];
+        this.buketMap = {};
+        this.visibleDialog = false;
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  .pagination {
+    display: flex;
+    justify-content: flex-end;
+    padding: 10px;
+  }
+
+  .sum-box {
+    width: 288px;
+    height: 25px;
+    line-height: 25px;
+    text-align: center;
+    margin: 20px 0 0 auto;
+    background-color: rgba(242, 242, 242, 1);
+
+    .fw {
+      font-weight: bold;
+    }
+    span + span {
+      margin-left: 20px;
+    }
+  }
+
+  .popover-content {
+    .popover-row {
+      display: flex;
+      align-items: center;
+      margin-bottom: 8px;
+      .items {
+        cursor: pointer;
+        width: 63px;
+        height: 20px;
+        line-height: 20px;
+        text-align: center;
+        background-color: rgba(242, 242, 242, 1);
+        color: #333;
+        margin-left: 8px;
+
+        &.itemActive {
+          background-color: rgba(112, 182, 3, 1);
+          color: #fff;
+        }
+      }
+    }
+
+    .title {
+      text-align: right;
+      border-bottom: 1px solid #333;
+      margin-bottom: 12px;
+      font-size: 20px;
+    }
+  }
+</style>

+ 347 - 0
src/views/warehouseManagement/components/selectType.vue

@@ -0,0 +1,347 @@
+<template>
+  <div>
+    <el-dialog
+      :title="`${title}信息`"
+      append-to-body
+      :visible="visibleDialog"
+      :before-close="closeWindows"
+      width="80vw"
+    >
+      <div class="search_box">
+        <el-col :span="8">
+          <el-input v-model="value" placeholder="搜索物品编码、名称">
+            <el-button
+              slot="append"
+              type="primary"
+              icon="el-icon-search"
+              size="small"
+              @click="handleSearch"
+              >搜索</el-button
+            >
+          </el-input>
+        </el-col>
+      </div>
+      <div class="flex_info">
+        <div class="flex_left">
+          <AssetTree
+            @handleNodeClick="handleNodeClick"
+            :type="type"
+            :init="true"
+            ref="treeList"
+          />
+        </div>
+        <div class="flex_right">
+          <el-table
+            ref="multipleTable"
+            :data="tableData"
+            tooltip-effect="dark"
+            height="80vh"
+            style="width: 100%"
+            :header-cell-style="{ background: '#F0F3F3', border: 'none' }"
+            @selection-change="handleSelectionChange"
+          >
+            <el-table-column width="80px" label="序号">
+              <template slot-scope="{ $index }">
+                {{ $tableIndex($index, pages.page, pages.size) }}
+              </template>
+            </el-table-column>
+            <el-table-column
+              prop="assetCode"
+              label="物品编码"
+            ></el-table-column>
+            <el-table-column
+              prop="assetName"
+              label="物品名称"
+            ></el-table-column>
+            <el-table-column
+              :prop="item.prop"
+              :label="item.label"
+              v-for="(item, index) in tableHeader"
+              :key="index"
+            >
+              <template slot-scope="{ row }">
+                <template v-if="item.formatter">{{
+                  item.formatter(row)
+                }}</template>
+                <template v-else>{{ row[item.prop] }}</template>
+              </template></el-table-column
+            >
+
+            <el-table-column type="selection" width="55"> </el-table-column>
+          </el-table>
+          <div class="right mt10" v-if="bizScene != 5">
+            <el-pagination
+              background
+              layout="total, sizes, prev, pager, next, jumper"
+              :total="total"
+              :page-sizes="[15, 30, 50, 100, 500]"
+              :page-size.sync="pages.size"
+              :current-page.sync="pages.page"
+              @current-change="handleCurrentChange"
+              @size-change="handleSizeChange"
+            >
+            </el-pagination>
+          </div>
+        </div>
+      </div>
+      <div class="select-btn">
+        <el-button type="primary" @click="onConfirm">确定</el-button>
+        <el-button @click="closeWindows">关闭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+  import AssetTree from '@/components/AssetTree';
+  // import {
+  //   getClassifyList,
+  //   getAssetLedger,
+  //   getInformation
+  // } from '@/api/stockManagement/index'
+
+  export default {
+    props: {
+      visibleDialog: {
+        type: Boolean,
+        default: false
+      },
+      title: {
+        type: String,
+        default: ''
+      },
+      bizScene: {
+        type: String,
+        default: ''
+      },
+      type: {
+        type: Array,
+        default: () => []
+      },
+      tableHeader: {
+        type: Array,
+        default: () => []
+      },
+      loadTree: {
+        type: Boolean,
+        default: true
+      }
+    },
+    watch: {
+      visibleDialog: {
+        handler(v) {
+          if (v) {
+            this.getTreeList();
+          }
+        },
+        deep: true
+      }
+    },
+    components: { AssetTree },
+    data() {
+      return {
+        value: '',
+        treeType: '',
+        treeList: [],
+        tableData: [],
+        multipleSelection: [],
+        pages1: { classificationIdList: [] },
+        pages: {
+          page: 1,
+          size: 10
+        },
+        total: 0,
+        curType: '',
+        classificationId: '',
+        memoSelection: []
+      };
+    },
+    created() {},
+    methods: {
+      handleSearch() {
+        this.pages.page = 1;
+        this.initData();
+      },
+      onConfirm() {
+        this.$emit('selectTableData', [
+          ...this.memoSelection,
+          ...this.multipleSelection
+        ]);
+        this.closeWindows();
+      },
+      getTreeList() {
+        this.$nextTick(() => {
+          if (!this.loadTree) this.$refs.treeList.getTreeData();
+        });
+      },
+      setclassIds(data, list) {
+        if (data && data.length !== 0) {
+          data.forEach((item) => {
+            if (item.children && item.children.length !== 0) {
+              this.setclassIds(item.children, list);
+            }
+            list.push(item.id);
+          });
+        }
+        return list;
+      },
+      handleSelectionChange(val) {
+        this.multipleSelection = val;
+      },
+      handleNodeClick(data) {
+        this.classificationId = data.id;
+        this.curType = data.type;
+        this.initData();
+      },
+      closeWindows() {
+        this.memoSelection = [];
+        this.multipleSelection = [];
+        this.$emit('update:loadTree', false);
+        this.$emit('update:visibleDialog', false);
+        this.pages.page = 1;
+      },
+      handleCurrentChange(e) {
+        this.initData();
+      },
+      handleSizeChange(e) {
+        this.pages.page = 1;
+        this.initData();
+      },
+      initData() {
+        this.memoSelection = this.multipleSelection.reduce((cur, pre) => {
+          if (!this.memoSelection.some((i) => i.curId === pre.curId)) {
+            cur.push(pre);
+          }
+          return cur;
+        }, this.memoSelection.slice(0));
+        if (this.bizScene == 5) {
+          this._getAssetLedger();
+        } else {
+          this._getInformation();
+        }
+      },
+      async _getInformation() {
+        const params = {
+          ...this.pages,
+          // type: this.curType,
+          code: this.value,
+          classificationId: this.classificationId
+        };
+        const res = await getInformation(params);
+        if (res?.success && this.classificationId == params.classificationId) {
+          const curMap = {
+            assetId: 'id',
+            assetCode: 'informationCode', //编码
+            assetName: 'informationName', //名称
+            materialId: 'id',
+            materialName: 'informationName',
+            batchNo: '', //批次号
+            unit: 'measuringUnit', //单位
+            minPackUnit: 'packingUnit' //最小包装单位
+          };
+          this.tableData = res.data.records.map((item) => {
+            for (const key in curMap) {
+              item[key] = curMap[key] ? item[curMap[key]] : '';
+            }
+            item.curId = item.id;
+
+            return item;
+          });
+
+          this.$nextTick(() => {
+            this.tableData.forEach((item) => {
+              const index = this.memoSelection.findIndex(
+                (i) => item.curId === i.curId
+              );
+              if (index > -1) {
+                // 删除还给 multipleSelection
+                this.$refs.multipleTable.toggleRowSelection(item, true);
+                this.memoSelection.splice(index, 1);
+              }
+            });
+          });
+          this.total = res.data.total;
+        }
+      },
+      async _getAssetLedger() {
+        const params = {
+          // // type: this.curType,
+          assetCode: this.value,
+          materialId: this.classificationId,
+          assetType: this.type[0]
+        };
+        const curMap = {
+          materialName: 'assetName', //类型
+          batchNo: 'batchNo', //批次号
+          outInNum: '' //数量
+        };
+        const res = await getAssetLedger(params);
+        if (res?.success && this.classificationId == params.materialId) {
+          this.tableData = res.data.map((item) => {
+            for (const key in curMap) {
+              item[key] = curMap[key] ? item[curMap[key]] : '';
+            }
+
+            item.curId =
+              item.assetCode +
+              item.measurementUnit +
+              item.minPackUnit +
+              item.unit;
+            return item;
+          });
+
+          this.$nextTick(() => {
+            this.tableData.forEach((item) => {
+              const index = this.memoSelection.findIndex(
+                (i) => item.curId === i.curId
+              );
+              if (index > -1) {
+                // 删除还给 multipleSelection
+                this.$refs.multipleTable.toggleRowSelection(item, true);
+                this.memoSelection.splice(index, 1);
+              }
+            });
+          });
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .flex_info {
+    display: flex;
+    margin-top: 20px;
+    margin-bottom: 20px;
+    .flex_left {
+      width: 202px;
+      height: 434px;
+      padding: 10px;
+      border: 1px solid #d7d7d7;
+      overflow-y: auto;
+    }
+    .flex_right {
+      flex: 1;
+      margin-left: 10px;
+    }
+  }
+  .search_box {
+    overflow: hidden;
+    ::v-deep .el-input-group__append {
+      background-color: #157a2c;
+      border-color: #157a2c;
+    }
+    .el-button {
+      color: #fff;
+    }
+  }
+  .select-btn {
+    text-align: right;
+  }
+  .right {
+    text-align: right;
+  }
+  .mt10 {
+    margin-top: 10px;
+  }
+</style>

+ 60 - 0
src/views/warehouseManagement/components/tablePagination.vue

@@ -0,0 +1,60 @@
+<template></template>
+
+<script>
+export default {
+  props: {
+    url: {
+      type: Function
+    },
+
+    params: {
+      type: Object,
+      default: () => ({})
+    },
+    tableData: {
+      type: Array,
+      default: () => []
+    },
+    params1: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  data () {
+    return {
+      sizes: [5, 10, 15, 20, 30, 40, 50]
+    }
+  },
+  created () {
+    this.initData()
+  },
+  methods: {
+    async initData () {
+      if (!this.url) return
+      let res = await this.url(this.params, this.params1)
+      if (res?.success) {
+        this.$emit('update:tableData', res.data.records)
+        this.params.total = res.data.total
+      }
+    },
+
+    handleCurrentChange (e) {
+      this.params.page = e
+      this.initData()
+    },
+    handleSizeChange (e) {
+      this.params.size = e
+      this.initData()
+    }
+  }
+}
+</script>
+
+<style lang="scss" scpoed>
+.mt10 {
+  margin-top: 10px;
+}
+.right {
+  text-align: right;
+}
+</style>

+ 1409 - 0
src/views/warehouseManagement/warehouseDefinition/add.vue

@@ -0,0 +1,1409 @@
+<template>
+  <div class="content-height p20 warehouseAdd">
+    <header>
+      <span class="title">{{ formData.code }} {{ formData.name }}</span>
+      <div>
+        <el-button @click="$router.go(-1)">返回</el-button>
+        <el-button type="primary" @click="submit" :loading="loading"
+          >保存</el-button
+        >
+      </div>
+    </header>
+    <el-divider></el-divider>
+    <div class="area">
+      <div class="mt20 reservoirArea">
+        <span>库区</span>
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="small"
+          @click="addArea"
+          >添加库区
+        </el-button>
+      </div>
+      <div class="mt10">
+        <el-form :model="areaForm" ref="areaFormName" class="areaForm">
+          <el-table
+            ref="multipleTable"
+            :data="areaForm.warehouseAreasSaveList"
+            tooltip-effect="dark"
+            style="width: 100%"
+            stripe
+            :header-cell-style="{ background: '#EEEEEE', border: 'none' }"
+          >
+            <el-table-column label="库区编号" prop="code" min-width="120">
+              <template slot-scope="{ row, $index }">
+                <el-form-item
+                  :prop="'warehouseAreasSaveList.' + $index + '.code'"
+                  :rules="areaRules.code"
+                  v-if="row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    clearable
+                    v-model="row.code"
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ row.code }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="库区名称" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="'warehouseAreasSaveList.' + scope.$index + '.name'"
+                  :rules="areaRules.name"
+                  v-if="scope.row.isEdit"
+                  id="reservoirAreaRef"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    clearable
+                    v-model="scope.row.name"
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.name }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="库区类型" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="'warehouseAreasSaveList.' + scope.$index + '.type'"
+                  :rules="areaRules.type"
+                  id="reservoirAreaRef"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-select
+                    v-model="scope.row.type"
+                    placeholder="请选择"
+                    clearable
+                  >
+                    <el-option
+                      v-for="(item, idx) in warehouseDefinition_areaType"
+                      :key="idx"
+                      :value="item.code"
+                      :label="item.label"
+                    ></el-option>
+                  </el-select>
+                </el-form-item>
+                <span v-else>{{
+                  scope.row.type | filterAreaType(warehouseDefinition_areaType)
+                }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="库区属性" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'warehouseAreasSaveList.' + scope.$index + '.attribute'
+                  "
+                  :rules="areaRules.attribute"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-select
+                    v-model="scope.row.attribute"
+                    placeholder="请选择"
+                    clearable
+                  >
+                    <el-option
+                      v-for="(item, idx) in warehouseDefinition_areaAttribute"
+                      :key="idx"
+                      :value="item.code"
+                      :label="item.label"
+                    ></el-option>
+                  </el-select>
+                </el-form-item>
+                <span v-else>{{
+                  scope.row.attribute
+                    | filterAreaType(warehouseDefinition_areaAttribute)
+                }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="库区位置" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="'warehouseAreasSaveList.' + scope.$index + '.address'"
+                  :rules="areaRules.address"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    clearable
+                    v-model="scope.row.address"
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.address }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="库区长(cm)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'warehouseAreasSaveList.' + scope.$index + '.areaLength'
+                  "
+                  :rules="areaRules.areaLength"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    clearable
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.areaLength"
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.areaLength }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="库区宽(cm)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="'warehouseAreasSaveList.' + scope.$index + '.areaWide'"
+                  :rules="areaRules.areaWide"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    clearable
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.areaWide"
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.areaWide }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="库区高(cm)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="'warehouseAreasSaveList.' + scope.$index + '.areaHigh'"
+                  :rules="areaRules.areaHigh"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.areaHigh"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.areaHigh }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="货架数量" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="'warehouseAreasSaveList.' + scope.$index + '.num'"
+                  :rules="areaRules.num"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @mousewheel.native.prevent
+                    @input="
+                      (value) =>
+                        (scope.row.num = value.replace(/^(0+)|[^\d]+/g, ''))
+                    "
+                    v-model.number="scope.row.num"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.num }}</span>
+              </template>
+            </el-table-column>
+
+            <!-- <el-table-column label="库区条码">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'warehouseAreasSaveList.' + scope.$index + 'areaBarcode'
+                  "
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="自动生成"
+                    disabled
+                    v-model="scope.row.areaBarcode"
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.areaBarcode }}</span>
+              </template>
+            </el-table-column> -->
+            <el-table-column label="备注" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'warehouseAreasSaveList.' + scope.$index + 'areaRemark'
+                  "
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="textarea"
+                    clearable
+                    :rows="1"
+                    v-model="scope.row.areaRemark"
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.areaRemark }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" fixed="right" width="150">
+              <template slot-scope="{ row, $index }">
+                <el-button
+                  type="text"
+                  v-if="row.isEdit"
+                  @click="saveArea($index)"
+                  >保存</el-button
+                >
+
+                <el-button type="text" v-else @click="addShelf(row, $index)"
+                  >添加货架</el-button
+                >
+                <el-button type="text" @click="remove($index, row)"
+                  >删除库区</el-button
+                >
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-form>
+      </div>
+    </div>
+    <!-- <div
+      class="area"
+      v-if="
+        areaForm.areaGoodsshelvesList &&
+        areaForm.areaGoodsshelvesList.length !== 0
+      "
+    > -->
+    <div class="area">
+      <div class="mt20 reservoirArea">
+        <span>货架</span>
+      </div>
+      <div class="mt10">
+        <el-form :model="areaForm" ref="areaCoodsForm" class="areaForm">
+          <el-table
+            ref="multipleTable"
+            :data="areaForm.areaGoodsshelvesList"
+            tooltip-effect="dark"
+            style="width: 100%"
+            stripe
+            :header-cell-style="{ background: '#EEEEEE', border: 'none' }"
+          >
+            <el-table-column
+              label="库区编号"
+              prop="warehouseAreaCode"
+            ></el-table-column>
+            <el-table-column
+              label="货架编号"
+              prop="goodsshelvesCode"
+              min-width="120"
+            >
+              <template slot-scope="{ row, $index }">
+                <el-form-item
+                  :prop="'areaGoodsshelvesList.' + $index + '.goodsshelvesCode'"
+                  :rules="areaCoodsRules.goodsshelvesCode"
+                  v-if="row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    clearable
+                    v-model="row.goodsshelvesCode"
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ row.goodsshelvesCode }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="货架行数" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'areaGoodsshelvesList.' + scope.$index + '.goodsshelvesLine'
+                  "
+                  :rules="areaCoodsRules.goodsshelvesLine"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @input="
+                      (value) =>
+                        (scope.row.goodsshelvesLine = value.replace(
+                          /^(0+)|[^\d]+/g,
+                          ''
+                        ))
+                    "
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.goodsshelvesLine"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.goodsshelvesLine }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="货架列数" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'areaGoodsshelvesList.' +
+                    scope.$index +
+                    '.goodsshelvesColumn'
+                  "
+                  :rules="areaCoodsRules.goodsshelvesColumn"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @input="
+                      (value) =>
+                        (scope.row.goodsshelvesColumn = value.replace(
+                          /^(0+)|[^\d]+/g,
+                          ''
+                        ))
+                    "
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.goodsshelvesColumn"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.goodsshelvesColumn }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="货架长(cm)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'areaGoodsshelvesList.' +
+                    scope.$index +
+                    '.goodsshelvesLength'
+                  "
+                  :rules="areaCoodsRules.goodsshelvesLength"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.goodsshelvesLength"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.goodsshelvesLength }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="货架宽(cm)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'areaGoodsshelvesList.' + scope.$index + '.goodsshelvesWide'
+                  "
+                  :rules="areaCoodsRules.goodsshelvesWide"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.goodsshelvesWide"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.goodsshelvesWide }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="货架高(cm)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'areaGoodsshelvesList.' + scope.$index + '.goodsshelvesHigh'
+                  "
+                  :rules="areaCoodsRules.goodsshelvesHigh"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.goodsshelvesHigh"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.goodsshelvesHigh }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="货位数量" prop="" min-width="120">
+              <template slot-scope="{ row }">
+                {{
+                  Number.isNaN(row.goodsshelvesLine * row.goodsshelvesColumn)
+                    ? ''
+                    : row.goodsshelvesLine * row.goodsshelvesColumn
+                }}
+              </template>
+            </el-table-column>
+            <el-table-column label="是否规则" prop="isRegular" min-width="120">
+              <template slot-scope="{ row }">
+                <el-select v-model="row.isRegular" v-if="row.isEdit">
+                  <el-option
+                    v-for="item in warehouseDefinition_isRegular"
+                    :key="item.code"
+                    :value="item.code"
+                    :label="item.label"
+                  ></el-option>
+                </el-select>
+                <template v-else>
+                  {{
+                    row.isRegular
+                      | filterAreaType(warehouseDefinition_isRegular)
+                  }}
+                </template>
+              </template>
+            </el-table-column>
+            <!-- <el-table-column
+              label="货架条码"
+              prop="goodsshelvesBarcode"
+            ></el-table-column> -->
+            <el-table-column label="备注" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'areaGoodsshelvesList.' +
+                    scope.$index +
+                    '.goodsshelvesRemark'
+                  "
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    v-model="scope.row.goodsshelvesRemark"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.goodsshelvesRemark }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" fixed="right" min-width="120">
+              <template slot-scope="{ $index, row }">
+                <el-button
+                  type="text"
+                  v-if="row.isEdit"
+                  @click="saveGoods($index, row)"
+                  >保存</el-button
+                >
+                <el-button type="text" @click="removeGoods($index, row)"
+                  >删除货架</el-button
+                >
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-form>
+      </div>
+    </div>
+
+    <!-- <div
+      class="area"
+      v-if="
+        areaForm.allocationReqList && areaForm.allocationReqList.length !== 0
+      "
+    > -->
+    <div class="area">
+      <div class="mt20 reservoirArea">
+        <span>货位</span>
+        <!-- <el-button type="primary" @click="reuse">复用</el-button> -->
+      </div>
+      <div class="mt10">
+        <el-form :model="areaForm" ref="allocationForm" class="areaForm">
+          <el-table
+            ref="multipleTable"
+            :data="areaForm.allocationReqList"
+            tooltip-effect="dark"
+            style="width: 100%"
+            stripe
+            :header-cell-style="{ background: '#EEEEEE', border: 'none' }"
+          >
+            <!-- <el-table-column type="selection" width="55"> </el-table-column> -->
+            <el-table-column label="货架编号" prop="warehouseAreaGoodsCode">
+              <template slot-scope="{ row }">
+                {{ getWarehouseAreaGoodsCode(row) }}
+              </template>
+            </el-table-column>
+            <el-table-column
+              label="货位编号"
+              prop="goodsAllocationCode"
+              min-width="120"
+            >
+              <template slot-scope="{ row, $index }">
+                <el-form-item
+                  :prop="'allocationReqList.' + $index + '.goodsAllocationCode'"
+                  :rules="areaLocationRules.goodsAllocationCode"
+                  v-if="row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    clearable
+                    v-model="row.goodsAllocationCode"
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ row.goodsAllocationCode }}</span>
+              </template></el-table-column
+            >
+            <el-table-column label="货位长(cm)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'allocationReqList.' +
+                    scope.$index +
+                    '.goodsAllocationLength'
+                  "
+                  :rules="areaLocationRules.allocationReq"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @mousewheel.native.prevent
+                    @blur="
+                      onBlur(
+                        scope.row,
+                        'goodsAllocationLength',
+                        'goodsshelvesLength'
+                      )
+                    "
+                    v-model.number="scope.row.goodsAllocationLength"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.goodsAllocationLength }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="货位宽(cm)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'allocationReqList.' + scope.$index + '.goodsAllocationWide'
+                  "
+                  v-if="scope.row.isEdit"
+                  :rules="areaLocationRules.allocationReq"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.goodsAllocationWide"
+                    @blur="
+                      onBlur(
+                        scope.row,
+                        'goodsAllocationWide',
+                        'goodsshelvesWide'
+                      )
+                    "
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.goodsAllocationWide }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="货位高(cm)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="
+                    'allocationReqList.' + scope.$index + '.goodsAllocationHigh'
+                  "
+                  v-if="scope.row.isEdit"
+                  :rules="areaLocationRules.allocationReq"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    @blur="
+                      onBlur(
+                        scope.row,
+                        'goodsAllocationHigh',
+                        'goodsshelvesHigh'
+                      )
+                    "
+                    type="number"
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.goodsAllocationHigh"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.goodsAllocationHigh }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="限重(kg)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="'allocationReqList.' + scope.$index + '.weightLimit'"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.weightLimit"
+                    clearable
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.weightLimit }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="基本货位容积(cm³)" min-width="120">
+              <template slot-scope="scope">
+                <el-form-item
+                  :prop="'allocationReqList.' + scope.$index + '.volumeUnit'"
+                  v-if="scope.row.isEdit"
+                >
+                  <el-input
+                    placeholder="请输入"
+                    type="number"
+                    @mousewheel.native.prevent
+                    v-model.number="scope.row.volumeUnit"
+                    disabled
+                  ></el-input>
+                </el-form-item>
+                <span v-else>{{ scope.row.volumeUnit }}</span>
+              </template>
+            </el-table-column>
+            <!-- <el-table-column
+              label="货位条码"
+              prop="allocationBarcode"
+            ></el-table-column> -->
+          </el-table>
+        </el-form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import selectTree from '@/components/selectTree';
+
+  // import {
+  //   warehouseDefinition_areaType,
+  //   warehouseDefinition_areaAttribute,
+  //   warehouseDefinition_isRegular,
+  //   useDictLabelFilter
+  // } from '@/utils/dict/index'
+
+  // import {
+  //   warehouseGoodsshelvesSave,
+  //   warehouseDetails,
+  //   existGoods
+  // } from '@/api/stockManagement/warehouseDefinition';
+  import { pushZero } from '@/utils/index';
+  import { throttle } from 'lodash';
+  export default {
+    components: { selectTree },
+    filters: {
+      filterAreaType: useDictLabelFilter
+    },
+    data() {
+      const msg = throttle(
+        () => this.$message.error('货架总体积不能大于库区体积!'),
+        500
+      );
+
+      const allocationReqValidator = (column, value, callback) => {
+        if (!value) {
+          callback(new Error('不能为空!'));
+        } else {
+          // 货位体积限制
+          const index = +column.field.split('.')[1];
+          const row = this.areaForm.allocationReqList[index];
+
+          const parent = this.areaForm.areaGoodsshelvesList.find(
+            (t) => t.code === row.goodsshelvesCode
+          );
+
+          let sameParentSavedSum = this.areaForm.allocationReqList
+            .filter((t) => t.warehouseAreaGoodsCode === row.goodsshelvesCode)
+            .reduce((sum, item) => {
+              if (!item.isEdit) {
+                sum +=
+                  item.goodsAllocationLength *
+                  item.goodsAllocationWide *
+                  item.goodsAllocationHigh;
+              }
+              return sum;
+            }, 0);
+
+          if (parent) {
+            const max =
+              parent.goodsshelvesLength *
+              parent.goodsshelvesWide *
+              parent.goodsshelvesHigh;
+
+            if (
+              max - sameParentSavedSum <
+              row.goodsAllocationLength *
+                row.goodsAllocationWide *
+                row.goodsAllocationHigh
+            ) {
+              msg();
+              callback(new Error('货架总体积不能大于库区体积!'));
+              return;
+            }
+          }
+          callback();
+        }
+      };
+
+      return {
+        warehouseDefinition_isRegular,
+        warehouseDefinition_areaType,
+        warehouseDefinition_areaAttribute,
+        loading: false,
+        areaForm: {
+          warehouseAreasSaveList: [], //库区
+          areaGoodsshelvesList: [], //货架
+          allocationReqList: [] //货位
+        },
+        areaCoodsRules: {
+          goodsshelvesCode: {
+            required: true,
+            message: '请输入货架编号',
+            trigger: 'blur'
+          },
+          goodsshelvesLine: {
+            required: true,
+            message: '请输入货架行',
+            trigger: 'blur'
+          },
+          goodsshelvesColumn: {
+            required: true,
+            message: '请输入货架列',
+            trigger: 'blur'
+          },
+          goodsshelvesLength: {
+            required: true,
+            message: '请输入货架长',
+            trigger: 'blur'
+          },
+          goodsshelvesWide: {
+            required: true,
+            message: '请输入货架宽',
+            trigger: 'blur'
+          },
+          goodsshelvesHigh: {
+            required: true,
+            message: '请输入货架高',
+            trigger: 'blur'
+          }
+        },
+        areaLocationRules: {
+          goodsAllocationCode: {
+            required: true,
+            message: '请输入货位编号',
+            trigger: 'blur'
+          },
+          allocationReq: {
+            required: true,
+            validator: allocationReqValidator,
+            trigger: 'blur'
+          }
+        },
+        isPageEdit: false,
+        areaRules: {
+          code: { required: true, message: '请输入库区编号', trigger: 'blur' },
+          name: { required: true, message: '请输入库区名称', trigger: 'blur' },
+          type: {
+            required: true,
+            message: '请选择库区类型',
+            trigger: 'change'
+          },
+          attribute: {
+            required: true,
+            message: '请选择库区属性',
+            trigger: 'change'
+          },
+          address: {
+            required: true,
+            message: '请输入库区位置',
+            trigger: 'blur'
+          },
+          areaLength: {
+            required: true,
+            message: '请输入库区长',
+            trigger: 'blur'
+          },
+          areaWide: {
+            required: true,
+            message: '请输入库区宽',
+            trigger: 'blur'
+          },
+          areaHigh: {
+            required: true,
+            message: '请输入库区高',
+            trigger: 'blur'
+          },
+          num: { required: true, message: '请输入货架数量', trigger: 'blur' }
+        },
+        areaDisabled: true,
+        addressDisabled: true,
+        ownerNameDisabled: true,
+        areaList: [],
+        inventoryList: [
+          { value: '1', name: '物料库' },
+          { value: '2', name: '产品库' },
+          { value: '3', name: '设备库' }
+        ],
+        statusList: [
+          { value: '0', name: '失效' },
+          { value: '1', name: '生效' }
+        ],
+        formData: {
+          code: '',
+          name: '',
+          inventoryType: '',
+          factoryName: '',
+          factoryId: '',
+          ownerId: '',
+          ownerName: '',
+          contact: '',
+          status: '',
+          city: '',
+          area: '',
+          address: '',
+          remarks: '',
+          departmentCode: '',
+          departmentName: ''
+        },
+        factoryList: [], //所属工厂
+        staffList: [],
+        multipleSelection: [],
+        shelfObj: {},
+        longWidthHeightBol: false,
+        savedWarehouse: [],
+        savedShelves: []
+      };
+    },
+    computed: {},
+    created() {
+      const { query } = this.$route;
+      this.formData.code = query.code;
+      this.formData.name = query.name;
+      this.formData.id = query.id;
+      this.getDetail(query.id);
+    },
+
+    methods: {
+      async getDetail(id) {
+        const res = await warehouseDetails({ id });
+
+        if (res?.success) {
+          this.areaForm = {
+            warehouseAreasSaveList: res.data.warehouseAreasSaveList, //库区
+            areaGoodsshelvesList: res.data.areaGoodsshelvesList, //货架
+            allocationReqList: res.data.allocationReqList //货位
+          };
+
+          this.formData = res.data.warehouseSaveReq;
+          //已保存库区货位 ,删除时判断
+          this.savedWarehouse = res.data.warehouseAreasSaveList.map(
+            (i) => i.id
+          );
+          this.savedShelves = res.data.areaGoodsshelvesList.map((i) => i.id);
+        }
+      },
+      editInfo(index) {
+        let obj = this.areaForm.warehouseAreasSaveList[index];
+        if (obj.isEdit) {
+          this.$set(
+            this.areaForm.warehouseAreasSaveList[index],
+            'isEdit',
+            false
+          );
+        } else {
+          this.$set(
+            this.areaForm.warehouseAreasSaveList[index],
+            'isEdit',
+            true
+          );
+        }
+      },
+      addShelf(row, index) {
+        this.$prompt('请输入', '添加货架数', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          inputPattern: /[1-9]\d*/,
+          inputErrorMessage: '请输入正整数'
+        })
+          .then(({ value }) => {
+            row.num = +row.num + +value;
+            let obj = this.areaForm.warehouseAreasSaveList[index];
+
+            const pre =
+              this.areaForm.areaGoodsshelvesList[
+                this.areaForm.areaGoodsshelvesList.length - 1
+              ];
+            let preCode = 0;
+            if (pre) {
+              preCode = +(pre.goodsshelvesCode?.substr(1) || 0);
+            }
+            for (var i = 0; i < value; i++) {
+              this.areaForm.areaGoodsshelvesList.push({
+                warehouseAreaCode: obj.code,
+                warehouseAreaId: obj.id,
+                warehouseAreaName: obj.name,
+                goodsshelvesCode: ``,
+                goodsshelvesLine: '',
+                goodsshelvesColumn: '',
+                goodsshelvesLength: '',
+                goodsshelvesWide: '',
+                goodsshelvesHigh: '',
+                isRegular: 1,
+                // goodsshelvesBarcode: '',
+                goodsshelvesRemark: '',
+                warehouseName: this.formData.name,
+                isEdit: true
+              });
+            }
+          })
+          .catch(() => {});
+        // let obj = this.areaForm.warehouseAreasSaveList[index],
+        //   list = this.areaForm.areaGoodsshelvesList.filter(
+        //     item => item.warehouseAreaCode === obj.code
+        //   )
+        // if (obj.id) {
+        //   if (list.length == obj.num)
+        //     return this.$message.error('添加货架数量达到上限')
+        //   let num = obj.num - list.length
+        //   for (var i = 0; i < num; i++) {
+        //     this.areaForm.areaGoodsshelvesList.push({
+        //       warehouseAreaCode: obj.code,
+        //       warehouseAreaId: obj.id,
+        //       warehouseAreaName: obj.name,
+        //       goodsshelvesCode: `C${pushZero(
+        //         this.areaForm.areaGoodsshelvesList.length + 1
+        //       )}`,
+        //       goodsshelvesLine: '',
+        //       goodsshelvesColumn: '',
+        //       goodsshelvesLength: '',
+        //       goodsshelvesWide: '',
+        //       goodsshelvesHigh: '',
+        //       // goodsshelvesBarcode: '',
+        //       goodsshelvesRemark: '',
+        //       warehouseName: this.formData.name,
+        //       isEdit: true
+        //     })
+        //   }
+        // } else {
+        //   this.saveArea(index)
+        // }
+      },
+      onBlur(item, name, name1) {
+        // name当前货位的长宽高,name1货架的长宽高
+
+        if (
+          item.goodsAllocationHigh &&
+          item.goodsAllocationLength &&
+          item.goodsAllocationWide
+        ) {
+          item.volumeUnit =
+            item.goodsAllocationHigh *
+            item.goodsAllocationLength *
+            item.goodsAllocationWide;
+        }
+      },
+      saveGoods(index, row) {
+        // 需要校验的字段 areaGoodsshelvesList
+        let list = Object.keys(this.areaCoodsRules),
+          obj = this.areaForm.areaGoodsshelvesList[index],
+          flag = true;
+
+        list.forEach((item) => {
+          this.$refs.areaCoodsForm.validateField(
+            'areaGoodsshelvesList.' + index + '.' + item,
+            (valid) => {
+              if (valid) {
+                flag = false;
+              }
+            }
+          );
+        });
+
+        // 库区体积限制
+        const parent = this.areaForm.warehouseAreasSaveList.find(
+          (t) => t.code === row.warehouseAreaCode
+        );
+
+        if (
+          this.areaForm.areaGoodsshelvesList.filter(
+            (item) =>
+              item.goodsshelvesCode === row.goodsshelvesCode &&
+              row.warehouseAreaCode === item.warehouseAreaCode
+          ).length > 1
+        ) {
+          return this.$message.error('货架编号不能重复!');
+        }
+        const savedSum = this.areaForm.areaGoodsshelvesList
+          .filter((t) => t.warehouseAreaCode === row.warehouseAreaCode)
+          .reduce((sum, item) => {
+            if (!item.isEdit) {
+              sum +=
+                item.goodsshelvesLength *
+                item.goodsshelvesWide *
+                item.goodsshelvesHigh;
+            }
+            return sum;
+          }, 0);
+        if (parent) {
+          const max = parent.areaLength * parent.areaWide * parent.areaHigh;
+
+          if (
+            max - savedSum <
+            row.goodsshelvesLength * row.goodsshelvesWide * row.goodsshelvesHigh
+          ) {
+            return this.$message.error('货架总体积不能大于库区体积!');
+          }
+        }
+
+        if (flag) {
+          this.$set(obj, 'isEdit', false);
+          this.shelfObj = obj; //储存货架对象
+          let num = obj.goodsshelvesLine * obj.goodsshelvesColumn;
+
+          this.areaIndex = index;
+          this.generateAllocation(num, obj);
+        }
+      },
+      generateAllocation(num, obj) {
+        console.log('obj', obj);
+        const pre =
+          this.areaForm.allocationReqList[
+            this.areaForm.allocationReqList.length - 1
+          ];
+
+        for (var i = 0; i < num; i++) {
+          this.areaForm.allocationReqList.push({
+            // allocationBarcode: '',
+            allocationRemark: '',
+            allocationStatus: 1,
+            departmentName: this.formData.departmentName,
+            goodsAllocationCode: ``,
+            goodsAllocationHigh: '',
+            goodsAllocationLength: '',
+            goodsAllocationWide: '',
+            ownerName: this.formData.ownerName,
+            volumeUnit: '',
+            warehouseAreaGoodsCode: obj.goodsshelvesCode,
+            warehouseAreaGoodsId: obj.id,
+            warehouseAreaGoodsName: obj.name,
+            warehouseAreaId: obj.warehouseAreaId, //?
+            warehouseAreaName: obj.warehouseAreaName,
+            warehouseAreaCode: obj.warehouseAreaCode,
+            warehouseId: this.id, //?
+            warehouseName: this.formData.name,
+            weightLimit: '',
+            isEdit: true
+          });
+        }
+      },
+      saveArea(index) {
+        let flag = true;
+        Object.keys(this.areaRules).forEach((item) => {
+          this.$refs.areaFormName.validateField(
+            'warehouseAreasSaveList.' + index + '.' + item,
+            (valid) => {
+              if (valid) {
+                // rej()
+                flag = false;
+              }
+            }
+          );
+        });
+
+        if (!flag) return;
+        if (
+          this.areaForm.warehouseAreasSaveList.filter(
+            (item) =>
+              item.code === this.areaForm.warehouseAreasSaveList[index].code
+          ).length > 1
+        ) {
+          return this.$message.error('库区编号不能重复!');
+        }
+
+        // let list = this.areaForm.areaGoodsshelvesList.filter(
+        //   item =>
+        //     item.warehouseAreaCode ===
+        //     this.areaForm.warehouseAreasSaveList[index].code
+        // )
+        // if (list.length == this.areaForm.warehouseAreasSaveList[index].num) {
+        //   // this.$message.error('添加货架数量达到上限')
+        //   return
+        // }
+
+        this.$set(this.areaForm.warehouseAreasSaveList[index], 'isEdit', false);
+
+        let obj = this.areaForm.warehouseAreasSaveList[index];
+        let num = this.areaForm.warehouseAreasSaveList[index].num;
+
+        const pre =
+          this.areaForm.areaGoodsshelvesList[
+            this.areaForm.areaGoodsshelvesList.length - 1
+          ];
+        let preCode = 0;
+        if (pre) {
+          preCode = +(pre.goodsshelvesCode?.substr(1) || 0);
+        }
+
+        for (var i = 0; i < num; i++) {
+          this.areaForm.areaGoodsshelvesList.push({
+            warehouseAreaCode: obj.code,
+            warehouseAreaId: obj.id,
+            warehouseAreaName: obj.name,
+            warehouseAreaId: this.id,
+            goodsshelvesCode: ``,
+            goodsshelvesLine: '',
+            goodsshelvesColumn: '',
+            goodsshelvesLength: '',
+            goodsshelvesWide: '',
+            goodsshelvesHigh: '',
+            // goodsshelvesBarcode: '',
+            goodsshelvesRemark: '',
+            warehouseName: this.formData.name,
+            isEdit: true,
+            isRegular: 1
+          });
+        }
+      },
+      async removeGoods(idx, { id, goodsshelvesCode, warehouseAreaCode }) {
+        if (
+          this.areaForm.areaGoodsshelvesList.filter(
+            (item) => item.warehouseAreaCode === warehouseAreaCode
+          ).length === 1
+        ) {
+          return this.$message.error('至少保留一个货架!');
+        }
+        if (this.savedShelves.includes(id)) {
+          let list = this.areaForm.allocationReqList
+            .filter((item) => item.warehouseAreaGoodsCode === goodsshelvesCode)
+            .map((i) => i.id);
+
+          const res = await existGoods(list);
+
+          if (res?.success && res.data) {
+            return this.$message.error('此货架下货位有关联货物,无法删除!');
+          }
+        }
+
+        this.areaForm.allocationReqList =
+          this.areaForm.allocationReqList.filter(
+            (item) =>
+              item.warehouseAreaGoodsCode !== goodsshelvesCode ||
+              warehouseAreaCode !== item.warehouseAreaCode
+          );
+        let areasIndex = this.areaForm.warehouseAreasSaveList.findIndex(
+          (item) =>
+            item.code ===
+            this.areaForm.areaGoodsshelvesList[idx].warehouseAreaCode
+        );
+        this.areaForm.areaGoodsshelvesList.splice(idx, 1);
+        if (this.areaForm.warehouseAreasSaveList[areasIndex].num - 1 <= 0) {
+          this.areaForm.warehouseAreasSaveList.splice(areasIndex, 1);
+        } else {
+          this.$set(
+            this.areaForm.warehouseAreasSaveList[areasIndex],
+            'num',
+            this.areaForm.warehouseAreasSaveList[areasIndex].num - 1
+          );
+        }
+      },
+      async remove(index, { id, code }) {
+        // 判断关联货物
+        console.log(this.savedWarehouse, id, this.savedWarehouse.includes(id));
+        if (this.savedWarehouse.includes(id)) {
+          let list = this.areaForm.areaGoodsshelvesList
+            .filter((item) => item.warehouseAreaCode === code)
+            .map((i) =>
+              this.areaForm.allocationReqList.filter(
+                (item) => item.warehouseAreaGoodsCode === i.goodsshelvesCode
+              )
+            )
+            .flat()
+            .map((i) => i.id);
+
+          const res = await existGoods(list);
+
+          if (res?.success && res.data) {
+            return this.$message.error('此库区下货位有关联货物,无法删除!');
+          }
+        }
+        // 货架code
+        let list = [];
+        this.areaForm.areaGoodsshelvesList.forEach((item) => {
+          if (item.warehouseAreaCode === code) {
+            list.push(item.goodsshelvesCode);
+          }
+        });
+        this.areaForm.areaGoodsshelvesList =
+          this.areaForm.areaGoodsshelvesList.filter(
+            (item) => item.warehouseAreaCode !== code
+          );
+
+        this.areaForm.allocationReqList =
+          this.areaForm.allocationReqList.filter(
+            (item) =>
+              !list.includes(item.warehouseAreaGoodsCode) ||
+              code !== item.warehouseAreaCode
+          );
+        this.areaForm.warehouseAreasSaveList.splice(index, 1);
+      },
+      addArea() {
+        const pre =
+          this.areaForm.warehouseAreasSaveList[
+            this.areaForm.warehouseAreasSaveList.length - 1
+          ];
+        let preCode = 0;
+        if (pre) {
+          preCode = +(pre.code?.substr(1) || 0);
+        }
+
+        this.areaForm.warehouseAreasSaveList.push({
+          code: ``,
+          name: '',
+          type: '',
+          attribute: '',
+          address: '',
+          areaLength: '',
+          areaWide: '',
+          areaHigh: '',
+          num: '',
+          // areaBarcode: '',
+          areaRemark: '',
+          warehouseName: this.formData.name,
+          warehouseCode: this.formData.code,
+          isEdit: true
+        });
+      },
+      submit() {
+        if (this.areaForm.warehouseAreasSaveList.length === 0) {
+          return this.$message.error('请添加库区');
+        }
+        if (this.areaForm.allocationReqList.length === 0) {
+          return this.$message.error('请添加货位');
+        }
+        if (this.areaForm.areaGoodsshelvesList.length === 0) {
+          return this.$message.error('请添加货架');
+        }
+
+        let obj = {};
+        for (const item of this.areaForm.allocationReqList) {
+          const area = this.areaForm.areaGoodsshelvesList.find((itm) => {
+            return (
+              itm.warehouseAreaName === item.warehouseAreaName &&
+              itm.goodsshelvesCode === item.warehouseAreaGoodsCode
+            );
+          });
+
+          const id = `${
+            area && area.warehouseAreaCode + '-' + item.warehouseAreaGoodsCode
+          }-${item.goodsAllocationCode}`;
+
+          if (obj[id]) {
+            return this.$message.error('货位编号不能重复!');
+          } else {
+            obj[id] = 1;
+          }
+        }
+
+        this.$refs.areaFormName.validate(async (valid) => {
+          if (valid) {
+            this.$refs.areaCoodsForm.validate(async (valid) => {
+              if (valid) {
+                this.$refs.allocationForm.validate(async (valid) => {
+                  if (valid) {
+                    let params = {
+                      warehouseSaveReq: this.formData,
+                      allocationReqList: this.areaForm.allocationReqList,
+                      areaGoodsshelvesList: this.areaForm.areaGoodsshelvesList,
+                      warehouseAreasSaveList:
+                        this.areaForm.warehouseAreasSaveList
+                    };
+                    this.loading = true;
+                    try {
+                      let res = await warehouseGoodsshelvesSave(params);
+                      if (res.success) {
+                        this.$message.success('保存成功');
+                        this.$router.push({
+                          path: '/warehouseManagement/warehouseDefinition'
+                        });
+                      }
+                    } catch (error) {}
+                    this.loading = false;
+                  }
+                });
+              }
+            });
+          }
+        });
+      },
+      // 货位组装货架编号
+      getWarehouseAreaGoodsCode(row) {
+        console.log(row);
+        const { warehouseAreaGoodsCode, warehouseAreaCode } = row;
+        const obj = this.areaForm.areaGoodsshelvesList.find((item) => {
+          return (
+            item.warehouseAreaCode === warehouseAreaCode &&
+            item.goodsshelvesCode === warehouseAreaGoodsCode
+          );
+        });
+        return obj && obj.warehouseAreaCode + '-' + warehouseAreaGoodsCode;
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .p20 {
+    padding: 20px;
+  }
+  .mt20 {
+    margin-top: 20px;
+  }
+  .mt10 {
+    margin-top: 10px;
+  }
+  ::v-deep .el-select {
+    width: 100%;
+  }
+  .el-form-item {
+    margin-bottom: 22px;
+  }
+  .areaForm {
+    .el-form-item {
+      margin-bottom: 0;
+    }
+  }
+  .warehouseAdd {
+    .el-row {
+      display: block;
+    }
+    header {
+      display: flex;
+      justify-content: space-between;
+      .title {
+        font-size: 20px;
+        color: #333;
+        font-weight: bold;
+      }
+    }
+  }
+  .reservoirArea {
+    display: flex;
+    justify-content: space-between;
+    span {
+      font-size: 14px;
+    }
+  }
+  .center {
+    text-align: center;
+  }
+  .el-select {
+    display: block;
+  }
+  ::v-deep input::-webkit-inner-spin-button {
+    -webkit-appearance: none;
+  }
+</style>

+ 578 - 0
src/views/warehouseManagement/warehouseDefinition/city.js

@@ -0,0 +1,578 @@
+export const city =    {
+    "label": "湖南省",
+    "value": "湖南省",
+    "children": [
+        {
+            "label": "长沙市",
+            "value": "长沙市",
+            "children": [
+                {
+                    "label": "芙蓉区",
+                    "value": "芙蓉区"
+                },
+                {
+                    "label": "天心区",
+                    "value": "天心区"
+                },
+                {
+                    "label": "岳麓区",
+                    "value": "岳麓区"
+                },
+                {
+                    "label": "开福区",
+                    "value": "开福区"
+                },
+                {
+                    "label": "雨花区",
+                    "value": "雨花区"
+                },
+                {
+                    "label": "望城区",
+                    "value": "望城区"
+                },
+                {
+                    "label": "长沙县",
+                    "value": "长沙县"
+                },
+                {
+                    "label": "宁乡县",
+                    "value": "宁乡县"
+                },
+                {
+                    "label": "浏阳市",
+                    "value": "浏阳市"
+                }
+            ]
+        },
+        {
+            "label": "株洲市",
+            "value": "株洲市",
+            "children": [
+                {
+                    "label": "荷塘区",
+                    "value": "荷塘区"
+                },
+                {
+                    "label": "芦淞区",
+                    "value": "芦淞区"
+                },
+                {
+                    "label": "石峰区",
+                    "value": "石峰区"
+                },
+                {
+                    "label": "天元区",
+                    "value": "天元区"
+                },
+                {
+                    "label": "株洲县",
+                    "value": "株洲县"
+                },
+                {
+                    "label": "攸县",
+                    "value": "攸县"
+                },
+                {
+                    "label": "茶陵县",
+                    "value": "茶陵县"
+                },
+                {
+                    "label": "炎陵县",
+                    "value": "炎陵县"
+                },
+                {
+                    "label": "醴陵市",
+                    "value": "醴陵市"
+                }
+            ]
+        },
+        {
+            "label": "湘潭市",
+            "value": "湘潭市",
+            "children": [
+                {
+                    "label": "雨湖区",
+                    "value": "雨湖区"
+                },
+                {
+                    "label": "岳塘区",
+                    "value": "岳塘区"
+                },
+                {
+                    "label": "湘潭县",
+                    "value": "湘潭县"
+                },
+                {
+                    "label": "湘乡市",
+                    "value": "湘乡市"
+                },
+                {
+                    "label": "韶山市",
+                    "value": "韶山市"
+                }
+            ]
+        },
+        {
+            "label": "衡阳市",
+            "value": "衡阳市",
+            "children": [
+                {
+                    "label": "珠晖区",
+                    "value": "珠晖区"
+                },
+                {
+                    "label": "雁峰区",
+                    "value": "雁峰区"
+                },
+                {
+                    "label": "石鼓区",
+                    "value": "石鼓区"
+                },
+                {
+                    "label": "蒸湘区",
+                    "value": "蒸湘区"
+                },
+                {
+                    "label": "南岳区",
+                    "value": "南岳区"
+                },
+                {
+                    "label": "衡阳县",
+                    "value": "衡阳县"
+                },
+                {
+                    "label": "衡南县",
+                    "value": "衡南县"
+                },
+                {
+                    "label": "衡山县",
+                    "value": "衡山县"
+                },
+                {
+                    "label": "衡东县",
+                    "value": "衡东县"
+                },
+                {
+                    "label": "祁东县",
+                    "value": "祁东县"
+                },
+                {
+                    "label": "耒阳市",
+                    "value": "耒阳市"
+                },
+                {
+                    "label": "常宁市",
+                    "value": "常宁市"
+                }
+            ]
+        },
+        {
+            "label": "邵阳市",
+            "value": "邵阳市",
+            "children": [
+                {
+                    "label": "双清区",
+                    "value": "双清区"
+                },
+                {
+                    "label": "大祥区",
+                    "value": "大祥区"
+                },
+                {
+                    "label": "北塔区",
+                    "value": "北塔区"
+                },
+                {
+                    "label": "邵东县",
+                    "value": "邵东县"
+                },
+                {
+                    "label": "新邵县",
+                    "value": "新邵县"
+                },
+                {
+                    "label": "邵阳县",
+                    "value": "邵阳县"
+                },
+                {
+                    "label": "隆回县",
+                    "value": "隆回县"
+                },
+                {
+                    "label": "洞口县",
+                    "value": "洞口县"
+                },
+                {
+                    "label": "绥宁县",
+                    "value": "绥宁县"
+                },
+                {
+                    "label": "新宁县",
+                    "value": "新宁县"
+                },
+                {
+                    "label": "城步苗族自治县",
+                    "value": "城步苗族自治县"
+                },
+                {
+                    "label": "武冈市",
+                    "value": "武冈市"
+                }
+            ]
+        },
+        {
+            "label": "岳阳市",
+            "value": "岳阳市",
+            "children": [
+                {
+                    "label": "岳阳楼区",
+                    "value": "岳阳楼区"
+                },
+                {
+                    "label": "云溪区",
+                    "value": "云溪区"
+                },
+                {
+                    "label": "君山区",
+                    "value": "君山区"
+                },
+                {
+                    "label": "岳阳县",
+                    "value": "岳阳县"
+                },
+                {
+                    "label": "华容县",
+                    "value": "华容县"
+                },
+                {
+                    "label": "湘阴县",
+                    "value": "湘阴县"
+                },
+                {
+                    "label": "平江县",
+                    "value": "平江县"
+                },
+                {
+                    "label": "汨罗市",
+                    "value": "汨罗市"
+                },
+                {
+                    "label": "临湘市",
+                    "value": "临湘市"
+                }
+            ]
+        },
+        {
+            "label": "常德市",
+            "value": "常德市",
+            "children": [
+                {
+                    "label": "武陵区",
+                    "value": "武陵区"
+                },
+                {
+                    "label": "鼎城区",
+                    "value": "鼎城区"
+                },
+                {
+                    "label": "安乡县",
+                    "value": "安乡县"
+                },
+                {
+                    "label": "汉寿县",
+                    "value": "汉寿县"
+                },
+                {
+                    "label": "澧县",
+                    "value": "澧县"
+                },
+                {
+                    "label": "临澧县",
+                    "value": "临澧县"
+                },
+                {
+                    "label": "桃源县",
+                    "value": "桃源县"
+                },
+                {
+                    "label": "石门县",
+                    "value": "石门县"
+                },
+                {
+                    "label": "津市市",
+                    "value": "津市市"
+                }
+            ]
+        },
+        {
+            "label": "张家界市",
+            "value": "张家界市",
+            "children": [
+                {
+                    "label": "永定区",
+                    "value": "永定区"
+                },
+                {
+                    "label": "武陵源区",
+                    "value": "武陵源区"
+                },
+                {
+                    "label": "慈利县",
+                    "value": "慈利县"
+                },
+                {
+                    "label": "桑植县",
+                    "value": "桑植县"
+                }
+            ]
+        },
+        {
+            "label": "益阳市",
+            "value": "益阳市",
+            "children": [
+                {
+                    "label": "资阳区",
+                    "value": "资阳区"
+                },
+                {
+                    "label": "赫山区",
+                    "value": "赫山区"
+                },
+                {
+                    "label": "南县",
+                    "value": "南县"
+                },
+                {
+                    "label": "桃江县",
+                    "value": "桃江县"
+                },
+                {
+                    "label": "安化县",
+                    "value": "安化县"
+                },
+                {
+                    "label": "沅江市",
+                    "value": "沅江市"
+                }
+            ]
+        },
+        {
+            "label": "郴州市",
+            "value": "郴州市",
+            "children": [
+                {
+                    "label": "北湖区",
+                    "value": "北湖区"
+                },
+                {
+                    "label": "苏仙区",
+                    "value": "苏仙区"
+                },
+                {
+                    "label": "桂阳县",
+                    "value": "桂阳县"
+                },
+                {
+                    "label": "宜章县",
+                    "value": "宜章县"
+                },
+                {
+                    "label": "永兴县",
+                    "value": "永兴县"
+                },
+                {
+                    "label": "嘉禾县",
+                    "value": "嘉禾县"
+                },
+                {
+                    "label": "临武县",
+                    "value": "临武县"
+                },
+                {
+                    "label": "汝城县",
+                    "value": "汝城县"
+                },
+                {
+                    "label": "桂东县",
+                    "value": "桂东县"
+                },
+                {
+                    "label": "安仁县",
+                    "value": "安仁县"
+                },
+                {
+                    "label": "资兴市",
+                    "value": "资兴市"
+                }
+            ]
+        },
+        {
+            "label": "永州市",
+            "value": "永州市",
+            "children": [
+                {
+                    "label": "零陵区",
+                    "value": "零陵区"
+                },
+                {
+                    "label": "冷水滩区",
+                    "value": "冷水滩区"
+                },
+                {
+                    "label": "祁阳县",
+                    "value": "祁阳县"
+                },
+                {
+                    "label": "东安县",
+                    "value": "东安县"
+                },
+                {
+                    "label": "双牌县",
+                    "value": "双牌县"
+                },
+                {
+                    "label": "道县",
+                    "value": "道县"
+                },
+                {
+                    "label": "江永县",
+                    "value": "江永县"
+                },
+                {
+                    "label": "宁远县",
+                    "value": "宁远县"
+                },
+                {
+                    "label": "蓝山县",
+                    "value": "蓝山县"
+                },
+                {
+                    "label": "新田县",
+                    "value": "新田县"
+                },
+                {
+                    "label": "江华瑶族自治县",
+                    "value": "江华瑶族自治县"
+                }
+            ]
+        },
+        {
+            "label": "怀化市",
+            "value": "怀化市",
+            "children": [
+                {
+                    "label": "鹤城区",
+                    "value": "鹤城区"
+                },
+                {
+                    "label": "中方县",
+                    "value": "中方县"
+                },
+                {
+                    "label": "沅陵县",
+                    "value": "沅陵县"
+                },
+                {
+                    "label": "辰溪县",
+                    "value": "辰溪县"
+                },
+                {
+                    "label": "溆浦县",
+                    "value": "溆浦县"
+                },
+                {
+                    "label": "会同县",
+                    "value": "会同县"
+                },
+                {
+                    "label": "麻阳苗族自治县",
+                    "value": "麻阳苗族自治县"
+                },
+                {
+                    "label": "新晃侗族自治县",
+                    "value": "新晃侗族自治县"
+                },
+                {
+                    "label": "芷江侗族自治县",
+                    "value": "芷江侗族自治县"
+                },
+                {
+                    "label": "靖州苗族侗族自治县",
+                    "value": "靖州苗族侗族自治县"
+                },
+                {
+                    "label": "通道侗族自治县",
+                    "value": "通道侗族自治县"
+                },
+                {
+                    "label": "洪江市",
+                    "value": "洪江市"
+                }
+            ]
+        },
+        {
+            "label": "娄底市",
+            "value": "娄底市",
+            "children": [
+                {
+                    "label": "娄星区",
+                    "value": "娄星区"
+                },
+                {
+                    "label": "双峰县",
+                    "value": "双峰县"
+                },
+                {
+                    "label": "新化县",
+                    "value": "新化县"
+                },
+                {
+                    "label": "冷水江市",
+                    "value": "冷水江市"
+                },
+                {
+                    "label": "涟源市",
+                    "value": "涟源市"
+                }
+            ]
+        },
+        {
+            "label": "湘西土家族苗族自治州",
+            "value": "湘西土家族苗族自治州",
+            "children": [
+                {
+                    "label": "吉首市",
+                    "value": "吉首市"
+                },
+                {
+                    "label": "泸溪县",
+                    "value": "泸溪县"
+                },
+                {
+                    "label": "凤凰县",
+                    "value": "凤凰县"
+                },
+                {
+                    "label": "花垣县",
+                    "value": "花垣县"
+                },
+                {
+                    "label": "保靖县",
+                    "value": "保靖县"
+                },
+                {
+                    "label": "古丈县",
+                    "value": "古丈县"
+                },
+                {
+                    "label": "永顺县",
+                    "value": "永顺县"
+                },
+                {
+                    "label": "龙山县",
+                    "value": "龙山县"
+                }
+            ]
+        }
+    ]
+}         

+ 287 - 0
src/views/warehouseManagement/warehouseDefinition/components/CodePrint.vue

@@ -0,0 +1,287 @@
+<template>
+  <el-dialog :visible.sync="visible" title="导出条码" width="500px">
+    <div class="select-box">
+      <div style="text-align: center">
+        <el-radio-group v-model="type" @change="handleRadioChange">
+          <el-radio label="1">货架码</el-radio>
+          <el-radio label="2">货位码</el-radio>
+        </el-radio-group>
+      </div>
+      <div class="area" :key="forceUpdate">
+        <el-form label-width="50px">
+          <el-row>
+            <el-col :span="10">
+              <el-form-item label="库区">
+                <el-select v-model="area" placeholder="" @change="handleChange">
+                  <el-option
+                    v-for="(item, index) in warehouseAreasSaveList"
+                    :key="item.id"
+                    :label="item.name"
+                    :value="item.id"
+                  ></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="10" v-if="type == 2">
+              <el-form-item label="货架">
+                <el-select v-model="shilves" @change="handleChange">
+                  <el-option
+                    v-for="(item, index) in areaGoodsshelvesList"
+                    :key="item.id"
+                    :label="item.goodsshelvesCode"
+                    :value="item.id"
+                  ></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-button type="text" @click="selectAll = !selectAll"
+            >全选</el-button
+          >
+        </el-form>
+      </div>
+    </div>
+    <div class="select-wrapper">
+      <el-row :gutter="10">
+        <el-col
+          :span="type == 1 ? 8 : 12"
+          v-for="(item, index) in showList"
+          :key="item.id + '*' + index"
+        >
+          <div
+            class="items"
+            :class="{
+              'item-active': !!selectList.find((i) => i.id === item.id)
+            }"
+            @click="handleCheck(item)"
+          >
+            <template v-if="type == 1">{{
+              `${item.warehouseAreaName}-${item.goodsshelvesCode}`
+            }}</template>
+            <template v-else>{{
+              `${item.warehouseAreaName}-${item.warehouseAreaGoodsCode}-${item.goodsAllocationCode}`
+            }}</template>
+          </div>
+        </el-col>
+      </el-row>
+    </div>
+    <div class="footer">
+      <el-button @click="cancel">取消</el-button>
+      <el-button type="primary" @click="confirm">确定</el-button>
+    </div>
+    <PrintWarehouse
+      ref="printWarehouseRef"
+      :config="barCodeConfig"
+      @close="QrPrintClose"
+      :openBarCode.sync="openWindows"
+    />
+  </el-dialog>
+</template>
+
+<script>
+  // import PrintWarehouse from '@/components/print/PrintWarehouse';
+  // import { batchBarPrint } from '@/api/ledgerAssets/booksList'
+  export default {
+    components: { PrintWarehouse },
+    data() {
+      return {
+        openWindows: false,
+        forceUpdate: false,
+        visible: false,
+        warehouseAreasSaveList: [],
+        type: '1',
+        shilves: '',
+        area: '',
+        selectList: [],
+        barCodeConfig: []
+      };
+    },
+    computed: {
+      areaGoodsshelvesList() {
+        this.shilves = '';
+        const obj = this.warehouseAreasSaveList.find(
+          (item) => item.id == this.area
+        );
+        return (obj?.children || []).map((item) => {
+          item.checked = false;
+          return item;
+        });
+      },
+      allocationReqList() {
+        const obj = this.areaGoodsshelvesList.find(
+          (item) => item.id == this.shilves
+        );
+
+        return (obj?.children || []).map((item) => {
+          item.checked = false;
+          return item;
+        });
+      },
+      showList() {
+        if (this.type == 1) {
+          return this.areaGoodsshelvesList;
+        } else {
+          return this.allocationReqList;
+        }
+      },
+      selectAll: {
+        get() {
+          return !!(
+            this.selectList.length &&
+            this.selectList.length === this.showList.length
+          );
+        },
+        set(val) {
+          this.selectList = val ? this.showList.slice(0) : [];
+        }
+      }
+    },
+    methods: {
+      open(list) {
+        this.warehouseAreasSaveList = list;
+        this.visible = true;
+      },
+      handleCheck(item) {
+        let index = this.selectList.findIndex((i) => i.id === item.id);
+        if (index > -1) {
+          this.selectList.splice(index, 1);
+        } else {
+          this.selectList.push(item);
+        }
+      },
+      cancel() {
+        this.visible = false;
+        this.warehouseAreasSaveList = [];
+        this.selectList = [];
+      },
+      confirm() {
+        //  const list =
+        if (!this.selectList?.length) {
+          this.$message.error(`请选择${this.type == 1 ? '货架' : '货位'}`);
+          return;
+        }
+        this.handlPrint();
+      },
+      handleRadioChange() {
+        this.selectList = [];
+      },
+      handleChange() {
+        this.selectList = [];
+      },
+      QrPrintClose() {
+        this.barCodeConfig = [];
+      },
+      async handlPrint() {
+        this.openWindows = true;
+        const barType = this.type == 1 ? 7 : 2;
+        let params = this.selectList.map((item) => {
+          return {
+            barType: barType,
+            bizId: item.id
+          };
+        });
+        let _this = this;
+        const res = await batchBarPrint(params);
+        async function getResList() {
+          for (const el of res.data) {
+            const fontTypeObj = { 1: '宋体', 2: '微软雅黑', 3: 'Arial' };
+            let item = el;
+            item.useModeList = item.useModeList.sort((a, b) => {
+              return a.barAvg.substr(4) - b.barAvg.substr(4);
+            });
+            const useModeList = item.useModeList;
+            // 条码框数据
+            _this.barCodeConfig.push({
+              putType: el.putType,
+              qrCode: el.qrCode,
+              sizeLong: el.sizeLong,
+              sizeWide: el.sizeWide,
+              code1: useModeList[0].sampleData,
+              code2: useModeList[1].sampleData,
+              code3: useModeList[2].sampleData,
+              code4: useModeList[3].sampleData,
+              code5: useModeList[4].sampleData,
+              code6: useModeList[5].sampleData,
+              code7: useModeList[6].sampleData,
+              code8: useModeList[7].sampleData,
+              code9: useModeList[8].sampleData,
+              code10: useModeList[9].sampleData,
+              code11: useModeList[10].sampleData,
+              code12: useModeList[11].sampleData,
+              code13: useModeList[12].sampleData,
+              code14: useModeList[13].sampleData,
+              fontSizeCode1: useModeList[0].fontSize,
+              fontSizeCode2: useModeList[1].fontSize,
+              fontSizeCode3: useModeList[2].fontSize,
+              fontSizeCode4: useModeList[3].fontSize,
+              fontSizeCode5: useModeList[4].fontSize,
+              fontSizeCode6: useModeList[5].fontSize,
+              fontSizeCode7: useModeList[6].fontSize,
+              fontSizeCode8: useModeList[7].fontSize,
+              fontSizeCode9: useModeList[8].fontSize,
+              fontSizeCode10: useModeList[9].fontSize,
+              fontSizeCode11: useModeList[10].fontSize,
+              fontSizeCode12: useModeList[11].fontSize,
+              fontSizeCode13: useModeList[12].fontSize,
+              fontSizeCode14: useModeList[13].fontSize,
+              typefaceCode1: fontTypeObj[useModeList[0].fontType],
+              typefaceCode2: fontTypeObj[useModeList[1].fontType],
+              typefaceCode3: fontTypeObj[useModeList[2].fontType],
+              typefaceCode4: fontTypeObj[useModeList[3].fontType],
+              typefaceCode5: fontTypeObj[useModeList[4].fontType],
+              typefaceCode6: fontTypeObj[useModeList[5].fontType],
+              typefaceCode7: fontTypeObj[useModeList[6].fontType],
+              typefaceCode8: fontTypeObj[useModeList[7].fontType],
+              typefaceCode9: fontTypeObj[useModeList[8].fontType],
+              typefaceCode10: fontTypeObj[useModeList[9].fontType],
+              typefaceCode11: fontTypeObj[useModeList[10].fontType],
+              typefaceCode12: fontTypeObj[useModeList[11].fontType],
+              typefaceCode13: fontTypeObj[useModeList[12].fontType],
+              typefaceCode14: fontTypeObj[useModeList[13].fontType]
+            });
+          }
+        }
+        getResList();
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .select-box {
+    .area {
+      padding: 20px 10px;
+      position: relative;
+
+      .el-button {
+        position: absolute;
+        right: 0;
+        bottom: 0;
+        transform: translateY(-50%);
+      }
+    }
+  }
+
+  .select-wrapper {
+    .items {
+      padding: 10px 0;
+      border: 1px solid #ccc;
+      margin-bottom: 10px;
+      text-align: center;
+      cursor: pointer;
+
+      &:hover {
+        // background-color: rgba($color: $mainColor, $alpha: 0.2);
+      }
+      &.item-active {
+        // background-color: $mainColor;
+        color: #fff;
+      }
+    }
+  }
+
+  .footer {
+    padding-top: 20px;
+    text-align: right;
+  }
+</style>

+ 83 - 0
src/views/warehouseManagement/warehouseDefinition/components/GoodsInfoDialog.vue

@@ -0,0 +1,83 @@
+<template>
+  <el-dialog
+    :visible.sync="visible"
+    center
+    width="90%"
+    :title="`货位号${title}`"
+  >
+    <el-table :data="tableData" height="50vh">
+      <el-table-column label="序号" type="index"></el-table-column>
+      <el-table-column
+        label="编码"
+        prop="onlyCode"
+        sortable
+        width="200"
+        show-overflow-tooltip
+      ></el-table-column>
+      <el-table-column
+        label="名称"
+        prop="assetName"
+        width="180"
+        show-overflow-tooltip
+      ></el-table-column>
+      <el-table-column
+        label="批次号"
+        prop="batchNum"
+        sortable
+      ></el-table-column>
+      <el-table-column label="包装编码" prop="num"></el-table-column>
+      <el-table-column
+        label="计量数量"
+        prop="measurementUnit"
+      ></el-table-column>
+      <el-table-column label="最小单元" prop="minPackUnit">
+        <template slot-scope="{ row }">
+          {{ row.unit }}/{{ row.minPackUnit }}
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="入库时间"
+        prop="createTime"
+        width="180"
+        sortable
+      ></el-table-column>
+      <el-table-column
+        label="有效期"
+        prop="expirationTime"
+        sortable
+        width="180"
+      ></el-table-column>
+      <!-- <el-table-column label="条码号" prop="">
+        <template slot-scope="{ row }">
+          <el-link type="primary" @click="codeView(row)">查看</el-link>
+        </template>
+      </el-table-column> -->
+    </el-table>
+  </el-dialog>
+</template>
+
+<script>
+  // import { getGoodsInfo } from '@/api/stockManagement/warehouseDefinition'
+  export default {
+    data() {
+      return {
+        visible: false,
+        tableData: [],
+        title: ''
+      };
+    },
+
+    methods: {
+      async open(cargoSpaceId, title) {
+        this.title = title;
+        this.visible = true;
+
+        const res = await getGoodsInfo({ cargoSpaceId });
+        if (res?.success) {
+          this.tableData = res.data;
+        }
+      },
+      codeView(row) {}
+    }
+  };
+</script>

+ 298 - 0
src/views/warehouseManagement/warehouseDefinition/components/WarehouseEdit.vue

@@ -0,0 +1,298 @@
+<template>
+  <el-dialog
+    :visible.sync="visible"
+    :title="`${type}仓库`"
+    :before-close="cancel"
+    width="500px"
+  >
+    <el-form :model="formData" :rules="rules" ref="formRef" label-width="100px">
+      <el-form-item label="仓库编码" prop="code">
+        <el-input
+          v-model="formData.code"
+          :disabled="type != '新建'"
+          placeholder="请输入"
+          size="small"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="仓库名称" size="small" prop="name">
+        <el-input
+          v-model="formData.name"
+          placeholder="限16个文字"
+          maxlength="16"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="仓库类型" prop="inventoryType">
+        <el-select
+          placeholder="请选择"
+          v-model="formData.inventoryType"
+          clearable
+          class="w100"
+        >
+          <el-option
+            v-for="(item, idx) in warehouseDefinition_inventoryList"
+            :key="item.code"
+            :value="item.code"
+            :label="item.label"
+          ></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="所属工厂" prop="factoryCode">
+        <el-select
+          size="small"
+          class="w100"
+          v-model="formData.factoryCode"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in factoryList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+            @click.native="() => (formData.factoryName = item.name)"
+          >
+          </el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="权属部门" prop="departmentName">
+        <selectTree
+          ref="tree"
+          id="tree-option"
+          size="small"
+          class="w100"
+          :initStr="formData.departmentName"
+          :options="deptList"
+          :props="{
+            value: 'code',
+            label: 'name',
+            children: 'children'
+          }"
+          @getValue="nodeClick"
+        />
+      </el-form-item>
+      <el-form-item label="权属人" prop="ownerId">
+        <el-select
+          class="w100"
+          size="small"
+          v-model="formData.ownerId"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in userList"
+            :key="item.userId"
+            :label="item.trueName"
+            :value="item.userId"
+            @click.native="
+              formData.ownerName = item.trueName;
+              formData.contact = item.mobile;
+            "
+          >
+          </el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="仓库位置" prop="location">
+        <el-cascader
+          size="small"
+          class="w100"
+          v-model="formData.location"
+          :options="locationOptions"
+        ></el-cascader>
+      </el-form-item>
+      <el-form-item label="详情地址" prop="address">
+        <el-input
+          v-model="formData.address"
+          placeholder="请输入"
+          size="small"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="备注" prop="remarks">
+        <el-input
+          type="textarea"
+          v-model="formData.remarks"
+          placeholder="请输入"
+          size="small"
+        ></el-input>
+      </el-form-item>
+      <!-- <el-form-item label="锁库状态" prop="lockStatus">
+        <el-switch
+          v-model="formData.lockStatus"
+          active-text="锁库"
+          inactive-text="开库"
+          :active-value="0"
+          :inactive-value="1"
+        ></el-switch>
+      </el-form-item> -->
+      <el-form-item label="状态" prop="status">
+        <el-switch
+          v-model="formData.status"
+          active-text="开"
+          inactive-text="关"
+          :active-value="1"
+          :inactive-value="0"
+        ></el-switch>
+      </el-form-item>
+    </el-form>
+    <el-divider></el-divider>
+    <div slot="footer">
+      <el-button type="primary" plain @click="cancel">取消</el-button>
+      <el-button type="primary" @click="handleSave" :loading="loading"
+        >确定</el-button
+      >
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+  import { warehouseSave } from '@/api/warehouseManagement/warehouseDefinition';
+  import org from '@/api/warehouseManagement/warehouseDefinition';
+
+  import selectTree from '@/components/selectTree';
+
+  import city from '@/assets/js/city';
+  // import user from '@/api/main/user';
+
+  export default {
+    components: { selectTree },
+    data() {
+      return {
+        warehouseDefinition_inventoryList: [
+          { code: 1, label: '物料仓' },
+          { code: 2, label: '产品仓' },
+          { code: 3, label: '设备仓' },
+          { code: 4, label: '模具仓' },
+          { code: 5, label: '舟皿仓' },
+          { code: 6, label: '备品备件仓' }
+        ],
+        visible: false,
+        loading: false,
+        formData: {
+          code: '',
+          name: '',
+          ownerId: '',
+          contact: '',
+          ownerName: '',
+          departmentCode: '',
+          departmentName: '',
+          address: '',
+          remarks: '',
+          location: [],
+          status: 1
+          // lockStatus: 0
+        },
+        rules: {
+          code: [
+            { required: true, message: '请输入仓库编码', trigger: 'blur' }
+          ],
+          name: [{ required: true, message: '请输入仓库名称', trigger: 'blur' }]
+        },
+        type: '新建',
+        userList: [],
+        deptList: [], //部门集合
+        factoryList: [], //工厂集合
+        locationOptions: city
+      };
+    },
+    created() {
+      this.init();
+    },
+    methods: {
+      async open(type, row) {
+        this.type = type;
+        this.visible = true;
+
+        // if (type === '修改') {
+        //   this.$nextTick(async () => {
+        //     this.formData = Object.assign({}, row);
+        //     this.formData.location = [row.province, row.city, row.area];
+
+        //     console.log(this.formData.location);
+
+        //     if (row.departmentCode) {
+        //       let userData = await user.list({
+        //         deptCode: row.departmentCode,
+        //         size: 9999
+        //       });
+        //       this.userList = userData.data.items;
+        //     }
+        //   });
+        // }
+
+        // if (type === '新建') {
+        //   let num = 1
+        //   const res = await warehouseList()
+        //   if (res?.success && res.data?.length) {
+        //     num = +res.data[0].code.substr(1) + 1
+        //   }
+        // this.formData.code = 'A' + pushZero(num)
+        // }
+      },
+      async init() {
+        org.tree().then((tree) => {
+          if (tree?.success) {
+            this.deptList = tree.data;
+          }
+        });
+
+        let res = org.factorys({ status: true });
+        if (res?.success) {
+          this.factoryList = res.data;
+        }
+      },
+
+      handleSave() {
+        this.$refs.formRef.validate(async (value) => {
+          if (value) {
+            const params = Object.assign(this.formData);
+
+            if (params.location?.length) {
+              const [province, city, area] = params.location;
+
+              Object.assign(params, {
+                province,
+                city,
+                area
+              });
+            }
+            delete params.location;
+
+            this.loading = true;
+            const res = await warehouseSave(params).finally(
+              () => (this.loading = false)
+            );
+            if (res?.success) {
+              this.$message.success('保存成功!');
+              this.$emit('success');
+              this.cancel();
+            }
+          }
+        });
+      },
+      cancel() {
+        this.$refs.formRef.resetFields();
+        this.$refs.tree.clearHandle();
+        this.visible = false;
+      },
+      async nodeClick(data) {
+        this.formData.departmentCode = data?.code;
+        this.formData.departmentName = data?.name;
+
+        this.formData.ownerName = '';
+        this.formData.ownerId = '';
+        if (data) {
+          let userData = await user.list({ deptCode: data.code, size: 99999 });
+          this.userList = userData.data.items;
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  ::v-deep .el-form {
+    .el-form-item {
+      margin-bottom: 20px;
+    }
+  }
+  .el-divider--horizontal {
+    margin: 0 !important;
+  }
+</style>

+ 665 - 0
src/views/warehouseManagement/warehouseDefinition/details.vue

@@ -0,0 +1,665 @@
+<template>
+  <div class="page">
+    <el-form label-width="130px">
+      <div class="page-title">
+        <div class="page-title-div">
+          <el-page-header @back="$router.go(-1)" content="仓库定义详情">
+            <div class="title-content" slot="content">
+              仓库定义详情
+              <el-button
+                size="mini"
+                icon="el-icon-upload2"
+                type="primary"
+                @click="exportCode"
+                >导出条码</el-button
+              >
+            </div>
+          </el-page-header>
+        </div>
+      </div>
+      <div class="content-detail">
+        <div class="basic-details">
+          <div class="basic-details-title">
+            <span class="border-span">基本信息</span>
+          </div>
+
+          <el-row>
+            <el-col :span="8">
+              <el-form-item label="仓库编码">
+                <span>{{ warehouseInfo.code }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="仓库名称">
+                <span>{{ warehouseInfo.name }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="仓库类型">
+                <span>{{
+                  warehouseInfo.inventoryType
+                    | useDictLabelFilter(warehouseDefinition_inventoryList)
+                }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="状态">
+                <span>{{ warehouseInfo.status ? '生效' : '失效' }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="所属工厂">
+                <span>{{ warehouseInfo.factoryName }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="权属部门">
+                <span>{{ warehouseInfo.departmentName }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="权属人">
+                <span>{{ warehouseInfo.ownerName }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="联系方式">
+                <span>{{ warehouseInfo.contact }}</span>
+              </el-form-item>
+            </el-col>
+
+            <el-col :span="8">
+              <el-form-item label="仓库位置">
+                <span
+                  >{{ warehouseInfo.province }} / {{ warehouseInfo.city }} /
+                  {{ warehouseInfo.area }}</span
+                >
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="详细地址">
+                <span>{{ warehouseInfo.address }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="创建人">
+                <span>{{ warehouseInfo.createUserName }}</span>
+              </el-form-item>
+            </el-col>
+
+            <!-- <el-col :span="8">
+              <el-form-item label="创建部门">
+                <span>人力资源部</span>
+              </el-form-item>
+            </el-col> -->
+            <el-col :span="8">
+              <el-form-item label="创建时间">
+                <span>{{ warehouseInfo.createTime }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="备注">
+                <span>{{ warehouseInfo.remarks }}</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </div>
+
+        <div class="basic-details mt20 warehouse-area">
+          <div class="basic-details-title">
+            <span class="border-span">货位信息</span>
+          </div>
+          <div class="status-legend">
+            <div
+              v-for="(item, index) in warehouseDefinition_locationStatus"
+              :key="index"
+            >
+              <span :style="{ 'background-color': item.color }"></span
+              >{{ item.label }}
+            </div>
+          </div>
+
+          <el-tabs v-model="warehouseAreaActive">
+            <el-tab-pane
+              :key="item.id"
+              v-for="(item, index) in warehouseAreasSaveList"
+              :label="item.name"
+              :name="index + ''"
+            >
+              <div class="msg">
+                <div>
+                  <span class="label">库区编号</span
+                  >{{ warehouseInfo.code + '-' + item.code }}
+                </div>
+                <div><span class="label">库区名称</span>{{ item.name }}</div>
+                <div>
+                  <span class="label">库区类型</span
+                  >{{
+                    item.type
+                      | useDictLabelFilter(warehouseDefinition_inventoryList)
+                  }}
+                </div>
+                <div>
+                  <span class="label">库区属性</span
+                  >{{
+                    item.attribute
+                      | useDictLabelFilter(warehouseDefinition_areaAttribute)
+                  }}
+                </div>
+                <div>
+                  <span class="label">库区长宽高(cm)</span
+                  >{{ item.areaLength }}*{{ item.areaWide }}*{{ item.areaHigh }}
+                </div>
+                <div><span class="label">货架数</span>{{ item.num }}</div>
+                <div>
+                  <span class="label">货位数</span>{{ item.allocationNumber }}
+                </div>
+                <div style="width: 10px"></div>
+              </div>
+              <div
+                class="shelves-container"
+                v-for="itm in item.children"
+                :key="itm.id"
+              >
+                <h3>货架{{ itm.goodsshelvesCode }}</h3>
+                <div class="content">
+                  <div class="content-box">
+                    <el-row :gutter="4">
+                      <el-col
+                        :span="4"
+                        v-for="p in itm.children"
+                        :key="p.id"
+                        class="box"
+                        :style="{
+                          'background-color': getStatus(p.allocationStatus)
+                            .color,
+                          color: p.allocationStatus === 3 ? '#fff' : '#000'
+                        }"
+                        >{{ p.goodsAllocationCode }}
+                        <div class="mask">
+                          {{ p.goodsAllocationCode }}
+                          <div>
+                            <i
+                              class="el-icon-tickets"
+                              @click="
+                                goodsInfoView(
+                                  p,
+                                  warehouseInfo.code +
+                                    '-' +
+                                    item.code +
+                                    '-' +
+                                    itm.goodsshelvesCode +
+                                    '-' +
+                                    p.goodsAllocationCode
+                                )
+                              "
+                            ></i>
+                            <img
+                              src="~@/assets/img/transform.svg"
+                              alt=""
+                              @click="transformStatus(p)"
+                            />
+                          </div>
+                        </div>
+                      </el-col>
+                    </el-row>
+                  </div>
+                  <div class="detail">
+                    <div>
+                      <span class="label">货架号</span
+                      >{{ warehouseInfo.code }}-{{ item.code }}-{{
+                        itm.goodsshelvesCode
+                      }}
+                    </div>
+                    <div>
+                      <span class="label">货架长宽高(cm)</span
+                      >{{ itm.goodsshelvesLength }}*{{
+                        itm.goodsshelvesWide
+                      }}*{{ itm.goodsshelvesHigh }}
+                    </div>
+                    <div>
+                      <span class="label">货架层数</span
+                      >{{ itm.goodsshelvesLine }}
+                    </div>
+                    <div>
+                      <span class="label">货位数</span>{{ itm.children.length }}
+                    </div>
+                    <div>
+                      <span class="label">空置货位数</span
+                      >{{
+                        itm.children.filter((i) => i.allocationStatus === 1)
+                          .length
+                      }}
+                    </div>
+                    <div>
+                      <span class="label">在用货位数</span
+                      >{{
+                        itm.children.filter((i) => i.allocationStatus === 2)
+                          .length
+                      }}
+                    </div>
+                    <div>
+                      <span class="label">已满货位数</span
+                      >{{
+                        itm.children.filter((i) => i.allocationStatus === 3)
+                          .length
+                      }}
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </el-tab-pane>
+          </el-tabs>
+        </div>
+      </div>
+    </el-form>
+
+    <el-dialog :visible.sync="statusVisible" title="变更货位状态" width="400px">
+      <el-radio-group v-model="statusSet">
+        <el-radio :label="0">正常</el-radio>
+        <el-radio :label="3" :disabled="[1, 4].includes(curLocation.preStatus)"
+          >已满</el-radio
+        >
+        <el-radio :label="4" :disabled="[2, 3].includes(curLocation.preStatus)"
+          >失效</el-radio
+        >
+      </el-radio-group>
+      <div slot="footer">
+        <el-button
+          type="primary"
+          plain
+          size="small"
+          @click="statusVisible = false"
+          >取消</el-button
+        >
+        <el-button
+          type="primary"
+          :loading="changeLoading"
+          size="small"
+          @click="confirmChange"
+          >确定</el-button
+        >
+      </div>
+    </el-dialog>
+    <GoodsInfoDialog ref="goodsInfoRef" />
+    <CodePrint ref="codePrintRef" />
+  </div>
+</template>
+<script>
+  // import {
+  //   warehouseDefinition_locationStatus,
+  //   warehouseDefinition_inventoryList,
+  //   warehouseDefinition_areaAttribute,
+  //   useDictLabelFilter,
+  //   useDict
+  // } from '@/utils/dict/index'
+  import CodePrint from './components/CodePrint';
+  // import {
+  //   warehouseDetails,
+  //   warehouseChangeStatus
+  // } from '@/api/stockManagement/warehouseDefinition';
+  import GoodsInfoDialog from './components/GoodsInfoDialog.vue';
+
+  export default {
+    components: { GoodsInfoDialog, CodePrint },
+    data() {
+      return {
+        warehouseDefinition_areaAttribute,
+        warehouseDefinition_inventoryList,
+        warehouseDefinition_locationStatus,
+        statusVisible: false,
+        warehouseAreaActive: '0',
+        num: 1,
+        warehouseAreasSaveList: [], //库区
+        warehouseAreaGoodsshelvesList: [],
+        allocationList: [],
+        shelfData: [],
+        detailInfo: {},
+        warehouseInfo: {}, //仓储基本信息
+        reservoirAreaData: [],
+        curLocation: {},
+        changeLoading: false
+      };
+    },
+    filters: {
+      useDictLabelFilter: useDictLabelFilter
+    },
+    computed: {
+      // 货位状态修改
+      statusSet: {
+        set(val) {
+          this.curLocation.allocationStatus = val;
+        },
+        get() {
+          if (this.curLocation.allocationStatus) {
+            if ([1, 2].includes(this.curLocation.allocationStatus)) {
+              return 0;
+            }
+            return this.curLocation.allocationStatus;
+          }
+
+          if (
+            this.curLocation.allocationStatus === 0 ||
+            [1, 2].includes(this.curLocation.preStatus)
+          ) {
+            return 0;
+          }
+          return this.curLocation.preStatus;
+        }
+      }
+    },
+    created() {
+      this.getInfo();
+    },
+    methods: {
+      getStatus: useDict(warehouseDefinition_locationStatus),
+      exportCode() {
+        this.$refs.codePrintRef.open(this.warehouseAreasSaveList);
+      },
+      async getInfo() {
+        const res = await warehouseDetails({ id: this.$route.query.id });
+        if (res?.success) {
+          this.warehouseInfo = res.data.warehouseSaveReq || {};
+          const {
+            warehouseAreasSaveList = [],
+            areaGoodsshelvesList = [],
+            allocationReqList = []
+          } = res.data;
+
+          warehouseAreasSaveList.forEach((item) => {
+            item.children = areaGoodsshelvesList
+              .filter((i) => i.warehouseAreaCode === item.code)
+              .map((itm) => {
+                itm.children = allocationReqList.filter(
+                  (i) =>
+                    itm.goodsshelvesCode === i.warehouseAreaGoodsCode &&
+                    itm.warehouseAreaCode === i.warehouseAreaCode
+                );
+                return itm;
+              });
+          });
+          this.warehouseAreasSaveList = warehouseAreasSaveList;
+          this.warehouseInfo = res.data.warehouseSaveReq || {};
+
+          console.log(warehouseAreasSaveList);
+        }
+      },
+      //变更货位状态
+      transformStatus(item) {
+        this.curLocation = Object.assign(item);
+        this.curLocation.preStatus = item.allocationStatus;
+        this.statusVisible = true;
+      },
+      async confirmChange() {
+        this.changeLoading = true;
+
+        try {
+          const res = await warehouseChangeStatus(this.curLocation);
+          this.statusVisible = false;
+          if (res?.success) {
+            this.$message.success('操作成功!');
+            this.getInfo();
+          } else {
+            this.$message.success('操作失败!');
+          }
+        } catch (error) {}
+        this.changeLoading = false;
+      },
+      goodsInfoView({ id }, title) {
+        this.$refs.goodsInfoRef.open(id, title);
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  .page {
+    padding: 10px;
+    margin: 10px 0 10px 0;
+    height: calc(100vh - 80px);
+    padding: 10px;
+    overflow-y: auto;
+
+    .title-content {
+      .el-button {
+        position: absolute;
+        right: 20px;
+        top: 50%;
+        transform: translateY(-50%);
+      }
+    }
+  }
+
+  .page-title {
+    background: #fff;
+    font-size: 18px;
+    padding: 6px 20px;
+    font-weight: 500;
+    .page-title-div {
+      position: relative;
+      margin: 5px 0;
+      height: 30px;
+      line-height: 30px;
+      border-bottom: 1px solid #eaeefb;
+    }
+  }
+  .mt20 {
+    margin-top: 20px;
+  }
+  .content-detail {
+    background: #fff;
+    padding: 20px;
+  }
+
+  .warehouse-area {
+    .msg {
+      line-height: 52px;
+      background-color: rgba(242, 242, 242, 1);
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      flex-wrap: wrap;
+      padding: 0 20px;
+      margin-bottom: 12px;
+      .label {
+        color: #333;
+        margin-right: 12px;
+        font-weight: bold;
+      }
+    }
+
+    .shelves-container {
+      .content {
+        display: flex;
+        align-items: stretch;
+      }
+      .detail {
+        width: 282px;
+        background-color: rgba(242, 242, 242, 1);
+        border-radius: 8px;
+        margin-left: 12px;
+        padding: 20px 0 0 2px;
+
+        > div {
+          margin-bottom: 12px;
+          .label {
+            display: inline-block;
+            width: 8em;
+            color: #333;
+            font-weight: bold;
+            text-align: right;
+            margin-right: 6px;
+          }
+        }
+      }
+      h3 {
+        // color: $mainColor;
+        font-size: 16px;
+      }
+
+      .content-box {
+        flex: 1;
+        .box {
+          background-clip: content-box;
+          height: 64px;
+          margin-bottom: 4px;
+          cursor: pointer;
+          position: relative;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          &:hover .mask {
+            display: block;
+          }
+          .mask {
+            display: none;
+            position: absolute;
+            top: 0;
+            left: 3px;
+            right: 3px;
+            bottom: 0;
+            background-color: rgba(0, 0, 0, 0.7);
+            color: #fff;
+            font-weight: bold;
+            text-align: center;
+            padding: 18px 25%;
+            img {
+              width: 1em;
+              height: 1em;
+            }
+            div {
+              margin-top: 8px;
+              display: flex;
+              justify-content: space-between;
+            }
+          }
+        }
+      }
+    }
+  }
+  .status-legend {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    div {
+      margin: 0 12px;
+    }
+    span {
+      display: inline-block;
+      width: 13px;
+      height: 13px;
+      margin: 0 4px;
+    }
+  }
+
+  .basic-details-title {
+    margin-bottom: 12px;
+    margin-top: 20px;
+    border-bottom: 1px solid #157a2c;
+    padding-bottom: 8px;
+    display: flex;
+    justify-content: space-between;
+  }
+  .basic-details-title .border-span {
+    height: 18px;
+    font-size: 16px;
+    border-left: 4px solid #157a2c;
+    padding-left: 8px;
+    font-weight: 500;
+  }
+
+  .area {
+    margin-top: 20px;
+    .title {
+      font-size: 14px;
+      span {
+        font-weight: bold;
+      }
+    }
+    .mt10 {
+      margin-top: 10px;
+    }
+  }
+  .locationFlex {
+    display: flex;
+    justify-content: space-between;
+    .locationRight {
+      .flex {
+        display: flex;
+        .title {
+          width: 50px;
+          font-size: 13px;
+          text-align: center;
+          margin-right: 5px;
+          margin-bottom: 5px;
+        }
+        .locationContent {
+          width: 50px;
+          padding: 10px 0;
+          color: #fff;
+          font-size: 13px;
+          text-align: center;
+          margin-right: 5px;
+          margin-bottom: 5px;
+        }
+      }
+    }
+    .green {
+      background-color: #157a2c;
+    }
+    .red {
+      background-color: #a60014;
+    }
+    .blue {
+      background-color: #027db4;
+    }
+  }
+  .no_data {
+    padding: 50px 0;
+    text-align: center;
+  }
+  .shelfBox {
+    display: flex;
+    justify-content: space-between;
+    .shelfCode {
+      // width: 60px;
+      padding: 74px 6px;
+      color: #fff;
+      text-align: center;
+      background-color: #157a2c;
+      font-size: 12px;
+    }
+  }
+  .shelfDataBox {
+    display: flex;
+    .shelfLeft {
+      width: 50%;
+      margin-right: 20px;
+      .shlefCode {
+        font-size: 12px;
+        display: block;
+        margin-bottom: 10px;
+      }
+      .shelfChildren {
+        display: flex;
+        .shelfShow {
+          background-color: #027db4;
+          color: #fff;
+          font-size: 12px;
+          padding: 12px;
+        }
+      }
+    }
+    .shelfRight {
+      flex: 1;
+    }
+  }
+  .mb10 {
+    margin-bottom: 10px;
+  }
+  .mb5 {
+    margin-bottom: 2px;
+  }
+  .mr10 {
+    margin-right: 10px;
+  }
+</style>

+ 24 - 0
src/views/warehouseManagement/warehouseDefinition/enum.js

@@ -0,0 +1,24 @@
+export const areaType = [
+    {key:"1",name:"原料库"},
+    {key:"2",name:"成品库"},
+    {key:"3",name:"设备库"},
+    {key:"4",name:"舟皿库"},
+    {key:"5",name:"模具库"},
+    {key:"6",name:"周转车库"},
+    {key:"7",name:"不良品库"},
+]
+export const areaAttribute = [
+    {key:"1",name:"常温"},
+    {key:"2",name:"冷藏"},
+    {key:"3",name:"恒温"},
+    {key:"4",name:"低温"}
+]
+export const statusList = [
+    {key:"0",name:"生效"},
+    {key:"1",name:"失效"}
+]
+export const inventoryList = [
+    { key: '1', name: '物料库' },
+    { key: '2', name: '产品库' },
+    { key: '3', name: '设备库' }
+  ]

+ 393 - 0
src/views/warehouseManagement/warehouseDefinition/index.vue

@@ -0,0 +1,393 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="nvner">
+      <el-form :model="formData" ref="formName" label-width="100px">
+        <el-row>
+          <el-col :span="4">
+            <el-form-item label="仓库编码" prop="code">
+              <el-input
+                placeholder="请输入"
+                v-model="formData.code"
+                clearable
+                class="w100"
+              ></el-input> </el-form-item
+          ></el-col>
+          <el-col :span="4">
+            <el-form-item label="仓库类型" prop="inventoryType">
+              <el-select
+                placeholder="请选择"
+                v-model="formData.inventoryType"
+                clearable
+                class="w100"
+              >
+                <el-option
+                  v-for="item in warehouseDefinition_inventoryList"
+                  :key="item.code"
+                  :value="item.code"
+                  :label="item.label"
+                ></el-option>
+              </el-select> </el-form-item
+          ></el-col>
+          <el-col :span="5">
+            <el-form-item label="所属工厂" prop="factoryId">
+              <el-select
+                placeholder="请选择"
+                v-model="formData.factoryId"
+                clearable
+                class="w100"
+              >
+                <el-option
+                  v-for="item in factoryList"
+                  :key="item.id"
+                  :label="item.name"
+                  :value="item.id"
+                ></el-option>
+              </el-select> </el-form-item
+          ></el-col>
+          <el-col :span="5">
+            <el-form-item label="空货位数">
+              <div class="divider11">
+                <el-col :span="9">
+                  <el-form-item label="" prop="emptyAllocationStart">
+                    <el-input
+                      type="text"
+                      @input="
+                        (value) =>
+                          (formData.emptyAllocationStart = value.replace(
+                            /[^\d]+/g,
+                            ''
+                          ))
+                      "
+                      v-model="formData.emptyAllocationStart"
+                    ></el-input
+                  ></el-form-item>
+                </el-col>
+
+                <div class="divider111"> <el-divider></el-divider></div>
+
+                <el-col :span="9">
+                  <el-form-item label="" prop="emptyAllocationEnd">
+                    <el-input
+                      type="text"
+                      @input="
+                        (value) =>
+                          (formData.emptyAllocationEnd = value.replace(
+                            /[^\d]+/g,
+                            ''
+                          ))
+                      "
+                      v-model="formData.emptyAllocationEnd"
+                    ></el-input> </el-form-item
+                ></el-col>
+              </div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6" style="text-align: right">
+            <el-form-item>
+              <div>
+                <el-button icon="el-icon-refresh-left" @click="reset"
+                  >重置</el-button
+                >
+                <el-button type="primary" icon="el-icon-search" @click="search"
+                  >搜索</el-button
+                >
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+
+      <div>
+        <el-button type="primary" icon="el-icon-plus" @click="add"
+          >新建仓库</el-button
+        >
+      </div>
+      <div class="warehouse-container">
+        <div
+          class="warehouse-card"
+          v-for="(item, index) in warehouse"
+          :key="index"
+        >
+          <h3 :class="item.status === 0 ? 'grey' : ''">
+            {{ item.code }} <span>{{ item.name }}</span>
+          </h3>
+          <el-row class="warehouse-card-main">
+            <el-col
+              :span="idx === warehouseLabel.length - 1 ? 24 : idx % 2 ? 9 : 15"
+              v-for="(itm, idx) in warehouseLabel"
+              :key="idx"
+            >
+              <span class="label">{{ itm.label }}</span>
+              <template v-if="itm.key === 'status'">
+                <span :class="item[itm.key] === 0 ? 'danger-text' : ''">{{
+                  itm.filter(item[itm.key])
+                }}</span>
+              </template>
+              <template v-else-if="itm.filter">{{
+                itm.filter(item[itm.key])
+              }}</template>
+              <template v-else>{{ item[itm.key] }}</template>
+            </el-col>
+          </el-row>
+          <div class="warehouse-card-footer">
+            <el-link type="primary" :underline="false" @click="add(item)"
+              >修改仓库</el-link
+            >
+            <el-link
+              type="primary"
+              :underline="false"
+              @click="locationManage(item)"
+              >货位管理</el-link
+            >
+            <el-link type="primary" :underline="false" @click="details(item)"
+              >查看详情</el-link
+            >
+            <el-link type="danger" :underline="false" @click="remove(item)"
+              >删除</el-link
+            >
+          </div>
+        </div>
+        <div class="warehouse-card-placeholder"></div>
+        <div class="warehouse-card-placeholder"></div>
+      </div>
+    </el-card>
+    <WarehouseEdit ref="warehouseEditRef" @success="handleList" />
+  </div>
+</template>
+
+<script>
+  // import tablePagination from '../components/tablePagination.vue';
+  // import {
+  //   warehouseListValuable,
+  //   warehouseRemove
+  // } from '@/api/stockManagement/warehouseDefinition';
+
+  // import selectTree from '@/components/selectTree'
+  import WarehouseEdit from './components/WarehouseEdit';
+  // import org from '@/api/warehouseManagement/warehouseDefinition';
+  import dictMixins from '@/mixins/dictMixins';
+  export default {
+    // components: { selectTree, tablePagination, WarehouseEdit },
+    components: { WarehouseEdit },
+
+    mixins: [dictMixins],
+    data() {
+      return {
+        formData: {
+          code: '',
+          name: '',
+          status: '',
+          inventoryType: '',
+          emptyAllocationEnd: '',
+          emptyAllocationStart: ''
+        },
+        warehouseDefinition_inventoryList: [
+          { code: 1, label: '物料仓' },
+          { code: 2, label: '产品仓' },
+          { code: 3, label: '设备仓' },
+          { code: 4, label: '模具仓' },
+          { code: 5, label: '舟皿仓' },
+          { code: 6, label: '备品备件仓' }
+        ],
+        factoryList: [],
+        treeList: [],
+        warehouse: [],
+        warehouseLabel: [
+          {
+            label: '状态',
+            key: 'status',
+            filter: (code) => getDictValue('仓库状态', code)
+          },
+          {
+            label: '仓库类型',
+            key: 'inventoryType',
+            filter: (code) => getDictValue('WD_inventoryList', code)
+          },
+          { label: '库区数', key: 'areaNumber' },
+          { label: '货架数', key: 'goodNumber' },
+          { label: '货位数', key: 'allocationNumber' },
+          { label: '空货位数', key: 'emptyAllocationNumber' },
+          { label: '所属工厂', key: 'factoryName' }
+        ]
+      };
+    },
+    created() {
+      this.requestDict('仓库状态');
+      this.handleList();
+      this.initData();
+    },
+    methods: {
+      initData() {
+        org.tree().then((res) => {
+          if (res?.success) {
+            this.treeList = res.data;
+          }
+        });
+
+        let data = org.factorys({ status: true });
+        this.factoryList = data.data;
+      },
+      async handleList() {
+        const res = await warehouseListValuable(this.formData);
+        if (res?.success) {
+          this.warehouse = res.data;
+        }
+      },
+      search() {
+        this.handleList();
+      },
+      add(item) {
+        let type = '新建';
+        if (item.id) {
+          type = '修改';
+        }
+        this.$refs.warehouseEditRef.open(type, item);
+      },
+      locationManage({ id, code, name }) {
+        this.$router.push({
+          path: '/warehouseManagement/warehouseDefinition/add',
+          query: {
+            id,
+            code,
+            name
+          }
+        });
+      },
+      details(data) {
+        this.$router.push({
+          path: '/warehouseManagement/warehouseDefinition/details',
+          query: {
+            id: data.id
+          }
+        });
+      },
+      edit(data) {
+        this.$router.push({
+          path: '/warehouseManagement/warehouseDefinition/edit',
+          query: {
+            id: data.id
+          }
+        });
+      },
+      reset() {
+        this.$refs.formName.resetFields();
+        this.search();
+      },
+      remove({ id, name }) {
+        this.$confirm(`确认删除仓库${name}?`).then(async () => {
+          const res = await warehouseRemove({ id });
+          if (res?.success) {
+            this.$message.success('删除成功!');
+            this.handleList();
+          }
+        });
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .divider11 {
+    display: flex;
+    align-items: center;
+  }
+  .divider111 {
+    padding: 0 10px;
+    flex: 1;
+  }
+  .devider {
+    position: relative;
+    padding-top: 20px;
+    &::before {
+      content: '';
+      border-top: 10px solid #f2f2f2;
+      z-index: 1;
+      position: absolute;
+      top: 0;
+      left: -25px;
+      right: -30px;
+    }
+  }
+  .warehouse-container {
+    display: flex;
+    justify-content: space-between;
+    // align-content: flex-start;
+    flex-wrap: wrap;
+    padding: 20px 0;
+    .warehouse-card-placeholder {
+      width: 350px;
+    }
+    .warehouse-card {
+      width: 350px;
+      font-size: 14px;
+      border: 1px solid rgb(121, 121, 121);
+      margin-bottom: 20px;
+      padding-bottom: 30px;
+      position: relative;
+      h3 {
+        height: 35px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        // background-color: $mainColor;
+        color: #fff;
+        padding: 8px;
+        span {
+          font-size: 18px;
+          font-weight: bold;
+        }
+
+        &.grey {
+          background-color: rgb(170, 170, 170);
+          color: rgba(0, 0, 0, 0.85);
+        }
+      }
+      .warehouse-card-main {
+        padding: 8px 12px;
+        color: rgba($color: #000000, $alpha: 0.89);
+        .el-col {
+          padding: 8px 0;
+        }
+        .label {
+          font-weight: bold;
+          display: inline-block;
+          width: 4.5em;
+        }
+      }
+
+      .warehouse-card-footer {
+        position: absolute;
+        bottom: 0;
+        left: 0;
+        right: 0;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 0 12px;
+        height: 30px;
+        background-color: rgb(242, 242, 242);
+      }
+    }
+  }
+
+  .p20 {
+    padding: 20px;
+  }
+  .mt20 {
+    margin-top: 20px;
+  }
+  .mt10 {
+    margin-top: 10px;
+  }
+  .el-form {
+    overflow: hidden;
+  }
+  .float-right {
+    float: right;
+    text-align: right;
+    margin-right: 20px;
+  }
+  .right {
+    text-align: right;
+  }
+</style>

+ 42 - 0
src/views/warehouseManagement/warehouseDefinition/mixins.js

@@ -0,0 +1,42 @@
+// import { warehouseDetails } from '@/api/stockManagement/warehouseDefinition'
+// import user from '@/api/main/user';
+export default {
+  data() {
+    return {
+      id: ''
+    };
+  },
+  created() {
+    this.id = this.$route.query.id;
+    if (this.id) {
+      this.isEdit = true;
+      this.ownerNameDisabled = false;
+      this.areaDisabled = false;
+      this.addressDisabled = false;
+      this.getDetails();
+    }
+  },
+  methods: {
+    getDetails() {
+      let res = warehouseDetails({ id: this.id });
+      if (res.success) {
+        for (var i in this.form) {
+          if (i === 'status' || i === 'inventoryType') {
+            res.data.warehouse[i] = res.data.warehouse[i].toString();
+          }
+          this.$set(this.form, i, res.data.warehouse[i]);
+        }
+        console.log(this.form.departmentCode);
+        this.areaForm.warehouseAreasSaveList = res.data.warehouseAreaList;
+        this.areaForm.areaGoodsshelvesList =
+          res.data.warehouseAreaGoodsshelvesList;
+        this.areaForm.allocationReqList = res.data.allocationList;
+        if (this.form.departmentCode) this.getUserInfo();
+      }
+    },
+    getUserInfo() {
+      let res = user.user({ deptCode: this.form.departmentCode });
+      this.staffList = res.data;
+    }
+  }
+};

Some files were not shown because too many files changed in this diff