5.1 KiB
Запрос для Opus — Рефакторинг фронтенда Contracts
Контекст
Проект: сверка договоров через LLM (colocation, ЦОД). Фронтенд — ванильный JS (app.js ~51KB + app_utils.js ~4KB). Бэкенд — Python http.server на ВМ. Фронт управляет пайплайном:
Загрузка → Парсинг → Классификация → Группировка → Сравнение
Текущая проблема
Код эволюционировал organically. Глобальные переменные (fileQueue, contractId, batchId), манипуляции с DOM через innerHTML, состояние размазано по DOM и JS-переменным. Последствия:
- Сложно тестировать (нет изолированных юнитов)
- Сложно отлаживать (состояние не в одном месте)
- Баги с гонками, затиранием данных, повторными срабатываниями кнопок
- Любое изменение ломает что-то в другом месте
Идея заказчика (НЕ догма — оцени и предложи лучшее)
Разбить на независимые функции-пайплайн:
upload(files) → [{ id, name, parsed }]
classify(docs) → [{ id, name, parsed, type, number, date, counterparty }]
group(classified) → [{ contract, documents[] }]
compare(group) → { contract, documents[], results[], expandable }
render(state) → DOM
Каждая функция: чистые входные данные → новые выходные, не мутирует, не трогает DOM. Рендеринг — отдельно. Состояние хранится в одном месте.
Что нужно от тебя
-
Оценить идею. Это правильный подход для ванильного JS? Или есть более подходящий паттерн (state machine, pub/sub, flux-like store)? Не изобретай велосипед — бери best practices для проектов такого масштаба (~50KB JS).
-
Предложить архитектуру. Как организовать код чтобы:
- Каждый этап пайплайна тестируем изолированно
- Состояние предсказуемо и отлаживаемо (console.log одного объекта показывает всё)
- DOM-рендеринг отделён от логики
- Минимальные изменения в текущем коде (не переписывать с нуля)
-
План миграции. Как перейти от текущего состояния к новому постепенно, не ломая работающий функционал.
Релевантные файлы (читать)
contractor/deploy/app.js— весь фронтенд (~51KB): renderTable, runClassify, loadGroups, runCompareForGroup, buildGroupCard, markGroupDone, syncDB, stepper, toggleClassifyDetail, showText, SSE handlerscontractor/deploy/app_utils.js— утилиты: removeFile, escHtml, formatSize, formatDate, openAboutcontractor/index.cfm— HTML-оболочка, DOM-структура
Игнорировать
contractor/deploy/convert_server.pyи все Python-файлы — бэкенд, не рефакторимcontractor/deploy/db/,contractor/deploy/services/— бэкендcontractor/*.cfmкроме index.cfm — старый Lucee-кодcontracts-app/,contracts-vm/,History/,DOC/,FILES/— не относится
Ключевые функции для анализа
| Функция | Строки (app.js) | Что делает |
|---|---|---|
| renderTable | 57-75 | Рендер таблицы файлов |
| fileInput change | 76-290 | Загрузка + парсинг |
| runClassify | 308-360 | Классификация |
| loadGroups | 362-430 | Группировка + рендер карточек |
| buildGroupCard | 433-442 | Карточка необработанной группы |
| markGroupDone | 444-478 | Карточка обработанной группы |
| runCompareForGroup | 483-590 | Сравнение группы (apply → SSE) |
| toggleClassifyDetail | 91-130 | Раскрытие промежуточных результатов |
| syncDB | 26-34 | Синхронизация БД с таблицей |
| stepper | 38-56 | StepDone/StepActive/ResetStepper |
Ограничения
- Без фреймворков (ванильный JS)
- Без классов и наследования (не ООП)
- Минимум зависимостей между модулями
- Фокус на тестируемость и отлаживаемость
- Не переписывать с нуля — мигрировать постепенно