From 22cb0758353d27cf582b0ad309b289473daabcb9 Mon Sep 17 00:00:00 2001 From: kim Date: Tue, 22 Sep 2026 19:36:01 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=9E=91=EC=97=85=EC=8B=A4=20=EC=95=B1?= =?UTF-8?q?=20=EB=B2=84=EA=B7=B8=204=EC=A2=85=20=E2=80=94=20STL=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20=EC=98=A4?= =?UTF-8?q?=EC=97=BC,=20=EB=B6=80=ED=92=88=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=9D=B8=EC=A0=9D=EC=85=98,=20=ED=8C=8C=EC=9D=BC=ED=83=AD=20?= =?UTF-8?q?=EC=8A=A4=ED=85=8C=EC=9D=BC,=20parts=20=EC=84=80=EB=8F=84?= =?UTF-8?q?=EC=9E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - switchProject/createProject/deleteProject에서 stlSelection 초기화 누락 → 프로젝트 전환 후 슬라이서 전송 시 옛 프로젝트 relPath가 현재 프로젝트 경로로 재해석되어 같은 이름의 다른 파일이 슬라이싱될 수 있던 버그 - renderParts에서 status/qty/unitPrice 이스케이프 누락(채팅 도구가 임의 문자열 쓰면 HTML 주입 경로) → escAttr 적용 - 프로젝트 생성/삭제 시 파일 탭이 열려있으면 loadFiles 미호출로 옛 프로젝트 파일 목록 남던 버그 → switchProject와 동일 갱신 추가 - callChat 내 SSE 파싱 변수 parts가 전역 부품 배열 parts를 섀도잉 → sseParts로 개명 Co-Authored-By: Claude Code --- web-ui/html/workshop-app.html | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/web-ui/html/workshop-app.html b/web-ui/html/workshop-app.html index da93742..def1900 100644 --- a/web-ui/html/workshop-app.html +++ b/web-ui/html/workshop-app.html @@ -330,6 +330,18 @@ function currentProject(){ return workshopData.projects.find(p=>p.id===workshopData.activeProjectId)||workshopData.projects[0]; } +// STL 선택은 프로젝트 기준 relPath를 담는다 — 프로젝트가 바뀌면(수동 전환/생성/삭제, +// 채팅 도구의 set_active_project 포함) 반드시 비운다. 안 그러면 옛 프로젝트 파일의 +// relPath가 workshopFilePath()에서 새 프로젝트 경로로 재해석되어, 같은 이름의 다른 +// 파일이 슬라이서로 잘못 전달될 수 있다. +function clearStlSelection(){ + stlSelection.clear(); + const btn=document.getElementById('stl-slice-btn'); + const countEl=document.getElementById('stl-sel-count'); + if(countEl)countEl.textContent='0'; + if(btn)btn.disabled=true; +} + function loadLocalFromProject(){ const proj=currentProject(); parts=proj?(proj.parts||[]):[]; @@ -366,6 +378,7 @@ function switchProject(id){ syncLocalToProject(); workshopData.activeProjectId=id; loadLocalFromProject(); + clearStlSelection(); refreshAllPanes(); scheduleSave(); if(document.getElementById('pane-files').classList.contains('active'))loadFiles(); @@ -378,8 +391,10 @@ function createProjectPrompt(){ workshopData.projects.push({id,name,parts:[],phases:[],notes:''}); workshopData.activeProjectId=id; loadLocalFromProject(); + clearStlSelection(); refreshAllPanes(); scheduleSave(); + if(document.getElementById('pane-files').classList.contains('active'))loadFiles(); } function deleteProjectPrompt(){ @@ -390,8 +405,10 @@ function deleteProjectPrompt(){ workshopData.projects=workshopData.projects.filter(p=>p.id!==proj.id); workshopData.activeProjectId=workshopData.projects[0].id; loadLocalFromProject(); + clearStlSelection(); refreshAllPanes(); scheduleSave(); + if(document.getElementById('pane-files').classList.contains('active'))loadFiles(); } async function loadWorkshopData(){ @@ -615,14 +632,14 @@ function renderParts(){
▶ ${escAttr(p.name)||'(이름 없음)'} - ${p.status} + ${escAttr(p.status)} ${fmtWon(p.qty*p.unitPrice)}
-
-
+
+