feat(select): 增加批次和仓库过滤功能,优化库存选择器

pull/871/MERGE
YunaiV 2026-04-08 09:56:32 +08:00
parent 606a9ed6e8
commit 55cb175f5a
12 changed files with 105 additions and 31 deletions

View File

@ -12,6 +12,7 @@ export interface WmMaterialStockVO {
batchId: number batchId: number
batchCode: string batchCode: string
warehouseId: number warehouseId: number
warehouseCode: string
warehouseName: string warehouseName: string
locationId: number locationId: number
locationName: string locationName: string

View File

@ -1,8 +1,6 @@
<!-- <!--
MES 生产任务弹窗选择器支持单选/多选 MES 生产任务弹窗选择器支持单选/多选
搜索字段展示字段对齐 KTG TaskSelect
Props: Props:
multiple true 多选checkboxfalse 单选radio默认 true multiple true 多选checkboxfalse 单选radio默认 true
Events: Events:

View File

@ -1,8 +1,6 @@
<!-- <!--
MES 质检指标弹窗选择器支持单选/多选 MES 质检指标弹窗选择器支持单选/多选
搜索字段展示字段对齐 KTG qcindexSelect/single.vue
Props: Props:
multiple true 多选checkboxfalse 单选radio默认 true multiple true 多选checkboxfalse 单选radio默认 true
Events: Events:

View File

@ -1,9 +1,6 @@
<!-- <!--
MES 到货通知单行弹窗选择器单选模式 MES 到货通知单行弹窗选择器单选模式
对齐 KTG noticeSelect/lineSingle.vue
展示字段物料编码物料名称规格型号单位到货数量是否检验合格数量检验单号备注
Props: Props:
noticeId 到货通知单编号必传按此筛选行数据 noticeId 到货通知单编号必传按此筛选行数据
Events: Events:

View File

@ -3,10 +3,13 @@
交互显示为只读 el-input点击打开弹窗单选模式进行选择 交互显示为只读 el-input点击打开弹窗单选模式进行选择
Props: Props:
modelValue 绑定的批次 IDv-model modelValue 绑定的批次 IDv-model
itemId 默认过滤的物料 ID打开弹窗时预设物料过滤条件 itemId 默认过滤的物料 ID打开弹窗时预设物料过滤条件
disabled 是否禁用 clientId 默认过滤的客户 ID
clearable 是否允许清空鼠标悬停时显示清除图标 vendorId 默认过滤的供应商 ID
salesOrderCode 默认过滤的销售订单编号
disabled 是否禁用
clearable 是否允许清空鼠标悬停时显示清除图标
placeholder 占位文字 placeholder 占位文字
Events: Events:
update:modelValue v-model 更新 update:modelValue v-model 更新
@ -61,6 +64,7 @@ const props = withDefaults(
itemId?: number // ID itemId?: number // ID
clientId?: number // ID clientId?: number // ID
vendorId?: number // ID vendorId?: number // ID
salesOrderCode?: string //
disabled?: boolean // disabled?: boolean //
clearable?: boolean // clearable?: boolean //
placeholder?: string // placeholder?: string //
@ -141,7 +145,7 @@ const handleClick = (e: MouseEvent) => {
} }
// ID itemId // ID itemId
const selectedIds = props.modelValue != null ? [props.modelValue] : [] const selectedIds = props.modelValue != null ? [props.modelValue] : []
dialogRef.value.open(selectedIds, props.itemId, props.clientId, props.vendorId) dialogRef.value.open(selectedIds, props.itemId, props.clientId, props.vendorId, props.salesOrderCode)
} }
/** 弹窗选中回调 */ /** 弹窗选中回调 */

View File

