|
|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
<template>
|
|
|
|
|
<el-form ref="formRef" :model="formData" :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" class="-mt-10px">
|
|
|
|
|
<el-table-column :label="t('common.index')" type="index" align="center" width="60" />
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.warehouse')" min-width="125">
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
@ -30,14 +30,34 @@
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.barcode')" min-width="160">
|
|
|
|
|
<el-table-column v-if="isProductStockIn" :label="t('ErpStock.Item.relatedTask')" min-width="120">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-select v-model="row.relateTask" :placeholder="t('common.selectText')" @change="handleRelatedTaskChange(row)">
|
|
|
|
|
<el-option :label="t('common.yes')" :value="true" />
|
|
|
|
|
<el-option :label="t('common.no')" :value="false" />
|
|
|
|
|
</el-select>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="isProductStockIn ? selectorColumnLabel : t('ErpStock.Item.barcode')" min-width="190">
|
|
|
|
|
<!-- <template #default="{ row }">
|
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
|
<el-input disabled v-model="row.productBarCode" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</template>-->
|
|
|
|
|
</template>-->
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<el-form-item :prop="`${$index}.productBarCode`" class="mb-0px!">
|
|
|
|
|
<div v-if="isProductStockIn && isRowRelatedTask(row)" class="task-product-select">
|
|
|
|
|
<el-form-item :prop="`${$index}.taskId`" :rules="formRules.taskId" class="mb-0px!">
|
|
|
|
|
<el-input
|
|
|
|
|
:model-value="formatTaskSelection(row)"
|
|
|
|
|
readonly
|
|
|
|
|
clearable
|
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderTaskOrder')"
|
|
|
|
|
@click="openTaskSelectDialog(row)"
|
|
|
|
|
@clear="clearTask(row)"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</div>
|
|
|
|
|
<el-form-item v-else :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!">
|
|
|
|
|
<div class="product-code-select">
|
|
|
|
|
<el-input v-model="row.productBarCode" readonly clearable
|
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderBarcode')" @click="openProductSelectDialog(row)"
|
|
|
|
|
@ -46,31 +66,37 @@
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.product')" min-width="180">
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<el-form-item v-if="isProductMaterialStockIn" :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 v-model="row.productId" :options="productCascaderOptions" :props="productCascaderProps"
|
|
|
|
|
:show-all-levels="false" clearable filterable @change="onChangeProduct($event, row)"
|
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderProduct')" class="!w-100%" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-table-column v-if="isProductStockIn" :label="t('ErpStock.Item.productName')" min-width="150">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-input :model-value="row.productName || '-'" readonly />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.stock')" min-width="100">
|
|
|
|
|
<el-table-column v-if="isProductStockIn" :label="t('ErpStock.Item.packagingScheme')" min-width="150">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
|
<el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-input :model-value="row.packagingSchemeName || '-'" readonly />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.inventoryUnit')" min-width="80">
|
|
|
|
|
<el-table-column v-if="isProductStockIn" :label="t('ErpStock.PackagingScheme.palletPackageQuantity')" min-width="120">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
|
<el-input disabled v-model="row.productUnitName" />
|
|
|
|
|
<el-input :model-value="row.palletPackageQuantity ?? '-'" readonly />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column v-if="isProductStockIn" :label="t('ErpStock.Item.packageItemCount')" min-width="120">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-input :model-value="row.packageQuantity ?? '-'" readonly />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column v-if="isProductStockIn" :label="t('ErpStock.Item.palletCode')" min-width="180">
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<el-form-item :prop="`${$index}.pallets`" :rules="formRules.pallets" class="mb-0px!">
|
|
|
|
|
<el-input
|
|
|
|
|
v-model="row.palletCode"
|
|
|
|
|
readonly
|
|
|
|
|
clearable
|
|
|
|
|
:placeholder="t('ErpStock.Item.placeholderPalletCode')"
|
|
|
|
|
@click="openPalletSelectDialog(row)"
|
|
|
|
|
@clear="clearPallet(row)"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
@ -88,43 +114,11 @@
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column v-if="isPurchaseUnitStockIn" 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 }">
|
|
|
|
|
<el-form-item class="mb-0px!">
|
|
|
|
|
<el-input disabled v-model="row.purchaseUnitConvertQuantity" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column v-if="isProductStockIn" :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('common.selectText')">
|
|
|
|
|
<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="isProductMaterialStockIn" :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>
|
|
|
|
|
</template>
|
|
|
|
|
</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" min-width="140">
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
|
|
|
|
|
<el-input disabled v-model="row.count" :formatter="erpCountInputFormatter" />
|
|
|
|
|
<el-input v-if="isProductStockIn" :model-value="row.count ?? '-'" readonly />
|
|
|
|
|
<el-input-number v-else v-model="row.count" controls-position="right" :min="0.001" :precision="3" class="!w-100%" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
@ -168,7 +162,7 @@
|
|
|
|
|
<el-button @click="handleAdd" round>+ {{ t('ErpStock.In.addItem') }}</el-button>
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
<Dialog :title="t('ErpStock.Item.selectCode')" v-model="productDialogVisible" width="900px">
|
|
|
|
|
<Dialog :title="t('ErpStock.Item.selectProduct')" 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')"
|
|
|
|
|
@ -213,6 +207,201 @@
|
|
|
|
|
<el-button @click="productDialogVisible = false">{{ t('common.cancel') }}</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</Dialog>
|
|
|
|
|
|
|
|
|
|
<Dialog :title="t('ErpStock.Item.selectTaskOrder')" v-model="taskDialogVisible" width="1100px">
|
|
|
|
|
<div class="task-select-dialog">
|
|
|
|
|
<div class="task-select-dialog__section-title">{{ t('ErpStock.Item.selectTaskOrder') }}</div>
|
|
|
|
|
<el-form :model="taskQueryParams" :inline="true" class="-mb-15px">
|
|
|
|
|
<el-form-item :label="t('ProductionPlan.Task.searchCodeLabel')">
|
|
|
|
|
<el-input
|
|
|
|
|
v-model="taskQueryParams.code"
|
|
|
|
|
clearable
|
|
|
|
|
:placeholder="t('ProductionPlan.Task.searchCodePlaceholder')"
|
|
|
|
|
@keyup.enter="handleTaskDialogQuery"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
|
|
|
|
<el-button type="primary" @click="handleTaskDialogQuery">
|
|
|
|
|
<Icon icon="ep:search" class="mr-5px" /> {{ t('common.query') }}
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
<el-table
|
|
|
|
|
v-loading="taskDialogLoading"
|
|
|
|
|
:data="taskDialogList"
|
|
|
|
|
row-key="id"
|
|
|
|
|
:stripe="true"
|
|
|
|
|
:show-overflow-tooltip="true"
|
|
|
|
|
@row-click="handleTaskDialogRowClick"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column width="55" align="center">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-radio v-model="selectedTaskId" :label="row.id"> </el-radio>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ProductionPlan.Task.tableCodeColumn')" prop="code" min-width="160" />
|
|
|
|
|
<el-table-column :label="t('ProductionPlan.Task.tableOrderDateColumn')" prop="orderDate" :formatter="dateFormatter2" min-width="120" />
|
|
|
|
|
<el-table-column :label="t('ProductionPlan.Task.tableDeliveryDateColumn')" prop="deliveryDate" :formatter="dateFormatter2" min-width="120" />
|
|
|
|
|
<el-table-column :label="t('ProductionPlan.Task.tableStatusColumn')" prop="status" min-width="100">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<dict-tag :type="DICT_TYPE.MES_TASK_STATUS" :value="row.status" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ProductionPlan.Task.tableRemarkColumn')" prop="remark" min-width="160" />
|
|
|
|
|
</el-table>
|
|
|
|
|
<div class="product-dialog-pagination">
|
|
|
|
|
<Pagination
|
|
|
|
|
:total="taskDialogTotal"
|
|
|
|
|
v-model:page="taskQueryParams.pageNo"
|
|
|
|
|
v-model:limit="taskQueryParams.pageSize"
|
|
|
|
|
@pagination="getTaskDialogList"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="task-select-dialog__section-title mt-12px">{{ t('ErpStock.Item.selectProduct') }}</div>
|
|
|
|
|
<el-table
|
|
|
|
|
v-loading="taskSchemeLoading"
|
|
|
|
|
:data="taskProductDialogList"
|
|
|
|
|
row-key="productId"
|
|
|
|
|
:stripe="true"
|
|
|
|
|
:show-overflow-tooltip="true"
|
|
|
|
|
empty-text="请先选择任务单"
|
|
|
|
|
@row-click="handleTaskProductDialogRowClick"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column width="55" align="center">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-radio v-model="selectedTaskProductId" :label="row.productId"> </el-radio>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.code')" prop="productCode" min-width="180" />
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.productName')" prop="productName" min-width="160" />
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.packagingScheme')" min-width="160">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
{{ getDefaultTaskProductScheme(row)?.packagingSchemeName || '-' }}
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.PackagingScheme.palletPackageQuantity')" min-width="120">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
{{ getDefaultTaskProductScheme(row)?.palletPackageQuantity ?? '-' }}
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.packageItemCount')" min-width="120">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
{{ getDefaultTaskProductScheme(row)?.packageQuantity ?? '-' }}
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
</div>
|
|
|
|
|
<template #footer>
|
|
|
|
|
<el-button type="primary" :loading="taskSchemeLoading" :disabled="!selectedTaskId || !selectedTaskProductId" @click="confirmTaskSelect">{{ t('common.ok') }}</el-button>
|
|
|
|
|
<el-button @click="taskDialogVisible = false">{{ t('common.cancel') }}</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</Dialog>
|
|
|
|
|
|
|
|
|
|
<Dialog :title="t('ErpStock.Item.selectPalletCode')" v-model="palletDialogVisible" width="1280px">
|
|
|
|
|
<el-form :model="palletQueryParams" :inline="true" class="-mb-15px">
|
|
|
|
|
<el-form-item :label="t('ErpStock.Pallet.code')">
|
|
|
|
|
<el-input
|
|
|
|
|
v-model="palletQueryParams.code"
|
|
|
|
|
clearable
|
|
|
|
|
:placeholder="t('ErpStock.Pallet.placeholderCode')"
|
|
|
|
|
@keyup.enter="handlePalletDialogQuery"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item :label="t('ErpStock.Pallet.status')">
|
|
|
|
|
<el-select v-model="palletQueryParams.status" clearable :placeholder="t('ErpStock.Pallet.placeholderStatus')" class="!w-180px">
|
|
|
|
|
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.STORAGE_PALLET_STATUS)" :key="dict.value" :label="dict.label" :value="dict.value" />
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
|
|
|
|
<el-button type="primary" @click="handlePalletDialogQuery">
|
|
|
|
|
<Icon icon="ep:search" class="mr-5px" /> {{ t('common.query') }}
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
<div class="pallet-transfer">
|
|
|
|
|
<div class="pallet-transfer__panel">
|
|
|
|
|
<div class="pallet-transfer__title">{{ t('ErpStock.Item.availablePallets') }}</div>
|
|
|
|
|
<el-table
|
|
|
|
|
ref="availablePalletTableRef"
|
|
|
|
|
v-loading="palletDialogLoading"
|
|
|
|
|
:data="availablePalletList"
|
|
|
|
|
row-key="id"
|
|
|
|
|
height="340"
|
|
|
|
|
:stripe="true"
|
|
|
|
|
:show-overflow-tooltip="true"
|
|
|
|
|
@selection-change="handleAvailablePalletSelectionChange"
|
|
|
|
|
@row-click="toggleAvailablePallet"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="selection" width="55" align="center" />
|
|
|
|
|
<el-table-column :label="t('ErpStock.Pallet.code')" prop="code" min-width="150" />
|
|
|
|
|
<el-table-column :label="t('ErpStock.Pallet.palletType')" prop="palletType" min-width="100">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<dict-tag :type="DICT_TYPE.STORAGE_PALLET_TYPES" :value="row.palletType" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Pallet.status')" prop="status" min-width="100">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<dict-tag :type="DICT_TYPE.STORAGE_PALLET_STATUS" :value="row.status" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Pallet.planCode')" prop="planCode" min-width="150" />
|
|
|
|
|
</el-table>
|
|
|
|
|
<div class="product-dialog-pagination">
|
|
|
|
|
<Pagination
|
|
|
|
|
:total="palletDialogTotal"
|
|
|
|
|
v-model:page="palletQueryParams.pageNo"
|
|
|
|
|
v-model:limit="palletQueryParams.pageSize"
|
|
|
|
|
@pagination="getPalletDialogList"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="pallet-transfer__actions">
|
|
|
|
|
<el-button type="primary" :disabled="availablePalletSelection.length === 0" @click="addSelectedPallets">
|
|
|
|
|
<Icon icon="ep:arrow-right" />
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button :disabled="rightPalletSelection.length === 0" @click="removeSelectedPallets">
|
|
|
|
|
<Icon icon="ep:arrow-left" />
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="pallet-transfer__panel">
|
|
|
|
|
<div class="pallet-transfer__title">{{ t('ErpStock.Item.selectedPallets') }}</div>
|
|
|
|
|
<el-table
|
|
|
|
|
ref="rightPalletTableRef"
|
|
|
|
|
:data="selectedPalletRows"
|
|
|
|
|
row-key="id"
|
|
|
|
|
height="340"
|
|
|
|
|
:stripe="true"
|
|
|
|
|
:show-overflow-tooltip="true"
|
|
|
|
|
@selection-change="handleRightPalletSelectionChange"
|
|
|
|
|
@row-click="toggleRightPallet"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="selection" width="55" align="center" />
|
|
|
|
|
<el-table-column :label="t('ErpStock.Pallet.code')" prop="code" min-width="150" />
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.packageCount')" min-width="130">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-input-number
|
|
|
|
|
v-model="row.packageCount"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
:min="0"
|
|
|
|
|
:precision="3"
|
|
|
|
|
class="!w-100%"
|
|
|
|
|
@click.stop
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.itemCount')" min-width="130">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-input :model-value="getSelectedPalletItemCount(row)" readonly />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<template #footer>
|
|
|
|
|
<el-button type="primary" @click="confirmPalletSelect">{{ t('common.ok') }}</el-button>
|
|
|
|
|
<el-button @click="palletDialogVisible = false">{{ t('common.cancel') }}</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</Dialog>
|
|
|
|
|
</template>
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { Icon } from '@/components/Icon'
|
|
|
|
|
@ -220,12 +409,11 @@ import { ProductApi, ProductVO } from '@/api/erp/product/product'
|
|
|
|
|
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
|
|
|
|
|
import { WarehouseAreaApi, WarehouseAreaVO } from '@/api/erp/stock/warehousearea'
|
|
|
|
|
import { StockApi } from '@/api/erp/stock/stock'
|
|
|
|
|
import {
|
|
|
|
|
erpCountInputFormatter,
|
|
|
|
|
erpPriceInputFormatter,
|
|
|
|
|
erpPriceMultiply,
|
|
|
|
|
getSumValue
|
|
|
|
|
} from '@/utils'
|
|
|
|
|
import { TaskApi, TaskVO } from '@/api/mes/task'
|
|
|
|
|
import { PalletApi, PalletVO } from '@/api/erp/stock/pallet'
|
|
|
|
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
|
|
|
|
import { dateFormatter2 } from '@/utils/formatTime'
|
|
|
|
|
import { erpPriceMultiply } from '@/utils'
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
items: any[] | undefined
|
|
|
|
|
@ -239,6 +427,8 @@ const formRules = reactive({
|
|
|
|
|
warehouseId: [{ required: true, message: t('ErpStock.Item.validatorWarehouseRequired'), trigger: 'blur' }],
|
|
|
|
|
areaId: [{ required: true, message: t('ErpStock.Item.placeholderArea'), trigger: 'change' }],
|
|
|
|
|
productId: [{ required: true, message: t('ErpStock.Item.validatorProductRequired'), trigger: 'blur' }],
|
|
|
|
|
taskId: [{ required: true, message: t('ErpStock.Item.validatorTaskRequired'), trigger: 'change' }],
|
|
|
|
|
pallets: [{ validator: validatePallets, trigger: 'change' }],
|
|
|
|
|
count: [{ required: true, message: t('ErpStock.Item.validatorCountRequired'), trigger: 'blur' }]
|
|
|
|
|
})
|
|
|
|
|
const formRef = ref([]) // 表单 Ref
|
|
|
|
|
@ -246,7 +436,6 @@ const productList = ref<ProductVO[]>([]) // 产品列表
|
|
|
|
|
const warehouseList = ref<WarehouseVO[]>([]) // 仓库列表
|
|
|
|
|
const defaultWarehouse = ref<WarehouseVO>(undefined) // 默认仓库
|
|
|
|
|
const warehouseAreaMap = ref<Record<number, WarehouseAreaVO[]>>({})
|
|
|
|
|
const inputUnitTypeOptions = ['个', '包', '托']
|
|
|
|
|
const stockInCategoryTypeMap: Record<string, number> = {
|
|
|
|
|
产品入库: 1,
|
|
|
|
|
物料入库: 2,
|
|
|
|
|
@ -256,7 +445,12 @@ const activeCategoryType = computed(() => stockInCategoryTypeMap[props.inType ||
|
|
|
|
|
const isProductMaterialStockIn = computed(() => Boolean(activeCategoryType.value))
|
|
|
|
|
const isProductStockIn = computed(() => activeCategoryType.value === 1)
|
|
|
|
|
const isPurchaseUnitStockIn = computed(() => activeCategoryType.value === 2 || activeCategoryType.value === 3)
|
|
|
|
|
const purchaseUnitConvertTipText = computed(() => t('FactoryModeling.ProductInformation.dialogPurchaseUnitConvertTip'))
|
|
|
|
|
const selectorColumnLabel = computed(() => {
|
|
|
|
|
const rows = formData.value || []
|
|
|
|
|
return rows.length > 0 && rows.every((row) => isRowRelatedTask(row))
|
|
|
|
|
? `${t('ErpStock.Item.taskOrder')}/${t('ErpStock.Item.selectProduct')}`
|
|
|
|
|
: t('ErpStock.Item.selectProduct')
|
|
|
|
|
})
|
|
|
|
|
const productDialogVisible = ref(false)
|
|
|
|
|
const productDialogLoading = ref(false)
|
|
|
|
|
const productDialogList = ref<any[]>([])
|
|
|
|
|
@ -270,36 +464,48 @@ const productQueryParams = reactive({
|
|
|
|
|
})
|
|
|
|
|
const currentSelectRow = ref<any>()
|
|
|
|
|
const selectedProductId = ref<number>()
|
|
|
|
|
const taskDialogVisible = ref(false)
|
|
|
|
|
const taskDialogLoading = ref(false)
|
|
|
|
|
const taskSchemeLoading = ref(false)
|
|
|
|
|
const taskDialogList = ref<TaskVO[]>([])
|
|
|
|
|
const taskDialogTotal = ref(0)
|
|
|
|
|
const taskQueryParams = reactive({
|
|
|
|
|
pageNo: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
code: undefined
|
|
|
|
|
})
|
|
|
|
|
const selectedTaskId = ref<number>()
|
|
|
|
|
const selectedTaskProductId = ref<number>()
|
|
|
|
|
const taskProductDialogList = ref<any[]>([])
|
|
|
|
|
const selectedTaskData = ref<any>()
|
|
|
|
|
const palletDialogVisible = ref(false)
|
|
|
|
|
const palletDialogLoading = ref(false)
|
|
|
|
|
const palletDialogList = ref<PalletVO[]>([])
|
|
|
|
|
const palletDialogTotal = ref(0)
|
|
|
|
|
const palletQueryParams = reactive({
|
|
|
|
|
pageNo: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
code: undefined,
|
|
|
|
|
status: undefined
|
|
|
|
|
})
|
|
|
|
|
const availablePalletSelection = ref<PalletVO[]>([])
|
|
|
|
|
const rightPalletSelection = ref<any[]>([])
|
|
|
|
|
const selectedPalletRows = ref<any[]>([])
|
|
|
|
|
const availablePalletTableRef = ref()
|
|
|
|
|
const rightPalletTableRef = ref()
|
|
|
|
|
const availablePalletList = computed(() => {
|
|
|
|
|
const selectedIds = new Set(selectedPalletRows.value.map((item) => item.id))
|
|
|
|
|
return palletDialogList.value.filter((item) => !selectedIds.has(item.id))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const productCascaderProps = {
|
|
|
|
|
emitPath: false,
|
|
|
|
|
value: 'value',
|
|
|
|
|
label: 'label',
|
|
|
|
|
children: 'children'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const productCascaderOptions = computed(() => {
|
|
|
|
|
const map = new Map<number | string, { value: number | string; label: string; children: any[] }>()
|
|
|
|
|
for (const item of productList.value) {
|
|
|
|
|
const categoryKey = item.categoryId ?? item.categoryName ?? ''
|
|
|
|
|
const categoryLabel = item.categoryName ?? String(categoryKey)
|
|
|
|
|
if (!map.has(categoryKey)) {
|
|
|
|
|
map.set(categoryKey, {
|
|
|
|
|
value: categoryKey,
|
|
|
|
|
label: categoryLabel,
|
|
|
|
|
children: []
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
const group = map.get(categoryKey)
|
|
|
|
|
if (group) {
|
|
|
|
|
group.children.push({
|
|
|
|
|
value: item.id,
|
|
|
|
|
label: item.name
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
function validatePallets(_: any, value: any[], callback: (error?: Error) => void) {
|
|
|
|
|
if (!Array.isArray(value) || value.length === 0) {
|
|
|
|
|
callback(new Error(t('ErpStock.Item.validatorPalletRequired')))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
return Array.from(map.values())
|
|
|
|
|
})
|
|
|
|
|
const hasEmptyPackageCount = value.some((item) => !Number.isFinite(Number(item?.packageCount)) || Number(item?.packageCount) <= 0)
|
|
|
|
|
callback(hasEmptyPackageCount ? new Error(t('ErpStock.Item.validatorPackageCountRequired')) : undefined)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const loadWarehouseList = async () => {
|
|
|
|
|
const categoryType = activeCategoryType.value
|
|
|
|
|
@ -327,6 +533,7 @@ watch(
|
|
|
|
|
() => props.items,
|
|
|
|
|
async (val) => {
|
|
|
|
|
formData.value = val || []
|
|
|
|
|
normalizeRows(formData.value)
|
|
|
|
|
fillProductNames(formData.value)
|
|
|
|
|
if (isProductMaterialStockIn.value) {
|
|
|
|
|
await loadRowsWarehouseAreas(formData.value)
|
|
|
|
|
@ -335,6 +542,20 @@ watch(
|
|
|
|
|
{ immediate: true }
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const normalizeRows = (rows: any[]) => {
|
|
|
|
|
;(rows || []).forEach((row) => {
|
|
|
|
|
if (row.relateTask === undefined) {
|
|
|
|
|
row.relateTask = row.relatedTask ?? false
|
|
|
|
|
}
|
|
|
|
|
if (!Array.isArray(row.pallets)) {
|
|
|
|
|
row.pallets = row.palletId ? [{ palletId: row.palletId, packageCount: row.packageCount }] : []
|
|
|
|
|
}
|
|
|
|
|
if (!row.palletCode && Array.isArray(row.pallets) && row.pallets.length > 0) {
|
|
|
|
|
row.palletCode = row.pallets.map((item) => item.palletCode).filter(Boolean).join(', ')
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
() => props.inType,
|
|
|
|
|
async () => {
|
|
|
|
|
@ -367,27 +588,6 @@ watch(
|
|
|
|
|
{ deep: true }
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
/** 合计 */
|
|
|
|
|
const getSummaries = (param: SummaryMethodProps) => {
|
|
|
|
|
const { columns, data } = param
|
|
|
|
|
const sums: string[] = []
|
|
|
|
|
columns.forEach((column, index) => {
|
|
|
|
|
if (index === 0) {
|
|
|
|
|
sums[index] = t('common.total')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (['count', 'totalPrice'].includes(column.property)) {
|
|
|
|
|
const sum = getSumValue(data.map((item) => Number(item[column.property])))
|
|
|
|
|
sums[index] =
|
|
|
|
|
column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
|
|
|
|
|
} else {
|
|
|
|
|
sums[index] = ''
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return sums
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 新增按钮操作 */
|
|
|
|
|
const handleAdd = () => {
|
|
|
|
|
const row = {
|
|
|
|
|
@ -403,6 +603,19 @@ const handleAdd = () => {
|
|
|
|
|
purchaseUnitName: undefined,
|
|
|
|
|
supplierName: undefined,
|
|
|
|
|
purchaseUnitConvertQuantity: undefined,
|
|
|
|
|
relateTask: false,
|
|
|
|
|
taskId: undefined,
|
|
|
|
|
taskCode: undefined,
|
|
|
|
|
taskName: undefined,
|
|
|
|
|
taskDetailIds: undefined,
|
|
|
|
|
packagingSchemeRelationId: undefined,
|
|
|
|
|
packagingSchemeId: undefined,
|
|
|
|
|
packagingSchemeName: undefined,
|
|
|
|
|
packageQuantity: undefined,
|
|
|
|
|
palletPackageQuantity: undefined,
|
|
|
|
|
palletTotalQuantity: undefined,
|
|
|
|
|
pallets: [],
|
|
|
|
|
palletCode: undefined,
|
|
|
|
|
inputUnitType: isProductStockIn.value ? '个' : undefined,
|
|
|
|
|
inputCount: isProductMaterialStockIn.value ? 1 : undefined,
|
|
|
|
|
stockCount: undefined,
|
|
|
|
|
@ -422,6 +635,28 @@ const handleDelete = (index) => {
|
|
|
|
|
formData.value.splice(index, 1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isRowRelatedTask = (row: any) => {
|
|
|
|
|
if (row?.relateTask !== undefined) {
|
|
|
|
|
return row.relateTask === true || row.relateTask === 1 || row.relateTask === '1'
|
|
|
|
|
}
|
|
|
|
|
return row?.relatedTask === true || row?.relatedTask === 1 || row?.relatedTask === '1'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleRelatedTaskChange = (row: any) => {
|
|
|
|
|
row.relatedTask = undefined
|
|
|
|
|
if (isRowRelatedTask(row)) {
|
|
|
|
|
clearProduct(row)
|
|
|
|
|
clearPallet(row)
|
|
|
|
|
row.count = undefined
|
|
|
|
|
row.inputCount = undefined
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
clearTask(row)
|
|
|
|
|
clearPallet(row)
|
|
|
|
|
row.count = isProductMaterialStockIn.value ? undefined : 1
|
|
|
|
|
row.inputCount = isProductMaterialStockIn.value ? 1 : undefined
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 处理产品变更 */
|
|
|
|
|
const onChangeProductCode = (productBarCode, row) => {
|
|
|
|
|
const product = productList.value.find((item) => item.barCode === productBarCode)
|
|
|
|
|
@ -451,6 +686,7 @@ const onChangeProduct = (productId, row) => {
|
|
|
|
|
const fillRowByProduct = (row: any, product: any) => {
|
|
|
|
|
row.productUnitName = product.unitName
|
|
|
|
|
row.productBarCode = product.barCode
|
|
|
|
|
row.productCode = product.barCode
|
|
|
|
|
row.productPrice = product.minPrice
|
|
|
|
|
row.productId = product.id
|
|
|
|
|
row.productName = product.name
|
|
|
|
|
@ -458,9 +694,25 @@ const fillRowByProduct = (row: any, product: any) => {
|
|
|
|
|
row.purchaseUnitName = product.purchaseUnitName
|
|
|
|
|
row.supplierName = getDefaultSupplierName(product)
|
|
|
|
|
row.purchaseUnitConvertQuantity = product.purchaseUnitConvertQuantity
|
|
|
|
|
fillPackagingSchemeByProduct(row, product)
|
|
|
|
|
syncCountByInputCount(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const fillPackagingSchemeByProduct = (row: any, product: any) => {
|
|
|
|
|
const schemes = Array.isArray(product?.packagingSchemes) ? product.packagingSchemes : []
|
|
|
|
|
const defaultSchemeId = product?.defaultPackagingSchemeId
|
|
|
|
|
const scheme =
|
|
|
|
|
schemes.find((item: any) => Number(item?.defaultStatus) === 1) ||
|
|
|
|
|
schemes.find((item: any) => item?.packagingSchemeId === defaultSchemeId || item?.id === defaultSchemeId) ||
|
|
|
|
|
schemes[0]
|
|
|
|
|
row.packagingSchemeRelationId = scheme?.id
|
|
|
|
|
row.packagingSchemeId = scheme?.packagingSchemeId ?? scheme?.id
|
|
|
|
|
row.packagingSchemeName = scheme?.packagingSchemeName ?? scheme?.name
|
|
|
|
|
row.packageQuantity = scheme?.packageQuantity
|
|
|
|
|
row.palletPackageQuantity = scheme?.palletPackageQuantity
|
|
|
|
|
row.palletTotalQuantity = scheme?.palletTotalQuantity
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getDefaultSupplierName = (product: any) => {
|
|
|
|
|
if (!product) return undefined
|
|
|
|
|
if (product.supplierName) return product.supplierName
|
|
|
|
|
@ -471,6 +723,7 @@ const getDefaultSupplierName = (product: any) => {
|
|
|
|
|
const clearProduct = (row: any) => {
|
|
|
|
|
row.productUnitName = undefined
|
|
|
|
|
row.productBarCode = undefined
|
|
|
|
|
row.productCode = undefined
|
|
|
|
|
row.productPrice = undefined
|
|
|
|
|
row.productId = undefined
|
|
|
|
|
row.productName = undefined
|
|
|
|
|
@ -478,6 +731,12 @@ const clearProduct = (row: any) => {
|
|
|
|
|
row.purchaseUnitName = undefined
|
|
|
|
|
row.supplierName = undefined
|
|
|
|
|
row.purchaseUnitConvertQuantity = undefined
|
|
|
|
|
row.packagingSchemeRelationId = undefined
|
|
|
|
|
row.packagingSchemeId = undefined
|
|
|
|
|
row.packagingSchemeName = undefined
|
|
|
|
|
row.packageQuantity = undefined
|
|
|
|
|
row.palletPackageQuantity = undefined
|
|
|
|
|
row.palletTotalQuantity = undefined
|
|
|
|
|
row.inputCount = isProductMaterialStockIn.value ? undefined : row.inputCount
|
|
|
|
|
row.count = isProductMaterialStockIn.value ? undefined : row.count
|
|
|
|
|
}
|
|
|
|
|
@ -520,14 +779,283 @@ const handleProductDialogRowClick = (row: any) => {
|
|
|
|
|
selectedProductId.value = row.id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const confirmProductSelect = () => {
|
|
|
|
|
const confirmProductSelect = async () => {
|
|
|
|
|
const product = productDialogList.value.find((item) => item.id === selectedProductId.value)
|
|
|
|
|
if (!product || !currentSelectRow.value) return
|
|
|
|
|
fillRowByProduct(currentSelectRow.value, product)
|
|
|
|
|
let finalProduct = product
|
|
|
|
|
if (!Array.isArray(product.packagingSchemes)) {
|
|
|
|
|
finalProduct = await ProductApi.getProduct(product.id)
|
|
|
|
|
}
|
|
|
|
|
fillRowByProduct(currentSelectRow.value, finalProduct)
|
|
|
|
|
clearPallet(currentSelectRow.value)
|
|
|
|
|
setStockCount(currentSelectRow.value)
|
|
|
|
|
productDialogVisible.value = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const openTaskSelectDialog = async (row: any) => {
|
|
|
|
|
currentSelectRow.value = row
|
|
|
|
|
selectedTaskId.value = row.taskId
|
|
|
|
|
selectedTaskProductId.value = row.productId
|
|
|
|
|
selectedTaskData.value = undefined
|
|
|
|
|
taskProductDialogList.value = getTaskProductOptions(row)
|
|
|
|
|
taskQueryParams.pageNo = 1
|
|
|
|
|
taskQueryParams.code = undefined
|
|
|
|
|
taskDialogVisible.value = true
|
|
|
|
|
await getTaskDialogList()
|
|
|
|
|
if (row.taskId) {
|
|
|
|
|
await loadTaskProductDialogList({ id: row.taskId, code: row.taskCode } as TaskVO)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getTaskDialogList = async () => {
|
|
|
|
|
taskDialogLoading.value = true
|
|
|
|
|
try {
|
|
|
|
|
const data = await TaskApi.getTaskPage(taskQueryParams)
|
|
|
|
|
taskDialogList.value = data?.list || []
|
|
|
|
|
taskDialogTotal.value = data?.total || 0
|
|
|
|
|
} finally {
|
|
|
|
|
taskDialogLoading.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleTaskDialogQuery = () => {
|
|
|
|
|
taskQueryParams.pageNo = 1
|
|
|
|
|
selectedTaskId.value = undefined
|
|
|
|
|
selectedTaskProductId.value = undefined
|
|
|
|
|
selectedTaskData.value = undefined
|
|
|
|
|
taskProductDialogList.value = []
|
|
|
|
|
getTaskDialogList()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleTaskDialogRowClick = async (row: TaskVO) => {
|
|
|
|
|
selectedTaskId.value = row.id
|
|
|
|
|
selectedTaskProductId.value = undefined
|
|
|
|
|
await loadTaskProductDialogList(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const confirmTaskSelect = async () => {
|
|
|
|
|
const task = taskDialogList.value.find((item) => item.id === selectedTaskId.value)
|
|
|
|
|
|| ({ id: selectedTaskData.value?.taskId, code: selectedTaskData.value?.taskName } as TaskVO)
|
|
|
|
|
const product = taskProductDialogList.value.find((item) => item.productId === selectedTaskProductId.value)
|
|
|
|
|
const data = selectedTaskData.value
|
|
|
|
|
if (!task || !product || !data || !currentSelectRow.value) return
|
|
|
|
|
fillRowByTask(currentSelectRow.value, task, data)
|
|
|
|
|
fillRowByTaskProduct(currentSelectRow.value, product)
|
|
|
|
|
taskDialogVisible.value = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const loadTaskProductDialogList = async (task: TaskVO) => {
|
|
|
|
|
taskSchemeLoading.value = true
|
|
|
|
|
try {
|
|
|
|
|
const data = await TaskApi.getTaskDefaultPackagingSchemes(task.id)
|
|
|
|
|
selectedTaskData.value = data
|
|
|
|
|
taskProductDialogList.value = Array.isArray(data?.products) ? data.products : []
|
|
|
|
|
} finally {
|
|
|
|
|
taskSchemeLoading.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleTaskProductDialogRowClick = (row: any) => {
|
|
|
|
|
selectedTaskProductId.value = row.productId
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const fillRowByTask = (row: any, task: TaskVO, data: any) => {
|
|
|
|
|
const products = Array.isArray(data?.products) ? data.products : []
|
|
|
|
|
row.relateTask = true
|
|
|
|
|
row.relatedTask = undefined
|
|
|
|
|
row.taskId = data?.taskId ?? task.id
|
|
|
|
|
row.taskCode = data?.taskName ?? task.code
|
|
|
|
|
row.taskName = data?.taskName ?? task.code
|
|
|
|
|
setTaskProductOptions(row, products)
|
|
|
|
|
clearTaskProduct(row)
|
|
|
|
|
clearPallet(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getTaskProductOptions = (row: any) => {
|
|
|
|
|
return Array.isArray(row?.taskProducts) ? row.taskProducts : []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const formatTaskSelection = (row: any) => {
|
|
|
|
|
return [row.taskCode, row.productName].filter(Boolean).join(' / ')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setTaskProductOptions = (row: any, products: any[]) => {
|
|
|
|
|
Object.defineProperty(row, 'taskProducts', {
|
|
|
|
|
value: products,
|
|
|
|
|
writable: true,
|
|
|
|
|
configurable: true,
|
|
|
|
|
enumerable: false
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getDefaultTaskProductScheme = (product: any) => {
|
|
|
|
|
const schemes = Array.isArray(product?.packagingSchemes) ? product.packagingSchemes : []
|
|
|
|
|
return schemes.find((item: any) => Number(item?.defaultStatus) === 1) || schemes[0]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const fillRowByTaskProduct = (row: any, product: any) => {
|
|
|
|
|
const scheme = getDefaultTaskProductScheme(product)
|
|
|
|
|
|
|
|
|
|
row.productId = product?.productId
|
|
|
|
|
row.productCode = product?.productCode
|
|
|
|
|
row.productName = product?.productName
|
|
|
|
|
row.productBarCode = product?.productCode
|
|
|
|
|
row.taskDetailIds = product?.taskDetailIds
|
|
|
|
|
row.packagingSchemeRelationId = scheme?.id
|
|
|
|
|
row.packagingSchemeId = scheme?.packagingSchemeId
|
|
|
|
|
row.packagingSchemeName = scheme?.packagingSchemeName
|
|
|
|
|
row.packageQuantity = scheme?.packageQuantity
|
|
|
|
|
row.palletPackageQuantity = scheme?.palletPackageQuantity
|
|
|
|
|
row.palletTotalQuantity = scheme?.palletTotalQuantity
|
|
|
|
|
row.inputCount = scheme?.palletPackageQuantity
|
|
|
|
|
row.count = scheme?.palletTotalQuantity
|
|
|
|
|
clearPallet(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const clearTaskProduct = (row: any) => {
|
|
|
|
|
row.productId = undefined
|
|
|
|
|
row.productCode = undefined
|
|
|
|
|
row.productName = undefined
|
|
|
|
|
row.productBarCode = undefined
|
|
|
|
|
row.taskDetailIds = undefined
|
|
|
|
|
row.packagingSchemeRelationId = undefined
|
|
|
|
|
row.packagingSchemeId = undefined
|
|
|
|
|
row.packagingSchemeName = undefined
|
|
|
|
|
row.packageQuantity = undefined
|
|
|
|
|
row.palletPackageQuantity = undefined
|
|
|
|
|
row.palletTotalQuantity = undefined
|
|
|
|
|
row.inputCount = undefined
|
|
|
|
|
row.count = undefined
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const clearTask = (row: any) => {
|
|
|
|
|
row.taskId = undefined
|
|
|
|
|
row.taskCode = undefined
|
|
|
|
|
row.taskName = undefined
|
|
|
|
|
setTaskProductOptions(row, [])
|
|
|
|
|
clearTaskProduct(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const openPalletSelectDialog = async (row: any) => {
|
|
|
|
|
currentSelectRow.value = row
|
|
|
|
|
selectedPalletRows.value = getInitialSelectedPalletRows(row)
|
|
|
|
|
availablePalletSelection.value = []
|
|
|
|
|
rightPalletSelection.value = []
|
|
|
|
|
palletQueryParams.pageNo = 1
|
|
|
|
|
palletQueryParams.code = undefined
|
|
|
|
|
palletQueryParams.status = undefined
|
|
|
|
|
palletDialogVisible.value = true
|
|
|
|
|
await getPalletDialogList()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getPalletDialogList = async () => {
|
|
|
|
|
palletDialogLoading.value = true
|
|
|
|
|
try {
|
|
|
|
|
const data = await PalletApi.getPalletPage(palletQueryParams)
|
|
|
|
|
palletDialogList.value = data?.list || []
|
|
|
|
|
palletDialogTotal.value = data?.total || 0
|
|
|
|
|
availablePalletSelection.value = []
|
|
|
|
|
availablePalletTableRef.value?.clearSelection()
|
|
|
|
|
} finally {
|
|
|
|
|
palletDialogLoading.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handlePalletDialogQuery = () => {
|
|
|
|
|
palletQueryParams.pageNo = 1
|
|
|
|
|
getPalletDialogList()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleAvailablePalletSelectionChange = (rows: PalletVO[]) => {
|
|
|
|
|
availablePalletSelection.value = rows
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleRightPalletSelectionChange = (rows: any[]) => {
|
|
|
|
|
rightPalletSelection.value = rows
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const toggleAvailablePallet = (row: PalletVO) => {
|
|
|
|
|
availablePalletTableRef.value?.toggleRowSelection(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const toggleRightPallet = (row: any) => {
|
|
|
|
|
rightPalletTableRef.value?.toggleRowSelection(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const addSelectedPallets = () => {
|
|
|
|
|
const row = currentSelectRow.value
|
|
|
|
|
const selectedIds = new Set(selectedPalletRows.value.map((item) => item.id))
|
|
|
|
|
const nextRows = availablePalletSelection.value
|
|
|
|
|
.filter((pallet) => !selectedIds.has(pallet.id))
|
|
|
|
|
.map((pallet) => ({
|
|
|
|
|
...pallet,
|
|
|
|
|
packageCount: getPalletPackageCount(row, pallet)
|
|
|
|
|
}))
|
|
|
|
|
selectedPalletRows.value = [...selectedPalletRows.value, ...nextRows]
|
|
|
|
|
availablePalletSelection.value = []
|
|
|
|
|
availablePalletTableRef.value?.clearSelection()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const removeSelectedPallets = () => {
|
|
|
|
|
const removeIds = new Set(rightPalletSelection.value.map((item) => item.id))
|
|
|
|
|
selectedPalletRows.value = selectedPalletRows.value.filter((item) => !removeIds.has(item.id))
|
|
|
|
|
rightPalletSelection.value = []
|
|
|
|
|
rightPalletTableRef.value?.clearSelection()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const confirmPalletSelect = () => {
|
|
|
|
|
if (!currentSelectRow.value) return
|
|
|
|
|
const row = currentSelectRow.value
|
|
|
|
|
row.pallets = selectedPalletRows.value.map((pallet) => ({
|
|
|
|
|
palletId: pallet.id,
|
|
|
|
|
packageCount: pallet.packageCount
|
|
|
|
|
}))
|
|
|
|
|
row.palletCode = selectedPalletRows.value.map((pallet) => pallet.code).filter(Boolean).join(', ')
|
|
|
|
|
syncCountByPallets(row)
|
|
|
|
|
palletDialogVisible.value = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const clearPallet = (row: any) => {
|
|
|
|
|
row.pallets = []
|
|
|
|
|
row.palletCode = undefined
|
|
|
|
|
if (isProductStockIn.value) {
|
|
|
|
|
row.count = undefined
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getInitialSelectedPalletRows = (row: any) => {
|
|
|
|
|
const palletCodes = String(row?.palletCode || '').split(',').map((item) => item.trim()).filter(Boolean)
|
|
|
|
|
return (row?.pallets || []).map((item: any, index: number) => ({
|
|
|
|
|
id: item.palletId,
|
|
|
|
|
code: item.palletCode || palletCodes[index] || String(item.palletId),
|
|
|
|
|
packageCount: item.packageCount
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getPalletPackageCount = (row: any, pallet: PalletVO) => {
|
|
|
|
|
return pallet.productCount ?? row?.palletPackageQuantity ?? row?.packageQuantity ?? row?.count
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getSelectedPalletItemCount = (pallet: any) => {
|
|
|
|
|
const packageQuantity = Number(currentSelectRow.value?.packageQuantity)
|
|
|
|
|
const packageCount = Number(pallet?.packageCount)
|
|
|
|
|
if (!Number.isFinite(packageQuantity) || !Number.isFinite(packageCount)) return '-'
|
|
|
|
|
return packageQuantity * packageCount
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const syncCountByPallets = (row: any) => {
|
|
|
|
|
const packageQuantity = Number(row?.packageQuantity)
|
|
|
|
|
if (!Array.isArray(row?.pallets) || !Number.isFinite(packageQuantity)) {
|
|
|
|
|
row.count = undefined
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const total = row.pallets.reduce((sum: number, pallet: any) => {
|
|
|
|
|
const packageCount = Number(pallet?.packageCount)
|
|
|
|
|
return Number.isFinite(packageCount) ? sum + packageQuantity * packageCount : sum
|
|
|
|
|
}, 0)
|
|
|
|
|
row.count = total || undefined
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
() => formData.value.map((row) => [row.inputCount, row.purchaseUnitConvertQuantity]),
|
|
|
|
|
() => {
|
|
|
|
|
@ -539,6 +1067,7 @@ watch(
|
|
|
|
|
|
|
|
|
|
const syncCountByInputCount = (row: any) => {
|
|
|
|
|
if (!isProductMaterialStockIn.value) return
|
|
|
|
|
if (isRowRelatedTask(row)) return
|
|
|
|
|
const inputCount = Number(row.inputCount)
|
|
|
|
|
const convertQuantity = Number(row.purchaseUnitConvertQuantity)
|
|
|
|
|
if (!Number.isFinite(inputCount)) {
|
|
|
|
|
@ -585,6 +1114,7 @@ const fillProductNames = (rows: any[]) => {
|
|
|
|
|
if (!product) return
|
|
|
|
|
row.productId = row.productId || product.id
|
|
|
|
|
row.productBarCode = row.productBarCode || product.barCode
|
|
|
|
|
row.productCode = row.productCode || product.barCode
|
|
|
|
|
row.productName = row.productName || product.name
|
|
|
|
|
row.productUnitName = row.productUnitName || product.unitName
|
|
|
|
|
row.productPrice = row.productPrice ?? product.minPrice
|
|
|
|
|
@ -650,4 +1180,71 @@ onMounted(async () => {
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
padding: 12px 0 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.task-product-select {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.task-select-dialog {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.task-select-dialog__section-title {
|
|
|
|
|
color: var(--el-text-color-primary);
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pallet-transfer {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: minmax(520px, 1fr) 72px minmax(420px, 0.85fr);
|
|
|
|
|
gap: 18px;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pallet-transfer__panel {
|
|
|
|
|
min-width: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pallet-transfer__title {
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
color: var(--el-text-color-primary);
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pallet-transfer__actions {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
justify-items: center;
|
|
|
|
|
padding-top: 36px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pallet-transfer__actions :deep(.el-button + .el-button) {
|
|
|
|
|
margin-left: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-task-info {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 2px;
|
|
|
|
|
line-height: 18px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-task-info__item {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: auto 1fr;
|
|
|
|
|
gap: 4px;
|
|
|
|
|
color: var(--el-text-color-secondary);
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-task-info__item strong {
|
|
|
|
|
color: var(--el-text-color-secondary);
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|