diff --git a/src/api/audio_content_series.js b/src/api/audio_content_series.js index 5e11544..2d5ff84 100644 --- a/src/api/audio_content_series.js +++ b/src/api/audio_content_series.js @@ -43,7 +43,7 @@ async function getSeriesBannerList(page = 1, size = 20) { async function createSeriesBanner(bannerData) { const formData = new FormData(); if (bannerData.image) formData.append("image", bannerData.image); - const requestData = { seriesId: bannerData.seriesId }; + const requestData = { seriesId: bannerData.seriesId, lang: bannerData.lang }; formData.append("request", JSON.stringify(requestData)); return Vue.axios.post("/admin/audio-content/series/banner/register", formData, { headers: { "Content-Type": "multipart/form-data" } diff --git a/src/api/character.js b/src/api/character.js index 5e46869..fbc21f7 100644 --- a/src/api/character.js +++ b/src/api/character.js @@ -115,9 +115,10 @@ async function createCharacterBanner(bannerData) { // 이미지 FormData에 추가 if (bannerData.image) formData.append('image', bannerData.image) - // 캐릭터 ID를 JSON 문자열로 변환하여 request 필드에 추가 + // 캐릭터 ID와 언어 코드를 JSON 문자열로 변환하여 request 필드에 추가 const requestData = { - characterId: bannerData.characterId + characterId: bannerData.characterId, + lang: bannerData.lang } formData.append('request', JSON.stringify(requestData)) diff --git a/src/views/Chat/CharacterBanner.vue b/src/views/Chat/CharacterBanner.vue index f1a0e84..5be3568 100644 --- a/src/views/Chat/CharacterBanner.vue +++ b/src/views/Chat/CharacterBanner.vue @@ -184,6 +184,18 @@ + + + + + !!v || this.isEdit || '이미지를 선택하세요' ] @@ -312,7 +330,7 @@ export default { computed: { isFormValid() { - return (this.bannerForm.image || (this.isEdit && this.bannerForm.imageUrl)) && this.selectedCharacter; + return (this.bannerForm.image || (this.isEdit && this.bannerForm.imageUrl)) && this.selectedCharacter && this.bannerForm.lang; } }, @@ -393,7 +411,8 @@ export default { image: null, imageUrl: '', characterId: null, - bannerId: null + bannerId: null, + lang: 'ko' }; this.previewImage = null; this.searchKeyword = ''; @@ -414,7 +433,8 @@ export default { image: null, imageUrl: banner.imageUrl, characterId: banner.characterId, - bannerId: banner.id + bannerId: banner.id, + lang: banner.lang || banner.language || null }; this.previewImage = null; this.searchKeyword = ''; @@ -430,7 +450,8 @@ export default { image: null, imageUrl: '', characterId: null, - bannerId: null + bannerId: null, + lang: 'ko' }; this.previewImage = null; this.searchKeyword = ''; @@ -501,7 +522,8 @@ export default { // 배너 추가 const response = await createCharacterBanner({ image: this.bannerForm.image, - characterId: this.selectedCharacter.id + characterId: this.selectedCharacter.id, + lang: this.bannerForm.lang }); if (response && response.status === 200 && response.data && response.data.success === true) { this.notifySuccess('배너가 추가되었습니다.'); diff --git a/src/views/Content/ContentList.vue b/src/views/Content/ContentList.vue index b4a2775..b759dec 100644 --- a/src/views/Content/ContentList.vue +++ b/src/views/Content/ContentList.vue @@ -75,6 +75,9 @@ 가격 + + 정산요율 + 한정판 @@ -157,6 +160,12 @@ 무료 + + + + {{ item.settlementRatio }} + + 0"> + + + 정산요율 + + + + + + + + + + 정산요율 삭제 + + + + + + @@ -497,6 +536,8 @@ export default { is_adult: false, is_comment_available: false, is_default_cover_image: false, + is_settlement_ratio_deleted: false, + settlement_ratio: "", }; await this.getAudioContentThemeList(); await this.getAudioContent(); @@ -531,6 +572,11 @@ export default { this.audio_content.is_adult = item.isAdult; this.audio_content.is_comment_available = item.isCommentAvailable; this.audio_content.is_default_cover_image = false; + this.audio_content.is_settlement_ratio_deleted = false; + this.audio_content.settlement_ratio = + item.settlementRatio !== null && item.settlementRatio !== undefined + ? String(item.settlementRatio) + : ""; this.image_preview = item.coverImageUrl; this.cover_image_file = null; @@ -590,6 +636,8 @@ export default { is_adult: false, is_comment_available: false, is_default_cover_image: false, + is_settlement_ratio_deleted: false, + settlement_ratio: "", }; this.image_preview = null; this.cover_image_file = null; @@ -631,6 +679,12 @@ export default { isDefaultCoverImage: this.audio_content.is_default_cover_image, }; + // 유료 콘텐츠인 경우에만 정산요율 관련 플래그/값 전송 고려 + const isPaid = this.selected_audio_content && this.selected_audio_content.price > 0; + if (isPaid) { + request.isSettlementRatioDeleted = this.audio_content.is_settlement_ratio_deleted; + } + if ( this.audio_content.title !== this.selected_audio_content.title && this.audio_content.title.trim().length > 0 @@ -657,6 +711,21 @@ export default { request.isCommentAvailable = this.audio_content.is_comment_available; } + // settlementRatio 처리 (null/빈문자 케이스 포함) + const originalRatio = + this.selected_audio_content.settlementRatio !== null && + this.selected_audio_content.settlementRatio !== undefined + ? String(this.selected_audio_content.settlementRatio) + : ""; + const newRatio = + this.audio_content.settlement_ratio !== null && + this.audio_content.settlement_ratio !== undefined + ? String(this.audio_content.settlement_ratio) + : ""; + if (isPaid && !this.audio_content.is_settlement_ratio_deleted && newRatio !== originalRatio) { + request.settlementRatio = newRatio; + } + const formData = new FormData(); formData.append("request", JSON.stringify(request)); diff --git a/src/views/Content/ContentMainTopBanner.vue b/src/views/Content/ContentMainTopBanner.vue index a030ee0..5ee3e4f 100644 --- a/src/views/Content/ContentMainTopBanner.vue +++ b/src/views/Content/ContentMainTopBanner.vue @@ -109,6 +109,23 @@ + + + + + 언어 + + + + + + @@ -327,7 +344,7 @@ export default { show_write_dialog: false, show_delete_confirm_dialog: false, selected_banner: {}, - banner: {type: 'CREATOR', tab_id: 1}, + banner: {type: 'CREATOR', tab_id: 1, lang: 'ko'}, banners: [], events: [], creators: [], @@ -335,7 +352,12 @@ export default { search_query_creator: '', search_query_series: '', tabs: [], - selected_tab_id: 1 + selected_tab_id: 1, + langItems: [ + { text: '한국어', value: 'ko' }, + { text: '일본어', value: 'ja' }, + { text: '영어', value: 'en' } + ] } }, @@ -379,7 +401,7 @@ export default { this.is_selecting = false this.show_write_dialog = false this.show_delete_confirm_dialog = false - this.banner = {type: 'CREATOR', tab_id: 1} + this.banner = {type: 'CREATOR', tab_id: 1, lang: 'ko'} this.selected_banner = {} this.search_query_creator = '' this.search_query_series = '' @@ -432,6 +454,10 @@ export default { this.banner.link = banner.link this.banner.is_adult = banner.isAdult this.banner.tab_id = banner.tabId + // 수정 시 언어는 변경 불가하므로 UI를 표시하지 않음. 필요 시 내부 유지만 함 (기본값 또는 서버 값 사용) + if (banner.lang) { + this.banner.lang = banner.lang + } setTimeout(() => { this.is_selecting = false; // 선택 상태 해제 @@ -497,7 +523,8 @@ export default { let request = { type: this.banner.type, - isAdult: this.banner.is_adult + isAdult: this.banner.is_adult, + lang: this.banner.lang || 'ko' } if (this.banner.type === 'CREATOR') { diff --git a/src/views/Live/LiveRecommend.vue b/src/views/Live/LiveRecommend.vue index bdc4538..df76afb 100644 --- a/src/views/Live/LiveRecommend.vue +++ b/src/views/Live/LiveRecommend.vue @@ -153,6 +153,22 @@ + + + + 언어 + + + + + + @@ -234,6 +250,12 @@ export default { start_date: null, end_date: null, is_adult: false, + lang: 'ko', + languageOptions: [ + { label: '한국어', value: 'ko' }, + { label: '일본어', value: 'ja' }, + { label: '영어', value: 'en' }, + ], headers: [ { text: '이미지', @@ -358,6 +380,7 @@ export default { formData.append("start_date", this.start_date) formData.append("end_date", this.end_date) formData.append("is_adult", this.is_adult) + formData.append("lang", this.lang) const res = await api.createRecommendCreatorBanner(formData); if (res.status === 200 && res.data.success === true) { @@ -383,7 +406,8 @@ export default { this.image === null || this.creator_id === null || this.start_date === null || - this.end_date === null + this.end_date === null || + this.lang === null ) { this.notifyError('내용을 입력하세요') } else { @@ -398,6 +422,9 @@ export default { this.creator_id = null this.start_date = null this.end_date = null + this.is_adult = false + this.lang = 'ko' + this.selected_recommend_live = null }, notifyError(message) { @@ -471,6 +498,8 @@ export default { } }, showWriteDialog() { + this.selected_recommend_live = null + this.lang = 'ko' this.show_write_dialog = true }, } diff --git a/src/views/Series/ContentSeriesBanner.vue b/src/views/Series/ContentSeriesBanner.vue index f52d3a3..a30a583 100644 --- a/src/views/Series/ContentSeriesBanner.vue +++ b/src/views/Series/ContentSeriesBanner.vue @@ -66,6 +66,14 @@ />
{{ resolveSeriesTitle(banner) }}
+ + {{ banner.lang === 'ko' ? '한국어' : banner.lang === 'ja' ? '일본어' : '영어' }} +
@@ -146,6 +154,17 @@ />
+ + + + + !!v || this.isEdit || '이미지를 선택하세요' @@ -306,7 +331,7 @@ export default { }, computed: { isFormValid() { - return (this.bannerForm.image || (this.isEdit && this.bannerForm.imageUrl)) && this.selectedSeries + return (this.bannerForm.image || (this.isEdit && this.bannerForm.imageUrl)) && this.selectedSeries && (this.isEdit || this.bannerForm.lang) } }, watch: { @@ -368,7 +393,7 @@ export default { showAddDialog() { this.isEdit = false this.selectedSeries = null - this.bannerForm = { image: null, imageUrl: '', seriesId: null, bannerId: null } + this.bannerForm = { image: null, imageUrl: '', seriesId: null, bannerId: null, lang: 'ko' } this.previewImage = null this.searchKeyword = '' this.searchResults = [] @@ -387,7 +412,8 @@ export default { image: null, imageUrl: banner.imageUrl || banner.imagePath, seriesId: banner.seriesId, - bannerId: banner.id + bannerId: banner.id, + lang: banner.lang || 'ko' } this.previewImage = null this.searchKeyword = '' @@ -398,7 +424,7 @@ export default { closeDialog() { this.showDialog = false this.selectedSeries = null - this.bannerForm = { image: null, imageUrl: '', seriesId: null, bannerId: null } + this.bannerForm = { image: null, imageUrl: '', seriesId: null, bannerId: null, lang: 'ko' } this.previewImage = null this.searchKeyword = '' this.searchResults = [] @@ -450,13 +476,16 @@ export default { }) if (response && response.status === 200 && response.data && response.data.success === true) { this.notifySuccess('배너가 수정되었습니다.') + this.closeDialog() + this.refreshBanners() } else { this.notifyError('배너 수정을 실패했습니다.') } } else { const response = await createSeriesBanner({ image: this.bannerForm.image, - seriesId: this.selectedSeries.id + seriesId: this.selectedSeries.id, + lang: this.bannerForm.lang }) if (response && response.status === 200 && response.data && response.data.success === true) { this.notifySuccess('배너가 추가되었습니다.')