diff --git a/src/api/original.js b/src/api/original.js index 7844b3f..8969011 100644 --- a/src/api/original.js +++ b/src/api/original.js @@ -1,6 +1,6 @@ import Vue from 'vue'; -// 공통: 빈 문자열 -> null +// 공통: 값 그대로 전달 (빈 문자열 유지) function toNullIfBlank(value) { if (typeof value === 'string') { return value.trim() === '' ? null : value; @@ -25,7 +25,12 @@ export async function createOriginal(data) { category: toNullIfBlank(data.category), isAdult: !!data.isAdult, description: toNullIfBlank(data.description), - originalLink: toNullIfBlank(data.originalLink) + originalLink: toNullIfBlank(data.originalLink), // 원천 원작 링크 + originalWork: toNullIfBlank(data.originalWork), + writer: toNullIfBlank(data.writer), + studio: toNullIfBlank(data.studio), + originalLinks: Array.isArray(data.originalLinks) ? data.originalLinks : [], + tags: Array.isArray(data.tags) ? data.tags : [] }; formData.append('request', JSON.stringify(request)); return Vue.axios.post('/admin/chat/original/register', formData, { @@ -39,12 +44,7 @@ export async function updateOriginal(data, image = null) { if (image) formData.append('image', image); const processed = {}; Object.keys(data).forEach(key => { - const value = data[key]; - if (typeof value === 'string' || value === '') { - processed[key] = toNullIfBlank(value) - } else { - processed[key] = value - } + processed[key] = data[key]; }) formData.append('request', JSON.stringify(processed)); return Vue.axios.put('/admin/chat/original/update', formData, { diff --git a/src/views/Chat/OriginalDetail.vue b/src/views/Chat/OriginalDetail.vue index f2dc361..ce923d6 100644 --- a/src/views/Chat/OriginalDetail.vue +++ b/src/views/Chat/OriginalDetail.vue @@ -44,8 +44,9 @@
카테고리(장르): {{ detail.category || '-' }}
19금 여부: {{ detail.isAdult ? '예' : '아니오' }}
-
- 원작 링크: +
원천 원작: {{ detail.originalWork || '-' }}
+
+ 원천 원작 링크: {{ detail.originalLink }} -
+
글/그림: {{ detail.writer || '-' }}
+
제작사: {{ detail.studio || '-' }}
+
+ 원작 링크: + + - +
+
+ 태그: + + - +
작품 소개:
diff --git a/src/views/Chat/OriginalForm.vue b/src/views/Chat/OriginalForm.vue index f4e40de..f980afe 100644 --- a/src/views/Chat/OriginalForm.vue +++ b/src/views/Chat/OriginalForm.vue @@ -93,15 +93,42 @@ + - + + + + + + + + + + + + + + + + + + + +

+ 원작 링크 +

+ + + + + + + 추가 + + + + + + + + + {{ link }} + + + + + 삭제 + + + + + + 추가된 원작 링크가 없습니다. + + +
+
+ + + + + +

+ 태그 +

