feat(mes): 抽取通用 Select 下拉组件,替换各表单内联 el-select

将 MES 模块中各表单的内联 el-select + 手动加载 SimpleList 数据的模式,
统一抽取为独立的 Select 组件,每个组件自包含数据加载和前端搜索过滤。

新增 8 个 Select 组件:
- MdItemSelect(物料产品选择器)
- MdClientSelect(客户选择器)
- MdVendorSelect(供应商选择器)
- MdUnitMeasureSelect(计量单位选择器)
- MdWorkshopSelect(车间选择器)
- WmWarehouseSelect(仓库选择器)
- QcIndicatorSelect(质检指标选择器)
- TmToolTypeSelect(工具类型选择器)

改造 10 个消费者文件:
- WorkOrderForm.vue:产品/客户/供应商选择器替换
- WorkOrderBom.vue:物料/单位选择器替换,修复 handleBomItemChange
- MdItemForm.vue:计量单位选择器替换
- WorkstationForm.vue:车间/仓库选择器替换
- MachineryForm.vue:车间选择器替换
- TemplateItemForm.vue:物料选择器替换
- TemplateIndicatorForm.vue:质检指标/计量单位选择器替换
- ToolForm.vue:工具类型选择器替换
- workstation/index.vue:搜索栏车间选择器替换
- tool/index.vue:搜索栏工具类型选择器替换
pull/871/MERGE
YunaiV 2026-02-19 12:09:52 +08:00
parent 5f010acc5f
commit b8254baf5a
18 changed files with 702 additions and 287 deletions

View File

