feat: 숏폼 큐에 전체 Output 복사 버튼 — capcut2 오팔 JSON 탭 통짜 붙여넣기용

JobDetail에 rawOutput 노출, 카드 펼침 상단에 전체 복사·영상 URL 복사 툴바 추가.
capcut2가 구분선·타이틀 후보 섞인 통짜 텍스트에서 JSON 5개를 알아서 뽑고
타이틀은 자체 선택 화면에서 고르므로 원문 그대로 복사한다.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
hehihoho3@gmail.com 2026-08-03 12:48:47 +09:00
parent de30174cd1
commit 9a960be663
2 changed files with 14 additions and 5 deletions

View File

@ -36,11 +36,12 @@ public final class ShortformDtos {
public record JobDetail(Long id, String youtubeUrl, String videoId, String title, public record JobDetail(Long id, String youtubeUrl, String videoId, String title,
String status, LocalDateTime createdAt, LocalDateTime completedAt, String status, LocalDateTime createdAt, LocalDateTime completedAt,
List<ClipDto> clips) { String rawOutput, List<ClipDto> clips) {
public static JobDetail from(ShortformJob job) { public static JobDetail from(ShortformJob job) {
return new JobDetail(job.getId(), job.getYoutubeUrl(), job.getVideoId(), return new JobDetail(job.getId(), job.getYoutubeUrl(), job.getVideoId(),
job.getTitle(), job.getStatus().name(), job.getCreatedAt(), job.getTitle(), job.getStatus().name(), job.getCreatedAt(),
job.getCompletedAt(), job.getClips().stream().map(ClipDto::from).toList()); job.getCompletedAt(), job.getRawOutput(),
job.getClips().stream().map(ClipDto::from).toList());
} }
} }
} }

View File

@ -103,16 +103,24 @@
async function toggleJob(id, el) { async function toggleJob(id, el) {
if (el.classList.contains('open')) { el.classList.remove('open'); return; } if (el.classList.contains('open')) { el.classList.remove('open'); return; }
const detail = await api('/api/shortform/jobs/' + id); const detail = await api('/api/shortform/jobs/' + id);
el.querySelector('.sf-clips').innerHTML = detail.clips.length const toolbar = `<div class="sf-clip-head" style="margin-bottom:0.6rem;">
<button class="btn btn-primary" data-copy="${encodeURIComponent(detail.rawOutput || '')}"
data-label="전체 Output 복사 (capcut2 오팔 JSON 탭용)"
${detail.rawOutput ? '' : 'disabled'}>전체 Output 복사 (capcut2 오팔 JSON 탭용)</button>
<button class="btn btn-secondary" data-copy="${encodeURIComponent(detail.youtubeUrl || '')}"
data-label="영상 URL 복사">영상 URL 복사</button>
</div>`;
el.querySelector('.sf-clips').innerHTML = toolbar + (detail.clips.length
? detail.clips.map(clipHtml).join('') ? detail.clips.map(clipHtml).join('')
: '<p style="color:var(--text-3);">저장된 클립이 없습니다. 결과 붙여넣기 또는 "숏폼 큐 돌려줘"로 채우세요.</p>'; : '<p style="color:var(--text-3);">저장된 클립이 없습니다. 결과 붙여넣기 또는 "숏폼 큐 돌려줘"로 채우세요.</p>');
el.classList.add('open'); el.classList.add('open');
el.querySelectorAll('[data-copy]').forEach(btn => { el.querySelectorAll('[data-copy]').forEach(btn => {
const label = btn.dataset.label || 'capcut2 JSON 복사';
btn.onclick = (e) => { btn.onclick = (e) => {
e.stopPropagation(); e.stopPropagation();
navigator.clipboard.writeText(decodeURIComponent(btn.dataset.copy)); navigator.clipboard.writeText(decodeURIComponent(btn.dataset.copy));
btn.textContent = '복사됨!'; btn.textContent = '복사됨!';
setTimeout(() => btn.textContent = 'capcut2 JSON 복사', 1200); setTimeout(() => btn.textContent = label, 1200);
}; };
}); });
} }