From 557f5bd8a5471cc325d7fb34f585d7960925c17e Mon Sep 17 00:00:00 2001 From: hyowons Date: Mon, 8 Jun 2026 14:58:04 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=A9=94=EC=9D=B8=20=EB=B3=B4=EC=9C=A0?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=20=EB=88=84=EB=9D=BD=20(data-row-key=20=EC=A0=91?= =?UTF-8?q?=EB=AF=B8=EC=82=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 보유행 키가 'CODE:held'(메인)·'CODE:held:계좌'(계좌별)·'CODE'(당일매매)로 갈리는데 paint 함수가 [data-row-key=CODE] 정확매칭이라 :held 메인 목록을 놓쳐 현재가·평가손익·등락률이 라이브 갱신 안 됨(당일매매 중복행·관심종목·KPI만 움직여 작동처럼 보임). selByCode로 바 키+접두 키 함께 매칭. fill_seq 빈파일('') 엣지도 수정 — 첫 체결 reload 누락 방지. Co-Authored-By: Claude Opus 4.8 --- agents/stock/workspace/scripts/behive_web.py | 31 +++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/agents/stock/workspace/scripts/behive_web.py b/agents/stock/workspace/scripts/behive_web.py index 482bbf9..a5d72d0 100644 --- a/agents/stock/workspace/scripts/behive_web.py +++ b/agents/stock/workspace/scripts/behive_web.py @@ -8938,16 +8938,19 @@ window.openPinModal = openPinModal; }); return Object.keys(s); } + // 종목코드로 행 찾기 — 같은 코드가 바 키(005930·당일매매·관심)와 접미사 키(005930:held·:held:계좌)로 동시 존재. + // 정확매칭만 하면 메인 보유목록(:held)을 놓치므로, 바 키 + "code:" 접두 키를 함께 매칭. + function selByCode(code){ return 'details.row[data-row-key="'+code+'"],details.row[data-row-key^="'+code+':"]'; } function paintPrice(code,q){ // 현재가 숫자 span(.rt-px)만 갱신 — 등락률·매매표시·당일정산(실현손익) 셀은 .rt-px가 없어 자동 제외. - // 값이 바뀔 때만 써서 깜빡임 방지. var t=q.price.toLocaleString(); - document.querySelectorAll('details.row[data-row-key="'+code+'"] .rt-px').forEach(function(el){ - if(el.textContent!==t) el.textContent=t; + document.querySelectorAll(selByCode(code)).forEach(function(r){ + r.querySelectorAll('.rt-px').forEach(function(el){ if(el.textContent!==t) el.textContent=t; }); // 값 바뀔 때만 → 깜빡임 방지 }); } function paintVI(code,active){ - document.querySelectorAll('details.row[data-row-key="'+code+'"] .line1').forEach(function(l1){ + document.querySelectorAll(selByCode(code)).forEach(function(r){ + var l1=r.querySelector('.line1'); if(!l1) return; var b=l1.querySelector('.rt-vi-badge'); if(active && !b){ b=document.createElement('span'); b.className='rt-vi-badge'; b.textContent='⚡VI'; l1.appendChild(b); } else if(!active && b){ b.remove(); } @@ -8959,10 +8962,10 @@ window.openPinModal = openPinModal; // 보유행 평가손익/평가금액 = 현재가×수량 − 매입금액(정밀). 서버 손익 공식과 동일. // data-rt-qty 있는 모든 사본(요약·당일매매·계좌별)에 적용. function paintProfit(code,price){ - document.querySelectorAll('details.row[data-rt-qty][data-row-key="'+code+'"]').forEach(function(r){ + document.querySelectorAll(selByCode(code)).forEach(function(r){ var qty=parseFloat(r.getAttribute('data-rt-qty')||'0'); var cost=parseFloat(r.getAttribute('data-rt-cost')||'0'); - if(!qty||!cost) return; + if(!qty||!cost) return; // 보유행 아닌 사본(관심·감시)은 data-rt-qty/cost 없어 자동 스킵 var ev=price*qty, profit=ev-cost, rate=profit/cost*100; var pf=r.querySelector('.rt-profit'); if(pf) pf.textContent=sgn(profit); var pp=r.querySelector('.rt-profit-pct'); if(pp) pp.textContent=(rate>=0?'+':'')+rate.toFixed(2)+'%'; @@ -8973,8 +8976,8 @@ window.openPinModal = openPinModal; } // 행 등락률·당일등락·평가금액변동 = 현재가 vs NXT 종가(data-rt-prevclose). 화면 표시와 동일 기준(0B의 KRX 등락율 아님). function paintDay(code,price){ - document.querySelectorAll('details.row[data-rt-prevclose][data-row-key="'+code+'"]').forEach(function(r){ - var pc=parseFloat(r.getAttribute('data-rt-prevclose')||'0'); + document.querySelectorAll(selByCode(code)).forEach(function(r){ + var pc=parseFloat(r.getAttribute('data-rt-prevclose')||'0'); // 없는 행(관심·감시)은 0 → 아래서 스킵 var qty=parseFloat(r.getAttribute('data-rt-qty')||'0'); if(pc<=0) return; var dc=price-pc, pct=(price/pc-1)*100, dv=dc*qty; @@ -9039,12 +9042,12 @@ window.openPinModal = openPinModal; window.__rtPx=px; updateScopes(px); // 체결 신호 변화 → 패널 새로고침(수량·예수금·당일정산 등 사건 기반 값). 첫 관측은 기준값만 저장(공회전 방지). - if(d.fill_seq){ - if(window.__rtFillSeq===undefined){ window.__rtFillSeq=d.fill_seq; } - else if(window.__rtFillSeq!==d.fill_seq){ - window.__rtFillSeq=d.fill_seq; - if(window.__behive_load){ window.__behive_load(window.__behive_active_owner?window.__behive_active_owner():null, true); } - } + // 빈 문자열('')도 유효 기준으로 취급 — 신호파일이 비어있다 첫 체결로 채워질 때도 reload 되게. + var fs=d.fill_seq||''; + if(window.__rtFillSeq===undefined){ window.__rtFillSeq=fs; } + else if(window.__rtFillSeq!==fs){ + window.__rtFillSeq=fs; + if(window.__behive_load){ window.__behive_load(window.__behive_active_owner?window.__behive_active_owner():null, true); } } }).catch(function(){}); }