1409 lines
62 KiB
Vue
1409 lines
62 KiB
Vue
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;
|
||
|
||
//update-begin---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】橡胶及配合剂明细默认展示种类列-----------
|
||
/** 默认隐藏的明细列(种类列默认展示,物料小类默认隐藏) */
|
||
export const MIXING_MATERIAL_DEFAULT_HIDDEN_COLUMN_KEYS = ['materialMajor', 'materialMinor'];
|
||
//update-end---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】橡胶及配合剂明细默认展示种类列-----------
|
||
|
||
/** 不允许隐藏的明细列 */
|
||
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: 88 },
|
||
{ 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: 'machineId', component: 'Input', show: false },
|
||
{ label: '规格', field: 'specName', component: 'Input', required: true, colProps: { span: 8 } },
|
||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】混炼示方基本信息字段优化-----------
|
||
{ label: '用途', field: 'purpose', component: 'Input', 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: 'Input', required: true, colProps: { span: 8 } },
|
||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】混炼示方基本信息字段优化-----------
|
||
{ label: '换算系数', field: 'convertFactor', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 2, 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: 'Input', colProps: { span: 8 }, componentProps: { placeholder: '如 2/3' } },
|
||
{ 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[] = [
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A55】混炼示方明细关联密炼物料ID-----------
|
||
{ title: '密炼物料ID', key: 'mixerMaterialId', type: JVxeTypes.hidden },
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A55】混炼示方明细关联密炼物料ID-----------
|
||
{ title: '物料大类', key: 'materialMajor', type: JVxeTypes.input, width: 100, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH },
|
||
//update-begin---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】种类列置于首列展示且只读-----------
|
||
{
|
||
title: '种类',
|
||
key: 'materialKind',
|
||
type: JVxeTypes.input,
|
||
width: 100,
|
||
minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH,
|
||
disabled: true,
|
||
},
|
||
{ title: '物料小类', key: 'materialMinor', type: JVxeTypes.input, width: 120, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH },
|
||
//update-end---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】种类列置于首列展示且只读-----------
|
||
{
|
||
title: '密炼物料名称',
|
||
key: 'mixerMaterialName',
|
||
type: JVxeTypes.slot,
|
||
slotName: 'mixerMaterialNameSlot',
|
||
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' },
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A41】累计列按种类分组合计只读展示-----------
|
||
{
|
||
title: '累计',
|
||
key: 'accumWeight',
|
||
type: JVxeTypes.inputNumber,
|
||
width: 72,
|
||
minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH,
|
||
align: 'center',
|
||
disabled: true,
|
||
},
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A41】累计列按种类分组合计只读展示-----------
|
||
{ 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));
|
||
}
|
||
//update-begin---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】迁移列显示偏好:原隐藏种类改为隐藏物料小类-----------
|
||
let keys = saved.filter(
|
||
(key) => typeof key === 'string' && !MIXING_MATERIAL_LOCKED_COLUMN_KEYS.includes(key) && validKeys.has(key),
|
||
);
|
||
if (keys.includes('materialKind') && !keys.includes('materialMinor')) {
|
||
keys = keys.filter((key) => key !== 'materialKind');
|
||
keys.push('materialMinor');
|
||
}
|
||
return keys;
|
||
//update-end---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】迁移列显示偏好:原隐藏种类改为隐藏物料小类-----------
|
||
}
|
||
|
||
/** 保存已隐藏的橡胶及配合剂明细列 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<string, number> {
|
||
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<string, number> = {};
|
||
Object.entries(saved as Record<string, unknown>).forEach(([key, value]) => {
|
||
if (validKeys.has(key) && typeof value === 'number' && value > 0) {
|
||
result[key] = value;
|
||
}
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/** 保存橡胶及配合剂明细列宽 */
|
||
export function saveMixingMaterialColumnWidths(widthMap: Record<string, number>) {
|
||
const validKeys = new Set(materialColumns.map((col) => String(col.key)));
|
||
const next: Record<string, number> = {};
|
||
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<string, number>): 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<string, number> = {}) {
|
||
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:20260525 for:【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
|
||
/** 是否为有效明细行(参与种类分组) */
|
||
function isMixingMaterialDataRow(row: Recordable): boolean {
|
||
if (!row) {
|
||
return false;
|
||
}
|
||
return !!(row.mixerMaterialId || row.mixerMaterialName || row.materialKind || row.unitWeight != null && row.unitWeight !== '');
|
||
}
|
||
|
||
/** 规范化种类字段,用于连续行分组 */
|
||
function normalizeMixingMaterialKind(row: Recordable): string {
|
||
const kind = row?.materialKind;
|
||
return kind != null && String(kind).trim() !== '' ? String(kind).trim() : '';
|
||
}
|
||
|
||
/** 按种类连续分组,累计写入每组最后一行 */
|
||
export function fillMixingMaterialAccumWeight(rows: Recordable[] = []): Recordable[] {
|
||
if (!rows?.length) {
|
||
return rows;
|
||
}
|
||
let index = 0;
|
||
while (index < rows.length) {
|
||
const current = rows[index];
|
||
if (!isMixingMaterialDataRow(current)) {
|
||
current.accumWeight = null;
|
||
index++;
|
||
continue;
|
||
}
|
||
const kind = normalizeMixingMaterialKind(current);
|
||
let groupEnd = index;
|
||
let sum = 0;
|
||
while (groupEnd < rows.length) {
|
||
const row = rows[groupEnd];
|
||
if (!isMixingMaterialDataRow(row) || normalizeMixingMaterialKind(row) !== kind) {
|
||
break;
|
||
}
|
||
const weight = toMixingMaterialNumber(row.unitWeight);
|
||
if (weight != null) {
|
||
sum += weight;
|
||
}
|
||
groupEnd++;
|
||
}
|
||
for (let rowIndex = index; rowIndex < groupEnd; rowIndex++) {
|
||
rows[rowIndex].accumWeight =
|
||
rowIndex === groupEnd - 1 && sum !== 0 ? roundMixingMaterialNumber(sum) : null;
|
||
}
|
||
index = groupEnd;
|
||
}
|
||
return rows;
|
||
}
|
||
|
||
/** 安全解析明细数值,避免字符串拼接 */
|
||
function toMixingMaterialNumber(value: unknown): number | null {
|
||
if (value == null || value === '') {
|
||
return null;
|
||
}
|
||
const num = Number(value);
|
||
return Number.isFinite(num) ? num : null;
|
||
}
|
||
|
||
/** 混炼示方重量小数位(与后端 BigDecimal 精度一致) */
|
||
const MIXING_MATERIAL_WEIGHT_SCALE = 6;
|
||
|
||
//update-begin---author:cursor ---date:20260526 for:【XSLMES-20260526-A60】换算系数/配方参数数值展示优化-----------
|
||
/** 换算系数展示小数位 */
|
||
export const MIXING_CONVERT_FACTOR_SCALE = 2;
|
||
|
||
/** 配方参数设定允许的小数精度 */
|
||
export const MIXING_RECIPE_PARAM_DECIMAL_SCALE = 6;
|
||
|
||
/** 配方参数设定:允许小数的字段 */
|
||
export const MIXING_RECIPE_PARAM_DECIMAL_FIELDS = [
|
||
'sideWallWaterTemp',
|
||
'overtempDischargeTemp',
|
||
'doorWaterTemp',
|
||
'rotorWaterTemp',
|
||
'maxFeedTemp',
|
||
] as const;
|
||
|
||
/** 换算系数展示:固定保留两位小数 */
|
||
export function formatMixingConvertFactorDisplay(value: unknown): string {
|
||
if (value === null || value === undefined || value === '') {
|
||
return '';
|
||
}
|
||
const num = Number(value);
|
||
if (Number.isNaN(num)) {
|
||
return String(value);
|
||
}
|
||
return num.toFixed(MIXING_CONVERT_FACTOR_SCALE);
|
||
}
|
||
|
||
/** 换算系数输入解析 */
|
||
export function parseMixingConvertFactorValue(value: unknown): number | null {
|
||
if (value === '' || value == null) {
|
||
return null;
|
||
}
|
||
const num = Number(String(value).replace(/,/g, '').trim());
|
||
if (Number.isNaN(num)) {
|
||
return null;
|
||
}
|
||
return Number(num.toFixed(MIXING_CONVERT_FACTOR_SCALE));
|
||
}
|
||
|
||
/** 配方参数展示:允许小数,无小数部分时仅展示整数 */
|
||
export function formatMixingRecipeParamDisplay(value: unknown, maxPrecision = MIXING_RECIPE_PARAM_DECIMAL_SCALE): string {
|
||
if (value === null || value === undefined || value === '') {
|
||
return '';
|
||
}
|
||
const num = Number(value);
|
||
if (Number.isNaN(num)) {
|
||
return String(value);
|
||
}
|
||
const rounded = Number(num.toFixed(maxPrecision));
|
||
if (Number.isInteger(rounded)) {
|
||
return String(rounded);
|
||
}
|
||
return String(rounded);
|
||
}
|
||
|
||
/** 配方参数输入解析 */
|
||
export function parseMixingRecipeParamValue(value: unknown): number | null {
|
||
if (value === '' || value == null) {
|
||
return null;
|
||
}
|
||
const text = String(value).replace(/,/g, '').trim();
|
||
if (!text) {
|
||
return null;
|
||
}
|
||
const num = Number(text);
|
||
if (Number.isNaN(num)) {
|
||
return null;
|
||
}
|
||
return Number(num.toFixed(MIXING_RECIPE_PARAM_DECIMAL_SCALE));
|
||
}
|
||
//update-end---author:cursor ---date:20260526 for:【XSLMES-20260526-A60】换算系数/配方参数数值展示优化-----------
|
||
|
||
/** 重量四舍五入,消除浮点累加误差 */
|
||
function roundMixingMaterialNumber(value: number): number {
|
||
return Number(value.toFixed(MIXING_MATERIAL_WEIGHT_SCALE));
|
||
}
|
||
|
||
/** 格式化重量展示文本 */
|
||
function formatMixingMaterialWeight(value: unknown): string {
|
||
const num = toMixingMaterialNumber(value);
|
||
if (num == null) {
|
||
return '';
|
||
}
|
||
return String(roundMixingMaterialNumber(num));
|
||
}
|
||
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A43】换算系数联动明细单重实时计算-----------
|
||
/** 规范化换算系数,空值或非正数按 1 处理 */
|
||
export function normalizeMixingConvertFactor(factor: unknown): number {
|
||
const num = toMixingMaterialNumber(factor);
|
||
if (num == null || num <= 0) {
|
||
return 1;
|
||
}
|
||
return num;
|
||
}
|
||
|
||
/** 基准单重 × 换算系数 */
|
||
export function calcMixingMaterialConvertedWeight(base: unknown, factor: unknown): number | null {
|
||
const baseNum = toMixingMaterialNumber(base);
|
||
if (baseNum == null) {
|
||
return null;
|
||
}
|
||
return Number((baseNum * normalizeMixingConvertFactor(factor)).toFixed(MIXING_MATERIAL_WEIGHT_SCALE));
|
||
}
|
||
|
||
/** 从当前显示单重反推基准单重 */
|
||
export function syncMaterialBaseUnitWeightFromDisplay(row: Recordable, factor: unknown) {
|
||
if (!row) {
|
||
return;
|
||
}
|
||
const unit = toMixingMaterialNumber(row.unitWeight);
|
||
if (unit == null) {
|
||
row.baseUnitWeight = null;
|
||
return;
|
||
}
|
||
row.baseUnitWeight = Number((unit / normalizeMixingConvertFactor(factor)).toFixed(MIXING_MATERIAL_WEIGHT_SCALE));
|
||
}
|
||
|
||
/** 初始化明细行基准单重(编辑加载时由已保存单重反推) */
|
||
export function initMaterialBaseUnitWeight(row: Recordable, factor: unknown, force = false) {
|
||
if (!isMixingMaterialDataRow(row)) {
|
||
row.baseUnitWeight = null;
|
||
return;
|
||
}
|
||
if (!force && toMixingMaterialNumber(row.baseUnitWeight) != null) {
|
||
return;
|
||
}
|
||
syncMaterialBaseUnitWeightFromDisplay(row, factor);
|
||
}
|
||
|
||
/** 批量初始化基准单重 */
|
||
export function initMaterialBaseUnitWeights(rows: Recordable[] = [], factor: unknown, force = false) {
|
||
for (const row of rows) {
|
||
initMaterialBaseUnitWeight(row, factor, force);
|
||
}
|
||
return rows;
|
||
}
|
||
|
||
/** 按换算系数重算所有明细单重 */
|
||
export function applyConvertFactorToMaterialRows(
|
||
rows: Recordable[] = [],
|
||
factor: unknown,
|
||
prevFactor?: unknown,
|
||
): Recordable[] {
|
||
const nextFactor = normalizeMixingConvertFactor(factor);
|
||
const oldFactor = prevFactor != null ? normalizeMixingConvertFactor(prevFactor) : nextFactor;
|
||
for (const row of rows) {
|
||
if (!isMixingMaterialDataRow(row)) {
|
||
continue;
|
||
}
|
||
let base = toMixingMaterialNumber(row.baseUnitWeight);
|
||
if (base == null) {
|
||
const unit = toMixingMaterialNumber(row.unitWeight);
|
||
if (unit == null) {
|
||
continue;
|
||
}
|
||
base = roundMixingMaterialNumber(unit / oldFactor);
|
||
row.baseUnitWeight = base;
|
||
}
|
||
row.unitWeight = calcMixingMaterialConvertedWeight(base, nextFactor);
|
||
}
|
||
return rows;
|
||
}
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A43】换算系数联动明细单重实时计算-----------
|
||
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A46】填充体积按单重/比重/机台有效体积自动计算-----------
|
||
/** 解析设备有效体积(支持纯数字或带单位字符串) */
|
||
export function parseMixingEffectiveVolume(raw: unknown): number | null {
|
||
if (raw == null || raw === '') {
|
||
return null;
|
||
}
|
||
const text = String(raw).trim();
|
||
if (!text) {
|
||
return null;
|
||
}
|
||
const direct = toMixingMaterialNumber(text);
|
||
if (direct != null && direct > 0) {
|
||
return direct;
|
||
}
|
||
const matched = text.match(/([0-9]+(?:\.[0-9]+)?)/);
|
||
if (!matched) {
|
||
return null;
|
||
}
|
||
const parsed = Number(matched[1]);
|
||
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
||
}
|
||
|
||
/** 按段数与比重字段选择本段计算用比重 */
|
||
export function resolveMixingSpecificGravity(form: Recordable = {}): number | null {
|
||
const motherSg = toMixingMaterialNumber(form.motherRubberSg);
|
||
const finalSg = toMixingMaterialNumber(form.finalRubberSg);
|
||
const stageCount = String(form.stageCount || '').trim();
|
||
const stageMatch = stageCount.match(/^(\d+)\/(\d+)$/);
|
||
const isFinalStage = stageMatch ? stageMatch[1] === stageMatch[2] : false;
|
||
if (isFinalStage && finalSg != null && finalSg > 0) {
|
||
return finalSg;
|
||
}
|
||
if (motherSg != null && motherSg > 0) {
|
||
return motherSg;
|
||
}
|
||
if (finalSg != null && finalSg > 0) {
|
||
return finalSg;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 填充体积(%) = 单重合计 ÷ 比重 ÷ 机台有效体积(L) × 100
|
||
* 单重合计已含换算系数,此处不再重复乘换算系数
|
||
*/
|
||
export function calcMixingFillVolume(totalWeight: unknown, specificGravity: unknown, effectiveVolume: unknown): number | null {
|
||
const weight = toMixingMaterialNumber(totalWeight);
|
||
const sg = toMixingMaterialNumber(specificGravity);
|
||
const volume = parseMixingEffectiveVolume(effectiveVolume);
|
||
if (weight == null || weight <= 0 || sg == null || sg <= 0 || volume == null || volume <= 0) {
|
||
return null;
|
||
}
|
||
const materialVolume = weight / sg;
|
||
return Number(((materialVolume / volume) * 100).toFixed(6));
|
||
}
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A46】填充体积按单重/比重/机台有效体积自动计算-----------
|
||
|
||
/** 汇总有效明细行的单重合计 */
|
||
export function calcMixingMaterialUnitWeightTotal(rows: Recordable[] = []): number | null {
|
||
let sum = 0;
|
||
let hasAny = false;
|
||
for (const row of rows) {
|
||
if (!isMixingMaterialDataRow(row)) {
|
||
continue;
|
||
}
|
||
const weight = toMixingMaterialNumber(row.unitWeight);
|
||
if (weight != null) {
|
||
sum += weight;
|
||
hasAny = true;
|
||
}
|
||
}
|
||
return hasAny ? roundMixingMaterialNumber(sum) : null;
|
||
}
|
||
|
||
/** 汇总有效明细行的累计合计(与单重合计一致) */
|
||
export function calcMixingMaterialAccumWeightTotal(rows: Recordable[] = []): number | null {
|
||
return calcMixingMaterialUnitWeightTotal(rows);
|
||
}
|
||
|
||
export interface MixingMaterialFooterCell {
|
||
key: string;
|
||
width: number;
|
||
text: string;
|
||
align?: 'left' | 'center' | 'right';
|
||
isLabel?: boolean;
|
||
isTotal?: boolean;
|
||
}
|
||
|
||
/** 构建橡胶及配合剂明细底部合计行单元格(列宽与明细表同步) */
|
||
export function buildMixingMaterialFooterCells(
|
||
columns: JVxeColumn[],
|
||
widthMap: Record<string, number>,
|
||
totals: { unitWeight?: number | null; accumWeight?: number | null },
|
||
): MixingMaterialFooterCell[] {
|
||
const unitWeightIndex = columns.findIndex((col) => String(col.key) === 'unitWeight');
|
||
const formatTotal = (value: number | null | undefined) => formatMixingMaterialWeight(value);
|
||
|
||
return columns.map((col, index) => {
|
||
const key = String(col.key);
|
||
const width = widthMap[key] ?? Number(col.width) ?? 80;
|
||
if (key === 'unitWeight') {
|
||
return { key, width, text: formatTotal(totals.unitWeight), align: 'center', isTotal: true };
|
||
}
|
||
if (key === 'accumWeight') {
|
||
return { key, width, text: formatTotal(totals.accumWeight), align: 'center', isTotal: true };
|
||
}
|
||
const isLabelCol = unitWeightIndex > 0 && index === unitWeightIndex - 1;
|
||
return {
|
||
key,
|
||
width,
|
||
text: isLabelCol ? '合计' : '',
|
||
align: 'center',
|
||
isLabel: isLabelCol,
|
||
};
|
||
});
|
||
}
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
|
||
|
||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A20】明细表默认列宽对齐参考图-----------
|
||
/** 混合步骤/下密炼机明细列可缩小到的最小宽度 */
|
||
export const MIXING_STEP_MIN_COLUMN_WIDTH = 48;
|
||
|
||
export const stepColumns: JVxeColumn[] = [
|
||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||
{
|
||
title: '动作',
|
||
key: 'actionName',
|
||
type: JVxeTypes.slot,
|
||
slotName: 'actionNameSlot',
|
||
width: 120,
|
||
minWidth: MIXING_STEP_MIN_COLUMN_WIDTH,
|
||
},
|
||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||
{ 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' },
|
||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||
{
|
||
title: '组合',
|
||
key: 'comboMode',
|
||
type: JVxeTypes.slot,
|
||
slotName: 'comboModeSlot',
|
||
width: 72,
|
||
minWidth: MIXING_STEP_MIN_COLUMN_WIDTH,
|
||
align: 'center',
|
||
},
|
||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||
{ 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<string, number> {
|
||
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<string, number> = {};
|
||
Object.entries(saved as Record<string, unknown>).forEach(([key, value]) => {
|
||
if (validKeys.has(key) && typeof value === 'number' && value > 0) {
|
||
result[key] = value;
|
||
}
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/** 保存混合步骤明细列宽 */
|
||
export function saveMixingStepColumnWidths(widthMap: Record<string, number>) {
|
||
const validKeys = new Set(stepColumns.map((col) => String(col.key)));
|
||
const next: Record<string, number> = {};
|
||
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<string, number>): 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<string, number> = {}) {
|
||
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[] = [
|
||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU区分固定上/下密炼机-----------
|
||
{ title: '区分', key: 'sectionType', type: JVxeTypes.select, dictCode: 'xslmes_mixing_tcu_section', disabled: true, width: 96, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' },
|
||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU区分固定上/下密炼机-----------
|
||
{ 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<string, number> {
|
||
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<string, number> = {};
|
||
Object.entries(saved as Record<string, unknown>).forEach(([key, value]) => {
|
||
if (validKeys.has(key) && typeof value === 'number' && value > 0) {
|
||
result[key] = value;
|
||
}
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/** 保存 TCU 温度条件明细列宽 */
|
||
export function saveMixingTcuColumnWidths(widthMap: Record<string, number>) {
|
||
const validKeys = new Set(tcuColumns.map((col) => String(col.key)));
|
||
const next: Record<string, number> = {};
|
||
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<string, number>): 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<string, number> = {}) {
|
||
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;
|
||
|
||
/** 橡胶及配合剂明细合计行高度(含边框) */
|
||
export const MIXING_MATERIAL_FOOTER_ROW_HEIGHT = MIXING_VXE_MINI_ROW_HEIGHT + 1;
|
||
|
||
//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<MixingDetailTableKey, MixingTableHeightSettingMeta> = {
|
||
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<MixingTableHeightPreference> | 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<string, Partial<MixingTableHeightPreference>>)[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<string, MixingTableHeightPreference>) }
|
||
: ({} as Record<string, MixingTableHeightPreference>);
|
||
next[tableKey] = normalizeMixingTableHeightPreference(tableKey, preference);
|
||
mixingMaterialColumnStorage.set(MIXING_TABLE_HEIGHT_PREF_CACHE_KEY, next);
|
||
}
|
||
|
||
/** 计算明细表展示区域高度 */
|
||
export function calcMixingDetailTableViewportHeight(
|
||
tableKey: MixingDetailTableKey,
|
||
preference?: Partial<MixingTableHeightPreference>,
|
||
) {
|
||
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);
|
||
}
|
||
|
||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU默认两行及上密炼机药品称默认值-----------
|
||
/** 上密炼机 TCU 行默认药品称量位置(药品称) */
|
||
export const MIXING_TCU_UP_MIXER_DRUG_WEIGH_POS = 'drug_scale';
|
||
|
||
/** 构建 TCU 温度条件默认两行(上密炼机/下密炼机) */
|
||
export function buildDefaultMixingTcuRows(rows: Recordable[] = []): Recordable[] {
|
||
const up =
|
||
rows.find((r) => r.sectionType === 'up_mixer') ||
|
||
({ sectionType: 'up_mixer', drugWeighPos: MIXING_TCU_UP_MIXER_DRUG_WEIGH_POS } as Recordable);
|
||
if (up.sectionType === 'up_mixer' && !up.drugWeighPos) {
|
||
up.drugWeighPos = MIXING_TCU_UP_MIXER_DRUG_WEIGH_POS;
|
||
}
|
||
const down = rows.find((r) => r.sectionType === 'down_mixer') || ({ sectionType: 'down_mixer', drugWeighPos: undefined } as Recordable);
|
||
return [up, down];
|
||
}
|
||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU默认两行及上密炼机药品称默认值-----------
|
||
|
||
/** 确保明细行具备唯一 id(JVxeTable 依赖 rowKey=id) */
|
||
export function normalizeMixingDetailRows(rows: Recordable[] = []): Recordable[] {
|
||
return (rows || []).map((row) => ({ ...row, id: row?.id || buildUUID() }));
|
||
}
|
||
|
||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A39】编辑页明细补齐默认空行与新增一致-----------
|
||
/** 编辑/详情加载时补齐明细默认空行(不少于 defaultCount,已有数据行保留) */
|
||
export function ensureMixingDetailRows(rows: Recordable[] = [], defaultCount: number): Recordable[] {
|
||
const normalized = normalizeMixingDetailRows(rows);
|
||
if (normalized.length >= defaultCount) {
|
||
return normalized;
|
||
}
|
||
return [...normalized, ...createEmptyMixingRows(defaultCount - normalized.length)];
|
||
}
|
||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A39】编辑页明细补齐默认空行与新增一致-----------
|
||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A22】明细表默认空行数-----------
|
||
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】混炼示方密炼物料选料弹窗与种类解析-----------
|
||
/** 混炼示方选料弹窗:隐藏的小类 ID 偏好 localStorage 键 */
|
||
export const MIXING_MATERIAL_PICKER_HIDDEN_CATEGORY_CACHE_KEY = 'mes_xsl_mixing_spec_material_picker_hidden_categories';
|
||
|
||
export interface MixingMaterialPickerCategoryItem {
|
||
id: string;
|
||
name: string;
|
||
majorId: string;
|
||
majorName: string;
|
||
label: string;
|
||
}
|
||
|
||
const mixingMaterialPickerStorage = createLocalStorage();
|
||
|
||
export function loadMixingMaterialPickerHiddenCategoryIds(): string[] {
|
||
const raw = mixingMaterialPickerStorage.get(MIXING_MATERIAL_PICKER_HIDDEN_CATEGORY_CACHE_KEY);
|
||
return Array.isArray(raw) ? raw.map(String) : [];
|
||
}
|
||
|
||
export function saveMixingMaterialPickerHiddenCategoryIds(ids: string[]) {
|
||
mixingMaterialPickerStorage.set(MIXING_MATERIAL_PICKER_HIDDEN_CATEGORY_CACHE_KEY, ids || []);
|
||
}
|
||
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】选料弹窗小类树为空时重置隐藏配置-----------
|
||
/** 过滤无效隐藏项;若全部小类被隐藏则自动重置,避免左侧树只剩「全部小类」 */
|
||
export function sanitizeMixingMaterialPickerHiddenCategoryIds(allMinorIds: string[], hidden: string[]) {
|
||
const allSet = new Set((allMinorIds || []).map(String));
|
||
const filtered = (hidden || []).map(String).filter((id) => allSet.has(id));
|
||
if (allSet.size > 0 && filtered.length >= allSet.size) {
|
||
return [];
|
||
}
|
||
return filtered;
|
||
}
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】选料弹窗小类树为空时重置隐藏配置-----------
|
||
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A52】混炼示方种类改读密炼物料种类配置-----------
|
||
export interface MixerMaterialKindLookup {
|
||
byRefId: Record<string, string>;
|
||
byRefCode: Record<string, string>;
|
||
//update-begin---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】种类查找表支持胶料类别名称-----------
|
||
byRefName?: Record<string, string>;
|
||
//update-end---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】种类查找表支持胶料类别名称-----------
|
||
rubberKindName?: string;
|
||
}
|
||
|
||
export const EMPTY_MIXER_MATERIAL_KIND_LOOKUP: MixerMaterialKindLookup = {
|
||
byRefId: {},
|
||
byRefCode: {},
|
||
byRefName: {},
|
||
rubberKindName: '胶料',
|
||
};
|
||
|
||
let mixingMaterialKindLookupCache: MixerMaterialKindLookup | null = null;
|
||
let mixingMaterialKindLookupPromise: Promise<MixerMaterialKindLookup> | null = null;
|
||
|
||
/** 加载密炼物料种类配置查找表(带内存缓存) */
|
||
export async function loadMixingMaterialKindLookup(forceReload = false): Promise<MixerMaterialKindLookup> {
|
||
if (!forceReload && mixingMaterialKindLookupCache) {
|
||
return mixingMaterialKindLookupCache;
|
||
}
|
||
if (!forceReload && mixingMaterialKindLookupPromise) {
|
||
return mixingMaterialKindLookupPromise;
|
||
}
|
||
mixingMaterialKindLookupPromise = (async () => {
|
||
try {
|
||
const { loadKindLookup } = await import('../mesXslMixerMaterialKindCfg/MesXslMixerMaterialKindCfg.api');
|
||
const raw = await loadKindLookup();
|
||
const lookup: MixerMaterialKindLookup = {
|
||
byRefId: raw?.byRefId || {},
|
||
byRefCode: raw?.byRefCode || {},
|
||
//update-begin---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】加载种类配置含类别名称映射-----------
|
||
byRefName: raw?.byRefName || {},
|
||
//update-end---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】加载种类配置含类别名称映射-----------
|
||
rubberKindName: raw?.rubberKindName || '胶料',
|
||
};
|
||
mixingMaterialKindLookupCache = lookup;
|
||
return lookup;
|
||
} catch {
|
||
return EMPTY_MIXER_MATERIAL_KIND_LOOKUP;
|
||
} finally {
|
||
mixingMaterialKindLookupPromise = null;
|
||
}
|
||
})();
|
||
return mixingMaterialKindLookupPromise;
|
||
}
|
||
|
||
/** 清除种类配置缓存(配置变更后可调用) */
|
||
export function clearMixingMaterialKindLookupCache() {
|
||
mixingMaterialKindLookupCache = null;
|
||
mixingMaterialKindLookupPromise = null;
|
||
}
|
||
|
||
function matchKindFromLookup(lookup: MixerMaterialKindLookup | null | undefined, key?: string) {
|
||
if (!lookup || key == null || String(key).trim() === '') {
|
||
return '';
|
||
}
|
||
const normalized = String(key).trim();
|
||
if (lookup.byRefId?.[normalized]) {
|
||
return lookup.byRefId[normalized];
|
||
}
|
||
if (lookup.byRefCode?.[normalized]) {
|
||
return lookup.byRefCode[normalized];
|
||
}
|
||
const lower = normalized.toLowerCase();
|
||
if (lookup.byRefCode?.[lower]) {
|
||
return lookup.byRefCode[lower];
|
||
}
|
||
for (const [code, kindName] of Object.entries(lookup.byRefCode || {})) {
|
||
if (code && normalized.includes(code)) {
|
||
return kindName;
|
||
}
|
||
}
|
||
return '';
|
||
}
|
||
|
||
/** 解析混炼示方明细种类:称量方式优先,其次分类 ID,再按分类名称(未命中返回空) */
|
||
export function resolveMixingMaterialKindFromLookup(
|
||
lookup: MixerMaterialKindLookup | null | undefined,
|
||
weighMode?: string,
|
||
minorCategoryId?: string,
|
||
minorCategoryName?: string,
|
||
) {
|
||
const fromWeighMode = matchKindFromLookup(lookup, weighMode);
|
||
if (fromWeighMode) {
|
||
return fromWeighMode;
|
||
}
|
||
const fromMinorId = matchKindFromLookup(lookup, minorCategoryId);
|
||
if (fromMinorId) {
|
||
return fromMinorId;
|
||
}
|
||
//update-begin---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】按胶料类别名称匹配种类配置-----------
|
||
if (minorCategoryName != null && String(minorCategoryName).trim() !== '') {
|
||
const refName = String(minorCategoryName).trim();
|
||
if (lookup?.byRefName?.[refName]) {
|
||
return lookup.byRefName[refName];
|
||
}
|
||
}
|
||
//update-end---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】按胶料类别名称匹配种类配置-----------
|
||
return '';
|
||
}
|
||
|
||
/** 胶料页签解析种类:配置匹配后可用 rubberKindName(如「胶料」)兜底 */
|
||
export function resolveMixingRubberKindForPicker(
|
||
lookup: MixerMaterialKindLookup | null | undefined,
|
||
weighMode?: string,
|
||
categoryId?: string,
|
||
categoryName?: string,
|
||
categoryCode?: string,
|
||
) {
|
||
let kind = resolveMixingMaterialKindFromLookup(lookup, weighMode, categoryId, categoryName);
|
||
if (!kind && categoryCode) {
|
||
kind = matchKindFromLookup(lookup, categoryCode);
|
||
}
|
||
if (!kind && lookup?.rubberKindName) {
|
||
kind = lookup.rubberKindName;
|
||
}
|
||
return kind;
|
||
}
|
||
|
||
/** @deprecated 保留兼容,请改用 resolveMixingMaterialKindFromLookup */
|
||
export function resolveMixingMaterialKindFromCategory(_isRubber?: unknown, minorName?: string) {
|
||
return minorName != null && String(minorName).trim() !== '' ? String(minorName).trim() : '';
|
||
}
|
||
|
||
/** @deprecated 保留兼容,请改用 resolveMixingMaterialKindFromLookup */
|
||
export function resolveMixingMaterialKindFromWeighMode(_weighMode?: string) {
|
||
return '';
|
||
}
|
||
|
||
/** 选料确认时种类:读密炼物料种类配置表 */
|
||
export function resolveMixingMaterialKindForPicker(
|
||
lookup: MixerMaterialKindLookup | null | undefined,
|
||
weighMode: string | undefined,
|
||
minorCategoryId?: string,
|
||
minorCategoryName?: string,
|
||
) {
|
||
return resolveMixingMaterialKindFromLookup(lookup, weighMode, minorCategoryId, minorCategoryName);
|
||
}
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A52】混炼示方种类改读密炼物料种类配置-----------
|
||
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】选料弹窗自动/人工称量列与种类映射-----------
|
||
/** 与配合示方「自动/人工」列相同字典 */
|
||
export const MIXING_MATERIAL_PICKER_WEIGH_MODE_DICT = 'xslmes_formula_spec_weigh_mode';
|
||
|
||
/** 选料弹窗表格列(隐藏 ERP 编号,新增种类列与自动/人工称量) */
|
||
export const mixingMaterialPickerTableColumns: BasicColumn[] = [
|
||
{ title: '物料编码', align: 'center', width: 120, dataIndex: 'materialCode' },
|
||
{ title: '物料名称', align: 'center', width: 160, dataIndex: 'materialName' },
|
||
{ title: '自动/人工称量', align: 'center', width: 132, dataIndex: 'pickerWeighMode' },
|
||
{ title: '种类', align: 'center', width: 100, dataIndex: 'pickerMaterialKind' },
|
||
{ title: '物料大类', align: 'center', width: 120, dataIndex: 'majorCategoryId_dictText' },
|
||
{ title: '物料小类', align: 'center', width: 120, dataIndex: 'minorCategoryId_dictText' },
|
||
{ title: '物料描述', align: 'center', width: 180, ellipsis: true, dataIndex: 'materialDesc' },
|
||
];
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】选料弹窗自动/人工称量列与种类映射-----------
|
||
|
||
/** 选择密炼物料后回填混炼示方橡胶及配合剂明细行 */
|
||
export function applyMixingMaterialFromSelection(row: Recordable, material: Recordable, materialKind: string) {
|
||
if (!row || !material) {
|
||
return;
|
||
}
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A55】选料回填密炼物料ID-----------
|
||
row.mixerMaterialId = material.id || material.mixerMaterialId || '';
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A55】选料回填密炼物料ID-----------
|
||
row.mixerMaterialName = material.materialName || material.materialCode || '';
|
||
row.mixerMaterialDesc = material.materialDesc || material.materialName || material.materialCode || '';
|
||
row.materialMajor = material.majorCategoryId_dictText || '';
|
||
row.materialMinor = material.minorCategoryId_dictText || '';
|
||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A53】种类仅读配置表,移除小类名兜底-----------
|
||
row.materialKind = materialKind != null && String(materialKind).trim() !== '' ? String(materialKind).trim() : '';
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A53】种类仅读配置表,移除小类名兜底-----------
|
||
}
|
||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】混炼示方密炼物料选料弹窗与种类解析-----------
|
||
|
||
//update-begin---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】选料弹窗新增胶料页签(查询胶料信息)-----------
|
||
/** 选料弹窗「胶料」页签表格列(数据源为胶料信息 mes_material) */
|
||
export const mixingRubberPickerTableColumns: BasicColumn[] = [
|
||
{ title: '胶料编码', align: 'center', width: 140, dataIndex: 'materialCode' },
|
||
{ title: '胶料名称', align: 'center', width: 180, dataIndex: 'materialName' },
|
||
//update-begin---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】胶料页签补齐自动/人工称量列-----------
|
||
{ title: '自动/人工称量', align: 'center', width: 132, dataIndex: 'pickerWeighMode' },
|
||
//update-end---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】胶料页签补齐自动/人工称量列-----------
|
||
{ title: '种类', align: 'center', width: 100, dataIndex: 'pickerMaterialKind' },
|
||
{ title: '胶料类别', align: 'center', width: 140, dataIndex: 'categoryId_dictText' },
|
||
{ title: '胶料别名', align: 'center', width: 140, dataIndex: 'aliasName' },
|
||
];
|
||
|
||
/** 选择胶料信息后回填混炼示方橡胶及配合剂明细行(复用 mixerMaterialId 存 mes_material.id) */
|
||
export function applyMixingRubberFromSelection(row: Recordable, material: Recordable, materialKind: string) {
|
||
if (!row || !material) {
|
||
return;
|
||
}
|
||
row.mixerMaterialId = material.id || '';
|
||
row.mixerMaterialName = material.materialName || material.materialCode || '';
|
||
row.mixerMaterialDesc = material.materialName || material.materialCode || '';
|
||
row.materialMajor = '';
|
||
row.materialMinor = material.categoryId_dictText || '';
|
||
row.materialKind = materialKind != null && String(materialKind).trim() !== '' ? String(materialKind).trim() : '';
|
||
}
|
||
//update-end---author:cursor ---date:20260601 for:【XSLMES-20260601-A62】选料弹窗新增胶料页签(查询胶料信息)-----------
|
||
|
||
//update-begin---author:cursor ---date:20260526 for:【XSLMES-20260526-A58】参照历史混合步骤选择弹窗-----------
|
||
/** 混合步骤可复制的业务字段 */
|
||
export const MIXING_STEP_COPY_FIELD_KEYS = [
|
||
'sortNo',
|
||
'actionName',
|
||
'actionSec',
|
||
'protectSec',
|
||
'tempC',
|
||
'powerKw',
|
||
'energyKwh',
|
||
'comboMode',
|
||
'speedRpm',
|
||
'pressureMpa',
|
||
'boltPercent',
|
||
] as const;
|
||
|
||
/** 判断混合步骤行是否含有效业务数据 */
|
||
export function isMixingStepRowFilled(row: Recordable = {}): boolean {
|
||
return MIXING_STEP_COPY_FIELD_KEYS.some((key) => {
|
||
const value = row[key];
|
||
return value != null && value !== '';
|
||
});
|
||
}
|
||
|
||
/** 从历史混炼示方混合步骤克隆为新行(生成新 id,剔除主表/审计字段) */
|
||
export function cloneMixingHistoryStepRows(sourceRows: Recordable[] = []): Recordable[] {
|
||
return (sourceRows || [])
|
||
.filter((row) => isMixingStepRowFilled(row))
|
||
.map((row, index) => {
|
||
const next: Recordable = { id: buildUUID() };
|
||
MIXING_STEP_COPY_FIELD_KEYS.forEach((key) => {
|
||
const value = row[key];
|
||
if (value != null && value !== '') {
|
||
next[key] = value;
|
||
}
|
||
});
|
||
if (next.sortNo == null) {
|
||
next.sortNo = index + 1;
|
||
}
|
||
return next;
|
||
});
|
||
}
|
||
|
||
/** 解析混炼示方配方状态(参照旧系统展示) */
|
||
export function resolveMixingSpecFormulaStatus(record: Recordable = {}): string {
|
||
if (Number(record.delFlag) === 1) {
|
||
return '作废';
|
||
}
|
||
if (record.approveTime) {
|
||
return '审批通过';
|
||
}
|
||
if (record.auditTime) {
|
||
return '审核通过';
|
||
}
|
||
if (record.proofreadTime) {
|
||
return '校对通过';
|
||
}
|
||
return '编制中';
|
||
}
|
||
|
||
/** 混炼示方是否允许编辑/删除(与配合示方一致:密炼PS校对后锁定) */
|
||
export function isMixingSpecEditable(record: Recordable = {}): boolean {
|
||
return !record?.proofreadBy && !record?.proofreadTime;
|
||
}
|
||
|
||
/** 参照历史混合步骤:混炼示方选择列表列 */
|
||
export const mixingSpecHistorySelectColumns: BasicColumn[] = [
|
||
{ title: '示方编号', align: 'center', dataIndex: 'specName', width: 160 },
|
||
{ title: '机台', align: 'center', dataIndex: 'machineName', width: 100 },
|
||
{ title: '发行编号', align: 'center', dataIndex: 'issueNumber', width: 150 },
|
||
{ title: '发行日期', align: 'center', dataIndex: 'makeDate', width: 120 },
|
||
{
|
||
title: '配方状态',
|
||
align: 'center',
|
||
dataIndex: 'formulaStatus',
|
||
width: 100,
|
||
customRender: ({ record }) => resolveMixingSpecFormulaStatus(record),
|
||
},
|
||
];
|
||
//update-end---author:cursor ---date:20260526 for:【XSLMES-20260526-A58】参照历史混合步骤选择弹窗-----------
|
||
|
||
//update-begin---author:cursor ---date:20260526 for:【XSLMES-20260526-A59】规格点击选择混炼示方及参照新增-----------
|
||
/** 参照新增时需剔除的主表字段 */
|
||
export const MIXING_SPEC_MAIN_STRIP_FIELDS = [
|
||
'id',
|
||
'createBy',
|
||
'createTime',
|
||
'updateBy',
|
||
'updateTime',
|
||
'draftBy',
|
||
'draftTime',
|
||
'proofreadBy',
|
||
'proofreadTime',
|
||
'auditBy',
|
||
'auditTime',
|
||
'approveBy',
|
||
'approveTime',
|
||
'changeDate',
|
||
'delFlag',
|
||
'tenantId',
|
||
'sysOrgCode',
|
||
] as const;
|
||
|
||
/** 参照新增时需剔除的明细字段 */
|
||
export const MIXING_SPEC_CHILD_STRIP_FIELDS = [
|
||
'id',
|
||
'mixingSpecId',
|
||
'createBy',
|
||
'createTime',
|
||
'updateBy',
|
||
'updateTime',
|
||
'tenantId',
|
||
] as const;
|
||
|
||
/** 参照选中示方新增:复制除 ID 及审计字段外的全部数据 */
|
||
export function cloneMixingSpecPageForReferenceAdd(source: Recordable = {}): Recordable {
|
||
const main: Recordable = { ...source };
|
||
MIXING_SPEC_MAIN_STRIP_FIELDS.forEach((key) => delete main[key]);
|
||
main.id = '';
|
||
|
||
const cloneChildList = (rows: Recordable[] = []) =>
|
||
normalizeMixingDetailRows(
|
||
(rows || []).map((row) => {
|
||
const next: Recordable = { ...row };
|
||
MIXING_SPEC_CHILD_STRIP_FIELDS.forEach((key) => delete next[key]);
|
||
delete next.baseUnitWeight;
|
||
return next;
|
||
}),
|
||
);
|
||
|
||
return {
|
||
...main,
|
||
materialList: cloneChildList(source.materialList),
|
||
stepList: cloneChildList(source.stepList),
|
||
downStepList: cloneChildList(source.downStepList),
|
||
tcuList: cloneChildList(source.tcuList),
|
||
};
|
||
}
|
||
//update-end---author:cursor ---date:20260526 for:【XSLMES-20260526-A59】规格点击选择混炼示方及参照新增-----------
|