From 2668fb7a38aa8ad6596246bba80f4302cf99ae5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Thu, 25 Jun 2026 08:28:51 +0400 Subject: [PATCH] =?UTF-8?q?v1.0.177:=20=D1=84=D0=B8=D0=BD=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D0=B9=20=D0=BF=D0=BB=D0=B0=D0=BD=20=D1=80?= =?UTF-8?q?=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= =?UTF-8?q?=D0=B0=20=E2=80=94=20store+render,=204=20=D1=84=D0=B0=D0=B7?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- History/llm-analysis/decoupling-final-plan.md | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 History/llm-analysis/decoupling-final-plan.md diff --git a/History/llm-analysis/decoupling-final-plan.md b/History/llm-analysis/decoupling-final-plan.md new file mode 100644 index 0000000..208788c --- /dev/null +++ b/History/llm-analysis/decoupling-final-plan.md @@ -0,0 +1,85 @@ +# Финальный план рефакторинга — store + render + +Согласовано: DeepSeek + Opus. Все открытые вопросы закрыты. + +## Архитектурное решение + +**Патерн:** единый `state` объект + одна `render(state)` + actions мутируют state. + +``` +action → мутация state → render(state) +``` + +- Асинхронные операции (upload, classify, compare-SSE) — actions, пишут в state +- Синхронные трансформации (group, applyParseResult) — чистые функции +- DOM — проекция state, никто не читает из DOM +- `console.log(state)` показывает всё + +## Структура state + +```javascript +state = { + batchId, contractId, + files: [{ id, name, size, status: { kind, pct, text, count }, parse, classify, supp_id, detailOpen }], + groups: [{ + contractNumber, counterparty, documents, unresolved, + compare: { status, sections: { [suppId]: { header, body, ops } }, totalTime, collapsed } + }], + compareAll: { status, sections, totalTime }, + ui: { steps: { upload, classify, groups, compare } }, + _activeCompare: { es, timer } +} +``` + +## Фазы + +### Фаза 0 — Каркас +- Ввести `state`, `render(state)` (пока вызывает существующие рендеры) +- Соглашение: мутировал → `render()` + +### Фаза 1 — Файлы +- `fileQueue` → `state.files` +- `renderTable` → `renderFiles(state)` +- `fileInput change` разбит: + - `onFilesSelected(files)` — оркестратор (10-15 строк) + - `reconcileSelection(newFiles)` — чистая мутация массива + - `addZipFiles(file)` — async-action + - `addRegularFile(file)` — async-action + - `applyParseResult(entry, parsed)` — чистая функция (убирает дубль zip/обычной ветки) + - `finalizeUpload()` — refreshSupps + stepDone + syncDB + кнопки +- `status` → структура `{ kind, pct, text, count }`, HTML через `statusToHTML(status)` +- Убрать `renderTable()` из обработчиков — только `render()` в конце action + +### Фаза 2 — Группы +- `loadGroups` → `loadGroupsAction()` (fetch → state.groups) + `renderGroups(state)` +- `buildGroupCard` → `renderGroupCard(group)` — чистая HTML-функция +- **`markGroupDone` удалить** — готовность = `state.groups[gi].compare.status === 'done'` +- Убрать `window._groupsData` +- `renderGroups` пересобирает ВСЕ карточки целиком + +### Фаза 3 — Сравнение/SSE +- Унификация через общие функции: + - `applyCompareEvent(target, event)` — чистая мутация SSE-события в target + - `startCompareSSE(url, target, { onDone })` — жизненный цикл SSE + - `renderCompareSections(sections)` — общий рендер таблиц ops +- `runCompareForGroup` → тонкая обёртка над `startCompareSSE` +- `llmBtn` → тонкая обёртка над `startCompareSSE` +- ~160 строк дублирования → ~60 строк общих + 2 вызова + +### Фаза 4 — Чистка +- `contractId`, `batchId` → `state` +- Степпер → `renderStepper(state)` +- Промпты, чат, showText — вне scope (отдельная итерация) + +## Верификация + +1. После каждой правки: `node -c` на app.js + app_utils.js +2. После Фазы 2: node-тесты на чистые функции (`applyParseResult`, `statusToHTML`, `renderGroupCard`) +3. Ручной прогон upload→classify→group→compare после git push +4. Регресс: «Готово» не перезапускается, параллельные сравнения заблокированы, группы не затираются + +## Релевантные файлы + +- `contractor/deploy/app.js` — все фазы (~1040 строк) +- `contractor/deploy/app_utils.js` — removeFile/moveUp/moveDown (Фаза 1) +- `contractor/index.cfm` — DOM-скелет, версия v1.0.177, `?v=` для cache bust