@ -47,14 +47,7 @@
</el-col>
<el-col :span="8">
<el-form-item label="所属车间" prop="workshopId">
<el-select v-model="formData.workshopId" placeholder="请选择所属车间" class="!w-1/1">
<el-option
v-for="item in workshopList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<MdWorkshopSelect v-model="formData.workshopId" placeholder="请选择所属车间" />
</el-form-item>
</el-col>
<el-col :span="8">
@ -133,7 +126,7 @@
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { DvMachineryApi, DvMachineryVO } from '@/api/mes/dv/machinery'
import { DvMachineryTypeApi } from '@/api/mes/dv/machinery/type'
import { MdWorkshopApi, MdWorkshopVO } from '@/api/mes/md/workstation/workshop'
import MdWorkshopSelect from '@/views/mes/md/workstation/components/MdWorkshopSelect.vue'
import { defaultProps, handleTree } from '@/utils/tree'
import { MesDvMachineryStatusEnum } from '@/views/mes/utils/constants'
import { generateRandomStr } from '@/utils'
@ -170,7 +163,6 @@ const formRules = reactive({
})
const formRef = ref() // Ref
const machineryTypeTree = ref<any[]>([]) //
const workshopList = ref<MdWorkshopVO[]>([]) //
/** 生成设备编码 */
const generateCode = () => {
@ -186,8 +178,6 @@ const open = async (type: string, id?: number) => {
//
const typeData = await DvMachineryTypeApi.getMachineryTypeSimpleList()
machineryTypeTree.value = handleTree(typeData)
//
workshopList.value = await MdWorkshopApi.getWorkshopSimpleList()
//
if (id) {
formLoading.value = true

View File

@ -0,0 +1,81 @@
<!-- MES 客户选择器纯下拉前端过滤支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
:filter-method="handleFilter"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in filteredList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">
编号: {{ item.code }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { MdClientApi, MdClientVO } from '@/api/mes/md/client'
defineOptions({ name: 'MdClientSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择客户'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: MdClientVO | undefined]
}>()
const allList = ref<MdClientVO[]>([])
const filteredList = ref<MdClientVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 前端过滤name + code */
const handleFilter = (query: string) => {
if (!query) {
filteredList.value = allList.value
return
}
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
)
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = allList.value.find((o) => o.id === val)
emit('change', item)
}
/** 加载客户列表 */
onMounted(async () => {
allList.value = await MdClientApi.getClientSimpleList()
filteredList.value = allList.value
})
</script>

View File

@ -32,14 +32,7 @@
</el-col>
<el-col :span="8">
<el-form-item label="单位" prop="unitMeasureId">
<el-select v-model="formData.unitMeasureId" placeholder="请选择计量单位" class="w-1/1">
<el-option
v-for="item in unitMeasureList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<MdUnitMeasureSelect v-model="formData.unitMeasureId" placeholder="请选择计量单位" />
</el-form-item>
</el-col>
<el-col :span="8">
@ -146,7 +139,7 @@ import MdItemBatchConfigForm from './MdItemBatchConfigForm.vue'
import MdProductBomForm from './MdProductBomForm.vue'
import MdProductSopForm from './MdProductSopForm.vue'
import MdProductSipForm from './MdProductSipForm.vue'
import { MdUnitMeasureApi, MdUnitMeasureVO } from '@/api/mes/md/unitmeasure'
import MdUnitMeasureSelect from '@/views/mes/md/unitmeasure/components/MdUnitMeasureSelect.vue'
import { CommonStatusEnum } from '@/utils/constants'
import { defaultProps, handleTree } from '@/utils/tree'
@ -186,7 +179,6 @@ const formRules = reactive({
const formRef = ref() // Ref
const itemTypeTree = ref<MdItemTypeVO[]>([]) //
const itemTypeList = ref<MdItemTypeVO[]>([]) //
const unitMeasureList = ref<MdUnitMeasureVO[]>([]) //
/** 当前物料的「物料/产品」标识 */
const currentItemOrProduct = computed(() => {
@ -222,8 +214,6 @@ const open = async (type: string, id?: number) => {
//
itemTypeList.value = await MdItemTypeApi.getItemTypeSimpleList()
itemTypeTree.value = handleTree(itemTypeList.value)
//
unitMeasureList.value = await MdUnitMeasureApi.getUnitMeasureSimpleList()
}
defineExpose({ open }) // open

View File

@ -0,0 +1,87 @@
<!-- MES 物料产品选择器纯下拉前端过滤支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
:filter-method="handleFilter"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in filteredList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">
编号: {{ item.code }}
</el-tag>
<el-tag v-if="item.specification" size="small" type="info" class="ml-4px">
规格: {{ item.specification }}
</el-tag>
<el-tag v-if="item.unitMeasureName" size="small" type="info" class="ml-4px">
单位: {{ item.unitMeasureName }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { MdItemApi, MdItemVO } from '@/api/mes/md/item'
defineOptions({ name: 'MdItemSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择产品'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: MdItemVO | undefined]
}>()
const allList = ref<MdItemVO[]>([]) //
const filteredList = ref<MdItemVO[]>([]) //
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 前端过滤name + code */
const handleFilter = (query: string) => {
if (!query) {
filteredList.value = allList.value
return
}
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
)
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = allList.value.find((o) => o.id === val)
emit('change', item)
}
/** 加载物料列表 */
onMounted(async () => {
allList.value = await MdItemApi.getItemSimpleList()
filteredList.value = allList.value
})
</script>

View File

@ -0,0 +1,81 @@
<!-- MES 计量单位选择器纯下拉前端过滤支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
:filter-method="handleFilter"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in filteredList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">
编号: {{ item.code }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { MdUnitMeasureApi, MdUnitMeasureVO } from '@/api/mes/md/unitmeasure'
defineOptions({ name: 'MdUnitMeasureSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择计量单位'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: MdUnitMeasureVO | undefined]
}>()
const allList = ref<MdUnitMeasureVO[]>([])
const filteredList = ref<MdUnitMeasureVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 前端过滤name + code */
const handleFilter = (query: string) => {
if (!query) {
filteredList.value = allList.value
return
}
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
)
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = allList.value.find((o) => o.id === val)
emit('change', item)
}
/** 加载计量单位列表 */
onMounted(async () => {
allList.value = await MdUnitMeasureApi.getUnitMeasureSimpleList()
filteredList.value = allList.value
})
</script>

View File

@ -0,0 +1,81 @@
<!-- MES 供应商选择器纯下拉前端过滤支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
:filter-method="handleFilter"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in filteredList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">
编号: {{ item.code }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { MdVendorApi, MdVendorVO } from '@/api/mes/md/vendor'
defineOptions({ name: 'MdVendorSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择供应商'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: MdVendorVO | undefined]
}>()
const allList = ref<MdVendorVO[]>([])
const filteredList = ref<MdVendorVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 前端过滤name + code */
const handleFilter = (query: string) => {
if (!query) {
filteredList.value = allList.value
return
}
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
)
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = allList.value.find((o) => o.id === val)
emit('change', item)
}
/** 加载供应商列表 */
onMounted(async () => {
allList.value = await MdVendorApi.getVendorSimpleList()
filteredList.value = allList.value
})
</script>

View File

@ -26,14 +26,7 @@
</el-col>
<el-col :span="8">
<el-form-item label="所在车间" prop="workshopId">
<el-select v-model="formData.workshopId" placeholder="请选择车间" class="!w-1/1">
<el-option
v-for="workshop in workshopList"
:key="workshop.id"
:label="workshop.name"
:value="workshop.id"
/>
</el-select>
<MdWorkshopSelect v-model="formData.workshopId" placeholder="请选择车间" />
</el-form-item>
</el-col>
</el-row>
@ -45,20 +38,12 @@
</el-col>
<el-col :span="8">
<el-form-item label="线边库" prop="warehouseId">
<el-select
<WmWarehouseSelect
v-model="formData.warehouseId"
placeholder="请选择线边库"
clearable
class="!w-1/1"
@change="handleWarehouseChange"
>
<el-option
v-for="warehouse in warehouseList"
:key="warehouse.id"
:label="warehouse.name"
:value="warehouse.id"
/>
</el-select>
@change="handleWarehouseSelectChange"
/>
</el-form-item>
</el-col>
<el-col :span="8">
@ -143,8 +128,9 @@
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { MdWorkstationApi, MdWorkstationVO } from '@/api/mes/md/workstation'
import { MdWorkshopApi, MdWorkshopVO } from '@/api/mes/md/workstation/workshop'
import { WmWarehouseApi, WmWarehouseVO } from '@/api/mes/wm/warehouse'
import MdWorkshopSelect from '@/views/mes/md/workstation/components/MdWorkshopSelect.vue'
import WmWarehouseSelect from '@/views/mes/wm/warehouse/components/WmWarehouseSelect.vue'
import { WmWarehouseVO } from '@/api/mes/wm/warehouse'
import { WmWarehouseLocationApi, WmWarehouseLocationVO } from '@/api/mes/wm/warehouse/location'
import { WmWarehouseAreaApi, WmWarehouseAreaVO } from '@/api/mes/wm/warehouse/area'
import { CommonStatusEnum } from '@/utils/constants'
@ -163,8 +149,6 @@ const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const activeTab = ref('machine') // Tab
const workshopList = ref<MdWorkshopVO[]>([]) //
const warehouseList = ref<WmWarehouseVO[]>([]) //
const locationList = ref<WmWarehouseLocationVO[]>([]) //
const areaList = ref<WmWarehouseAreaVO[]>([]) //
const formData = ref({
@ -211,12 +195,12 @@ const loadAreaList = async (locationId?: number) => {
areaList.value = await WmWarehouseAreaApi.getWarehouseAreaSimpleList(locationId)
}
/** 仓库改变时,重置库区和库位 */
const handleWarehouseChange = async (warehouseId?: number) => {
/** 仓库选择变化:重置库区和库位 */
const handleWarehouseSelectChange = async (item: WmWarehouseVO | undefined) => {
formData.value.locationId = undefined
formData.value.areaId = undefined
areaList.value = []
await loadLocationList(warehouseId)
await loadLocationList(item?.id)
}
/** 库区改变时,重置库位 */
@ -231,10 +215,6 @@ const open = async (type: string, id?: number) => {
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
workshopList.value = await MdWorkshopApi.getWorkshopSimpleList()
//
warehouseList.value = await WmWarehouseApi.getWarehouseSimpleList()
//
if (id) {
formLoading.value = true

View File

@ -0,0 +1,81 @@
<!-- MES 车间选择器纯下拉前端过滤支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
:filter-method="handleFilter"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in filteredList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">
编号: {{ item.code }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { MdWorkshopApi, MdWorkshopVO } from '@/api/mes/md/workstation/workshop'
defineOptions({ name: 'MdWorkshopSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择车间'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: MdWorkshopVO | undefined]
}>()
const allList = ref<MdWorkshopVO[]>([])
const filteredList = ref<MdWorkshopVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 前端过滤name + code */
const handleFilter = (query: string) => {
if (!query) {
filteredList.value = allList.value
return
}
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
)
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = allList.value.find((o) => o.id === val)
emit('change', item)
}
/** 加载车间列表 */
onMounted(async () => {
allList.value = await MdWorkshopApi.getWorkshopSimpleList()
filteredList.value = allList.value
})
</script>

View File

@ -27,19 +27,7 @@
/>
</el-form-item>
<el-form-item label="所在车间" prop="workshopId">
<el-select
v-model="queryParams.workshopId"
placeholder="请选择车间"
clearable
class="!w-240px"
>
<el-option
v-for="workshop in workshopList"
:key="workshop.id"
:label="workshop.name"
:value="workshop.id"
/>
</el-select>
<MdWorkshopSelect v-model="queryParams.workshopId" placeholder="请选择车间" clearable class="!w-240px" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
@ -134,7 +122,7 @@
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { MdWorkstationApi, MdWorkstationVO } from '@/api/mes/md/workstation'
import { MdWorkshopApi, MdWorkshopVO } from '@/api/mes/md/workstation/workshop'
import MdWorkshopSelect from './components/MdWorkshopSelect.vue'
import WorkstationForm from './WorkstationForm.vue'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
@ -146,7 +134,6 @@ const { t } = useI18n() // 国际化
const loading = ref(true) //
const list = ref<MdWorkstationVO[]>([]) //
const total = ref(0) //
const workshopList = ref<MdWorkshopVO[]>([]) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
@ -214,7 +201,5 @@ const handleExport = async () => {
/** 初始化 **/
onMounted(async () => {
await getList()
//
workshopList.value = await MdWorkshopApi.getWorkshopSimpleList()
})
</script>

View File

@ -44,35 +44,10 @@
v-loading="bomFormLoading"
>
<el-form-item label="物料" prop="itemId">
<el-select
v-model="bomFormData.itemId"
placeholder="请选择物料"
filterable
class="!w-1/1"
@change="handleBomItemChange"
>
<el-option
v-for="item in itemList"
:key="item.id"
:label="item.name + (item.code ? ' (' + item.code + ')' : '')"
:value="item.id"
/>
</el-select>
<MdItemSelect v-model="bomFormData.itemId" @change="handleBomItemChange" />
</el-form-item>
<el-form-item label="单位" prop="unitMeasureId">
<el-select
v-model="bomFormData.unitMeasureId"
placeholder="请选择单位"
filterable
class="!w-1/1"
>
<el-option
v-for="item in unitMeasureList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<MdUnitMeasureSelect v-model="bomFormData.unitMeasureId" />
</el-form-item>
<el-form-item label="预计使用量" prop="quantity">
<el-input-number
@ -96,8 +71,9 @@
<script setup lang="ts">
import { ProWorkOrderBomApi, ProWorkOrderBomVO } from '@/api/mes/pro/workorder/bom'
import { MdItemApi, MdItemVO } from '@/api/mes/md/item'
import { MdUnitMeasureApi } from '@/api/mes/md/unitmeasure'
import { MdItemVO } from '@/api/mes/md/item'
import MdItemSelect from '@/views/mes/md/item/components/MdItemSelect.vue'
import MdUnitMeasureSelect from '@/views/mes/md/unitmeasure/components/MdUnitMeasureSelect.vue'
defineOptions({ name: 'WorkOrderBom' })
@ -161,17 +137,12 @@ const bomFormRules = reactive({
quantity: [{ required: true, message: '预计使用量不能为空', trigger: 'blur' }]
})
const bomFormRef = ref()
const itemList = ref<MdItemVO[]>([])
const unitMeasureList = ref<any[]>([])
/** 打开 BOM 表单弹窗 */
const openBomForm = async (type: string, row?: any) => {
bomDialogVisible.value = true
bomDialogTitle.value = type === 'create' ? '添加物料' : '编辑物料'
bomFormType.value = type
//
itemList.value = await MdItemApi.getItemSimpleList()
unitMeasureList.value = await MdUnitMeasureApi.getUnitMeasureSimpleList()
//
bomFormData.value = {
id: undefined,
@ -188,9 +159,8 @@ const openBomForm = async (type: string, row?: any) => {
}
/** 物料变更:自动填充单位 */
const handleBomItemChange = (itemId: number) => {
const item = itemList.value.find((i) => i.id === itemId)
if (item && item.unitMeasureId) {
const handleBomItemChange = (item: MdItemVO | undefined) => {
if (item?.unitMeasureId) {
bomFormData.value.unitMeasureId = item.unitMeasureId
}
}

View File

@ -69,43 +69,12 @@
</el-row>
<el-row>
<el-col :span="8">
<!-- TODO @AI应该是 ItemSelect -->
<el-form-item label="产品" prop="productId">
<el-select
<MdItemSelect
v-model="formData.productId"
placeholder="请选择产品"
filterable
class="!w-1/1"
:disabled="isDetail"
@change="handleProductChange"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name + (item.code ? ' (' + item.code + ')' : '')"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<!-- TODO @AI这里 disabled 展示产品名称规格类型单位 -->
<!-- TODO @AI这个字段单位应该不用存储通过 item 查询就好了 -->
<el-col :span="8">
<el-form-item label="单位" prop="unitMeasureId">
<el-select
v-model="formData.unitMeasureId"
placeholder="请选择单位"
filterable
class="!w-1/1"
:disabled="isDetail"
>
<el-option
v-for="item in unitMeasureList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
/>
</el-form-item>
</el-col>
<el-col :span="8">
@ -123,46 +92,15 @@
</el-row>
<el-row>
<el-col :span="8">
<!-- TODO @AI这个需要搞个客户的 select 弹出类似 itemselect 这种 -->
<el-form-item label="客户" prop="clientId">
<el-select
v-model="formData.clientId"
placeholder="请选择客户"
filterable
clearable
class="!w-1/1"
:disabled="isDetail"
>
<el-option
v-for="item in clientList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<MdClientSelect v-model="formData.clientId" :disabled="isDetail" />
</el-form-item>
<!-- TODO @AI展示客户编码客户名称 -->
</el-col>
<el-col :span="8">
<!-- TODO @AI只有外协外购才有供应商 -->
<el-form-item label="供应商" prop="vendorId">
<el-select
v-model="formData.vendorId"
placeholder="请选择供应商"
filterable
clearable
class="!w-1/1"
:disabled="isDetail"
>
<el-option
v-for="item in vendorList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<MdVendorSelect v-model="formData.vendorId" :disabled="isDetail" />
</el-form-item>
<!-- TODO @AI展示供应商编码供应商名称 -->
</el-col>
<el-col :span="8">
<!-- TODO @AI这个字段是必须的么在调研确认下 -->
@ -224,10 +162,10 @@
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { ProWorkOrderApi, ProWorkOrderVO } from '@/api/mes/pro/workorder'
import { MdItemApi, MdItemVO } from '@/api/mes/md/item'
import { MdClientApi } from '@/api/mes/md/client'
import { MdVendorApi } from '@/api/mes/md/vendor'
import { MdUnitMeasureApi } from '@/api/mes/md/unitmeasure'
import { MdItemVO } from '@/api/mes/md/item'
import MdItemSelect from '@/views/mes/md/item/components/MdItemSelect.vue'
import MdClientSelect from '@/views/mes/md/client/components/MdClientSelect.vue'
import MdVendorSelect from '@/views/mes/md/vendor/components/MdVendorSelect.vue'
import WorkOrderBom from './WorkOrderBom.vue'
defineOptions({ name: 'WorkOrderForm' })
@ -263,18 +201,11 @@ const formRules = reactive({
type: [{ required: true, message: '工单类型不能为空', trigger: 'change' }],
orderSourceType: [{ required: true, message: '来源类型不能为空', trigger: 'change' }],
productId: [{ required: true, message: '产品不能为空', trigger: 'change' }],
unitMeasureId: [{ required: true, message: '单位不能为空', trigger: 'change' }],
quantity: [{ required: true, message: '生产数量不能为空', trigger: 'blur' }],
requestDate: [{ required: true, message: '需求日期不能为空', trigger: 'change' }]
})
const formRef = ref() // Ref
//
const productList = ref<MdItemVO[]>([]) //
const clientList = ref<any[]>([]) //
const vendorList = ref<any[]>([]) //
const unitMeasureList = ref<any[]>([]) //
/** 是否为详情模式 */
const isDetail = computed(() => formType.value === 'detail')
@ -285,11 +216,6 @@ const open = async (type: string, id?: number) => {
formType.value = type
activeTab.value = 'bom'
resetForm()
//
productList.value = await MdItemApi.getItemSimpleList()
clientList.value = await MdClientApi.getClientSimpleList()
vendorList.value = await MdVendorApi.getVendorSimpleList()
unitMeasureList.value = await MdUnitMeasureApi.getUnitMeasureSimpleList()
// /
if (id) {
formLoading.value = true
@ -303,9 +229,8 @@ const open = async (type: string, id?: number) => {
defineExpose({ open }) // open
/** 产品变更:自动填充单位 */
const handleProductChange = (productId: number) => {
const product = productList.value.find((item) => item.id === productId)
if (product && product.unitMeasureId) {
const handleProductChange = (product: MdItemVO) => {
if (product?.unitMeasureId) {
formData.value.unitMeasureId = product.unitMeasureId
}
}

View File

@ -0,0 +1,81 @@
<!-- MES 质检指标选择器纯下拉前端过滤支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
:filter-method="handleFilter"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in filteredList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">
编号: {{ item.code }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { QcIndicatorApi, QcIndicatorVO } from '@/api/mes/qc/indicator'
defineOptions({ name: 'QcIndicatorSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择质检指标'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: QcIndicatorVO | undefined]
}>()
const allList = ref<QcIndicatorVO[]>([])
const filteredList = ref<QcIndicatorVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 前端过滤name + code */
const handleFilter = (query: string) => {
if (!query) {
filteredList.value = allList.value
return
}
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
)
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = allList.value.find((o) => o.id === val)
emit('change', item)
}
/** 加载质检指标列表 */
onMounted(async () => {
allList.value = await QcIndicatorApi.getIndicatorSimpleList()
filteredList.value = allList.value
})
</script>

View File

@ -9,19 +9,7 @@
v-loading="formLoading"
>
<el-form-item label="质检指标" prop="indicatorId">
<el-select
v-model="formData.indicatorId"
placeholder="请选择质检指标"
filterable
class="!w-1/1"
>
<el-option
v-for="item in indicatorList"
:key="item.id"
:label="item.code + ' - ' + item.name"
:value="item.id"
/>
</el-select>
<QcIndicatorSelect v-model="formData.indicatorId" placeholder="请选择质检指标" />
</el-form-item>
<el-form-item label="检测方法" prop="checkMethod">
<el-input
@ -40,20 +28,7 @@
/>
</el-form-item>
<el-form-item label="单位" prop="unitMeasureId">
<el-select
v-model="formData.unitMeasureId"
placeholder="请选择计量单位"
filterable
clearable
class="!w-1/1"
>
<el-option
v-for="unit in unitMeasureList"
:key="unit.id"
:label="unit.name"
:value="unit.id"
/>
</el-select>
<MdUnitMeasureSelect v-model="formData.unitMeasureId" placeholder="请选择计量单位" clearable />
</el-form-item>
<el-form-item label="误差上限" prop="thresholdMax">
<el-input-number
@ -87,8 +62,8 @@
<script setup lang="ts">
import { QcTemplateApi, QcTemplateIndicatorVO } from '@/api/mes/qc/template'
import { QcIndicatorApi, QcIndicatorVO } from '@/api/mes/qc/indicator'
import { MdUnitMeasureApi, MdUnitMeasureVO } from '@/api/mes/md/unitmeasure'
import QcIndicatorSelect from '@/views/mes/qc/indicator/components/QcIndicatorSelect.vue'
import MdUnitMeasureSelect from '@/views/mes/md/unitmeasure/components/MdUnitMeasureSelect.vue'
defineOptions({ name: 'TemplateIndicatorForm' })
@ -116,11 +91,6 @@ const formRules = reactive({
})
const formRef = ref()
/** 质检指标精简列表 */
const indicatorList = ref<QcIndicatorVO[]>([])
/** 计量单位精简列表 */
const unitMeasureList = ref<MdUnitMeasureVO[]>([])
/** 打开弹窗 */
const open = async (type: string, id?: number, templateId?: number) => {
dialogVisible.value = true
@ -128,12 +98,6 @@ const open = async (type: string, id?: number, templateId?: number) => {
formType.value = type
resetForm()
formData.value.templateId = templateId
//
// TODO @AI
;[indicatorList.value, unitMeasureList.value] = await Promise.all([
QcIndicatorApi.getIndicatorSimpleList(),
MdUnitMeasureApi.getUnitMeasureSimpleList()
])
if (id) {
formLoading.value = true
try {

View File

@ -9,16 +9,7 @@
v-loading="formLoading"
>
<el-form-item label="产品物料" prop="itemId">
<!-- TODO @AIitem select 选择 -->
<el-select v-model="formData.itemId" placeholder="请选择产品物料" filterable class="!w-1/1">
<el-option
v-for="item in itemList"
:key="item.id"
:label="item.code + ' - ' + item.name + (item.specification ? '' + item.specification + '' : '')"
:value="item.id"
/>
</el-select>
<!-- TODO @AI产品物料编码产品物料名称规格型号 -->
<MdItemSelect v-model="formData.itemId" placeholder="请选择产品物料" />
</el-form-item>
<el-form-item label="最低检测数" prop="quantityCheck">
<el-input-number
@ -75,7 +66,7 @@
<script setup lang="ts">
import { QcTemplateApi, QcTemplateItemVO } from '@/api/mes/qc/template'
import { MdItemApi, MdItemVO } from '@/api/mes/md/item'
import MdItemSelect from '@/views/mes/md/item/components/MdItemSelect.vue'
defineOptions({ name: 'TemplateItemForm' })
@ -102,8 +93,6 @@ const formRules = reactive({
})
const formRef = ref()
/** 物料精简列表 */
const itemList = ref<MdItemVO[]>([])
/** 打开弹窗 */
const open = async (type: string, id?: number, templateId?: number) => {
@ -112,8 +101,6 @@ const open = async (type: string, id?: number, templateId?: number) => {
formType.value = type
resetForm()
formData.value.templateId = templateId
//
itemList.value = await MdItemApi.getItemSimpleList()
if (id) {
formLoading.value = true
try {

View File

@ -29,19 +29,11 @@
<el-row>
<el-col :span="8">
<el-form-item label="工具类型" prop="toolTypeId">
<el-select
<TmToolTypeSelect
v-model="formData.toolTypeId"
placeholder="请选择工具类型"
class="!w-1/1"
@change="handleToolTypeChange"
>
<el-option
v-for="item in toolTypeList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
/>
</el-form-item>
</el-col>
<el-col :span="8">
@ -142,7 +134,8 @@
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { TmToolApi, TmToolVO } from '@/api/mes/tm/tool'
import { TmToolTypeApi, TmToolTypeVO } from '@/api/mes/tm/tool/type'
import { TmToolTypeVO } from '@/api/mes/tm/tool/type'
import TmToolTypeSelect from '@/views/mes/tm/tool/components/TmToolTypeSelect.vue'
import { MesToolStatusEnum, MesMaintenTypeEnum } from '@/views/mes/utils/constants'
import { generateRandomStr } from '@/utils'
@ -177,7 +170,6 @@ const formRules = reactive({
status: [{ required: true, message: '状态不能为空', trigger: 'change' }]
})
const formRef = ref() // Ref
const toolTypeList = ref<TmToolTypeVO[]>([]) //
const selectedToolType = ref<TmToolTypeVO>() //
/** 打开弹窗 */
@ -186,17 +178,11 @@ const open = async (type: string, id?: number) => {
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
toolTypeList.value = await TmToolTypeApi.getToolTypeSimpleList()
//
if (id) {
formLoading.value = true
try {
formData.value = await TmToolApi.getTool(id)
//
selectedToolType.value = toolTypeList.value.find(
(item) => item.id === formData.value.toolTypeId
)
} finally {
formLoading.value = false
}
@ -211,10 +197,10 @@ const generateCode = () => {
}
/** 工具类型变更 */
const handleToolTypeChange = (toolTypeId: number) => {
selectedToolType.value = toolTypeList.value.find((item) => item.id === toolTypeId)
const handleToolTypeChange = (item: TmToolTypeVO | undefined) => {
selectedToolType.value = item
// 1
if (selectedToolType.value?.codeFlag === true) {
if (item?.codeFlag === true) {
formData.value.quantity = 1
formData.value.quantityAvailable = 1
}

View File

@ -0,0 +1,81 @@
<!-- MES 工具类型选择器纯下拉前端过滤支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
:filter-method="handleFilter"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in filteredList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">
编号: {{ item.code }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { TmToolTypeApi, TmToolTypeVO } from '@/api/mes/tm/tool/type'
defineOptions({ name: 'TmToolTypeSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择工具类型'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: TmToolTypeVO | undefined]
}>()
const allList = ref<TmToolTypeVO[]>([])
const filteredList = ref<TmToolTypeVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 前端过滤name + code */
const handleFilter = (query: string) => {
if (!query) {
filteredList.value = allList.value
return
}
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
)
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = allList.value.find((o) => o.id === val)
emit('change', item)
}
/** 加载工具类型列表 */
onMounted(async () => {
allList.value = await TmToolTypeApi.getToolTypeSimpleList()
filteredList.value = allList.value
})
</script>

View File

@ -28,19 +28,7 @@
/>
</el-form-item>
<el-form-item label="工具类型" prop="toolTypeId">
<el-select
v-model="queryParams.toolTypeId"
placeholder="请选择工具类型"
clearable
class="!w-240px"
>
<el-option
v-for="item in toolTypeList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<TmToolTypeSelect v-model="queryParams.toolTypeId" placeholder="请选择工具类型" clearable class="!w-240px" />
</el-form-item>
<el-form-item label="品牌" prop="brand">
<el-input
@ -170,7 +158,7 @@
import { dateFormatter, formatDate } from '@/utils/formatTime'
import download from '@/utils/download'
import { TmToolApi, TmToolVO } from '@/api/mes/tm/tool'
import { TmToolTypeApi, TmToolTypeVO } from '@/api/mes/tm/tool/type'
import TmToolTypeSelect from './components/TmToolTypeSelect.vue'
import ToolForm from './ToolForm.vue'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { MesMaintenTypeEnum } from '@/views/mes/utils/constants'
@ -195,8 +183,6 @@ const queryParams = reactive({
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const toolTypeList = ref<TmToolTypeVO[]>([]) //
/** 查询列表 */
const getList = async () => {
loading.value = true
@ -258,7 +244,5 @@ const handleExport = async () => {
/** 初始化 **/
onMounted(async () => {
await getList()
//
toolTypeList.value = await TmToolTypeApi.getToolTypeSimpleList()
})
</script>

View File

@ -0,0 +1,81 @@
<!-- MES 仓库选择器纯下拉前端过滤支持 namecode -->
<template>
<el-select
v-model="selectValue"
:placeholder="placeholder"
:disabled="disabled"
:clearable="clearable"
filterable
:filter-method="handleFilter"
class="!w-1/1"
@change="handleChange"
>
<el-option v-for="item in filteredList" :key="item.id" :label="item.name" :value="item.id">
<div class="flex items-center gap-8px">
<span>{{ item.name }}</span>
<el-tag v-if="item.code" size="small" type="info" class="ml-4px">
编号: {{ item.code }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { WmWarehouseApi, WmWarehouseVO } from '@/api/mes/wm/warehouse'
defineOptions({ name: 'WmWarehouseSelect' })
const props = withDefaults(
defineProps<{
modelValue?: number
disabled?: boolean
clearable?: boolean
placeholder?: string
}>(),
{
disabled: false,
clearable: true,
placeholder: '请选择仓库'
}
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
change: [item: WmWarehouseVO | undefined]
}>()
const allList = ref<WmWarehouseVO[]>([])
const filteredList = ref<WmWarehouseVO[]>([])
const selectValue = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
/** 前端过滤name + code */
const handleFilter = (query: string) => {
if (!query) {
filteredList.value = allList.value
return
}
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
)
}
/** 选中变化 */
const handleChange = (val: number | undefined) => {
const item = allList.value.find((o) => o.id === val)
emit('change', item)
}
/** 加载仓库列表 */
onMounted(async () => {
allList.value = await WmWarehouseApi.getWarehouseSimpleList()
filteredList.value = allList.value
})
</script>