Преглед изворни кода

feat(发货单): 添加挂起功能

liujt пре 7 месеци
родитељ
комит
58ee339f1d

+ 89 - 2
src/views/saleManage/saleOrder/invoice/components/inventoryTable.vue

@@ -12,6 +12,7 @@
       full-height="calc(100vh - 76px)"
       :show-summary="clientEnvironmentId == 4"
       :summary-method="getSummaries"
+      :row-class-name="tableRowClassName"
     >
       <!-- 表头工具栏 -->
       <template v-slot:toolbar>
@@ -288,6 +289,21 @@
           </el-input>
         </el-form-item>
       </template>
+      <template v-slot:warehouseNum="scope">
+        <el-form-item
+          :prop="'datasource.' + scope.$index + '.warehouseNum'"
+        > 
+          <el-link
+            v-if="scope.row.isSuspend === 1"
+            :underline="false"
+            type="primary"
+            @click="pendingReplaceTable()"
+          >
+            {{ scope.row.warehouseNum }}
+          </el-link>
+          <span v-else>{{ scope.row.warehouseNum }}</span>
+        </el-form-item>
+      </template>
       <!-- <template v-slot:saleUnit="scope">
         <el-form-item
           style="margin-bottom: 20px"
@@ -360,6 +376,25 @@
         >
           替代料
         </el-link>
+        
+        <el-popconfirm
+          v-if="scope.row.isSuspend === 1"
+          class="ele-action"
+          title="确定要挂起吗?"
+          @confirm="pending(scope.row, 0)"
+        >
+          <template v-slot:reference>
+            <el-link
+              type="primary"
+              :underline="false"
+            >
+          取消挂起
+        </el-link>
+          </template>
+        </el-popconfirm>
+        <el-link v-else type="primary" :underline="false" @click="pendingReplaceTable(scope.row, scope.$index)">
+              挂起
+        </el-link>
       </template>
     </ele-pro-table>
     <productListNew
@@ -384,6 +419,10 @@
       ref="selectStockLedgerDialogRef"
       @changeParent="replaceTable"
     ></selectStockLedgerDialog>
+    <selectStockLedgerDialogPending
+      ref="selectStockLedgerDialogPendingRef"
+      @changeParent="pendingReplaceTableConfirm"
+    ></selectStockLedgerDialogPending>
     <BIZproductList
       ref="BIZproductListRef"
       classType="1"
@@ -419,6 +458,7 @@
   import { parameterGetByCode } from '@/api/main/index.js';
   import { getSummaries } from '@/utils/util.js';
   import { getBatchList } from '@/api/wms';
