import Vue from 'vue'; // 캐릭터 리스트 async function getCharacterList(page = 1, size = 20) { return Vue.axios.get('/admin/chat/character/list', { params: { page: page - 1, size } }) } // 캐릭터 검색 async function searchCharacters(searchTerm, page = 1, size = 20) { return Vue.axios.get('/admin/chat/banner/search-character', { params: { searchTerm, page: page - 1, size } }) } // 캐릭터 상세 조회 async function getCharacter(id) { return Vue.axios.get(`/admin/chat/character/${id}`) } // 내부 헬퍼: 빈 문자열을 null로 변환 function toNullIfBlank(value) { if (typeof value === 'string') { return value.trim() === '' ? null : value; } return value === '' ? null : value; } // 캐릭터 등록 async function createCharacter(characterData) { const formData = new FormData() // 이미지만 FormData에 추가 if (characterData.image) formData.append('image', characterData.image) // 나머지 데이터는 JSON 문자열로 변환하여 request 필드에 추가 const requestData = { name: toNullIfBlank(characterData.name), systemPrompt: toNullIfBlank(characterData.systemPrompt), description: toNullIfBlank(characterData.description), age: toNullIfBlank(characterData.age), gender: toNullIfBlank(characterData.gender), mbti: toNullIfBlank(characterData.mbti), characterType: toNullIfBlank(characterData.type), originalTitle: toNullIfBlank(characterData.originalTitle), originalLink: toNullIfBlank(characterData.originalLink), speechPattern: toNullIfBlank(characterData.speechPattern), speechStyle: toNullIfBlank(characterData.speechStyle), appearance: toNullIfBlank(characterData.appearance), tags: characterData.tags || [], hobbies: characterData.hobbies || [], values: characterData.values || [], goals: characterData.goals || [], relationships: characterData.relationships || [], personalities: characterData.personalities || [], backgrounds: characterData.backgrounds || [], memories: characterData.memories || [] } formData.append('request', JSON.stringify(requestData)) return Vue.axios.post('/admin/chat/character/register', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) } // 캐릭터 수정 async function updateCharacter(characterData, image = null) { const formData = new FormData() // 이미지가 있는 경우에만 FormData에 추가 if (image) formData.append('image', image) // 변경된 데이터만 JSON 문자열로 변환하여 request 필드에 추가 ('' -> null 변환) // characterData는 이미 변경된 필드만 포함하고 있음 const processed = {} Object.keys(characterData).forEach(key => { const value = characterData[key] if (typeof value === 'string' || value === '') { processed[key] = toNullIfBlank(value) } else { processed[key] = value } }) formData.append('request', JSON.stringify(processed)) return Vue.axios.put(`/admin/chat/character/update`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }) } // 캐릭터 배너 리스트 조회 async function getCharacterBannerList(page = 1, size = 20) { return Vue.axios.get('/admin/chat/banner/list', { params: { page: page - 1, size } }) } // 캐릭터 배너 등록 async function createCharacterBanner(bannerData) { const formData = new FormData() // 이미지 FormData에 추가 if (bannerData.image) formData.append('image', bannerData.image) // 캐릭터 ID를 JSON 문자열로 변환하여 request 필드에 추가 const requestData = { characterId: bannerData.characterId } formData.append('request', JSON.stringify(requestData)) return Vue.axios.post('/admin/chat/banner/register', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) } // 캐릭터 배너 수정 async function updateCharacterBanner(bannerData) { const formData = new FormData() // 이미지가 있는 경우에만 FormData에 추가 if (bannerData.image) formData.append('image', bannerData.image) // 캐릭터 ID와 배너 ID를 JSON 문자열로 변환하여 request 필드에 추가 const requestData = { characterId: bannerData.characterId, bannerId: bannerData.bannerId } formData.append('request', JSON.stringify(requestData)) return Vue.axios.put('/admin/chat/banner/update', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) } // 캐릭터 배너 삭제 async function deleteCharacterBanner(bannerId) { return Vue.axios.delete(`/admin/chat/banner/${bannerId}`) } // 캐릭터 배너 순서 변경 async function updateCharacterBannerOrder(bannerIds) { return Vue.axios.put('/admin/chat/banner/orders', {ids: bannerIds}) } // 캐릭터 이미지 리스트 async function getCharacterImageList(characterId, page = 1, size = 20) { return Vue.axios.get('/admin/chat/character/image/list', { params: { characterId, page: page - 1, size } }) } // 캐릭터 이미지 상세 async function getCharacterImage(imageId) { return Vue.axios.get(`/admin/chat/character/image/${imageId}`) } // 캐릭터 이미지 등록 async function createCharacterImage(imageData) { const formData = new FormData() if (imageData.image) formData.append('image', imageData.image) const requestData = { characterId: imageData.characterId, imagePriceCan: imageData.imagePriceCan, messagePriceCan: imageData.messagePriceCan, isAdult: imageData.isAdult, triggers: imageData.triggers || [] } formData.append('request', JSON.stringify(requestData)) return Vue.axios.post('/admin/chat/character/image/register', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) } // 캐릭터 이미지 수정 (트리거만 수정) async function updateCharacterImage(imageData) { const imageId = imageData.imageId const payload = { triggers: imageData.triggers || [] } return Vue.axios.put(`/admin/chat/character/image/${imageId}/triggers`, payload) } // 캐릭터 이미지 삭제 async function deleteCharacterImage(imageId) { return Vue.axios.delete(`/admin/chat/character/image/${imageId}`) } // 캐릭터 이미지 순서 변경 async function updateCharacterImageOrder(characterId, imageIds) { return Vue.axios.put('/admin/chat/character/image/orders', { characterId, ids: imageIds }) } // 캐릭터 큐레이션 목록 async function getCharacterCurationList() { return Vue.axios.get('/admin/chat/character/curation/list') } // 캐릭터 큐레이션 등록 async function createCharacterCuration({ title, isAdult, isActive }) { return Vue.axios.post('/admin/chat/character/curation/register', { title, isAdult, isActive }) } // 캐릭터 큐레이션 수정 // payload: { id: Long, title?, isAdult?, isActive? } async function updateCharacterCuration(payload) { return Vue.axios.put('/admin/chat/character/curation/update', payload) } // 캐릭터 큐레이션 삭제 async function deleteCharacterCuration(curationId) { return Vue.axios.delete(`/admin/chat/character/curation/${curationId}`) } // 캐릭터 큐레이션 정렬 순서 변경 async function updateCharacterCurationOrder(ids) { return Vue.axios.put('/admin/chat/character/curation/reorder', { ids }) } // 큐레이션에 캐릭터 등록 (다중 등록) // characterIds: Array async function addCharacterToCuration(curationId, characterIds) { return Vue.axios.post(`/admin/chat/character/curation/${curationId}/characters`, { characterIds }) } // 큐레이션에서 캐릭터 삭제 async function removeCharacterFromCuration(curationId, characterId) { return Vue.axios.delete(`/admin/chat/character/curation/${curationId}/characters/${characterId}`) } // 큐레이션 내 캐릭터 정렬 순서 변경 async function updateCurationCharactersOrder(curationId, characterIds) { return Vue.axios.put(`/admin/chat/character/curation/${curationId}/characters/reorder`, { characterIds }) } // 큐레이션 캐릭터 목록 조회 (가정된 엔드포인트) async function getCharactersInCuration(curationId) { return Vue.axios.get(`/admin/chat/character/curation/${curationId}/characters`) } // 캐릭터별 정산 목록 // params: { startDateStr, endDateStr, sort, page, size } async function getCharacterCalculateList({ startDateStr, endDateStr, sort = 'TOTAL_SALES_DESC', page = 0, size = 30 }) { return Vue.axios.get('/admin/chat/calculate/characters', { params: { startDateStr, endDateStr, sort, page, size } }) } export { getCharacterList, searchCharacters, getCharacter, createCharacter, updateCharacter, getCharacterBannerList, createCharacterBanner, updateCharacterBanner, deleteCharacterBanner, updateCharacterBannerOrder, getCharacterImageList, getCharacterImage, createCharacterImage, updateCharacterImage, deleteCharacterImage, updateCharacterImageOrder, // Character Curation getCharacterCurationList, createCharacterCuration, updateCharacterCuration, deleteCharacterCuration, updateCharacterCurationOrder, addCharacterToCuration, removeCharacterFromCuration, updateCurationCharactersOrder, getCharactersInCuration, getCharacterCalculateList }