2026-09-07 15:26:37 +08:00
|
|
|
|
<script setup>
|
2026-09-20 14:52:36 +08:00
|
|
|
|
// 物料下拉选择器(公共组件,全项目统一 —— 客户诉求 问题18:下拉显示字段 编码/图号/类型/品类)
|
2026-09-07 15:26:37 +08:00
|
|
|
|
// 规范:数据量不确定的下拉只加载最近 100 条(created_at desc),支持远程模糊搜索(keyword 查询,结果仍封顶 100)。
|
2026-09-20 14:52:36 +08:00
|
|
|
|
// 选中后通过 item-change 事件抛出完整物料对象(无匹配为 null),供页面读取 manageMode/itemType 自动判定类型,
|
|
|
|
|
|
// 杜绝让客户手动选择「电气件/结构件」——物料类型物料档案里就有(问题18)。
|
2026-09-07 15:26:37 +08:00
|
|
|
|
import { ref, onMounted } from 'vue'
|
|
|
|
|
|
import request from '../utils/request'
|
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
modelValue: { type: [String, Array], default: '' },
|
|
|
|
|
|
multiple: { type: Boolean, default: false },
|
2026-09-10 16:59:15 +08:00
|
|
|
|
manageMode: { type: Number, default: 0 }, // 0=全部 1=结构件 2=电气件
|
2026-09-15 16:37:39 +08:00
|
|
|
|
itemType: { type: Number, default: 0 }, // 0=全部 1原材料 2半成品 3成品 4其他
|
2026-09-18 18:54:54 +08:00
|
|
|
|
excludeItemType: { type: Number, default: 0 }, // 排除指定品类,如结构件/电气件入库排除「其他」(4)
|
2026-09-07 15:26:37 +08:00
|
|
|
|
placeholder: { type: String, default: '选择物料' },
|
|
|
|
|
|
clearable: { type: Boolean, default: true },
|
|
|
|
|
|
width: { type: String, default: '100%' }
|
|
|
|
|
|
})
|
|
|
|
|
|
const emit = defineEmits(['update:modelValue', 'item-change'])
|
|
|
|
|
|
|
|
|
|
|
|
const options = ref([])
|
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
|
2026-09-20 14:52:36 +08:00
|
|
|
|
// 类型标签(问题18 类型含「其他」):其他品类(itemType=4)统一显示「其他」,否则按管理粒度分结构件/电气件
|
|
|
|
|
|
function typeLabel(m) {
|
|
|
|
|
|
if (m?.itemType === 4) return '其他'
|
|
|
|
|
|
return m?.manageMode === 2 ? '电气件' : '结构件'
|
|
|
|
|
|
}
|
|
|
|
|
|
// 品类标签:1原材料/2半成品/3成品/4其他
|
|
|
|
|
|
function catLabel(m) {
|
|
|
|
|
|
switch (m?.itemType) {
|
|
|
|
|
|
case 1: return '原材料'
|
|
|
|
|
|
case 2: return '半成品'
|
|
|
|
|
|
case 3: return '成品'
|
|
|
|
|
|
case 4: return '其他'
|
|
|
|
|
|
default: return '-'
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 选中回显文本:编码 图号 类型 品类
|
|
|
|
|
|
function optionLabel(m) {
|
|
|
|
|
|
return `${m.code} ${m.name || ''} [${typeLabel(m)}·${catLabel(m)}]`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-07 15:26:37 +08:00
|
|
|
|
// 最近 100 条 + keyword 模糊搜索(后端 /material/query 兼容空 keyword)
|
|
|
|
|
|
async function load(kw = '') {
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
try {
|
|
|
|
|
|
const data = await request.get('/material/query', {
|
2026-09-15 16:37:39 +08:00
|
|
|
|
params: {
|
|
|
|
|
|
page: 1, pageSize: 100, keyword: kw || '',
|
|
|
|
|
|
manageMode: props.manageMode || '',
|
2026-09-18 18:54:54 +08:00
|
|
|
|
itemType: props.itemType || '',
|
|
|
|
|
|
excludeItemType: props.excludeItemType || ''
|
2026-09-15 16:37:39 +08:00
|
|
|
|
}
|
2026-09-07 15:26:37 +08:00
|
|
|
|
})
|
|
|
|
|
|
options.value = data?.list || []
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
options.value = []
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function onChange(v) {
|
|
|
|
|
|
emit('update:modelValue', v)
|
|
|
|
|
|
if (props.multiple) {
|
|
|
|
|
|
emit('item-change', options.value.filter((o) => v.includes(o.code)))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
emit('item-change', options.value.find((o) => o.code === v) || null)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-09-20 14:52:36 +08:00
|
|
|
|
|
2026-09-21 10:48:53 +08:00
|
|
|
|
// 展开下拉即重拉最近 100 条(仅在未输入搜索词时):新建/修改物料后无需刷新页面即可选到最新数据。
|
|
|
|
|
|
function onVisible(v) { if (v) load('') }
|
|
|
|
|
|
|
2026-09-20 14:52:36 +08:00
|
|
|
|
onMounted(() => load(''))
|
2026-09-07 15:26:37 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<el-select :model-value="modelValue" :multiple="multiple" filterable remote clearable
|
|
|
|
|
|
:remote-method="load" :loading="loading" :placeholder="placeholder"
|
2026-09-21 10:48:53 +08:00
|
|
|
|
:style="{ width }" @change="onChange" @visible-change="onVisible">
|
2026-09-20 14:52:36 +08:00
|
|
|
|
<el-option v-for="m in options" :key="m.id" :value="m.code" :label="optionLabel(m)">
|
|
|
|
|
|
<span style="float:left">{{ m.code }} {{ m.name || '' }}</span>
|
|
|
|
|
|
<span style="float:right;color:#8492a6;font-size:12px;margin-left:16px">
|
|
|
|
|
|
{{ typeLabel(m) }}|{{ catLabel(m) }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</el-option>
|
2026-09-07 15:26:37 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
</template>
|