refactor: [rd] CM송 → 나레이션 명칭 변경 + 결과 자동 스크롤
- 모든 UI 텍스트 CM송 → 나레이션으로 변경 - 버튼: 나레이션 제작 - 제작 시 결과 패널로 자동 스크롤 - 프롬프트, 다운로드 파일명, 저장 메시지 모두 변경
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'AI CM송 제작')
|
||||
@section('title', 'AI 나레이션 제작')
|
||||
|
||||
@section('content')
|
||||
<!-- 페이지 헤더 -->
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-800 flex items-center gap-2">
|
||||
<i class="ri-music-2-line text-indigo-600"></i>
|
||||
AI CM송 제작
|
||||
AI 나레이션 제작
|
||||
</h1>
|
||||
<a href="{{ route('rd.cm-song.index') }}" class="bg-white hover:bg-gray-100 text-gray-700 px-4 py-2 rounded-lg border transition">
|
||||
<i class="ri-arrow-left-line mr-1"></i> CM송 목록
|
||||
<i class="ri-arrow-left-line mr-1"></i> 나레이션 목록
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
|
||||
<h2 class="text-lg font-semibold text-gray-800 mb-5 flex items-center gap-2">
|
||||
<i class="ri-edit-line text-indigo-500"></i>
|
||||
CM송 정보 입력
|
||||
나레이션 정보 입력
|
||||
</h2>
|
||||
|
||||
<div class="space-y-5">
|
||||
@@ -76,11 +76,11 @@ class="w-full px-4 py-3 rounded-lg border border-gray-200 focus:ring-2 focus:rin
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CM송 길이 슬라이더 -->
|
||||
<!-- 나레이션 길이 슬라이더 -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1.5 flex items-center gap-1.5">
|
||||
<i class="ri-time-line text-gray-400"></i>
|
||||
CM송 길이
|
||||
나레이션 길이
|
||||
</label>
|
||||
<div class="flex items-center gap-4">
|
||||
<input
|
||||
@@ -108,29 +108,29 @@ class="flex-1 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-i
|
||||
class="w-full py-3.5 bg-indigo-600 hover:bg-indigo-700 disabled:bg-gray-300 disabled:cursor-not-allowed text-white rounded-lg font-medium flex items-center justify-center gap-2 transition shadow-sm hover:shadow-md"
|
||||
>
|
||||
<i class="ri-sparkling-line"></i>
|
||||
CM송 만들기
|
||||
나레이션 제작
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 결과 섹션 -->
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex flex-col">
|
||||
<div id="resultPanel" class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex flex-col">
|
||||
<h2 class="text-lg font-semibold text-gray-800 mb-5 flex items-center gap-2">
|
||||
<i class="ri-music-2-line text-indigo-500"></i>
|
||||
생성된 CM송
|
||||
생성된 나레이션
|
||||
</h2>
|
||||
|
||||
<div class="flex-1 flex flex-col justify-center" id="resultArea">
|
||||
<!-- 초기 상태 -->
|
||||
<div id="emptyState" class="text-center text-gray-400 py-12">
|
||||
<i class="ri-music-2-line text-5xl mb-3 block opacity-20"></i>
|
||||
<p class="text-sm">정보를 입력하고 버튼을 누르면<br>이곳에 CM송이 나타납니다.</p>
|
||||
<p class="text-sm">정보를 입력하고 버튼을 누르면<br>이곳에 나레이션이 나타납니다.</p>
|
||||
</div>
|
||||
|
||||
<!-- 로딩 상태 -->
|
||||
<div id="loadingState" class="text-center text-indigo-400 py-12 hidden">
|
||||
<i class="ri-loader-4-line text-5xl mb-3 block animate-spin"></i>
|
||||
<p class="text-sm" id="loadingText">AI가 멋진 가사를 쓰고 있어요...</p>
|
||||
<p class="text-sm" id="loadingText">AI가 나레이션을 작성하고 있어요...</p>
|
||||
</div>
|
||||
|
||||
<!-- 결과 -->
|
||||
@@ -199,6 +199,7 @@ class="flex items-center gap-1.5 px-5 py-2 bg-white hover:bg-gray-50 text-gray-6
|
||||
const moodSelector = document.getElementById('moodSelector');
|
||||
const durationSlider = document.getElementById('durationSlider');
|
||||
const durationDisplay = document.getElementById('durationDisplay');
|
||||
const resultPanel = document.getElementById('resultPanel');
|
||||
const emptyState = document.getElementById('emptyState');
|
||||
const loadingState = document.getElementById('loadingState');
|
||||
const loadingText = document.getElementById('loadingText');
|
||||
@@ -290,7 +291,7 @@ function showState(state) {
|
||||
if (state === 'result') resultState.classList.remove('hidden');
|
||||
}
|
||||
|
||||
// CM송 생성
|
||||
// 나레이션 생성
|
||||
async function generate() {
|
||||
const companyName = companyInput.value.trim();
|
||||
const industry = industryInput.value.trim();
|
||||
@@ -302,14 +303,17 @@ function showState(state) {
|
||||
}
|
||||
|
||||
generateBtn.disabled = true;
|
||||
generateBtn.innerHTML = '<i class="ri-loader-4-line animate-spin"></i> CM송 제작 중...';
|
||||
generateBtn.innerHTML = '<i class="ri-loader-4-line animate-spin"></i> 나레이션 제작 중...';
|
||||
showState('loading');
|
||||
loadingText.textContent = 'AI가 멋진 가사를 쓰고 있어요...';
|
||||
loadingText.textContent = 'AI가 나레이션을 작성하고 있어요...';
|
||||
audioSection.classList.add('hidden');
|
||||
currentAudioData = null;
|
||||
currentAudioMimeType = null;
|
||||
currentAudioBlob = null;
|
||||
|
||||
// 결과 패널로 스크롤
|
||||
resultPanel.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
|
||||
try {
|
||||
// 1. 가사 생성
|
||||
const lyricsRes = await fetch('{{ route("rd.cm-song.generate-lyrics") }}', {
|
||||
@@ -328,7 +332,7 @@ function showState(state) {
|
||||
|
||||
const lyricsData = await lyricsRes.json();
|
||||
if (!lyricsData.success) {
|
||||
throw new Error(lyricsData.error || '가사 생성 실패');
|
||||
throw new Error(lyricsData.error || '나레이션 생성 실패');
|
||||
}
|
||||
|
||||
currentLyrics = lyricsData.lyrics;
|
||||
@@ -371,23 +375,23 @@ function showState(state) {
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('CM송 생성 오류:', error);
|
||||
console.error('나레이션 생성 오류:', error);
|
||||
alert('생성 중 오류가 발생했습니다: ' + error.message);
|
||||
showState('empty');
|
||||
} finally {
|
||||
generateBtn.disabled = false;
|
||||
generateBtn.innerHTML = '<i class="ri-sparkling-line"></i> CM송 만들기';
|
||||
generateBtn.innerHTML = '<i class="ri-sparkling-line"></i> 나레이션 제작';
|
||||
}
|
||||
}
|
||||
|
||||
// 다운로드
|
||||
downloadBtn.addEventListener('click', function () {
|
||||
if (!currentAudioBlob) return;
|
||||
const companyName = companyInput.value.trim() || 'CM송';
|
||||
const companyName = companyInput.value.trim() || '나레이션';
|
||||
const url = URL.createObjectURL(currentAudioBlob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'CM송_' + companyName + '_' + new Date().toISOString().slice(0,10) + '.wav';
|
||||
a.download = '나레이션_' + companyName + '_' + new Date().toISOString().slice(0,10) + '.wav';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
@@ -421,7 +425,7 @@ function showState(state) {
|
||||
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
alert('CM송이 저장되었습니다.');
|
||||
alert('나레이션이 저장되었습니다.');
|
||||
window.location.href = '{{ route("rd.cm-song.index") }}';
|
||||
} else {
|
||||
throw new Error(data.error || '저장 실패');
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'CM송 관리')
|
||||
@section('title', '나레이션 관리')
|
||||
|
||||
@section('content')
|
||||
<!-- 페이지 헤더 -->
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-800 flex items-center gap-2">
|
||||
<i class="ri-music-2-line text-indigo-600"></i>
|
||||
CM송 관리
|
||||
나레이션 관리
|
||||
</h1>
|
||||
<div class="flex gap-2">
|
||||
<a href="{{ route('rd.index') }}" class="bg-white hover:bg-gray-100 text-gray-700 px-4 py-2 rounded-lg border transition">
|
||||
<i class="ri-arrow-left-line mr-1"></i> R&D
|
||||
</a>
|
||||
<a href="{{ route('rd.cm-song.create') }}" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg transition">
|
||||
<i class="ri-add-line mr-1"></i> CM송 제작
|
||||
<i class="ri-add-line mr-1"></i> 나레이션 제작
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,9 +91,9 @@ class="p-1.5 text-gray-400 hover:text-red-600 transition"
|
||||
@else
|
||||
<div class="py-16 text-center text-gray-400">
|
||||
<i class="ri-music-2-line text-5xl mb-3 block opacity-20"></i>
|
||||
<p>아직 생성된 CM송이 없습니다.</p>
|
||||
<p>아직 생성된 나레이션이 없습니다.</p>
|
||||
<a href="{{ route('rd.cm-song.create') }}" class="text-indigo-600 hover:text-indigo-800 text-sm mt-2 inline-block">
|
||||
첫 번째 CM송을 만들어보세요 →
|
||||
첫 번째 나레이션을 만들어보세요 →
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
@@ -103,7 +103,7 @@ class="p-1.5 text-gray-400 hover:text-red-600 transition"
|
||||
@push('scripts')
|
||||
<script>
|
||||
function deleteSong(id) {
|
||||
if (!confirm('이 CM송을 삭제하시겠습니까?')) return;
|
||||
if (!confirm('이 나레이션을 삭제하시겠습니까?')) return;
|
||||
fetch(`/rd/cm-song/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'CM송 상세 - ' . $song->company_name)
|
||||
@section('title', '나레이션 상세 - ' . $song->company_name)
|
||||
|
||||
@section('content')
|
||||
<!-- 페이지 헤더 -->
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-800 flex items-center gap-2">
|
||||
<i class="ri-music-2-line text-indigo-600"></i>
|
||||
CM송 상세
|
||||
나레이션 상세
|
||||
</h1>
|
||||
<div class="flex gap-2">
|
||||
<a href="{{ route('rd.cm-song.index') }}" class="bg-white hover:bg-gray-100 text-gray-700 px-4 py-2 rounded-lg border transition">
|
||||
@@ -24,7 +24,7 @@
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
|
||||
<h2 class="text-lg font-semibold text-gray-800 mb-5 flex items-center gap-2">
|
||||
<i class="ri-information-line text-indigo-500"></i>
|
||||
CM송 정보
|
||||
나레이션 정보
|
||||
</h2>
|
||||
|
||||
<div class="space-y-4">
|
||||
|
||||
@@ -94,15 +94,15 @@
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- AI CM송 제작 -->
|
||||
<!-- AI 나레이션 제작 -->
|
||||
<a href="{{ route('rd.cm-song.index') }}" class="bg-white rounded-lg shadow-sm p-6 hover:shadow-md transition group">
|
||||
<div class="flex items-start gap-4">
|
||||
<div class="w-14 h-14 bg-gradient-to-br from-indigo-500 to-violet-600 rounded-xl flex items-center justify-center text-white shrink-0">
|
||||
<i class="ri-music-2-line text-2xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-800 group-hover:text-indigo-600 transition">AI CM송 제작</h3>
|
||||
<p class="text-sm text-gray-500 mt-1">회사명과 업종을 입력하면 AI가 CM송 가사를 작성하고 목소리를 입혀줍니다.</p>
|
||||
<h3 class="text-lg font-semibold text-gray-800 group-hover:text-indigo-600 transition">AI 나레이션 제작</h3>
|
||||
<p class="text-sm text-gray-500 mt-1">회사명과 업종을 입력하면 AI가 나레이션을 작성하고 목소리를 입혀줍니다.</p>
|
||||
<div class="flex gap-2 mt-3">
|
||||
<span class="px-2 py-0.5 bg-purple-50 text-purple-600 text-xs rounded-full">Gemini TTS</span>
|
||||
<span class="px-2 py-0.5 bg-indigo-50 text-indigo-600 text-xs rounded-full">음성 생성</span>
|
||||
|
||||
Reference in New Issue
Block a user