556 lines
36 KiB
HTML
556 lines
36 KiB
HTML
<!doctype html>
|
||
<html lang="ko">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'">
|
||
<title>MBN Stock WebView</title>
|
||
<link rel="stylesheet" href="styles.css">
|
||
<link rel="stylesheet" href="manual-lists-ui.css">
|
||
<link rel="stylesheet" href="manual-financial-ui.css">
|
||
<link rel="stylesheet" href="operator-catalog-ui.css">
|
||
</head>
|
||
<body>
|
||
<div class="app-shell">
|
||
<aside class="sidebar" aria-label="주요 메뉴">
|
||
<div class="brand-block">
|
||
<div class="brand-mark">M</div>
|
||
<div>
|
||
<strong>MBN STOCK</strong>
|
||
<span>방송 그래픽 콘솔</span>
|
||
</div>
|
||
</div>
|
||
|
||
<nav id="marketNav" class="market-nav">
|
||
<button class="nav-item active" data-market="dashboard"><span>⌂</span>대시보드</button>
|
||
<button class="nav-item" data-market="overseas"><span>◉</span>해외</button>
|
||
<button class="nav-item" data-market="exchange"><span>⇄</span>환율</button>
|
||
<button class="nav-item" data-market="index"><span>⌁</span>지수</button>
|
||
<button class="nav-item" data-market="kospi"><span>K</span>코스피</button>
|
||
<button class="nav-item" data-market="kosdaq"><span>Q</span>코스닥</button>
|
||
<button class="nav-item" data-market="compare"><span>≍</span>비교</button>
|
||
<button class="nav-item" data-market="theme"><span>◆</span>테마</button>
|
||
<button class="nav-item" data-market="foreign-stock"><span>$</span>해외종목</button>
|
||
<button class="nav-item" data-market="expert"><span>✦</span>전문가</button>
|
||
<button class="nav-item" data-market="halted"><span>Ⅱ</span>정지</button>
|
||
</nav>
|
||
|
||
<div class="sidebar-status">
|
||
<div class="status-row"><span class="status-dot ok"></span><span>Native Bridge</span><strong id="bridgeState">연결 중</strong></div>
|
||
<div class="status-row"><span id="databaseStateDot" class="status-dot pending"></span><span>Database</span><strong id="databaseState">확인 중</strong></div>
|
||
<div class="runtime" id="runtimeLabel">.NET 8 · WinUI 3 · x64</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<main class="workspace">
|
||
<header class="workspace-header">
|
||
<div>
|
||
<p class="eyebrow">OPERATOR WORKSPACE</p>
|
||
<h1 id="workspaceTitle">마이그레이션 대시보드</h1>
|
||
</div>
|
||
<div class="header-meta">
|
||
<div><span>현재 시각</span><strong id="clock">--:--:--</strong></div>
|
||
<div><span>패키지</span><strong id="packageLabel">MSIX</strong></div>
|
||
<button id="requestInfoButton" class="ghost-button" type="button">상태 새로고침</button>
|
||
</div>
|
||
</header>
|
||
|
||
<section class="summary-strip" aria-label="마이그레이션 상태">
|
||
<article><span class="metric-icon mint">✓</span><div><strong>WebView UI</strong><small>FarPoint 대체 기반</small></div><b>READY</b></article>
|
||
<article><span class="metric-icon blue">71</span><div><strong>데이터 요청</strong><small>기존 SQL 계층 이관</small></div><b>MIGRATED</b></article>
|
||
<article id="databaseSummary"><span id="databaseSummaryIcon" class="metric-icon amber">DB</span><div><strong>Oracle · MariaDB</strong><small id="databaseSummaryDetail">연결 상태 확인 중</small></div><b id="databaseSummaryBadge">CHECKING</b></article>
|
||
<article id="playoutSummary" class="playout-summary"><span id="playoutSummaryIcon" class="metric-icon violet">T2</span><div><strong>Tornado Engine</strong><small id="playoutSummaryDetail">상태 확인 중</small></div><b id="playoutSummaryBadge">CHECKING</b></article>
|
||
</section>
|
||
|
||
<div class="console-grid">
|
||
<section class="panel catalog-panel">
|
||
<div class="panel-header">
|
||
<div><p class="panel-kicker">OPERATOR INPUT</p><h2>종목·그래픽 선택</h2></div>
|
||
<span id="catalogModeBadge" class="badge">Web UI</span>
|
||
</div>
|
||
<section id="stockWorkflow" class="stock-workflow" aria-labelledby="stockWorkflowTitle">
|
||
<div class="stock-workflow-header">
|
||
<div>
|
||
<p class="panel-kicker">LEGACY STOCK WORKFLOW</p>
|
||
<h3 id="stockWorkflowTitle">종목 검색</h3>
|
||
</div>
|
||
<div class="stock-workflow-tools">
|
||
<span id="stockSearchBadge" class="badge neutral">DB SEARCH</span>
|
||
<button id="stockWorkflowToggle" type="button" aria-expanded="true">접기</button>
|
||
</div>
|
||
</div>
|
||
<form id="stockSearchForm" class="stock-search-form" autocomplete="off">
|
||
<label for="stockSearchInput" class="visually-hidden">종목명</label>
|
||
<input id="stockSearchInput" type="search" maxlength="64" placeholder="예: 삼성" spellcheck="false">
|
||
<button id="stockSearchButton" type="submit">검색</button>
|
||
</form>
|
||
<div id="stockSearchState" class="stock-search-state" role="status" aria-live="polite">종목명을 입력하고 Enter를 누르세요.</div>
|
||
<div id="stockSearchResults" class="stock-search-results" role="listbox" aria-label="종목 검색 결과"></div>
|
||
<div id="selectedStock" class="selected-stock" hidden>
|
||
<span>선택 종목</span>
|
||
<strong id="selectedStockName">—</strong>
|
||
<small id="selectedStockMeta">—</small>
|
||
</div>
|
||
<div class="stock-cut-header">
|
||
<div><strong>종목용 컷</strong><small>더블클릭 또는 + 버튼으로 추가</small></div>
|
||
<label><input id="stockMa5" type="checkbox" checked>5일선</label>
|
||
<label><input id="stockMa20" type="checkbox" checked>20일선</label>
|
||
</div>
|
||
<div id="stockCutList" class="stock-cut-list" aria-label="종목용 컷 목록"></div>
|
||
<div id="manualStockActions" class="manual-stock-actions" aria-label="수동 재무 데이터"></div>
|
||
</section>
|
||
<section id="legacyFixedWorkflow" class="legacy-fixed-workflow" aria-labelledby="legacyFixedWorkflowTitle" hidden>
|
||
<div class="legacy-fixed-header">
|
||
<div>
|
||
<p class="panel-kicker">LEGACY RUNTIME CATALOG</p>
|
||
<h3 id="legacyFixedWorkflowTitle">원본 운영 항목</h3>
|
||
</div>
|
||
<div class="legacy-fixed-tools">
|
||
<span id="legacyFixedCount" class="badge neutral">0 ACTIONS</span>
|
||
<button id="legacyFixedToggle" type="button" aria-expanded="true">접기</button>
|
||
</div>
|
||
</div>
|
||
<label class="legacy-fixed-search">
|
||
<span>⌕</span>
|
||
<input id="legacyFixedSearch" type="search" maxlength="64" autocomplete="off" placeholder="원본 항목 검색">
|
||
</label>
|
||
<div id="legacyFixedState" class="legacy-fixed-state" role="status" aria-live="polite"></div>
|
||
<div id="legacyFixedSections" class="legacy-fixed-sections" aria-label="원본 운영 항목"></div>
|
||
</section>
|
||
<section id="industryWorkflow" class="industry-workflow" aria-labelledby="industryWorkflowTitle" hidden>
|
||
<div class="industry-workflow-header">
|
||
<div>
|
||
<p class="panel-kicker">LEGACY INDUSTRY WORKFLOW</p>
|
||
<h3 id="industryWorkflowTitle">업종 선택</h3>
|
||
</div>
|
||
<div class="industry-workflow-tools">
|
||
<span id="industryCount" class="badge neutral">DB</span>
|
||
<button id="industryRetry" type="button">다시 조회</button>
|
||
<button id="industryWorkflowToggle" type="button" aria-expanded="true">접기</button>
|
||
</div>
|
||
</div>
|
||
<label class="industry-search">
|
||
<span>⌕</span>
|
||
<input id="industrySearch" type="search" maxlength="64" autocomplete="off" placeholder="업종명 검색">
|
||
</label>
|
||
<div id="industryState" class="industry-state" role="status" aria-live="polite"></div>
|
||
<div id="industryResults" class="industry-results" role="listbox" aria-label="업종 목록"></div>
|
||
<div class="industry-pair" aria-label="업종 비교 선택">
|
||
<div><span>첫 번째</span><strong id="industryPrimary">선택 없음</strong></div>
|
||
<button id="industrySwap" type="button" title="두 업종 순서 교환">⇄</button>
|
||
<div><span>두 번째</span><strong id="industrySecondary">선택 없음</strong></div>
|
||
<button id="industryClear" type="button">초기화</button>
|
||
</div>
|
||
<div id="industryCutList" class="industry-cut-list" aria-label="업종용 컷 목록"></div>
|
||
</section>
|
||
<section id="comparisonWorkflow" class="comparison-workflow" aria-labelledby="comparisonWorkflowTitle" hidden>
|
||
<div class="comparison-workflow-header">
|
||
<div>
|
||
<p class="panel-kicker">LEGACY COMPARISON WORKFLOW</p>
|
||
<h3 id="comparisonWorkflowTitle">종목 비교</h3>
|
||
</div>
|
||
<span id="comparisonPairCount" class="badge neutral">0 PAIRS</span>
|
||
</div>
|
||
<div id="comparisonSourceTabs" class="comparison-source-tabs" role="tablist" aria-label="비교 대상 종류">
|
||
<button type="button" class="active" data-comparison-source="domestic">국내·NXT</button>
|
||
<button type="button" data-comparison-source="fixed">지수·환율</button>
|
||
<button type="button" data-comparison-source="world">해외 종목</button>
|
||
</div>
|
||
<section id="comparisonDomesticPanel" class="comparison-source-panel">
|
||
<form id="comparisonDomesticSearchForm" class="comparison-search-form" autocomplete="off">
|
||
<input id="comparisonDomesticSearch" type="search" maxlength="64" placeholder="국내·NXT 종목명" aria-label="국내·NXT 종목명">
|
||
<button id="comparisonDomesticSearchButton" type="submit">검색</button>
|
||
</form>
|
||
<div id="comparisonDomesticState" class="comparison-search-state" role="status" aria-live="polite"></div>
|
||
<div id="comparisonDomesticResults" class="comparison-target-results" role="listbox" aria-label="국내·NXT 종목 검색 결과"></div>
|
||
</section>
|
||
<section id="comparisonFixedPanel" class="comparison-source-panel" hidden>
|
||
<div id="comparisonFixedTargets" class="comparison-target-results fixed" role="listbox" aria-label="고정 비교 대상"></div>
|
||
</section>
|
||
<section id="comparisonWorldPanel" class="comparison-source-panel" hidden>
|
||
<form id="comparisonWorldSearchForm" class="comparison-search-form" autocomplete="off">
|
||
<input id="comparisonWorldSearch" type="search" maxlength="64" placeholder="미국·대만 종목명" aria-label="해외 종목명">
|
||
<button id="comparisonWorldSearchButton" type="submit">검색</button>
|
||
</form>
|
||
<div id="comparisonWorldState" class="comparison-search-state" role="status" aria-live="polite"></div>
|
||
<div id="comparisonWorldResults" class="comparison-target-results" role="listbox" aria-label="해외 종목 검색 결과"></div>
|
||
</section>
|
||
<div class="comparison-draft" aria-label="비교쌍 편집">
|
||
<div><span>첫 번째</span><strong id="comparisonFirst">선택 없음</strong></div>
|
||
<button id="comparisonSwap" type="button" title="비교 대상 순서 교환">⇄</button>
|
||
<div><span>두 번째</span><strong id="comparisonSecond">선택 없음</strong></div>
|
||
<button id="comparisonClear" type="button">초기화</button>
|
||
<button id="comparisonSavePair" class="primary" type="button">비교쌍 추가</button>
|
||
</div>
|
||
<div class="comparison-pair-header">
|
||
<div><strong>저장 비교쌍</strong><small>행을 선택한 뒤 컷을 추가합니다.</small></div>
|
||
<div>
|
||
<button id="comparisonMoveUp" type="button" title="위로">↑</button>
|
||
<button id="comparisonMoveDown" type="button" title="아래로">↓</button>
|
||
<button id="comparisonDeletePair" type="button">삭제</button>
|
||
<button id="comparisonDeleteAll" type="button">전체삭제</button>
|
||
</div>
|
||
</div>
|
||
<div id="comparisonPairList" class="comparison-pair-list" role="listbox" aria-label="저장 비교쌍"></div>
|
||
<div class="comparison-action-header">
|
||
<div><strong>비교용 컷</strong><small>원본 종목비교.ini 9개 액션</small></div>
|
||
<button id="comparisonYieldBatch" type="button">수익률 5종 일괄 추가</button>
|
||
</div>
|
||
<div id="comparisonActionList" class="comparison-action-list" aria-label="비교용 컷 목록"></div>
|
||
</section>
|
||
<section id="themeWorkflow" class="theme-workflow" aria-labelledby="themeWorkflowTitle" hidden>
|
||
<div class="theme-workflow-header">
|
||
<div>
|
||
<p class="panel-kicker">LEGACY THEME WORKFLOW</p>
|
||
<h3 id="themeWorkflowTitle">테마 선택</h3>
|
||
</div>
|
||
<span id="themeCount" class="badge neutral">READ ONLY</span>
|
||
</div>
|
||
<form id="themeSearchForm" class="theme-search-form" autocomplete="off">
|
||
<input id="themeSearch" type="search" maxlength="64" placeholder="테마명 · 빈 값은 전체" aria-label="테마명">
|
||
<select id="themeNxtSession" aria-label="NXT 세션">
|
||
<option value="preMarket">NXT 장전</option>
|
||
<option value="afterMarket">NXT 시간외</option>
|
||
</select>
|
||
<button id="themeSearchButton" type="submit">조회</button>
|
||
</form>
|
||
<div id="themeSearchState" class="theme-search-state" role="status" aria-live="polite"></div>
|
||
<div id="themeResults" class="theme-results" role="listbox" aria-label="테마 검색 결과"></div>
|
||
<div id="selectedTheme" class="selected-theme" hidden>
|
||
<div><span>선택 테마</span><strong id="selectedThemeTitle">—</strong><small id="selectedThemeMeta">—</small></div>
|
||
<label>정렬
|
||
<select id="themeSort">
|
||
<option value="INPUT_ORDER">입력순</option>
|
||
<option value="GAIN_DESC">상승률순</option>
|
||
<option value="GAIN_ASC">하락률순</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
<div class="theme-preview-header">
|
||
<div><strong>테마 종목</strong><small>송출 전 read-only 미리보기</small></div>
|
||
<span id="themePreviewCount">0 ITEMS</span>
|
||
</div>
|
||
<div id="themePreviewState" class="theme-preview-state" role="status" aria-live="polite"></div>
|
||
<div id="themePreviewItems" class="theme-preview-items" aria-label="테마 종목 미리보기"></div>
|
||
<div class="theme-action-header"><strong>테마용 컷</strong><small>5·6·12개 단위 · 최대 20페이지</small></div>
|
||
<div id="themeActionList" class="theme-action-list" aria-label="테마용 컷 목록"></div>
|
||
<div class="theme-crud-notice">
|
||
<span>ThemeA · 트랜잭션 기반 추가·편집·삭제</span>
|
||
<button id="themeCatalogManageButton" type="button">테마 관리</button>
|
||
</div>
|
||
</section>
|
||
<section id="overseasWorkflow" class="overseas-workflow" aria-labelledby="overseasWorkflowTitle" hidden>
|
||
<div class="overseas-workflow-header">
|
||
<div>
|
||
<p class="panel-kicker">LEGACY FOREIGN INSTRUMENT WORKFLOW</p>
|
||
<h3 id="overseasWorkflowTitle">해외업종·해외종목</h3>
|
||
</div>
|
||
<span id="overseasCount" class="badge neutral">ORACLE</span>
|
||
</div>
|
||
<div id="overseasSourceTabs" class="overseas-source-tabs" role="tablist" aria-label="해외 검색 종류">
|
||
<button type="button" class="active" data-overseas-source="industry">미국 해외업종</button>
|
||
<button type="button" data-overseas-source="stock">US·TW 해외종목</button>
|
||
</div>
|
||
<form id="overseasSearchForm" class="overseas-search-form" autocomplete="off">
|
||
<input id="overseasSearch" type="search" maxlength="64" placeholder="빈 값은 전체 목록" aria-label="해외업종 또는 해외종목 검색어">
|
||
<button id="overseasSearchButton" type="submit">조회</button>
|
||
</form>
|
||
<div id="overseasSearchState" class="overseas-search-state" role="status" aria-live="polite"></div>
|
||
<div id="overseasResults" class="overseas-results" role="listbox" aria-label="해외업종·해외종목 검색 결과"></div>
|
||
<div id="selectedOverseas" class="selected-overseas" hidden>
|
||
<div>
|
||
<span>선택 대상</span>
|
||
<strong id="selectedOverseasName">-</strong>
|
||
<small id="selectedOverseasMeta">-</small>
|
||
</div>
|
||
<div class="overseas-ma-options" aria-label="해외종목 캔들 이동평균선">
|
||
<label><input id="overseasMa5" type="checkbox" checked>5일선</label>
|
||
<label><input id="overseasMa20" type="checkbox" checked>20일선</label>
|
||
</div>
|
||
</div>
|
||
<div class="overseas-action-header"><strong>해외 대상 컷</strong><small>업종 1개 · 종목 6개 닫힌 동작</small></div>
|
||
<div id="overseasActionList" class="overseas-action-list" aria-label="해외 대상 컷 목록"></div>
|
||
</section>
|
||
<section id="expertWorkflow" class="expert-workflow" aria-labelledby="expertWorkflowTitle" hidden>
|
||
<div class="expert-workflow-header">
|
||
<div>
|
||
<p class="panel-kicker">LEGACY EXPERT WORKFLOW</p>
|
||
<h3 id="expertWorkflowTitle">전문가 추천</h3>
|
||
</div>
|
||
<span id="expertCount" class="badge neutral">READ ONLY</span>
|
||
</div>
|
||
<form id="expertSearchForm" class="expert-search-form" autocomplete="off">
|
||
<input id="expertSearch" type="search" maxlength="64" placeholder="전문가명 · 빈 값은 전체" aria-label="전문가명">
|
||
<button id="expertSearchButton" type="submit">조회</button>
|
||
</form>
|
||
<div id="expertSearchState" class="expert-search-state" role="status" aria-live="polite"></div>
|
||
<div id="expertResults" class="expert-results" role="listbox" aria-label="전문가 검색 결과"></div>
|
||
<div id="selectedExpert" class="selected-expert" hidden>
|
||
<span>선택 전문가</span>
|
||
<strong id="selectedExpertName">-</strong>
|
||
<small id="selectedExpertMeta">-</small>
|
||
</div>
|
||
<div class="expert-preview-header">
|
||
<div><strong>추천 종목</strong><small>PLAYINDEX 순서 · read-only 미리보기</small></div>
|
||
<span id="expertPreviewCount">0 ITEMS</span>
|
||
</div>
|
||
<div id="expertPreviewState" class="expert-preview-state" role="status" aria-live="polite"></div>
|
||
<div id="expertPreviewItems" class="expert-preview-items" aria-label="전문가 추천 종목 미리보기"></div>
|
||
<div class="expert-action-header"><strong>전문가 추천 컷</strong><small>5개 단위 · 최대 20페이지</small></div>
|
||
<div id="expertActionList" class="expert-action-list" aria-label="전문가 추천 컷 목록"></div>
|
||
<div class="expert-crud-notice">
|
||
<span>EList · 전문가·추천종목 추가·편집·삭제</span>
|
||
<button id="expertCatalogManageButton" type="button">전문가 관리</button>
|
||
</div>
|
||
</section>
|
||
<section id="tradingHaltWorkflow" class="trading-halt-workflow" aria-labelledby="tradingHaltWorkflowTitle" hidden>
|
||
<div class="trading-halt-workflow-header">
|
||
<div>
|
||
<p class="panel-kicker">LEGACY TRADING HALT WORKFLOW</p>
|
||
<h3 id="tradingHaltWorkflowTitle">거래 정지 종목</h3>
|
||
</div>
|
||
<span id="tradingHaltCount" class="badge neutral">DB</span>
|
||
</div>
|
||
<form id="tradingHaltSearchForm" class="trading-halt-search-form" autocomplete="off">
|
||
<input id="tradingHaltSearch" type="search" maxlength="64" placeholder="종목명 · 빈 값은 전체" aria-label="거래 정지 종목명">
|
||
<button id="tradingHaltSearchButton" type="submit">조회</button>
|
||
</form>
|
||
<div id="tradingHaltSearchState" class="trading-halt-search-state" role="status" aria-live="polite"></div>
|
||
<div id="tradingHaltResults" class="trading-halt-results" role="listbox" aria-label="거래 정지 종목 검색 결과"></div>
|
||
<div id="selectedTradingHalt" class="selected-trading-halt" hidden>
|
||
<div>
|
||
<span>선택 종목</span>
|
||
<strong id="selectedTradingHaltName">-</strong>
|
||
<small id="selectedTradingHaltMeta">-</small>
|
||
</div>
|
||
<div class="trading-halt-ma-options" aria-label="캔들 이동평균선">
|
||
<label><input id="tradingHaltMa5" type="checkbox" checked>5일선</label>
|
||
<label><input id="tradingHaltMa20" type="checkbox" checked>20일선</label>
|
||
</div>
|
||
</div>
|
||
<div class="trading-halt-action-header">
|
||
<strong>거래 정지 컷</strong>
|
||
<small>원본 UC7 · 현재가와 120일 캔들</small>
|
||
</div>
|
||
<div id="tradingHaltActionList" class="trading-halt-action-list" aria-label="거래 정지 컷 목록"></div>
|
||
</section>
|
||
<label class="search-box">
|
||
<span>⌕</span>
|
||
<input id="catalogSearch" type="search" autocomplete="off" placeholder="장면 코드·그래픽 검색">
|
||
<kbd>Ctrl K</kbd>
|
||
</label>
|
||
<div id="catalogTabs" class="catalog-tabs" role="tablist">
|
||
<button class="active" type="button" data-category="all">전체</button>
|
||
<button type="button" data-category="plate">판</button>
|
||
<button type="button" data-category="chart">차트</button>
|
||
<button type="button" data-category="market">시장</button>
|
||
</div>
|
||
<section id="liveDataPanel" class="live-data-panel" aria-labelledby="liveDataTitle" hidden>
|
||
<div class="live-data-header">
|
||
<div>
|
||
<p class="panel-kicker">LIVE DATABASE</p>
|
||
<h3 id="liveDataTitle">실시간 시장 데이터</h3>
|
||
</div>
|
||
<button id="retryLiveDataButton" class="live-retry" type="button">다시 조회</button>
|
||
</div>
|
||
<div id="databaseSources" class="database-sources" aria-label="데이터베이스 연결 상태"></div>
|
||
<div id="liveDataState" class="live-data-state" role="status" aria-live="polite"></div>
|
||
<div id="liveDataTables" class="live-data-tables"></div>
|
||
</section>
|
||
<div id="catalogList" class="catalog-list" aria-live="polite"></div>
|
||
</section>
|
||
|
||
<section class="panel playlist-panel">
|
||
<div class="panel-header">
|
||
<div><p class="panel-kicker">PLAYLIST</p><h2>송출 순서</h2></div>
|
||
<span id="playlistCount" class="badge neutral">0 CUTS</span>
|
||
</div>
|
||
<div class="playlist-actions">
|
||
<button id="toggleAllEnabledButton" type="button">전체 송출</button>
|
||
<button id="selectAllButton" type="button">작업 전체선택</button>
|
||
<button id="moveUpButton" type="button" title="선택 항목 위로">↑</button>
|
||
<button id="moveDownButton" type="button" title="선택 항목 아래로">↓</button>
|
||
<button id="deleteButton" class="danger" type="button">삭제</button>
|
||
<button id="deleteAllButton" class="danger" type="button">전체삭제</button>
|
||
<div class="global-candle-options" aria-label="전체 캔들 이동평균선">
|
||
<span>캔들</span>
|
||
<label><input id="globalMa5" type="checkbox" checked>5일선</label>
|
||
<label><input id="globalMa20" type="checkbox" checked>20일선</label>
|
||
</div>
|
||
<button id="namedPlaylistOpenButton" class="database-soft" type="button" aria-expanded="false" aria-controls="namedPlaylistPanel">DB 저장·불러오기</button>
|
||
<button id="loadButton" type="button">로컬 불러오기</button>
|
||
<button id="saveButton" class="primary-soft" type="button">로컬 임시저장</button>
|
||
</div>
|
||
<section id="namedPlaylistPanel" class="named-playlist-panel" aria-labelledby="namedPlaylistTitle" hidden>
|
||
<header class="named-playlist-header">
|
||
<div>
|
||
<p class="panel-kicker">ORACLE · DC_LIST / PLAY_LIST</p>
|
||
<h3 id="namedPlaylistTitle">DB 플레이리스트</h3>
|
||
</div>
|
||
<div class="named-playlist-header-actions">
|
||
<span id="namedPlaylistStateBadge" class="badge neutral">대기</span>
|
||
<button id="namedPlaylistRefreshButton" type="button">목록 새로고침</button>
|
||
<button id="namedPlaylistCloseButton" type="button" aria-label="DB 플레이리스트 닫기">닫기</button>
|
||
</div>
|
||
</header>
|
||
<div id="namedPlaylistStatus" class="named-playlist-status" role="status" aria-live="polite">
|
||
Oracle에 저장된 이름 목록을 조회하세요. 로컬 임시저장과는 별도입니다.
|
||
</div>
|
||
<div class="named-playlist-layout">
|
||
<label class="named-playlist-definitions-label" for="namedPlaylistDefinitions">저장된 이름</label>
|
||
<select id="namedPlaylistDefinitions" class="named-playlist-definitions" size="6" aria-describedby="namedPlaylistSelectionSummary"></select>
|
||
<div id="namedPlaylistSelectionSummary" class="named-playlist-selection-summary">선택된 DB 정의 없음</div>
|
||
<div class="named-playlist-load-actions">
|
||
<button id="namedPlaylistLoadButton" class="primary-soft" type="button">선택 DB 불러오기</button>
|
||
<button id="namedPlaylistPageRetryButton" type="button" hidden>페이지 다시 조회</button>
|
||
<button id="namedPlaylistRestoreBackupButton" type="button">불러오기 전 상태 복원</button>
|
||
</div>
|
||
<div class="named-playlist-create">
|
||
<label for="namedPlaylistProgramCode">새 코드</label>
|
||
<input id="namedPlaylistProgramCode" type="text" inputmode="numeric" maxlength="8" autocomplete="off" placeholder="00000001">
|
||
<label for="namedPlaylistProgramTitle">새 이름</label>
|
||
<input id="namedPlaylistProgramTitle" type="text" maxlength="128" autocomplete="off" placeholder="예: 오전 방송">
|
||
<button id="namedPlaylistCreateButton" type="button">새 이름 만들기</button>
|
||
</div>
|
||
<div class="named-playlist-mutation-actions">
|
||
<button id="namedPlaylistReplaceButton" class="primary-soft" type="button">선택 정의에 현재 순서 저장</button>
|
||
<button id="namedPlaylistDeleteButton" class="danger" type="button">선택 정의 삭제</button>
|
||
</div>
|
||
</div>
|
||
<p id="namedPlaylistGuardSummary" class="named-playlist-guard-summary">
|
||
DB에서 읽은 각 행은 신뢰 복원과 현재 페이지 재계산을 통과해야 PREPARE할 수 있습니다.
|
||
</p>
|
||
</section>
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead><tr><th class="check-cell">송출</th><th class="number-cell">#</th><th>종목·대상</th><th>컷</th><th>세부사항</th><th class="page-cell">Page</th><th class="drag-cell">정렬</th></tr></thead>
|
||
<tbody id="playlistBody"></tbody>
|
||
</table>
|
||
<div id="playlistEmpty" class="empty-state">
|
||
<strong>플레이리스트가 비어 있습니다.</strong>
|
||
<span>왼쪽 항목의 + 버튼으로 송출 순서를 구성하세요.</span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel playout-panel">
|
||
<div class="panel-header">
|
||
<div><p class="panel-kicker">PROGRAM / PREVIEW</p><h2>송출 제어</h2></div>
|
||
<span id="playoutState" class="badge neutral">IDLE</span>
|
||
</div>
|
||
<div class="playout-health" aria-label="Tornado 송출 연결 상태">
|
||
<div class="playout-health-item">
|
||
<span id="tornadoProcessDot" class="status-dot pending"></span>
|
||
<small>Tornado2 Process</small>
|
||
<strong id="tornadoProcessState">확인 중</strong>
|
||
</div>
|
||
<div class="playout-health-item">
|
||
<span id="playoutConnectionDot" class="status-dot pending"></span>
|
||
<small>Engine</small>
|
||
<strong id="playoutConnectionState">확인 중</strong>
|
||
</div>
|
||
<div class="playout-health-item safety">
|
||
<small>Safety Mode</small>
|
||
<strong id="playoutSafetyMode">확인 중</strong>
|
||
</div>
|
||
</div>
|
||
<div class="background-control-bar" aria-label="장면 배경 설정">
|
||
<div>
|
||
<small>BACKGROUND</small>
|
||
<strong id="backgroundFileName">배경 없음</strong>
|
||
<span id="backgroundStateText">원본 F2/F3 배경 상태 확인 중</span>
|
||
</div>
|
||
<button id="chooseBackgroundButton" type="button">배경 파일 (F2)</button>
|
||
<button id="toggleBackgroundButton" type="button">배경 켜기/끄기 (F3)</button>
|
||
</div>
|
||
<div id="playoutStatusMessage" class="playout-status-message" role="status" aria-live="polite">송출 어댑터 상태를 확인하고 있습니다.</div>
|
||
<div class="playout-page-state" aria-label="장면 및 페이지 상태">
|
||
<span>SCENE <strong id="playoutSceneCode">—</strong></span>
|
||
<span>ENTRY <strong id="playoutEntryId">—</strong></span>
|
||
<span>BUILDER <strong id="playoutBuilderKey">—</strong></span>
|
||
<span>PAGE <strong id="playoutPageNumber">—</strong></span>
|
||
<span>PAGE SIZE <strong id="playoutPageSize">—</strong></span>
|
||
<span>TOTAL ROWS <strong id="playoutItemCount">0</strong></span>
|
||
<span>PAGE ROWS <strong id="playoutCurrentRows">0</strong></span>
|
||
<span>LAST PAGE <strong id="playoutLastPage">YES</strong></span>
|
||
<span>NEXT <strong id="playoutNextKind">NONE</strong></span>
|
||
<span>REFRESH <strong id="playoutRefreshState">STOPPED</strong></span>
|
||
</div>
|
||
<div id="playoutError" class="playout-error" role="alert" hidden>
|
||
<div><strong>송출 명령 오류</strong><span id="playoutErrorMessage"></span></div>
|
||
<button id="clearPlayoutErrorButton" type="button" aria-label="송출 오류 닫기">닫기</button>
|
||
</div>
|
||
<div class="preview-stage" id="previewStage">
|
||
<div class="safe-area">
|
||
<span>PREVIEW</span>
|
||
<strong id="previewTitle">선택된 그래픽 없음</strong>
|
||
<small id="previewSubtitle">플레이리스트 항목을 선택하세요.</small>
|
||
</div>
|
||
<div class="stage-corner top-left"></div><div class="stage-corner top-right"></div>
|
||
<div class="stage-corner bottom-left"></div><div class="stage-corner bottom-right"></div>
|
||
</div>
|
||
<section class="scene-data-preview" aria-label="실제 장면 DTO mutation 미리보기">
|
||
<div class="scene-data-preview-header"><strong>SCENE DATA</strong><span>asset 경로는 숨김 처리</span></div>
|
||
<div id="sceneDataPreview" class="scene-data-preview-body"></div>
|
||
</section>
|
||
<form id="sceneSelectionForm" class="scene-selection-form" autocomplete="off">
|
||
<label>CUT ALIAS<select id="sceneCutAlias" aria-label="CUT alias"></select></label>
|
||
<label>GROUP<input id="sceneGroupCode" maxlength="256" list="sceneGroupOptions" placeholder="KOSPI_STOCK"></label>
|
||
<label>SUBJECT<input id="sceneSubject" maxlength="256" placeholder="종목명 또는 지수명"></label>
|
||
<label>GRAPHIC<input id="sceneGraphicType" maxlength="256" placeholder="MA5,MA20 등 닫힌 옵션"></label>
|
||
<label>SUBTYPE<input id="sceneSubtype" maxlength="256" list="sceneSubtypeOptions" placeholder="PRICE"></label>
|
||
<label>DATA CODE<input id="sceneDataCode" maxlength="256" placeholder="종목·업종 코드"></label>
|
||
<label>FADE<input id="sceneFadeDuration" type="number" min="0" max="60" step="1" value="6"></label>
|
||
<button id="applySceneSelectionButton" type="submit">조회값 적용</button>
|
||
<datalist id="sceneGroupOptions">
|
||
<option value="KOSPI_INDEX"></option><option value="KOSDAQ_INDEX"></option>
|
||
<option value="KOSPI200_INDEX"></option><option value="KRX100_INDEX"></option>
|
||
<option value="FUTURES_INDEX"></option><option value="KOSPI_INDUSTRY"></option>
|
||
<option value="KOSDAQ_INDUSTRY"></option><option value="FOREIGN_INDEX"></option>
|
||
<option value="FOREIGN_STOCK"></option><option value="KOSPI_STOCK"></option>
|
||
<option value="KOSDAQ_STOCK"></option><option value="NXT_KOSPI"></option>
|
||
<option value="NXT_KOSDAQ"></option>
|
||
</datalist>
|
||
<datalist id="sceneSubtypeOptions">
|
||
<option value="PRICE"></option><option value="EXPECTED"></option>
|
||
<option value="VOLUME"></option><option value="TRADING_HALT"></option>
|
||
</datalist>
|
||
</form>
|
||
<div class="playout-controls">
|
||
<button id="prepareButton" class="prepare" type="button"><span>PREP</span>PREPARE</button>
|
||
<button id="takeInButton" class="take-in" type="button"><span>F8</span>TAKE IN</button>
|
||
<button id="nextButton" type="button"><span>→</span>NEXT</button>
|
||
<button id="takeOutButton" class="take-out" type="button"><span>ESC</span>TAKE OUT</button>
|
||
</div>
|
||
<div class="event-log">
|
||
<div class="event-log-header"><strong>운영 로그</strong><button id="clearLogButton" type="button">지우기</button></div>
|
||
<ol id="eventLog"></ol>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
|
||
<div id="toast" class="toast" role="status" aria-live="polite"></div>
|
||
<script src="playout-safety.js"></script>
|
||
<script src="operator-workflow.js"></script>
|
||
<script src="legacy-fixed-workflow.js"></script>
|
||
<script src="industry-workflow.js"></script>
|
||
<script src="comparison-workflow.js"></script>
|
||
<script src="theme-workflow.js"></script>
|
||
<script src="overseas-workflow.js"></script>
|
||
<script src="expert-workflow.js"></script>
|
||
<script src="trading-halt-workflow.js"></script>
|
||
<script src="candle-options-workflow.js"></script>
|
||
<script src="manual-lists-workflow.js"></script>
|
||
<script src="manual-financial-workflow.js"></script>
|
||
<script src="named-manual-restore-workflow.js"></script>
|
||
<script src="operator-catalog-workflow.js"></script>
|
||
<script src="manual-lists-ui.js"></script>
|
||
<script src="manual-financial-ui.js"></script>
|
||
<script src="operator-catalog-ui.js"></script>
|
||
<script src="named-playlist-workflow.js"></script>
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|