html / index.html
blueellia's picture
Upload index.html
d489611 verified
Raw
History Blame Contribute Delete
27.5 kB
<!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=[];
// โ”€โ”€ ์ง€๋„ ์ดˆ๊ธฐํ™” (OSM ๋ผ์ดํŠธ ํƒ€์ผ) โ”€โ”€
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>