import { BasicColumn, FormSchema } from '/@/components/Table'; import { JVxeColumn, JVxeTypes } from '/@/components/jeecg/JVxeTable/types'; import { createLocalStorage } from '/@/utils/cache'; import { buildUUID } from '/@/utils/uuid'; const mixingMaterialColumnStorage = createLocalStorage(); /** 橡胶及配合剂明细列隐藏偏好 localStorage 键 */ export const MIXING_MATERIAL_COLUMN_CACHE_KEY = 'mes_xsl_mixing_spec_material_hidden_columns'; /** 橡胶及配合剂明细列宽偏好 localStorage 键 */ export const MIXING_MATERIAL_COLUMN_WIDTH_CACHE_KEY = 'mes_xsl_mixing_spec_material_column_widths_v2'; /** 行号列宽度(与 JVxeTable rowNumber 默认一致) */ export const MIXING_MATERIAL_ROW_NUMBER_WIDTH = 60; /** 橡胶及配合剂明细列可缩小到的最小宽度 */ export const MIXING_MATERIAL_MIN_COLUMN_WIDTH = 40; /** 默认隐藏的明细列 */ export const MIXING_MATERIAL_DEFAULT_HIDDEN_COLUMN_KEYS = ['materialMajor', 'materialKind']; /** 不允许隐藏的明细列 */ export const MIXING_MATERIAL_LOCKED_COLUMN_KEYS = ['mixerMaterialName']; export interface MixingMaterialColumnSettingItem { key: string; title: string; locked?: boolean; } export const columns: BasicColumn[] = [ { title: '规格', align: 'center', dataIndex: 'specName', width: 160, fixed: 'left' }, { title: '用途', align: 'center', dataIndex: 'purpose', width: 180 }, { title: '机台', align: 'center', dataIndex: 'machineName', width: 120 }, { title: '制作日期', align: 'center', dataIndex: 'makeDate', width: 120 }, { title: '发行编号', align: 'center', dataIndex: 'issueNumber', width: 150 }, { title: '段数', align: 'center', dataIndex: 'stageCount', width: 80 }, { title: '纯混炼时间(秒)', align: 'center', dataIndex: 'pureMixSec', width: 130 }, { title: '变更日期', align: 'center', dataIndex: 'changeDate', width: 120 }, { title: '修改时间', align: 'center', dataIndex: 'updateTime', width: 165 }, ]; export const searchFormSchema: FormSchema[] = [ { label: '关键字', field: 'keyword', component: 'Input', colProps: { span: 8 }, componentProps: { placeholder: '规格/用途/发行编号/机台' } }, { label: '制作日期起', field: 'makeDate_begin', component: 'DatePicker', colProps: { span: 8 }, componentProps: { valueFormat: 'YYYY-MM-DD' } }, { label: '制作日期止', field: 'makeDate_end', component: 'DatePicker', colProps: { span: 8 }, componentProps: { valueFormat: 'YYYY-MM-DD' } }, ]; export const mainSchema: FormSchema[] = [ { label: '', field: 'id', component: 'Input', show: false }, { label: '规格', field: 'specName', component: 'Input', required: true, colProps: { span: 8 } }, { label: '用途', field: 'purpose', component: 'AutoComplete', required: true, colProps: { span: 8 } }, { label: '机台', field: 'machineName', component: 'Input', colProps: { span: 8 } }, { label: '制作日期', field: 'makeDate', component: 'DatePicker', colProps: { span: 8 }, componentProps: { valueFormat: 'YYYY-MM-DD' } }, { label: '发行编号', field: 'issueNumber', component: 'AutoComplete', required: true, colProps: { span: 8 } }, { label: '换算系数', field: 'convertFactor', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '填充体积', field: 'fillVolume', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '回收炭黑(秒)', field: 'recycleCarbonSec', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 0, style: { width: '100%' } } }, { label: '母胶比重', field: 'motherRubberSg', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '终炼胶比重', field: 'finalRubberSg', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '适用工厂', field: 'applyFactory', component: 'Input', colProps: { span: 8 } }, { label: '段数', field: 'stageCount', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 0, style: { width: '100%' } } }, { label: '纯混炼时间(秒)', field: 'pureMixSec', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 0, style: { width: '100%' } } }, { label: '回收炭黑(KG)', field: 'recycleCarbonKg', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '自动小料打印设定', field: 'autoSmallPrintSetting', component: 'Input', colProps: { span: 8 } }, { label: '设定车数', field: 'setTrainCount', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 0, style: { width: '100%' } } }, { label: '侧壁水温', field: 'sideWallWaterTemp', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '超时排胶时间', field: 'overtimeDischargeSec', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 0, style: { width: '100%' } } }, { label: '超温排胶时间', field: 'overtempDischargeSec', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 0, style: { width: '100%' } } }, { label: '超温排胶温度', field: 'overtempDischargeTemp', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '卸料门水温', field: 'doorWaterTemp', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '转子水温', field: 'rotorWaterTemp', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '最高进料温度', field: 'maxFeedTemp', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } }, { label: '起草人', field: 'draftBy', component: 'Input', colProps: { span: 8 } }, { label: '起草时间', field: 'draftTime', component: 'DatePicker', colProps: { span: 8 }, componentProps: { showTime: true, valueFormat: 'YYYY-MM-DD HH:mm:ss' } }, { label: '校对人', field: 'proofreadBy', component: 'Input', colProps: { span: 8 } }, { label: '校对时间', field: 'proofreadTime', component: 'DatePicker', colProps: { span: 8 }, componentProps: { showTime: true, valueFormat: 'YYYY-MM-DD HH:mm:ss' } }, { label: '审核人', field: 'auditBy', component: 'Input', colProps: { span: 8 } }, { label: '审核时间', field: 'auditTime', component: 'DatePicker', colProps: { span: 8 }, componentProps: { showTime: true, valueFormat: 'YYYY-MM-DD HH:mm:ss' } }, { label: '批准人', field: 'approveBy', component: 'Input', colProps: { span: 8 } }, { label: '批准时间', field: 'approveTime', component: 'DatePicker', colProps: { span: 8 }, componentProps: { showTime: true, valueFormat: 'YYYY-MM-DD HH:mm:ss' } }, { label: '变更日期', field: 'changeDate', component: 'DatePicker', colProps: { span: 8 }, componentProps: { valueFormat: 'YYYY-MM-DD' } }, ]; //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】橡胶及配合剂明细列展示设置----------- export const materialColumns: JVxeColumn[] = [ { title: '物料大类', key: 'materialMajor', type: JVxeTypes.input, width: 100, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH }, { title: '物料小类', key: 'materialMinor', type: JVxeTypes.input, width: 120, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH }, { title: '种类', key: 'materialKind', type: JVxeTypes.input, width: 80, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH }, { title: '密炼物料名称', key: 'mixerMaterialName', type: JVxeTypes.input, width: 160, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH }, { title: '密炼物料描述', key: 'mixerMaterialDesc', type: JVxeTypes.input, width: 220, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH }, { title: '单重', key: 'unitWeight', type: JVxeTypes.inputNumber, width: 72, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center' }, { title: '累计', key: 'accumWeight', type: JVxeTypes.inputNumber, width: 72, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center' }, { title: '顺序', key: 'seqNo', type: JVxeTypes.inputNumber, width: 64, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center' }, ]; /** 橡胶及配合剂明细列设置项 */ export function getMixingMaterialColumnSettingItems(): MixingMaterialColumnSettingItem[] { return materialColumns.map((col) => ({ key: String(col.key), title: String(col.title), locked: MIXING_MATERIAL_LOCKED_COLUMN_KEYS.includes(String(col.key)), })); } /** 读取已隐藏的橡胶及配合剂明细列 key */ export function loadMixingMaterialHiddenColumnKeys(): string[] { const saved = mixingMaterialColumnStorage.get(MIXING_MATERIAL_COLUMN_CACHE_KEY); const validKeys = new Set(getMixingMaterialColumnSettingItems().map((item) => item.key)); if (!Array.isArray(saved)) { return MIXING_MATERIAL_DEFAULT_HIDDEN_COLUMN_KEYS.filter((key) => validKeys.has(key)); } return saved.filter( (key) => typeof key === 'string' && !MIXING_MATERIAL_LOCKED_COLUMN_KEYS.includes(key) && validKeys.has(key), ); } /** 保存已隐藏的橡胶及配合剂明细列 key */ export function saveMixingMaterialHiddenColumnKeys(hiddenKeys: string[]) { const validKeys = hiddenKeys.filter((key) => !MIXING_MATERIAL_LOCKED_COLUMN_KEYS.includes(key)); if (validKeys.length) { mixingMaterialColumnStorage.set(MIXING_MATERIAL_COLUMN_CACHE_KEY, validKeys); return; } mixingMaterialColumnStorage.remove(MIXING_MATERIAL_COLUMN_CACHE_KEY); } /** 按隐藏配置过滤橡胶及配合剂明细列 */ export function applyMixingMaterialColumnVisibility(columns: JVxeColumn[], hiddenKeys: string[]): JVxeColumn[] { if (!hiddenKeys?.length) { return columns; } const hiddenSet = new Set(hiddenKeys); return columns.filter((col) => !col.key || !hiddenSet.has(String(col.key))); } /** 读取已保存的橡胶及配合剂明细列宽 */ export function loadMixingMaterialColumnWidths(): Record { const saved = mixingMaterialColumnStorage.get(MIXING_MATERIAL_COLUMN_WIDTH_CACHE_KEY); const validKeys = new Set(materialColumns.map((col) => String(col.key))); if (!saved || typeof saved !== 'object') { return {}; } const result: Record = {}; Object.entries(saved as Record).forEach(([key, value]) => { if (validKeys.has(key) && typeof value === 'number' && value > 0) { result[key] = value; } }); return result; } /** 保存橡胶及配合剂明细列宽 */ export function saveMixingMaterialColumnWidths(widthMap: Record) { const validKeys = new Set(materialColumns.map((col) => String(col.key))); const next: Record = {}; Object.entries(widthMap || {}).forEach(([key, value]) => { if (validKeys.has(key) && typeof value === 'number' && value > 0) { next[key] = value; } }); if (Object.keys(next).length) { mixingMaterialColumnStorage.set(MIXING_MATERIAL_COLUMN_WIDTH_CACHE_KEY, next); return; } mixingMaterialColumnStorage.remove(MIXING_MATERIAL_COLUMN_WIDTH_CACHE_KEY); } /** 应用已保存列宽(minWidth 保持最小值,允许拖拽缩小) */ export function applyMixingMaterialColumnWidths(columns: JVxeColumn[], widthMap: Record): JVxeColumn[] { return columns.map((col) => { const savedWidth = widthMap[String(col.key)]; const nextCol = { ...col, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, }; if (savedWidth) { nextCol.width = savedWidth; } return nextCol; }); } /** 计算橡胶及配合剂明细表总宽度 */ export function calcMixingMaterialTableWidth(columns: JVxeColumn[], widthMap: Record = {}) { const dataWidth = columns.reduce((sum, col) => { const key = String(col.key); const width = widthMap[key] ?? Number(col.width) ?? 80; return sum + width; }, 0); return MIXING_MATERIAL_ROW_NUMBER_WIDTH + dataWidth + 1; } //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】橡胶及配合剂明细列展示设置----------- //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A20】明细表默认列宽对齐参考图----------- /** 混合步骤/下密炼机明细列可缩小到的最小宽度 */ export const MIXING_STEP_MIN_COLUMN_WIDTH = 48; export const stepColumns: JVxeColumn[] = [ { title: '动作', key: 'actionName', type: JVxeTypes.input, width: 120, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH }, { title: '时间(")', key: 'actionSec', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' }, { title: '保护时间', key: 'protectSec', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' }, { title: '温度(℃)', key: 'tempC', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' }, { title: '功率(Kw)', key: 'powerKw', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' }, { title: '能量(Kwh)', key: 'energyKwh', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' }, { title: '组合', key: 'comboMode', type: JVxeTypes.input, width: 72, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' }, { title: '转速(rpm)', key: 'speedRpm', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' }, { title: '压力(Mpa)', key: 'pressureMpa', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' }, { title: '栓(%)', key: 'boltPercent', type: JVxeTypes.inputNumber, width: 72, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' }, ]; /** 混合步骤/下密炼机明细列宽偏好 localStorage 键(两表共用同步) */ export const MIXING_STEP_COLUMN_WIDTH_CACHE_KEY = 'mes_xsl_mixing_spec_step_column_widths_v1'; /** 读取已保存的混合步骤明细列宽 */ export function loadMixingStepColumnWidths(): Record { const saved = mixingMaterialColumnStorage.get(MIXING_STEP_COLUMN_WIDTH_CACHE_KEY); const validKeys = new Set(stepColumns.map((col) => String(col.key))); if (!saved || typeof saved !== 'object') { return {}; } const result: Record = {}; Object.entries(saved as Record).forEach(([key, value]) => { if (validKeys.has(key) && typeof value === 'number' && value > 0) { result[key] = value; } }); return result; } /** 保存混合步骤明细列宽 */ export function saveMixingStepColumnWidths(widthMap: Record) { const validKeys = new Set(stepColumns.map((col) => String(col.key))); const next: Record = {}; Object.entries(widthMap || {}).forEach(([key, value]) => { if (validKeys.has(key) && typeof value === 'number' && value > 0) { next[key] = value; } }); if (Object.keys(next).length) { mixingMaterialColumnStorage.set(MIXING_STEP_COLUMN_WIDTH_CACHE_KEY, next); return; } mixingMaterialColumnStorage.remove(MIXING_STEP_COLUMN_WIDTH_CACHE_KEY); } /** 应用已保存混合步骤列宽(minWidth 保持最小值,允许拖拽缩小) */ export function applyMixingStepColumnWidths(columns: JVxeColumn[], widthMap: Record): JVxeColumn[] { return columns.map((col) => { const savedWidth = widthMap[String(col.key)]; const nextCol = { ...col, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, }; if (savedWidth) { nextCol.width = savedWidth; } return nextCol; }); } /** 计算混合步骤/下密炼机明细表总宽度 */ export function calcMixingStepTableWidth(columns: JVxeColumn[] = stepColumns, widthMap: Record = {}) { const dataWidth = columns.reduce((sum, col) => { const key = String(col.key); const width = widthMap[key] ?? Number(col.width) ?? Number(col.minWidth) ?? 80; return sum + width; }, 0); return MIXING_MATERIAL_ROW_NUMBER_WIDTH + dataWidth + 1; } //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A20】明细表默认列宽对齐参考图----------- export const downStepColumns: JVxeColumn[] = [...stepColumns]; //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A19】TCU温度条件表列宽可调且表头换行----------- /** TCU 温度条件明细列宽偏好 localStorage 键 */ export const MIXING_TCU_COLUMN_WIDTH_CACHE_KEY = 'mes_xsl_mixing_spec_tcu_column_widths_v2'; /** TCU 温度条件明细列可缩小到的最小宽度 */ export const MIXING_TCU_MIN_COLUMN_WIDTH = 48; export const tcuColumns: JVxeColumn[] = [ { title: '区分', key: 'sectionType', type: JVxeTypes.select, dictCode: 'xslmes_mixing_tcu_section', width: 96, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' }, { title: '前转子温度', key: 'frontRotorTemp', type: JVxeTypes.inputNumber, width: 76, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' }, { title: '后转子温度', key: 'rearRotorTemp', type: JVxeTypes.inputNumber, width: 76, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' }, { title: '前混炼室温度', key: 'frontChamberTemp', type: JVxeTypes.inputNumber, width: 76, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' }, { title: '后混炼室温度', key: 'rearChamberTemp', type: JVxeTypes.inputNumber, width: 76, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' }, { title: '上下顶栓温度', key: 'topPlugTemp', type: JVxeTypes.inputNumber, width: 76, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' }, { title: '药品称量位置', key: 'drugWeighPos', type: JVxeTypes.select, dictCode: 'xslmes_mixing_drug_weigh_pos', width: 76, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' }, ]; /** 读取已保存的 TCU 温度条件明细列宽 */ export function loadMixingTcuColumnWidths(): Record { const saved = mixingMaterialColumnStorage.get(MIXING_TCU_COLUMN_WIDTH_CACHE_KEY); const validKeys = new Set(tcuColumns.map((col) => String(col.key))); if (!saved || typeof saved !== 'object') { return {}; } const result: Record = {}; Object.entries(saved as Record).forEach(([key, value]) => { if (validKeys.has(key) && typeof value === 'number' && value > 0) { result[key] = value; } }); return result; } /** 保存 TCU 温度条件明细列宽 */ export function saveMixingTcuColumnWidths(widthMap: Record) { const validKeys = new Set(tcuColumns.map((col) => String(col.key))); const next: Record = {}; Object.entries(widthMap || {}).forEach(([key, value]) => { if (validKeys.has(key) && typeof value === 'number' && value > 0) { next[key] = value; } }); if (Object.keys(next).length) { mixingMaterialColumnStorage.set(MIXING_TCU_COLUMN_WIDTH_CACHE_KEY, next); return; } mixingMaterialColumnStorage.remove(MIXING_TCU_COLUMN_WIDTH_CACHE_KEY); } /** 应用已保存 TCU 列宽(minWidth 保持最小值,允许拖拽缩小) */ export function applyMixingTcuColumnWidths(columns: JVxeColumn[], widthMap: Record): JVxeColumn[] { return columns.map((col) => { const savedWidth = widthMap[String(col.key)]; const nextCol = { ...col, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, }; if (savedWidth) { nextCol.width = savedWidth; } return nextCol; }); } /** 计算 TCU 温度条件明细表总宽度 */ export function calcMixingTcuTableWidth(columns: JVxeColumn[] = tcuColumns, widthMap: Record = {}) { const dataWidth = columns.reduce((sum, col) => { const key = String(col.key); const width = widthMap[key] ?? Number(col.width) ?? Number(col.minWidth) ?? 80; return sum + width; }, 0); return MIXING_MATERIAL_ROW_NUMBER_WIDTH + dataWidth + 1; } //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A19】TCU温度条件表列宽可调且表头换行----------- //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A26】TCU紧凑两行且胶料表向下扩展----------- /** TCU 温度条件固定行数(上密炼机/下密炼机) */ export const DEFAULT_MIXING_TCU_ROW_COUNT = 2; /** TCU 表头高度(列标题换行) */ export const MIXING_TCU_HEADER_HEIGHT = 48; /** 计算 TCU 温度条件表格高度(仅展示固定两行) */ export function calcMixingTcuTableHeight(rowCount = DEFAULT_MIXING_TCU_ROW_COUNT) { const rows = Math.max(1, rowCount); return MIXING_TCU_HEADER_HEIGHT + rows * MIXING_VXE_MINI_ROW_HEIGHT + 2; } //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A26】TCU紧凑两行且胶料表向下扩展----------- //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A22】明细表默认空行数----------- /** 橡胶及配合剂明细默认行数 */ export const DEFAULT_MIXING_MATERIAL_ROW_COUNT = 20; /** 混合步骤明细默认行数 */ export const DEFAULT_MIXING_STEP_ROW_COUNT = 30; //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A30】胶料/混合步骤列表默认展示高度----------- /** 橡胶及配合剂明细列表默认展示行数(可视高度) */ export const MIXING_MATERIAL_VISIBLE_ROW_COUNT = 17; /** 混合步骤明细列表默认展示行数(可视高度) */ export const MIXING_STEP_VISIBLE_ROW_COUNT = 15; //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A30】胶料/混合步骤列表默认展示高度----------- //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A27】下密炼机混炼条件默认行数改为4----------- /** 下密炼机混炼条件明细默认行数 */ export const DEFAULT_MIXING_DOWN_STEP_ROW_COUNT = 4; //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A27】下密炼机混炼条件默认行数改为4----------- /** vxe mini 表头高度 */ export const MIXING_VXE_MINI_HEADER_HEIGHT = 36; /** vxe mini 行高 */ export const MIXING_VXE_MINI_ROW_HEIGHT = 32; //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A29】胶料/混合步骤表格高度按行数完整展示----------- /** 计算橡胶及配合剂明细表格展示高度 */ export function calcMixingMaterialTableHeight(rowCount = MIXING_MATERIAL_VISIBLE_ROW_COUNT) { const rows = Math.max(1, rowCount); return MIXING_VXE_MINI_HEADER_HEIGHT + rows * MIXING_VXE_MINI_ROW_HEIGHT + 4; } /** 计算混合步骤明细表格展示高度 */ export function calcMixingStepTableHeight(rowCount = MIXING_STEP_VISIBLE_ROW_COUNT) { const rows = Math.max(1, rowCount); return MIXING_VXE_MINI_HEADER_HEIGHT + rows * MIXING_VXE_MINI_ROW_HEIGHT + 4; } //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A31】下密炼机4行表格高度微调----------- /** 计算下密炼机混炼条件表格高度(默认完整展示4行) */ export function calcMixingDownStepTableHeight(rowCount = DEFAULT_MIXING_DOWN_STEP_ROW_COUNT) { const rows = Math.max(1, rowCount); // 额外留白补偿边框与 vxe 内边距,避免第4行底部被裁切 return MIXING_VXE_MINI_HEADER_HEIGHT + rows * MIXING_VXE_MINI_ROW_HEIGHT + 12; } //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A31】下密炼机4行表格高度微调----------- //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A29】胶料/混合步骤表格高度按行数完整展示----------- //update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A32】四明细表行高/展示行数设置持久化----------- /** 混炼示方明细表标识 */ export type MixingDetailTableKey = 'material' | 'tcu' | 'step' | 'downStep'; /** 明细表行高与展示行数偏好 */ export interface MixingTableHeightPreference { rowHeight: number; visibleRowCount: number; } /** 明细表行高设置元数据 */ export interface MixingTableHeightSettingMeta { key: MixingDetailTableKey; label: string; defaultRowHeight: number; defaultVisibleRowCount: number; minVisibleRowCount: number; maxVisibleRowCount: number; headerHeight: number; extraPadding: number; } /** 明细表行高 localStorage 键 */ export const MIXING_TABLE_HEIGHT_PREF_CACHE_KEY = 'mes_xsl_mixing_spec_table_height_prefs_v1'; /** 行高可调范围(px) */ export const MIXING_TABLE_ROW_HEIGHT_MIN = 24; export const MIXING_TABLE_ROW_HEIGHT_MAX = 56; export const MIXING_TABLE_HEIGHT_SETTING_META: Record = { material: { key: 'material', label: '橡胶及配合剂', defaultRowHeight: MIXING_VXE_MINI_ROW_HEIGHT, defaultVisibleRowCount: MIXING_MATERIAL_VISIBLE_ROW_COUNT, minVisibleRowCount: 5, maxVisibleRowCount: 30, headerHeight: MIXING_VXE_MINI_HEADER_HEIGHT, extraPadding: 4, }, tcu: { key: 'tcu', label: 'TCU温度条件', defaultRowHeight: MIXING_VXE_MINI_ROW_HEIGHT, defaultVisibleRowCount: DEFAULT_MIXING_TCU_ROW_COUNT, minVisibleRowCount: 2, maxVisibleRowCount: 6, headerHeight: MIXING_TCU_HEADER_HEIGHT, extraPadding: 2, }, step: { key: 'step', label: '混合步骤', defaultRowHeight: MIXING_VXE_MINI_ROW_HEIGHT, defaultVisibleRowCount: MIXING_STEP_VISIBLE_ROW_COUNT, minVisibleRowCount: 5, maxVisibleRowCount: 40, headerHeight: MIXING_VXE_MINI_HEADER_HEIGHT, extraPadding: 4, }, downStep: { key: 'downStep', label: '下密炼机混炼条件', defaultRowHeight: MIXING_VXE_MINI_ROW_HEIGHT, defaultVisibleRowCount: DEFAULT_MIXING_DOWN_STEP_ROW_COUNT, minVisibleRowCount: 2, maxVisibleRowCount: 12, headerHeight: MIXING_VXE_MINI_HEADER_HEIGHT, extraPadding: 12, }, }; function clampMixingTableNumber(value: unknown, min: number, max: number, fallback: number) { const num = Number(value); if (Number.isNaN(num)) { return fallback; } return Math.min(max, Math.max(min, Math.round(num))); } /** 获取明细表默认行高偏好 */ export function getMixingTableHeightDefault(tableKey: MixingDetailTableKey): MixingTableHeightPreference { const meta = MIXING_TABLE_HEIGHT_SETTING_META[tableKey]; return { rowHeight: meta.defaultRowHeight, visibleRowCount: meta.defaultVisibleRowCount, }; } /** 规范化明细表行高偏好 */ export function normalizeMixingTableHeightPreference( tableKey: MixingDetailTableKey, preference?: Partial | null, ): MixingTableHeightPreference { const meta = MIXING_TABLE_HEIGHT_SETTING_META[tableKey]; const defaults = getMixingTableHeightDefault(tableKey); return { rowHeight: clampMixingTableNumber( preference?.rowHeight, MIXING_TABLE_ROW_HEIGHT_MIN, MIXING_TABLE_ROW_HEIGHT_MAX, defaults.rowHeight, ), visibleRowCount: clampMixingTableNumber( preference?.visibleRowCount, meta.minVisibleRowCount, meta.maxVisibleRowCount, defaults.visibleRowCount, ), }; } /** 读取明细表行高偏好 */ export function loadMixingTableHeightPreference(tableKey: MixingDetailTableKey): MixingTableHeightPreference { const saved = mixingMaterialColumnStorage.get(MIXING_TABLE_HEIGHT_PREF_CACHE_KEY); const tableSaved = saved && typeof saved === 'object' ? (saved as Record>)[tableKey] : null; return normalizeMixingTableHeightPreference(tableKey, tableSaved); } /** 保存明细表行高偏好 */ export function saveMixingTableHeightPreference(tableKey: MixingDetailTableKey, preference: MixingTableHeightPreference) { const saved = mixingMaterialColumnStorage.get(MIXING_TABLE_HEIGHT_PREF_CACHE_KEY); const next = saved && typeof saved === 'object' ? { ...(saved as Record) } : ({} as Record); next[tableKey] = normalizeMixingTableHeightPreference(tableKey, preference); mixingMaterialColumnStorage.set(MIXING_TABLE_HEIGHT_PREF_CACHE_KEY, next); } /** 计算明细表展示区域高度 */ export function calcMixingDetailTableViewportHeight( tableKey: MixingDetailTableKey, preference?: Partial, ) { const meta = MIXING_TABLE_HEIGHT_SETTING_META[tableKey]; const normalized = normalizeMixingTableHeightPreference(tableKey, preference); return meta.headerHeight + normalized.visibleRowCount * normalized.rowHeight + meta.extraPadding; } /** 构建 JVxeTable rowConfig */ export function buildMixingTableRowConfig(preference: MixingTableHeightPreference) { return { isHover: true, height: preference.rowHeight, }; } //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A32】四明细表行高/展示行数设置持久化----------- function createEmptyMixingRows(count: number): Recordable[] { return Array.from({ length: count }, () => ({ id: buildUUID() })); } /** 创建橡胶及配合剂默认空行 */ export function createEmptyMaterialRows(count = DEFAULT_MIXING_MATERIAL_ROW_COUNT): Recordable[] { return createEmptyMixingRows(count); } /** 创建混合步骤默认空行 */ export function createEmptyStepRows(count = DEFAULT_MIXING_STEP_ROW_COUNT): Recordable[] { return createEmptyMixingRows(count); } /** 创建下密炼机混炼条件默认空行 */ export function createEmptyDownStepRows(count = DEFAULT_MIXING_DOWN_STEP_ROW_COUNT): Recordable[] { return createEmptyMixingRows(count); } /** 确保明细行具备唯一 id(JVxeTable 依赖 rowKey=id) */ export function normalizeMixingDetailRows(rows: Recordable[] = []): Recordable[] { return (rows || []).map((row) => ({ ...row, id: row?.id || buildUUID() })); } //update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A22】明细表默认空行数-----------