From ce234132dd8b18d14592e0a0f6dc376823df2b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Wed, 26 Aug 2026 07:12:27 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20README=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB?= =?UTF-8?q?=D1=8F=20=E2=80=94=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B0=D1=87=D0=B0?= =?UTF-8?q?=20=D0=B2=20Flask,=20onXHR,=20=D1=81=D0=BB=D0=BE=D0=B9=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/routes/api_bp.py | 2 +- upload/README.md | 60 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/site/routes/api_bp.py b/site/routes/api_bp.py index c06ee27..c568185 100644 --- a/site/routes/api_bp.py +++ b/site/routes/api_bp.py @@ -30,7 +30,7 @@ from upload.backend.upload_refs import safe_name api_bp = Blueprint("api", __name__, url_prefix="/api") log = logging.getLogger("routes.api_bp") - +TMP/примеры_договоров_для_ИИ def _disconnect_exceptions(): """Исключения, означающие отключение клиента SSE.""" return (GeneratorExit, BrokenPipeError, ConnectionResetError) diff --git a/upload/README.md b/upload/README.md index eea2b74..f0826d5 100644 --- a/upload/README.md +++ b/upload/README.md @@ -53,10 +53,12 @@ const table = initUploadTable(cfg, { }); // Слой 2 — закачка учитываемых файлов на ВМ: -const res = await uploadViaVM(table.getFiles(), cfg.vmUploadUrl, { +// idxInSf[k] — индекс k-го отправляемого файла в строках таблицы (своя логика маппинга) +const res = await uploadViaVM(toSend, cfg.vmUploadUrl, { session: currentSid, - onStatus(k, html) { table.setStatus(idxInSf[k], html); }, // маппинг idx → строка таблицы + onStatus(k, html) { table.setStatus(idxInSf[k], html); }, // прогресс → ячейка таблицы onUploadStatus(text) { /* статусная строка */ }, + onXHR(xhr) { activeXHR = xhr; }, // регистрация активного PUT для отмены (abort) }); // res = {ok:true, session, count} | {ok:false, error} // После этого у вас в сессии res.session лежат файлы — запускайте СВОЮ обработку. @@ -103,6 +105,60 @@ app.register_blueprint(create_upload_refs_blueprint({ --- +## Раздача модуля в Flask (обязательно) + +Фронт-модули — ES-модули, браузер грузит их по HTTP (не через file://). +Добавьте route, который отдаёт папку `upload/frontend` (как в drhider `site/routes/main_bp.py`): + +```python +# в любом blueprint приложения +import os +from flask import send_from_directory + +_UPLOAD_FRONTEND = os.path.join(os.path.dirname(os.path.dirname(__file__)), + "upload", "frontend") + +@bp.route("/upload/") +def upload_frontend(filename): + return send_from_directory(_UPLOAD_FRONTEND, filename) +``` + +Тогда импорты в браузере: `import { initUploadTable } from '/upload/table/init_upload_table.js';`. + +> Если фронт-модули хостятся отдельно (другой домен/приложение) — путь `/upload/...` +> и CORS настраиваются под ваш случай (правка приложения/nginx, не кода модуля). + +--- + +## Слой 3: как подключить обработку (опционально) + +Модуль отдаёт файлы в сессию, а обрабатываете их ВЫ (обфускация, конвертация, ...). +После `uploadViaVM` файлы лежат в `res.session`: + +```python +files = get_files(res.session) # [(name, bytes), ...] +# ... ваша обработка ... +store_result(res.session, result_zip) # если нужно отдать результат обратно +``` + +Для 3-секционной таблицы прогресса (готово/текущий/ожидают) модуль предоставляет +`renderProcTable` — достаточно дать слою 3 доступ к `table.state.proc`: + +```js +table.state.proc = { phase: 'processing', procState: {}, procExtractRate: null }; +function syncProcCtx() { + table.state.proc.phase = phase; + table.state.proc.procState = procState; // {idx: {st, elapsed, eta, chars, t0}} + table.state.proc.procExtractRate = rate; // сек/МБ (для оценок ожидающих) +} +syncProcCtx(); +table.render(); // сам выберет renderProcTable при phase==='processing' +``` + +Статусы в ячейках: `table.setStatus(idx, html)`. + +--- + ## Конфиг (слой 0) Всё drhider-специфичное задаётся конфигом, а не кодом слоёв: