主材出站界面优化

This commit is contained in:
tao
2026-01-09 16:37:16 +08:00
parent 541edc1f4e
commit c7f118dab1
2 changed files with 189 additions and 21 deletions

View File

@@ -59,7 +59,8 @@ const handleInfeed = (record: any) => {
router.push({ name: 'Infeed' }); router.push({ name: 'Infeed' });
}; };
const handleOutfeed = () => { const handleOutfeed = (record: any) => {
jobStore.setInfo(record);
router.push({ name: 'Outfeed' }); router.push({ name: 'Outfeed' });
}; };
@@ -96,7 +97,7 @@ defineExpose({
<template v-if="column.key === 'action'"> <template v-if="column.key === 'action'">
<a-space> <a-space>
<a-button size="large" type="primary" @click="handleInfeed(record)">进站</a-button> <a-button size="large" type="primary" @click="handleInfeed(record)">进站</a-button>
<a-button size="large" type="primary" danger @click="handleOutfeed">出站</a-button> <a-button size="large" type="primary" danger @click="handleOutfeed(record)">出站</a-button>
</a-space> </a-space>
</template> </template>
</template> </template>

View File

@@ -1,10 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, computed, getCurrentInstance } from 'vue'; import { ref, reactive, onMounted, computed, getCurrentInstance } from 'vue';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useJobStore } from '@/store'; import { useJobStore } from '@/store';
import type { ColumnsType } from 'ant-design-vue/es/table/interface'; import type { ColumnsType } from 'ant-design-vue/es/table/interface';
import { listMainMaterialEntryLog } from '@/api/pwoManage/primaryMaterial' import { listMainMaterialEntryLog, listMainMaterialOutboundLog, batchAddMainMaterialOutboundLog, getMainMaterialOutboundLog, updateMainMaterialOutboundLog, delMainMaterialOutboundLog } from "@/api/pwoManage/primaryMaterial";
import { listMainMaterialOutboundLog } from '@/api/pwoManage/primaryMaterial';
const { proxy } = getCurrentInstance() as any const { proxy } = getCurrentInstance() as any
const { main_material_ok_level, main_material_ng_level } = proxy.useDict("main_material_ok_level", "main_material_ng_level") const { main_material_ok_level, main_material_ng_level } = proxy.useDict("main_material_ok_level", "main_material_ng_level")
@@ -15,8 +14,12 @@ interface PrimaryMaterialTableItem {
key: string; key: string;
waferCode: string; waferCode: string;
dieCode: string; dieCode: string;
result: 'OK' | 'NG'; xcoordinates: string;
ycoordinates: string;
outputResult: 'OK' | 'NG';
qualityLevel: string; qualityLevel: string;
createBy: string;
createTime: string;
[key: string]: any; [key: string]: any;
} }
@@ -24,9 +27,13 @@ const primaryMaterialColumns = [
{ title: '序号', dataIndex: 'index', key: 'index', align: 'center', width: 80 }, { title: '序号', dataIndex: 'index', key: 'index', align: 'center', width: 80 },
{ title: 'Wafer ID', dataIndex: 'waferCode', key: 'waferCode', align: 'center' }, { title: 'Wafer ID', dataIndex: 'waferCode', key: 'waferCode', align: 'center' },
{ title: 'Die ID', dataIndex: 'dieCode', key: 'dieCode', align: 'center' }, { title: 'Die ID', dataIndex: 'dieCode', key: 'dieCode', align: 'center' },
{ title: '结果', dataIndex: 'result', key: 'result', align: 'center' }, { title: 'Die X 坐标', dataIndex: 'xcoordinates', key: 'xcoordinates', align: 'center' },
{ title: 'Die Y 坐标', dataIndex: 'ycoordinates', key: 'ycoordinates', align: 'center' },
{ title: '结果', dataIndex: 'outputResult', key: 'outputResult', align: 'center' },
{ title: '质量等级', dataIndex: 'qualityLevel', key: 'qualityLevel' }, { title: '质量等级', dataIndex: 'qualityLevel', key: 'qualityLevel' },
{ title: '操作', key: 'action', align: 'center', width: 120 }, { title: '创建人', dataIndex: 'createBy', key: 'createBy' },
{ title: '创建时间', dataIndex: 'createTime', key: 'createTime' },
{ title: '操作', key: 'action', align: 'center', width: 180 },
]; ];
// 总计数据 // 总计数据
@@ -34,8 +41,8 @@ const totals = computed(() => {
let okNum = 0; let okNum = 0;
let ngNum = 0; let ngNum = 0;
primaryMaterialTableData.value.forEach(({ result, qualityLevel }) => { primaryMaterialTableData.value.forEach(({ outputResult, qualityLevel }) => {
if (result === 'OK') { if (outputResult === 'OK') {
okNum++; okNum++;
} else { } else {
ngNum++; ngNum++;
@@ -52,21 +59,120 @@ const fetchPrimaryMaterialList = async () => {
if (!stationId) return; if (!stationId) return;
loadingPrimaryMaterialList.value = true; loadingPrimaryMaterialList.value = true;
try { try {
const { rows } = await listMainMaterialEntryLog({ stationId }); const { rows } = await listMainMaterialOutboundLog({ stationId });
primaryMaterialTableData.value = rows; primaryMaterialTableData.value = rows;
} catch (error: any) { } catch (error: any) {
message.error(error.message || '查询治具列表失败'); message.error(error.message || '查询失败');
} finally { } finally {
loadingPrimaryMaterialList.value = false; loadingPrimaryMaterialList.value = false;
} }
} }
const openPickPrimaryMaterial = ref(false);
interface InfeedMaterialTableItem {
key: string;
waferCode: string;
dieCode: string;
result: 'OK' | 'NG';
qualityLevel: string;
[key: string]: any;
}
const infeedMaterialColumns = [
{ title: '序号', dataIndex: 'index', key: 'index', align: 'center', width: 80 },
{ title: 'Wafer ID', dataIndex: 'waferCode', key: 'waferCode', align: 'center' },
{ title: 'Die ID', dataIndex: 'dieCode', key: 'dieCode', align: 'center' },
{ title: '结果', dataIndex: 'result', key: 'result', align: 'center' },
{ title: '质量等级', dataIndex: 'qualityLevel', key: 'qualityLevel' },
];
const infeedMaterialTableData = ref<InfeedMaterialTableItem[]>([]);
// 挑选主材
const handlePickPrimaryMaterial = async () => {
const stationId = jobStore.jobInfo.id;
if (!stationId) return;
try {
const { rows } = await listMainMaterialEntryLog({ stationId });
infeedMaterialTableData.value = rows.map(item => {
return {
...item,
result: 'OK',
qualityLevel: main_material_ok_level.value[0].value || '',
}
});
openPickPrimaryMaterial.value = true;
} catch (err: any) {
message.error(err.message);
}
}
const openEditRecordModal = ref(false);
const editingRecord = reactive<any>({});
// 修改主材出站记录
const handleEditRecord = (record: any) => {
Object.assign(editingRecord, record);
openEditRecordModal.value = true;
}
// 提交修改主材出站记录
const handleSubmitEdit = async () => {
try {
await updateMainMaterialOutboundLog(editingRecord);
openEditRecordModal.value = false;
} catch (err: any) {
message.error(err.message || '修改失败');
}
}
// 删除主材出站记录
const handleDeleteRecord = async (record: any) => {
try {
await delMainMaterialOutboundLog(record.id);
message.success('删除成功');
} catch (err: any) {
message.error(err.message || '删除失败');
}
}
// 选择主材
const rowSelection = ref<any[]>([]);
const selectedKeys = ref<any>([]);
const handleChangeSelection = (selectedRowKeys: any, selectedRows: InfeedMaterialTableItem[]) => {
selectedKeys.value = selectedRowKeys;
rowSelection.value = selectedRows.map(item => {
return {
mainMaterialId: item.waferId ?? item.dieId,
result: item.result,
qualityLevel: item.qualityLevel,
}
})
}
// 提交主材出站
const submitOutfeed = async () => {
const stationCode = jobStore.jobInfo.code;
try {
await batchAddMainMaterialOutboundLog({ stationCode, outbounds: rowSelection.value });
message.success("出站成功");
handleCancel();
fetchPrimaryMaterialList();
} catch (err: any) {
message.error(err.message || '提交失败');
}
}
// 取消选择主材
const handleCancel = () => {
rowSelection.value = [];
selectedKeys.value = [];
}
// 计算表格高度 // 计算表格高度
const customTable = ref<HTMLElement | null>(null) const customTable = ref<HTMLElement | null>(null)
const tableHeight = ref(200) const tableHeight = ref(200)
const renderTableHeight = () => { const renderTableHeight = () => {
if (customTable.value) { if (customTable.value) {
tableHeight.value = customTable.value.clientHeight - 50 tableHeight.value = customTable.value.clientHeight - 60
console.log('元素高度:', tableHeight.value) console.log('元素高度:', tableHeight.value)
} }
} }
@@ -85,25 +191,31 @@ fetchPrimaryMaterialList()
<template> <template>
<div class="equipment__container"> <div class="equipment__container">
<Title name="主材报工" showRefresh @refresh="fetchPrimaryMaterialList" /> <Title name="主材报工" showRefresh @refresh="fetchPrimaryMaterialList" />
<a-button size="large" @click="handlePickPrimaryMaterial">选择主材</a-button>
<div class="table-wrapper" ref="customTable"> <div class="table-wrapper" ref="customTable">
<a-table :dataSource="primaryMaterialTableData" :columns="primaryMaterialColumns as ColumnsType<PrimaryMaterialTableItem>" <a-table :dataSource="primaryMaterialTableData" :columns="primaryMaterialColumns as ColumnsType<PrimaryMaterialTableItem>"
:pagination="false" bordered sticky size="middle" :scroll="{ y: tableHeight }" :pagination="false" bordered sticky :scroll="{ y: tableHeight }"
:loading="loadingPrimaryMaterialList"> :loading="loadingPrimaryMaterialList">
<template #bodyCell="{ column, index, record }"> <template #bodyCell="{ column, index, record }">
<template v-if="column.key === 'index'">{{ index + 1 }}</template> <template v-if="column.key === 'index'">{{ index + 1 }}</template>
<template v-if="column.key === 'result'"> <template v-if="column.key === 'outputResult'">
<a-switch v-model:checked="record.result" checked-children="NG" checkedValue="NG" un-checked-children="OK" unCheckedValue="OK" /> <a-switch v-model:checked="record.outputResult" checked-children="NG" checkedValue="NG" un-checked-children="OK" unCheckedValue="OK" />
</template> </template>
<template v-if="column.key === 'qualityLevel'"> <template v-if="column.key === 'qualityLevel'">
<a-select v-model:value="record.qualityLevel" style="width: 80%" v-if="record.result === 'OK'"> <a-select v-model:value="record.qualityLevel" style="width: 80%" v-if="record.outputResult === 'NG'">
<a-select-option v-for="dict in main_material_ok_level" :value="dict.value">{{ dict.label }}</a-select-option>
</a-select>
<a-select v-model:value="record.qualityLevel" style="width: 80%" v-else>
<a-select-option v-for="dict in main_material_ng_level" :value="dict.value">{{ dict.label }}</a-select-option> <a-select-option v-for="dict in main_material_ng_level" :value="dict.value">{{ dict.label }}</a-select-option>
</a-select> </a-select>
<a-select v-model:value="record.qualityLevel" style="width: 80%" v-if="record.outputResult === 'OK'">
<a-select-option v-for="dict in main_material_ok_level" :value="dict.value">{{ dict.label }}</a-select-option>
</a-select>
</template> </template>
<template v-if="column.key === 'action'"> <template v-if="column.key === 'action'">
<a-button @click="">查看明细</a-button> <a-space>
<a-button @click="handleEditRecord(record)">修改</a-button>
<a-popconfirm title="确定删除该记录?" ok-text="" cancel-text="" @confirm="handleDeleteRecord(record)">
<a-button danger>删除</a-button>
</a-popconfirm>
</a-space>
</template> </template>
</template> </template>
<template #summary> <template #summary>
@@ -119,6 +231,61 @@ fetchPrimaryMaterialList()
</template> </template>
</a-table> </a-table>
</div> </div>
<a-modal v-model:open="openEditRecordModal" title="修改主材出站记录" @ok="handleSubmitEdit">
<a-form :model="editingRecord" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
<a-form-item label="Wafer ID">
<a-input v-model:value="editingRecord.waferCode" disabled />
</a-form-item>
<a-form-item label="Die ID">
<a-input v-model:value="editingRecord.dieCode" disabled />
</a-form-item>
<a-form-item label="Die X 坐标">
<a-input v-model:value="editingRecord.xcoordinates" disabled />
</a-form-item>
<a-form-item label="Die Y 坐标">
<a-input v-model:value="editingRecord.ycoordinates" disabled />
</a-form-item>
<a-form-item label="结果" :rules="[{ required: true, message: '请选择结果!' }]">
<a-switch v-model:checked="editingRecord.outputResult" checked-children="NG" checkedValue="NG"
un-checked-children="OK" unCheckedValue="OK" />
</a-form-item>
<a-form-item label="质量等级" :rules="[{ required: true, message: '请选择质量等级!' }]">
<a-select v-model:value="editingRecord.qualityLevel" style="width: 80%" v-if="editingRecord.outputResult === 'NG'">
<a-select-option v-for="dict in main_material_ng_level" :value="dict.value">{{ dict.label
}}</a-select-option>
</a-select>
<a-select v-model:value="editingRecord.qualityLevel" style="width: 80%" v-if="editingRecord.outputResult === 'OK'">
<a-select-option v-for="dict in main_material_ok_level" :value="dict.value">{{ dict.label
}}</a-select-option>
</a-select>
</a-form-item>
</a-form>
</a-modal>
<a-modal v-model:open="openPickPrimaryMaterial" title="选择主材出站" width="50vw" @ok="submitOutfeed" @cancel="handleCancel">
已选择 {{ rowSelection.length }} 条主材
<a-table :dataSource="infeedMaterialTableData" :row-selection="{ selectedRowKeys: selectedKeys, onChange: handleChangeSelection }" row-key="id"
:columns="infeedMaterialColumns as ColumnsType<InfeedMaterialTableItem>" :pagination="false" bordered sticky>
<template #bodyCell="{ column, index, record }">
<template v-if="column.key === 'index'">{{ index + 1 }}</template>
<template v-if="column.key === 'result'">
<a-switch v-model:checked="record.result" checked-children="NG" checkedValue="NG"
un-checked-children="OK" unCheckedValue="OK" />
</template>
<template v-if="column.key === 'qualityLevel'">
<a-select v-model:value="record.qualityLevel" style="width: 80%" v-if="record.result === 'NG'">
<a-select-option v-for="dict in main_material_ng_level" :value="dict.value">{{ dict.label
}}</a-select-option>
</a-select>
<a-select v-model:value="record.qualityLevel" style="width: 80%" v-if="record.result === 'OK'">
<a-select-option v-for="dict in main_material_ok_level" :value="dict.value">{{ dict.label
}}</a-select-option>
</a-select>
</template>
</template>
</a-table>
</a-modal>
</div> </div>
</template> </template>