Browse Source

备品备件功能提交

luogang 6 tháng trước cách đây
mục cha
commit
5e9499b9e3

+ 73 - 0
src/api/sparesManage/index.ts

@@ -56,3 +56,76 @@ export const delWarehouse = (id: string | number | Array<string | number>) => {
         method: 'delete'
     });
 };
+
+/**
+ * 查询入库列表
+ * @param query
+ * @returns {*}
+ */
+export const listDeviceInWarehouse = (query) => {
+  return request({
+      url: '/jdyw/deviceInWarehouse/list',
+      method: 'get',
+      params: query
+  });
+};
+/**
+ * 新增入库信息
+ * @param data
+ */
+export const addDeviceInWarehouse = (data) => {
+  return request({
+      url: '/jdyw/deviceInWarehouse',
+      method: 'post',
+      data: data
+  });
+};
+/**
+ * 查询实时库存列表
+ * @param query
+ * @returns {*}
+ */
+export const getRealStorelist = (query) => {
+  return request({
+      url: '/jdyw/deviceInWarehouse/realStorelist',
+      method: 'get',
+      params: query
+  });
+};
+/**
+ * 根据设备查询入库列表
+ * @param query
+ * @returns {*}
+ */
+export const getInWarehouseListByDevice = (deviceTypeDetailId) => {
+  return request({
+      url: '/jdyw/deviceInWarehouse/getInWarehouseListByDevice',
+      method: 'get',
+      params: {
+        deviceTypeDetailId
+      }
+  });
+};
+
+/**
+ * 新增出库信息
+ * @param data
+ */
+export const addDeviceOutWarehouse = (data) => {
+  return request({
+      url: '/jdyw/deviceOutWarehouse',
+      method: 'post',
+      data: data
+  });
+};
+/**
+ * 出库列表
+ * @param data
+ */
+export const listDeviceOutWarehouse = (query) => {
+  return request({
+      url: '/jdyw/deviceOutWarehouse/list',
+      method: 'get',
+      params: query
+  });
+};

+ 32 - 0
src/assets/styles/element-ui.scss

@@ -147,3 +147,35 @@
 .el-form--inline .el-input {
   width: 240px;
 }
+// 自定义drawer样式
+.customDrawer {
+  .el-drawer__header {
+    align-items: flex-start !important;
+    margin-bottom: 10px;
+
+    .drawer-title {
+      .el-descriptions__body {
+        margin-top: 10px;
+        background-color: #F4F5F7;
+        border-radius: 2px;
+        padding: 10px 10px 0 10px;
+      }
+
+      .el-descriptions__label {
+        padding-bottom: 5px;
+      }
+
+      .title-name {
+        color: #000;
+      }
+    }
+  }
+
+  .el-drawer__body {
+    padding-top: 0;
+
+    .el-collapse-item__content {
+      padding-bottom: 8px;
+    }
+  }
+}

+ 0 - 1
src/views/deviceMaintain/innerWorkorder/index.vue

@@ -93,7 +93,6 @@
               <el-input v-model="form.remark" placeholder="请输入" />
             </el-form-item>
           </el-col>
-
         </el-row>
       </el-form>
       <template #footer>

+ 0 - 33
src/views/deviceMaintain/record/index.vue

@@ -385,36 +385,3 @@ onMounted(() => {
   }
 }
 </style>
-<style lang="scss">
-.customDrawer {
-  .el-drawer__header {
-    align-items: flex-start !important;
-    margin-bottom: 10px;
-
-    .drawer-title {
-      .el-descriptions__body {
-        margin-top: 10px;
-        background-color: #F4F5F7;
-        border-radius: 2px;
-        padding: 10px 10px 0 10px;
-      }
-
-      .el-descriptions__label {
-        padding-bottom: 5px;
-      }
-
-      .title-name {
-        color: #000;
-      }
-    }
-  }
-
-  .el-drawer__body {
-    padding-top: 0;
-
-    .el-collapse-item__content {
-      padding-bottom: 8px;
-    }
-  }
-}
-</style>

+ 5 - 0
src/views/deviceManage/versionManage/index.vue

@@ -63,6 +63,7 @@
             </el-table-column>
             <el-table-column label="品牌" align="center" prop="ext1.brand" />
             <el-table-column label="型号" align="center" prop="xh" />
+            <el-table-column label="单位" align="center" prop="units" />
             <el-table-column label="供应商" align="center" prop="productorId">
               <template #default="scope">
                 {{ formatDict(scope.row.productorId, 'productorOptions') }}
@@ -103,6 +104,9 @@
         <el-form-item label="型号" prop="xh" :rules="[{ required: true, message: '型号不能为空', trigger: 'blur' }]">
           <el-input v-model="form.xh" placeholder="请输入型号" />
         </el-form-item>
+        <el-form-item label="单位" prop="units" :rules="[{ required: true, message: '单位不能为空', trigger: 'blur' }]">
+          <el-input v-model="form.units" placeholder="请输入单位" />
+        </el-form-item>
         <el-form-item label="供应商" prop="productorId"
           :rules="[{ required: true, message: '供应商不能为空', trigger: 'change' }]">
           <el-select v-model="form.productorId" clearable placeholder="请选择供应商" @change="setProductorInfo">
