mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-11 20:50:52 +03:00
Merge branch 'dev' — checkbox support for readTable/getFormState/fillTableRow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2110,7 +2110,16 @@ export async function fillTableRow(fields, { tab, add, row, table } = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Add new row if requested
|
// 2. Add new row if requested
|
||||||
|
let addedRowIdx = -1;
|
||||||
if (add) {
|
if (add) {
|
||||||
|
// Count rows before add — new row will be appended at this index
|
||||||
|
addedRowIdx = await page.evaluate(`(() => {
|
||||||
|
const grid = ${gridSelector
|
||||||
|
? `document.querySelector(${JSON.stringify(gridSelector)})`
|
||||||
|
: `(() => { const grids = [...document.querySelectorAll('.grid')].filter(el => el.offsetWidth > 0); return grids[grids.length - 1]; })()`};
|
||||||
|
const body = grid?.querySelector('.gridBody');
|
||||||
|
return body ? body.querySelectorAll('.gridLine').length : 0;
|
||||||
|
})()`);
|
||||||
await clickElement('Добавить', { table });
|
await clickElement('Добавить', { table });
|
||||||
// Poll for edit mode (INPUT inside grid) instead of fixed 1000ms wait
|
// Poll for edit mode (INPUT inside grid) instead of fixed 1000ms wait
|
||||||
for (let aw = 0; aw < 6; aw++) {
|
for (let aw = 0; aw < 6; aw++) {
|
||||||
@@ -2206,6 +2215,13 @@ export async function fillTableRow(fields, { tab, add, row, table } = {}) {
|
|||||||
}
|
}
|
||||||
const results = [{ field: firstKey0, ok: true, method: 'toggle', value: desired }];
|
const results = [{ field: firstKey0, ok: true, method: 'toggle', value: desired }];
|
||||||
await waitForStable(formNum);
|
await waitForStable(formNum);
|
||||||
|
// If more fields remain, process them on the same row
|
||||||
|
const remaining = { ...fields };
|
||||||
|
delete remaining[firstKey0];
|
||||||
|
if (Object.keys(remaining).length > 0) {
|
||||||
|
const more = await fillTableRow(remaining, { row, table });
|
||||||
|
results.push(...more);
|
||||||
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2521,7 +2537,10 @@ export async function fillTableRow(fields, { tab, add, row, table } = {}) {
|
|||||||
if (cell.tag !== 'INPUT' || !cell.fullName) {
|
if (cell.tag !== 'INPUT' || !cell.fullName) {
|
||||||
// Not in an editable grid cell — Tab past (ERP has DIV focus between cells)
|
// Not in an editable grid cell — Tab past (ERP has DIV focus between cells)
|
||||||
nonInputCount++;
|
nonInputCount++;
|
||||||
if (nonInputCount > 3) break; // truly exited edit mode
|
// If only checkbox fields remain unfilled, stop Tab'ing to avoid creating extra rows
|
||||||
|
const onlyCheckboxLeft = [...pending.values()].every(p => p.filled ||
|
||||||
|
['true', 'false', 'да', 'нет', '1', '0', 'yes', 'no'].includes(p.value.toLowerCase().trim()));
|
||||||
|
if (nonInputCount > 3 || onlyCheckboxLeft) break;
|
||||||
await page.keyboard.press('Tab');
|
await page.keyboard.press('Tab');
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
continue;
|
continue;
|
||||||
@@ -3029,6 +3048,45 @@ export async function fillTableRow(fields, { tab, add, row, table } = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const notFilled = [...pending].filter(([_, info]) => !info.filled).map(([key]) => key);
|
const notFilled = [...pending].filter(([_, info]) => !info.filled).map(([key]) => key);
|
||||||
|
|
||||||
|
// Retry unfilled checkbox fields via direct click (Tab skips checkbox cells)
|
||||||
|
if (notFilled.length > 0) {
|
||||||
|
const checkboxFields = {};
|
||||||
|
for (const key of notFilled) {
|
||||||
|
const val = String(pending.get(key).value).toLowerCase().trim();
|
||||||
|
if (['true', 'false', 'да', 'нет', '1', '0', 'yes', 'no'].includes(val)) {
|
||||||
|
checkboxFields[key] = pending.get(key).value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(checkboxFields).length > 0) {
|
||||||
|
// Use row index: addedRowIdx (from add mode) or fallback to selected row
|
||||||
|
const currentRow = addedRowIdx >= 0 ? addedRowIdx : (row != null ? row : await page.evaluate(`(() => {
|
||||||
|
const grid = ${gridSelector
|
||||||
|
? `document.querySelector(${JSON.stringify(gridSelector)})`
|
||||||
|
: `(() => { const grids = [...document.querySelectorAll('.grid')].filter(el => el.offsetWidth > 0); return grids[grids.length - 1]; })()`};
|
||||||
|
if (!grid) return -1;
|
||||||
|
const body = grid.querySelector('.gridBody');
|
||||||
|
if (!body) return -1;
|
||||||
|
const lines = [...body.querySelectorAll('.gridLine')];
|
||||||
|
const sel = lines.findIndex(l => l.classList.contains('selected'));
|
||||||
|
return sel >= 0 ? sel : lines.length - 1;
|
||||||
|
})()`)
|
||||||
|
);
|
||||||
|
if (currentRow >= 0) {
|
||||||
|
const more = await fillTableRow(checkboxFields, { row: currentRow, table });
|
||||||
|
if (Array.isArray(more)) {
|
||||||
|
results.push(...more);
|
||||||
|
} else if (more?.filled) {
|
||||||
|
results.push(...more.filled);
|
||||||
|
}
|
||||||
|
for (const key of Object.keys(checkboxFields)) {
|
||||||
|
const idx = notFilled.indexOf(key);
|
||||||
|
if (idx >= 0) notFilled.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const formData = await getFormState();
|
const formData = await getFormState();
|
||||||
const result = { filled: results };
|
const result = { filled: results };
|
||||||
if (notFilled.length > 0) result.notFilled = notFilled;
|
if (notFilled.length > 0) result.notFilled = notFilled;
|
||||||
|
|||||||
@@ -200,7 +200,20 @@ const READ_FORM_FN = `function readForm(p) {
|
|||||||
if (box.offsetWidth === 0) return;
|
if (box.offsetWidth === 0) return;
|
||||||
const textEl = box.querySelector('.gridBoxText');
|
const textEl = box.querySelector('.gridBoxText');
|
||||||
const text = (textEl || box).innerText?.trim().replace(/\\n/g, ' ') || '';
|
const text = (textEl || box).innerText?.trim().replace(/\\n/g, ' ') || '';
|
||||||
if (text) columns.push(text);
|
if (text) {
|
||||||
|
columns.push(text);
|
||||||
|
} else {
|
||||||
|
// Unnamed column — check if data cells contain checkboxes
|
||||||
|
const firstLine = body?.querySelector('.gridLine');
|
||||||
|
if (firstLine) {
|
||||||
|
const visibleHeaders = [...headLine.children].filter(c => c.offsetWidth > 0);
|
||||||
|
const idx = visibleHeaders.indexOf(box);
|
||||||
|
const cells = [...firstLine.children].filter(c => c.offsetWidth > 0);
|
||||||
|
if (cells[idx]?.querySelector('.checkbox')) {
|
||||||
|
columns.push('(checkbox)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const rowCount = body ? body.querySelectorAll('.gridLine').length : 0;
|
const rowCount = body ? body.querySelectorAll('.gridLine').length : 0;
|
||||||
@@ -483,7 +496,20 @@ export function readTableScript(formNum, { maxRows = 20, offset = 0, gridSelecto
|
|||||||
if (box.offsetWidth === 0) return;
|
if (box.offsetWidth === 0) return;
|
||||||
const textEl = box.querySelector('.gridBoxText');
|
const textEl = box.querySelector('.gridBoxText');
|
||||||
const text = (textEl || box).innerText?.trim().replace(/\\n/g, ' ') || '';
|
const text = (textEl || box).innerText?.trim().replace(/\\n/g, ' ') || '';
|
||||||
if (!text) return;
|
if (!text) {
|
||||||
|
// Unnamed column — check if data cells contain checkboxes
|
||||||
|
const firstLine = body?.querySelector('.gridLine');
|
||||||
|
if (firstLine) {
|
||||||
|
const visibleHeaders = [...headLine.children].filter(c => c.offsetWidth > 0);
|
||||||
|
const idx = visibleHeaders.indexOf(box);
|
||||||
|
const cells = [...firstLine.children].filter(c => c.offsetWidth > 0);
|
||||||
|
if (cells[idx]?.querySelector('.checkbox')) {
|
||||||
|
const r = box.getBoundingClientRect();
|
||||||
|
columns.push({ text: '(checkbox)', x: r.x, w: r.width, right: r.x + r.width });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
const r = box.getBoundingClientRect();
|
const r = box.getBoundingClientRect();
|
||||||
columns.push({ text, x: r.x, w: r.width, right: r.x + r.width });
|
columns.push({ text, x: r.x, w: r.width, right: r.x + r.width });
|
||||||
});
|
});
|
||||||
@@ -501,8 +527,14 @@ export function readTableScript(formNum, { maxRows = 20, offset = 0, gridSelecto
|
|||||||
[...line.children].forEach(box => {
|
[...line.children].forEach(box => {
|
||||||
if (box.offsetWidth === 0) return;
|
if (box.offsetWidth === 0) return;
|
||||||
const textEl = box.querySelector('.gridBoxText');
|
const textEl = box.querySelector('.gridBoxText');
|
||||||
const val = (textEl || box).innerText?.trim().replace(/\\n/g, ' ') || '';
|
const chk = box.querySelector('.checkbox');
|
||||||
if (!val) return;
|
let val;
|
||||||
|
if (chk) {
|
||||||
|
val = chk.classList.contains('select') ? 'true' : 'false';
|
||||||
|
} else {
|
||||||
|
val = (textEl || box).innerText?.trim().replace(/\\n/g, ' ') || '';
|
||||||
|
if (!val) return;
|
||||||
|
}
|
||||||
// Match cell to column by X-coordinate overlap
|
// Match cell to column by X-coordinate overlap
|
||||||
const r = box.getBoundingClientRect();
|
const r = box.getBoundingClientRect();
|
||||||
const cx = r.x + r.width / 2;
|
const cx = r.x + r.width / 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user