edit views
This commit is contained in:
parent
9d1d11108f
commit
1d06854f94
@ -16,12 +16,12 @@
|
||||
:items="stepperItems"
|
||||
alt-labels
|
||||
>
|
||||
<!-- Stepper Window로 각 단계 구현 -->
|
||||
<v-stepper-window>
|
||||
|
||||
<!-- Step 1: 콘텐츠 타입 선택 -->
|
||||
<template v-slot:item.1>
|
||||
<v-card
|
||||
class="pa-4"
|
||||
flat
|
||||
>
|
||||
<v-stepper-window-item value="1">
|
||||
<v-card class="pa-4" flat>
|
||||
<h3 class="text-h6 mb-4">어떤 콘텐츠를 만들까요?</h3>
|
||||
|
||||
<v-row>
|
||||
@ -54,26 +54,17 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card>
|
||||
</template>
|
||||
</v-stepper-window-item>
|
||||
|
||||
<!-- Step 2: 홍보 대상 선택 -->
|
||||
<template v-slot:item.2>
|
||||
<v-stepper-window-item value="2">
|
||||
<v-card class="pa-4" flat>
|
||||
<h3 class="text-h6 mb-4">무엇을 홍보할까요?</h3>
|
||||
|
||||
<v-radio-group v-model="contentData.target">
|
||||
<v-radio
|
||||
label="🍜 메뉴 홍보"
|
||||
value="menu"
|
||||
/>
|
||||
<v-radio
|
||||
label="🏪 매장 소개"
|
||||
value="store"
|
||||
/>
|
||||
<v-radio
|
||||
label="🎉 이벤트 홍보"
|
||||
value="event"
|
||||
/>
|
||||
<v-radio label="🍜 메뉴 홍보" value="menu" />
|
||||
<v-radio label="🏪 매장 소개" value="store" />
|
||||
<v-radio label="🎉 이벤트 홍보" value="event" />
|
||||
</v-radio-group>
|
||||
|
||||
<!-- 메뉴 선택 -->
|
||||
@ -98,10 +89,10 @@
|
||||
class="mt-4"
|
||||
/>
|
||||
</v-card>
|
||||
</template>
|
||||
</v-stepper-window-item>
|
||||
|
||||
<!-- Step 3: 이미지 업로드 -->
|
||||
<template v-slot:item.3>
|
||||
<v-stepper-window-item value="3">
|
||||
<v-card class="pa-4" flat>
|
||||
<h3 class="text-h6 mb-4">이미지를 업로드하세요</h3>
|
||||
|
||||
@ -126,19 +117,15 @@
|
||||
md="3"
|
||||
>
|
||||
<v-card class="pa-2">
|
||||
<v-img
|
||||
:src="url"
|
||||
height="100"
|
||||
cover
|
||||
/>
|
||||
<v-img :src="url" height="100" cover />
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card>
|
||||
</template>
|
||||
</v-stepper-window-item>
|
||||
|
||||
<!-- Step 4: 세부 옵션 -->
|
||||
<template v-slot:item.4>
|
||||
<v-stepper-window-item value="4">
|
||||
<v-card class="pa-4" flat>
|
||||
<h3 class="text-h6 mb-4">세부 옵션을 설정하세요</h3>
|
||||
|
||||
@ -212,10 +199,10 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card>
|
||||
</template>
|
||||
</v-stepper-window-item>
|
||||
|
||||
<!-- Step 5: 생성 결과 -->
|
||||
<template v-slot:item.5>
|
||||
<v-stepper-window-item value="5">
|
||||
<v-card class="pa-4" flat>
|
||||
<h3 class="text-h6 mb-4">생성된 콘텐츠</h3>
|
||||
|
||||
@ -274,7 +261,9 @@
|
||||
<p class="text-body-2">{{ generationError }}</p>
|
||||
</v-card>
|
||||
</v-card>
|
||||
</template>
|
||||
</v-stepper-window-item>
|
||||
|
||||
</v-stepper-window>
|
||||
</v-stepper>
|
||||
</v-card-text>
|
||||
|
||||
@ -347,244 +336,3 @@
|
||||
</v-snackbar>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useContentStore } from '@/store/content'
|
||||
import { useStoreStore } from '@/store/store'
|
||||
import { TONE_OPTIONS, EMOTION_INTENSITY, PROMOTION_OPTIONS, PLATFORMS } from '@/utils/constants'
|
||||
|
||||
const router = useRouter()
|
||||
const contentStore = useContentStore()
|
||||
const storeStore = useStoreStore()
|
||||
|
||||
// 스테퍼 설정
|
||||
const currentStep = ref(1)
|
||||
const stepperItems = [
|
||||
{ title: '타입 선택', value: 1 },
|
||||
{ title: '홍보 대상', value: 2 },
|
||||
{ title: '이미지 업로드', value: 3 },
|
||||
{ title: '세부 옵션', value: 4 },
|
||||
{ title: '생성 완료', value: 5 }
|
||||
]
|
||||
|
||||
// 콘텐츠 데이터
|
||||
const contentData = ref({
|
||||
type: '',
|
||||
target: '',
|
||||
selectedMenu: null,
|
||||
eventName: '',
|
||||
images: [],
|
||||
toneAndManner: '친근함',
|
||||
emotionIntensity: '보통',
|
||||
promotion: '없음',
|
||||
platform: 'INSTAGRAM',
|
||||
startDate: '',
|
||||
endDate: ''
|
||||
})
|
||||
|
||||
// 상태 관리
|
||||
const generating = ref(false)
|
||||
const saving = ref(false)
|
||||
const generatedContent = ref(null)
|
||||
const generationError = ref('')
|
||||
const showSuccess = ref(false)
|
||||
const showError = ref(false)
|
||||
const errorMessage = ref('')
|
||||
|
||||
// 이미지 미리보기
|
||||
const imagePreviewUrls = ref([])
|
||||
|
||||
// 계산된 속성
|
||||
const canProceed = computed(() => {
|
||||
switch (currentStep.value) {
|
||||
case 1:
|
||||
return !!contentData.value.type
|
||||
case 2:
|
||||
if (contentData.value.target === 'menu') {
|
||||
return !!contentData.value.selectedMenu
|
||||
} else if (contentData.value.target === 'event') {
|
||||
return !!contentData.value.eventName
|
||||
}
|
||||
return !!contentData.value.target
|
||||
case 3:
|
||||
return contentData.value.images.length > 0
|
||||
case 4:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
const menuOptions = computed(() => {
|
||||
return storeStore.menus.map(menu => ({
|
||||
text: menu.menuName,
|
||||
value: menu.id
|
||||
}))
|
||||
})
|
||||
|
||||
const platformOptions = [
|
||||
{ text: '인스타그램', value: 'INSTAGRAM' },
|
||||
{ text: '네이버 블로그', value: 'NAVER_BLOG' }
|
||||
]
|
||||
|
||||
/**
|
||||
* 다음 단계로 이동
|
||||
*/
|
||||
const nextStep = async () => {
|
||||
if (currentStep.value === 4) {
|
||||
await generateContent()
|
||||
} else {
|
||||
currentStep.value++
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 콘텐츠 생성
|
||||
*/
|
||||
const generateContent = async () => {
|
||||
generating.value = true
|
||||
generationError.value = ''
|
||||
currentStep.value = 5
|
||||
|
||||
try {
|
||||
let response
|
||||
|
||||
if (contentData.value.type === 'SNS_POST') {
|
||||
response = await contentStore.generateSNSContent({
|
||||
target: contentData.value.target,
|
||||
selectedMenu: contentData.value.selectedMenu,
|
||||
eventName: contentData.value.eventName,
|
||||
images: contentData.value.images,
|
||||
toneAndManner: contentData.value.toneAndManner,
|
||||
emotionIntensity: contentData.value.emotionIntensity,
|
||||
promotion: contentData.value.promotion,
|
||||
platform: contentData.value.platform,
|
||||
startDate: contentData.value.startDate,
|
||||
endDate: contentData.value.endDate
|
||||
})
|
||||
} else {
|
||||
response = await contentStore.generatePosterContent({
|
||||
target: contentData.value.target,
|
||||
selectedMenu: contentData.value.selectedMenu,
|
||||
eventName: contentData.value.eventName,
|
||||
images: contentData.value.images,
|
||||
toneAndManner: contentData.value.toneAndManner,
|
||||
promotion: contentData.value.promotion,
|
||||
startDate: contentData.value.startDate,
|
||||
endDate: contentData.value.endDate
|
||||
})
|
||||
}
|
||||
|
||||
generatedContent.value = response
|
||||
} catch (error) {
|
||||
console.error('콘텐츠 생성 실패:', error)
|
||||
generationError.value = '콘텐츠 생성 중 오류가 발생했습니다.'
|
||||
|
||||
// 샘플 데이터로 대체
|
||||
generatedContent.value = {
|
||||
title: '신메뉴 떡볶이 출시!',
|
||||
content: `🔥 새로운 맛의 떡볶이가 출시되었어요! 🔥
|
||||
|
||||
매콤달콤한 특제 소스로 만든 우리 매장만의 시그니처 떡볶이를 맛보세요!
|
||||
|
||||
신선한 떡과 정성스럽게 끓인 국물의 조화가 일품입니다.
|
||||
|
||||
지금 방문하시면 특별 할인가로 만나보실 수 있어요! ✨`,
|
||||
hashtags: ['#떡볶이', '#신메뉴', '#분식맛집', '#김사장님분식점', '#매운맛', '#달콤한맛']
|
||||
}
|
||||
} finally {
|
||||
generating.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 콘텐츠 재생성
|
||||
*/
|
||||
const regenerateContent = async () => {
|
||||
generatedContent.value = null
|
||||
await generateContent()
|
||||
}
|
||||
|
||||
/**
|
||||
* 콘텐츠 저장
|
||||
*/
|
||||
const saveContent = async () => {
|
||||
saving.value = true
|
||||
try {
|
||||
const saveData = {
|
||||
...contentData.value,
|
||||
...generatedContent.value
|
||||
}
|
||||
|
||||
if (contentData.value.type === 'SNS_POST') {
|
||||
await contentStore.saveSNSContent(saveData)
|
||||
} else {
|
||||
await contentStore.savePosterContent(saveData)
|
||||
}
|
||||
|
||||
showSuccess.value = true
|
||||
|
||||
// 잠시 후 콘텐츠 관리 페이지로 이동
|
||||
setTimeout(() => {
|
||||
router.push({ name: 'ContentManagement' })
|
||||
}, 2000)
|
||||
} catch (error) {
|
||||
console.error('콘텐츠 저장 실패:', error)
|
||||
errorMessage.value = '콘텐츠 저장 중 오류가 발생했습니다.'
|
||||
showError.value = true
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 이미지 파일 변경 감지
|
||||
watch(() => contentData.value.images, (newImages) => {
|
||||
imagePreviewUrls.value = []
|
||||
|
||||
if (newImages && newImages.length > 0) {
|
||||
newImages.forEach(file => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = (e) => {
|
||||
imagePreviewUrls.value.push(e.target.result)
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 컴포넌트 마운트시 데이터 로드
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await storeStore.fetchMenus()
|
||||
} catch (error) {
|
||||
console.error('메뉴 데이터 로드 실패:', error)
|
||||
}
|
||||
|
||||
// 기본 날짜 설정
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
const nextWeek = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]
|
||||
|
||||
contentData.value.startDate = today
|
||||
contentData.value.endDate = nextWeek
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.content-type-card {
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.content-type-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.content-type-card.selected {
|
||||
border-color: #1976D2;
|
||||
background-color: #E3F2FD;
|
||||
}
|
||||
</style>
|
||||
@ -979,7 +979,8 @@ onMounted(async () => {
|
||||
|
||||
.content-preview {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
line-clamp: 3; /* 표준 속성 추가 */
|
||||
-webkit-line-clamp: 3; /* 웹킷 fallback */
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
line-height: 1.4;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user