From a3199d636ed15b1de8a4f8a65d41b1a5e1d79ea9 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sun, 18 Oct 2026 20:06:02 +0400 Subject: [PATCH] =?UTF-8?q?fix(arm-web):=20=D0=B2=D1=91=D1=80=D1=81=D1=82?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=8D=D0=BA=D1=80=D0=B0=D0=BD=D0=B0=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D1=8B=20=E2=80=94=20=D1=88=D0=B8=D1=80=D0=B8=D0=BD=D1=8B?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD=D0=BE=D0=BA,=20=D0=B7=D0=BD?= =?UTF-8?q?=D0=B0=D1=87=D0=BA=D0=B8=20=D0=B2=20=D1=8F=D1=87=D0=B5=D0=B9?= =?UTF-8?q?=D0=BA=D0=B5,=20=D1=88=D0=B0=D0=BF=D0=BA=D0=B0,=20=D1=81=D1=81?= =?UTF-8?q?=D1=8B=D0=BB=D0=BA=D0=B0=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA=D0=BE?= =?UTF-8?q?=D0=B9=20(#43)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit T11.1–T11.4, T11.6–T11.8: короткая подпись кнопки даты, фиксированная раскладка таблиц, код без переноса, значок уровня внутри ячейки, подсказка на всю ячейку, отступ child-строки, ссылка «Разберите строки без кода» — Button type=link. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W --- src/widgets/DocumentReview/ColumnHeader.tsx | 15 ++++++++--- .../DocumentReview/StatementHeaderBlock.tsx | 21 +++++++++++---- .../DocumentReview/StatementReview.tsx | 13 ++++++--- src/widgets/DocumentReview/StatementTable.tsx | 18 ++++++++----- src/widgets/DocumentReview/ValueCell.tsx | 27 ++++++++++--------- 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/widgets/DocumentReview/ColumnHeader.tsx b/src/widgets/DocumentReview/ColumnHeader.tsx index 7c44e3f..b585d98 100644 --- a/src/widgets/DocumentReview/ColumnHeader.tsx +++ b/src/widgets/DocumentReview/ColumnHeader.tsx @@ -51,9 +51,18 @@ export function ColumnHeader({ col, issues, editing, draftDate, error = false, o style={{ marginTop: 4, fontWeight: 400 }} /> {canConfirm && ( - + // короткая подпись, чтобы кнопка помещалась в колонку 112 px и ширина не прыгала (T11.1); длинный текст — в подсказке + + + )} ); diff --git a/src/widgets/DocumentReview/StatementHeaderBlock.tsx b/src/widgets/DocumentReview/StatementHeaderBlock.tsx index 56d1094..01f2480 100644 --- a/src/widgets/DocumentReview/StatementHeaderBlock.tsx +++ b/src/widgets/DocumentReview/StatementHeaderBlock.tsx @@ -45,7 +45,12 @@ export function StatementHeaderBlock({ header, documentType, editing, draft, onD const reportDate = formatReportDate(header.report_date.value); return (
- +
+ {/* фиксированная раскладка: ширина блока не зависит от содержимого и подписи кнопки (T11.6) */} + + + + {headerFields(header, byField).map((r) => ( @@ -54,7 +59,6 @@ export function StatementHeaderBlock({ header, documentType, editing, draft, onD style={{ ...cell, fontWeight: 600, - minWidth: r.field === 'organization_name' ? 320 : 160, background: fieldBackground(r.modified, r.attention), }}> {r.issues.length > 0 && ( @@ -74,9 +78,16 @@ export function StatementHeaderBlock({ header, documentType, editing, draft, onD onChange={(e) => onDraftChange(r.field, e.target.value)} /> {r.canConfirm && onConfirmDate && ( - + + + )} ) : ( diff --git a/src/widgets/DocumentReview/StatementReview.tsx b/src/widgets/DocumentReview/StatementReview.tsx index 1ab3ac7..bc61dad 100644 --- a/src/widgets/DocumentReview/StatementReview.tsx +++ b/src/widgets/DocumentReview/StatementReview.tsx @@ -208,7 +208,9 @@ export function StatementReview({ document, onChanged }: { document: DocumentOut confirmDescription = confirmFailures.map((f) =>
{failureText(f)}
); } else if (confirmLines.length > 0) { confirmDescription = ( - focusRow(confirmLines[0].line_id)}>{unresolvedHint(confirmLines.length)} + ); } else if (duplicateId) { confirmDescription = ( @@ -242,9 +244,6 @@ export function StatementReview({ document, onChanged }: { document: DocumentOut onClick={confirm}> Подтвердить данные - {unresolved.length > 0 && ( - focusRow(unresolved[0].key)}>{unresolvedHint(unresolved.length)} - )} ); @@ -259,6 +258,12 @@ export function StatementReview({ document, onChanged }: { document: DocumentOut
+ {unresolved.length > 0 && ( + // настоящая кнопка: достижима Tab, срабатывает по Enter; отдельной строкой, чтобы не ломать заголовок (T11.7) + + )} void; }; +const ICON_WIDTH = 18; // значок уровня с отступом: у ребёнка вычитается из отступа, чтобы текст не съезжал const CHILD_INDENT = 20; // отступ названия строки детализации под родителем function lineWeight(r: LayoutRow): number | undefined { @@ -89,7 +90,7 @@ export function StatementTable({ const rowIssues = places.byRow.get(r.key) ?? []; const rowWorst = worstSeverity(rowIssues); const text = ( - + {r.displayName || '—'} {r.secondaryName && ( @@ -111,9 +112,11 @@ export function StatementTable({ ) : ( namedText ); - if (!rowWorst) return named; + // отступ ребёнка — на общей обёртке: значок уровня остаётся внутри отступа и не сдвигает текст (T11.8) + const indent = r.child ? CHILD_INDENT : undefined; + if (!rowWorst) return
{named}
; return ( - <> +
(
{i.message}
@@ -123,16 +126,16 @@ export function StatementTable({
{named} - +
); }, }, { key: 'code', title: 'Код', - width: editable ? 160 : 60, + width: editable ? 160 : 84, align: 'center' as const, - onCell: (r) => (r.kind === 'section' ? sectionSpan(r, false) : { style: { background: labelBackground(r) } }), + onCell: (r) => (r.kind === 'section' ? sectionSpan(r, false) : { style: { background: labelBackground(r), whiteSpace: 'nowrap' } }), render: (_: unknown, r: LayoutRow) => { if (r.kind !== 'line') return null; const lineId = r.row.lineId; @@ -161,7 +164,7 @@ export function StatementTable({ onConfirmDate={onColumnDateConfirm} /> ), - width: 112, + width: 128, align: 'right' as const, onCell: (r: LayoutRow) => r.kind === 'section' @@ -198,6 +201,7 @@ export function StatementTable({ return ( size='small' + tableLayout='fixed' bordered rowKey='key' columns={tableColumns} diff --git a/src/widgets/DocumentReview/ValueCell.tsx b/src/widgets/DocumentReview/ValueCell.tsx index c5d920c..6681191 100644 --- a/src/widgets/DocumentReview/ValueCell.tsx +++ b/src/widgets/DocumentReview/ValueCell.tsx @@ -1,9 +1,9 @@ import { CheckOutlined, UndoOutlined } from '@ant-design/icons'; -import { Button, Input, Tooltip } from 'antd'; +import { Button, Input, Tooltip, Typography } from 'antd'; import type { IssueOut, ValueOut } from '../../types/api'; -import { formatAmount, parseAmountInput } from '../../utils/money'; +import { parseAmountInput } from '../../utils/money'; import { SeverityIcon } from './IssuesPanel'; -import { cellTipLines } from './cellView'; +import { cellTipLines, valueCellText } from './cellView'; import type { CellConfirmState } from './editRules'; import { worstSeverity } from './issuePlaces'; @@ -51,17 +51,19 @@ export function ValueCell({ }: Props) { const lines = cellTipLines(value, issues); const worst = worstSeverity(issues); - // значок — в левом углу ячейки; поверх ввода и текста, не двигает суммы - const corner = worst && ; + const shown = valueCellText(value); + // значок уровня — внутри ячейки, слева от суммы, по центру по вертикали (T11.3) + const corner = worst && ; const tip = lines.length > 0 ? lines.map((line, i) =>
{line}
) : undefined; if (!editable) { return ( + // подсказка на всей ячейке: блок на всю ширину колонки (T11.4) - +
{corner} - {value.is_confirmed && } - {formatAmount(value.amount, { fraction: 'auto', empty: '-' })} - + {value.is_confirmed && } + {shown.muted ? {shown.text} : shown.text} +
); } @@ -70,7 +72,7 @@ export function ValueCell({ const pending = confirmState === 'pending-confirm' || confirmState === 'pending-unconfirm'; return ( - +
{corner} : undefined} value={text} onChange={(e) => onDraftChange(draftKey, e.target.value, value.amount)} - // значок записи лежит в левом углу поверх поля — освобождаем ему место, чтобы не налезал на галочку и текст - style={{ textAlign: 'right', paddingLeft: worst ? 14 : undefined }} + style={{ textAlign: 'right', minWidth: 0, flex: 1 }} /> {confirmState && ( @@ -93,7 +94,7 @@ export function ValueCell({ /> )} - +
); }