+  import selectStockLedgerDialogPending from './selectStockLedger/selectStockLedgerDialog.vue';
 
   export default {
     mixins: [dictMixins, getDynamicsColumns, tabMixins],
@@ -454,7 +494,8 @@
       productListNew,
       stockLedgerDialog,
       selectStockLedgerDialog,
-      BIZproductList
+      BIZproductList,
+      selectStockLedgerDialogPending
     },
     data() {
       const defaultForm = {
@@ -930,7 +971,7 @@
           {
             columnKey: 'action',
             label: '操作',
-            width: 180,
+            width: 200,
             align: 'center',
             resizable: false,
             slot: 'action',
@@ -944,6 +985,52 @@
       // this.clientEnvironmentId =
     },
     methods: {
+       // 挂起/取消挂起功能
+      async pending(row) {
+        console.log('pending~~~', row, type)
+          // 取消挂起不需要二次确认
+          this.$set(row, 'isSuspend', 0);
+          this.$forceUpdate();
+          this.current['offsetDetail'] = [];
+          this.current['isSuspend'] = 0;
+          this.$set(this.current, 'warehouseList', await getIdWarehouseList({
+              categoryId: this.current.id
+            }))
+          this.$set(this.current, 'warehouseId', '')
+      },
+      // 通过挂起状态设置行样式
+      tableRowClassName({row}) {
+        // console.log('tableRowClassName', row)
+        if (row.isSuspend === 1) {
+          return 'warning-row';
+        }
+        return '';
+      },
+      // 挂起选择库存
+      pendingReplaceTable(row, index) {
+        // console.log('handleWarehouseClick', row, index)
+        this.current = row;
+        this.$refs.selectStockLedgerDialogPendingRef.open(row, index)
+      },
+      pendingReplaceTableConfirm(list) {
+        console.log('confirm', list)
+        list.forEach((item) => {
+          item.warehouseList =[{
+            warehouseName: item.warehouseName,
+            warehouseId: item.warehouseId,
+          }]
+        });
+        
+        this.$set(this.current, 'warehouseList', list[0].warehouseList)
+        this.$set(this.current, 'warehouseId', list[0].warehouseId)
+        this.$set(this.current, 'warehouseNum', list[0].measureQuantity)
+        this.current['offsetDetail'] = list
+        this.$set(this.current, 'isSuspend', 1)
+        console.log('current', this.current)
+        // this.$emit('pendingReplaceTableConfirm', list);
+        // this.$emit('replaceTableChange', list);
+        // console.log('pendingReplaceTableConfirm', list)
+      },
       getSummaries(param) {
         if (this.clientEnvironmentId != 4) {
           return;

+ 249 - 0
src/views/saleManage/saleOrder/invoice/components/selectStockLedger/item-search.vue

@@ -0,0 +1,249 @@
+<!-- 搜索表单 -->
+<template>
+  <div class="itemSearch">
+    <el-form
+      label-width="80px"
+      label-position="left"
+      class="ele-form-search"
+      @keyup.enter.native="search"
+      @submit.native.prevent
+    >
+      <el-row :gutter="15">
+        <el-col :span="6">
+          <el-form-item label="仓库:" prop="warehouseId">
+            <template>
+              <el-select
+                clearable
+                style="width: 100%"
+                v-model="params.warehouseId"
+                placeholder="请选择"
+              >
+                <el-option
+                  v-for="item in warehouseList"
+                  :label="item.name"
+                  :value="item.id"
+                  :key="item.id"
+                >
+                </el-option>
+              </el-select>
+            </template>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6" style="height: 43px">
+          <el-form-item label="列表维度:" prop="dimension">
+            <template>
+              <el-select
+                style="width: 100%"
+                @change="search"
+                v-model="params.dimension"
+                placeholder="请选择"
+              >
+                <el-option label="批次维度" value="2"></el-option>
+                <el-option label="物品维度" value="1"></el-option>
+              </el-select>
+            </template>
+          </el-form-item>
+        </el-col>
+        <!-- <el-col :span="6">
+          <el-form-item label="物品编码:" prop="categoryCode">
+            <el-input
+              clearable
+              placeholder="请输入"
+              v-model.trim="params.categoryCode"
+              disabled
+            ></el-input>
+          </el-form-item>
+        </el-col> -->
+
+        <el-col :span="6">
+          <el-form-item label="物品名称:" prop="categoryName">
+            <el-input
+              clearable
+              v-model="params.categoryName"
+              placeholder="请输入"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="型号:" prop="categoryModel">
+            <el-input
+              clearable
+              v-model="params.categoryModel"
+              placeholder="请输入"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="规格:" prop="specification">
+            <el-input
+              clearable
+              v-model="params.specification"
+              placeholder="请输入"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <!--        <el-col :span="6">-->
+        <!--          <el-form-item label="组织机构:">-->
+        <!--            <auth-selection-->
+        <!--              v-model="params.deptIds"-->
+        <!--              style="width: 100%"-->
+        <!--            ></auth-selection>-->
+        <!--          </el-form-item>-->
+        <!--        </el-col>-->
+        <el-col :span="6">
+          <el-form-item label="所属工厂" prop="factoryId">
+            <el-select
+              filterable
+              placeholder="请选择"
+              v-model="params.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="6">
+          <div class="ele-form-actions">
+            <el-button
+              type="primary"
+              icon="el-icon-search"
+              class="ele-btn-icon"
+              @click="search"
+              size="small"
+            >
+              查询
+            </el-button>
+            <el-button
+              @click="reset"
+              icon="el-icon-refresh-left"
+              size="small"
+              type="primary"
+              >重置</el-button
+            >
+          </div>
+        </el-col>
+      </el-row>
+    </el-form>
+  </div>
+</template>
+<script>
+  import { getFactoryarea } from '@/api/main';
+  import { getWarehouseList } from '@/api/wms';
+  export default {
+    data() {
+      // 默认表单数据
+      const defaultParams = {
+        batchNo: '',
+        informationName: '',
+        warehouseId: '',
+        manualBatchNo: '',
+        barcodes: '',
+        engrave: '',
+        clientCode: '',
+        modelType: '',
+        specification: '',
+        code: '',
+        categoryCode: '',
+        assetName: '',
+        qualityResult: '',
+        factoryId: '',
+        dimension: '2'
+      };
+      return {
+        // 表单数据
+        params: { ...defaultParams },
+
+        qualityResultOption: [
+          {
+            value: 0,
+            label: '合格'
+          },
+          {
+            value: 1,
+            label: '不合格'
+          }
+        ],
+        qualityStatusOption: [
+          {
+            value: 1,
+            label: '已质检'
+          },
+          {
+            value: 0,
+            label: '未质检'
+          }
+        ],
+        warehouseList: [],
+        dimension: '1',
+        factoryList: []
+      };
+    },
+    props: {
+      type: {
+        type: String,
+        default: ''
+      }
+    },
+    watch: {
+      type(val) {
+        if (val === 'warehouse') {
+          this.dimension = '3';
+        } else {
+          this.dimension = '1';
+        }
+      }
+    },
+    computed: {
+      // 是否开启响应式布局
+      styleResponsive() {
+        return this.$store.state.theme.styleResponsive;
+      }
+    },
+    created() {
+      this.getArguInfo();
+      this.getFactoryList();
+    },
+    methods: {
+      //获取工厂列表
+      async getFactoryList() {
+        const res = await getFactoryarea({
+          pageNum: 1,
+          size: 9999,
+          type: 1
+        });
+        this.factoryList = res.list;
+      },
+      //搜索数据源
+      async getArguInfo() {
+        const { data } = await getWarehouseList();
+        this.warehouseList = data;
+      },
+      /* 搜索 */
+      search() {
+        console.log(this.current);
+        this.$emit('search', {
+          ...this.params
+        });
+      },
+      /*  重置 */
+      reset() {
+        this.params = { ...this.defaultParams };
+        this.search();
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  ::v-deep .el-row {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  .ele-form-actions {
+    float: right;
+  }
+</style>

+ 412 - 0
src/views/saleManage/saleOrder/invoice/components/selectStockLedger/selectStockLedgerDialog.vue

@@ -0,0 +1,412 @@
+<template>
+  <el-dialog
+    title="库存台账"
+    :visible.sync="visible"
+    :before-close="handleClose"
+    :close-on-click-modal="false"
+    top="5vh"
+    :close-on-press-escape="false"
+    append-to-body
+    width="70%"
+    :maxable="true"
+    :resizable="true"
+  
+  >
+    <el-card shadow="never">
+      <item-search @search="reload" ref="refSeavch"></item-search>
+      <ele-split-layout
+        width="244px"
+        allow-collapse
+        :right-style="{ overflow: 'hidden' }"
+      >
+        <div class="ele-border-lighter split-layout-right-content">
+          <el-tree
+            :data="treeList"
+            :props="defaultProps"
+            ref="treeRef"
+            :default-expanded-keys="
+              curNodeData && curNodeData.id ? [curNodeData.id] : []
+            "
+            :highlight-current="true"
+            node-key="id"
+            :expand-on-click-node="false"
+            @node-click="handleNodeClick"
+            ><span class="custom-tree-node" slot-scope="{ node, data }">
+              <span
+                >{{ data.factoryName ? data.factoryName + '-' : ''
+                }}{{ data.name }}</span
+              >
+            </span></el-tree
+          >
+        </div>
+        <!-- 表格 -->
+        <template v-slot:content>
+          <ele-pro-table
+            ref="table"
+            :columns="columns"
+            :datasource="datasource"
+            row-key="id"
+            height="calc(100vh - 480px)"
+            class="dict-table"
+            @cell-click="cellClick"
+            :selection.sync="selection"
+          >
+            <template v-slot:action="{ row }">
+              <el-radio class="radio" v-model="radio" :label="row.batchNo"
+                ><i></i
+              ></el-radio>
+            </template>
+          </ele-pro-table>
+        </template>
+      </ele-split-layout>
+    </el-card>
+
+    <div slot="footer">
+      <el-button type="primary" size="small" @click="selected">选择</el-button>
+      <el-button size="small" @click="handleClose">关闭</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+  import {
+    getOutindetailtwoList,
+    getTreeByGroup,
+    getBatchList,
+    getCategoryPackageDisposition
+  } from '@/api/wms';
+  import ItemSearch from './item-search.vue';
+  import { contactQueryByCategoryIdsAPI } from '@/api/saleManage/contact';
+
+  export default {
+    components: { ItemSearch },
+    props: {
+      /*已选择的产品*/
+      data: {
+        type: Array,
+        default: () => []
+      },
+      /*是否需要供应商*/
+      isSupplier: {
+        type: Boolean,
+        default: false
+      }
+    },
+
+    data() {
+      return {
+        visible: false,
+        currentIndex: null,
+        radio: null,
+        dictList: {},
+        curNodeData: {},
+        selection: [],
+        treeData: [],
+        dimension:'2',
+        defaultProps: {
+          children: 'children',
+          label: 'name'
+        },
+        treeList: [],
+        treeLoading: false,
+        currentItem: {}
+      };
+    },
+    watch: {},
+    computed: {
+      columns() {
+        let data = null;
+        if (this.currentIndex != -1) {
+          data = {
+            action: 'action',
+            slot: 'action',
+            align: 'center',
+            label: '选择',
+            reserveSelection: true
+          };
+        }
+        if (this.currentIndex == -1) {
+          data = {
+            label: '选择',
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center',
+            reserveSelection: true
+          };
+        }
+        return [
+          data,
+
+          {
+            columnKey: 'index',
+            type: 'index',
+            width: 50,
+            align: 'center',
+            showOverflowTooltip: true,
+            label: '序号'
+          },
+          {
+            prop: 'categoryCode',
+            label: '编码',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'categoryName',
+            label: '名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'brandNum',
+            align: 'center',
+            label: '牌号',
+            showOverflowTooltip: true
+          },
+          this.dimension=="2"?
+          {
+            prop: 'batchNo',
+            label: '批次号',
+            align: 'center',
+            showOverflowTooltip: true
+          }:{
+              width:1
+          },
+          {
+            prop: 'categoryModel',
+            label: '型号',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'specification',
+            label: '规格',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'measureQuantity',
+            label: '库存',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 90
+          },
+          {
+            prop: 'measureUnit',
+            label: '单位',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 90
+          },
+          {
+            prop: 'weight',
+            label: '重量',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 90
+          },
+          {
+            prop: 'weightUnit',
+            label: '重量单位',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 90
+          },
+          {
+            prop: 'packingUnit',
+            align: 'center',
+            label: '包装单位',
+            showOverflowTooltip: true
+          }
+        ];
+      }
+    },
+    methods: {
+      getDictV(code, val) {
+        if (!this.dictList[code]) return '';
+        return this.dictList[code].find((item) => item.value == val)?.label;
+      },
+      open(item, currentIndex) {
+        console.log('item', item);
+        this.currentItem = item;
+        this.currentIndex = currentIndex;
+        this.visible = true;
+        this.getTreeData();
+      },
+      async getTreeData() {
+        try {
+          this.treeLoading = true;
+          let res = null;
+          res = await getTreeByGroup({ type: 2 });
+          this.reload();
+          this.treeLoading = false;
+          if (res?.code === '0') {
+            this.treeList = res.data;
+            return this.treeList;
+          }
+        } catch (error) {
+          console.log(error);
+        }
+        this.treeLoading = false;
+      },
+
+      /* 表格数据源 */
+      async datasource({ page, limit, where, order }) {
+        this.dimension = where.dimension||'2';
+        console.log('where', where);
+        let api = where.dimension == '1' ? getOutindetailtwoList : getBatchList;
+        return await api({
+          ...where,
+          categoryCode: this.currentItem.productCode,
+          ...order,
+          pageNum: page,
+          size: limit
+        });
+      },
+
+      /* 刷新表格 */
+      reload(where) {
+        this.$refs.table.reload({ pageNum: 1, where: where, categoryCode: this.currentItem.productCode });
+      },
+
+      handleNodeClick(data, node) {
+        this.curNodeData = data;
+        if (data.id == this.currentId) {
+          this.$refs.treeRef.setCurrentKey(null);
+          this.reload();
+        } else {
+          this.reload({ categoryLevelId: data.id });
+        }
+      },
+      async getSupplierObj(productList, queryName) {
+        try {
+          let categoryIds = productList
+            .filter((item) => item.id)
+            .map((item) => item.id);
+          if (categoryIds.length > 0) {
+            return await contactQueryByCategoryIdsAPI({
+              categoryIds,
+              isQueryEE: 1
+            });
+          } else {
+            return Promise.resolve({});
+          }
+        } catch (e) {
+          return Promise.resolve({});
+        }
+      },
+      // 单击获取id
+      cellClick(row) {
+        if (this.currentIndex == -1) return;
+        this.current = row;
+        this.radio = row.id;
+      },
+      handleClose() {
+        this.visible = false;
+        this.current = null;
+        this.selection = [];
+        this.$refs.table.clearSelection();
+        this.radio = '';
+      },
+
+      async selected() {
+        if (!this.current && !this.selection.length) {
+          return this.$message.warning('请至少选择一条数据');
+        }
+        if (this.currentIndex != -1) {
+          if (
+            this.data
+              .map((item) => item.productCode)
+              .includes(this.current.code)
+          ) {
+            return this.$message.error('选择的物品已经存在列表了');
+          }
+        } else {
+          if (
+            this.selection.some((item) =>
+              this.data.some((i) => i.productCode == item.code)
+            )
+          ) {
+            return this.$message.error('选择的物品已经存在列表了');
+          }
+        }
+        let list = this.currentIndex == -1 ? this.selection : [this.current];
+        //获取供应商
+        if (this.isSupplier) {
+          let supplierList = await this.getSupplierObj(list);
+          list.forEach((item) => {
+            item['entrustedEnterpriseIdList'] = supplierList[item.id];
+            if (supplierList[item.id]?.length === 1) {
+              item['entrustedEnterpriseId'] = supplierList[item.id][0].id;
+            }
+          });
+        }
+        let idList = list.map((item) => item.categoryId);
+
+        // 获取包装规格
+        let packingSpecification = await getCategoryPackageDisposition({
+          categoryIds: idList
+        });
+
+        list.forEach((item, index) => {
+          item.productName = item.categoryName;
+          item.productCode = item.categoryCode;
+          item.productCategoryName = '';
+          item.productBrand = item.brandNum;
+          item.provenance = item.provenance || [];
+          item['packageDispositionList'] = packingSpecification
+            .filter(
+              (ite) => item.categoryId == ite.categoryId && ite.conversionUnit
+            )
+            .sort((a, b) => a.sort - b.sort);
+          this.$set(list[index], 'totalCount', 1);
+          // item.totalCount = 1;
+          item.measuringUnit = item.measureUnit;
+          //item.weightUnit = item.weightUnit;
+          // item.warehouseNum = item.measureQuantity;
+          item.productId = item.categoryId;
+          item.id = '';
+
+          // item.specification = item.specification;
+        });
+        this.$emit('changeParent', list, this.currentIndex);
+        this.handleClose();
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .tree_col {
+    border: 1px solid #eee;
+    padding: 10px 0;
+    box-sizing: border-box;
+    height: 500px;
+    overflow: auto;
+  }
+
+  .table_col {
+    padding-left: 10px;
+
+    ::v-deep .el-table th.el-table__cell {
+      background: #f2f2f2;
+    }
+  }
+
+  .pagination {
+    text-align: right;
+    padding: 10px 0;
+  }
+
+  .btns {
+    text-align: center;
+    padding: 10px 0;
+  }
+
+  .topsearch {
+    margin-bottom: 15px;
+  }
+</style>