@@ -180,6 +184,7 @@ const initFormData = {
   productorId: '',
   deviceTypeId: undefined,
   xh: null,
+  units: undefined,
   remark: undefined,
   ext1: <any>{
     brand: undefined,

+ 272 - 116
src/views/sparesManage/inStore/index.vue

@@ -26,46 +26,41 @@
           <el-col :span="1.5">
             <el-button type="primary" plain icon="Plus" @click="handleAdd"> 新增 </el-button>
           </el-col>
-          <el-col :span="1.5">
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"> 修改
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"> 删除
-            </el-button>
-          </el-col>
           <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
         </el-row>
       </template>
 
-      <el-table v-loading="loading" :data="tableList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="入库单号" align="center" show-overflow-tooltip prop="sn" width="150" />
+      <el-table v-loading="loading" :data="tableList" >
+        <el-table-column label="入库单号" align="center" show-overflow-tooltip prop="sn" width="180" />
         <el-table-column label="入库名称" align="center" show-overflow-tooltip prop="name" width="150" />
         <el-table-column label="设备种类" align="center" show-overflow-tooltip prop="deviceCategory" width="150" />
         <el-table-column label="到货数量" align="center" show-overflow-tooltip prop="deviceNum" width="150" />
-        <el-table-column label="入库仓库" align="center" show-overflow-tooltip prop="storeName" width="150" />
-        <el-table-column label="入库人" align="center" show-overflow-tooltip prop="storePerson" width="150"/>
-        <el-table-column label="入库时间" align="center" show-overflow-tooltip prop="storeDate"  width="150"/>
+        <el-table-column label="入库仓库" align="center" show-overflow-tooltip  width="150" >
+          <template #default="scope">
+            <span>{{ formatWareHouse(scope.row.warehouseId) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="入库人" align="center" show-overflow-tooltip prop="createName" width="150" />
+        <el-table-column label="入库时间" align="center" show-overflow-tooltip prop="createTime" width="150" />
         <el-table-column label="入库说明" align="center" show-overflow-tooltip prop="remark" width="150" />
-        <el-table-column label="操作" align="center" width="100" fixed="right" class-name="small-padding fixed-width">
+        <!-- <el-table-column label="操作" align="center" width="100" fixed="right" class-name="small-padding fixed-width">
           <template #default="scope">
             <el-button size="small" link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
             <el-button size="small" link type="danger" @click="handleDelete(scope.row)">删除</el-button>
           </template>
-        </el-table-column>
+        </el-table-column> -->
       </el-table>
       <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
         :total="total" @pagination="getList" />
     </el-card>
     <!-- 添加或修改对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="950px" append-to-body>
+    <el-dialog v-model="dialog.visible" :title="dialog.title" width="1200px" append-to-body>
       <el-form ref="addFormRef" :model="form" label-width="110px">
         <SubTitle title="基本信息" />
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item label="入库单号" prop="sn" :rules="[{ required: true, message: '入库单号不能为空', trigger: 'blur' }]">
-              <el-input v-model="form.sn" placeholder="请输入入库单号" />
+            <el-form-item label="入库单号" prop="sn">
+              <el-input v-model="form.sn" disabled />
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -75,26 +70,23 @@
           </el-col>
 
           <el-col :span="12">
-            <el-form-item label="入库人" prop="storePerson"
-              :rules="[{ required: true, message: '入库人不能为空', trigger: 'change' }]">
-              <el-select v-model="form.storePerson" clearable placeholder="请选择入库人" >
-                <el-option v-for="item in userOptions" :key="item.userId" :label="item.nickName"
-                  :value="item.userId"></el-option>
-              </el-select>
+            <el-form-item label="入库人" prop="createName">
+              <el-input v-model="form.createName" disabled />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="入库仓库" prop="storeName" :rules="[{ required: true, message: '入库仓库不能为空', trigger: 'change' }]">
-              <el-select v-model="form.storeName" clearable placeholder="请选择入库仓库" >
-                <el-option value="仓库一"></el-option>
-                <el-option value="仓库二"></el-option>
+            <el-form-item label="入库仓库" prop="warehouseId"
+              :rules="[{ required: true, message: '入库仓库不能为空', trigger: 'change' }]">
+              <el-select v-model="form.warehouseId" clearable placeholder="请选择入库仓库" @change="getShelfList">
+                <el-option v-for="item in wareHouseOptions" :key="item.id" :value="item.id"
+                  :label="item.name"></el-option>
               </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="入库时间" prop="storeDate"
+            <el-form-item label="入库时间" prop="ext1.storeDate"
               :rules="[{ required: true, message: '入库时间不能为空', trigger: 'change' }]">
-              <el-date-picker v-model="form.storeDate" style="width: 100%;" value-format="YYYY-MM-DD" type="date"
+              <el-date-picker v-model="form.ext1.storeDate" style="width: 100%;" value-format="YYYY-MM-DD" type="date"
                 placeholder="选择日期">
               </el-date-picker>
             </el-form-item>
@@ -105,44 +97,71 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <SubTitle title="采购备品备件" style="margin-bottom: 10px;" />
+        <div class="device-title">
+          <SubTitle title="采购备品备件" style="margin-bottom: 10px;" />
+          <div>
+            <span>设备种类:{{ deviceTypeNum }}</span>
+            <span>合计入库数量:{{ deviceNum }}</span>
+          </div>
+        </div>
+
         <el-table :data="form.deviceInfo" max-height="300">
-          <el-table-column label="备品备件名称" align="center">
+          <el-table-column label="备品备件名称" align="center" width="120">
             <template #default="scope">
-              <el-input v-model="scope.row.deviceName" placeholder="请输入" />
+              <el-select v-model="scope.row.deviceTypeDetailId" clearable placeholder="请选择"
+                @change="devTypeDetailChange($event, scope.$index)">
+                <el-option v-for="dict in deviceTypeDetailOptions" :key="dict.id" :label="dict.deviceType.name"
+                  :value="dict.id">
+                  <span style="float: left">{{ dict.deviceType.name }}</span>
+                  <span style="float: right;color: var(--el-text-color-secondary);font-size: 13px;">
+                    {{ dict.ext1.brand }}{{ dict.xh }}
+                  </span>
+                </el-option>
+              </el-select>
             </template>
           </el-table-column>
-          <el-table-column label="品牌" align="center">
+          <el-table-column label="品牌" align="center" width="130">
             <template #default="scope">
-              <el-input v-model="scope.row.brand" placeholder="请输入" />
+              <el-input v-model="scope.row.brand" disabled />
             </template>
           </el-table-column>
-          <el-table-column label="型号" align="center">
+          <el-table-column label="型号" align="center" width="120">
             <template #default="scope">
-              <el-input v-model="scope.row.xh" placeholder="请输入" />
+              <el-input v-model="scope.row.xh" disabled />
             </template>
           </el-table-column>
-          <el-table-column label="供应商" align="center">
+          <el-table-column label="供应商" align="center" width="120">
             <template #default="scope">
-              <el-input v-model="scope.row.productor" placeholder="请输入" />
+              <el-input v-model="scope.row.productor" disabled />
             </template>
           </el-table-column>
-          <el-table-column label="单位" align="center">
+          <el-table-column label="单位" align="center" width="80">
             <template #default="scope">
-              <el-input v-model="scope.row.unit" placeholder="请输入" />
+              <el-input v-model="scope.row.unit" disabled />
+            </template>
+          </el-table-column>
+          <el-table-column label="质保期" align="center" width="150">
+            <template #default="scope">
+              <el-date-picker v-model="scope.row.qualityEndTime" style="width: 100%;" value-format="YYYY-MM-DD"
+                type="date" placeholder="选择日期">
+              </el-date-picker>
             </template>
           </el-table-column>
           <el-table-column label="本次入库数量" align="center">
             <template #default="scope">
-              <el-input v-model="scope.row.deviceNum" placeholder="请输入" />
+              <el-input-number v-model="scope.row.num" style="width: 100%;" :min="1" controls-position="right" />
             </template>
           </el-table-column>
           <el-table-column label="入库库位" align="center">
             <template #default="scope">
-              <el-input v-model="scope.row.shelf" placeholder="请输入" />
+              <el-select v-model="scope.row.shelfInfo" clearable placeholder="请选择">
+                <el-option v-for="dict in shelfOptions" :key="dict.shelfName" :label="dict.shelfName"
+                  :value="dict.shelfName">
+                </el-option>
+              </el-select>
             </template>
           </el-table-column>
-          <el-table-column label="操作" align="center" width="80">
+          <el-table-column label="操作" align="center" width="80" fixed="right">
             <template #header>
               <div class="operateBtn">
                 <span>操作</span>
@@ -171,15 +190,14 @@
 
 <script setup name="InStore" lang="ts">
 import { deepClone } from '@/utils';
-import { listUser } from '@/api/system/user/index'
+import useUserStore from '@/store/modules/user';
+import { listWarehouse, listDeviceInWarehouse, addDeviceInWarehouse } from '@/api/sparesManage/index';
+import { listDeviceType, getDeviceTypeDetailList } from '@/api/deviceManage/deviceType';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const tableList = ref([]);
 const buttonLoading = ref(false);
 const loading = ref(true);
 const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
 const total = ref(0);
 const queryFormRef = ref<ElFormInstance>();
 const addFormRef = ref<ElFormInstance>();
@@ -191,78 +209,82 @@ const initFormData = {
   id: undefined,
   sn: undefined,
   name: undefined,
-  deviceCategory: undefined,
-  deviceNum: undefined,
-  storeName: undefined,
-  storePerson: undefined,
-  storeDate: undefined,
+  warehouseId: undefined,
+  createName: undefined,
   remark: undefined,
   deviceInfo: [{
-    deviceName:'',
-    brand:'',
+    deviceTypeDetailId: '',
+    brand: '',
     xh: '',
     productor: '',
+    qualityEndTime: '',
     unit: '',
-    deviceNum: '',
-    shelf:''
+    num: '',
+    shelfInfo: ''
   }],
-  ext1: undefined,
+  ext1: {
+    storeDate: undefined,
+  },
   ext2: undefined
 };
 const formData = reactive({
   form: { ...initFormData },
   queryParams: {
     pageNum: 1,
-    pageSize: 10,
+    pageSize: 100000,
     name: undefined,
-    status: undefined,
+    sn: undefined,
     params: {}
   }
 });
 const { queryParams, form } = toRefs(formData);
+const deviceTypeDetailOptions = ref([])
+const wareHouseOptions = ref([])
+const shelfOptions = ref([])
 
-const userOptions = ref([])
+const deviceTypeNum = computed(() => {
+  const { deviceInfo } = form.value
+  return uniqueByField(deviceInfo.filter(item => item.deviceTypeDetailId != ''), 'deviceTypeDetailId').length
+});
+const formatWareHouse = (val) => {
+  return wareHouseOptions.value.filter(item => item.id === val)[0]?.name
+}
+const deviceNum = computed(() => {
+  const { deviceInfo } = form.value
+  return deviceInfo.filter(item => item.num !== '').reduce((total, item) => total + Number(item.num), 0)
+});
+const uniqueByField = (arr, field) => {
+  const set = new Set();
+  arr.forEach(item => {
+    set.add(item[field]);
+  });
+  return Array.from(set);
+}
 /** 查询列表 */
 const getList = async () => {
   loading.value = true;
-  // const res = await listInspectionTask(queryParams.value);
-  // tableList.value = res.rows.map((item) => ({
-  //   ...item,
-  //   ext1: item.ext1 ? JSON.parse(item.ext1) : null,
-  // }));
-  // total.value = res.total;
-  tableList.value = [
-    {
-      name: '路由器备件补货一',
-      sn: 2024121901,
-      deviceCategory: '9',
-      deviceNum: '120',
-      storeName: '成品仓库一',
-      storePerson: '王乐',
-      storeDate:'2024-12-20',
-      remark: '--',
-    },
-    {
-      name: '路由器备件补货二',
-      sn: 2024121902,
-      deviceCategory: '6',
-      deviceNum: '100',
-      storeName: '半成品成品仓库一',
-      storePerson: '王乐',
-      storeDate:'2024-12-20',
-      remark: '--',
-    },
-    {
-      name: '路由器备件补货三',
-      sn: 2024121903,
-      deviceCategory: '10',
-      deviceNum: '150',
-      storeName: '成品仓库一',
-      storePerson: '王乐',
-      storeDate:'2024-12-20',
-      remark: '--',
-    },
-  ]
+  const res = await listDeviceInWarehouse(queryParams.value);
+  const tmpObj = {}
+  res.rows.forEach(item => {
+    if (tmpObj[item.sn]) {
+      tmpObj[item.sn].push(item)
+    } else {
+      tmpObj[item.sn] = [item]
+    }
+  })
+  const tmpArr =[]
+  Object.keys(tmpObj).forEach(key => {
+    if (tmpObj[key].length) {
+      tmpArr.push({
+        deviceCategory:tmpObj[key].length,
+        deviceNum: tmpObj[key].reduce((total, item) => total + Number(item.num), 0),
+        ...tmpObj[key][0],
+      })
+    }
+
+  })
+  tableList.value = tmpArr
+  total.value = tmpArr.length;
   loading.value = false;
 };
 
@@ -280,7 +302,6 @@ const reset = () => {
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
-  queryParams.value.pageNum = 1;
   getList();
 };
 
@@ -290,15 +311,11 @@ const resetQuery = () => {
   handleQuery();
 };
 
-/** 多选框选中数据 */
-const handleSelectionChange = (selection) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
 /** 新增按钮操作 */
 const handleAdd = () => {
   reset();
+  form.value.sn = generateSerialNumber()
+  form.value.createName = useUserStore().nickname
   dialog.visible = true;
   dialog.title = '新增到货入库';
 };
@@ -314,9 +331,76 @@ const handleUpdate = (row) => {
 const submitForm = () => {
   addFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
+      const { deviceInfo, ext1, ...rest } = form.value
+      if (deviceInfo.length === 0) return proxy?.$modal.msgError('请填写备品备件信息')
+      const validFlag = deviceInfo.some(item => !item.deviceTypeDetailId || !item.qualityEndTime  || !item.num || !item.shelfInfo)
+      if (validFlag) return proxy?.$modal.msgError('请填写完善备品备件信息')
+      buttonLoading.value = true;
+      deviceInfo.forEach(async (item, index) => {
+        const params = {
+          ...rest,
+          ext1: JSON.stringify(ext1),
+          deviceTypeDetailId: item.deviceTypeDetailId,
+          qualityEndTime: item.qualityEndTime,
+          num: item.num,
+          shelfInfo: item.shelfInfo,
+        }
+        await addDeviceInWarehouse(params);
+        if (index === deviceInfo.length - 1) {
+          proxy?.$modal.msgSuccess('操作成功');
+          buttonLoading.value = false;
+          dialog.visible = false;
+          getList();
+        }
+      })
+
     }
   });
 };
+/**
+ * @name  getTableData
+ * @desc  纯JS前端分页方法
+ * @param  {Number} page 当前页码,默认1
+ * @param  {Number} pageSize 每页最多显示条数,默认10
+ * @param  {Array} totalData 总的数据集,默认为空数组
+ * @return {Object} {
+    data, //当前页展示数据,数组
+    page, //当前页码
+    pageSize, //每页最多显示条数
+    length, //总的数据条数
+  }
+**/
+const getTableData = (page = 1, pageSize = 10, totalData = []) => {
+  const { length } = totalData;
+  const tableData = {
+    data: [],
+    page,
+    pageSize,
+    length,
+  };
+  if (pageSize >= length) { //pageSize大于等于总数据长度,说明只有1页数据或没有数据
+    tableData.data = totalData;
+    tableData.page = 1;//直接取第一页
+  } else { //pageSize小于总数据长度,数据多余1页
+    const num = pageSize * (page - 1);//计算当前页(不含)之前的所有数据总条数
+    if (num < length) { //如果当前页之前所有数据总条数小于(不能等于)总的数据集长度,则说明当前页码没有超出最大页码
+      const startIndex = num;//当前页第一条数据在总数据集中的索引
+      const endIndex = num + pageSize - 1;//当前页最后一条数据索引
+      tableData.data = totalData.filter((_, index) => index >= startIndex && index <= endIndex);//当前页数据条数小于每页最大条数时,也按最大条数范围筛取数据
+    } else { //当前页码超出最大页码,则计算实际最后一页的page,自动返回最后一页数据
+      const size = parseInt((length / pageSize).toString()); //取商
+      const rest = length % pageSize; //取余数
+      if (rest > 0) { //余数大于0,说明实际最后一页数据不足pageSize,应该取size+1为最后一条的页码
+        tableData.page = size + 1;//当前页码重置,取size+1
+        tableData.data = totalData.filter((_, index) => index >= (pageSize * size) && index <= length);
+      } else if (rest === 0) { //余数等于0,最后一页数据条数正好是pageSize
+        tableData.page = size;//当前页码重置,取size
+        tableData.data = totalData.filter((_, index) => index >= (pageSize * (size - 1)) && index <= length);
+      } //注:余数不可能小于0
+    }
+  }
+  return tableData;
+};
 /** 删除按钮操作 */
 const handleDelete = async (row) => {
   // const _ids = row?.id || ids.value;
@@ -327,28 +411,86 @@ const handleDelete = async (row) => {
 };
 const addDeviceInfo = () => {
   form.value.deviceInfo.push({
-    deviceName:'',
-    brand:'',
+    deviceTypeDetailId: '',
+    brand: '',
     xh: '',
     productor: '',
+    qualityEndTime: '',
     unit: '',
-    deviceNum: '',
-    shelf:''
+    num: '',
+    shelfInfo: ''
   })
 }
 const delDeviceInfo = (index) => {
-  form.value.deviceInfo.splice(index,1)
+  form.value.deviceInfo.splice(index, 1)
+}
+const getWarehouseList = () => {
+  listWarehouse({}).then(({ code, rows }) => {
+    if (code === 200) {
+      wareHouseOptions.value = rows
+    }
+  })
+}
+const getShelfList = (val) => {
+  if (val) {
+    const [{ shelfs }] = wareHouseOptions.value.filter(item => item.id === val)
+    shelfOptions.value = JSON.parse(shelfs).shelfsData
+  } else {
+    shelfOptions.value = []
+  }
 }
-const getUserList = () => {
-  listUser({ status: '0', pageSize: 10000, pageNum: 1 }).then(({ code, rows }) => {
+const generateSerialNumber = () => {
+  const date = new Date();
+  const year = date.getFullYear();
+  const month = (date.getMonth() + 1).toString().padStart(2, '0');
+  const day = date.getDate().toString().padStart(2, '0');
+  const hours = date.getHours().toString().padStart(2, '0');
+  const minutes = date.getMinutes().toString().padStart(2, '0');
+  const seconds = date.getSeconds().toString().padStart(2, '0');
+  const milliseconds = date.getMilliseconds().toString().padStart(3, '0');
+  return `${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`;
+}
+const getDeviceTypeList = async () => {
+  let deviceTypeList = []
+  await listDeviceType({}).then(({ code, rows }) => {
+    if (code === 200) {
+      deviceTypeList = rows || []
+    }
+  })
+  let deviceTypeDetailList = []
+  await getDeviceTypeDetailList({}).then(({ code, rows }) => {
     if (code === 200) {
-      userOptions.value = rows
+      deviceTypeDetailList = rows.map((item) => ({
+        ...item,
+        deviceType: {},
+        ext1: item.ext1 ? JSON.parse(item.ext1) : null
+      }));
     }
+  });
+  deviceTypeDetailList.forEach(item => {
+    deviceTypeList.forEach(el => {
+      if (item.deviceTypeId === el.id) {
+        item.deviceType = el
+      }
+    })
   })
+  deviceTypeDetailOptions.value = deviceTypeDetailList
+};
+const devTypeDetailChange = (val, index) => {
+  if (val) {
+    const [{ ext1: { brand, productorName }, xh,units }] = deviceTypeDetailOptions.value.filter(item => item.id === val)
+    form.value.deviceInfo[index].brand = brand
+    form.value.deviceInfo[index].xh = xh
+    form.value.deviceInfo[index].productor = productorName
+    form.value.deviceInfo[index].unit = units
+  }
+
 }
+
 onMounted(() => {
   getList();
-  getUserList();
+  getWarehouseList()
+  getDeviceTypeList()
 });
 </script>
 <style lang="scss" scoped>
@@ -362,4 +504,18 @@ onMounted(() => {
     cursor: pointer;
   }
 }
+
+.device-title {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+
+  >div:last-child {
+    color: #01A7F0;
+
+    span:last-child {
+      margin-left: 40px;
+    }
+  }
+}
 </style>

+ 282 - 174
src/views/sparesManage/realtimeStore/index.vue

@@ -20,37 +20,33 @@
     <el-card shadow="never">
       <template #header>
         <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd"> 新增 </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"> 修改
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"> 删除
-            </el-button>
-          </el-col>
           <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
         </el-row>
       </template>
 
-      <el-table v-loading="loading" :data="tableList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
+      <el-table v-loading="loading" :data="tableList">
         <el-table-column label="备品备件名称" align="center" show-overflow-tooltip prop="name" width="150" />
-        <el-table-column label="品牌" align="center" show-overflow-tooltip prop="brand" width="150" />
+        <el-table-column label="品牌" align="center" show-overflow-tooltip prop="ext1.brand" width="150" />
         <el-table-column label="型号" align="center" show-overflow-tooltip prop="xh" width="150" />
-        <el-table-column label="供应商" align="center" show-overflow-tooltip prop="productor" width="150" />
-        <el-table-column label="质保期(天)" align="center" show-overflow-tooltip prop="deadline" width="150" />
-        <el-table-column label="安全库存数量" align="center" show-overflow-tooltip prop="storeNum" width="150"/>
-        <el-table-column label="单位" align="center" show-overflow-tooltip prop="unit"  width="150"/>
-        <el-table-column label="用途" align="center" show-overflow-tooltip prop="condition" width="150" />
-        <el-table-column label="实时库存" align="center" show-overflow-tooltip prop="realStoreNum" width="150" />
-        <el-table-column label="是否有过期备件" align="center" show-overflow-tooltip prop="isExpire" width="150" />
+        <el-table-column label="供应商" align="center" show-overflow-tooltip prop="ext1.productorName" width="150" />
+        <el-table-column label="安全库存数量" align="center" show-overflow-tooltip prop="safe_num" width="150" />
+        <el-table-column label="单位" align="center" show-overflow-tooltip prop="units" width="150" />
+        <el-table-column label="用途" align="center" show-overflow-tooltip prop="remark" width="150" />
+        <el-table-column label="实时库存" align="center" show-overflow-tooltip prop="current_stock" width="150">
+          <template #default="{ row }">
+            <span :style="{ 'color': row.current_stock < row.safe_num ? 'red' : null }">{{ row.current_stock }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="是否有过期备件" align="center" show-overflow-tooltip prop="has_expired" width="150">
+          <template #default="{ row }">
+            <el-tag v-if="row.has_expired == '是'" type="danger">是</el-tag>
+            <el-tag v-else>否</el-tag>
+          </template>
+        </el-table-column>
         <el-table-column label="操作" align="center" width="100" fixed="right" class-name="small-padding fixed-width">
           <template #default="scope">
-            <el-button size="small" link type="primary" @click="handleDelete(scope.row)">详情</el-button>
-            <el-button size="small" link type="danger" @click="handleDelete(scope.row)">出库</el-button>
+            <el-button size="small" link type="primary" @click="handleDetail(scope.row)">详情</el-button>
+            <el-button size="small" link type="danger" @click="handleRemove(scope.row)">出库</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -58,71 +54,83 @@
         :total="total" @pagination="getList" />
     </el-card>
     <!-- 添加或修改对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="950px" append-to-body>
+    <el-dialog v-model="dialog.visible" :title="dialog.title" width="1100px" append-to-body>
       <el-form ref="addFormRef" :model="form" label-width="110px">
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="计划名称" prop="name" :rules="[{ required: true, message: '计划名称不能为空', trigger: 'blur' }]">
-              <el-input v-model="form.name" placeholder="请输入计划名称" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="计划开始时间" prop="startTime"
-              :rules="[{ required: true, message: '计划开始时间不能为空', trigger: 'change' }]">
-              <el-date-picker v-model="form.startTime" style="width: 100%;" value-format="YYYY-MM-DD hh:mm:ss"
-                type="datetime" placeholder="请选择开始时间" />
+        <SubTitle title="备品信息" />
+        <div class="drawer-title">
+          <el-descriptions title="" direction="vertical" :column="7">
+            <el-descriptions-item align="center" label="备品备件名称">{{ curRow.name }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="品牌">{{ curRow.ext1.brand }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="型号">{{ curRow.xh }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="供应商">{{ curRow.ext1.productorName }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="安全库存数量">{{ curRow.safe_num }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="单位">{{ curRow.units }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="实时库存">{{ curRow.current_stock }}</el-descriptions-item>
+          </el-descriptions>
+        </div>
+        <SubTitle title="出库信息" style="margin-top: 20px;" />
+        <el-row style="margin-top: 10px;">
+          <el-col :span="12">
+            <el-form-item label="出库单号" prop="sn">
+              <el-input v-model="form.sn" disabled />
             </el-form-item>
           </el-col>
-          <el-col :span="8">
-            <el-form-item label="计划结束时间" prop="endTime"
-              :rules="[{ required: true, message: '计划结束时间不能为空', trigger: 'change' }]">
-              <el-date-picker v-model="form.endTime" style="width: 100%;" value-format="YYYY-MM-DD hh:mm:ss"
-                type="datetime" placeholder="请选择结束时间" />
+          <el-col :span="12">
+            <el-form-item label="出库名称" prop="name" :rules="[{ required: true, message: '出库名称不能为空', trigger: 'blur' }]">
+              <el-input v-model="form.name" placeholder="请输入" />
             </el-form-item>
           </el-col>
-          <el-col :span="8">
-            <el-form-item label="巡检类型" prop="inspectionType"
-              :rules="[{ required: true, message: '巡检类型不能为空', trigger: 'change' }]">
-              <el-select v-model="form.inspectionType" clearable placeholder="请选择巡检类型" >
-                <el-option v-for="dict in inspection_type" :key="dict.value" :label="dict.label"
-                  :value="dict.value"></el-option>
-              </el-select>
+          <el-col :span="12">
+            <el-form-item label="出库人" prop="createName">
+              <el-input v-model="form.createName" disabled />
             </el-form-item>
           </el-col>
-          <el-col :span="8">
-            <el-form-item label="巡检周期(天)" prop="inspectionCycle"
-              :rules="[{ required: true, message: '巡检周期不能为空', trigger: 'blur' }]">
-              <el-input-number v-model="form.inspectionCycle" :disabled="cycleDisabled" style="width:100%" :min="1" />
+          <el-col :span="12">
+            <el-form-item label="出库时间" prop="ext1.removeDate"
+              :rules="[{ required: true, message: '出库时间不能为空', trigger: 'change' }]">
+              <el-date-picker v-model="form.ext1.removeDate" style="width: 100%;" value-format="YYYY-MM-DD" type="date"
+                placeholder="选择日期">
+              </el-date-picker>
             </el-form-item>
           </el-col>
-          <el-col :span="8">
-            <el-form-item label="巡检范围" prop="inspectionRange"
-              :rules="[{ required: true, message: '巡检类型不能为空', trigger: 'change' }]">
-              <el-select v-model="form.inspectionRange" clearable placeholder="请选择巡检范围">
-                <el-option label="按设备" :value="1"></el-option>
-                <el-option label="按道路点位" :value="2"></el-option>
-                <el-option label="按项目" :value="3"></el-option>
+          <el-col :span="12">
+            <el-form-item label="领用人" prop="recipientsId"
+              :rules="[{ required: true, message: '领用人不能为空', trigger: 'change' }]">
+              <el-select v-model="form.recipientsId" clearable placeholder="请选择领用人">
+                <el-option v-for="item in userOptions" :key="item.userId" :label="item.nickName"
+                  :value="item.userId"></el-option>
               </el-select>
             </el-form-item>
           </el-col>
-          <el-col :span="8">
-            <el-form-item label="巡检员" prop="inspectionPersonId"
-              :rules="[{ required: true, message: '巡检员不能为空', trigger: 'change' }]">
-              <el-cascader v-model="form.inspectionPersonId" :props="{ emitPath: false }" :options="userOptions"
-                placeholder="请选择巡检员" clearable :show-all-levels="false" @change="setUserInfo" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="联系电话" prop="ext1.phone">
-              <el-input v-model="form.ext1.phone" disabled placeholder="选巡检员带出" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="备注" prop="remark">
-              <el-input v-model="form.remark" placeholder="请输入备注" />
+          <el-col :span="12">
+            <el-form-item label="出库说明" prop="remark">
+              <el-input v-model="form.remark" placeholder="请输入" />
             </el-form-item>
           </el-col>
         </el-row>
+        <SubTitle title="备品备件出库" style="margin-top: 20px;" />
+        <el-table :data="curRow.inWarehouseList" max-height="300">
+          <el-table-column label="入库单号" align="center" prop="sn" show-overflow-tooltip width="150">
+          </el-table-column>
+          <el-table-column label="入库名称" align="center" prop="name">
+          </el-table-column>
+          <el-table-column label="入库数量" align="center" prop="num">
+          </el-table-column>
+          <el-table-column label="入库时间" align="center" show-overflow-tooltip prop="ext1.storeDate"></el-table-column>
+          <el-table-column label="实时库存" align="center" show-overflow-tooltip prop="current_stock"></el-table-column>
+          <el-table-column label="在库时长(天)" align="center" show-overflow-tooltip
+            prop="in_warehouse_days"></el-table-column>
+          <el-table-column label="剩余寿命(天)" align="center" show-overflow-tooltip
+            prop="remaining_life_days"></el-table-column>
+          <el-table-column label="寿命超期(天)" align="center" show-overflow-tooltip
+            prop="life_exceeded_days"></el-table-column>
+          <el-table-column label="出库数量" align="center">
+            <template #default="{ row }">
+              <el-input-number v-model="row.removeNum" style="width: 100%;" :min="0" :max="row.current_stock"
+                controls-position="right" />
+            </template>
+          </el-table-column>
+        </el-table>
       </el-form>
       <template #footer>
         <div class="dialog-footer">
@@ -131,27 +139,97 @@
         </div>
       </template>
     </el-dialog>
+    <el-drawer v-model="detailDrawer" class="customDrawer" size="70%">
+      <template #header>
+        <div class="drawer-title">
+          <div class="title-name">备品备件详情</div>
+          <el-descriptions title="" direction="vertical" :column="7">
+            <el-descriptions-item align="center" label="备品备件名称">{{ curRow.name }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="品牌">{{ curRow.ext1.brand }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="型号">{{ curRow.xh }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="供应商">{{ curRow.ext1.productorName }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="安全库存数量">{{ curRow.safe_num }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="单位">{{ curRow.units }}</el-descriptions-item>
+            <el-descriptions-item align="center" label="实时库存">{{ curRow.current_stock }}</el-descriptions-item>
+          </el-descriptions>
+        </div>
+      </template>
+      <div>
+        <el-tabs v-model="detailTab">
+          <el-tab-pane label="基础信息" name="1">
+            <el-descriptions class="detail-descriptions" :column="2" border>
+              <el-descriptions-item label-align="center" label="备品备件名称">{{ curRow.name }}</el-descriptions-item>
+              <el-descriptions-item label-align="center" label="备品备件编号">{{ curRow.id }}</el-descriptions-item>
+              <el-descriptions-item label-align="center" label="品牌">{{ curRow.ext1.brand }}</el-descriptions-item>
+              <el-descriptions-item label-align="center" label="型号">{{ curRow.xh }}</el-descriptions-item>
+              <el-descriptions-item label-align="center" label="供应商">{{ curRow.ext1.productorName
+                }}</el-descriptions-item>
+              <el-descriptions-item label-align="center" label="安全库存数量">{{ curRow.safe_num }}</el-descriptions-item>
+              <el-descriptions-item label-align="center" label="单位">{{ curRow.units }}</el-descriptions-item>
+              <el-descriptions-item label-align="center" label="用途">{{ curRow.remark }}</el-descriptions-item>
+            </el-descriptions>
+          </el-tab-pane>
+          <el-tab-pane label="入库信息" name="2">
+            <el-table :data="curRow.inWarehouseList">
+              <el-table-column label="入库单号" show-overflow-tooltip align="center" prop="sn">
+              </el-table-column>
+              <el-table-column label="入库名称" width="120" show-overflow-tooltip align="center" prop="name">
+              </el-table-column>
+              <el-table-column label="入库数量" align="center" prop="num">
+              </el-table-column>
+              <el-table-column label="入库时间" width="120" align="center" show-overflow-tooltip
+                prop="ext1.storeDate"></el-table-column>
+              <el-table-column label="仓库" align="center" show-overflow-tooltip prop="warehouseName"></el-table-column>
+              <el-table-column label="库位" align="center" show-overflow-tooltip prop="shelf_info"></el-table-column>
+              <el-table-column label="仓库管理员" align="center" width="120" show-overflow-tooltip
+                prop="managerName"></el-table-column>
+              <el-table-column label="实时库存" align="center" show-overflow-tooltip prop="current_stock"></el-table-column>
+              <el-table-column label="在库时长(天)" align="center" width="150" show-overflow-tooltip
+                prop="in_warehouse_days"></el-table-column>
+              <el-table-column label="剩余寿命(天)" align="center" width="150" show-overflow-tooltip
+                prop="remaining_life_days"></el-table-column>
+              <el-table-column label="寿命超期(天)" align="center" width="150" show-overflow-tooltip
+                prop="life_exceeded_days">
+                <template #default="{ row }">
+                  {{ row.life_exceeded_days || '--' }}
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-tab-pane>
+          <el-tab-pane label="出库信息" name="3">
+            <el-table :data="curRow.outWarehouseList" max-height="300">
+              <el-table-column label="出库单号" align="center" show-overflow-tooltip prop="sn">
+              </el-table-column>
+              <el-table-column label="出库名称" align="center" show-overflow-tooltip prop="name"></el-table-column>
+              <el-table-column label="出库说明" align="center" show-overflow-tooltip prop="remark"></el-table-column>
+              <el-table-column label="仓库" align="center" >
+                <template #default="{ row }">
+                  {{ formatWarehouse(row.warehouseId) }}
+                </template>
+              </el-table-column>
+              <el-table-column label="库位" align="center" prop="shelfInfo"></el-table-column>
+              <el-table-column label="出库数量" align="center" prop="num"></el-table-column>
+              <el-table-column label="出库人" align="center" prop="createName"></el-table-column>
+              <el-table-column label="领用人" align="center" prop="recipientsName"></el-table-column>
+              <el-table-column label="出库时间" align="center" show-overflow-tooltip prop="ext1.removeDate"></el-table-column>
+            </el-table>
+          </el-tab-pane>
+        </el-tabs>
+      </div>
+    </el-drawer>
   </div>
 </template>
 
-<script setup name="PatrolPlan" lang="ts">
-import { listInspectionTeam, listInspectionItem, listInspectionTask, getInspectionTask, delInspectionTask, addInspectionTask, updateInspectionTask } from '@/api/deviceCheck/index';
-import {
-  listDeviceType,
-  getDeviceTypeDetailList
-} from '@/api/deviceManage/deviceType';
-import {
-  listDevice,
-} from '@/api/deviceManage/device';
+<script setup name="RealtimeStore" lang="ts">
 import { deepClone } from '@/utils';
+import { getRealStorelist, getInWarehouseListByDevice, addDeviceOutWarehouse,listDeviceOutWarehouse,listWarehouse } from '@/api/sparesManage/index';
+import { listUser } from '@/api/system/user/index'
+import useUserStore from '@/store/modules/user';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const tableList = ref([]);
 const buttonLoading = ref(false);
 const loading = ref(true);
 const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
 const total = ref(0);
 const queryFormRef = ref<ElFormInstance>();
 const addFormRef = ref<ElFormInstance>();
@@ -161,24 +239,13 @@ const dialog = reactive<DialogOption>({
 });
 const initFormData = {
   id: undefined,
+  sn: undefined,
   name: undefined,
-  startTime: undefined,
-  endTime: undefined,
-  inspectionType: undefined,
-  inspectionCycle: 1,
-  status: 0,
-  inspectionRange: undefined,
-  inspectionPersonId: undefined,
-  inspectionItem: [{
-    deviceTypeId: undefined,
-    deviceTypeDetailIds: [],
-    items: [],
-    deviceOptions: [],
-  }],
+  createName: undefined,
+  recipientsId: undefined,
   remark: undefined,
   ext1: <any>{
-    phone: undefined,
-    inspectionPersonName: undefined,
+    removeDate: undefined
   },
   ext2: undefined
 };
@@ -192,55 +259,23 @@ const formData = reactive({
     params: {}
   }
 });
-const cycleDisabled = ref(false)
-const { queryParams, form } = toRefs(formData);
-const { inspection_type } = toRefs<any>(proxy?.useDict('inspection_type'));
-const { inspection_status } = toRefs<any>(proxy?.useDict('inspection_status'));
-const dictGroup = reactive({
-  deviceTypeOptions: [],
-  inspectionItemOptions: []
-})
+const detailDrawer = ref(false);
+const detailTab = ref('1');
+const curRow = ref({
+  ext1: {}
+} as any);
 const userOptions = ref([])
+const warehouseOptions = ref([])
+const { queryParams, form } = toRefs(formData);
 /** 查询列表 */
 const getList = async () => {
   loading.value = true;
-  // const res = await listInspectionTask(queryParams.value);
-  // tableList.value = res.rows.map((item) => ({
-  //   ...item,
-  //   ext1: item.ext1 ? JSON.parse(item.ext1) : null,
-  // }));
-  // total.value = res.total;
-  tableList.value = [
-    {
-      name: '备件一',
-      brand: '华为',
-      xh:'HW00001',
-      id: 2024121901,
-      productor:'供应商一',
-      deadline: '300',
-      storeNum: '200',
-      unti: '件',
-      condition: '--',
-      realStoreNum:'100',
-      remark: '--',
-      isExpire:'是'
-    },
-    {
-      name: '备件二',
-      brand: '华为',
-      xh:'HW00001',
-      id: 2024121901,
-      productor:'供应商一',
-      deadline: '300',
-      storeNum: '200',
-      unti: '件',
-      condition: '--',
-      realStoreNum:'100',
-      remark: '--',
-      isExpire:'是'
-    },
-
-  ]
+  const res = await getRealStorelist(queryParams.value);
+  tableList.value = res.rows.map(item => ({
+    ...item,
+    ext1: JSON.parse(item.ext1),
+  }))
+  total.value = res.total;
   loading.value = false;
 };
 
@@ -268,48 +303,104 @@ const resetQuery = () => {
   handleQuery();
 };
 
-/** 多选框选中数据 */
-const handleSelectionChange = (selection) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-/** 新增按钮操作 */
-const handleAdd = () => {
+const handleRemove = async (row) => {
   reset();
-  // dialog.visible = true;
-  dialog.title = '新增故障类型';
-};
-/** 修改按钮操作 */
-const handleUpdate = (row) => {
-  reset();
-  const _id = row?.id || ids.value[0];
-  getInspectionTask(_id).then(({ data }) => {
-    data.ext1 = data.ext1 && JSON.parse(data.ext1);
-    data.inspectionItem = data.inspectionItem && JSON.parse(data.inspectionItem);
-    Object.assign(form.value, data);
-  });
-  // dialog.visible = true;
-  dialog.title = '修改故障类型';
+  dialog.visible = true;
+  dialog.title = '出库';
+  Object.assign(curRow.value, row);
+  form.value.sn = generateSerialNumber()
+  form.value.createName = useUserStore().nickname
+  const { data } = await getInWarehouseListByDevice(row.id)
+  curRow.value.inWarehouseList = data.map(item => ({
+    ...item,
+    ext1: item.ext1 && JSON.parse(item.ext1),
+    removeNum: 0
+  }))
+
 };
 
 /** 提交按钮 */
 const submitForm = () => {
   addFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
+      const { inWarehouseList } = curRow.value
+      const { ext1, ...rest } = form.value
+      if (inWarehouseList.every(item => item.removeNum === 0)) proxy?.$modal.msgError('请填写出库数量')
+      buttonLoading.value = true
+      const tmpArr = inWarehouseList.filter(item => item.removeNum > 0)
+      tmpArr.forEach(async (item, index) => {
+        await addDeviceOutWarehouse({
+          ...rest,
+          ext1: JSON.stringify(ext1),
+          deviceTypeDetailId: item.device_type_detail_id,
+          warehouseId: item.warehouse_id,
+          shelfInfo: item.shelf_info,
+          inWarehouseSn: item.sn,
+          num:item.removeNum,
+        })
+        if (index === tmpArr.length - 1) {
+          buttonLoading.value = false
+          dialog.visible = false;
+          proxy?.$modal.msgSuccess('出库成功')
+          getList()
+        }
+      })
     }
   });
 };
-/** 删除按钮操作 */
-const handleDelete = async (row) => {
-  // const _ids = row?.id || ids.value;
-  // await proxy?.$modal.confirm('是否确认删除?').finally(() => (loading.value = false));
-  // await delInspectionTask(_ids);
-  // proxy?.$modal.msgSuccess('删除成功');
-  // await getList();
+const handleDetail = async (row) => {
+  detailDrawer.value = true;
+  detailTab.value = '1';
+  Object.assign(curRow.value, row);
+  const { data } = await getInWarehouseListByDevice(row.id)
+  curRow.value.inWarehouseList = data.map(item => ({
+    ...item,
+    ext1: item.ext1 && JSON.parse(item.ext1),
+  }))
+  const { rows } = await listDeviceOutWarehouse({ deviceTypeDetailId: row.id })
+  curRow.value.outWarehouseList = rows.map(item => ({
+    ...item,
+    ext1: item.ext1 && JSON.parse(item.ext1),
+  }))
 };
+const generateSerialNumber = () => {
+  const date = new Date();
+  const year = date.getFullYear();
+  const month = (date.getMonth() + 1).toString().padStart(2, '0');
+  const day = date.getDate().toString().padStart(2, '0');
+  const hours = date.getHours().toString().padStart(2, '0');
+  const minutes = date.getMinutes().toString().padStart(2, '0');
+  const seconds = date.getSeconds().toString().padStart(2, '0');
+  const milliseconds = date.getMilliseconds().toString().padStart(3, '0');
+  return `${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`;
+}
+const getUserList = () => {
+  listUser({ status: '0', pageSize: 10000, pageNum: 1 }).then(({ code, rows }) => {
+    if (code === 200) {
+      userOptions.value = rows
+    }
+  })
+}
+const getWarehouseList = () => {
+  listWarehouse({}).then(({ code, rows }) => {
+    if (code === 200) {
+      warehouseOptions.value = rows
+    }
+  })
+}
+const formatWarehouse = (val) => {
+  let label =''
+  warehouseOptions.value.forEach(item => {
+    if (item.id === val) {
+      label= item.name
+    }
+  })
+  return label
+}
 onMounted(() => {
   getList();
+  getUserList()
+  getWarehouseList()
 });
 </script>
 <style lang="scss" scoped>
@@ -323,4 +414,21 @@ onMounted(() => {
     cursor: pointer;
   }
 }
+
+.drawer-title {
+  :deep(.el-descriptions__body) {
+    margin-top: 10px;
+    background-color: #F4F5F7;
+    border-radius: 2px;
+    padding: 10px 10px 0 10px;
+  }
+
+  :deep(.el-descriptions__label) {
+    padding-bottom: 5px;
+  }
+
+  .title-name {
+    color: #000;
+  }
+}
 </style>

+ 38 - 89
src/views/sparesManage/storeManage/index.vue

@@ -41,21 +41,11 @@
         <el-card shadow="never">
           <template #header>
             <el-row :gutter="10" class="mb8">
-              <!-- <el-col :span="1.5">
-                <el-button type="primary" plain icon="Plus" @click="handleAdd"> 新增 </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"> 修改 </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"> 删除 </el-button>
-              </el-col> -->
               <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
             </el-row>
           </template>
 
-          <el-table v-loading="loading" :data="deviceTypeList" @selection-change="handleSelectionChange">
-            <el-table-column type="selection" width="55" align="center" />
+          <el-table v-loading="loading" :data="deviceTypeList">
             <el-table-column label="设备类型名称" width="120" align="center">
               <template #default="scope">
                 {{ formatDict(scope.row.deviceTypeId, 'deviceTypeOptions') }}
@@ -68,13 +58,12 @@
                 {{ formatDict(scope.row.productorId, 'productorOptions') }}
               </template>
             </el-table-column>
-            <el-table-column label="安全库存数量" align="center" prop="ext1.storeNum"  width="150"/>
-            <el-table-column label="设置人" align="center" prop="ext1.operator" width="120" />
+            <el-table-column label="安全库存数量" align="center" prop="safeNum" width="150" />
+            <el-table-column label="设置人" align="center" prop="ext1.setSafePersonName" width="120" />
             <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
             <el-table-column label="操作" align="center" width="120" fixed="right" class-name="small-padding fixed-width">
               <template #default="scope">
-                <el-button v-hasPermi="['jdyw:deviceType:edit']" size="small" link type="primary"
-                  @click="handleUpdate(scope.row)">设置</el-button>
+                <el-button size="small" link type="primary" @click="handleStore(scope.row)">设置</el-button>
               </template>
             </el-table-column>
           </el-table>
@@ -86,35 +75,22 @@
 
     <!-- 添加或修改设备类型信息对话框 -->
     <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="deviceTypeFormRef" :model="form" label-width="110px">
-        <el-form-item label="设备类型名称" prop="deviceTypeId"
-          :rules="[{ required: true, message: '设备类型名称不能为空', trigger: 'change' }]">
-          <el-select v-model="form.deviceTypeId" placeholder="请选择设备类型名称">
+      <el-form ref="addFormRef" :model="form" label-width="110px">
+        <el-form-item label="设备类型名称" prop="deviceTypeId">
+          <el-select v-model="form.deviceTypeId" placeholder="请选择设备类型名称" disabled>
             <el-option v-for="dict in dictGroup.deviceTypeOptions" :key="dict.id" :label="dict.name"
               :value="dict.id"></el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="品牌" prop="ext1.brand" :rules="[{ required: true, message: '品牌不能为空', trigger: 'blur' }]">
-          <el-input v-model="form.ext1.brand" placeholder="请输入品牌" />
+        <el-form-item label="品牌" prop="ext1.brand">
+          <el-input v-model="form.ext1.brand" placeholder="请输入品牌" disabled />
         </el-form-item>
-        <el-form-item label="型号" prop="xh" :rules="[{ required: true, message: '型号不能为空', trigger: 'blur' }]">
-          <el-input v-model="form.xh" placeholder="请输入型号" />
+        <el-form-item label="型号" prop="xh">
+          <el-input v-model="form.xh" placeholder="请输入型号" disabled />
         </el-form-item>
-        <el-form-item label="供应商" prop="productorId"
-          :rules="[{ required: true, message: '供应商不能为空', trigger: 'change' }]">
-          <el-select v-model="form.productorId" clearable placeholder="请选择供应商" @change="setProductorInfo">
-            <el-option v-for="dict in dictGroup.productorOptions" :key="dict.id" :label="dict.name"
-              :value="dict.id"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="供应商联系人" prop="ext1.linkName">
-          <el-input v-model="form.ext1.linkName" disabled />
-        </el-form-item>
-        <el-form-item label="联系电话" prop="ext1.linkPhone">
-          <el-input v-model="form.ext1.linkPhone" disabled />
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
+        <el-form-item label="安全库存数量" prop="safeNum"
+          :rules="[{ required: true, message: '安全库存数量不能为空', trigger: 'blur' }]">
+          <el-input-number v-model="form.safeNum" style="width: 100%;" :min="1" controls-position="right" />
         </el-form-item>
       </el-form>
       <template #footer>
@@ -127,18 +103,16 @@
   </div>
 </template>
 
-<script setup name="VersionManage" lang="ts">
+<script setup name="StoreManage" lang="ts">
 import {
   listDeviceType,
-  getDeviceTypeDetail,
-  delDeviceTypeDetail,
-  addDeviceTypeDetail,
   updateDeviceTypeDetail,
   getDeviceSystemTree,
   getDeviceTypeDetailList
 } from '@/api/deviceManage/deviceType';
 import { listProductor } from '@/api/supplierManage/index';
 import { deepClone } from '@/utils/index';
+import { useUserStore } from '@/store/modules/user'
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const deviceTypeList = ref([]);
 const buttonLoading = ref(false);
@@ -149,7 +123,7 @@ const single = ref(true);
 const multiple = ref(true);
 const total = ref(0);
 const queryFormRef = ref<ElFormInstance>();
-const deviceTypeFormRef = ref<ElFormInstance>();
+const addFormRef = ref<ElFormInstance>();
 const filterText = ref('');
 const treeRef = ref<ElTreeInstance>();
 const filterNode = (value: string, data) => {
@@ -178,10 +152,13 @@ const initFormData = {
   deviceTypeId: undefined,
   xh: null,
   remark: undefined,
+  safeNum: undefined,
   ext1: <any>{
     brand: undefined,
     linkName: '',
-    linkPhone: ''
+    linkPhone: '',
+    setSafePerson: '',
+    setSafePersonName: '',
   },
   ext2: undefined
 };
@@ -219,7 +196,7 @@ const cancel = () => {
 /** 表单重置 */
 const reset = () => {
   form.value = deepClone(initFormData);
-  deviceTypeFormRef.value?.resetFields();
+  addFormRef.value?.resetFields();
 };
 
 /** 搜索按钮操作 */
@@ -234,58 +211,36 @@ const resetQuery = () => {
   handleQuery();
 };
 
-/** 多选框选中数据 */
-const handleSelectionChange = (selection) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
 
-/** 新增按钮操作 */
-const handleAdd = () => {
+const handleStore = (row) => {
   reset();
+  Object.assign(form.value, row);
   dialog.visible = true;
-  dialog.title = '新增品牌型号';
+  dialog.title = '设置安全库存数量';
 };
 
-/** 修改按钮操作 */
-const handleUpdate = async (row) => {
-  // reset();
-  // const _id = row?.id || ids.value[0];
-  // const res = await getDeviceTypeDetail(_id);
-  // res.data.ext1 = res.data.ext1 && JSON.parse(res.data.ext1);
-  // Object.assign(form.value, res.data);
-  // dialog.visible = true;
-  // dialog.title = '修改品牌型号';
-};
 
 /** 提交按钮 */
 const submitForm = () => {
-  deviceTypeFormRef.value?.validate(async (valid: boolean) => {
+  addFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
-      buttonLoading.value = true;
-      const { ext1 } = form.value;
-      const params = Object.assign(form.value, { ext1: JSON.stringify(ext1) });
-      if (form.value.id) {
-        await updateDeviceTypeDetail(params).finally(() => (buttonLoading.value = false));
-      } else {
-        await addDeviceTypeDetail(params).finally(() => (buttonLoading.value = false));
-      }
-      proxy?.$modal.msgSuccess('操作成功');
+      const { id, ext1, safeNum } = form.value;
+      ext1.setSafePerson = useUserStore().userId
+      ext1.setSafePersonName = useUserStore().nickname
+      buttonLoading.value = true
+      await updateDeviceTypeDetail({
+        id,
+        ext1: JSON.stringify(ext1),
+        safeNum
+      })
+      buttonLoading.value = false
       dialog.visible = false;
-      await getList();
+      proxy?.$modal.msgSuccess('设置成功');
+      getList();
     }
   });
 };
 
-/** 删除按钮操作 */
-const handleDelete = async (row) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除?').finally(() => (loading.value = false));
-  await delDeviceTypeDetail(_ids);
-  proxy?.$modal.msgSuccess('删除成功');
-  await getList();
-};
 
 const getTreeData = async () => {
   getDeviceSystemTree({}).then(({ code, rows }) => {
@@ -345,12 +300,6 @@ const getProductorList = () => {
     }
   });
 };
-const setProductorInfo = (val) => {
-  const [{ contact, phone,name }] = dictGroup.productorOptions.filter((item) => item.id === val);
-  form.value.ext1.linkName = contact;
-  form.value.ext1.productorName = name;
-  form.value.ext1.linkPhone = phone;
-};
 const handleNodeClick = (data, node) => {
   queryParams.value.systemId = data.id;
   handleQuery();

+ 139 - 179
src/views/sparesManage/warehouseManage/index.vue

@@ -8,6 +8,9 @@
             <el-form-item label="库房名称" prop="name">
               <el-input v-model="queryParams.name" placeholder="请输入库房名称" clearable @keyup.enter="handleQuery" />
             </el-form-item>
+            <el-form-item label="库房编号" prop="sn">
+              <el-input v-model="queryParams.sn" placeholder="请输入库房编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery"> 搜索 </el-button>
               <el-button icon="Refresh" @click="resetQuery"> 重置 </el-button>
@@ -23,28 +26,19 @@
           <el-col :span="1.5">
             <el-button type="primary" plain icon="Plus" @click="handleAdd"> 新增 </el-button>
           </el-col>
-          <!-- <el-col :span="1.5">
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"> 修改
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"> 删除
-            </el-button>
-          </el-col> -->
           <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
         </el-row>
       </template>
 
-      <el-table v-loading="loading" :data="tableList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
+      <el-table v-loading="loading" :data="tableList" >
         <el-table-column label="库房名称" align="center" show-overflow-tooltip prop="name" width="150" />
-        <el-table-column label="库房编号" align="center" show-overflow-tooltip prop="id" width="150" />
-        <el-table-column label="管理人员" align="center" show-overflow-tooltip prop="managePerson" width="150" />
-        <el-table-column label="联系电话" align="center" show-overflow-tooltip prop="linkPhone" width="150" />
-        <el-table-column label="库房地址" align="center" show-overflow-tooltip prop="storeAddress" width="150" />
-        <el-table-column label="库位总数" align="center" show-overflow-tooltip prop="storeNum" />
+        <el-table-column label="库房编号" align="center" show-overflow-tooltip prop="sn" width="150" />
+        <el-table-column label="管理人员" align="center" prop="managerName" width="150" />
+        <el-table-column label="负责人" align="center" prop="headerName" width="150" />
+        <el-table-column label="库房地址" align="center" show-overflow-tooltip prop="address" width="150" />
+        <el-table-column label="库位总数" align="center" show-overflow-tooltip prop="shelfs.total" />
         <el-table-column label="备注" align="center" show-overflow-tooltip prop="remark" width="150" />
-        <el-table-column label="创建人" align="center" show-overflow-tooltip prop="creator" width="150" />
+        <el-table-column label="创建人" align="center" show-overflow-tooltip prop="createName" width="150" />
         <el-table-column label="创建时间" align="center" show-overflow-tooltip prop="createTime" width="150" />
         <el-table-column label="操作" align="center" width="100" fixed="right" class-name="small-padding fixed-width">
           <template #default="scope">
@@ -56,7 +50,7 @@
         :total="total" @pagination="getList" />
     </el-card>
     <!-- 添加或修改对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="950px" append-to-body>
+    <el-dialog v-model="dialog.visible" :title="dialog.title" width="900px" append-to-body>
       <el-form ref="addFormRef" :model="form" label-width="110px">
         <SubTitle title="基本信息" />
         <el-row :gutter="20">
@@ -73,7 +67,7 @@
           <el-col :span="12">
             <el-form-item label="管理人员" prop="managerId"
               :rules="[{ required: true, message: '管理人员不能为空', trigger: 'change' }]">
-              <el-select v-model="form.managerId" clearable placeholder="请选择管理人员" @change="setUserInfo('manager')">
+              <el-select v-model="form.managerId" clearable placeholder="请选择管理人员">
                 <el-option v-for="item in userOptions" :key="item.userId" :label="item.nickName"
                   :value="item.userId"></el-option>
               </el-select>
@@ -82,7 +76,7 @@
           <el-col :span="12">
             <el-form-item label="仓库负责人" prop="headerId"
               :rules="[{ required: true, message: '仓库负责人不能为空', trigger: 'change' }]">
-              <el-select v-model="form.headerId" clearable placeholder="请选择仓库负责人" @change="setUserInfo('header')">
+              <el-select v-model="form.headerId" clearable placeholder="请选择仓库负责人">
                 <el-option v-for="item in userOptions" :key="item.userId" :label="item.nickName"
                   :value="item.userId"></el-option>
               </el-select>
@@ -100,25 +94,37 @@
           </el-col>
         </el-row>
         <SubTitle title="库位管理" />
-        <el-table :data="form.shelfs" max-height="300">
+        <el-table :data="form.tmpShelfs" max-height="300">
           <el-table-column label="库位前缀" align="center">
             <template #default="scope">
-              <el-input v-model="scope.row.suffix" placeholder="请输入" />
+              <el-input v-model="scope.row.suffix" placeholder="类似A、B、C..." />
             </template>
           </el-table-column>
           <el-table-column label="货架号" align="center">
             <template #default="scope">
-              <el-input v-model="scope.row.shelfNum" placeholder="请输入" />
+              <div class="input-group">
+                <el-input-number v-model="scope.row.shelfMinNum" :min="1" :max="1" controls-position="right" />
+                <span>-</span>
+                <el-input-number v-model="scope.row.shelfMaxNum" :min="1" controls-position="right" />
+              </div>
             </template>
           </el-table-column>
           <el-table-column label="层数" align="center">
             <template #default="scope">
-              <el-input v-model="scope.row.layerNum" placeholder="请输入" />
+              <div class="input-group">
+                <el-input-number v-model="scope.row.layerMinNum" :min="1" :max="1" controls-position="right" />
+                <span>-</span>
+                <el-input-number v-model="scope.row.layerMaxNum" :min="1" controls-position="right" />
+              </div>
             </template>
           </el-table-column>
           <el-table-column label="货位数" align="center">
             <template #default="scope">
-              <el-input v-model="scope.row.placeNum" placeholder="请输入" />
+              <div class="input-group">
+                <el-input-number v-model="scope.row.placeMinNum" :min="1" :max="1" controls-position="right" />
+                <span>-</span>
+                <el-input-number v-model="scope.row.placeMaxNum" :min="1" controls-position="right" />
+              </div>
             </template>
           </el-table-column>
           <el-table-column label="操作" align="center" width="80">
@@ -145,34 +151,35 @@
         </div>
       </template>
     </el-dialog>
-    <el-drawer v-model="detailDrawer" title="库房详情" class="customDrawer" size="80%">
+    <el-drawer v-model="detailDrawer" title="库房详情" class="customDrawer" size="60%">
       <div>
         <el-tabs v-model="detailTab">
           <el-tab-pane label="基础信息" name="1">
             <div>
               <el-descriptions class="detail-descriptions" :column="2" border>
-                <el-descriptions-item label-align="right" label="库房名称">{{ curRow.name }}</el-descriptions-item>
-                <el-descriptions-item label-align="right" label="库房编号">{{ curRow.id }}</el-descriptions-item>
-                <el-descriptions-item label-align="right" label="管理人员">{{ curRow.managePerson }}</el-descriptions-item>
-                <el-descriptions-item label-align="right" label="联系电话">{{ curRow.linkPhone }}</el-descriptions-item>
-                <el-descriptions-item label-align="right" label="库房地址">{{ curRow.storeAddress }}</el-descriptions-item>
-                <el-descriptions-item label-align="right" label="库位总数">{{ curRow.storeNum }}</el-descriptions-item>
-                <el-descriptions-item label-align="right" label="创建人">{{ curRow.creator }}</el-descriptions-item>
-                <el-descriptions-item label-align="right" label="备注">{{ curRow.remark }}</el-descriptions-item>
+                <el-descriptions-item label-align="center" label="库房名称">{{ curRow.name }}</el-descriptions-item>
+                <el-descriptions-item label-align="center" label="库房编号">{{ curRow.sn }}</el-descriptions-item>
+                <el-descriptions-item label-align="center" label="管理人员">{{ curRow.managerName }}</el-descriptions-item>
+                <el-descriptions-item label-align="center" label="负责人">{{ curRow.headerName }}</el-descriptions-item>
+                <el-descriptions-item label-align="center" label="库房地址">{{ curRow.address }}</el-descriptions-item>
+                <el-descriptions-item label-align="center" label="库位总数">{{ curRow.shelfs.total }}</el-descriptions-item>
+                <el-descriptions-item label-align="center" label="备注">{{ curRow.remark }}</el-descriptions-item>
+                <el-descriptions-item label-align="center" label="创建人">{{ curRow.createName }}</el-descriptions-item>
+                <el-descriptions-item label-align="center" label="创建时间">{{ curRow.createTime }}</el-descriptions-item>
               </el-descriptions>
             </div>
           </el-tab-pane>
           <el-tab-pane label="库位管理" name="2">
-            <el-table :data="curRow.shelfs" >
-              <el-table-column label="库位名称" align="center" prop="name">
+            <el-table :data="curRow.shelfs.shelfsData" >
+              <el-table-column label="库位名称" align="center" prop="shelfName">
               </el-table-column>
               <el-table-column label="前缀" align="center" prop="suffix">
               </el-table-column>
               <el-table-column label="货架号" align="center" prop="shelfNum">
               </el-table-column>
-              <el-table-column label="层号" align="center"  prop="layerNum">
+              <el-table-column label="层号" align="center" prop="layerNum">
               </el-table-column>
-              <el-table-column label="货位号" align="center"  prop="placeNum">
+              <el-table-column label="货位号" align="center" prop="placeNum">
               </el-table-column>
             </el-table>
           </el-tab-pane>
@@ -183,7 +190,7 @@
 </template>
 
 <script setup name="WarehouseManage" lang="ts">
-import { listWarehouse, getWarehouse, delWarehouse, addWarehouse, updateWarehouse } from '@/api/sparesManage/index';
+import { listWarehouse,  addWarehouse} from '@/api/sparesManage/index';
 import { deepClone } from '@/utils';
 import { listUser } from '@/api/system/user/index'
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -191,9 +198,6 @@ const tableList = ref([]);
 const buttonLoading = ref(false);
 const loading = ref(true);
 const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
 const total = ref(0);
 const queryFormRef = ref<ElFormInstance>();
 const addFormRef = ref<ElFormInstance>();
@@ -208,17 +212,18 @@ const initFormData = {
   managerId: undefined,
   address: undefined,
   headerId: undefined,
-  shelfs: [{
+  tmpShelfs: [{
     suffix: '',
-    shelfNum: '',
-    layerNum: '',
-    placeNum: ''
+    shelfMinNum: 1,
+    shelfMaxNum: 1,
+    layerMinNum: 1,
+    layerMaxNum: 1,
+    placeMinNum: 1,
+    placeMaxNum: 1
   }],
+  shelfs: undefined,
   remark: undefined,
-  ext1: <any>{
-    headerName: undefined,
-    managerName: undefined,
-  },
+  ext1: undefined,
   ext2: undefined
 };
 const formData = reactive({
@@ -227,7 +232,7 @@ const formData = reactive({
     pageNum: 1,
     pageSize: 10,
     name: undefined,
-    status: undefined,
+    sn: undefined,
     params: {}
   }
 });
@@ -239,50 +244,12 @@ const userOptions = ref([])
 /** 查询列表 */
 const getList = async () => {
   loading.value = true;
-  // const res = await listWarehouse(queryParams.value);
-  // tableList.value = res.rows.map((item) => ({
-  //   ...item,
-  //   ext1: item.ext1 ? JSON.parse(item.ext1) : null,
-  // }));
-  // total.value = res.total;
-  tableList.value = [
-    {
-      name: '成品库房一',
-      id: 120001,
-      storeType: '成品库房',
-      managePerson: '王乐',
-      linkPhone: '13218816060',
-      storeAddress: '112号',
-      storeNum: '300',
-      remark: '--',
-      creator: '王乐',
-      createTime: '2024-12-19 12:13:02',
-    },
-    {
-      name: '半成品库房一',
-      id: 120002,
-      storeType: '半成品库房',
-      managePerson: '王乐',
-      linkPhone: '13218816060',
-      storeAddress: '102号',
-      storeNum: '250',
-      remark: '--',
-      creator: '王乐',
-      createTime: '2024-12-19 12:13:02',
-    },
-    {
-      name: '余料库房一',
-      id: 120003,
-      storeType: '余料库房',
-      managePerson: '王乐',
-      linkPhone: '13218816060',
-      storeAddress: '112号',
-      storeNum: '500',
-      remark: '--',
-      creator: '王乐',
-      createTime: '2024-12-19 12:13:02',
-    },
-  ]
+  const res = await listWarehouse(queryParams.value);
+  tableList.value = res.rows.map((item) => ({
+    ...item,
+    shelfs: item.shelfs ? JSON.parse(item.shelfs) : null,
+  }));
+  total.value = res.total;
   loading.value = false;
 };
 
@@ -310,95 +277,84 @@ const resetQuery = () => {
   handleQuery();
 };
 
-/** 多选框选中数据 */
-const handleSelectionChange = (selection) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
 /** 新增按钮操作 */
 const handleAdd = () => {
   reset();
   dialog.visible = true;
   dialog.title = '新增库房库位';
 };
-/** 修改按钮操作 */
-const handleUpdate = (row) => {
-  reset();
-  const _id = row?.id || ids.value[0];
-  getWarehouse(_id).then(({ data }) => {
-    data.ext1 = data.ext1 && JSON.parse(data.ext1);
-    Object.assign(form.value, data);
-  });
-  dialog.visible = true;
-  dialog.title = '修改故障类型';
-};
 
 /** 提交按钮 */
 const submitForm = () => {
   addFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
-      // buttonLoading.value = true;
-      // if (form.value.id) {
-      //   await updateWarehouse(form.value).finally(() => (buttonLoading.value = false));
-      // } else {
-      //   await addWarehouse(form.value).finally(() => (buttonLoading.value = false));
-      // }
-      // proxy?.$modal.msgSuccess('操作成功');
-      // dialog.visible = false;
-      // await getList();
+      const { tmpShelfs } = form.value
+      if (tmpShelfs.length === 0) proxy?.$modal.msgError('请添加库位');
+      let validFlag = false
+      let validMessage = ''
+      const suffixObj = {}
+      let shelfsJson = {
+        total: 0,
+        shelfsData: []
+      }
+      for (let i = 0; i < tmpShelfs.length; i++) {
+        const shelf = tmpShelfs[i]
+        if (shelf.suffix.trim() === '') {
+          validFlag = true;
+          validMessage = `请填写第${i + 1}行库位前缀`
+          break
+        }
+        if (!suffixObj[shelf.suffix]) {
+          suffixObj[shelf.suffix] = shelf.suffix
+        } else {
+          validFlag = true;
+          validMessage = `库位前缀存在重复,请检查`
+          break
+        }
+        if (shelf.shelfMinNum > shelf.shelfMaxNum) {
+          validFlag = true;
+          validMessage = `第${i + 1}行库位货架号最大值应大于最小值`
+          break
+        }
+        if (shelf.layerMinNum > shelf.layerMaxNum) {
+          validFlag = true;
+          validMessage = `第${i + 1}行库位层数最大值应大于最小值`
+          break
+        }
+        if (shelf.placeMinNum > shelf.placeMaxNum) {
+          validFlag = true;
+          validMessage = `第${i + 1}行库位货位数最大值应大于最小值`
+          break
+        }
+        for (let j = 1; j <= shelf.shelfMaxNum; j++) {
+          for (let k = 1; k <= shelf.layerMaxNum; k++) {
+            for (let n = 1; n <= shelf.placeMaxNum; n++) {
+              shelfsJson.shelfsData.push({
+                shelfName: `${shelf.suffix}-${j}-${k}-${n}`,
+                suffix: shelf.suffix,
+                shelfNum: j,
+                layerNum: k,
+                placeNum: n,
+              })
+            }
+          }
+        }
+      }
+      if (validFlag) proxy?.$modal.msgError(validMessage)
+      buttonLoading.value = true;
+      shelfsJson.total = shelfsJson.shelfsData.length
+      form.value.shelfs = JSON.stringify(shelfsJson)
+      await addWarehouse(form.value).finally(() => (buttonLoading.value = false));
+      proxy?.$modal.msgSuccess('操作成功');
+      dialog.visible = false;
+      await getList();
     }
   });
 };
-/** 删除按钮操作 */
-const handleDelete = async (row) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除?').finally(() => (loading.value = false));
-  await delWarehouse(_ids);
-  proxy?.$modal.msgSuccess('删除成功');
-  await getList();
-};
 const showDetail = (row) => {
+  Object.assign(curRow.value, row)
   detailDrawer.value = true
-  curRow.value = row
   detailTab.value = '1'
-  curRow.value.shelfs = [
-    {
-      name:'A-1-1-1',
-      suffix: '1',
-      shelfNum: '1',
-      layerNum: '1',
-      placeNum: '1'
-    },
-    {
-      name:'A-1-1-2',
-      suffix: '1',
-      shelfNum: '1',
-      layerNum: '1',
-      placeNum: '2'
-    },
-    {
-      name:'A-1-1-3',
-      suffix: '1',
-      shelfNum: '1',
-      layerNum: '1',
-      placeNum: '3'
-    },
-    {
-      name:'A-1-1-4',
-      suffix: '1',
-      shelfNum: '1',
-      layerNum: '1',
-      placeNum: '4'
-    },
-    {
-      name:'A-1-1-5',
-      suffix: '1',
-      shelfNum: '1',
-      layerNum: '1',
-      placeNum: '5'
-    }
-  ]
 }
 const getUserList = () => {
   listUser({ status: '0', pageSize: 10000, pageNum: 1 }).then(({ code, rows }) => {
@@ -407,24 +363,19 @@ const getUserList = () => {
     }
   })
 }
-const setUserInfo = (key) => {
-  form.value.ext1[`${key}Name`] = ''
-  userOptions.value.forEach(item => {
-    if (form.value[`${key}Id`] === item.userId) {
-      form.value.ext1[`${key}Name`] = item.nickName
-    }
-  })
-}
 const addShelfs = () => {
-  form.value.shelfs.push({
+  form.value.tmpShelfs.push({
     suffix: '',
-    shelfNum: '',
-    layerNum: '',
-    placeNum: ''
+    shelfMinNum: 1,
+    shelfMaxNum: 1,
+    layerMinNum: 1,
+    layerMaxNum: 1,
+    placeMinNum: 1,
+    placeMaxNum: 1
   })
 }
 const delShelfs = (index) => {
-  form.value.shelfs.splice(index, 1)
+  form.value.tmpShelfs.splice(index, 1)
 }
 onMounted(() => {
   getList();
@@ -442,4 +393,13 @@ onMounted(() => {
     cursor: pointer;
   }
 }
+
+.input-group {
+  display: flex;
+  align-items: center;
+
+  >span {
+    margin: 0 5px;
+  }
+}
 </style>