게시물 Export 일괄 다운로드와 재시도 추가 v1.5.24
This commit is contained in:
@@ -22,6 +22,8 @@ const uploadingHomeCover = ref(false)
|
||||
const uploadingHomeCoverDark = ref(false)
|
||||
const requestingPostExport = ref(false)
|
||||
const deletingPostExportJobIds = ref([])
|
||||
const downloadingPostExportJobIds = ref([])
|
||||
const retryingPostExportJobIds = ref([])
|
||||
const postExportDateRangeMode = ref('all')
|
||||
const postExportYear = ref(new Date().getFullYear())
|
||||
const postExportMonth = ref(new Date().getMonth() + 1)
|
||||
@@ -585,6 +587,88 @@ const requestPostExport = async () => {
|
||||
*/
|
||||
const getPostExportDownloadUrl = (file) => `/admin/api/posts/export-jobs/${file.id}/download`
|
||||
|
||||
/**
|
||||
* Export 작업의 다운로드 가능한 파일만 추린다.
|
||||
* @param {Object} job - Export 작업
|
||||
* @returns {Array} 다운로드 가능한 파일 목록
|
||||
*/
|
||||
const getReadyPostExportFiles = (job) => Array.isArray(job?.files)
|
||||
? job.files.filter((file) => file.status === 'ready' && file.filePath)
|
||||
: []
|
||||
|
||||
/**
|
||||
* Export 일괄 다운로드 중 여부
|
||||
* @param {string} jobId - 작업 ID
|
||||
* @returns {boolean} 다운로드 중 여부
|
||||
*/
|
||||
const isDownloadingPostExportJob = (jobId) => downloadingPostExportJobIds.value.includes(jobId)
|
||||
|
||||
/**
|
||||
* Export 작업 재시도 중 여부
|
||||
* @param {string} jobId - 작업 ID
|
||||
* @returns {boolean} 재시도 중 여부
|
||||
*/
|
||||
const isRetryingPostExportJob = (jobId) => retryingPostExportJobIds.value.includes(jobId)
|
||||
|
||||
/**
|
||||
* Export 분할 파일을 브라우저에서 순차 다운로드한다.
|
||||
* @param {Object} job - Export 작업
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const downloadPostExportJobFiles = async (job) => {
|
||||
const readyFiles = getReadyPostExportFiles(job)
|
||||
|
||||
if (!job?.id || readyFiles.length === 0 || isDownloadingPostExportJob(job.id)) {
|
||||
return
|
||||
}
|
||||
|
||||
downloadingPostExportJobIds.value = [...downloadingPostExportJobIds.value, job.id]
|
||||
showToast('info', `${readyFiles.length}개 파일을 순차 다운로드합니다.`)
|
||||
|
||||
try {
|
||||
for (const file of readyFiles) {
|
||||
const link = document.createElement('a')
|
||||
link.href = getPostExportDownloadUrl(file)
|
||||
link.download = file.fileName || ''
|
||||
link.rel = 'noopener'
|
||||
document.body.append(link)
|
||||
link.click()
|
||||
link.remove()
|
||||
await new Promise((resolve) => window.setTimeout(resolve, 700))
|
||||
}
|
||||
showToast('success', '일괄 다운로드 요청을 보냈습니다.')
|
||||
} finally {
|
||||
downloadingPostExportJobIds.value = downloadingPostExportJobIds.value.filter((id) => id !== job.id)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 실패한 Export 작업을 재시도한다.
|
||||
* @param {Object} job - Export 작업
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const retryPostExportJob = async (job) => {
|
||||
if (!job?.id || job.status !== 'failed' || isRetryingPostExportJob(job.id)) {
|
||||
return
|
||||
}
|
||||
|
||||
retryingPostExportJobIds.value = [...retryingPostExportJobIds.value, job.id]
|
||||
showToast('info', '실패한 Export 작업을 다시 대기열에 등록하는 중입니다.')
|
||||
|
||||
try {
|
||||
await $fetch(`/admin/api/posts/export-jobs/${job.id}/retry`, {
|
||||
method: 'POST'
|
||||
})
|
||||
await refreshPostExportJobs()
|
||||
showToast('success', 'Export 작업을 다시 시작했습니다.')
|
||||
} catch (error) {
|
||||
errorMessage.value = error?.data?.message || 'Export 작업을 다시 시작하지 못했습니다.'
|
||||
showToast('error', errorMessage.value)
|
||||
} finally {
|
||||
retryingPostExportJobIds.value = retryingPostExportJobIds.value.filter((id) => id !== job.id)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export 작업 삭제 중 여부
|
||||
* @param {string} jobId - 작업 ID
|
||||
@@ -2079,11 +2163,21 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-2">
|
||||
<button
|
||||
class="inline-flex h-9 shrink-0 cursor-not-allowed items-center justify-center rounded-md border border-[#dce0e5] px-3 text-xs font-semibold text-[#9aa3ad]"
|
||||
class="inline-flex h-9 shrink-0 cursor-pointer items-center justify-center rounded-md border border-[#15171a] bg-[#15171a] px-3 text-xs font-semibold text-white transition hover:bg-black disabled:cursor-not-allowed disabled:border-[#dce0e5] disabled:bg-white disabled:text-[#9aa3ad]"
|
||||
type="button"
|
||||
disabled
|
||||
:disabled="getReadyPostExportFiles(job).length === 0 || isDownloadingPostExportJob(job.id)"
|
||||
@click="downloadPostExportJobFiles(job)"
|
||||
>
|
||||
일괄 다운로드 준비 중
|
||||
{{ isDownloadingPostExportJob(job.id) ? '다운로드 중' : `일괄 다운로드 ${getReadyPostExportFiles(job).length || ''}` }}
|
||||
</button>
|
||||
<button
|
||||
v-if="job.status === 'failed'"
|
||||
class="inline-flex h-9 shrink-0 cursor-pointer items-center justify-center rounded-md border border-[#dce0e5] px-3 text-xs font-semibold text-[#15171a] transition hover:bg-[#f4f6f8] disabled:cursor-not-allowed disabled:text-[#a6b0bb]"
|
||||
type="button"
|
||||
:disabled="isRetryingPostExportJob(job.id)"
|
||||
@click="retryPostExportJob(job)"
|
||||
>
|
||||
{{ isRetryingPostExportJob(job.id) ? '재시도 중' : '재시도' }}
|
||||
</button>
|
||||
<button
|
||||
class="inline-flex h-9 shrink-0 cursor-pointer items-center justify-center rounded-md border border-[#ffd5d5] px-3 text-xs font-semibold text-[#d64545] transition hover:bg-[#fff3f3] disabled:cursor-not-allowed disabled:border-[#e1e5ea] disabled:text-[#a6b0bb]"
|
||||
|
||||
Reference in New Issue
Block a user