9c37fa4c61
2、调整客商 3、调整临时额度 4、新增表头拖拽排序
138 lines
3.9 KiB
JavaScript
138 lines
3.9 KiB
JavaScript
const FORM_SELECTOR = '.el-dialog .el-form';
|
|
const ITEM_SELECTOR = '.el-form-item';
|
|
const COLUMN_TOLERANCE = 8;
|
|
const REQUIRED_MARK_WIDTH = 12;
|
|
|
|
let textMeasureEl;
|
|
|
|
const isVisible = element => {
|
|
if (!element) return false;
|
|
const rect = element.getBoundingClientRect();
|
|
return rect.width > 0 && rect.height > 0;
|
|
};
|
|
|
|
const getDirectLabel = item => {
|
|
return Array.from(item.children).find(child => child.classList.contains('el-form-item__label'));
|
|
};
|
|
|
|
const getColumnLeft = item => {
|
|
const column = item.closest('.el-col');
|
|
const target = column || item;
|
|
return Math.round(target.getBoundingClientRect().left);
|
|
};
|
|
|
|
const findColumnGroup = (groups, left) => {
|
|
return groups.find(group => Math.abs(group.left - left) <= COLUMN_TOLERANCE);
|
|
};
|
|
|
|
const getTextMeasureEl = () => {
|
|
if (textMeasureEl) return textMeasureEl;
|
|
textMeasureEl = document.createElement('span');
|
|
textMeasureEl.style.position = 'fixed';
|
|
textMeasureEl.style.left = '-9999px';
|
|
textMeasureEl.style.top = '-9999px';
|
|
textMeasureEl.style.visibility = 'hidden';
|
|
textMeasureEl.style.whiteSpace = 'nowrap';
|
|
textMeasureEl.style.pointerEvents = 'none';
|
|
document.body.appendChild(textMeasureEl);
|
|
return textMeasureEl;
|
|
};
|
|
|
|
const measureLabelWidth = (label, item) => {
|
|
const text = String(label.textContent || '').trim();
|
|
if (!text) return 0;
|
|
|
|
const style = window.getComputedStyle(label);
|
|
const measurer = getTextMeasureEl();
|
|
measurer.style.font = style.font;
|
|
measurer.style.letterSpacing = style.letterSpacing;
|
|
measurer.textContent = text;
|
|
|
|
const paddingLeft = Number.parseFloat(style.paddingLeft) || 0;
|
|
const paddingRight = Number.parseFloat(style.paddingRight) || 0;
|
|
const requiredWidth = item.classList.contains('is-required') ? REQUIRED_MARK_WIDTH : 0;
|
|
return Math.ceil(measurer.getBoundingClientRect().width + paddingLeft + paddingRight + requiredWidth);
|
|
};
|
|
|
|
const collectLabelGroups = form => {
|
|
const groups = [];
|
|
const items = Array.from(form.querySelectorAll(ITEM_SELECTOR));
|
|
|
|
items.forEach(item => {
|
|
if (!isVisible(item) || item.closest('.avue-form__menu')) return;
|
|
|
|
const label = getDirectLabel(item);
|
|
if (!label || !isVisible(label)) return;
|
|
|
|
const width = measureLabelWidth(label, item);
|
|
if (!width) return;
|
|
|
|
const left = getColumnLeft(item);
|
|
let group = findColumnGroup(groups, left);
|
|
if (!group) {
|
|
group = {
|
|
left,
|
|
labels: [],
|
|
width: 0,
|
|
};
|
|
groups.push(group);
|
|
}
|
|
|
|
group.labels.push(label);
|
|
group.width = Math.max(group.width, width);
|
|
});
|
|
|
|
return groups;
|
|
};
|
|
|
|
const alignFormLabelsByColumn = form => {
|
|
if (form.classList.contains('dialog-form-label-fixed')) return;
|
|
const groups = collectLabelGroups(form);
|
|
|
|
groups.forEach(group => {
|
|
group.labels.forEach(label => {
|
|
const width = `${group.width}px`;
|
|
if (label.style.width !== width) {
|
|
label.style.width = width;
|
|
}
|
|
if (label.style.flexBasis !== width) {
|
|
label.style.flexBasis = width;
|
|
}
|
|
if (label.style.justifyContent !== 'flex-end') {
|
|
label.style.justifyContent = 'flex-end';
|
|
}
|
|
if (label.style.textAlign !== 'right') {
|
|
label.style.textAlign = 'right';
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
const alignAllDialogFormLabels = () => {
|
|
document.querySelectorAll(FORM_SELECTOR).forEach(alignFormLabelsByColumn);
|
|
};
|
|
|
|
export const setupDialogFormLabelAlign = () => {
|
|
if (typeof window === 'undefined' || typeof document === 'undefined') return;
|
|
|
|
let frameId = 0;
|
|
const scheduleAlign = () => {
|
|
if (frameId) return;
|
|
frameId = window.requestAnimationFrame(() => {
|
|
frameId = 0;
|
|
alignAllDialogFormLabels();
|
|
});
|
|
};
|
|
|
|
scheduleAlign();
|
|
window.addEventListener('resize', scheduleAlign);
|
|
|
|
const observer = new MutationObserver(scheduleAlign);
|
|
observer.observe(document.body, {
|
|
attributes: true,
|
|
attributeFilter: ['class', 'style'],
|
|
childList: true,
|
|
subtree: true,
|
|
});
|
|
};
|