From 56f626911aafed5379b90f8facef1281378c6607 Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Thu, 9 Apr 2026 13:46:46 +0900 Subject: [PATCH] =?UTF-8?q?fix(tkqc):=20=EA=B4=80=EB=A6=AC=ED=95=A8=20?= =?UTF-8?q?=EB=8D=B0=EC=8A=A4=ED=81=AC=ED=86=B1=20=EC=9D=B8=EB=9D=BC?= =?UTF-8?q?=EC=9D=B8=20=EC=B9=B4=EB=93=9C=EC=97=90=EB=8F=84=20=EC=82=AC?= =?UTF-8?q?=EC=A7=84=20=EB=B3=B4=EC=B6=A9=20UI=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 첫 커밋(178155d)에서는 createModalContent(완료된 이슈 상세 모달)에만 사진 보충 input을 추가했는데, 데스크톱 관리함은 상세 모달이 아니라 createInProgressRow 로 렌더링되는 인라인 카드(저장/삭제/완료처리 버튼이 카드에 직접 있는 형태) 이었음. 사용자 스크린샷으로 확인. - createInProgressRow: "업로드 사진" 섹션 아래 file input 추가 - saveIssueChanges: 저장 시 빈 슬롯에만 photo/photo2~5 base64 업로드 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../web/issues-management.html | 2 +- .../web/static/js/pages/issues-management.js | 64 +++++++++++++++---- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/system3-nonconformance/web/issues-management.html b/system3-nonconformance/web/issues-management.html index 36f6ffc..5f8a2fc 100644 --- a/system3-nonconformance/web/issues-management.html +++ b/system3-nonconformance/web/issues-management.html @@ -349,6 +349,6 @@ - + diff --git a/system3-nonconformance/web/static/js/pages/issues-management.js b/system3-nonconformance/web/static/js/pages/issues-management.js index dc1f3cf..2be57de 100644 --- a/system3-nonconformance/web/static/js/pages/issues-management.js +++ b/system3-nonconformance/web/static/js/pages/issues-management.js @@ -427,25 +427,37 @@ function createInProgressRow(issue, project) {
${(() => { - const photos = [ + const photoSlots = [ issue.photo_path, issue.photo_path2, issue.photo_path3, issue.photo_path4, issue.photo_path5 - ].filter(p => p); + ]; + const filled = photoSlots.filter(p => p); + const emptyCount = 5 - filled.length; - if (photos.length === 0) { - return '
사진 없음
'; - } + const existing = filled.length === 0 + ? '
사진 없음
' + : `
+ ${filled.map((path, idx) => ` + 업로드 사진 ${idx + 1} + `).join('')} +
`; - return ` -
- ${photos.map((path, idx) => ` - 업로드 사진 ${idx + 1} - `).join('')} + // 사진 보충 UI (빈 슬롯에만 채움, 저장 버튼 클릭 시 업로드) + const uploadUi = isPendingCompletion ? '' : (emptyCount > 0 ? ` +
+ + +

※ 비어있는 슬롯에만 자동으로 채워집니다 (기존 사진은 유지). 저장 버튼 클릭 시 업로드.

- `; + ` : '

5장 모두 찬 상태입니다

'); + + return existing + uploadUi; })()}
@@ -909,6 +921,36 @@ async function saveIssueChanges(issueId) { } } + // 원본 사진 보충 — 빈 슬롯에만 자동 채움 (기존 사진 유지) + const originalPhotoInput = document.getElementById(`original_photo_${issueId}`); + if (originalPhotoInput && originalPhotoInput.files && originalPhotoInput.files.length > 0) { + const currentIssue = issues.find(i => i.id === issueId); + if (currentIssue) { + const slotKeys = ['photo_path', 'photo_path2', 'photo_path3', 'photo_path4', 'photo_path5']; + const emptySlots = []; + slotKeys.forEach((key, idx) => { + if (!currentIssue[key]) emptySlots.push(idx + 1); + }); + + if (emptySlots.length === 0) { + alert('원본 사진 슬롯이 가득 찼습니다. 보충할 수 없습니다.'); + return; + } + + const files = Array.from(originalPhotoInput.files).slice(0, emptySlots.length); + if (originalPhotoInput.files.length > emptySlots.length) { + alert(`빈 슬롯은 ${emptySlots.length}개인데 ${originalPhotoInput.files.length}개를 선택하셨습니다. 처음 ${emptySlots.length}장만 업로드됩니다.`); + } + + for (let i = 0; i < files.length; i++) { + const slotNum = emptySlots[i]; + const base64 = await fileToBase64(files[i]); + const fieldName = slotNum === 1 ? 'photo' : `photo${slotNum}`; + updates[fieldName] = base64; + } + } + } + // API 호출 const response = await fetch(`/api/issues/${issueId}/management`, { method: 'PUT',