新增混炼示方生成预览与批量创建功能,优化相关字段及用户交互,修复界面显示问题,增强系统稳定性和用户体验。

This commit is contained in:
geht
2026-05-22 19:43:41 +08:00
parent f3e3a99ebc
commit c85657d199
30 changed files with 1786 additions and 61 deletions

View File

@@ -0,0 +1,193 @@
<template>
<BasicModal
v-bind="$attrs"
title="生成混炼示方"
:width="880"
destroyOnClose
@register="registerModal"
@ok="handleConfirm"
>
<a-spin :spinning="loading">
<div v-if="rubberName" class="generate-mixing-tip">
胶料名称<strong>{{ rubberName }}</strong>混合段数<strong>{{ mixingStages }}</strong>确认后将按预览行 × 机台生成混炼示方
</div>
<a-table
:columns="tableColumns"
:data-source="tableRows"
:pagination="false"
row-key="rowKey"
size="small"
bordered
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'machines'">
<div class="machine-cell">
<a-input
:value="formatMachineNames(record.machines)"
readonly
placeholder="请点击选择机台(可多选)"
class="machine-picker-input"
@click="openMachinePicker(record)"
/>
<a-button type="link" size="small" @click="openMachinePicker(record)">选择</a-button>
</div>
</template>
</template>
</a-table>
<div v-if="totalGenerateCount > 0" class="generate-mixing-summary">
预计生成 <strong>{{ totalGenerateCount }}</strong> 条混炼示方
</div>
</a-spin>
<MesXslEquipmentLedgerMultiSelectModal @register="registerMachineModal" @select="onMachineSelect" />
</BasicModal>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import MesXslEquipmentLedgerMultiSelectModal from '/@/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerMultiSelectModal.vue';
import { buildMixingGeneratePreview, generateMixingSpec } from '../MesXslFormulaSpec.api';
const emit = defineEmits(['register', 'success']);
const { createMessage } = useMessage();
const loading = ref(false);
const formulaSpecId = ref('');
const rubberName = ref('');
const mixingStages = ref(0);
const tableRows = ref<Recordable[]>([]);
const editingRowKey = ref<number | null>(null);
function formatStageCountText(record: Recordable) {
const current = record?.stageIndex;
const total = mixingStages.value;
if (total > 0) {
return `${current ?? ''}/${total}`;
}
return current != null ? String(current) : '';
}
const tableColumns = [
{ title: '示方编号', dataIndex: 'specCode', width: 220 },
{ title: '段数', dataIndex: 'stageIndex', width: 72, customRender: ({ record }) => formatStageCountText(record) },
{ title: '机台', dataIndex: 'machines' },
];
const totalGenerateCount = computed(() =>
tableRows.value.reduce((sum, row) => sum + (row.machines?.length || 0), 0),
);
const [registerMachineModal, { openModal: openMachineModalInner }] = useModal();
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
formulaSpecId.value = data?.formulaSpecId || '';
tableRows.value = [];
rubberName.value = '';
mixingStages.value = 0;
setModalProps({ confirmLoading: false });
if (!formulaSpecId.value) {
createMessage.warning('未指定配合示方');
return;
}
loading.value = true;
try {
const preview = await buildMixingGeneratePreview({ formulaSpecId: formulaSpecId.value });
rubberName.value = preview?.rubberName || '';
mixingStages.value = preview?.mixingStages || 0;
tableRows.value = (preview?.items || []).map((item: Recordable) => ({
rowKey: item.rowKey,
specCode: item.specCode,
stageIndex: item.stageIndex,
aSegmentIndex: item.aSegmentIndex,
stepType: item.stepType,
machines: [],
}));
if (!tableRows.value.length) {
createMessage.warning('无可生成的混炼段,请检查混合段数');
}
} finally {
loading.value = false;
}
});
function formatMachineNames(machines: Recordable[] = []) {
return machines.map((m) => m.machineName).filter(Boolean).join('、');
}
function openMachinePicker(record: Recordable) {
editingRowKey.value = record.rowKey;
openMachineModalInner(true, { selectedMachines: record.machines || [] });
}
function onMachineSelect(machines: Recordable[]) {
const key = editingRowKey.value;
if (key == null) {
return;
}
const row = tableRows.value.find((r) => r.rowKey === key);
if (row) {
row.machines = machines || [];
}
editingRowKey.value = null;
}
async function handleConfirm() {
if (!formulaSpecId.value) {
createMessage.warning('未指定配合示方');
return;
}
if (!tableRows.value.length) {
createMessage.warning('无可生成的混炼段');
return;
}
const emptyMachine = tableRows.value.find((r) => !r.machines?.length);
if (emptyMachine) {
createMessage.warning(`请为示方「${emptyMachine.specCode}」选择机台`);
return;
}
setModalProps({ confirmLoading: true });
try {
const res = await generateMixingSpec({
formulaSpecId: formulaSpecId.value,
rows: tableRows.value.map((r) => ({
specCode: r.specCode,
stageIndex: r.stageIndex,
aSegmentIndex: r.aSegmentIndex,
stepType: r.stepType,
machines: (r.machines || []).map((m: Recordable) => ({
machineId: m.machineId,
machineName: m.machineName,
})),
})),
});
const count = Number(res?.count ?? 0);
createMessage.success(count > 0 ? `成功生成 ${count} 条混炼示方` : '生成成功');
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
<style lang="less" scoped>
.generate-mixing-tip {
margin-bottom: 12px;
color: rgba(0, 0, 0, 0.65);
}
.machine-cell {
display: flex;
align-items: center;
gap: 4px;
.machine-picker-input {
flex: 1;
cursor: pointer;
}
}
.generate-mixing-summary {
margin-top: 12px;
text-align: right;
color: rgba(0, 0, 0, 0.85);
}
</style>