store source release

This commit is contained in:
unknown 2025-06-18 10:52:01 +09:00
parent ccdc2c91bb
commit 4be4ba790f
2 changed files with 136 additions and 35 deletions

View File

@ -140,8 +140,10 @@ class StoreService {
businessType: storeData.businessType, businessType: storeData.businessType,
address: storeData.address, address: storeData.address,
phoneNumber: storeData.phoneNumber, phoneNumber: storeData.phoneNumber,
businessHours: storeData.businessHours, // ✅ 수정: businessHours 필드 처리
closedDays: storeData.closedDays, businessHours: storeData.businessHours || `${storeData.openTime || '09:00'}-${storeData.closeTime || '21:00'}`,
// ✅ 수정: closedDays 필드 처리
closedDays: storeData.closedDays || storeData.holidays || '',
seatCount: parseInt(storeData.seatCount) || 0, seatCount: parseInt(storeData.seatCount) || 0,
instaAccounts: storeData.instaAccounts || '', instaAccounts: storeData.instaAccounts || '',
blogAccounts: storeData.blogAccounts || '', blogAccounts: storeData.blogAccounts || '',
@ -150,9 +152,9 @@ class StoreService {
console.log('백엔드 전송 데이터:', requestData) console.log('백엔드 전송 데이터:', requestData)
// PUT 요청 (storeId는 JWT에서 추출하므로 URL에 포함하지 않음) // ✅ 핵심 수정: 슬래시 제거하고 빈 문자열 사용
const response = await storeApi.put('/', requestData) console.log('API 호출 경로: PUT /api/store (baseURL + 빈 문자열)')
const response = await storeApi.put('', requestData)
console.log('매장 정보 수정 API 응답:', response.data) console.log('매장 정보 수정 API 응답:', response.data)
if (response.data && (response.data.status === 200 || response.data.success !== false)) { if (response.data && (response.data.status === 200 || response.data.success !== false)) {

View File

@ -356,8 +356,14 @@
</div> </div>
<!-- 매장 등록/수정 다이얼로그 --> <!-- 매장 등록/수정 다이얼로그 -->
<v-dialog v-model="showCreateDialog" max-width="600" persistent> <v-dialog
<v-card> v-model="showCreateDialog"
max-width="600"
persistent
:style="{ zIndex: 2000 }"
class="store-dialog"
>
<v-card class="store-dialog-card">
<v-card-title class="pa-4"> <v-card-title class="pa-4">
<div class="d-flex align-center"> <div class="d-flex align-center">
<v-icon class="mr-2" color="primary">mdi-store</v-icon> <v-icon class="mr-2" color="primary">mdi-store</v-icon>
@ -367,7 +373,8 @@
<v-divider /> <v-divider />
<v-card-text class="pa-4"> <!-- 스크롤 가능한 컨텐츠 영역 -->
<v-card-text class="pa-4 store-dialog-content">
<v-form ref="storeFormRef" v-model="formValid"> <v-form ref="storeFormRef" v-model="formValid">
<v-row> <v-row>
<v-col cols="12"> <v-col cols="12">
@ -481,7 +488,7 @@
label="매장 소개" label="매장 소개"
variant="outlined" variant="outlined"
density="compact" density="compact"
rows="3" rows="2"
/> />
</v-col> </v-col>
</v-row> </v-row>
@ -778,7 +785,7 @@
</template> </template>
<script setup> <script setup>
import { ref, computed, onMounted, watch } from 'vue' import { ref, computed, onMounted, watch, nextTick } from 'vue'
import { useStoreStore } from '@/store/index' import { useStoreStore } from '@/store/index'
const storeStore = useStoreStore() const storeStore = useStoreStore()
@ -804,6 +811,7 @@ const menuFormValid = ref(false)
// //
const selectedImageFile = ref(null) const selectedImageFile = ref(null)
const previewImageUrl = ref('') const previewImageUrl = ref('')
const forceShowFileInput = ref(false) // :
// //
const menuFormData = ref({ const menuFormData = ref({
@ -881,8 +889,13 @@ const filteredMenus = computed(() => {
return filtered return filtered
}) })
// (computed) //
const shouldShowImagePreview = computed(() => { const shouldShowImagePreview = computed(() => {
//
if (forceShowFileInput.value) {
return null
}
// 1: // 1:
if (previewImageUrl.value) { if (previewImageUrl.value) {
return previewImageUrl.value return previewImageUrl.value
@ -895,7 +908,6 @@ const shouldShowImagePreview = computed(() => {
return null return null
}) })
// ===== ===== // ===== =====
/** /**
@ -1016,13 +1028,14 @@ watch(selectedImageFile, (newFile, oldFile) => {
} }
}, { immediate: false }) }, { immediate: false })
// v-file-input modelValue //
const onFileInputChange = (file) => { const onFileInputChange = (file) => {
console.log('=== v-file-input v-model 변경 감지 ===') console.log('=== v-file-input v-model 변경 감지 ===')
console.log('전달받은 file:', file) console.log('전달받은 file:', file)
if (file) { if (file) {
// selectedImageFile //
forceShowFileInput.value = false
selectedImageFile.value = file selectedImageFile.value = file
onImageFileSelected(file) onImageFileSelected(file)
} else { } else {
@ -1158,17 +1171,21 @@ const uploadMenuImage = async (menuId) => {
} }
} }
// //
const resetImageSelection = () => { const resetImageSelection = () => {
console.log('이미지 선택 초기화') console.log('=== 이미지 선택 초기화 시작 ===')
// 1.
selectedImageFile.value = null selectedImageFile.value = null
previewImageUrl.value = '' previewImageUrl.value = ''
// v-file-input DOM // 2.
const fileInput = document.querySelector('input[type="file"]') forceShowFileInput.value = true
if (fileInput) {
fileInput.value = '' // 3. Vue nextTick
} nextTick(() => {
console.log('✅ 이미지 선택 초기화 완료 - 파일 입력 표시됨')
})
} }
// //
@ -1206,7 +1223,7 @@ const resetForm = () => {
} }
} }
// //
const resetMenuForm = () => { const resetMenuForm = () => {
console.log('=== 메뉴 폼 리셋 ===') console.log('=== 메뉴 폼 리셋 ===')
@ -1225,6 +1242,7 @@ const resetMenuForm = () => {
// //
selectedImageFile.value = null selectedImageFile.value = null
previewImageUrl.value = '' previewImageUrl.value = ''
forceShowFileInput.value = false //
if (menuFormRef.value) { if (menuFormRef.value) {
menuFormRef.value.resetValidation() menuFormRef.value.resetValidation()
@ -1273,7 +1291,7 @@ const openCreateMenuDialog = () => {
showMenuDialog.value = true showMenuDialog.value = true
} }
// //
const editMenu = (menu) => { const editMenu = (menu) => {
console.log('=== 메뉴 수정 호출 ===') console.log('=== 메뉴 수정 호출 ===')
console.log('전달받은 메뉴 객체:', menu) console.log('전달받은 메뉴 객체:', menu)
@ -1309,11 +1327,13 @@ const editMenu = (menu) => {
imageUrl: menu.image || menu.imageUrl || '' imageUrl: menu.image || menu.imageUrl || ''
} }
// //
selectedImageFile.value = null selectedImageFile.value = null
previewImageUrl.value = '' previewImageUrl.value = ''
forceShowFileInput.value = false //
console.log('✅ 메뉴 수정 폼 데이터 설정 완료:', menuFormData.value) console.log('✅ 메뉴 수정 폼 데이터 설정 완료:', menuFormData.value)
console.log('✅ 기존 이미지 URL:', menuFormData.value.imageUrl)
showMenuDialog.value = true showMenuDialog.value = true
} }
@ -1372,6 +1392,8 @@ const cancelMenuForm = () => {
// ===== ===== // ===== =====
// StoreManagementView.vue saveStore
// //
const saveStore = async () => { const saveStore = async () => {
if (!storeFormRef.value) { if (!storeFormRef.value) {
@ -1389,17 +1411,19 @@ const saveStore = async () => {
try { try {
console.log('매장 정보 저장 시작') console.log('매장 정보 저장 시작')
console.log('폼 데이터:', formData.value)
// //
const storeData = { const storeData = {
storeName: formData.value.storeName, storeName: formData.value.storeName,
businessType: formData.value.businessType, businessType: formData.value.businessType,
address: formData.value.address, address: formData.value.address,
phoneNumber: formData.value.phoneNumber || '', phoneNumber: formData.value.phoneNumber || '',
openTime: formData.value.openTime || '09:00', // :
closeTime: formData.value.closeTime || '21:00', businessHours: `${formData.value.openTime || '09:00'}-${formData.value.closeTime || '21:00'}`,
holidays: Array.isArray(formData.value.holidays) ? // :
formData.value.holidays.join(',') : '', closedDays: Array.isArray(formData.value.holidays) ?
formData.value.holidays.join(',') : (formData.value.holidays || ''),
seatCount: parseInt(formData.value.seatCount) || 0, seatCount: parseInt(formData.value.seatCount) || 0,
instaAccounts: formData.value.instagramUrl || '', instaAccounts: formData.value.instagramUrl || '',
blogAccounts: formData.value.blogUrl || '', blogAccounts: formData.value.blogUrl || '',
@ -1407,11 +1431,19 @@ const saveStore = async () => {
} }
console.log('백엔드로 전송할 데이터:', storeData) console.log('백엔드로 전송할 데이터:', storeData)
console.log('=== 필드별 상세 정보 ===')
console.log('storeName:', storeData.storeName, '(타입:', typeof storeData.storeName, ')')
console.log('businessType:', storeData.businessType, '(타입:', typeof storeData.businessType, ')')
console.log('businessHours:', storeData.businessHours, '(타입:', typeof storeData.businessHours, ')')
console.log('closedDays:', storeData.closedDays, '(타입:', typeof storeData.closedDays, ')')
console.log('seatCount:', storeData.seatCount, '(타입:', typeof storeData.seatCount, ')')
let result let result
if (editMode.value) { if (editMode.value) {
console.log('🔄 매장 정보 수정 API 호출')
result = await storeStore.updateStore(storeInfo.value.storeId, storeData) result = await storeStore.updateStore(storeInfo.value.storeId, storeData)
} else { } else {
console.log(' 매장 정보 등록 API 호출')
result = await storeStore.registerStore(storeData) result = await storeStore.registerStore(storeData)
} }
@ -1437,6 +1469,8 @@ const saveStore = async () => {
} }
} }
// saveMenu
// //
const saveMenu = async () => { const saveMenu = async () => {
console.log('=== 메뉴 저장 시작 ===') console.log('=== 메뉴 저장 시작 ===')
@ -1469,6 +1503,7 @@ const saveMenu = async () => {
let menuResult let menuResult
let savedMenuId let savedMenuId
let isEdit = menuEditMode.value //
if (menuEditMode.value) { if (menuEditMode.value) {
// //
@ -1530,21 +1565,33 @@ const saveMenu = async () => {
if (imageUrl) { if (imageUrl) {
console.log('✅ 이미지 업로드 완료:', imageUrl) console.log('✅ 이미지 업로드 완료:', imageUrl)
showSnackbar(`메뉴가 ${menuEditMode.value ? '수정' : '등록'}되었고 이미지도 업로드되었습니다`, 'success') showSnackbar(`메뉴가 ${isEdit ? '수정' : '등록'}되었고 이미지도 업로드되었습니다`, 'success')
} else { } else {
console.warn('⚠️ 이미지 업로드 실패') console.warn('⚠️ 이미지 업로드 실패')
showSnackbar(`메뉴는 ${menuEditMode.value ? '수정' : '등록'}되었지만 이미지 업로드에 실패했습니다`, 'warning') showSnackbar(`메뉴는 ${isEdit ? '수정' : '등록'}되었지만 이미지 업로드에 실패했습니다`, 'warning')
} }
} else { } else {
console.log('새 이미지가 선택되지 않아 이미지 업로드 건너뜀') console.log('새 이미지가 선택되지 않아 이미지 업로드 건너뜀')
showSnackbar(`메뉴가 ${menuEditMode.value ? '수정' : '등록'}되었습니다`, 'success') showSnackbar(`메뉴가 ${isEdit ? '수정' : '등록'}되었습니다`, 'success')
} }
// //
showMenuDialog.value = false showMenuDialog.value = false
menuEditMode.value = false menuEditMode.value = false
resetMenuForm() resetMenuForm()
// ( )
if (isEdit) {
// :
await loadMenus() await loadMenus()
console.log('✅ 메뉴 수정 완료 - 목록 새로고침됨 (위치 유지)')
} else {
// : ( )
setTimeout(async () => {
await loadMenus()
console.log('✅ 메뉴 등록 완료 - 목록 새로고침됨')
}, 500)
}
} catch (error) { } catch (error) {
console.error('❌ 메뉴 저장 중 예외 발생:', error) console.error('❌ 메뉴 저장 중 예외 발생:', error)
@ -2136,4 +2183,56 @@ onMounted(async () => {
.dialog-content::-webkit-scrollbar-thumb:hover { .dialog-content::-webkit-scrollbar-thumb:hover {
background: #a8a8a8; background: #a8a8a8;
} }
/* ✅ 매장 다이얼로그 스타일 추가 - Style 부분에 추가 */
/* 매장 다이얼로그 전용 스타일 */
.store-dialog .v-overlay__content {
max-height: 90vh !important;
margin: 24px;
}
.store-dialog-card {
max-height: 90vh !important;
display: flex;
flex-direction: column;
}
.store-dialog-card .store-dialog-content {
flex: 1;
overflow-y: auto;
max-height: calc(90vh - 120px); /* 헤더와 푸터 공간 제외 */
}
/* 모바일에서 매장 다이얼로그 최적화 */
@media (max-width: 600px) {
.store-dialog .v-overlay__content {
margin: 16px;
max-height: 95vh !important;
}
.store-dialog-card .store-dialog-content {
max-height: calc(95vh - 100px);
padding: 16px !important;
}
}
/* 매장 다이얼로그 스크롤바 스타일 */
.store-dialog-content::-webkit-scrollbar {
width: 6px;
}
.store-dialog-content::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.store-dialog-content::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.store-dialog-content::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
</style> </style>