v1.0.177: финальный план рефакторинга — store+render, 4 фазы
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user