v0.0.64: тикер текущего файла и оценки времени на всех этапах обработки (в т.ч. извлечение), самокалибровка скорости
Deploy drhider / validate (push) Canceled after 0s

This commit is contained in:
“Naeel”
2026-08-24 15:23:38 +03:00
parent db7cdbdd84
commit a645493c32
2 changed files with 29 additions and 1 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ if _sys_path_root not in sys.path:
sys.path.insert(0, _sys_path_root)
# Версия приложения (меняется при изменениях)
VERSION = "0.0.63"
VERSION = "0.0.64"
def setup_logging():
+28
View File
@@ -210,6 +210,7 @@ let procPhase = 'idle'; // 'idle' | 'processing'
let procState = {}; // sfIdx -> {st, elapsed, eta, est, chars, t0}
let procNameIdx = {}; // имя (с бэка) -> sfIdx
let procExtractDone = false; // true после extract_done (далее done = реальная готовность)
let procExtractRate = null; // измеренная скорость извлечения (сек/МБ) для оценок ожидающих
let procRefresh = null; // setInterval перерисовки таблицы
let ptimer = null, liveRefresh = null; // таймеры статуса и live-блока
const MAX_FILE_BYTES = 50 * 1024 * 1024; // 50 МБ на один файл
@@ -235,6 +236,7 @@ function resetAll() {
procState = {};
procNameIdx = {};
procExtractDone = false;
procExtractRate = null;
document.getElementById('cancelBtn').style.display = 'none';
fi.value = '';
rr();
@@ -323,10 +325,17 @@ function renderProcTable() {
rows.push('<tr class="grp-row"><td colspan="4">○ Ожидают обработки (' + groups.pending.length + ')</td></tr>');
for (const i of groups.pending) {
const p = procState[i] || {};
// Оценка: LLM (chars x rate) если известна; иначе грубая по размеру/скорости извлечения
if (rate && !p.est && p.chars > 0) p.est = p.chars * rate;
if (!p.est) {
const szMB = (sf[i] ? sf[i].size : 0) / 1048576;
const k = procExtractRate || 3; // сек/МБ: замеренная или запасная
p.est = Math.max(1, Math.round(szMB * k));
}
let txt;
if (overNames.has(sf[i].name)) txt = '<span style="color:#c0392b;">🔥 не учитывается</span>';
else if (p.st === 'analyzed') txt = '<span style="color:#7d3c98;">анализ ✓</span>';
else if (p.st === 'current') txt = '<span style="color:#2563eb;">⏳</span>';
else if (p.est != null) txt = '<span style="color:#999;">~' + fmtSec(p.est) + '</span>';
else txt = '<span style="color:#999;">—</span>';
rows.push(procRow(i, txt));
@@ -644,6 +653,7 @@ async function uploadFiles() {
procState = {};
procNameIdx = {};
procExtractDone = false;
procExtractRate = null;
for (let k = 0; k < total; k++) {
procState[sendIdx[k]] = { st: 'pending', elapsed: 0, eta: null, est: null, chars: 0, t0: 0 };
}
@@ -688,6 +698,20 @@ async function uploadFiles() {
procNameIdx[d.name] = idx;
const p = procState[idx];
if (p) { p.st = 'pending'; p.elapsed = 0; }
// Этап извлечения: текущий файл = обрабатываемый сейчас (тикер в таблице).
// Предыдущий «текущий» демотируем и замеряем его скорость (сек/МБ) для оценок.
if (!procExtractDone) {
let prevIdx = null;
for (const i in procState) {
if (procState[i].st === 'current') { prevIdx = Number(i); procState[i].st = 'pending'; }
}
if (prevIdx != null && sf[prevIdx] && procState[prevIdx].t0) {
const el = (performance.now() - procState[prevIdx].t0) / 1000;
const szMB = sf[prevIdx].size / 1048576;
if (el > 0 && szMB > 0) procExtractRate = el / szMB;
}
if (p) { p.st = 'current'; p.t0 = performance.now(); p.eta = null; }
}
const f = sf[idx];
const sz = f ? fs(f.size) : '';
currentLiveFile = 'Файл ' + (d.idx + 1) + '/' + total + ': ' + d.name + (sz ? ' (' + sz + ')' : '');
@@ -696,6 +720,10 @@ async function uploadFiles() {
activeES.addEventListener('extract_done', function(e) {
const d = JSON.parse(e.data);
procExtractDone = true;
// Этап извлечения завершён — снимаем подсветку «текущего» извлечения
for (const i in procState) {
if (procState[i].st === 'current') procState[i].st = 'pending';
}
// per-file символы -> оценка времени для ожидающих файлов
if (d.per_file) {
for (const nm in d.per_file) {