feat: photo jobs apply/reject flow with applied flag in history
- DB: add photo_jobs.applied column (init + migration + ensure) - Worker: generate preview only (after_path), no longer mutates entry - New POST /api/entries/:id/photo/jobs/:jobId/apply — apply done job result to entry (backs up current photo, marks applied) - New POST /api/entries/:id/photo/jobs/:jobId/reject — discard result, delete temp file, mark rejected - saveEnhance: apply AI result directly when sliders are at defaults - Photo history: '✓ Применить' action for unapplied done AI jobs; 'rejected' status label - sweepOrphanedUploads keeps done-not-applied preview files
This commit is contained in:
@@ -138,18 +138,12 @@ function createPhotoEnhanceWorker({ pool, getSetting, logAudit, invalidateEntrie
|
||||
fs.writeFileSync(path.join(uploadsDir, newName), out);
|
||||
return `/uploads/${newName}`;
|
||||
}
|
||||
async function applyResult(job, photoPath, newPath) {
|
||||
const beforePath = backupOldFile(photoPath);
|
||||
await pool.query('UPDATE entries SET photo_path = $1 WHERE id = $2', [newPath, job.entry_id]);
|
||||
await pool.query('UPDATE entry_photos SET photo_path = $1 WHERE entry_id = $2 AND photo_path = $3', [newPath, job.entry_id, photoPath]);
|
||||
const oldThumb = path.join(uploadsDir, '.thumbs', path.basename(photoPath).replace(/\.[^.]+$/, '') + '.webp');
|
||||
safeUnlinkPath(oldThumb);
|
||||
async function applyResult(job, newPath) {
|
||||
await pool.query(
|
||||
`UPDATE photo_jobs SET status = 'done', before_path = $1, after_path = $2, error = NULL, finished_at = now() WHERE id = $3`,
|
||||
[beforePath, newPath, job.id]
|
||||
`UPDATE photo_jobs SET status = 'done', after_path = $1, error = NULL, finished_at = now() WHERE id = $2`,
|
||||
[newPath, job.id]
|
||||
);
|
||||
if (logAudit) await logAudit(null, 'photo.job.done', { entry_id: job.entry_id, job_id: job.id, action: job.action, before_path: beforePath, after_path: newPath });
|
||||
if (invalidateEntries) invalidateEntries();
|
||||
if (logAudit) await logAudit(null, 'photo.job.preview', { entry_id: job.entry_id, job_id: job.id, action: job.action, after_path: newPath });
|
||||
}
|
||||
async function processOne(job) {
|
||||
stats.jobs++;
|
||||
@@ -168,7 +162,7 @@ function createPhotoEnhanceWorker({ pool, getSetting, logAudit, invalidateEntrie
|
||||
const srcAbs = path.join(uploadsDir, String(photoPath).replace(/^\/+/, '').replace(/^uploads\//, ''));
|
||||
try {
|
||||
const newPath = job.action === 'ai' ? await runAiEnhance(srcAbs) : await enhanceWithSharp(srcAbs, job.params);
|
||||
await applyResult(job, photoPath, newPath);
|
||||
await applyResult(job, newPath);
|
||||
stats.done++;
|
||||
stats.last_at = new Date().toISOString();
|
||||
stats.last_error = null;
|
||||
|
||||
Reference in New Issue
Block a user