fix: repair photo worker broken code; add pending queue view
- Fix runAiEnhance missing return/closing brace from previous commit - Remove duplicate code fragments in worker.js - Add renderPhotoPending() to show pending/processing jobs in worker dashboard - New pending queue table in worker.html photo section
This commit is contained in:
@@ -232,6 +232,7 @@ function renderPhoto() {
|
|||||||
['error', 'Ошибка', c.error || 0],
|
['error', 'Ошибка', c.error || 0],
|
||||||
].map(([cls, label, n]) => `<span class="chip ${cls}">${label}: <b>${n}</b></span>`).join('');
|
].map(([cls, label, n]) => `<span class="chip ${cls}">${label}: <b>${n}</b></span>`).join('');
|
||||||
const rows = photoState.recent || [];
|
const rows = photoState.recent || [];
|
||||||
|
renderPhotoPending();
|
||||||
const tbody = document.querySelector('#photoTable tbody');
|
const tbody = document.querySelector('#photoTable tbody');
|
||||||
const empty = document.getElementById('photoEmpty');
|
const empty = document.getElementById('photoEmpty');
|
||||||
if (!rows.length) { tbody.innerHTML = ''; empty.style.display = 'block'; return; }
|
if (!rows.length) { tbody.innerHTML = ''; empty.style.display = 'block'; return; }
|
||||||
@@ -258,6 +259,26 @@ function renderPhoto() {
|
|||||||
renderIcons();
|
renderIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderPhotoPending() {
|
||||||
|
const rows = photoState.pending || [];
|
||||||
|
document.getElementById('photoPendingCount').textContent = rows.length;
|
||||||
|
const tbody = document.querySelector('#photoPendingTable tbody');
|
||||||
|
const empty = document.getElementById('photoPendingEmpty');
|
||||||
|
if (!rows.length) { tbody.innerHTML = ''; empty.style.display = 'block'; return; }
|
||||||
|
empty.style.display = 'none';
|
||||||
|
tbody.innerHTML = rows.map(r => {
|
||||||
|
const processing = r.status === 'processing';
|
||||||
|
const action = esc(PHOTO_ACTION_LABELS[r.action] || r.action);
|
||||||
|
const badge = `<span class="ai-badge ${processing ? 'ai-badge-skipped' : ''}">${processing ? '⏳ Обрабатывается' : 'В очереди'}</span>`;
|
||||||
|
return `<tr${processing ? ' style="background:rgba(59,130,246,.08)"' : ''}>
|
||||||
|
<td>#${r.id}</td>
|
||||||
|
<td>#${r.entry_id} ${esc(r.student_name || '')} <span style="color:var(--muted)">(${esc(r.group_name || '')})</span></td>
|
||||||
|
<td>${action} ${badge}</td>
|
||||||
|
<td style="color:var(--muted);white-space:nowrap">${fmtTime(r.created_at)}</td>
|
||||||
|
</tr>`;
|
||||||
|
}).join('');
|
||||||
|
}
|
||||||
|
|
||||||
function findPhotoJob(id) {
|
function findPhotoJob(id) {
|
||||||
return (photoState && photoState.recent || []).find(r => r.id === id) || null;
|
return (photoState && photoState.recent || []).find(r => r.id === id) || null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,6 +106,16 @@
|
|||||||
<button class="btn-link" id="photoRequeueBtn" type="button" title="Вернуть задания с ошибкой в очередь">Повторить ошибки фото</button>
|
<button class="btn-link" id="photoRequeueBtn" type="button" title="Вернуть задания с ошибкой в очередь">Повторить ошибки фото</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="worker-counts" id="photoCounts" style="margin-bottom:10px"></div>
|
<div class="worker-counts" id="photoCounts" style="margin-bottom:10px"></div>
|
||||||
|
<p class="hint">В очереди (<span id="photoPendingCount">0</span>)</p>
|
||||||
|
<div class="audit-wrap" style="margin-bottom:14px">
|
||||||
|
<table class="audit-table" id="photoPendingTable">
|
||||||
|
<thead>
|
||||||
|
<tr><th>Задание</th><th>Запись</th><th>Действие</th><th>Поставлено</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
<div class="empty" id="photoPendingEmpty" style="display:none">Очередь пуста.</div>
|
||||||
|
</div>
|
||||||
<div class="audit-wrap">
|
<div class="audit-wrap">
|
||||||
<table class="audit-table" id="photoTable">
|
<table class="audit-table" id="photoTable">
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ function createPhotoEnhanceWorker({ pool, getSetting, logAudit, invalidateEntrie
|
|||||||
const out = Buffer.from(await resp.arrayBuffer());
|
const out = Buffer.from(await resp.arrayBuffer());
|
||||||
const newName = crypto.randomBytes(12).toString('hex') + '.jpg';
|
const newName = crypto.randomBytes(12).toString('hex') + '.jpg';
|
||||||
fs.writeFileSync(path.join(uploadsDir, newName), out);
|
fs.writeFileSync(path.join(uploadsDir, newName), out);
|
||||||
|
return `/uploads/${newName}`;
|
||||||
|
}
|
||||||
async function applyResult(job, photoPath, newPath) {
|
async function applyResult(job, photoPath, newPath) {
|
||||||
const beforePath = backupOldFile(photoPath);
|
const beforePath = backupOldFile(photoPath);
|
||||||
await pool.query('UPDATE entries SET photo_path = $1 WHERE id = $2', [newPath, job.entry_id]);
|
await pool.query('UPDATE entries SET photo_path = $1 WHERE id = $2', [newPath, job.entry_id]);
|
||||||
@@ -186,6 +188,12 @@ function createPhotoEnhanceWorker({ pool, getSetting, logAudit, invalidateEntrie
|
|||||||
`UPDATE photo_jobs SET status = 'error', attempts = $1, error = $2, finished_at = now() WHERE id = $3`,
|
`UPDATE photo_jobs SET status = 'error', attempts = $1, error = $2, finished_at = now() WHERE id = $3`,
|
||||||
[tries, message, job.id]
|
[tries, message, job.id]
|
||||||
);
|
);
|
||||||
|
stats.errors++;
|
||||||
|
if (logAudit) await logAudit(null, 'photo.job.error', { entry_id: job.entry_id, job_id: job.id, error: message });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function loop() {
|
async function loop() {
|
||||||
while (!stopped) {
|
while (!stopped) {
|
||||||
let job = null;
|
let job = null;
|
||||||
@@ -248,17 +256,6 @@ function createPhotoEnhanceWorker({ pool, getSetting, logAudit, invalidateEntrie
|
|||||||
return { start, notify, getInfo };
|
return { start, notify, getInfo };
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.errors++;
|
|
||||||
if (logAudit) await logAudit(null, 'photo.job.error', { entry_id: job.entry_id, job_id: job.id, error: message });
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return `/uploads/${newName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function createEntryAutoChecker({ pool, getSetting, logAudit, aiUrl, defaultPrompt, model }) {
|
function createEntryAutoChecker({ pool, getSetting, logAudit, aiUrl, defaultPrompt, model }) {
|
||||||
const AI_URL = aiUrl || process.env.AI_URL || 'http://text-corrector:8080';
|
const AI_URL = aiUrl || process.env.AI_URL || 'http://text-corrector:8080';
|
||||||
const MODEL = model || process.env.AI_MODEL || 'qwen2.5-1.5b-instruct-q4_k_m.gguf';
|
const MODEL = model || process.env.AI_MODEL || 'qwen2.5-1.5b-instruct-q4_k_m.gguf';
|
||||||
@@ -514,5 +511,3 @@ function createEntryAutoChecker({ pool, getSetting, logAudit, aiUrl, defaultProm
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { createEntryAutoChecker, createPhotoEnhanceWorker };
|
module.exports = { createEntryAutoChecker, createPhotoEnhanceWorker };
|
||||||
|
|
||||||
(function photoEnhanceWorkerImpl() {})();
|
|
||||||
|
|||||||
Reference in New Issue
Block a user