fix(import): les episodes avec une association changé n'apparait plus sur la page serie

This commit is contained in:
MasutaYunikon committed 2026-05-11 19:03:26 +02:00
1 parent ad829c0a99
commit 8972679e25
2 files changed
+17 -22

No files matched your search

+13
View File
@@ -72,6 +72,19 @@ router.post('/manual-import', requireAuth, async (req, res) => {
const destPath = path.join(destDir, destFilename)
try {
if (!fs.existsSync(file_path)) throw new Error('Fichier source introuvable')
// Nettoyer toute entrée organized qui référence ce même fichier physique
// sous un épisode différent (réassignation → l'ancien enregistrement devient invalide)
for (const [h, eps] of Object.entries(organized)) {
for (const [epId, entry] of Object.entries(eps)) {
if (entry?.dest_path === file_path && Number(epId) !== Number(episode_id)) {
delete (organized[h] as any)[epId]
logger.info('api', `Import manuel : suppression entrée stale ep ${epId} (fichier réassigné)`)
}
}
if (Object.keys(organized[h]).length === 0) delete organized[h]
}
fs.mkdirSync(destDir, { recursive: true })
if (file_path !== destPath) {
const serieRootPath = path.join(mediaPath, serieTitle)
+4 -22
View File
@@ -187,7 +187,7 @@ const serieFolder = computed(() => `${props.initialPath}/${serieTitle.value}`)
interface FileItem {
file : { name: string; path: string; size: number }
episode_id : number | null
previousEpisodeId : number | null // ep_id original si alreadyImported et qu'on le réassigne
originalEpisodeId : number | null // ep_id au moment du scan (immuable) — sert au serveur pour cleanup
hash : string | null
alreadyImported : boolean
willRename : boolean
@@ -268,12 +268,7 @@ function formatSize(bytes: number): string {
function onEpisodeChange(i: number) {
const item = items.value[i]
const newEpId = item.episode_id
// Tracker l'ancien épisode pour pouvoir nettoyer l'entrée organized au moment de l'import
if (item.alreadyImported && item.episode_id !== newEpId) {
item.previousEpisodeId = item.episode_id
}
const newEpId = item.episode_id // v-model a déjà mis à jour la valeur
item.hash = getHashForEpisode(Number(newEpId))
item.alreadyImported = false
@@ -310,11 +305,11 @@ async function scan() {
// Vérifier si déjà importé via dest_path
const existingEpId = organizedByPath.get(f.path) ?? null
if (existingEpId) {
return { file: f, episode_id: existingEpId, previousEpisodeId: null, hash: getHashForEpisode(existingEpId), alreadyImported: true, willRename: false }
return { file: f, episode_id: existingEpId, originalEpisodeId: existingEpId, hash: getHashForEpisode(existingEpId), alreadyImported: true, willRename: false }
}
const match = autoMatch(f.name)
return { file: f, ...match, previousEpisodeId: null, alreadyImported: false, willRename: match.episode_id !== null }
return { file: f, ...match, originalEpisodeId: null, alreadyImported: false, willRename: match.episode_id !== null }
})
} catch {
scanError.value = 'Impossible de contacter le serveur'
@@ -337,19 +332,6 @@ async function doImport() {
return
}
// Nettoyer les anciens épisodes réassignés (fichier était "alreadyImported" ep A,
// l'utilisateur l'a changé en ep B → supprimer l'entrée organized de ep A sans toucher au fichier)
const toUnimport = items.value
.filter(i => i.previousEpisodeId !== null && i.episode_id !== i.previousEpisodeId)
.map(i => i.previousEpisodeId as number)
for (const oldEpId of toUnimport) {
try {
await fetch(`/api/organized/${props.serieId}/${oldEpId}?deleteFile=false`, {
method: 'DELETE', credentials: 'include',
})
} catch {}
}
try {
const res = await fetch('/api/manual-import', {
method : 'POST',