99 body { font-family : system-ui, sans-serif; background : # f6f8fc ; margin : 0 ; padding : 2rem ; overflow-x : hidden; }
1010 header { display : flex; justify-content : space-between; align-items : center; margin-bottom : 1.5rem ; }
1111 h1 { margin : 0 ; }
12- .section { background : # fff ; padding : 1.5rem ; border-radius : 16px ; box-shadow : 0 8px 24px rgba (15 , 23 , 42 , 0.08 ); margin-bottom : 1.5rem ; overflow-x : auto; }
12+ .section { background : # fff ; padding : 1.5rem ; border-radius : 16px ; box-shadow : 0 8px 24px rgba (15 , 23 , 42 , 0.08 ); margin-bottom : 1.5rem ; overflow-x : auto; -webkit-overflow-scrolling : touch; overscroll-behavior-x : contain; }
1313 .section h2 { margin : 0 ; font-size : 1.1rem ; }
1414 .section-header { display : flex; justify-content : space-between; align-items : flex-end; gap : 1rem ; margin-bottom : 0.75rem ; }
1515 .summary { color : # 475569 ; font-size : 0.9rem ; }
3131 .page-btn { border : 1px solid # e2e8f0 ; background : # fff ; color : # 0f172a ; padding : 0.25rem 0.55rem ; border-radius : 8px ; cursor : pointer; font-size : 0.85rem ; }
3232 .page-btn .is-active { background : # 1d4ed8 ; color : # fff ; border-color : # 1d4ed8 ; }
3333 .page-btn : disabled { cursor : default; opacity : 0.4 ; }
34+ @media (max-width : 1024px ) {
35+ body { padding : 1rem ; }
36+ .section { padding : 1rem ; }
37+ }
3438 @media (max-width : 768px ) {
3539 body { padding : 0.5rem ; }
3640 .section { padding : 0.6rem ; border-radius : 12px ; }
@@ -73,6 +77,32 @@ <h2>시뮬레이션 AI Agent 로그</h2>
7377 < div class ="summary muted " id ="ai-note "> </ div >
7478 </ section >
7579
80+ < section class ="section ">
81+ < div class ="section-header ">
82+ < h2 > 검색 로그</ h2 >
83+ < div class ="summary " id ="search-summary "> 총 {count}건</ div >
84+ </ div >
85+ < table >
86+ < thead >
87+ < tr >
88+ < th class ="sortable narrow " data-table ="search " data-key ="timestamp "> 시간< span class ="sort-indicator "> </ span > </ th >
89+ < th class ="narrow "> search_id</ th >
90+ < th > 검색어</ th >
91+ < th > 상품류</ th >
92+ < th > 유사군</ th >
93+ < th class ="narrow "> 결과 수</ th >
94+ < th > IP</ th >
95+ < th class ="col-user-agent "> user_agent</ th >
96+ </ tr >
97+ </ thead >
98+ < tbody id ="search-table ">
99+ < tr > < td colspan ="8 " class ="muted "> 로딩 중...</ td > </ tr >
100+ </ tbody >
101+ </ table >
102+ < div class ="pagination " id ="search-pagination "> </ div >
103+ < div class ="summary muted " id ="search-note "> </ div >
104+ </ section >
105+
76106 < section class ="section ">
77107 < div class ="section-header ">
78108 < h2 > LLM 유사어 로그</ h2 >
@@ -148,6 +178,7 @@ <h2>시뮬레이션 내용 로그</h2>
148178
149179 const state = {
150180 ai : { items : [ ] , total_cost_usd : 0 , sortKey : "last_modified" , sortDir : "desc" , page : 1 } ,
181+ search : { items : [ ] , sortKey : "timestamp" , sortDir : "desc" , page : 1 } ,
151182 variants : { items : [ ] , total_cost_usd : 0 , sortKey : "timestamp" , sortDir : "desc" , page : 1 } ,
152183 debug : { items : [ ] , sortKey : "last_modified" , sortDir : "desc" , page : 1 } ,
153184 } ;
@@ -209,6 +240,7 @@ <h2>시뮬레이션 내용 로그</h2>
209240 if ( ! Number . isFinite ( next ) || next < 1 || next > totalPages ) return ;
210241 st . page = next ;
211242 if ( tableKey === "ai" ) renderAiAgent ( ) ;
243+ if ( tableKey === "search" ) renderSearch ( ) ;
212244 if ( tableKey === "variants" ) renderVariants ( ) ;
213245 if ( tableKey === "debug" ) renderDebug ( ) ;
214246 } ) ;
@@ -258,6 +290,38 @@ <h2>시뮬레이션 내용 로그</h2>
258290 updateSortIndicators ( "ai" ) ;
259291 } ;
260292
293+ const renderSearch = ( ) => {
294+ const body = document . getElementById ( "search-table" ) ;
295+ body . innerHTML = "" ;
296+ const sorted = sortItems ( state . search . items , state . search . sortKey , state . search . sortDir ) ;
297+ const items = paginateItems ( sorted , state . search . page ) ;
298+ if ( ! items . length ) {
299+ body . innerHTML = '<tr><td colspan="8" class="muted">데이터가 없습니다.</td></tr>' ;
300+ return ;
301+ }
302+ items . forEach ( ( item ) => {
303+ const row = document . createElement ( "tr" ) ;
304+ row . classList . add ( "clickable" ) ;
305+ row . innerHTML = `
306+ <td class="narrow">${ formatDate ( item . timestamp ) } </td>
307+ <td class="narrow">${ item . search_id || "-" } </td>
308+ <td>${ item . query_text || "-" } </td>
309+ <td>${ item . goods_classes || "-" } </td>
310+ <td>${ item . group_codes || "-" } </td>
311+ <td class="narrow">${ item . total_results ?? "-" } </td>
312+ <td>${ item . client_ip || "-" } </td>
313+ <td class="col-user-agent">${ item . user_agent || "-" } </td>
314+ ` ;
315+ row . addEventListener ( "click" , ( ) => toggleDetail ( row , item . key , 8 ) ) ;
316+ body . appendChild ( row ) ;
317+ } ) ;
318+ document . getElementById ( "search-summary" ) . textContent =
319+ `총 ${ state . search . items . length } 건` ;
320+ document . getElementById ( "search-note" ) . textContent = state . search . note || "" ;
321+ renderPagination ( "search-pagination" , "search" ) ;
322+ updateSortIndicators ( "search" ) ;
323+ } ;
324+
261325 const renderVariants = ( ) => {
262326 const body = document . getElementById ( "variants-table" ) ;
263327 body . innerHTML = "" ;
@@ -350,6 +414,7 @@ <h2>시뮬레이션 내용 로그</h2>
350414 }
351415 st . page = 1 ;
352416 if ( table === "ai" ) renderAiAgent ( ) ;
417+ if ( table === "search" ) renderSearch ( ) ;
353418 if ( table === "variants" ) renderVariants ( ) ;
354419 if ( table === "debug" ) renderDebug ( ) ;
355420 } ) ;
@@ -367,6 +432,15 @@ <h2>시뮬레이션 내용 로그</h2>
367432 document . getElementById ( "ai-table" ) . innerHTML =
368433 `<tr><td colspan="7" class="muted">불러오기 실패</td></tr>` ;
369434 }
435+ try {
436+ const data = await fetchLogs ( "search" ) ;
437+ state . search . items = data . items || [ ] ;
438+ state . search . note = data . note || "" ;
439+ renderSearch ( ) ;
440+ } catch ( err ) {
441+ document . getElementById ( "search-table" ) . innerHTML =
442+ `<tr><td colspan="8" class="muted">불러오기 실패</td></tr>` ;
443+ }
370444 try {
371445 const data = await fetchLogs ( "variants" ) ;
372446 state . variants . items = data . items || [ ] ;
0 commit comments