캐릭터 챗봇 #74
| @@ -57,36 +57,15 @@ async function createCharacter(characterData) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // 캐릭터 수정 | // 캐릭터 수정 | ||||||
| async function updateCharacter(characterData) { | async function updateCharacter(characterData, image = null) { | ||||||
|   const formData = new FormData() |   const formData = new FormData() | ||||||
|  |  | ||||||
|   // 이미지만 FormData에 추가 |   // 이미지가 있는 경우에만 FormData에 추가 | ||||||
|   if (characterData.image) formData.append('image', characterData.image) |   if (image) formData.append('image', image) | ||||||
|  |  | ||||||
|   // 나머지 데이터는 JSON 문자열로 변환하여 request 필드에 추가 |   // 변경된 데이터만 JSON 문자열로 변환하여 request 필드에 추가 | ||||||
|   const requestData = { |   // characterData는 이미 변경된 필드만 포함하고 있음 | ||||||
|     id: characterData.id, |   formData.append('request', JSON.stringify(characterData)) | ||||||
|     name: characterData.name, |  | ||||||
|     systemPrompt: characterData.systemPrompt, |  | ||||||
|     description: characterData.description, |  | ||||||
|     age: characterData.age, |  | ||||||
|     gender: characterData.gender, |  | ||||||
|     mbti: characterData.mbti, |  | ||||||
|     speechPattern: characterData.speechPattern, |  | ||||||
|     speechStyle: characterData.conversationStyle, |  | ||||||
|     appearance: 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 || [], |  | ||||||
|     isActive: characterData.isActive |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   formData.append('request', JSON.stringify(requestData)) |  | ||||||
|  |  | ||||||
|   return Vue.axios.put(`/admin/chat/character/update`, formData, { |   return Vue.axios.put(`/admin/chat/character/update`, formData, { | ||||||
|     headers: { |     headers: { | ||||||
|   | |||||||
| @@ -914,6 +914,7 @@ export default { | |||||||
|       goals: [], |       goals: [], | ||||||
|       personalities: [], |       personalities: [], | ||||||
|       backgrounds: [], |       backgrounds: [], | ||||||
|  |       originalCharacter: null, // 원본 캐릭터 데이터 저장용 | ||||||
|       character: { |       character: { | ||||||
|         id: null, |         id: null, | ||||||
|         name: '', |         name: '', | ||||||
| @@ -1233,6 +1234,97 @@ export default { | |||||||
|       this.backgrounds.splice(index, 1); |       this.backgrounds.splice(index, 1); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  |     // 변경된 필드만 추출하는 함수 | ||||||
|  |     getChangedFields() { | ||||||
|  |       if (!this.originalCharacter || !this.isEdit) { | ||||||
|  |         // 신규 등록인 경우 또는 원본 데이터가 없는 경우 전체 데이터 반환 | ||||||
|  |         return { | ||||||
|  |           name: this.character.name, | ||||||
|  |           systemPrompt: this.character.systemPrompt, | ||||||
|  |           description: this.character.description, | ||||||
|  |           age: this.character.age, | ||||||
|  |           gender: this.character.gender, | ||||||
|  |           mbti: this.character.mbti, | ||||||
|  |           speechPattern: this.character.speechPattern, | ||||||
|  |           speechStyle: this.character.conversationStyle, | ||||||
|  |           appearance: this.character.appearance, | ||||||
|  |           tags: this.character.tags || [], | ||||||
|  |           hobbies: this.character.hobbies || [], | ||||||
|  |           values: this.character.values || [], | ||||||
|  |           goals: this.character.goals || [], | ||||||
|  |           relationships: this.character.relationships || [], | ||||||
|  |           personalities: this.character.personalities || [], | ||||||
|  |           backgrounds: this.character.backgrounds || [], | ||||||
|  |           memories: this.character.memories || [], | ||||||
|  |           isActive: this.character.isActive | ||||||
|  |         }; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // 변경된 필드만 포함하는 객체 | ||||||
|  |       const changedFields = { | ||||||
|  |         id: this.character.id // ID는 항상 포함 | ||||||
|  |       }; | ||||||
|  |  | ||||||
|  |       // 기본 필드 비교 | ||||||
|  |       const simpleFields = [ | ||||||
|  |         'name', 'description', 'age', 'gender', 'mbti', | ||||||
|  |         'speechPattern', 'isActive' | ||||||
|  |       ]; | ||||||
|  |  | ||||||
|  |       simpleFields.forEach(field => { | ||||||
|  |         if (this.character[field] !== this.originalCharacter[field]) { | ||||||
|  |           changedFields[field] = this.character[field]; | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |       // 특수 필드 매핑 처리 (conversationStyle은 API에서 speechStyle로 사용됨) | ||||||
|  |       if (this.character.conversationStyle !== this.originalCharacter.conversationStyle) { | ||||||
|  |         changedFields.speechStyle = this.character.conversationStyle; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (this.character.systemPrompt !== this.originalCharacter.systemPrompt) { | ||||||
|  |         changedFields.systemPrompt = this.character.systemPrompt; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (this.character.appearance !== this.originalCharacter.appearance) { | ||||||
|  |         changedFields.appearance = this.character.appearance; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // 배열 필드 비교 (깊은 비교) | ||||||
|  |       const arrayFields = [ | ||||||
|  |         'tags', 'hobbies', 'values', 'goals', 'relationships' | ||||||
|  |       ]; | ||||||
|  |  | ||||||
|  |       arrayFields.forEach(field => { | ||||||
|  |         const original = this.originalCharacter[field] || []; | ||||||
|  |         const current = this.character[field] || []; | ||||||
|  |  | ||||||
|  |         // 길이가 다르거나 내용이 다른 경우 | ||||||
|  |         if (original.length !== current.length || | ||||||
|  |             JSON.stringify(original) !== JSON.stringify(current)) { | ||||||
|  |           changedFields[field] = current; | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |       // 복잡한 객체 배열 비교 | ||||||
|  |       const objectArrayFields = [ | ||||||
|  |         'personalities', 'backgrounds', 'memories' | ||||||
|  |       ]; | ||||||
|  |  | ||||||
|  |       objectArrayFields.forEach(field => { | ||||||
|  |         const original = this.originalCharacter[field] || []; | ||||||
|  |         const current = this.character[field] || []; | ||||||
|  |  | ||||||
|  |         // 길이가 다르거나 내용이 다른 경우 | ||||||
|  |         if (original.length !== current.length || | ||||||
|  |             JSON.stringify(original) !== JSON.stringify(current)) { | ||||||
|  |           changedFields[field] = current; | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |       return changedFields; | ||||||
|  |     }, | ||||||
|  |  | ||||||
|     async loadCharacter(id) { |     async loadCharacter(id) { | ||||||
|       this.isLoading = true; |       this.isLoading = true; | ||||||
|       try { |       try { | ||||||
| @@ -1242,6 +1334,9 @@ export default { | |||||||
|         if (response && response.data) { |         if (response && response.data) { | ||||||
|           const data = response.data; |           const data = response.data; | ||||||
|  |  | ||||||
|  |           // 원본 데이터 저장 (깊은 복사) | ||||||
|  |           this.originalCharacter = JSON.parse(JSON.stringify(data)); | ||||||
|  |  | ||||||
|           // 기본 데이터 설정 |           // 기본 데이터 설정 | ||||||
|           this.character = { |           this.character = { | ||||||
|             ...this.character, // 기본 구조 유지 |             ...this.character, // 기본 구조 유지 | ||||||
| @@ -1293,9 +1388,15 @@ export default { | |||||||
|         let response; |         let response; | ||||||
|  |  | ||||||
|         if (this.isEdit) { |         if (this.isEdit) { | ||||||
|           response = await updateCharacter(this.character); |           // 수정 시 변경된 필드만 전송 | ||||||
|  |           const changedData = this.getChangedFields(); | ||||||
|  |           console.log('변경된 필드만 전송:', changedData); | ||||||
|  |           response = await updateCharacter(changedData, this.character.image); | ||||||
|         } else { |         } else { | ||||||
|           response = await createCharacter(this.character); |           // 신규 등록 시 ID 필드를 제외한 데이터 전송 | ||||||
|  |           const characterWithoutId = { ...this.character }; | ||||||
|  |           delete characterWithoutId.id; | ||||||
|  |           response = await createCharacter(characterWithoutId); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (response && response.data) { |         if (response && response.data) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user