Files
qhmes/jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue

1175 lines
41 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<BasicModal
v-bind="$attrs"
destroyOnClose
:width="'96%'"
:defaultFullscreen="true"
wrapClassName="mixing-spec-modal-wrap"
@register="registerModal"
@ok="handleSubmit"
>
<template #title>{{ title }}</template>
<div class="mixing-sheet">
<!--update-begin---author:cursor ---date:20260522 forXSLMES-20260522-A17顶部施工表对齐旧系统13列表格----------- -->
<table class="mixing-form-table">
<tbody>
<tr class="form-title-row">
<th class="formTitle" colspan="13">TBR混合施工表</th>
</tr>
<tr>
<th class="formTitle required" rowspan="3">规格</th>
<td class="formValue" colspan="3" rowspan="3">
<a-input v-model:value="sheetForm.specName" :disabled="!showFooter" :bordered="false" class="form-input" />
</td>
<th class="formTitle" colspan="2">机台</th>
<th class="formTitle" colspan="1">制作日期</th>
<td class="formValue" colspan="2">
<a-date-picker v-model:value="sheetForm.makeDate" value-format="YYYY-MM-DD" :disabled="!showFooter" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle" colspan="1">发行编号</th>
<td class="formValue" colspan="3">
<a-select
v-model:value="sheetForm.issueNumber"
show-search
allow-clear
:options="issueNumberOptions"
:disabled="!showFooter"
:filter-option="selectFilterOption"
:bordered="false"
class="form-input"
style="width: 100%"
/>
</td>
</tr>
<tr>
<td class="formValue" colspan="2" rowspan="2">
<a-input v-model:value="sheetForm.machineName" :disabled="!showFooter" :bordered="false" class="form-input" />
</td>
</tr>
<tr>
<th class="formTitle" colspan="1">换算系数</th>
<td class="formValue" colspan="2">
<a-input-number v-model:value="sheetForm.convertFactor" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle" colspan="1">填充体积</th>
<td class="formValue" colspan="1">
<a-input-number v-model:value="sheetForm.fillVolume" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle" colspan="1">回收炭黑()</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.recycleCarbonSec" :disabled="!showFooter" :precision="0" :bordered="false" class="form-input" style="width: 100%" />
</td>
</tr>
<tr>
<th class="formTitle required" rowspan="2">用途</th>
<td class="formValue" colspan="3" rowspan="2">
<a-select
v-model:value="sheetForm.purpose"
show-search
allow-clear
:options="purposeOptions"
:disabled="!showFooter"
:filter-option="selectFilterOption"
:bordered="false"
class="form-input"
style="width: 100%"
/>
</td>
<th class="formTitle" colspan="1">母胶比重</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.motherRubberSg" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle">段数</th>
<td class="formValue" colspan="2">
<a-input-number v-model:value="sheetForm.stageCount" :disabled="!showFooter" :precision="0" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle" colspan="1">纯混炼时间()</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.pureMixSec" :disabled="!showFooter" :precision="0" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle" colspan="1">回收炭黑(KG)</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.recycleCarbonKg" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
</tr>
<tr>
<th class="formTitle" colspan="1">终炼胶比重</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.finalRubberSg" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle" colspan="1">适用工厂</th>
<td class="formValue" colspan="2">
<a-input v-model:value="sheetForm.applyFactory" :disabled="!showFooter" :bordered="false" class="form-input" />
</td>
<th class="formTitle" colspan="1">自动小料打印设定</th>
<td class="formValue">
<a-input v-model:value="sheetForm.autoSmallPrintSetting" :disabled="!showFooter" :bordered="false" class="form-input" />
</td>
<th class="formTitle" colspan="1">设定车数</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.setTrainCount" :disabled="!showFooter" :precision="0" :bordered="false" class="form-input" style="width: 100%" />
</td>
</tr>
<tr>
<td colspan="13" class="form-nested-wrap">
<table class="mixing-form-table mixing-form-nested">
<tbody>
<tr>
<th class="formTitle" colspan="12">配方参数设定</th>
</tr>
<tr>
<th class="formTitle">侧壁水温</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.sideWallWaterTemp" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle">超时排胶时间</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.overtimeDischargeSec" :disabled="!showFooter" :precision="0" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle">超温排胶时间</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.overtempDischargeSec" :disabled="!showFooter" :precision="0" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle">超温排胶温度</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.overtempDischargeTemp" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle">卸料门水温</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.doorWaterTemp" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
<th class="formTitle">转子水温</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.rotorWaterTemp" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
</tr>
<tr>
<th class="formTitle">最高进料温度</th>
<td class="formValue">
<a-input-number v-model:value="sheetForm.maxFeedTemp" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
</td>
<td class="formValue blank" colspan="10"></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!--update-end---author:cursor ---date:20260522 forXSLMES-20260522-A17顶部施工表对齐旧系统13列表格----------- -->
<div class="sheet-panels">
<div class="panel panel-left" :style="materialPanelStyle">
<div class="panel-head">
<span>橡胶及配合剂</span>
<div v-if="showFooter" class="panel-head-actions" @click.stop>
<MesXslMixingMaterialColumnSetting v-model:hidden-keys="materialHiddenColumnKeys" />
<MesXslMixingTableRowHeightSetting table-key="material" v-model:preference="materialHeightPref" />
<a-button size="small" type="primary" @click="addMaterialRow">新增行</a-button>
</div>
<div v-else class="panel-head-actions" @click.stop>
<MesXslMixingTableRowHeightSetting table-key="material" v-model:preference="materialHeightPref" />
</div>
</div>
<div class="material-table-wrap" :style="{ height: `${materialMainTableHeight}px` }">
<JVxeTable
:key="materialTableLayoutKey"
ref="materialRef"
row-number
keep-source
bordered
:fit="false"
:column-config="{ resizable: true }"
:row-config="materialRowConfig"
size="mini"
:height="materialMainTableHeight"
:scroll-x="{ enabled: false }"
:scroll-y="{ enabled: true }"
:columns="visibleMaterialColumns"
:dataSource="materialData"
:disabled="!showFooter"
@resizable-change="handleMaterialColumnResize"
@column-resizable-change="handleMaterialColumnResize"
/>
</div>
<!--update-begin---author:cursor ---date:20260522 forXSLMES-20260522-A18TCU温度条件表移至橡胶及配合剂下方----------- -->
<div class="left-panel-section left-panel-section-tcu">
<div class="panel-head">
<span>TCU温度条件</span>
<div class="panel-head-actions" @click.stop>
<MesXslMixingTableRowHeightSetting table-key="tcu" v-model:preference="tcuHeightPref" />
</div>
</div>
<div class="tcu-table-wrap" :style="tcuTableWrapStyle">
<JVxeTable
:key="tcuTableLayoutKey"
ref="tcuRef"
row-number
keep-source
bordered
:fit="false"
:column-config="{ resizable: true }"
:row-config="tcuRowConfig"
:show-header-overflow="false"
size="mini"
:height="tcuTableHeight"
:scroll-x="{ enabled: false }"
:columns="visibleTcuColumns"
:dataSource="tcuData"
:disabled="!showFooter"
@value-change="handleTcuValueChange"
@resizable-change="handleTcuColumnResize"
@column-resizable-change="handleTcuColumnResize"
/>
</div>
</div>
<!--update-end---author:cursor ---date:20260522 forXSLMES-20260522-A18TCU温度条件表移至橡胶及配合剂下方----------- -->
</div>
<div class="panel panel-right">
<div class="panel panel-step-main">
<div class="panel-head">
<span>混合步骤</span>
<div class="panel-head-actions" @click.stop>
<MesXslMixingTableRowHeightSetting table-key="step" v-model:preference="stepHeightPref" />
<a-button v-if="showFooter" size="small" type="primary" @click="addStepRow">新增行</a-button>
</div>
</div>
<!--update-begin---author:cursor ---date:20260522 forXSLMES-20260522-A21混合步骤与下密炼机列宽同步可调----------- -->
<div class="step-table-wrap" :style="{ height: `${stepMainTableHeight}px` }">
<JVxeTable
:key="stepTableLayoutKey"
ref="stepRef"
row-number
keep-source
bordered
:fit="true"
:column-config="{ resizable: true }"
:row-config="stepRowConfig"
size="mini"
:height="stepMainTableHeight"
:scroll-y="{ enabled: true }"
:columns="visibleStepColumns"
:dataSource="stepData"
:disabled="!showFooter"
@resizable-change="handleStepColumnResize"
@column-resizable-change="handleStepColumnResize"
/>
</div>
<!--update-end---author:cursor ---date:20260522 forXSLMES-20260522-A21混合步骤与下密炼机列宽同步可调----------- -->
</div>
<div class="panel panel-down-step">
<div class="panel-head">
<span>下密炼机混炼条件</span>
<div class="panel-head-actions" @click.stop>
<MesXslMixingTableRowHeightSetting table-key="downStep" v-model:preference="downStepHeightPref" />
<a-button v-if="showFooter" size="small" type="primary" @click="addDownStepRow">新增行</a-button>
</div>
</div>
<div class="step-table-wrap step-table-wrap--compact" :style="{ height: `${downStepTableHeight}px` }">
<JVxeTable
:key="downStepTableLayoutKey"
ref="downStepRef"
row-number
keep-source
bordered
:fit="true"
:column-config="{ resizable: true }"
:row-config="downStepRowConfig"
size="mini"
:height="downStepTableHeight"
:columns="visibleStepColumns"
:dataSource="downStepData"
:disabled="!showFooter"
@resizable-change="handleStepColumnResize"
@column-resizable-change="handleStepColumnResize"
/>
</div>
</div>
</div>
</div>
<!-- 页脚审批签字区五列只读展示 -->
<div class="sheet-sign-footer">
<div class="sign-grid sign-grid-head">
<div class="sign-cell sign-title">起草人</div>
<div class="sign-cell sign-title">校对人</div>
<div class="sign-cell sign-title">审核人</div>
<div class="sign-cell sign-title">批准人</div>
<div class="sign-cell sign-title sign-title-stack">
<span>变更人</span>
<span>变更日期</span>
</div>
</div>
<div class="sign-grid sign-grid-name">
<div class="sign-cell sign-value sign-text">{{ signDisplay.draftBy || '—' }}</div>
<div class="sign-cell sign-value sign-text">{{ signDisplay.proofreadBy || '—' }}</div>
<div class="sign-cell sign-value sign-text">{{ signDisplay.auditBy || '—' }}</div>
<div class="sign-cell sign-value sign-text">{{ signDisplay.approveBy || '—' }}</div>
<div class="sign-cell sign-value sign-text">{{ signDisplay.changeBy || '—' }}</div>
</div>
<div class="sign-grid sign-grid-time">
<div class="sign-cell sign-value sign-text">{{ signDisplay.draftTime || '—' }}</div>
<div class="sign-cell sign-value sign-text">{{ signDisplay.proofreadTime || '—' }}</div>
<div class="sign-cell sign-value sign-text">{{ signDisplay.auditTime || '—' }}</div>
<div class="sign-cell sign-value sign-text">{{ signDisplay.approveTime || '—' }}</div>
<div class="sign-cell sign-value sign-text">{{ signDisplay.changeDate || '—' }}</div>
</div>
</div>
<BasicForm v-show="false" @register="registerForm" />
</div>
</BasicModal>
</template>
<script lang="ts" setup>
import { computed, reactive, ref, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { useMessage } from '/@/hooks/web/useMessage';
import { useUserStore } from '/@/store/modules/user';
import {
mainSchema,
materialColumns,
stepColumns,
tcuColumns,
loadMixingMaterialHiddenColumnKeys,
loadMixingMaterialColumnWidths,
saveMixingMaterialColumnWidths,
applyMixingMaterialColumnVisibility,
applyMixingMaterialColumnWidths,
calcMixingMaterialTableWidth,
calcMixingDetailTableViewportHeight,
buildMixingTableRowConfig,
loadMixingTableHeightPreference,
calcMixingTcuTableWidth,
loadMixingTcuColumnWidths,
saveMixingTcuColumnWidths,
applyMixingTcuColumnWidths,
loadMixingStepColumnWidths,
saveMixingStepColumnWidths,
applyMixingStepColumnWidths,
createEmptyMaterialRows,
createEmptyStepRows,
createEmptyDownStepRows,
normalizeMixingDetailRows,
MIXING_MATERIAL_MIN_COLUMN_WIDTH,
MIXING_TCU_MIN_COLUMN_WIDTH,
MIXING_STEP_MIN_COLUMN_WIDTH,
} from '../MesXslMixingSpec.data';
import { saveOrUpdate, queryById, queryIssueNumberOptions, queryPurposeOptions } from '../MesXslMixingSpec.api';
import MesXslMixingMaterialColumnSetting from './MesXslMixingMaterialColumnSetting.vue';
import MesXslMixingTableRowHeightSetting from './MesXslMixingTableRowHeightSetting.vue';
const emit = defineEmits(['register', 'success']);
const { createMessage } = useMessage();
const userStore = useUserStore();
const isUpdate = ref(false);
const showFooter = ref(true);
const issueNumberOptions = ref<{ label: string; value: string }[]>([]);
const purposeOptions = ref<{ label: string; value: string }[]>([]);
const materialRef = ref();
const stepRef = ref();
const downStepRef = ref();
const tcuRef = ref();
const materialData = ref<Recordable[]>([]);
const stepData = ref<Recordable[]>([]);
const downStepData = ref<Recordable[]>([]);
const tcuData = ref<Recordable[]>([]);
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A17】橡胶及配合剂明细列展示设置-----------
const materialHiddenColumnKeys = ref<string[]>(loadMixingMaterialHiddenColumnKeys());
const materialColumnWidths = ref<Record<string, number>>(loadMixingMaterialColumnWidths());
const visibleMaterialColumns = computed(() =>
applyMixingMaterialColumnWidths(
applyMixingMaterialColumnVisibility(materialColumns, materialHiddenColumnKeys.value),
materialColumnWidths.value,
),
);
const materialTableWidth = computed(() => calcMixingMaterialTableWidth(visibleMaterialColumns.value, materialColumnWidths.value));
const materialTableColumnKey = computed(() => materialHiddenColumnKeys.value.join('|') || 'all');
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A32】四明细表行高/展示行数设置持久化-----------
const materialHeightPref = ref(loadMixingTableHeightPreference('material'));
const tcuHeightPref = ref(loadMixingTableHeightPreference('tcu'));
const stepHeightPref = ref(loadMixingTableHeightPreference('step'));
const downStepHeightPref = ref(loadMixingTableHeightPreference('downStep'));
const materialMainTableHeight = computed(() => calcMixingDetailTableViewportHeight('material', materialHeightPref.value));
const stepMainTableHeight = computed(() => calcMixingDetailTableViewportHeight('step', stepHeightPref.value));
const tcuTableHeight = computed(() => calcMixingDetailTableViewportHeight('tcu', tcuHeightPref.value));
const downStepTableHeight = computed(() => calcMixingDetailTableViewportHeight('downStep', downStepHeightPref.value));
const materialRowConfig = computed(() => buildMixingTableRowConfig(materialHeightPref.value));
const tcuRowConfig = computed(() => buildMixingTableRowConfig(tcuHeightPref.value));
const stepRowConfig = computed(() => buildMixingTableRowConfig(stepHeightPref.value));
const downStepRowConfig = computed(() => buildMixingTableRowConfig(downStepHeightPref.value));
const materialTableLayoutKey = computed(
() => `${materialTableColumnKey.value}-${materialHeightPref.value.rowHeight}-${materialHeightPref.value.visibleRowCount}`,
);
const tcuTableLayoutKey = computed(
() => `${tcuHeightPref.value.rowHeight}-${tcuHeightPref.value.visibleRowCount}-${tcuTableWidth.value}`,
);
const stepTableLayoutKey = computed(
() => `${stepHeightPref.value.rowHeight}-${stepHeightPref.value.visibleRowCount}-${visibleStepColumns.value.length}`,
);
const downStepTableLayoutKey = computed(
() => `${downStepHeightPref.value.rowHeight}-${downStepHeightPref.value.visibleRowCount}-${visibleStepColumns.value.length}`,
);
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A32】四明细表行高/展示行数设置持久化-----------
function handleMaterialColumnResize(params: Recordable) {
const column = params?.resizeColumn ?? params?.column;
const key = column?.params?.key ?? column?.field;
if (!key || column?.type === 'seq') {
return;
}
const width = Math.max(
MIXING_MATERIAL_MIN_COLUMN_WIDTH,
Math.round(Number(params?.resizeWidth ?? column?.renderWidth ?? column?.width)),
);
if (!width || Number.isNaN(width)) {
return;
}
materialColumnWidths.value = {
...materialColumnWidths.value,
[String(key)]: width,
};
saveMixingMaterialColumnWidths(materialColumnWidths.value);
}
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A17】橡胶及配合剂明细列展示设置-----------
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A19】TCU温度条件表列宽可调且表头换行-----------
const tcuColumnWidths = ref<Record<string, number>>(loadMixingTcuColumnWidths());
const visibleTcuColumns = computed(() => applyMixingTcuColumnWidths(tcuColumns, tcuColumnWidths.value));
const tcuTableWidth = computed(() => calcMixingTcuTableWidth(visibleTcuColumns.value, tcuColumnWidths.value));
const tcuTableWrapStyle = computed(() => ({
width: `${tcuTableWidth.value}px`,
height: `${tcuTableHeight.value}px`,
}));
const materialPanelStyle = computed(() => ({
width: `${Math.max(materialTableWidth.value, tcuTableWidth.value)}px`,
maxWidth: '100%',
}));
function handleTcuColumnResize(params: Recordable) {
const column = params?.resizeColumn ?? params?.column;
const key = column?.params?.key ?? column?.field;
if (!key || column?.type === 'seq') {
return;
}
const width = Math.max(
MIXING_TCU_MIN_COLUMN_WIDTH,
Math.round(Number(params?.resizeWidth ?? column?.renderWidth ?? column?.width)),
);
if (!width || Number.isNaN(width)) {
return;
}
tcuColumnWidths.value = {
...tcuColumnWidths.value,
[String(key)]: width,
};
saveMixingTcuColumnWidths(tcuColumnWidths.value);
}
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A19】TCU温度条件表列宽可调且表头换行-----------
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A21】混合步骤与下密炼机列宽同步可调-----------
const stepColumnWidths = ref<Record<string, number>>(loadMixingStepColumnWidths());
const visibleStepColumns = computed(() => applyMixingStepColumnWidths(stepColumns, stepColumnWidths.value));
function handleStepColumnResize(params: Recordable) {
const column = params?.resizeColumn ?? params?.column;
const key = column?.params?.key ?? column?.field;
if (!key || column?.type === 'seq') {
return;
}
const width = Math.max(
MIXING_STEP_MIN_COLUMN_WIDTH,
Math.round(Number(params?.resizeWidth ?? column?.renderWidth ?? column?.width)),
);
if (!width || Number.isNaN(width)) {
return;
}
stepColumnWidths.value = {
...stepColumnWidths.value,
[String(key)]: width,
};
saveMixingStepColumnWidths(stepColumnWidths.value);
}
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A21】混合步骤与下密炼机列宽同步可调-----------
const sheetForm = reactive<Recordable>({
id: '',
specName: '',
purpose: '',
machineName: '',
makeDate: '',
issueNumber: '',
convertFactor: null,
fillVolume: null,
recycleCarbonSec: null,
motherRubberSg: null,
finalRubberSg: null,
applyFactory: '',
stageCount: null,
pureMixSec: null,
recycleCarbonKg: null,
autoSmallPrintSetting: '',
setTrainCount: null,
sideWallWaterTemp: null,
overtimeDischargeSec: null,
overtempDischargeSec: null,
overtempDischargeTemp: null,
doorWaterTemp: null,
rotorWaterTemp: null,
maxFeedTemp: null,
draftBy: '',
draftTime: '',
proofreadBy: '',
proofreadTime: '',
auditBy: '',
auditTime: '',
approveBy: '',
approveTime: '',
changeDate: '',
});
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A17】页脚签章区只读展示-----------
const signDisplay = reactive({
draftBy: '',
draftTime: '',
proofreadBy: '',
proofreadTime: '',
auditBy: '',
auditTime: '',
approveBy: '',
approveTime: '',
changeBy: '',
changeDate: '',
});
function formatSignDateTime(value?: string) {
if (!value) {
return '';
}
const text = String(value);
return text.length >= 19 ? text.slice(0, 19) : text.slice(0, 10);
}
function formatSignDate(value?: string) {
if (!value) {
return '';
}
return String(value).slice(0, 10);
}
function refreshSignDisplay(row: Recordable = {}) {
signDisplay.draftBy = row.draftBy || row.createBy_dictText || row.createBy || '';
signDisplay.draftTime = formatSignDateTime(row.draftTime || row.createTime);
signDisplay.proofreadBy = row.proofreadBy || row.proofreadBy_dictText || '';
signDisplay.proofreadTime = formatSignDateTime(row.proofreadTime);
signDisplay.auditBy = row.auditBy || row.auditBy_dictText || '';
signDisplay.auditTime = formatSignDateTime(row.auditTime);
signDisplay.approveBy = row.approveBy || row.approveBy_dictText || '';
signDisplay.approveTime = formatSignDateTime(row.approveTime);
signDisplay.changeBy = row.updateBy_dictText || row.updateBy || '';
signDisplay.changeDate = formatSignDate(row.changeDate || row.updateTime);
}
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A17】页脚签章区只读展示-----------
const [registerForm, { resetFields, setFieldsValue, validate, setProps }] = useForm({
labelWidth: 96,
schemas: mainSchema,
showActionButtonGroup: false,
baseColProps: { span: 8 },
});
const selectFilterOption = (input: string, option: any) => String(option?.label || '').toLowerCase().includes(input.toLowerCase());
async function applyAutoCompleteSource() {
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A17】混炼示方用途/发行编号联想-----------
const issueRows = await queryIssueNumberOptions({});
const purposeRows = await queryPurposeOptions({});
const toOptions = (rows: any) => {
const list = Array.isArray(rows) ? rows : rows?.result || [];
return list.map((item) => ({ label: item.label, value: item.value }));
};
issueNumberOptions.value = toOptions(issueRows);
purposeOptions.value = toOptions(purposeRows);
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A17】混炼示方用途/发行编号联想-----------
}
function ensureTcuDefaultRows(rows: Recordable[] = []) {
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A17】TCU子表默认固定两行-----------
const up = rows.find((r) => r.sectionType === 'up_mixer') || { sectionType: 'up_mixer' };
const down = rows.find((r) => r.sectionType === 'down_mixer') || { sectionType: 'down_mixer', drugWeighPos: undefined };
return [up, down];
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A17】TCU子表默认固定两行-----------
}
function handleTcuValueChange(event) {
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A17】下密炼机禁用药品称量位置-----------
const row = event?.row;
const key = event?.column?.key;
if (!row || key !== 'drugWeighPos') {
return;
}
if (row.sectionType === 'down_mixer') {
row.drugWeighPos = undefined;
createMessage.warning('下密炼机不允许选择药品称量位置');
}
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A17】下密炼机禁用药品称量位置-----------
}
function resetSheetForm() {
Object.keys(sheetForm).forEach((key) => {
sheetForm[key] =
key === 'specName' ||
key === 'purpose' ||
key === 'machineName' ||
key === 'issueNumber' ||
key.endsWith('By') ||
key === 'applyFactory' ||
key === 'autoSmallPrintSetting'
? ''
: null;
});
sheetForm.id = '';
sheetForm.makeDate = '';
sheetForm.draftTime = '';
sheetForm.proofreadTime = '';
sheetForm.auditTime = '';
sheetForm.approveTime = '';
sheetForm.changeDate = '';
refreshSignDisplay({});
}
async function syncSheetToForm() {
await setFieldsValue({ ...sheetForm });
}
function addMaterialRow() {
materialRef.value?.addRows?.({});
}
function addStepRow() {
stepRef.value?.addRows?.({});
}
function addDownStepRow() {
downStepRef.value?.addRows?.({});
}
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
await resetFields();
resetSheetForm();
materialData.value = [];
stepData.value = [];
downStepData.value = [];
tcuData.value = ensureTcuDefaultRows([]);
isUpdate.value = !!data?.isUpdate;
showFooter.value = !!data?.showFooter;
await setProps({ disabled: !showFooter.value });
setModalProps({ showOkBtn: showFooter.value, showCancelBtn: showFooter.value, confirmLoading: false });
await applyAutoCompleteSource();
if (isUpdate.value && data?.record?.id) {
const raw = await queryById({ id: data.record.id });
const row = raw?.result || raw;
Object.assign(sheetForm, row || {});
refreshSignDisplay(row || {});
await syncSheetToForm();
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A22】明细表默认空行数-----------
materialData.value = normalizeMixingDetailRows(row?.materialList || []);
stepData.value = normalizeMixingDetailRows(row?.stepList || []);
downStepData.value = normalizeMixingDetailRows(row?.downStepList || []);
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A22】明细表默认空行数-----------
tcuData.value = ensureTcuDefaultRows(row?.tcuList || []);
} else {
const userInfo = userStore.getUserInfo || {};
refreshSignDisplay({
createBy_dictText: userInfo.realname,
createBy: userInfo.username,
});
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A22】明细表默认空行数-----------
materialData.value = createEmptyMaterialRows();
stepData.value = createEmptyStepRows();
downStepData.value = createEmptyDownStepRows();
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A22】明细表默认空行数-----------
await syncSheetToForm();
}
});
const title = computed(() => (!showFooter.value && unref(isUpdate) ? '混炼示方详情' : !unref(isUpdate) ? '新增混炼示方' : '编辑混炼示方'));
async function handleSubmit() {
await syncSheetToForm();
const formValues = await validate();
const materialList = materialRef.value?.getTableData?.() || materialData.value;
const stepList = stepRef.value?.getTableData?.() || stepData.value;
const downStepList = downStepRef.value?.getTableData?.() || downStepData.value;
const tcuList = ensureTcuDefaultRows((tcuRef.value?.getTableData?.() || tcuData.value) as Recordable[]);
const cleanRows = (rows: Recordable[]) => (rows || []).filter((row) => Object.values(row || {}).some((v) => v != null && v !== ''));
const payload = {
...formValues,
materialList: cleanRows(materialList),
stepList: cleanRows(stepList),
downStepList: cleanRows(downStepList),
tcuList: tcuList.map((row) => ({
...row,
drugWeighPos: row.sectionType === 'down_mixer' ? undefined : row.drugWeighPos,
})),
};
setModalProps({ confirmLoading: true });
try {
await saveOrUpdate(payload, unref(isUpdate));
createMessage.success(unref(isUpdate) ? '编辑成功' : '新增成功');
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
<style lang="less" scoped>
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A17】顶部施工表对齐旧系统13列表格-----------
@form-border: #ccc;
@form-label-bg: #f5f5f5;
@form-bg: #fcfdfd;
.mixing-sheet {
border: 1px solid @form-border;
background: @form-bg;
overflow-x: auto;
}
.mixing-form-table {
width: 100%;
min-width: 1350px;
border-collapse: collapse;
table-layout: fixed;
background: @form-bg;
th.formTitle {
height: 28px;
padding: 0 4px;
border: 1px solid @form-border;
background: @form-label-bg;
color: #333;
font-size: 12px;
font-weight: 600;
text-align: center;
vertical-align: middle;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
th.formTitle.required::before {
content: '*';
color: #ff4d4f;
margin-right: 2px;
}
td.formValue {
height: 28px;
padding: 0;
border: 1px solid @form-border;
background: #fff;
text-align: center;
vertical-align: middle;
}
td.formValue.blank {
background: #fff;
}
td.form-nested-wrap {
padding: 0;
border: 1px solid @form-border;
background: @form-bg;
}
tr.form-title-row th.formTitle {
height: 40px;
font-size: 16px;
font-weight: 700;
letter-spacing: 2px;
}
}
.mixing-form-nested {
min-width: 100%;
border: none;
th.formTitle,
td.formValue {
border: 1px solid @form-border;
}
}
.formValue {
:deep(.form-input.ant-input),
:deep(.form-input.ant-input-number),
:deep(.form-input.ant-picker),
:deep(.form-input.ant-select .ant-select-selector) {
width: 100% !important;
height: 26px !important;
min-height: 26px;
border: none !important;
box-shadow: none !important;
border-radius: 0 !important;
background: transparent !important;
text-align: center;
font-size: 12px;
color: #333;
padding: 0 4px !important;
}
:deep(.form-input.ant-input-number-input),
:deep(.form-input.ant-picker-input > input) {
text-align: center;
font-size: 12px;
height: 24px;
}
:deep(.form-input.ant-input-number-handler-wrap) {
display: none;
}
:deep(.form-input.ant-select-selection-item),
:deep(.form-input.ant-select-selection-placeholder) {
text-align: center;
line-height: 24px !important;
padding-inline-end: 16px !important;
}
:deep(.form-input.ant-select-arrow) {
right: 4px;
font-size: 10px;
color: #999;
}
:deep(.form-input.ant-picker-suffix) {
color: #999;
}
}
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A17】顶部施工表对齐旧系统13列表格-----------
.sheet-panels {
display: flex;
align-items: stretch;
gap: 0;
}
.panel-left {
flex: 0 0 auto;
align-self: stretch;
min-height: 0;
overflow: hidden;
display: flex;
flex-direction: column;
.material-table-wrap {
overflow-x: auto;
:deep(.jeecg-j-vxe-table),
:deep(.j-vxe-table-box),
:deep(.vxe-grid),
:deep(.vxe-table) {
max-width: none;
}
:deep(.vxe-header--column .vxe-resizable) {
cursor: col-resize;
}
}
//update-begin---author:cursor ---date:20260522 for【XSLMES-20260522-A26】TCU紧凑两行且胶料表向下扩展-----------
.material-table-wrap--fill {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
height: 100%;
:deep(.jeecg-j-vxe-table),
:deep(.ant-spin-nested-loading),
:deep(.ant-spin-container),
:deep(.j-vxe-table-box),
:deep(.vxe-grid) {
width: 100% !important;
height: 100% !important;
min-height: 0;
}
:deep(.vxe-table--render-wrapper),
:deep(.vxe-table--layout-wrapper),
:deep(.vxe-table--viewport-wrapper),
:deep(.vxe-table--main-wrapper) {
height: 100% !important;
}
:deep(.vxe-table--body-wrapper.body--wrapper) {
flex: 1;
min-height: 0;
}
}
.left-panel-section-tcu {
flex-shrink: 0;
border-top: 1px solid #d9d9d9;
}
//update-end---author:cursor ---date:20260522 for【XSLMES-20260522-A26】TCU紧凑两行且胶料表向下扩展-----------
.tcu-table-wrap {
flex-shrink: 0;
overflow-x: auto;
overflow-y: hidden;
:deep(.jeecg-j-vxe-table),
:deep(.ant-spin-nested-loading),
:deep(.ant-spin-container),
:deep(.j-vxe-table-box),
:deep(.vxe-grid) {
height: 100% !important;
}
:deep(.jeecg-j-vxe-table),
:deep(.j-vxe-table-box),
:deep(.vxe-grid),
:deep(.vxe-table) {
max-width: none;
}
:deep(.vxe-header--column .vxe-resizable) {
cursor: col-resize;
}
:deep(.vxe-header--row),
:deep(.vxe-header--column) {
height: auto !important;
}
:deep(.vxe-header--column .vxe-cell),
:deep(.vxe-header--column .vxe-cell--title) {
white-space: normal !important;
word-break: break-all;
line-height: 1.3;
height: auto !important;
overflow: visible !important;
text-overflow: clip !important;
}
}
:deep(.vxe-table) {
font-size: 12px;
}
:deep(.vxe-header--column),
:deep(.vxe-body--column) {
padding: 0 2px;
}
:deep(.vxe-header--column) {
background: #f5f5f5;
font-weight: 600;
}
}
.panel-right {
flex: 1 1 0;
min-width: 0;
min-height: 0;
border-right: none;
display: grid;
grid-template-rows: 1fr auto;
.panel-step-main {
display: flex;
flex-direction: column;
min-height: 0;
overflow: hidden;
}
.panel-down-step {
display: flex;
flex-direction: column;
flex-shrink: 0;
}
.step-table-wrap {
width: 100%;
min-height: 0;
overflow: hidden;
:deep(.jeecg-j-vxe-table),
:deep(.ant-spin-nested-loading),
:deep(.ant-spin-container),
:deep(.j-vxe-table-box),
:deep(.vxe-grid) {
width: 100% !important;
height: 100% !important;
min-height: 0;
}
:deep(.jeecg-j-vxe-table),
:deep(.ant-spin-nested-loading),
:deep(.ant-spin-container),
:deep(.j-vxe-table-box),
:deep(.vxe-grid) {
display: flex;
flex-direction: column;
}
:deep(.vxe-table) {
width: 100% !important;
flex: 1;
min-height: 0;
}
:deep(.vxe-table--body-inner-wrapper),
:deep(.vxe-table--header-inner-wrapper) {
width: 100% !important;
}
:deep(.vxe-header--column .vxe-resizable) {
cursor: col-resize;
}
}
.step-table-wrap--fill {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
height: 100%;
:deep(.vxe-table--render-wrapper),
:deep(.vxe-table--layout-wrapper),
:deep(.vxe-table--viewport-wrapper),
:deep(.vxe-table--main-wrapper) {
height: 100% !important;
}
:deep(.vxe-table--body-wrapper.body--wrapper) {
flex: 1;
min-height: 0;
}
}
.step-table-wrap--compact {
flex: none;
}
}
.panel {
border-right: 1px solid #d9d9d9;
border-bottom: 1px solid #d9d9d9;
}
.panel-head {
height: 32px;
border-bottom: 1px solid #d9d9d9;
background: #fafafa;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
font-size: 13px;
font-weight: 600;
color: #262626;
.panel-head-actions {
display: flex;
align-items: center;
gap: 8px;
}
}
.panel-right :deep(.vxe-table) {
font-size: 12px;
}
.panel-right :deep(.vxe-header--column) {
background: #f5f5f5;
font-weight: 600;
}
.sheet-sign-footer {
border-top: 1px solid #d9d9d9;
background: #fff;
}
.sign-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
border-bottom: 1px solid #ececec;
&:last-child {
border-bottom: none;
}
}
.sign-cell {
min-height: 32px;
border-right: 1px solid #ececec;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
&:last-child {
border-right: none;
}
}
.sign-cell.sign-title {
background: #fafafa;
font-size: 12px;
font-weight: 600;
color: #434343;
box-shadow: inset 1px 1px 2px rgba(0, 0, 0, 0.08);
}
.sign-cell.sign-title-stack {
flex-direction: column;
gap: 2px;
line-height: 1.2;
padding: 4px 0;
}
.sign-cell.sign-value {
padding: 2px 8px;
min-height: 34px;
}
.sign-cell.sign-text {
font-size: 12px;
color: #262626;
justify-content: center;
text-align: center;
word-break: break-all;
}
</style>
<style lang="less">
.mixing-spec-modal-wrap {
.ant-modal-header {
border-bottom: 1px solid #dcdcdc;
}
.ant-modal-body {
padding: 12px 16px 16px;
background: #f0f2f5;
}
.mixing-sheet {
background: #fcfdfd;
}
}
</style>