fix: HEIC 프리뷰 placeholder + 모바일 사진함 접근 허용

1. issue-report.js updatePhotoSlot: 브라우저가 <img> 로 렌더링 못하는
   포맷(HEIC 등) 감지해서 녹색 placeholder("📷 HEIC 첨부됨") 로 대체.
   photos[index] 데이터는 유지해서 업로드는 정상 동작 (서버 ImageMagick
   fallback 이 HEIC→JPEG 변환). 데스크톱 Chrome 에서 깨진 이미지 아이콘
   보이던 문제 해결.

2. m/management.html editPhotoInput: capture="environment" 제거.
   이 속성이 있으면 모바일에서 카메라 직접 호출만 되고 사진함 선택 UI 가
   나오지 않음. 관리함 사진 보충 시 기존 사진에서 고를 수 있어야 함.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-04-09 14:01:29 +09:00
parent bf0d7fd87a
commit bbffa47a9d
3 changed files with 24 additions and 8 deletions

View File

@@ -1090,22 +1090,38 @@ function resizeImage(file, maxSize, quality) {
/** /**
* 사진 슬롯 업데이트 * 사진 슬롯 업데이트
* 브라우저가 렌더링 못하는 포맷(HEIC 등) 은 img 대신 placeholder 로 표시하되
* photos[index] 데이터 자체는 유지해서 업로드는 정상 동작.
*/ */
function updatePhotoSlot(index) { function updatePhotoSlot(index) {
const slot = document.querySelector(`.photo-slot[data-index="${index}"]`); const slot = document.querySelector(`.photo-slot[data-index="${index}"]`);
// 기존 img 나 placeholder 제거
const existingImg = slot.querySelector('img');
if (existingImg) existingImg.remove();
const existingPlaceholder = slot.querySelector('.photo-placeholder');
if (existingPlaceholder) existingPlaceholder.remove();
if (photos[index]) { if (photos[index]) {
slot.classList.add('has-photo'); slot.classList.add('has-photo');
let img = slot.querySelector('img'); const data = photos[index];
if (!img) { // 브라우저가 <img> 로 렌더링 가능한 포맷만 img 사용, 그 외엔 placeholder
img = document.createElement('img'); const isRenderable = /^data:image\/(jpeg|jpg|png|gif|webp|bmp|svg)/i.test(data);
if (isRenderable) {
const img = document.createElement('img');
img.src = data;
slot.insertBefore(img, slot.firstChild); slot.insertBefore(img, slot.firstChild);
} else {
// HEIC 등 렌더링 불가 포맷 — placeholder 표시 (업로드는 정상)
const ph = document.createElement('div');
ph.className = 'photo-placeholder';
ph.style.cssText = 'width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#ecfdf5;color:#059669;font-size:0.625rem;font-weight:600;text-align:center;gap:2px;';
ph.innerHTML = '<div style="font-size:1.25rem">&#128247;</div><div>HEIC</div><div style="font-size:0.5625rem;color:#10b981">첨부됨</div>';
slot.insertBefore(ph, slot.firstChild);
} }
img.src = photos[index];
} else { } else {
slot.classList.remove('has-photo'); slot.classList.remove('has-photo');
const img = slot.querySelector('img');
if (img) img.remove();
} }
} }

View File

@@ -783,6 +783,6 @@
<input type="file" id="photoInput" accept="image/*" style="display:none"> <input type="file" id="photoInput" accept="image/*" style="display:none">
<script src="/js/cross-nav.js?v=2026031401"></script> <script src="/js/cross-nav.js?v=2026031401"></script>
<script src="/js/issue-report.js?v=2026031401"></script> <script src="/js/issue-report.js?v=2026040901"></script>
</body> </body>
</html> </html>

View File

@@ -96,7 +96,7 @@
<div class="m-form-group" id="editPhotoGroup"> <div class="m-form-group" id="editPhotoGroup">
<label class="m-label"><i class="fas fa-camera" style="color:#10b981;margin-right:4px"></i>사진 보충 <span id="editPhotoSlotInfo" style="font-size:11px;color:#6b7280"></span></label> <label class="m-label"><i class="fas fa-camera" style="color:#10b981;margin-right:4px"></i>사진 보충 <span id="editPhotoSlotInfo" style="font-size:11px;color:#6b7280"></span></label>
<div id="editExistingPhotos" style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px"></div> <div id="editExistingPhotos" style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px"></div>
<input type="file" id="editPhotoInput" accept="image/*" capture="environment" multiple <input type="file" id="editPhotoInput" accept="image/*" multiple
class="m-input" style="padding:8px;font-size:12px" onchange="previewEditPhotos(event)"> class="m-input" style="padding:8px;font-size:12px" onchange="previewEditPhotos(event)">
<div id="editPhotoPreview" style="display:flex;flex-wrap:wrap;gap:6px;margin-top:6px"></div> <div id="editPhotoPreview" style="display:flex;flex-wrap:wrap;gap:6px;margin-top:6px"></div>
<p style="font-size:11px;color:#9ca3af;margin-top:4px">※ 비어있는 슬롯에만 자동 채움. 기존 사진은 유지됩니다.</p> <p style="font-size:11px;color:#9ca3af;margin-top:4px">※ 비어있는 슬롯에만 자동 채움. 기존 사진은 유지됩니다.</p>