|
|
|
@ -1,73 +1,60 @@
|
|
|
|
<template>
|
|
|
|
<template>
|
|
|
|
<el-form
|
|
|
|
<el-form
|
|
|
|
ref="formRef"
|
|
|
|
ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px"
|
|
|
|
:model="formData"
|
|
|
|
:inline-message="true" :disabled="disabled">
|
|
|
|
:rules="formRules"
|
|
|
|
|
|
|
|
v-loading="formLoading"
|
|
|
|
|
|
|
|
label-width="0px"
|
|
|
|
|
|
|
|
:inline-message="true"
|
|
|
|
|
|
|
|
:disabled="disabled"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-table :data="formData" size="small" show-summary :summary-method="getSummaries" class="-mt-10px">
|
|
|
|
<el-table :data="formData" size="small" show-summary :summary-method="getSummaries" class="-mt-10px">
|
|
|
|
<el-table-column :label="t('common.index')" type="index" align="center" width="60" />
|
|
|
|
<el-table-column :label="t('common.index')" type="index" align="center" width="60" />
|
|
|
|
<el-table-column :label="t('ErpStock.Item.warehouse')" min-width="125">
|
|
|
|
<el-table-column :label="t('ErpStock.Item.warehouse')" min-width="125">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<el-form-item
|
|
|
|
<el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!">
|
|
|
|
:prop="`${$index}.warehouseId`"
|
|
|
|
|
|
|
|
:rules="formRules.warehouseId"
|
|
|
|
|
|
|
|
class="mb-0px!"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-select
|
|
|
|
<el-select
|
|
|
|
v-model="row.warehouseId"
|
|
|
|
v-model="row.warehouseId" clearable filterable
|
|
|
|
clearable
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderWarehouse')" @change="onChangeWarehouse($event, row)">
|
|
|
|
filterable
|
|
|
|
<el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderWarehouse')"
|
|
|
|
|
|
|
|
@change="onChangeWarehouse($event, row)"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-option
|
|
|
|
|
|
|
|
v-for="item in warehouseList"
|
|
|
|
|
|
|
|
:key="item.id"
|
|
|
|
|
|
|
|
:label="item.name"
|
|
|
|
|
|
|
|
:value="item.id"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column :label="t('ErpStock.Item.barcode')" min-width="160">
|
|
|
|
<el-table-column v-if="isProductMaterialStockOut" :label="t('ErpStock.Item.area')" min-width="140">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<el-form-item :prop="`${$index}.productBarCode`" class="mb-0px!">
|
|
|
|
<el-form-item :prop="`${$index}.areaId`" :rules="formRules.areaId" class="mb-0px!">
|
|
|
|
<el-select
|
|
|
|
<el-select v-model="row.areaId" clearable filterable :placeholder="t('ErpStock.Item.placeholderArea')" :disabled="!row.warehouseId">
|
|
|
|
v-model="row.productBarCode"
|
|
|
|
|
|
|
|
clearable
|
|
|
|
|
|
|
|
filterable
|
|
|
|
|
|
|
|
@change="onChangeProductCode($event, row)"
|
|
|
|
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderBarcode')"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-option
|
|
|
|
<el-option
|
|
|
|
v-for="item in productList"
|
|
|
|
v-for="item in getAreaOptions(row.warehouseId)" :key="item.id" :label="getAreaLabel(item)"
|
|
|
|
:key="item.barCode"
|
|
|
|
:value="item.id" />
|
|
|
|
:label="item.barCode"
|
|
|
|
|
|
|
|
:value="item.barCode"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.barcode')" min-width="160">
|
|
|
|
|
|
|
|
<!-- <template #default="{ row }">
|
|
|
|
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
|
|
|
|
<el-input disabled v-model="row.productBarCode" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</template>-->
|
|
|
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
|
|
|
<el-form-item :prop="`${$index}.productBarCode`" class="mb-0px!">
|
|
|
|
|
|
|
|
<div class="product-code-select">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model="row.productBarCode" readonly clearable
|
|
|
|
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderBarcode')" @click="openProductSelectDialog(row)"
|
|
|
|
|
|
|
|
@clear="handleProductClear(row)" />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column :label="t('ErpStock.Item.product')" min-width="180">
|
|
|
|
<el-table-column :label="t('ErpStock.Item.product')" min-width="180">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!">
|
|
|
|
<el-form-item
|
|
|
|
|
|
|
|
v-if="isProductMaterialStockOut" :prop="`${$index}.productId`" :rules="formRules.productId"
|
|
|
|
|
|
|
|
class="mb-0px!">
|
|
|
|
|
|
|
|
<el-input v-model="row.productName" disabled :placeholder="t('ErpStock.Item.placeholderProduct')" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item v-else :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!">
|
|
|
|
<el-cascader
|
|
|
|
<el-cascader
|
|
|
|
v-model="row.productId"
|
|
|
|
v-model="row.productId" :options="productCascaderOptions" :props="productCascaderProps"
|
|
|
|
:options="productCascaderOptions"
|
|
|
|
:show-all-levels="false" clearable filterable @change="onChangeProduct($event, row)"
|
|
|
|
:props="productCascaderProps"
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderProduct')" class="!w-100%" />
|
|
|
|
:show-all-levels="false"
|
|
|
|
|
|
|
|
clearable
|
|
|
|
|
|
|
|
filterable
|
|
|
|
|
|
|
|
@change="onChangeProduct($event, row)"
|
|
|
|
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderProduct')"
|
|
|
|
|
|
|
|
class="!w-100%"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
@ -78,34 +65,63 @@
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<!-- <el-table-column :label="t('ErpStock.Item.barcode')" min-width="150">
|
|
|
|
|
|
|
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.inventoryUnit')" min-width="80">
|
|
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
|
|
|
|
<el-input disabled v-model="row.productUnitName" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column v-if="isPurchaseUnitStockOut" :label="t('ErpStock.Item.purchaseUnit')" min-width="100">
|
|
|
|
<template #default="{ row }">
|
|
|
|
<template #default="{ row }">
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
<el-input disabled v-model="row.productBarCode" />
|
|
|
|
<el-input disabled v-model="row.purchaseUnitName" />
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>-->
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column :label="t('ErpStock.Item.unit')" min-width="80">
|
|
|
|
<el-table-column v-if="isPurchaseUnitStockOut" min-width="120">
|
|
|
|
|
|
|
|
<template #header>
|
|
|
|
|
|
|
|
{{ t('ErpStock.Item.purchaseUnitConvertQuantity') }}
|
|
|
|
|
|
|
|
<el-tooltip effect="dark" placement="top">
|
|
|
|
|
|
|
|
<template #content>
|
|
|
|
|
|
|
|
{{ purchaseUnitConvertTipText }}
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<Icon icon="ep:question-filled" class="ml-4px" style="vertical-align: middle; color: #909399; cursor: pointer;" />
|
|
|
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
<template #default="{ row }">
|
|
|
|
<template #default="{ row }">
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
<el-input disabled v-model="row.productUnitName" />
|
|
|
|
<el-input disabled v-model="row.purchaseUnitConvertQuantity" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column v-if="isProductStockOut" :label="t('ErpStock.Item.inputUnitType')" min-width="120">
|
|
|
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
|
|
|
<el-form-item :prop="`${$index}.inputUnitType`" class="mb-0px!">
|
|
|
|
|
|
|
|
<el-select v-model="row.inputUnitType" clearable :placeholder="t('ErpStock.Item.placeholderInputUnitType')">
|
|
|
|
|
|
|
|
<el-option v-for="item in inputUnitTypeOptions" :key="item" :label="item" :value="item" />
|
|
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column v-if="isProductMaterialStockOut" :label="t('ErpStock.Item.inputCount')" prop="inputCount" min-width="140">
|
|
|
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
|
|
|
<el-form-item :prop="`${$index}.inputCount`" class="mb-0px!">
|
|
|
|
|
|
|
|
<el-input-number
|
|
|
|
|
|
|
|
v-model="row.inputCount" controls-position="right" :min="0.001" :precision="3"
|
|
|
|
|
|
|
|
class="!w-100%" />
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column :label="t('ErpStock.Item.count')" prop="count" fixed="right" min-width="140">
|
|
|
|
<el-table-column :label="t('ErpStock.Item.count')" prop="count" fixed="right" min-width="140">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
|
|
|
|
<el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
|
|
|
|
<el-input-number
|
|
|
|
<el-input disabled v-model="row.count" :formatter="erpCountInputFormatter" />
|
|
|
|
v-model="row.count"
|
|
|
|
|
|
|
|
controls-position="right"
|
|
|
|
|
|
|
|
:min="0.001"
|
|
|
|
|
|
|
|
:precision="3"
|
|
|
|
|
|
|
|
class="!w-100%"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<!-- <el-table-column :label="t('ErpStock.Item.price')" fixed="right" min-width="120">
|
|
|
|
<!-- <el-table-column :label="t('ErpStock.Item.price')" fixed="right" min-width="120">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
<el-form-item :prop="`${$index}.productPrice`" class="mb-0px!">
|
|
|
|
<el-form-item :prop="`${$index}.productPrice`" class="mb-0px!">
|
|
|
|
<el-input-number
|
|
|
|
<el-input-number
|
|
|
|
@ -144,10 +160,57 @@
|
|
|
|
<el-row justify="center" class="mt-3" v-if="!disabled">
|
|
|
|
<el-row justify="center" class="mt-3" v-if="!disabled">
|
|
|
|
<el-button @click="handleAdd" round>+ {{ t('ErpStock.Out.addItem') }}</el-button>
|
|
|
|
<el-button @click="handleAdd" round>+ {{ t('ErpStock.Out.addItem') }}</el-button>
|
|
|
|
</el-row>
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<Dialog :title="t('ErpStock.Item.selectCode')" v-model="productDialogVisible" width="900px">
|
|
|
|
|
|
|
|
<el-form :model="productQueryParams" :inline="true" class="-mb-15px">
|
|
|
|
|
|
|
|
<el-form-item :label="t('ErpStock.Item.code')">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model="productQueryParams.barCode" clearable :placeholder="t('ErpStock.Item.placeholderCode')"
|
|
|
|
|
|
|
|
@keyup.enter="handleProductDialogQuery" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item :label="t('ErpStock.Item.name')">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model="productQueryParams.name" clearable :placeholder="t('ErpStock.Item.placeholderName')"
|
|
|
|
|
|
|
|
@keyup.enter="handleProductDialogQuery" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="handleProductDialogQuery">
|
|
|
|
|
|
|
|
<Icon icon="ep:search" class="mr-5px" /> {{ t('common.query') }}
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
<el-table
|
|
|
|
|
|
|
|
v-loading="productDialogLoading" :data="productDialogList" row-key="id" :stripe="true"
|
|
|
|
|
|
|
|
:show-overflow-tooltip="true" @row-click="handleProductDialogRowClick">
|
|
|
|
|
|
|
|
<el-table-column width="55" align="center">
|
|
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
|
|
<el-radio v-model="selectedProductId" :label="row.id"> </el-radio>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.code')" prop="barCode" min-width="160" />
|
|
|
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.name')" prop="name" min-width="160" />
|
|
|
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.spec')" prop="standard" min-width="120" />
|
|
|
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.category')" prop="subCategoryName" min-width="120" />
|
|
|
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.unit')" prop="unitName" min-width="80" />
|
|
|
|
|
|
|
|
<el-table-column v-if="isPurchaseUnitStockOut" :label="t('ErpStock.Item.purchaseUnit')" prop="purchaseUnitName" min-width="100" />
|
|
|
|
|
|
|
|
<el-table-column v-if="isPurchaseUnitStockOut" :label="t('ErpStock.Item.purchaseUnitConvertQuantity')" prop="purchaseUnitConvertQuantity" min-width="120" />
|
|
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
|
|
<div class="product-dialog-pagination">
|
|
|
|
|
|
|
|
<Pagination
|
|
|
|
|
|
|
|
:total="productDialogTotal" v-model:page="productQueryParams.pageNo"
|
|
|
|
|
|
|
|
v-model:limit="productQueryParams.pageSize" @pagination="getProductDialogList" />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="confirmProductSelect">{{ t('common.ok') }}</el-button>
|
|
|
|
|
|
|
|
<el-button @click="productDialogVisible = false">{{ t('common.cancel') }}</el-button>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</Dialog>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
|
|
import { Icon } from '@/components/Icon'
|
|
|
|
import { ProductApi, ProductVO } from '@/api/erp/product/product'
|
|
|
|
import { ProductApi, ProductVO } from '@/api/erp/product/product'
|
|
|
|
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
|
|
|
|
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
|
|
|
|
|
|
|
|
import { WarehouseAreaApi, WarehouseAreaVO } from '@/api/erp/stock/warehousearea'
|
|
|
|
import { StockApi } from '@/api/erp/stock/stock'
|
|
|
|
import { StockApi } from '@/api/erp/stock/stock'
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
erpCountInputFormatter,
|
|
|
|
erpCountInputFormatter,
|
|
|
|
@ -157,14 +220,16 @@ import {
|
|
|
|
} from '@/utils'
|
|
|
|
} from '@/utils'
|
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
const props = defineProps<{
|
|
|
|
items: undefined
|
|
|
|
items: any[] | undefined
|
|
|
|
disabled: false
|
|
|
|
outType?: string
|
|
|
|
|
|
|
|
disabled: boolean
|
|
|
|
}>()
|
|
|
|
}>()
|
|
|
|
const formLoading = ref(false) // 表单的加载中
|
|
|
|
const formLoading = ref(false) // 表单的加载中
|
|
|
|
const formData = ref([])
|
|
|
|
const formData = ref([])
|
|
|
|
const { t } = useI18n()
|
|
|
|
const { t } = useI18n()
|
|
|
|
const formRules = reactive({
|
|
|
|
const formRules = reactive({
|
|
|
|
warehouseId: [{ required: true, message: t('ErpStock.Item.validatorWarehouseRequired'), trigger: 'blur' }],
|
|
|
|
warehouseId: [{ required: true, message: t('ErpStock.Item.validatorWarehouseRequired'), trigger: 'blur' }],
|
|
|
|
|
|
|
|
areaId: [{ required: true, message: t('ErpStock.Item.validatorAreaRequired'), trigger: 'change' }],
|
|
|
|
productId: [{ required: true, message: t('ErpStock.Item.validatorProductRequired'), trigger: 'blur' }],
|
|
|
|
productId: [{ required: true, message: t('ErpStock.Item.validatorProductRequired'), trigger: 'blur' }],
|
|
|
|
count: [{ required: true, message: t('ErpStock.Item.validatorCountRequired'), trigger: 'blur' }]
|
|
|
|
count: [{ required: true, message: t('ErpStock.Item.validatorCountRequired'), trigger: 'blur' }]
|
|
|
|
})
|
|
|
|
})
|
|
|
|
@ -172,6 +237,33 @@ const formRef = ref([]) // 表单 Ref
|
|
|
|
const productList = ref<ProductVO[]>([]) // 产品列表
|
|
|
|
const productList = ref<ProductVO[]>([]) // 产品列表
|
|
|
|
const warehouseList = ref<WarehouseVO[]>([]) // 仓库列表
|
|
|
|
const warehouseList = ref<WarehouseVO[]>([]) // 仓库列表
|
|
|
|
const defaultWarehouse = ref<WarehouseVO>(undefined) // 默认仓库
|
|
|
|
const defaultWarehouse = ref<WarehouseVO>(undefined) // 默认仓库
|
|
|
|
|
|
|
|
const warehouseAreaMap = ref<Record<number, WarehouseAreaVO[]>>({})
|
|
|
|
|
|
|
|
const inputUnitTypeOptions = ['个', '包', '托']
|
|
|
|
|
|
|
|
const resolveStockOutCategoryType = (outType?: string) => {
|
|
|
|
|
|
|
|
if (!outType) return undefined
|
|
|
|
|
|
|
|
if (outType.includes('产品')) return 1
|
|
|
|
|
|
|
|
if (outType.includes('物料') || outType.includes('原料') || outType.includes('领料')) return 2
|
|
|
|
|
|
|
|
if (outType.includes('备件')) return 3
|
|
|
|
|
|
|
|
return undefined
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const activeCategoryType = computed(() => resolveStockOutCategoryType(props.outType))
|
|
|
|
|
|
|
|
const isProductMaterialStockOut = computed(() => Boolean(activeCategoryType.value))
|
|
|
|
|
|
|
|
const isProductStockOut = computed(() => activeCategoryType.value === 1)
|
|
|
|
|
|
|
|
const isPurchaseUnitStockOut = computed(() => activeCategoryType.value === 2 || activeCategoryType.value === 3)
|
|
|
|
|
|
|
|
const purchaseUnitConvertTipText = computed(() => t('FactoryModeling.ProductInformation.dialogPurchaseUnitConvertTip'))
|
|
|
|
|
|
|
|
const productDialogVisible = ref(false)
|
|
|
|
|
|
|
|
const productDialogLoading = ref(false)
|
|
|
|
|
|
|
|
const productDialogList = ref<any[]>([])
|
|
|
|
|
|
|
|
const productDialogTotal = ref(0)
|
|
|
|
|
|
|
|
const productQueryParams = reactive({
|
|
|
|
|
|
|
|
pageNo: 1,
|
|
|
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
|
|
|
categoryType: 1,
|
|
|
|
|
|
|
|
barCode: undefined,
|
|
|
|
|
|
|
|
name: undefined
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
const currentSelectRow = ref<any>()
|
|
|
|
|
|
|
|
const selectedProductId = ref<number>()
|
|
|
|
|
|
|
|
|
|
|
|
const productCascaderProps = {
|
|
|
|
const productCascaderProps = {
|
|
|
|
emitPath: false,
|
|
|
|
emitPath: false,
|
|
|
|
@ -203,15 +295,35 @@ const productCascaderOptions = computed(() => {
|
|
|
|
return Array.from(map.values())
|
|
|
|
return Array.from(map.values())
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
/** 初始化设置出库项 */
|
|
|
|
/** 初始化设置入库项 */
|
|
|
|
watch(
|
|
|
|
watch(
|
|
|
|
() => props.items,
|
|
|
|
() => props.items,
|
|
|
|
async (val) => {
|
|
|
|
async (val) => {
|
|
|
|
formData.value = val
|
|
|
|
formData.value = val || []
|
|
|
|
|
|
|
|
fillProductNames(formData.value)
|
|
|
|
|
|
|
|
if (isProductMaterialStockOut.value) {
|
|
|
|
|
|
|
|
await loadRowsWarehouseAreas(formData.value)
|
|
|
|
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ immediate: true }
|
|
|
|
{ immediate: true }
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
|
|
() => props.outType,
|
|
|
|
|
|
|
|
async () => {
|
|
|
|
|
|
|
|
if (isProductMaterialStockOut.value) {
|
|
|
|
|
|
|
|
formData.value.forEach((row) => {
|
|
|
|
|
|
|
|
row.inputCount = row.inputCount ?? row.count ?? 1
|
|
|
|
|
|
|
|
if (isProductStockOut.value) {
|
|
|
|
|
|
|
|
row.inputUnitType = row.inputUnitType || '个'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
syncCountByInputCount(row)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
await loadRowsWarehouseAreas(formData.value)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/** 监听合同产品变化,计算合同产品总价 */
|
|
|
|
/** 监听合同产品变化,计算合同产品总价 */
|
|
|
|
watch(
|
|
|
|
watch(
|
|
|
|
() => formData.value,
|
|
|
|
() => formData.value,
|
|
|
|
@ -253,16 +365,27 @@ const handleAdd = () => {
|
|
|
|
const row = {
|
|
|
|
const row = {
|
|
|
|
id: undefined,
|
|
|
|
id: undefined,
|
|
|
|
warehouseId: defaultWarehouse.value?.id,
|
|
|
|
warehouseId: defaultWarehouse.value?.id,
|
|
|
|
|
|
|
|
areaId: undefined,
|
|
|
|
productId: undefined,
|
|
|
|
productId: undefined,
|
|
|
|
|
|
|
|
productName: undefined,
|
|
|
|
productUnitName: undefined, // 产品单位
|
|
|
|
productUnitName: undefined, // 产品单位
|
|
|
|
productBarCode: undefined, // 产品条码
|
|
|
|
productBarCode: undefined, // 产品条码
|
|
|
|
productPrice: undefined,
|
|
|
|
productPrice: undefined,
|
|
|
|
|
|
|
|
purchaseUnitId: undefined,
|
|
|
|
|
|
|
|
purchaseUnitName: undefined,
|
|
|
|
|
|
|
|
purchaseUnitConvertQuantity: undefined,
|
|
|
|
|
|
|
|
inputUnitType: isProductStockOut.value ? '个' : undefined,
|
|
|
|
|
|
|
|
inputCount: isProductMaterialStockOut.value ? 1 : undefined,
|
|
|
|
stockCount: undefined,
|
|
|
|
stockCount: undefined,
|
|
|
|
count: 1,
|
|
|
|
count: isProductMaterialStockOut.value ? undefined : 1,
|
|
|
|
totalPrice: undefined,
|
|
|
|
totalPrice: undefined,
|
|
|
|
remark: undefined
|
|
|
|
remark: undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
syncCountByInputCount(row)
|
|
|
|
formData.value.push(row)
|
|
|
|
formData.value.push(row)
|
|
|
|
|
|
|
|
if (row.warehouseId && isProductMaterialStockOut.value) {
|
|
|
|
|
|
|
|
loadWarehouseAreas(row.warehouseId)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 删除按钮操作 */
|
|
|
|
/** 删除按钮操作 */
|
|
|
|
@ -273,18 +396,17 @@ const handleDelete = (index) => {
|
|
|
|
/** 处理产品变更 */
|
|
|
|
/** 处理产品变更 */
|
|
|
|
const onChangeProductCode = (productBarCode, row) => {
|
|
|
|
const onChangeProductCode = (productBarCode, row) => {
|
|
|
|
const product = productList.value.find((item) => item.barCode === productBarCode)
|
|
|
|
const product = productList.value.find((item) => item.barCode === productBarCode)
|
|
|
|
if (product) {
|
|
|
|
product ? fillRowByProduct(row, product) : clearProduct(row)
|
|
|
|
row.productUnitName = product.unitName
|
|
|
|
|
|
|
|
row.productBarCode = product.barCode
|
|
|
|
|
|
|
|
row.productPrice = product.minPrice
|
|
|
|
|
|
|
|
row.productId = product.id
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 加载库存
|
|
|
|
// 加载库存
|
|
|
|
setStockCount(row)
|
|
|
|
setStockCount(row)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 处理仓库变更 */
|
|
|
|
/** 处理仓库变更 */
|
|
|
|
const onChangeWarehouse = (warehouseId, row) => {
|
|
|
|
const onChangeWarehouse = (warehouseId, row) => {
|
|
|
|
|
|
|
|
row.areaId = undefined
|
|
|
|
|
|
|
|
if (warehouseId && isProductMaterialStockOut.value) {
|
|
|
|
|
|
|
|
loadWarehouseAreas(warehouseId)
|
|
|
|
|
|
|
|
}
|
|
|
|
// 加载库存
|
|
|
|
// 加载库存
|
|
|
|
setStockCount(row)
|
|
|
|
setStockCount(row)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -292,15 +414,149 @@ const onChangeWarehouse = (warehouseId, row) => {
|
|
|
|
/** 处理产品变更 */
|
|
|
|
/** 处理产品变更 */
|
|
|
|
const onChangeProduct = (productId, row) => {
|
|
|
|
const onChangeProduct = (productId, row) => {
|
|
|
|
const product = productList.value.find((item) => item.id === productId)
|
|
|
|
const product = productList.value.find((item) => item.id === productId)
|
|
|
|
if (product) {
|
|
|
|
product ? fillRowByProduct(row, product) : clearProduct(row)
|
|
|
|
row.productUnitName = product.unitName
|
|
|
|
|
|
|
|
row.productBarCode = product.barCode
|
|
|
|
|
|
|
|
row.productPrice = product.minPrice
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 加载库存
|
|
|
|
// 加载库存
|
|
|
|
setStockCount(row)
|
|
|
|
setStockCount(row)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const fillRowByProduct = (row: any, product: any) => {
|
|
|
|
|
|
|
|
row.productUnitName = product.unitName
|
|
|
|
|
|
|
|
row.productBarCode = product.barCode
|
|
|
|
|
|
|
|
row.productPrice = product.minPrice
|
|
|
|
|
|
|
|
row.productId = product.id
|
|
|
|
|
|
|
|
row.productName = product.name
|
|
|
|
|
|
|
|
row.purchaseUnitId = product.purchaseUnitId
|
|
|
|
|
|
|
|
row.purchaseUnitName = product.purchaseUnitName
|
|
|
|
|
|
|
|
row.purchaseUnitConvertQuantity = product.purchaseUnitConvertQuantity
|
|
|
|
|
|
|
|
syncCountByInputCount(row)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const clearProduct = (row: any) => {
|
|
|
|
|
|
|
|
row.productUnitName = undefined
|
|
|
|
|
|
|
|
row.productBarCode = undefined
|
|
|
|
|
|
|
|
row.productPrice = undefined
|
|
|
|
|
|
|
|
row.productId = undefined
|
|
|
|
|
|
|
|
row.productName = undefined
|
|
|
|
|
|
|
|
row.purchaseUnitId = undefined
|
|
|
|
|
|
|
|
row.purchaseUnitName = undefined
|
|
|
|
|
|
|
|
row.purchaseUnitConvertQuantity = undefined
|
|
|
|
|
|
|
|
row.inputCount = isProductMaterialStockOut.value ? undefined : row.inputCount
|
|
|
|
|
|
|
|
row.count = isProductMaterialStockOut.value ? undefined : row.count
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleProductClear = (row: any) => {
|
|
|
|
|
|
|
|
clearProduct(row)
|
|
|
|
|
|
|
|
setStockCount(row)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const openProductSelectDialog = async (row: any) => {
|
|
|
|
|
|
|
|
if (!activeCategoryType.value) return
|
|
|
|
|
|
|
|
currentSelectRow.value = row
|
|
|
|
|
|
|
|
selectedProductId.value = row.productId
|
|
|
|
|
|
|
|
productQueryParams.pageNo = 1
|
|
|
|
|
|
|
|
productQueryParams.categoryType = activeCategoryType.value
|
|
|
|
|
|
|
|
productQueryParams.barCode = undefined
|
|
|
|
|
|
|
|
productQueryParams.name = undefined
|
|
|
|
|
|
|
|
productDialogVisible.value = true
|
|
|
|
|
|
|
|
await getProductDialogList()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getProductDialogList = async () => {
|
|
|
|
|
|
|
|
productDialogLoading.value = true
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
productQueryParams.categoryType = activeCategoryType.value || 1
|
|
|
|
|
|
|
|
const data = await ProductApi.getProductPage(productQueryParams)
|
|
|
|
|
|
|
|
productDialogList.value = data?.list || []
|
|
|
|
|
|
|
|
productDialogTotal.value = data?.total || 0
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
productDialogLoading.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleProductDialogQuery = () => {
|
|
|
|
|
|
|
|
productQueryParams.pageNo = 1
|
|
|
|
|
|
|
|
getProductDialogList()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleProductDialogRowClick = (row: any) => {
|
|
|
|
|
|
|
|
selectedProductId.value = row.id
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const confirmProductSelect = () => {
|
|
|
|
|
|
|
|
const product = productDialogList.value.find((item) => item.id === selectedProductId.value)
|
|
|
|
|
|
|
|
if (!product || !currentSelectRow.value) return
|
|
|
|
|
|
|
|
fillRowByProduct(currentSelectRow.value, product)
|
|
|
|
|
|
|
|
setStockCount(currentSelectRow.value)
|
|
|
|
|
|
|
|
productDialogVisible.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
|
|
() => formData.value.map((row) => [row.inputCount, row.purchaseUnitConvertQuantity]),
|
|
|
|
|
|
|
|
() => {
|
|
|
|
|
|
|
|
if (!isProductMaterialStockOut.value) return
|
|
|
|
|
|
|
|
formData.value.forEach(syncCountByInputCount)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{ deep: true }
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const syncCountByInputCount = (row: any) => {
|
|
|
|
|
|
|
|
if (!isProductMaterialStockOut.value) return
|
|
|
|
|
|
|
|
const inputCount = Number(row.inputCount)
|
|
|
|
|
|
|
|
const convertQuantity = Number(row.purchaseUnitConvertQuantity)
|
|
|
|
|
|
|
|
if (!Number.isFinite(inputCount)) {
|
|
|
|
|
|
|
|
row.count = undefined
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!row.purchaseUnitId && !row.purchaseUnitName) {
|
|
|
|
|
|
|
|
row.count = inputCount
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
row.count = Number.isFinite(convertQuantity) ? inputCount * convertQuantity : inputCount
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const loadWarehouseAreas = async (warehouseId: number) => {
|
|
|
|
|
|
|
|
if (!warehouseId || warehouseAreaMap.value[warehouseId]) return
|
|
|
|
|
|
|
|
const data = await WarehouseAreaApi.getWarehouseAreaPage({
|
|
|
|
|
|
|
|
pageNo: 1,
|
|
|
|
|
|
|
|
pageSize: 100,
|
|
|
|
|
|
|
|
warehouseId
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
warehouseAreaMap.value = {
|
|
|
|
|
|
|
|
...warehouseAreaMap.value,
|
|
|
|
|
|
|
|
[warehouseId]: data?.list || []
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const loadRowsWarehouseAreas = async (rows: any[]) => {
|
|
|
|
|
|
|
|
const warehouseIds = Array.from(new Set((rows || []).map((row) => row.warehouseId).filter(Boolean)))
|
|
|
|
|
|
|
|
await Promise.all(warehouseIds.map((warehouseId) => loadWarehouseAreas(warehouseId)))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getAreaOptions = (warehouseId: number) => {
|
|
|
|
|
|
|
|
return warehouseId ? warehouseAreaMap.value[warehouseId] || [] : []
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getAreaLabel = (item: WarehouseAreaVO) => {
|
|
|
|
|
|
|
|
return item.areaCode ? `${item.areaCode} - ${item.areaName}` : item.areaName
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const fillProductNames = (rows: any[]) => {
|
|
|
|
|
|
|
|
if (!productList.value.length) return
|
|
|
|
|
|
|
|
rows.forEach((row) => {
|
|
|
|
|
|
|
|
const product = productList.value.find((item) => item.id === row.productId || item.barCode === row.productBarCode)
|
|
|
|
|
|
|
|
if (!product) return
|
|
|
|
|
|
|
|
row.productId = row.productId || product.id
|
|
|
|
|
|
|
|
row.productBarCode = row.productBarCode || product.barCode
|
|
|
|
|
|
|
|
row.productName = row.productName || product.name
|
|
|
|
|
|
|
|
row.productUnitName = row.productUnitName || product.unitName
|
|
|
|
|
|
|
|
row.productPrice = row.productPrice ?? product.minPrice
|
|
|
|
|
|
|
|
row.purchaseUnitId = row.purchaseUnitId ?? (product as any).purchaseUnitId
|
|
|
|
|
|
|
|
row.purchaseUnitName = row.purchaseUnitName ?? (product as any).purchaseUnitName
|
|
|
|
|
|
|
|
row.purchaseUnitConvertQuantity = row.purchaseUnitConvertQuantity ?? (product as any).purchaseUnitConvertQuantity
|
|
|
|
|
|
|
|
syncCountByInputCount(row)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 加载库存 */
|
|
|
|
/** 加载库存 */
|
|
|
|
const setStockCount = async (row) => {
|
|
|
|
const setStockCount = async (row) => {
|
|
|
|
if (!row.productId || !row.warehouseId) {
|
|
|
|
if (!row.productId || !row.warehouseId) {
|
|
|
|
@ -314,16 +570,46 @@ const setStockCount = async (row) => {
|
|
|
|
const validate = () => {
|
|
|
|
const validate = () => {
|
|
|
|
return formRef.value.validate()
|
|
|
|
return formRef.value.validate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
defineExpose({ validate })
|
|
|
|
|
|
|
|
|
|
|
|
const resetItems = () => {
|
|
|
|
|
|
|
|
formData.value.splice(0, formData.value.length)
|
|
|
|
|
|
|
|
if (!props.disabled) {
|
|
|
|
|
|
|
|
handleAdd()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defineExpose({ validate, resetItems })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 初始化 */
|
|
|
|
/** 初始化 */
|
|
|
|
onMounted(async () => {
|
|
|
|
onMounted(async () => {
|
|
|
|
productList.value = await ProductApi.getProductSimpleList()
|
|
|
|
productList.value = await ProductApi.getProductSimpleList()
|
|
|
|
warehouseList.value = await WarehouseApi.getWarehouseSimpleList()
|
|
|
|
warehouseList.value = await WarehouseApi.getWarehouseSimpleList()
|
|
|
|
defaultWarehouse.value = warehouseList.value.find((item) => item.defaultStatus)
|
|
|
|
defaultWarehouse.value = warehouseList.value.find((item) => item.defaultStatus)
|
|
|
|
|
|
|
|
fillProductNames(formData.value)
|
|
|
|
|
|
|
|
if (isProductMaterialStockOut.value) {
|
|
|
|
|
|
|
|
await loadRowsWarehouseAreas(formData.value)
|
|
|
|
|
|
|
|
}
|
|
|
|
// 默认添加一个
|
|
|
|
// 默认添加一个
|
|
|
|
if (formData.value.length === 0) {
|
|
|
|
if (formData.value.length === 0) {
|
|
|
|
handleAdd()
|
|
|
|
handleAdd()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
|
|
.product-code-select {
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-input__wrapper) {
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.product-dialog-pagination {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
|
|
padding: 12px 0 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|