+ + + +
+
+ (this.isEdit ? true : (!!v || '이미지를 선택하세요'))], contentTypeRules: [v => (this.isEdit ? true : (!!(v && v.toString().trim()) || '콘텐츠 타입은 필수입니다'))], categoryRules: [v => (this.isEdit ? true : (!!(v && v.toString().trim()) || '카테고리는 필수입니다'))], - originalLinkRules: [v => (this.isEdit ? true : (!!(v && v.toString().trim()) || '원작 링크는 필수입니다'))], + originalLinkRules: [v => (this.isEdit ? true : (!!(v && v.toString().trim()) || '원천 원작 링크는 필수입니다'))], descriptionRules: [v => (this.isEdit ? true : (!!(v && v.toString().trim()) || '작품 소개는 필수입니다'))] } }, @@ -184,8 +327,11 @@ export default { }, hasNonImageChanges() { if (!this.isEdit || !this.originalInitial) return false; - const fields = ['title', 'contentType', 'category', 'isAdult', 'description', 'originalLink']; - return fields.some(f => this.form[f] !== this.originalInitial[f]); + const fields = ['title', 'contentType', 'category', 'isAdult', 'description', 'originalLink', 'originalWork', 'writer', 'studio']; + const basicChanged = fields.some(f => this.form[f] !== this.originalInitial[f]); + const arraysChanged = !this.arraysEqual(this.form.originalLinks, this.originalInitial.originalLinks) + || !this.arraysEqual(this.form.tags, this.originalInitial.tags); + return basicChanged || arraysChanged; }, hasEditChanges() { return this.imageChanged || this.hasNonImageChanges; @@ -219,6 +365,44 @@ export default { notifyError(message) { this.$dialog.notify.error(message) }, notifySuccess(message) { this.$dialog.notify.success(message) }, goBack() { this.$router.push('/original-work') }, + arraysEqual(a, b) { + const arrA = Array.isArray(a) ? a : []; + const arrB = Array.isArray(b) ? b : []; + if (arrA.length !== arrB.length) return false; + for (let i = 0; i < arrA.length; i++) { + if (arrA[i] !== arrB[i]) return false; + } + return true; + }, + addOriginalLink() { + if (!this.newOriginalLink || !this.newOriginalLink.trim()) return; + const val = this.newOriginalLink.trim(); + if (!this.form.originalLinks) this.form.originalLinks = []; + if (!this.form.originalLinks.includes(val)) { + this.form.originalLinks.push(val); + } + this.newOriginalLink = ''; + }, + removeOriginalLink(index) { + if (!this.form.originalLinks) return; + this.form.originalLinks.splice(index, 1); + }, + onTagSpace() { + // CharacterForm의 태그 방식과 유사: 마지막 항목을 공백 기준으로 확정 + if (!Array.isArray(this.form.tags)) this.form.tags = []; + const last = this.form.tags[this.form.tags.length - 1]; + if (typeof last === 'string' && last.trim()) { + let processed = last.trim().replace(/\s+/g, ''); + if (processed.length > 50) processed = processed.substring(0, 50); + this.form.tags.splice(this.form.tags.length - 1, 1, processed); + this.$nextTick(() => this.form.tags.push('')); + } + }, + removeTag(item) { + if (!Array.isArray(this.form.tags)) return; + const idx = this.form.tags.indexOf(item); + if (idx >= 0) this.form.tags.splice(idx, 1); + }, async load(id) { try { const res = await getOriginal(id); @@ -233,7 +417,12 @@ export default { category: d.category || '', isAdult: !!d.isAdult, description: d.description || '', - originalLink: d.originalLink || '' + originalLink: d.originalLink || '', + originalWork: d.originalWork || '', + writer: d.writer || '', + studio: d.studio || '', + originalLinks: Array.isArray(d.originalLinks) ? d.originalLinks.slice() : [], + tags: Array.isArray(d.tags) ? d.tags.slice() : [] } this.originalInitial = { id: d.id, @@ -243,7 +432,12 @@ export default { category: d.category || '', isAdult: !!d.isAdult, description: d.description || '', - originalLink: d.originalLink || '' + originalLink: d.originalLink || '', + originalWork: d.originalWork || '', + writer: d.writer || '', + studio: d.studio || '', + originalLinks: Array.isArray(d.originalLinks) ? d.originalLinks.slice() : [], + tags: Array.isArray(d.tags) ? d.tags.slice() : [] } } else { this.notifyError('상세 조회 실패'); @@ -261,7 +455,7 @@ export default { } if (this.isEdit) { - const fields = ['title', 'contentType', 'category', 'isAdult', 'description', 'originalLink']; + const fields = ['title', 'contentType', 'category', 'isAdult', 'description', 'originalLink', 'originalWork', 'writer', 'studio']; const patch = { id: this.form.id }; if (this.originalInitial) { fields.forEach(f => { @@ -269,6 +463,12 @@ export default { patch[f] = this.form[f]; } }); + if (!this.arraysEqual(this.form.originalLinks, this.originalInitial.originalLinks)) { + patch.originalLinks = this.form.originalLinks; + } + if (!this.arraysEqual(this.form.tags, this.originalInitial.tags)) { + patch.tags = this.form.tags; + } } const image = this.form.image || null; if (Object.keys(patch).length === 1 && !image) {