feat(mes): 将输入框改为下拉选择并添加物料选择功能

- 将机台、班次、班组的输入框改为下拉选择组件
- 添加机台、班次、班组选项的数据加载功能
- 实现物料选择对话框和确认逻辑
- 集成物料选择组件并支持点击选择物料
- 优化配方树构建逻辑避免重复重建
master
zangch@mesnac.com 2 days ago
parent addf83dddb
commit 36d592a683

@ -12,23 +12,33 @@
<el-form-item label="计划编号" prop="planCode">
<el-input v-model="traceQuery.planCode" clearable />
</el-form-item>
<el-form-item label="明细编号" prop="planDetailCode">
<!-- <el-form-item label="明细编号" prop="planDetailCode">
<el-input v-model="traceQuery.planDetailCode" clearable />
</el-form-item>
</el-form-item> -->
<el-form-item label="生产条码" prop="productionBarcode">
<el-input v-model="traceQuery.productionBarcode" clearable />
</el-form-item>
<el-form-item label="机台" prop="machineName">
<el-input v-model="traceQuery.machineName" clearable />
<el-select v-model="traceQuery.machineName" clearable filterable placeholder="请选择机台" style="width: 180px">
<el-option v-for="item in machineOptions" :key="item.machineId" :label="item.machineName" :value="item.machineName" />
</el-select>
</el-form-item>
<el-form-item label="物料" prop="materialName">
<el-input v-model="traceQuery.materialName" clearable />
<el-input v-model="traceQuery.materialName" clearable readonly placeholder="点击选择物料" style="width: 180px" @click="openMaterialSelect">
<template #append>
<el-button icon="Search" @click="openMaterialSelect" />
</template>
</el-input>
</el-form-item>
<el-form-item label="班次" prop="shiftName">
<el-input v-model="traceQuery.shiftName" clearable />
<el-select v-model="traceQuery.shiftName" clearable filterable placeholder="请选择班次" style="width: 150px">
<el-option v-for="item in shiftOptions" :key="item.shiftId" :label="item.shiftName" :value="item.shiftName" />
</el-select>
</el-form-item>
<el-form-item label="班组" prop="classTeamName">
<el-input v-model="traceQuery.classTeamName" clearable />
<el-select v-model="traceQuery.classTeamName" clearable filterable placeholder="请选择班组" style="width: 150px">
<el-option v-for="item in classTeamOptions" :key="item.classTeamId" :label="item.teamName" :value="item.teamName" />
</el-select>
</el-form-item>
<el-form-item label="创建日期" style="width: 380px">
<el-date-picker
@ -321,6 +331,15 @@
</el-tabs>
<!-- Drawer 已移除详情内容已迁移至底部 Tab每车基本信息/每车明细信息 -->
<!-- 物料选择对话框 -->
<el-dialog v-model="materialDialogVisible" title="选择物料" width="800px" append-to-body>
<MaterialSelect ref="materialSelectRef" />
<template #footer>
<el-button @click="materialDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleMaterialConfirm"></el-button>
</template>
</el-dialog>
</div>
</template>
@ -329,6 +348,13 @@ import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, rea
import type { ComponentInternalInstance } from 'vue';
import * as echarts from 'echarts';
import { getMixTraceDetail, getSpcCapability, getSpcRunChart, getSpcXbarR, listMixTrace, listSpcSamples } from '@/api/mes/mixTrace';
import { getProdBaseMachineInfoList } from '@/api/mes/prodBaseMachineInfo';
import { getBaseShiftInfoList } from '@/api/mes/baseShiftInfo';
import { getBaseClassTeamInfoList } from '@/api/mes/baseClassTeamInfo';
import type { ProdBaseMachineInfoVO } from '@/api/mes/prodBaseMachineInfo/types';
import type { BaseShiftInfoVO } from '@/api/mes/baseShiftInfo/types';
import type { BaseClassTeamInfoVO } from '@/api/mes/baseClassTeamInfo/types';
import MaterialSelect from '@/views/mes/recipeInfo/components/MaterialSelect.vue';
import type {
MixTraceDetailQuery,
MixTraceDetailVO,
@ -357,6 +383,13 @@ const traceTableRef = ref();
const treeFilterText = ref('');
const trayBarcode = ref('');
/** 下拉框数据 */
const machineOptions = ref<ProdBaseMachineInfoVO[]>([]);
const shiftOptions = ref<BaseShiftInfoVO[]>([]);
const classTeamOptions = ref<BaseClassTeamInfoVO[]>([]);
const materialSelectRef = ref();
const materialDialogVisible = ref(false);
const traceLoading = ref(false);
const traceList = ref<any[]>([]);
const traceTotal = ref(0);
@ -538,6 +571,60 @@ const handleTrayTrace = () => {
handleTraceQuery();
};
/** 加载机台下拉选项 */
const loadMachineOptions = async () => {
try {
const res = await getProdBaseMachineInfoList({});
machineOptions.value = (res as any).data || [];
} catch {
machineOptions.value = [];
}
};
/** 加载班次下拉选项 */
const loadShiftOptions = async () => {
try {
const res = await getBaseShiftInfoList({});
shiftOptions.value = (res as any).data || [];
} catch {
shiftOptions.value = [];
}
};
/** 加载班组下拉选项 */
const loadClassTeamOptions = async () => {
try {
const res = await getBaseClassTeamInfoList({});
classTeamOptions.value = (res as any).data || [];
} catch {
classTeamOptions.value = [];
}
};
/** 打开物料选择对话框 */
const openMaterialSelect = () => {
materialDialogVisible.value = true;
nextTick(() => {
materialSelectRef.value?.getList();
});
};
/** 确认物料选择 */
const handleMaterialConfirm = () => {
const selected = materialSelectRef.value?.getSelected();
if (selected) {
traceQuery.materialName = selected.materialName;
materialDialogVisible.value = false;
} else {
proxy?.$modal?.msgWarning?.('请选择物料');
}
};
/** 清除物料选择 */
const clearMaterialSelect = () => {
traceQuery.materialName = undefined;
};
/** 从列表数据构建配方树(父=配方编码+物料名,子=该配方下的记录) */
const buildRecipeTree = (list: any[]) => {
const grouped = new Map<string, { label: string; recipeId: any; children: any[] }>();
@ -892,6 +979,10 @@ watch(
/** 列表数据变化时构建配方树 */
watch(traceList, (list) => {
// recipeId
if (traceQuery.recipeId && recipeTreeData.value.length > 0) {
return;
}
buildRecipeTree(list);
});
@ -911,6 +1002,10 @@ watch(detailTab, async (tab) => {
onMounted(() => {
getTraceList();
window.addEventListener('resize', handleResize);
//
loadMachineOptions();
loadShiftOptions();
loadClassTeamOptions();
//
watch(() => traceQuery.pageNum, () => {
selectedRow.value = null;

@ -6,7 +6,9 @@
<el-form-item>
<el-checkbox v-model="enabled.machine" />
<span class="ml-1 mr-2">按生产机台</span>
<el-input v-model="query.machineName" :disabled="!enabled.machine" clearable placeholder="机台名称" style="width: 150px" />
<el-select v-model="query.machineName" :disabled="!enabled.machine" clearable filterable placeholder="请选择机台" style="width: 180px">
<el-option v-for="item in machineOptions" :key="item.machineId" :label="item.machineName" :value="item.machineName" />
</el-select>
</el-form-item>
<el-form-item>
<el-checkbox v-model="enabled.dateRange" />
@ -25,12 +27,16 @@
<el-form-item>
<el-checkbox v-model="enabled.classTeam" />
<span class="ml-1 mr-2">按班组</span>
<el-input v-model="query.classTeamName" :disabled="!enabled.classTeam" clearable placeholder="班组" style="width: 120px" />
<el-select v-model="query.classTeamName" :disabled="!enabled.classTeam" clearable filterable placeholder="请选择班组" style="width: 150px">
<el-option v-for="item in classTeamOptions" :key="item.classTeamId" :label="item.teamName" :value="item.teamName" />
</el-select>
</el-form-item>
<el-form-item>
<el-checkbox v-model="enabled.shift" />
<span class="ml-1 mr-2">按班次</span>
<el-input v-model="query.shiftName" :disabled="!enabled.shift" clearable placeholder="班次" style="width: 120px" />
<el-select v-model="query.shiftName" :disabled="!enabled.shift" clearable filterable placeholder="请选择班次" style="width: 150px">
<el-option v-for="item in shiftOptions" :key="item.shiftId" :label="item.shiftName" :value="item.shiftName" />
</el-select>
</el-form-item>
<el-form-item>
<el-checkbox v-model="enabled.trainNumber" />
@ -116,6 +122,12 @@ import { ArrowRight, DArrowRight } from '@element-plus/icons-vue';
import * as echarts from 'echarts';
import { getMixTraceDetail, listMixTrace } from '@/api/mes/mixTrace';
import type { MixTraceDetailQuery, MixTraceDetailVO, MixTraceQuery, MixTraceStepItem } from '@/api/mes/mixTrace/types';
import { getProdBaseMachineInfoList } from '@/api/mes/prodBaseMachineInfo';
import { getBaseShiftInfoList } from '@/api/mes/baseShiftInfo';
import { getBaseClassTeamInfoList } from '@/api/mes/baseClassTeamInfo';
import type { ProdBaseMachineInfoVO } from '@/api/mes/prodBaseMachineInfo/types';
import type { BaseShiftInfoVO } from '@/api/mes/baseShiftInfo/types';
import type { BaseClassTeamInfoVO } from '@/api/mes/baseClassTeamInfo/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -151,6 +163,11 @@ const records = ref<any[]>([]);
const currentIndex = ref(-1);
const currentRow = computed(() => (currentIndex.value >= 0 && currentIndex.value < records.value.length) ? records.value[currentIndex.value] : null);
/** 下拉框数据 */
const machineOptions = ref<ProdBaseMachineInfoVO[]>([]);
const shiftOptions = ref<BaseShiftInfoVO[]>([]);
const classTeamOptions = ref<BaseClassTeamInfoVO[]>([]);
/* ======================== 详情数据 ======================== */
const detailData = ref<MixTraceDetailVO | null>(null);
const summary = computed<any>(() => detailData.value?.summaryInfo || {});
@ -232,6 +249,36 @@ const handleReset = () => {
detailData.value = null;
};
/** 加载机台下拉选项 */
const loadMachineOptions = async () => {
try {
const res = await getProdBaseMachineInfoList({});
machineOptions.value = (res as any).data || [];
} catch {
machineOptions.value = [];
}
};
/** 加载班次下拉选项 */
const loadShiftOptions = async () => {
try {
const res = await getBaseShiftInfoList({});
shiftOptions.value = (res as any).data || [];
} catch {
shiftOptions.value = [];
}
};
/** 加载班组下拉选项 */
const loadClassTeamOptions = async () => {
try {
const res = await getBaseClassTeamInfoList({});
classTeamOptions.value = (res as any).data || [];
} catch {
classTeamOptions.value = [];
}
};
/* 导航按钮 */
const goFirst = () => { if (records.value.length > 0) currentIndex.value = 0; };
const goPrev = () => { if (currentIndex.value > 0) currentIndex.value--; };
@ -323,6 +370,10 @@ const handleResize = () => { curveChart?.resize(); };
onMounted(() => {
window.addEventListener('resize', handleResize);
//
loadMachineOptions();
loadShiftOptions();
loadClassTeamOptions();
});
onBeforeUnmount(() => {

Loading…
Cancel
Save