From 806af4aba00b93dd161dea658209e66e870c9dcb Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Wed, 13 Aug 2025 17:30:42 +0900 Subject: [PATCH] =?UTF-8?q?fix(character-form):=20=EC=9D=B8=EB=AC=BC=20?= =?UTF-8?q?=EA=B4=80=EA=B3=84=20=EC=9E=85=EB=A0=A5=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=95=84=EC=9B=83=203=EB=8B=A8=20=EA=B5=AC=EC=84=B1=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9E=85=EB=A0=A5=20=EB=B0=A9=EC=8B=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - relationshipType, currentStatus를 v-text-field로 변경하고 길이 제한(<=10자) 및 필수 입력 검증 추가 - 인물 관계 입력을 3단 레이아웃으로 재구성 (1행: 상대방 이름+관계명, 2행: 관계 타입+현재 상태+중요도, 3행: 관계 설명) - addRelationship 로직 보강: 각 필드 substring 보정, 중요도 1~10 범위 보정, 최대 개수(10개) 체크 - 저장 로직 비교 함수에서 relationships를 객체 배열 비교 대상에 포함하여 변경 감지 정확도 개선 왜: 기존 TextField 하나로 관계를 모두 입력해 가독성과 구조화가 어려웠고, 선택형 필드 요구사항이 변경되어 직접 입력하도록 수정 필요 무엇: UI/검증/데이터 처리 전반을 요구사항에 맞게 분리 및 보강 --- src/views/Chat/CharacterForm.vue | 321 ++++++++++++++++++++++--------- 1 file changed, 230 insertions(+), 91 deletions(-) diff --git a/src/views/Chat/CharacterForm.vue b/src/views/Chat/CharacterForm.vue index a8e6df1..ef3d470 100644 --- a/src/views/Chat/CharacterForm.vue +++ b/src/views/Chat/CharacterForm.vue @@ -280,82 +280,6 @@ - - - - -

- 인물 관계 -

- - - - - - - - - - 추가 - - - - - - - - - - - - {{ relationship }} - - - - - 삭제 - - - - - - 인물 관계가 없습니다. 위 입력창에서 인물 관계를 추가해주세요. (최대 10개) - - -
-
@@ -881,6 +805,154 @@ + + + + +

+ 인물 관계 +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 추가 + + + + + + + + + + {{ relationship.personName }} - {{ relationship.relationshipName }} + + + 타입: {{ relationship.relationshipType }} | 상태: {{ relationship.currentStatus }} | 중요도: {{ relationship.importance }} + + + {{ relationship.description }} + + + + + 삭제 + + + + + + 인물 관계가 없습니다. 위 입력창에서 인물 관계를 추가해주세요. (최대 10개) + + +
+
+ @@ -936,7 +1008,14 @@ export default { newMemoryTitle: '', newMemoryContent: '', newMemoryEmotion: '', - newRelationship: '', + newRelationship: { + personName: '', + relationshipName: '', + description: '', + importance: null, + relationshipType: '', + currentStatus: '' + }, newHobby: '', newValue: '', newGoal: '', @@ -1007,6 +1086,33 @@ export default { typeOptions: ['Clone', 'Character'], systemPromptRules: [ v => (this.isEdit ? true : (!!v && v.trim().length > 0) || '시스템 프롬프트를 입력하세요') + ], + // 인물 관계 옵션 및 검증 규칙 + relationshipTypeOptions: ['가족', '친구', '동료', '연인', '기타'], + relationshipStatusOptions: ['생존', '사망', '불명'], + personNameRules: [ + v => (v === '' || v != null) || '상대방 이름을 입력하세요', + v => (!v || (typeof v === 'string' && v.length <= 10)) || '최대 10자까지 입력 가능합니다', + v => (!!v && v.trim().length > 0) || '상대방 이름을 입력하세요' + ], + relationshipNameRules: [ + v => (!!v && v.trim().length > 0) || '관계명을 입력하세요', + v => (typeof v === 'string' && v.length <= 20) || '최대 20자까지 입력 가능합니다' + ], + relationshipDescriptionRules: [ + v => (!v || (typeof v === 'string' && v.length <= 500)) || '최대 500자까지 입력 가능합니다' + ], + relationshipImportanceRules: [ + v => (v !== null && v !== '' && !isNaN(v)) || '중요도를 입력하세요', + v => (parseInt(v) >= 1 && parseInt(v) <= 10) || '1~10 사이 숫자만 입력 가능합니다' + ], + relationshipTypeRules: [ + v => (!!v && v.trim().length > 0) || '관계 타입을 입력하세요', + v => (typeof v === 'string' && v.length <= 10) || '최대 10자까지 입력 가능합니다' + ], + relationshipStatusRules: [ + v => (!!v && v.trim().length > 0) || '현재 상태를 입력하세요', + v => (typeof v === 'string' && v.length <= 10) || '최대 10자까지 입력 가능합니다' ] } }, @@ -1145,19 +1251,52 @@ export default { }, addRelationship() { - if (this.newRelationship.trim()) { - if (this.relationships.length >= 10) { - this.notifyError('인물 관계는 최대 10개까지 등록 가능합니다.'); - return; - } - - if (this.newRelationship.length > 200) { - this.newRelationship = this.newRelationship.substring(0, 200); - } - - this.relationships.unshift(this.newRelationship.trim()); - this.newRelationship = ''; + const r = this.newRelationship; + // 필수값 검사 + if (!r.personName || !r.relationshipName || !r.relationshipType || !r.currentStatus || r.importance === null || r.importance === '') { + this.notifyError('상대방 이름, 관계명, 관계 타입, 현재 상태, 중요도를 모두 입력하세요.'); + return; } + + if (this.relationships.length >= 10) { + this.notifyError('인물 관계는 최대 10개까지 등록 가능합니다.'); + return; + } + + // 길이 제한 적용 + let personName = r.personName.trim().substring(0, 10); + let relationshipName = r.relationshipName.trim().substring(0, 20); + let description = (r.description || '').trim().substring(0, 500); + + // 중요도 범위 보정 + let importance = parseInt(r.importance); + if (isNaN(importance)) importance = 1; + importance = Math.max(1, Math.min(10, importance)); + + // 타입/상태 길이 제한 적용 + let relationshipType = (r.relationshipType || '').trim().substring(0, 10); + let currentStatus = (r.currentStatus || '').trim().substring(0, 10); + + const relationshipObj = { + personName, + relationshipName, + description, + importance, + relationshipType, + currentStatus + }; + + this.relationships.unshift(relationshipObj); + + // 입력 필드 초기화 + this.newRelationship = { + personName: '', + relationshipName: '', + description: '', + importance: null, + relationshipType: '', + currentStatus: '' + }; }, removeRelationship(index) { @@ -1371,7 +1510,7 @@ export default { // 배열 필드 비교 (깊은 비교) const arrayFields = [ - 'tags', 'hobbies', 'values', 'goals', 'relationships' + 'tags', 'hobbies', 'values', 'goals' ]; arrayFields.forEach(field => { @@ -1387,7 +1526,7 @@ export default { // 복잡한 객체 배열 비교 const objectArrayFields = [ - 'personalities', 'backgrounds', 'memories' + 'personalities', 'backgrounds', 'memories', 'relationships' ]; objectArrayFields.forEach(field => {