@ -13,7 +13,7 @@
<Dialog title="批次选择" v-model="dialogVisible" width="75%"> <Dialog title="批次选择" v-model="dialogVisible" width="75%">
<ContentWrap> <ContentWrap>
<el-alert <el-alert
v-if="externalClientId != null || externalVendorId != null" v-if="showAlert"
:title="alertTitle" :title="alertTitle"
type="info" type="info"
:closable="false" :closable="false"
@ -402,7 +402,7 @@ const resetQuery = () => {
queryParams.workstationId = undefined queryParams.workstationId = undefined
queryParams.toolId = undefined queryParams.toolId = undefined
queryParams.moldId = undefined queryParams.moldId = undefined
queryParams.salesOrderCode = undefined queryParams.salesOrderCode = externalSalesOrderCode.value
queryParams.purchaseOrderCode = undefined queryParams.purchaseOrderCode = undefined
queryParams.lotNumber = undefined queryParams.lotNumber = undefined
queryParams.qualityStatus = undefined queryParams.qualityStatus = undefined
@ -432,31 +432,51 @@ const confirmSelect = () => {
const externalClientId = ref<number | undefined>() // clientId const externalClientId = ref<number | undefined>() // clientId
const externalVendorId = ref<number | undefined>() // vendorId const externalVendorId = ref<number | undefined>() // vendorId
const externalSalesOrderCode = ref<string | undefined>() // salesOrderCode
/** 拼装 el-alert 提示文字 */ /** 拼装 el-alert 提示文字 */
const alertTitle = computed(() => { const alertTitle = computed(() => {
const parts: string[] = [] const parts: string[] = []
if (externalClientId.value != null) parts.push('客户') if (externalClientId.value != null) {
if (externalVendorId.value != null) parts.push('供应商') parts.push('客户')
}
if (externalVendorId.value != null) {
parts.push('供应商')
}
if (externalSalesOrderCode.value != null) {
parts.push('销售订单')
}
return `已按${parts.join('/')}预过滤` return `已按${parts.join('/')}预过滤`
}) })
/** 是否显示 alert 提示 */
const showAlert = computed(() => {
return (
externalClientId.value != null ||
externalVendorId.value != null ||
externalSalesOrderCode.value != null
)
})
/** /**
* 打开弹窗 * 打开弹窗
* @param selectedIds 已选 ID用于预选高亮 * @param selectedIds 已选 ID用于预选高亮
* @param itemId 默认过滤的物料 ID * @param itemId 默认过滤的物料 ID
* @param clientId 默认过滤的客户 ID * @param clientId 默认过滤的客户 ID
* @param vendorId 默认过滤的供应商 ID * @param vendorId 默认过滤的供应商 ID
* @param salesOrderCode 默认过滤的销售订单编号
*/ */
const open = async ( const open = async (
selectedIds?: number[], selectedIds?: number[],
itemId?: number, itemId?: number,
clientId?: number, clientId?: number,
vendorId?: number vendorId?: number,
salesOrderCode?: string
) => { ) => {
dialogVisible.value = true dialogVisible.value = true
externalClientId.value = clientId externalClientId.value = clientId
externalVendorId.value = vendorId externalVendorId.value = vendorId
externalSalesOrderCode.value = salesOrderCode
// + // +
queryParams.code = undefined queryParams.code = undefined
queryParams.itemId = itemId ?? undefined queryParams.itemId = itemId ?? undefined
@ -467,7 +487,7 @@ const open = async (
queryParams.workstationId = undefined queryParams.workstationId = undefined
queryParams.toolId = undefined queryParams.toolId = undefined
queryParams.moldId = undefined queryParams.moldId = undefined
queryParams.salesOrderCode = undefined queryParams.salesOrderCode = salesOrderCode ?? undefined
queryParams.purchaseOrderCode = undefined queryParams.purchaseOrderCode = undefined
queryParams.lotNumber = undefined queryParams.lotNumber = undefined
queryParams.qualityStatus = undefined queryParams.qualityStatus = undefined

View File

@ -3,11 +3,14 @@
交互显示为只读 el-input点击打开弹窗单选模式进行选择 交互显示为只读 el-input点击打开弹窗单选模式进行选择
Props: Props:
modelValue 绑定的库存 IDv-model modelValue 绑定的库存 IDv-model
itemId 按物料 ID 过滤库存可选透传给弹窗 itemId 按物料 ID 过滤库存可选透传给弹窗
disabled 是否禁用 batchId 按批次 ID 过滤库存可选透传给弹窗
clearable 是否允许清空鼠标悬停时显示清除图标 warehouseId 按仓库 ID 过滤库存可选透传给弹窗
placeholder 占位文字 excludeVirtual 是否排除虚拟线边仓库存默认 true
disabled 是否禁用
clearable 是否允许清空鼠标悬停时显示清除图标
placeholder 占位文字
Events: Events:
update:modelValue v-model 更新 update:modelValue v-model 更新
change(item) 选中库存变化时触发传递完整 WmMaterialStockVO清空时为 undefined change(item) 选中库存变化时触发传递完整 WmMaterialStockVO清空时为 undefined
@ -47,6 +50,9 @@
ref="dialogRef" ref="dialogRef"
:multiple="false" :multiple="false"
:item-id="itemId" :item-id="itemId"
:batch-id="batchId"
:warehouse-id="warehouseId"
:exclude-virtual="excludeVirtual"
@selected="handleSelected" @selected="handleSelected"
/> />
</template> </template>
@ -66,11 +72,15 @@ const props = withDefaults(
defineProps<{ defineProps<{
modelValue?: number // ID modelValue?: number // ID
itemId?: number // ID itemId?: number // ID
batchId?: number // ID
warehouseId?: number // ID
excludeVirtual?: boolean // 线 true
disabled?: boolean // disabled?: boolean //
clearable?: boolean // clearable?: boolean //
placeholder?: string // placeholder?: string //
}>(), }>(),
{ {
excludeVirtual: true,
disabled: false, disabled: false,
clearable: true, clearable: true,
placeholder: '请选择库存' placeholder: '请选择库存'

View File

@ -2,8 +2,11 @@
MES 库存弹窗选择器支持单选/多选 MES 库存弹窗选择器支持单选/多选
Props: Props:
multiple true 多选checkboxfalse 单选radio默认 true multiple true 多选checkboxfalse 单选radio默认 true
itemId 按物料 ID 过滤库存可选 itemId 按物料 ID 过滤库存可选
batchId 按批次 ID 过滤库存可选
warehouseId 按仓库 ID 过滤库存可选
excludeVirtual 是否排除虚拟线边仓库存默认 true
Events: Events:
selected(rows: WmMaterialStockVO[]) 确认选择后触发单选时数组长度为 1 selected(rows: WmMaterialStockVO[]) 确认选择后触发单选时数组长度为 1
Expose: Expose:
@ -20,8 +23,16 @@
</el-col> </el-col>
<!-- 右侧搜索 + 表格 --> <!-- 右侧搜索 + 表格 -->
<el-col :span="20" :xs="24"> <el-col :span="20" :xs="24">
<!-- 搜索 --> <!-- 预过滤提示 -->
<ContentWrap> <ContentWrap>
<el-alert
v-if="showAlert"
:title="alertTitle"
type="info"
:closable="false"
show-icon
class="!mb-10px"
/>
<el-form :inline="true" :model="queryParams" label-width="68px"> <el-form :inline="true" :model="queryParams" label-width="68px">
<el-form-item label="物料"> <el-form-item label="物料">
<MdItemSelect v-model="queryParams.itemId" class="!w-220px" /> <MdItemSelect v-model="queryParams.itemId" class="!w-220px" />
@ -155,9 +166,13 @@ const props = withDefaults(
defineProps<{ defineProps<{
multiple?: boolean // true checkboxfalse radio multiple?: boolean // true checkboxfalse radio
itemId?: number // ID itemId?: number // ID
batchId?: number // ID
warehouseId?: number // ID
excludeVirtual?: boolean // 线 true
}>(), }>(),
{ {
multiple: true multiple: true,
excludeVirtual: true
} }
) )
@ -227,6 +242,7 @@ const queryParams = reactive({
itemId: undefined as number | undefined, // itemId: undefined as number | undefined, //
vendorId: undefined as number | undefined, // vendorId: undefined as number | undefined, //
batchCode: undefined as string | undefined, // batchCode: undefined as string | undefined, //
batchId: undefined as number | undefined, // ID
warehouseId: undefined as number | undefined, // warehouseId: undefined as number | undefined, //
locationId: undefined as number | undefined, // locationId: undefined as number | undefined, //
areaId: undefined as number | undefined, // areaId: undefined as number | undefined, //
@ -249,7 +265,14 @@ const getList = async () => {
loading.value = true loading.value = true
try { try {
const data = await WmMaterialStockApi.getMaterialStockPage(queryParams) const data = await WmMaterialStockApi.getMaterialStockPage(queryParams)
list.value = data.list // 线 warehouseCode WIP_VIRTUAL
if (props.excludeVirtual) {
list.value = data.list.filter(
(row: WmMaterialStockVO) => !row.warehouseCode?.includes('WIP_VIRTUAL')
)
} else {
list.value = data.list
}
total.value = data.total total.value = data.total
await nextTick() await nextTick()
applyPreSelection() applyPreSelection()
@ -294,7 +317,8 @@ const resetQuery = () => {
queryParams.itemId = props.itemId // props queryParams.itemId = props.itemId // props
queryParams.vendorId = undefined queryParams.vendorId = undefined
queryParams.batchCode = undefined queryParams.batchCode = undefined
queryParams.warehouseId = undefined queryParams.batchId = props.batchId // props
queryParams.warehouseId = props.warehouseId // props
queryParams.locationId = undefined queryParams.locationId = undefined
queryParams.areaId = undefined queryParams.areaId = undefined
typeTreeRef.value?.reset() typeTreeRef.value?.reset()
@ -328,12 +352,13 @@ const open = async (selectedIds?: number[]) => {
queryParams.itemTypeId = undefined queryParams.itemTypeId = undefined
queryParams.vendorId = undefined queryParams.vendorId = undefined
queryParams.batchCode = undefined queryParams.batchCode = undefined
queryParams.warehouseId = undefined
queryParams.locationId = undefined queryParams.locationId = undefined
queryParams.areaId = undefined queryParams.areaId = undefined
queryParams.pageNo = 1 queryParams.pageNo = 1
// itemId props // props
queryParams.itemId = props.itemId queryParams.itemId = props.itemId
queryParams.batchId = props.batchId
queryParams.warehouseId = props.warehouseId
// //
queryParams.frozen = false queryParams.frozen = false
// + // +
@ -349,6 +374,22 @@ const open = async (selectedIds?: number[]) => {
await getList() await getList()
} }
defineExpose({ open }) defineExpose({ open })
// ==================== ====================
/** 拼装 el-alert 提示文字 */
const alertTitle = computed(() => {
const parts: string[] = []
if (props.batchId != null) parts.push('批次')
if (props.warehouseId != null) parts.push('仓库')
if (props.excludeVirtual) parts.push('排除虚拟仓')
return `已按${parts.join('/')}预过滤`
})
/** 是否显示 alert 提示 */
const showAlert = computed(() => {
return props.batchId != null || props.warehouseId != null
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -78,6 +78,7 @@
v-model="formData.materialStockId" v-model="formData.materialStockId"
placeholder="请选择库存" placeholder="请选择库存"
class="!w-1/1" class="!w-1/1"
:exclude-virtual="false"
@change="handleStockChange" @change="handleStockChange"
/> />
</el-form-item> </el-form-item>

View File

@ -20,6 +20,7 @@
<WmMaterialStockSelect <WmMaterialStockSelect
v-model="formData.materialStockId" v-model="formData.materialStockId"
:item-id="formData.itemId" :item-id="formData.itemId"
:batch-id="formData.batchId"
@change="handleStockChange" @change="handleStockChange"
/> />
</el-form-item> </el-form-item>

View File

@ -92,6 +92,7 @@
:return-id="formData.id" :return-id="formData.id"
:form-type="formType" :form-type="formType"
:client-id="formData.clientId" :client-id="formData.clientId"
:sales-order-code="formData.salesOrderCode"
/> />
</template> </template>
<template #footer> <template #footer>

View File

@ -104,6 +104,7 @@
v-model="formData.batchId" v-model="formData.batchId"
:item-id="formData.itemId" :item-id="formData.itemId"
:client-id="props.clientId" :client-id="props.clientId"
:sales-order-code="props.salesOrderCode"
placeholder="请选择批次" placeholder="请选择批次"
class="!w-1/1" class="!w-1/1"
/> />
@ -151,6 +152,7 @@ const props = defineProps<{
returnId: number returnId: number
formType: string formType: string
clientId?: number // ID clientId?: number // ID
salesOrderCode?: string //
}>() }>()
const { t } = useI18n() // const { t } = useI18n() //