| <!DOCTYPE html> |
| <html lang="ko"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>๊ตญ๋ฏผ์ฐ๊ธ ๊ฐ์
์ฌ์
์ฅ ๋ด์ญ</title> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css"/> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script> |
| <link href="https://fonts.googleapis.com/css2?family=Pretendard:wght@300;400;500;600;700&display=swap" rel="stylesheet"> |
| <style> |
| :root{ |
| --bg:#ffffff;--bg2:#f8f9fa;--bg3:#f1f3f5;--border:#dee2e6; |
| --text:#212529;--muted:#868e96;--accent:#3b82f6;--green:#10b981; |
| --yellow:#f59e0b;--red:#ef4444;--sidebar:#ffffff; |
| } |
| *{box-sizing:border-box;margin:0;padding:0} |
| body{font-family:'Pretendard',-apple-system,sans-serif;background:var(--bg);color:var(--text);height:100vh;display:flex;flex-direction:column;overflow:hidden} |
| |
| .topbar{display:flex;align-items:center;justify-content:space-between;padding:0 1.5rem;height:54px;background:#fff;border-bottom:1px solid var(--border);flex-shrink:0;box-shadow:0 1px 4px rgba(0,0,0,.06)} |
| .topbar h1{font-size:15px;font-weight:700;color:var(--text)}.topbar h1 span{color:var(--accent)} |
| .topbar-right{display:flex;align-items:center;gap:8px} |
| .status-badge{font-size:11px;color:var(--muted);background:var(--bg3);padding:3px 10px;border-radius:10px;border:1px solid var(--border)} |
| .upload-label{display:flex;align-items:center;gap:5px;padding:5px 12px;border-radius:6px;background:var(--accent);color:#fff;font-size:11px;font-weight:600;cursor:pointer} |
| |
| .main{display:flex;flex:1;overflow:hidden} |
| |
| .sidebar{width:260px;flex-shrink:0;background:#fff;border-right:1px solid var(--border);display:flex;flex-direction:column;overflow:hidden} |
| .sel-wrap{padding:10px 14px;border-bottom:1px solid var(--border)} |
| .sel-wrap label{font-size:10px;font-weight:600;color:var(--muted);letter-spacing:.8px;text-transform:uppercase;display:block;margin-bottom:5px} |
| .sel-box{width:100%;background:#fff;border:1px solid var(--border);color:var(--text);padding:7px 10px;border-radius:6px;font-size:12px;font-family:inherit;outline:none;cursor:pointer} |
| .sel-box:focus{border-color:var(--accent)} |
| |
| .stats-row{display:grid;grid-template-columns:1fr 1fr;gap:6px;padding:10px 14px;border-bottom:1px solid var(--border)} |
| .stat{background:var(--bg2);border-radius:8px;padding:10px 12px;border:1px solid var(--border)} |
| .stat .n{font-size:18px;font-weight:700;color:var(--accent);line-height:1} |
| .stat .l{font-size:10px;color:var(--muted);margin-top:3px} |
| |
| .search-wrap{padding:8px 14px;border-bottom:1px solid var(--border)} |
| .search{width:100%;background:#fff;border:1px solid var(--border);color:var(--text);padding:7px 10px;border-radius:6px;font-size:12px;font-family:inherit;outline:none} |
| .search:focus{border-color:var(--accent)} |
| .search::placeholder{color:var(--muted)} |
| |
| .list-hdr{display:flex;justify-content:space-between;padding:7px 14px;background:var(--bg3);border-bottom:1px solid var(--border)} |
| .list-hdr span{font-size:10px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.5px} |
| .list-wrap{flex:1;overflow-y:auto} |
| .list-wrap::-webkit-scrollbar{width:4px} |
| .list-wrap::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px} |
| |
| .list-item{display:flex;justify-content:space-between;align-items:center;padding:10px 14px;border-bottom:1px solid #f1f3f5;cursor:pointer;transition:background .1s} |
| .list-item:hover{background:#f8f9ff} |
| .list-item.active{background:#eff6ff;border-left:2px solid var(--accent)} |
| .item-left{flex:1;min-width:0} |
| .item-name{font-size:12px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis} |
| .item-sub{font-size:10px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} |
| .item-emp{font-size:13px;font-weight:700;color:var(--green);white-space:nowrap;margin-left:8px} |
| .item-emp span{font-size:9px;color:var(--muted);font-weight:400} |
| .pill{display:inline-block;padding:1px 6px;border-radius:3px;font-size:9px;font-weight:600;margin-right:3px} |
| .pill-c{background:#dbeafe;color:#1d4ed8} |
| .pill-i{background:#d1fae5;color:#065f46} |
| |
| .content{flex:1;display:flex;flex-direction:column;overflow:hidden} |
| .tab-bar{display:flex;align-items:center;padding:0 1rem;border-bottom:1px solid var(--border);background:#fff;height:44px;gap:2px} |
| .tab{padding:0 14px;height:100%;display:flex;align-items:center;font-size:12px;font-weight:500;color:var(--muted);cursor:pointer;border-bottom:2px solid transparent;transition:all .15s} |
| .tab.active{color:var(--accent);border-bottom-color:var(--accent);font-weight:600} |
| .tab-actions{margin-left:auto} |
| .dl-btn{display:flex;align-items:center;gap:5px;padding:6px 14px;border-radius:6px;background:var(--bg2);color:var(--text);font-size:11px;font-weight:600;cursor:pointer;border:1px solid var(--border);font-family:inherit;transition:all .15s} |
| .dl-btn:hover{background:var(--green);color:#fff;border-color:var(--green)} |
| |
| .panel{display:none;flex:1;overflow:hidden} |
| .panel.active{display:flex;flex-direction:column} |
| #map{flex:1;width:100%} |
| |
| .detail-scroll{flex:1;overflow-y:auto;padding:1.2rem;background:var(--bg2)} |
| .detail-scroll::-webkit-scrollbar{width:4px} |
| .detail-scroll::-webkit-scrollbar-thumb{background:var(--border)} |
| .d-card{background:#fff;border:1px solid var(--border);border-radius:10px;padding:1rem 1.2rem;margin-bottom:.8rem;box-shadow:0 1px 3px rgba(0,0,0,.04)} |
| .d-card h3{font-size:10px;font-weight:700;color:var(--muted);letter-spacing:.8px;text-transform:uppercase;margin-bottom:.8rem} |
| .d-row{display:flex;padding:7px 0;border-bottom:1px solid #f1f3f5} |
| .d-row:last-child{border-bottom:none} |
| .d-key{font-size:11px;color:var(--muted);min-width:110px} |
| .d-val{font-size:11px;color:var(--text);font-weight:500} |
| .formula{background:var(--bg3);border:1px solid var(--border);border-radius:6px;padding:10px 14px;font-family:'Courier New',monospace;font-size:11px;color:#1d4ed8;margin-top:6px} |
| .highlight-box{margin-top:10px;padding:10px 14px;background:#eff6ff;border-radius:6px;border-left:3px solid var(--accent)} |
| .highlight-box .hl{font-size:11px;color:var(--muted);margin-bottom:4px} |
| .highlight-box .hv{font-size:20px;font-weight:700;color:var(--accent)} |
| |
| .empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:8px;color:var(--muted);text-align:center} |
| .empty .ei{font-size:36px;opacity:.3} |
| |
| .overlay{position:fixed;inset:0;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;z-index:1000;backdrop-filter:blur(4px)} |
| .ov-box{background:#fff;border:1px solid var(--border);border-radius:16px;padding:2.5rem;text-align:center;max-width:380px;width:90%;box-shadow:0 20px 60px rgba(0,0,0,.15)} |
| .ov-box h2{font-size:18px;font-weight:700;margin-bottom:6px;color:var(--text)} |
| .ov-box p{font-size:12px;color:var(--muted);margin-bottom:1.2rem;line-height:1.6} |
| .drop-zone{border:2px dashed var(--border);border-radius:10px;padding:2rem;cursor:pointer;transition:all .2s;background:var(--bg2)} |
| .drop-zone:hover{border-color:var(--accent);background:#eff6ff} |
| .drop-zone .di{font-size:36px;margin-bottom:8px} |
| .drop-zone p{font-size:11px;color:var(--muted)} |
| .prog-bar{height:4px;background:var(--border);border-radius:2px;overflow:hidden;margin-top:.8rem;display:none} |
| .prog-fill{height:100%;background:var(--accent);border-radius:2px;transition:width .3s} |
| #loadMsg{font-size:11px;color:var(--muted);margin-top:6px;display:none} |
| </style> |
| </head> |
| <body> |
|
|
| <div class="overlay" id="ov"> |
| <div class="ov-box"> |
| <h2>๐ ๊ตญ๋ฏผ์ฐ๊ธ ์ฌ์
์ฅ ๋์๋ณด๋</h2> |
| <p>๊ตญ๋ฏผ์ฐ๊ธ๊ณต๋จ ๊ฐ์
์ฌ์
์ฅ ๋ด์ญ ์์
ํ์ผ์<br>์
๋ก๋ํ๋ฉด ๋ฐ๋ก ์์๋ฉ๋๋ค</p> |
| <div class="drop-zone" id="dropZone" onclick="document.getElementById('fi').click()"> |
| <div class="di">๐</div> |
| <p>ํด๋ฆญํ๊ฑฐ๋ ํ์ผ์ ๋๋๊ทธํ์ธ์<br><span style="font-size:10px">.xlsx / .xls</span></p> |
| </div> |
| <div class="prog-bar" id="pb"><div class="prog-fill" id="pf" style="width:0%"></div></div> |
| <p id="loadMsg"></p> |
| <input type="file" id="fi" accept=".xlsx,.xls" style="display:none"> |
| </div> |
| </div> |
|
|
| <div class="topbar"> |
| <h1>๊ตญ๋ฏผ์ฐ๊ธ <span>๊ฐ์
์ฌ์
์ฅ ๋ด์ญ</span></h1> |
| <div class="topbar-right"> |
| <div class="status-badge" id="sb">ํ์ผ ๋ก๋ฉ ๋๊ธฐ ์ค</div> |
| <label class="upload-label">๐ ํ์ผ ๊ต์ฒด<input type="file" accept=".xlsx,.xls" onchange="loadFile(this.files[0])" style="display:none"></label> |
| </div> |
| </div> |
|
|
| <div class="main"> |
| <div class="sidebar"> |
| <div class="sel-wrap"> |
| <label>์ / ๋</label> |
| <select class="sel-box" id="sidoSel" onchange="updateGu()"><option value="">์ ํ</option></select> |
| </div> |
| <div class="sel-wrap"> |
| <label>๊ตฌ / ๊ตฐ</label> |
| <select class="sel-box" id="guSel" onchange="filterData()"><option value="">์ ํ</option></select> |
| </div> |
| <div class="stats-row"> |
| <div class="stat"><div class="n" id="s1">-</div><div class="l">์ ์ฒด</div></div> |
| <div class="stat"><div class="n" id="s2">-</div><div class="l">๋ฒ์ธ</div></div> |
| <div class="stat"><div class="n" id="s3">-</div><div class="l">์ด ์ง์</div></div> |
| <div class="stat"><div class="n" id="s4">-</div><div class="l">ํ๊ท ์ง์</div></div> |
| </div> |
| <div class="search-wrap"> |
| <input class="search" id="srch" placeholder="๐ ์ฌ์
์ฅ๋ช
๊ฒ์..." oninput="filterList()"> |
| </div> |
| <div class="list-hdr"> |
| <span>์ฌ์
์ฅ</span> |
| <span>์ง์์</span> |
| </div> |
| <div class="list-wrap" id="lw"> |
| <div class="empty"><div class="ei">๐๏ธ</div><p>์/๋์ ๊ตฌ/๊ตฐ์ ์ ํํ์ธ์</p></div> |
| </div> |
| </div> |
|
|
| <div class="content"> |
| <div class="tab-bar"> |
| <div class="tab active" onclick="showTab('map')">๐บ๏ธ ์ง๋</div> |
| <div class="tab" onclick="showTab('detail')">๐ ์์ธ</div> |
| <div class="tab-actions"> |
| <button class="dl-btn" onclick="dlExcel()">โฌ๏ธ ์์
๋ค์ด๋ก๋</button> |
| </div> |
| </div> |
| <div class="panel active" id="panel-map"><div id="map"></div></div> |
| <div class="panel" id="panel-detail"> |
| <div class="detail-scroll" id="dc"> |
| <div class="empty"><div class="ei">๐</div><p style="font-size:13px;font-weight:600">์ฌ์
์ฅ์ ์ ํํ์ธ์</p><p style="font-size:11px;margin-top:4px;color:var(--muted)">๋ชฉ๋ก์์ ํด๋ฆญํ๋ฉด ์์ธ ์ ๋ณด๊ฐ ํ์๋ฉ๋๋ค</p></div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| const C={ |
| '๊ฐ๋จ๊ตฌ':[37.5172,127.0473],'๊ฐ๋๊ตฌ':[37.5301,127.1238],'๊ฐ๋ถ๊ตฌ':[37.6397,127.0259],'๊ฐ์๊ตฌ':[37.5509,126.8495], |
| '๊ด์
๊ตฌ':[37.4784,126.9516],'๊ด์ง๊ตฌ':[37.5385,127.0822],'๊ตฌ๋ก๊ตฌ':[37.4954,126.8876],'๊ธ์ฒ๊ตฌ':[37.4602,126.9000], |
| '๋
ธ์๊ตฌ':[37.6543,127.0568],'๋๋ด๊ตฌ':[37.6688,127.0471],'๋๋๋ฌธ๊ตฌ':[37.5744,127.0396],'๋์๊ตฌ':[37.5124,126.9393], |
| '๋งํฌ๊ตฌ':[37.5638,126.9084],'์๋๋ฌธ๊ตฌ':[37.5791,126.9368],'์์ด๊ตฌ':[37.4837,127.0324],'์ฑ๋๊ตฌ':[37.5633,127.0371], |
| '์ฑ๋ถ๊ตฌ':[37.5894,127.0167],'์กํ๊ตฌ':[37.5145,127.1058],'์์ฒ๊ตฌ':[37.5170,126.8665],'์๋ฑํฌ๊ตฌ':[37.5264,126.8962], |
| '์ฉ์ฐ๊ตฌ':[37.5324,126.9904],'์ํ๊ตฌ':[37.6176,126.9227],'์ข
๋ก๊ตฌ':[37.5735,126.9789],'์ค๊ตฌ':[37.5579,126.9942],'์ค๋๊ตฌ':[37.6063,127.0926], |
| '๊ธ์ ๊ตฌ':[35.2428,129.0927],'๊ธฐ์ฅ๊ตฐ':[35.2445,129.2220],'๋จ๊ตฌ':[35.1367,129.0845],'๋๊ตฌ':[35.1299,129.0453], |
| '๋๋๊ตฌ':[35.1993,129.0841],'๋ถ์ฐ์ง๊ตฌ':[35.1631,129.0531],'๋ถ๊ตฌ':[35.1977,128.9898],'์ฌ์๊ตฌ':[35.1524,128.9921], |
| '์ฌํ๊ตฌ':[35.1046,128.9742],'์๊ตฌ':[35.0978,129.0245],'์์๊ตฌ':[35.1454,129.1133],'์ฐ์ ๊ตฌ':[35.1764,129.0804], |
| '์๋๊ตฌ':[35.0906,129.0671],'ํด์ด๋๊ตฌ':[35.1631,129.1639], |
| '์์์':[37.2636,127.0286],'์ฑ๋จ์':[37.4201,127.1264],'๊ณ ์์':[37.6584,126.8320],'์ฉ์ธ์':[37.2410,127.1775], |
| '๋ถ์ฒ์':[37.5035,126.7660],'์์ฐ์':[37.3219,126.8310],'์์์':[37.3943,126.9568],'๋จ์์ฃผ์':[37.6360,127.2165], |
| 'ํ์ฑ์':[37.1996,126.8312],'ํํ์':[36.9921,127.1128],'์์ ๋ถ์':[37.7382,127.0337],'์ํฅ์':[37.3800,126.8030], |
| 'ํ์ฃผ์':[37.7601,126.7799],'๊ด๋ช
์':[37.4784,126.8642],'๊นํฌ์':[37.6153,126.7156],'๊ด์ฃผ์':[37.4293,127.2558], |
| '๊ตฐํฌ์':[37.3615,126.9349],'ํ๋จ์':[37.5394,127.2148],'์ค์ฐ์':[37.1520,127.0776],'์ด์ฒ์':[37.2722,127.4350], |
| '์์ฑ์':[37.0081,127.2797],'์์์':[37.3448,126.9686],'์ํ๊ตฐ':[37.4914,127.4875],'์ฌ์ฃผ์':[37.2984,127.6376], |
| '๊ณผ์ฒ์':[37.4292,126.9876],'๊ตฌ๋ฆฌ์':[37.5943,127.1296],'ํฌ์ฒ์':[37.8948,127.2002],'์์ฃผ์':[37.7852,127.0457], |
| '๋๋์ฒ์':[37.9039,127.0606],'๊ฐํ๊ตฐ':[37.8314,127.5101],'์ฐ์ฒ๊ตฐ':[38.0965,127.0747], |
| '๋ถ๋น๊ตฌ':[37.3845,127.1218],'์์ ๊ตฌ':[37.4389,127.1378],'์ค์๊ตฌ':[37.4418,127.1480],'๋์๊ตฌ':[37.6344,126.8350], |
| '์ผ์ฐ๋๊ตฌ':[37.6592,126.8218],'์ผ์ฐ์๊ตฌ':[37.6740,126.7680],'๊ธฐํฅ๊ตฌ':[37.2751,127.1152],'์์ง๊ตฌ':[37.3220,127.0977], |
| '์ฒ์ธ๊ตฌ':[37.2375,127.2018],'๋จ์๊ตฌ':[37.3213,126.8187],'์๋ก๊ตฌ':[37.2983,126.8721],'๋ง์๊ตฌ':[37.3862,126.9369], |
| '๋์๊ตฌ':[37.3947,126.9492],'์ค์ ๊ตฌ':[37.5032,126.7872],'์๋ฏธ๊ตฌ':[37.5087,126.7577],'์์ฌ๊ตฌ':[37.4830,126.8017], |
| '๊ถ์ ๊ตฌ':[37.2505,127.0040],'ํ๋ฌ๊ตฌ':[37.2869,127.0173],'์ํต๊ตฌ':[37.2517,127.0509],'์ฅ์๊ตฌ':[37.3050,127.0138], |
| '๋ฏธ์ถํ๊ตฌ':[37.4561,126.7052],'์ฐ์๊ตฌ':[37.4106,126.6780],'๋จ๋๊ตฌ':[37.4469,126.7310], |
| '๋ถํ๊ตฌ':[37.5074,126.7219],'๊ณ์๊ตฌ':[37.5379,126.7378],'๊ฐํ๊ตฐ':[37.7480,126.4879], |
| '๋ฌ์๊ตฌ':[35.8285,128.5330],'๋ฌ์ฑ๊ตฐ':[35.7747,128.4314],'์์ฑ๊ตฌ':[35.8583,128.6310], |
| '๋๋๊ตฌ':[36.3462,127.4151],'์ ์ฑ๊ตฌ':[36.3624,127.3563],'๊ด์ฐ๊ตฌ':[35.1397,126.7936],'์ธ์ฃผ๊ตฐ':[35.5225,129.2440], |
| '์์ฐฝ๊ตฌ':[35.2271,128.6811],'์ฑ์ฐ๊ตฌ':[35.2217,128.6921],'๋ง์ฐํฉํฌ๊ตฌ':[35.1827,128.5644], |
| '๋ง์ฐํ์๊ตฌ':[35.2184,128.5868],'์งํด๊ตฌ':[35.1541,128.6971],'๊นํด์':[35.2286,128.8893], |
| '์์ฐ์':[35.3350,129.0370],'์ง์ฃผ์':[35.1799,128.1076],'๊ฑฐ์ ์':[34.8804,128.6213], |
| 'ํต์์':[34.8544,128.4330],'๋ฐ์์':[35.5039,128.7459],'์ฌ์ฒ์':[35.0003,128.0645], |
| 'ํจ์๊ตฐ':[35.2715,128.4063],'์ฐฝ๋
๊ตฐ':[35.5446,128.4922],'๊ณ ์ฑ๊ตฐ':[34.9748,128.3224], |
| '๋จํด๊ตฐ':[34.8374,127.8917],'ํ๋๊ตฐ':[35.0671,127.7518],'์ฐ์ฒญ๊ตฐ':[35.4153,127.8737], |
| 'ํจ์๊ตฐ':[35.5203,127.7239],'๊ฑฐ์ฐฝ๊ตฐ':[35.6878,127.9101],'ํฉ์ฒ๊ตฐ':[35.5664,128.1658],'์๋ น๊ตฐ':[35.3219,128.2616], |
| 'ํฌํญ์':[36.0190,129.3435],'๊ฒฝ์ฃผ์':[35.8562,129.2247],'๊น์ฒ์':[36.1397,128.1135], |
| '์๋์':[36.5684,128.7294],'๊ตฌ๋ฏธ์':[36.1196,128.3441],'์์ฃผ์':[36.8057,128.6236], |
| '์์ฒ์':[35.9735,128.9383],'์์ฃผ์':[36.4110,128.1597],'๋ฌธ๊ฒฝ์':[36.5863,128.1861], |
| '๊ฒฝ์ฐ์':[35.8249,128.7414],'๋ฌ์ฑ๊ตฐ':[35.7747,128.4314], |
| '์ฒ์์':[36.8151,127.1139],'๊ณต์ฃผ์':[36.4465,127.1190],'๋ณด๋ น์':[36.3334,126.6127], |
| '์์ฐ์':[36.7893,127.0021],'์์ฐ์':[36.7848,126.4503],'๋
ผ์ฐ์':[36.1872,127.0986], |
| '๋น์ง์':[36.8896,126.6454],'ํ์ฑ๊ตฐ':[36.6010,126.6600],'์์ฐ๊ตฐ':[36.6817,126.8451], |
| 'ํ์๊ตฐ':[36.7456,126.2978],'๋๋จ๊ตฌ':[36.7914,127.1619],'์๋ถ๊ตฌ':[36.8421,127.0961], |
| '์ฒญ์ฃผ์':[36.6424,127.4890],'์ถฉ์ฃผ์':[36.9911,127.9261],'์ ์ฒ์':[37.1326,128.1909], |
| '์๋น๊ตฌ':[36.6575,127.5291],'์์๊ตฌ':[36.6166,127.4509],'ํฅ๋๊ตฌ':[36.6405,127.4255],'์ฒญ์๊ตฌ':[36.6527,127.5027], |
| '์ ์ฃผ์':[35.8242,127.1480],'๊ตฐ์ฐ์':[35.9674,126.7368],'์ต์ฐ์':[35.9483,126.9579], |
| '์ ์์':[35.5700,126.8562],'๋จ์์':[35.4169,127.3899],'๊น์ ์':[35.8032,126.8813], |
| '์์ฐ๊ตฌ':[35.8150,127.1127],'๋์ง๊ตฌ':[35.8566,127.1568], |
| '๋ชฉํฌ์':[34.8120,126.3922],'์ฌ์์':[34.7604,127.6622],'์์ฒ์':[34.9506,127.4875], |
| '๋์ฃผ์':[35.0160,126.7108],'๊ด์์':[34.9407,127.6963], |
| '์ถ์ฒ์':[37.8813,127.7298],'์์ฃผ์':[37.3422,127.9202],'๊ฐ๋ฆ์':[37.7519,128.8760], |
| '๋ํด์':[37.5243,129.1140],'์์ด์':[38.2071,128.5916],'์ผ์ฒ์':[37.4498,129.1658], |
| '์ ์ฃผ์':[33.4996,126.5312],'์๊ทํฌ์':[33.2541,126.5600], |
| }; |
| |
| let allData=[],filteredData=[],currentData=[],mapObj,mkrs=[]; |
| |
| |
| mapObj=L.map('map',{zoomControl:true}).setView([36.5,127.8],7); |
| L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{ |
| attribution:'ยฉ <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>', |
| maxZoom:19, |
| crossOrigin:true |
| }).addTo(mapObj); |
| |
| function rand(n=0.012){return(Math.random()-.5)*n} |
| |
| function updateMap(data){ |
| mkrs.forEach(m=>mapObj.removeLayer(m)); |
| mkrs=[]; |
| if(!data.length)return; |
| const gu=document.getElementById('guSel').value; |
| const center=C[gu]; |
| if(center){ |
| mapObj.setView(center,13); |
| data.slice(0,600).forEach(r=>{ |
| const lat=center[0]+rand(); |
| const lng=center[1]+rand(); |
| const emp=r.๊ฐ์
์์||0; |
| const radius=Math.max(5,Math.min(22,emp/8)); |
| const col=emp>=100?'#ef4444':emp>=30?'#f59e0b':emp>=10?'#3b82f6':'#10b981'; |
| const m=L.circleMarker([lat,lng],{ |
| radius,color:'#fff',weight:1.5,fillColor:col,fillOpacity:.8 |
| }).bindPopup(` |
| <div style="font-family:'Pretendard',sans-serif;min-width:200px;padding:4px"> |
| <b style="font-size:13px;color:#1e293b">${r.์ฌ์
์ฅ๋ช
}</b><br> |
| <span style="font-size:10px;color:#94a3b8">${r.์
์ข
||''}</span> |
| <hr style="border:none;border-top:1px solid #e2e8f0;margin:6px 0"> |
| <div style="font-size:11px;color:#475569">๐ฅ ์ง์์: <b style="color:#10b981">${emp.toLocaleString()}๋ช
</b></div> |
| <div style="font-size:10px;color:#94a3b8;margin-top:4px">${r.์ฃผ์||''}</div> |
| </div> |
| `,{maxWidth:250}).addTo(mapObj); |
| mkrs.push(m); |
| }); |
| } else { |
| |
| const el=document.createElement('div'); |
| el.style.cssText='position:absolute;bottom:20px;left:50%;transform:translateX(-50%);background:rgba(0,0,0,.7);color:#fff;padding:8px 16px;border-radius:20px;font-size:11px;z-index:500;pointer-events:none'; |
| el.textContent=`'${gu}' ์ง๋ ์ขํ ๋ฏธ๋ฑ๋ก โ ๋ฆฌ์คํธ/์์
์ ์ ์ ์๋ํฉ๋๋ค`; |
| document.getElementById('panel-map').style.position='relative'; |
| document.getElementById('panel-map').appendChild(el); |
| setTimeout(()=>el.remove(),4000); |
| } |
| } |
| |
| function getSido(a){ |
| for(const s of['์์ธํน๋ณ์','๋ถ์ฐ๊ด์ญ์','๋๊ตฌ๊ด์ญ์','์ธ์ฒ๊ด์ญ์','๊ด์ฃผ๊ด์ญ์','๋์ ๊ด์ญ์','์ธ์ฐ๊ด์ญ์','์ธ์ข
ํน๋ณ์์น์','๊ฒฝ๊ธฐ๋','๊ฐ์๋','์ถฉ์ฒญ๋ถ๋','์ถฉ์ฒญ๋จ๋','์ ๋ผ๋ถ๋','์ ๋ผ๋จ๋','๊ฒฝ์๋ถ๋','๊ฒฝ์๋จ๋','์ ์ฃผํน๋ณ์์น๋']) |
| if(a.includes(s))return s; |
| return '๊ธฐํ'; |
| } |
| function getGu(a){ |
| const p=a.split(' '); |
| for(const x of p)if((x.endsWith('๊ตฌ')||x.endsWith('๊ตฐ'))&&x.length>2)return x; |
| for(const x of p)if(x.endsWith('์')&&x.length>2&&!['ํน๋ณ์','๊ด์ญ์','์์น์'].some(s=>x.includes(s)))return x; |
| return '๊ธฐํ'; |
| } |
| |
| function loadFile(file){ |
| if(!file)return; |
| document.getElementById('ov').style.display='flex'; |
| document.getElementById('pb').style.display='block'; |
| document.getElementById('loadMsg').style.display='block'; |
| document.getElementById('loadMsg').textContent='ํ์ผ ์ฝ๋ ์ค...'; |
| const reader=new FileReader(); |
| reader.onload=e=>{ |
| document.getElementById('pf').style.width='30%'; |
| document.getElementById('loadMsg').textContent='๋ฐ์ดํฐ ํ์ฑ ์ค...'; |
| setTimeout(()=>{ |
| try{ |
| const wb=XLSX.read(e.target.result,{type:'array'}); |
| const raw=XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); |
| document.getElementById('pf').style.width='70%'; |
| document.getElementById('loadMsg').textContent=`${raw.length.toLocaleString()}๊ฑด ์ฒ๋ฆฌ ์ค...`; |
| setTimeout(()=>{ |
| allData=raw.map(r=>({ |
| ์ฌ์
์ฅ๋ช
:String(r['์ฌ์
์ฅ๋ช
']||''), |
| ์
์ข
:String(r['์ฌ์
์ฅ์
์ข
์ฝ๋๋ช
']||r['์
์ข
']||''), |
| ์ฃผ์:String(r['์ฌ์
์ฅ๋๋ก๋ช
์์ธ์ฃผ์']||''), |
| ๊ฐ์
์์:parseInt(r['๊ฐ์
์์'])||0, |
| ๋น์๊ณ ์ง๊ธ์ก:parseInt(r['๋น์๊ณ ์ง๊ธ์ก'])||0, |
| ๋ฒ์ธ์ฌ๋ถ:(r['์ฌ์
์ฅํํ๊ตฌ๋ถ์ฝ๋ 1 ๋ฒ์ธ 2 ๊ฐ์ธ']==1||r['์ฌ์
์ฅํํ๊ตฌ๋ถ์ฝ๋']==1)?'๋ฒ์ธ':'๊ฐ์ธ', |
| ์๋:getSido(String(r['์ฌ์
์ฅ๋๋ก๋ช
์์ธ์ฃผ์']||'')), |
| ๊ตฌ๊ตฐ:getGu(String(r['์ฌ์
์ฅ๋๋ก๋ช
์์ธ์ฃผ์']||'')), |
| })); |
| buildSido(); |
| document.getElementById('pf').style.width='100%'; |
| document.getElementById('sb').textContent=`์ด ${allData.length.toLocaleString()}๊ฐ ๋ก๋`; |
| document.getElementById('loadMsg').textContent='์๋ฃ!'; |
| setTimeout(()=>document.getElementById('ov').style.display='none',500); |
| },100); |
| }catch(err){document.getElementById('loadMsg').textContent='์ค๋ฅ: '+err.message;} |
| },100); |
| }; |
| reader.readAsArrayBuffer(file); |
| } |
| |
| function buildSido(){ |
| const s=document.getElementById('sidoSel'); |
| const sidos=[...new Set(allData.map(r=>r.์๋))].filter(x=>x!=='๊ธฐํ').sort(); |
| s.innerHTML='<option value="">์ ํ</option>'; |
| sidos.forEach(x=>{const o=document.createElement('option');o.value=o.textContent=x;s.appendChild(o);}); |
| } |
| |
| function updateGu(){ |
| const sido=document.getElementById('sidoSel').value; |
| const g=document.getElementById('guSel'); |
| g.innerHTML='<option value="">์ ํ</option>'; |
| if(!sido)return; |
| const gus=[...new Set(allData.filter(r=>r.์๋===sido).map(r=>r.๊ตฌ๊ตฐ))].filter(x=>x!=='๊ธฐํ').sort(); |
| gus.forEach(x=>{const o=document.createElement('option');o.value=o.textContent=x;g.appendChild(o);}); |
| filterData(); |
| } |
| |
| function filterData(){ |
| const sido=document.getElementById('sidoSel').value; |
| const gu=document.getElementById('guSel').value; |
| if(!sido||!gu){currentData=[];renderList([]);updateStats([]);return;} |
| currentData=allData.filter(r=>r.์๋===sido&&r.๊ตฌ๊ตฐ===gu).sort((a,b)=>b.๊ฐ์
์์-a.๊ฐ์
์์); |
| filteredData=[...currentData]; |
| document.getElementById('srch').value=''; |
| renderList(filteredData); |
| updateStats(filteredData); |
| updateMap(filteredData); |
| } |
| |
| function filterList(){ |
| const q=document.getElementById('srch').value.toLowerCase(); |
| filteredData=q?currentData.filter(r=>r.์ฌ์
์ฅ๋ช
.toLowerCase().includes(q)||r.์
์ข
.toLowerCase().includes(q)):[...currentData]; |
| renderList(filteredData); |
| updateMap(filteredData); |
| } |
| |
| function updateStats(d){ |
| const t=d.length,corp=d.filter(r=>r.๋ฒ์ธ์ฌ๋ถ==='๋ฒ์ธ').length; |
| const emp=d.reduce((s,r)=>s+r.๊ฐ์
์์,0); |
| document.getElementById('s1').textContent=t.toLocaleString(); |
| document.getElementById('s2').textContent=corp.toLocaleString(); |
| document.getElementById('s3').textContent=emp.toLocaleString(); |
| document.getElementById('s4').textContent=t?Math.round(emp/t):0; |
| } |
| |
| function renderList(data){ |
| const w=document.getElementById('lw'); |
| if(!data.length){w.innerHTML='<div class="empty"><div class="ei">๐</div><p>๊ฒฐ๊ณผ ์์</p></div>';return;} |
| w.innerHTML=data.slice(0,300).map((r,i)=>` |
| <div class="list-item" onclick="selectItem(${i})" id="li-${i}"> |
| <div class="item-left"> |
| <div class="item-name">${r.์ฌ์
์ฅ๋ช
}</div> |
| <div class="item-sub"><span class="pill ${r.๋ฒ์ธ์ฌ๋ถ==='๋ฒ์ธ'?'pill-c':'pill-i'}">${r.๋ฒ์ธ์ฌ๋ถ}</span>${r.์
์ข
.slice(0,18)}</div> |
| </div> |
| <div class="item-emp">${(r.๊ฐ์
์์||0).toLocaleString()}<span>๋ช
</span></div> |
| </div> |
| `).join('')+(data.length>300?`<div style="padding:10px;text-align:center;font-size:11px;color:var(--muted)">์์ 300๊ฐ ํ์ (์ ์ฒด ${data.length.toLocaleString()}๊ฐ)</div>`:''); |
| } |
| |
| function selectItem(i){ |
| const r=filteredData[i]; |
| document.querySelectorAll('.list-item').forEach(el=>el.classList.remove('active')); |
| document.getElementById('li-'+i)?.classList.add('active'); |
| const mi=Math.round(r.๋น์๊ณ ์ง๊ธ์ก/0.09); |
| const mr=Math.round(mi/12); |
| document.getElementById('dc').innerHTML=` |
| <div class="d-card"> |
| <h3>๊ธฐ๋ณธ ์ ๋ณด</h3> |
| <div class="d-row"><div class="d-key">์ฌ์
์ฅ๋ช
</div><div class="d-val" style="font-size:14px;font-weight:700">${r.์ฌ์
์ฅ๋ช
}</div></div> |
| <div class="d-row"><div class="d-key">๋ฒ์ธ ๊ตฌ๋ถ</div><div class="d-val"><span class="pill ${r.๋ฒ์ธ์ฌ๋ถ==='๋ฒ์ธ'?'pill-c':'pill-i'}" style="font-size:11px;padding:3px 8px">${r.๋ฒ์ธ์ฌ๋ถ}</span></div></div> |
| <div class="d-row"><div class="d-key">์
์ข
</div><div class="d-val">${r.์
์ข
||'-'}</div></div> |
| <div class="d-row"><div class="d-key">์ฃผ์</div><div class="d-val">${r.์ฃผ์||'-'}</div></div> |
| </div> |
| <div class="d-card"> |
| <h3>๊ท๋ชจ ์งํ</h3> |
| <div class="d-row"><div class="d-key">์ง์์ (๊ฐ์
์์)</div><div class="d-val" style="font-size:20px;font-weight:700;color:var(--green)">${r.๊ฐ์
์์.toLocaleString()}๋ช
</div></div> |
| <div class="d-row"><div class="d-key">๋น์๊ณ ์ง๊ธ์ก</div><div class="d-val" style="color:var(--yellow);font-weight:600">${r.๋น์๊ณ ์ง๊ธ์ก.toLocaleString()}์</div></div> |
| </div> |
| <div class="d-card"> |
| <h3>๐ก ํด์ง์ฐ๊ธ ๊ท๋ชจ ์ถ์ </h3> |
| <div class="formula">์ ์๊ธ์ด์ก = ${r.๋น์๊ณ ์ง๊ธ์ก.toLocaleString()} รท 0.09 |
| = ${mi.toLocaleString()}์ |
| ์ ํด์ง๊ธ = ${mi.toLocaleString()} รท 12 |
| = ${mr.toLocaleString()}์ |
| ์ฐ ํด์ง๊ธ โ ${(mr*12).toLocaleString()}์</div> |
| <div class="highlight-box"><div class="hl">์์ ์ฐ๊ฐ ์ ๋ฆฝ ๊ท๋ชจ</div><div class="hv">์ฝ ${Math.round(mr*12/100000000*10)/10}์ต์ / ๋
</div></div> |
| </div>`; |
| showTab('detail'); |
| } |
| |
| function showTab(id){ |
| document.querySelectorAll('.tab').forEach((t,i)=>t.classList.toggle('active',['map','detail'][i]===id)); |
| document.querySelectorAll('.panel').forEach(p=>p.classList.remove('active')); |
| document.getElementById('panel-'+id).classList.add('active'); |
| if(id==='map')setTimeout(()=>mapObj.invalidateSize(),100); |
| } |
| |
| |
| function dlExcel(){ |
| const d=filteredData.length?filteredData:currentData; |
| if(!d.length){alert('์ง์ญ์ ์ ํํด์ฃผ์ธ์');return;} |
| const sido=document.getElementById('sidoSel').value; |
| const gu=document.getElementById('guSel').value; |
| const ws=XLSX.utils.json_to_sheet(d.map(r=>({ |
| ์ฌ์
์ฅ๋ช
: r.์ฌ์
์ฅ๋ช
, |
| ์
์ข
: r.์
์ข
, |
| ๋ฒ์ธ์ฌ๋ถ: r.๋ฒ์ธ์ฌ๋ถ, |
| ์ฌ์
์ฅ๋๋ก๋ช
์์ธ์ฃผ์: r.์ฃผ์, |
| ๊ฐ์
์์: r.๊ฐ์
์์, |
| ๋น์๊ณ ์ง๊ธ์ก: r.๋น์๊ณ ์ง๊ธ์ก, |
| ์์๊ธ์ด์ก์ถ์ : Math.round(r.๋น์๊ณ ์ง๊ธ์ก/0.09), |
| ์ํด์ง๊ธ์ ๋ฆฝ์ก์ถ์ : Math.round(r.๋น์๊ณ ์ง๊ธ์ก/0.09/12), |
| }))); |
| const wb=XLSX.utils.book_new(); |
| XLSX.utils.book_append_sheet(wb,ws,gu||'๋ชฉ๋ก'); |
| XLSX.writeFile(wb,`๊ตญ๋ฏผ์ฐ๊ธ_${sido}_${gu}_์ฌ์
์ฅ.xlsx`); |
| } |
| |
| const dz=document.getElementById('dropZone'); |
| dz.addEventListener('dragover',e=>{e.preventDefault();dz.style.borderColor='var(--accent)'}); |
| dz.addEventListener('dragleave',()=>{dz.style.borderColor='var(--border)'}); |
| dz.addEventListener('drop',e=>{e.preventDefault();loadFile(e.dataTransfer.files[0])}); |
| document.getElementById('fi').addEventListener('change',e=>loadFile(e.target.files[0])); |
| </script> |
| </body> |
| </html> |
|
|