feat:出库单据-备件出库-添加出库用途逻辑

main
黄伟杰 7 days ago
parent f59c04387a
commit bd2e645ab3

@ -495,6 +495,12 @@
purchaseUnit: 'Purchase Unit',
purchaseUnitConvertQuantity: 'Purchase Convert Qty',
defaultSupplier: 'Supplier (Default)',
outboundPurpose: 'Outbound Purpose',
relatedOrder: 'Related Order',
relatedRepairOrder: 'Related Repair Order',
relatedMaintainRecord: 'Related Maintenance Record',
selectRelatedRepairOrder: 'Select Repair Order',
selectRelatedMaintainRecord: 'Select Maintenance Record',
inputUnitType: 'Unit Input Type',
inputCount: 'Purchase Unit Quantity',
count: 'Quantity',
@ -511,13 +517,17 @@
placeholderArea: 'Please select area',
placeholderProduct: 'Please select product',
placeholderBarcode: 'Please select barcode',
placeholderOutboundPurpose: 'Please select outbound purpose',
placeholderRelatedRepairOrder: 'Please select related repair order',
placeholderRelatedMaintainRecord: 'Please select related maintenance record',
placeholderInputUnitType: 'Please select',
placeholderCode: 'Please enter code',
placeholderName: 'Please enter name',
validatorWarehouseRequired: 'Warehouse is required',
validatorAreaRequired: 'Please select area',
validatorProductRequired: 'Product is required',
validatorCountRequired: 'Quantity is required'
validatorCountRequired: 'Quantity is required',
stockCountExceededWarning: 'Quantity cannot exceed stock. It has been adjusted to stock quantity.'
},
Check: {
no: 'Check No',

@ -495,6 +495,12 @@
purchaseUnit: '采购单位',
purchaseUnitConvertQuantity: '采购换算数量',
defaultSupplier: '供应商(默认)',
outboundPurpose: '出库用途',
relatedOrder: '关联单据',
relatedRepairOrder: '关联维修单',
relatedMaintainRecord: '关联保养记录',
selectRelatedRepairOrder: '选择维修单',
selectRelatedMaintainRecord: '选择保养记录',
inputUnitType: '单位输入方式',
inputCount: '采购单位数量',
count: '数量',
@ -511,13 +517,17 @@
placeholderArea: '请选择库区',
placeholderProduct: '请选择产品',
placeholderBarcode: '请选择编码',
placeholderOutboundPurpose: '请选择出库用途',
placeholderRelatedRepairOrder: '请选择关联维修单',
placeholderRelatedMaintainRecord: '请选择关联保养记录',
placeholderInputUnitType: '请选择',
placeholderCode: '请输入编码',
placeholderName: '请输入名称',
validatorWarehouseRequired: '仓库不能为空',
validatorAreaRequired: '请选择库区',
validatorProductRequired: '产品不能为空',
validatorCountRequired: '产品数量不能为空'
validatorCountRequired: '产品数量不能为空',
stockCountExceededWarning: '数量不能超出库存,已自动调整为库存数量'
},
Check: {
no: '盘点单号',

@ -232,6 +232,7 @@ export enum DICT_TYPE {
WAREHOUSE_DOCUMENT_OUT_TYPES = 'warehouse_document_out_types', // 出库单据类型
WAREHOUSE_RECEIVING_STATUS = 'warehouse_receiving_status', // 入库状态
WAREHOUSE_OUTBOUND_STATUS = 'Warehouse_outbound_status', // 出库状态
WAREHOUSE_OUTBOUND_PURPOSE = 'warehouse_outbound_purpose', // 出库用途
SUBMOLD_TYPE = 'submold_type', // 子模具类型
ERP_MAINTAIN_TYPE = 'maintain_type',// ERP 保养类型

@ -110,28 +110,83 @@ v-model="row.productId" :options="productCascaderOptions" :props="productCascade
</el-form-item>
</template>
</el-table-column>
<el-table-column v-if="isProductStockOut" :label="t('ErpStock.Item.inputUnitType')" min-width="120">
<el-table-column v-if="isSparePartStockOut" :label="t('ErpStock.Item.outboundPurpose')" min-width="140">
<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-form-item :prop="`${$index}.outUsageType`" class="mb-0px!">
<el-select
v-model="row.outUsageType"
clearable
:placeholder="t('ErpStock.Item.placeholderOutboundPurpose')"
@change="handleOutboundPurposeChange(row)"
>
<el-option
v-for="dict in outboundPurposeOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</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">
<el-table-column
v-if="showRelatedRepairColumn"
:label="t('ErpStock.Item.relatedRepairOrder')"
min-width="190"
>
<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
v-if="isRepairPurpose(row.outUsageType)"
:prop="`${$index}.relatedOrderNo`"
class="mb-0px!"
>
<el-input
v-model="row.relatedOrderNo"
readonly
:placeholder="getRelatedOrderPlaceholder(row.outUsageType)"
>
<template #append>
<el-button @click="openRelatedOrderDialog(row)">
<Icon icon="ep:search" />
</el-button>
</template>
</el-input>
</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
v-if="showRelatedMaintainColumn"
:label="t('ErpStock.Item.relatedMaintainRecord')"
min-width="190"
>
<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-form-item
v-if="isMaintainPurpose(row.outUsageType)"
:prop="`${$index}.relatedMaintenanceNo`"
class="mb-0px!"
>
<el-input
v-model="row.relatedMaintenanceNo"
readonly
:placeholder="getRelatedOrderPlaceholder(row.outUsageType)"
>
<template #append>
<el-button @click="openRelatedOrderDialog(row)">
<Icon icon="ep:search" />
</el-button>
</template>
</el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column v-if="isProductMaterialStockOut" :label="t('ErpStock.Item.count')" prop="inputCount" min-width="140">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.inputCount`" :rules="formRules.inputCount" class="mb-0px!">
<el-input-number
v-model="row.inputCount" controls-position="right" :min="0.001" :precision="3"
class="!w-100%"
@blur="handleInputCountBlur(row)"
/>
</el-form-item>
</template>
</el-table-column>
@ -224,6 +279,103 @@ v-loading="productDialogLoading" :data="productDialogList" row-key="id" :stripe=
<el-button @click="productDialogVisible = false">{{ t('common.cancel') }}</el-button>
</template>
</Dialog>
<Dialog :title="relatedOrderDialogTitle" v-model="relatedOrderDialogVisible" width="1100px">
<el-table
v-loading="relatedOrderLoading"
:data="relatedOrderList"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
@row-click="handleRelatedOrderRowClick"
>
<el-table-column width="55" align="center">
<template #default="{ row }">
<el-radio v-model="selectedRelatedOrderId" :label="row.id">&nbsp;</el-radio>
</template>
</el-table-column>
<template v-if="relatedOrderType === 'repair'">
<el-table-column :label="t('EquipmentManagement.DvRepair.repairCode')" align="center" prop="repairCode" min-width="180" />
<el-table-column :label="t('EquipmentManagement.DvRepair.repairName')" align="center" prop="repairName" min-width="160" />
<el-table-column :label="t('EquipmentManagement.DvRepair.status')" align="center" prop="status" width="110">
<template #default="scope">
<el-tag :type="getRepairStatusTagType(scope.row.status)" effect="light">
{{ getRepairStatusLabel(scope.row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column :label="t('EquipmentManagement.DvRepair.repairStatus')" align="center" prop="repairStatus" min-width="120">
<template #default="scope">
<el-tag :type="getRepairResultTagType(scope.row.repairStatus)" effect="light">
{{ getRepairResultLabel(scope.row.repairStatus) }}
</el-tag>
</template>
</el-table-column>
<el-table-column :label="t('EquipmentManagement.DvRepair.machineryName')" align="center" prop="machineryName" min-width="180" />
<el-table-column :label="t('EquipmentManagement.DvRepair.machineryCode')" align="center" prop="machineryCode" min-width="180" />
<el-table-column :label="t('EquipmentManagement.DvRepair.machinerySpec')" align="center" prop="machinerySpec" min-width="120" />
<el-table-column :label="t('EquipmentManagement.DvRepair.machineryType')" align="center" prop="machineryTypeId" width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_MACHINE_TYPE" :value="scope.row.machineryTypeId" />
</template>
</el-table-column>
<el-table-column :label="t('EquipmentManagement.DvRepair.requireDate')" align="center" prop="requireDate" :formatter="dateFormatter2" width="110" />
<el-table-column :label="t('EquipmentManagement.DvRepair.finishDate')" align="center" prop="finishDate" :formatter="dateFormatter2" width="110" />
<el-table-column :label="t('EquipmentManagement.DvRepair.confirmDate')" align="center" prop="confirmDate" :formatter="dateFormatter2" width="110" />
<el-table-column :label="t('EquipmentManagement.DvRepair.acceptedBy')" align="center" prop="acceptedBy" min-width="150" />
<el-table-column :label="t('EquipmentManagement.DvRepair.confirmBy')" align="center" prop="confirmBy" min-width="150" />
<el-table-column :label="t('EquipmentManagement.DvRepair.createTime')" align="center" prop="createTime" :formatter="dateFormatter" width="170" />
</template>
<template v-else>
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.planNo')" align="center" prop="planNo" min-width="160" />
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.deviceName')" align="center" prop="deviceName" min-width="160" />
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.planType')" align="center" prop="planType" width="90">
<template #default="scope">
<el-tag v-if="String(scope.row.planType) === '1'" type="primary">
{{ t('EquipmentManagement.WorkOrderManagement.planTypeInspect') }}
</el-tag>
<el-tag v-else-if="String(scope.row.planType) === '2'" type="success">
{{ t('EquipmentManagement.WorkOrderManagement.planTypeMaintain') }}
</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.configName')" align="center" prop="configName" min-width="160" />
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.jobStatus')" align="center" prop="jobStatus" width="120">
<template #default="scope">
<dict-tag :type="'job_status'" :value="scope.row.jobStatus" />
</template>
</el-table-column>
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.operatorName')" align="center" prop="operatorName" width="140" />
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.taskTime')" align="center" prop="taskTime" :formatter="dateFormatter" width="180" />
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.taskEndTime')" align="center" prop="taskEndTime" :formatter="dateFormatter" width="180" />
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.jobResult')" align="center" prop="jobResult" width="90">
<template #default="scope">
<el-tag v-if="scope.row.jobResult == '1'" type="success">
{{ t('EquipmentManagement.WorkOrderManagement.jobResultOk') }}
</el-tag>
<el-tag v-else-if="scope.row.jobResult == '2'" type="danger">
{{ t('EquipmentManagement.WorkOrderManagement.jobResultNg') }}
</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="t('EquipmentManagement.WorkOrderManagement.createTime')" align="center" prop="createTime" :formatter="dateFormatter" width="180" />
</template>
</el-table>
<div class="product-dialog-pagination">
<Pagination
:total="relatedOrderTotal"
v-model:page="relatedOrderQueryParams.pageNo"
v-model:limit="relatedOrderQueryParams.pageSize"
@pagination="getRelatedOrderList"
/>
</div>
<template #footer>
<el-button type="primary" @click="confirmRelatedOrderSelect">{{ t('common.ok') }}</el-button>
<el-button @click="relatedOrderDialogVisible = false">{{ t('common.cancel') }}</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { Icon } from '@/components/Icon'
@ -231,6 +383,10 @@ 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 { DvRepairApi } from '@/api/mes/dvrepair'
import { TicketManagementApi } from '@/api/mes/ticketManagement'
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
@ -246,10 +402,12 @@ const props = defineProps<{
const formLoading = ref(false) //
const formData = ref([])
const { t } = useI18n()
const message = useMessage()
const formRules = reactive({
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' }],
inputCount: [{ required: true, message: t('ErpStock.Item.validatorCountRequired'), trigger: 'blur' }],
count: [{ required: true, message: t('ErpStock.Item.validatorCountRequired'), trigger: 'blur' }]
})
const formRef = ref([]) // Ref
@ -257,7 +415,6 @@ const productList = ref<ProductVO[]>([]) // 产品列表
const warehouseList = ref<WarehouseVO[]>([]) //
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
@ -269,6 +426,8 @@ const activeCategoryType = computed(() => resolveStockOutCategoryType(props.outT
const isProductMaterialStockOut = computed(() => Boolean(activeCategoryType.value))
const isProductStockOut = computed(() => activeCategoryType.value === 1)
const isPurchaseUnitStockOut = computed(() => activeCategoryType.value === 2 || activeCategoryType.value === 3)
const isSparePartStockOut = computed(() => activeCategoryType.value === 3)
const outboundPurposeOptions = computed(() => getStrDictOptions(DICT_TYPE.WAREHOUSE_OUTBOUND_PURPOSE))
const purchaseUnitConvertTipText = computed(() => t('FactoryModeling.ProductInformation.dialogPurchaseUnitConvertTip'))
const productDialogVisible = ref(false)
const productDialogLoading = ref(false)
@ -283,6 +442,31 @@ const productQueryParams = reactive({
})
const currentSelectRow = ref<any>()
const selectedProductId = ref<number>()
const RELATED_PURPOSE_REPAIR = '1'
const RELATED_PURPOSE_MAINTAIN = '2'
const relatedOrderDialogVisible = ref(false)
const relatedOrderLoading = ref(false)
const relatedOrderType = ref<'repair' | 'maintain'>('repair')
const relatedOrderList = ref<any[]>([])
const relatedOrderTotal = ref(0)
const currentRelatedRow = ref<any>()
const selectedRelatedOrderId = ref<number>()
const repairCodeCache = new Map<number | string, string>()
const relatedOrderQueryParams = reactive({
pageNo: 1,
pageSize: 10
})
const relatedOrderDialogTitle = computed(() =>
relatedOrderType.value === 'repair'
? t('ErpStock.Item.selectRelatedRepairOrder')
: t('ErpStock.Item.selectRelatedMaintainRecord')
)
const showRelatedRepairColumn = computed(
() => isSparePartStockOut.value && formData.value.some((row) => isRepairPurpose(row.outUsageType))
)
const showRelatedMaintainColumn = computed(
() => isSparePartStockOut.value && formData.value.some((row) => isMaintainPurpose(row.outUsageType))
)
const productCascaderProps = {
emitPath: false,
@ -319,6 +503,8 @@ watch(
() => props.items,
async (val) => {
formData.value = val || []
normalizeRows(formData.value)
await fillRelatedRepairCodes(formData.value)
fillProductNames(formData.value)
if (isProductMaterialStockOut.value) {
await loadRowsWarehouseAreas(formData.value)
@ -332,6 +518,7 @@ watch(
async () => {
if (isProductMaterialStockOut.value) {
formData.value.forEach((row) => {
normalizeRow(row)
row.inputCount = row.inputCount ?? row.count ?? 1
if (isProductStockOut.value) {
row.inputUnitType = row.inputUnitType || '个'
@ -367,10 +554,12 @@ const getSummaries = (param: SummaryMethodProps) => {
sums[index] = t('common.total')
return
}
if (['count', 'totalPrice'].includes(column.property)) {
if (['inputCount', 'count', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] =
column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
column.property === 'inputCount' || column.property === 'count'
? erpCountInputFormatter(sum)
: erpPriceInputFormatter(sum)
} else {
sums[index] = ''
}
@ -398,6 +587,15 @@ const handleAdd = () => {
inputCount: isProductMaterialStockOut.value ? 1 : undefined,
stockCount: undefined,
count: isProductMaterialStockOut.value ? undefined : 1,
outUsageType: undefined,
repairId: undefined,
repairDeviceId: undefined,
maintenanceId: undefined,
relatedOrderNo: undefined,
relatedOrderName: undefined,
relatedMaintenanceNo: undefined,
relatedMaintenanceName: undefined,
relatedOrderType: undefined,
totalPrice: undefined,
remark: undefined
}
@ -459,6 +657,57 @@ const getDefaultSupplierName = (product: any) => {
return suppliers.find((item) => Number(item?.defaultStatus) === 1)?.supplierName
}
const normalizeRows = (rows: any[]) => {
;(rows || []).forEach(normalizeRow)
}
const normalizeRow = (row: any) => {
if (!row) return
if (row.outUsageType !== undefined && row.outUsageType !== null) {
row.outUsageType = String(row.outUsageType)
}
row.inputCount = row.inputCount ?? row.count
if (row.repairId) {
row.relatedOrderNo = row.relatedOrderNo || row.repairCode || row.repairNo || String(row.repairId)
row.relatedOrderName = row.relatedOrderName || row.repairName
row.relatedOrderType = row.relatedOrderType || 'repair'
}
if (row.maintenanceId) {
row.relatedMaintenanceNo =
row.relatedMaintenanceNo ||
row.maintenanceCode ||
row.maintenanceNo ||
row.planNo ||
row.maintenanceName ||
String(row.maintenanceId)
row.relatedMaintenanceName = row.relatedMaintenanceName || row.maintenanceName
row.relatedOrderType = row.relatedOrderType || 'maintain'
}
}
const fillRelatedRepairCodes = async (rows: any[]) => {
const repairRows = (rows || []).filter((row) => row?.repairId)
await Promise.all(
repairRows.map(async (row) => {
const repairId = row.repairId
let repairCode = repairCodeCache.get(repairId)
if (!repairCode) {
try {
const repair = await DvRepairApi.getDvRepair(repairId)
repairCode = repair?.repairCode
if (repairCode) {
repairCodeCache.set(repairId, repairCode)
}
row.repairDeviceId = row.repairDeviceId ?? repair?.machineryId
} catch {
repairCode = undefined
}
}
row.relatedOrderNo = repairCode || row.repairCode || row.repairNo || String(repairId)
})
)
}
const clearProduct = (row: any) => {
row.productUnitName = undefined
row.productBarCode = undefined
@ -519,6 +768,118 @@ const confirmProductSelect = () => {
productDialogVisible.value = false
}
const isRepairPurpose = (purpose: any) => String(purpose ?? '') === RELATED_PURPOSE_REPAIR
const isMaintainPurpose = (purpose: any) => String(purpose ?? '') === RELATED_PURPOSE_MAINTAIN
const isRelatedPurpose = (purpose: any) => {
const value = String(purpose ?? '')
return value === RELATED_PURPOSE_REPAIR || value === RELATED_PURPOSE_MAINTAIN
}
const clearRelatedOrder = (row: any) => {
row.repairId = undefined
row.repairDeviceId = undefined
row.maintenanceId = undefined
row.relatedOrderNo = undefined
row.relatedOrderName = undefined
row.relatedMaintenanceNo = undefined
row.relatedMaintenanceName = undefined
row.relatedOrderType = undefined
}
const handleOutboundPurposeChange = (row: any) => {
clearRelatedOrder(row)
}
const getRelatedOrderPlaceholder = (purpose: any) => {
return String(purpose ?? '') === RELATED_PURPOSE_REPAIR
? t('ErpStock.Item.placeholderRelatedRepairOrder')
: t('ErpStock.Item.placeholderRelatedMaintainRecord')
}
const openRelatedOrderDialog = async (row: any) => {
const purpose = String(row.outUsageType ?? '')
if (!isRelatedPurpose(purpose)) return
currentRelatedRow.value = row
relatedOrderType.value = purpose === RELATED_PURPOSE_REPAIR ? 'repair' : 'maintain'
selectedRelatedOrderId.value =
relatedOrderType.value === 'repair' ? row.repairId : row.maintenanceId
relatedOrderQueryParams.pageNo = 1
relatedOrderDialogVisible.value = true
await getRelatedOrderList()
}
const getRelatedOrderList = async () => {
relatedOrderLoading.value = true
try {
if (relatedOrderType.value === 'repair') {
const data = await DvRepairApi.getDvRepairPage(relatedOrderQueryParams)
relatedOrderList.value = data?.list || []
relatedOrderTotal.value = data?.total || 0
return
}
const data = await TicketManagementApi.getTicketManagementPage({
...relatedOrderQueryParams,
planType: 2
})
relatedOrderList.value = data?.list || []
relatedOrderTotal.value = data?.total || 0
} finally {
relatedOrderLoading.value = false
}
}
const handleRelatedOrderRowClick = (row: any) => {
selectedRelatedOrderId.value = row.id
}
const confirmRelatedOrderSelect = () => {
const selected = relatedOrderList.value.find((item) => item.id === selectedRelatedOrderId.value)
if (!selected || !currentRelatedRow.value) return
if (relatedOrderType.value === 'repair') {
currentRelatedRow.value.repairId = selected.id
currentRelatedRow.value.repairDeviceId = selected.machineryId
currentRelatedRow.value.relatedOrderNo = selected.repairCode
currentRelatedRow.value.relatedOrderName = selected.repairName
} else {
currentRelatedRow.value.maintenanceId = selected.id
currentRelatedRow.value.relatedMaintenanceNo = selected.planNo
currentRelatedRow.value.relatedMaintenanceName = selected.configName
}
currentRelatedRow.value.relatedOrderType = relatedOrderType.value
relatedOrderDialogVisible.value = false
}
const getRepairStatusLabel = (value: any) => {
const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (v === '0') return t('EquipmentManagement.DvRepair.statusPending')
if (v === '1') return t('EquipmentManagement.DvRepair.statusFinished')
return '-'
}
const getRepairStatusTagType = (value: any) => {
const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (v === '1') return 'success'
if (v === '0') return 'warning'
return 'info'
}
const getRepairResultLabel = (value: any) => {
const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (v == '0') return t('EquipmentManagement.DvRepair.repairResultPending')
if (v == '1') return t('EquipmentManagement.DvRepair.repairResultOk')
if (v == '2') return t('EquipmentManagement.DvRepair.repairResultNg')
return '-'
}
const getRepairResultTagType = (value: any) => {
const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (v == '1') return 'success'
if (v == '2') return 'danger'
if (v == '0') return 'info'
return 'info'
}
watch(
() => formData.value.map((row) => [row.inputCount, row.purchaseUnitConvertQuantity]),
() => {
@ -543,6 +904,17 @@ const syncCountByInputCount = (row: any) => {
row.count = Number.isFinite(convertQuantity) ? inputCount * convertQuantity : inputCount
}
const handleInputCountBlur = (row: any) => {
if (!isProductMaterialStockOut.value) return
const inputCount = Number(row.inputCount)
const stockCount = Number(row.stockCount)
if (!Number.isFinite(inputCount) || !Number.isFinite(stockCount)) return
if (inputCount <= stockCount) return
row.inputCount = stockCount
syncCountByInputCount(row)
message.warning(t('ErpStock.Item.stockCountExceededWarning'))
}
const loadWarehouseAreas = async (warehouseId: number) => {
if (!warehouseId || warehouseAreaMap.value[warehouseId]) return
const data = await WarehouseAreaApi.getWarehouseAreaPage({

@ -3,94 +3,41 @@
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="auto"
>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="auto">
<el-form-item :label="t('ErpStock.Record.product')" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
:placeholder="t('ErpStock.Record.placeholderProduct')"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
<el-select v-model="queryParams.productId" clearable filterable
:placeholder="t('ErpStock.Record.placeholderProduct')" class="!w-240px">
<el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item :label="t('ErpStock.Record.warehouse')" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
:placeholder="t('ErpStock.Record.placeholderWarehouse')"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
<el-select v-model="queryParams.warehouseId" clearable filterable
:placeholder="t('ErpStock.Record.placeholderWarehouse')" class="!w-240px">
<el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item :label="t('ErpStock.Record.materialCategory')" prop="categoryType">
<el-select
v-model="queryParams.categoryType"
clearable
:placeholder="t('ErpStock.Record.placeholderMaterialCategory')"
class="!w-240px"
>
<el-option
v-for="item in categoryTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-select v-model="queryParams.categoryType" clearable
:placeholder="t('ErpStock.Record.placeholderMaterialCategory')" class="!w-240px">
<el-option v-for="item in categoryTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item :label="t('ErpStock.Record.bizNo')" prop="bizNo" v-show="showAllFilters">
<el-input v-model="queryParams.bizNo" :placeholder="t('ErpStock.Record.placeholderBizNo')" clearable
@keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item :label="t('ErpStock.Record.bizType')" prop="bizType">
<el-select
v-model="queryParams.bizType"
:placeholder="t('ErpStock.Record.placeholderBizType')"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_STOCK_RECORD_BIZ_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-select v-model="queryParams.bizType" :placeholder="t('ErpStock.Record.placeholderBizType')" clearable
class="!w-240px">
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.ERP_STOCK_RECORD_BIZ_TYPE)" :key="dict.value"
:label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item :label="t('ErpStock.Record.bizNo')" prop="bizNo" v-show="showAllFilters">
<el-input
v-model="queryParams.bizNo"
:placeholder="t('ErpStock.Record.placeholderBizNo')"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item :label="t('common.createTime')" prop="createTime" v-show="showAllFilters">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
:start-placeholder="t('ErpStock.Record.placeholderCreateTimeStart')"
:end-placeholder="t('ErpStock.Record.placeholderCreateTimeEnd')"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-220px" />
</el-form-item>
<el-form-item v-if="filterCount > 3">
<el-button type="text" class="text-primary" @click="toggleFilters">
@ -100,23 +47,17 @@
</el-button>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> {{ t('common.query') }}</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> {{ t('common.reset') }}</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:stock-record:create']"
>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> {{ t('common.query') }}
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> {{ t('common.reset') }}
</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:stock-record:create']">
<Icon icon="ep:plus" class="mr-5px" /> {{ t('common.add') }}
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:stock-record:export']"
>
<el-button type="success" plain @click="handleExport" :loading="exportLoading"
v-hasPermi="['erp:stock-record:export']">
<Icon icon="ep:download" class="mr-5px" /> {{ t('action.export') }}
</el-button>
</el-form-item>
@ -125,17 +66,12 @@
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
@selection-change="handleSelectionChange"
>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id"
@selection-change="handleSelectionChange">
<el-table-column width="30" :label="t('action.select')" type="selection" />
<el-table-column :label="t('ErpStock.Record.id')" align="center" prop="id" width="100" sortable />
<el-table-column :label="t('ErpStock.Record.bizDirection')" align="center" prop="bizDirection" min-width="90" sortable>
<el-table-column :label="t('ErpStock.Record.bizNo')" align="center" prop="bizNo" min-width="180" sortable />
<el-table-column :label="t('ErpStock.Record.bizDirection')" align="center" prop="bizDirection" min-width="90"
sortable>
<template #default="scope">
<el-tag v-if="scope.row.bizDirection" :type="getDirectionTagType(scope.row.bizDirection)">
{{ scope.row.bizDirection || '-' }}
@ -143,58 +79,42 @@
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="t('ErpStock.Record.categoryType')" align="center" prop="bizDocType" min-width="120" sortable />
<el-table-column :label="t('ErpStock.Record.productName')" align="center" sortable prop="productName" min-width="160" />
<el-table-column :label="t('ErpStock.Record.materialCategory')" align="center" prop="categoryType" min-width="120" sortable>
<el-table-column :label="t('ErpStock.Record.categoryType')" align="center" prop="bizDocType" min-width="120"
sortable />
<el-table-column :label="t('ErpStock.Record.productName')" align="center" sortable prop="productName"
min-width="160" />
<el-table-column :label="t('ErpStock.Record.materialCategory')" align="center" prop="categoryType" min-width="120"
sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE" :value="scope.row.categoryType" />
</template>
</el-table-column>
<el-table-column :label="t('ErpStock.Record.categoryName')" align="center" prop="categoryName" min-width="120" sortable />
<el-table-column :label="t('ErpStock.Record.warehouseName')" align="center" prop="warehouseName" min-width="140" sortable />
<el-table-column :label="t('ErpStock.Record.categoryName')" align="center" prop="categoryName" min-width="120"
sortable />
<el-table-column :label="t('ErpStock.Record.warehouseName')" align="center" prop="warehouseName" min-width="140"
sortable />
<el-table-column :label="t('ErpStock.Record.areaName')" align="center" prop="areaName" min-width="120" sortable />
<el-table-column
:label="t('ErpStock.Record.count')"
align="center"
sortable
prop="count"
min-width="120"
>
<el-table-column :label="t('ErpStock.Record.count')" align="center" sortable prop="count" min-width="120">
<template #default="scope">
<span :class="getDirectionClass(scope.row.bizDirection)">
{{ formatCountWithUnit(scope.row, true) }}
</span>
</template>
</el-table-column>
<el-table-column
:label="t('ErpStock.Record.totalCount')"
align="center"
sortable
prop="totalCount"
min-width="120"
>
<el-table-column :label="t('ErpStock.Record.totalCount')" align="center" sortable prop="totalCount"
min-width="120">
<template #default="scope">
{{ formatCountWithUnit(scope.row) }}
</template>
</el-table-column>
<el-table-column :label="t('ErpStock.Record.bizNo')" align="center" prop="bizNo" min-width="180" sortable />
<el-table-column :label="t('ErpStock.Record.creatorName')" align="center" prop="creatorName" min-width="100" sortable />
<el-table-column
:label="t('ErpStock.Record.recordTime')"
align="center"
sortable
prop="recordTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column :label="t('ErpStock.Record.creatorName')" align="center" prop="creatorName" min-width="100"
sortable />
<el-table-column :label="t('ErpStock.Record.recordTime')" align="center" sortable prop="recordTime"
:formatter="dateFormatter" width="180px" />
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
</template>
@ -328,7 +248,7 @@ const handleDelete = async (id: number) => {
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
} catch { }
}
/** 导出按钮操作 */

Loading…
Cancel
Save